Rechercher sur le trajet avec l'API Places

Ce document explique comment trouver un hôtel, un restaurant ou une station-service sur un itinéraire planifié. Vous apprendrez à utiliser l'API Routes pour obtenir une polyligne d'itinéraire et l'utiliser avec une requête Recherche le long de l'itinéraire (SAR, Search Along Route) de l'API Places. Vous apprendrez également à obtenir les meilleurs résultats en définissant l'origine de la recherche le long de l'itinéraire, par exemple deux heures après le début du trajet.

API Routes

Pour rechercher des lieux le long de l'itinéraire, nous allons utiliser l'API Routes. Les données de route de la réponse de l'API Routes sont une série de coordonnées LatLng de l'origine à la destination. Les données d'itinéraire contiennent des étapes et des tronçons qui suivent le réseau routier.

Les itinéraires sont également renvoyés sous forme de polyline encodée, que vous transmettez en tant que paramètre d'entrée à la requête SAR. L'encodage de polylignes est un algorithme de compression avec perte qui vous permet de stocker une série de coordonnées sous la forme d'une seule chaîne. Il n'est pas obligatoire d'obtenir la polyligne à partir de l'API Routes. Vous pouvez créer les données vous-même, mais pour les besoins de cet exemple, l'API Routes est un moyen rapide et sûr d'obtenir les données requises.

Dans ce tutoriel, nous utilisons un itinéraire de Londres (-37.8167,144.9619) à Manchester (-37.8155, 144.9663).

Itinéraire de Londres à Manchester

Itinéraire de l'exemple : Londres à Manchester

Étape 1 : Obtenir un itinéraire à partir de l'API Routes

Pour obtenir un itinéraire à partir de l'API Routes, vous devez fournir les informations suivantes :

  • Les lieux de départ et d'arrivée
  • le mode de transport (voiture, à pied, etc.) ;
  • Tous les waypoints (facultatif)
  • Toutes les préférences (éviter les péages, les autoroutes, etc.)
  • La préférence de routage tenant compte du trafic vous donnera les estimations les plus précises, mais il s'agit d'une opération plus lourde en termes de calcul, ce qui augmente la latence de la réponse.
{"origin":{
    "location": {
        "latLng":{
            "latitude":  -37.8167,
            "longitude": 144.9619
        }
    }
},
"destination":{
    "location": {
        "latLng":{
            "latitude":-37.8155,
            "longitude": 144.9663
        }
    }
},
"routingPreference":"TRAFFIC_AWARE",
"travelMode":"DRIVE"
}

Lorsque vous effectuez l'appel, veillez à inclure le champ "encodedPolyline" dans le masque de champ des en-têtes.

headers = {
    "Content-Type": "application/json",
    "X-Goog-FieldMask": "routes.distanceMeters,routes.duration,routes.legs,routes.polyline.encodedPolyline"
}

Documentation complète avec des exemples de récupération d'un itinéraire et de récupération des polylignes d'un itinéraire.

Une fois que vous aurez fourni ces informations dans la requête, l'API Routes renverra un objet route. L'objet route contient les informations suivantes :

  • Distance totale de l'itinéraire
  • Durée totale de l'itinéraire
  • Les étapes et les tronçons de l'itinéraire
  • Polyligne encodée de l'itinéraire, des étapes et des sections.
{
  "routes": [
    {
      "legs": [
        {
          "distanceMeters": 321799,
          "duration": "15401s",
          "staticDuration": "14518s",
          "polyline": {
            "encodedPolyline": "y_kyH`_XOr@q@xKGnBBZ|AlGPj@Y^k@^MEqAfAQLK?eI … <rest of content removed for readability>"
          },
          "startLocation": {
            "latLng": {
              "latitude": 51.507334500000006,
              "longitude": -0.1280107
            }
          },
          "endLocation": {
            "latLng": {
              "latitude": 53.4808513,
              "longitude": -2.2425864
            }
          },
          "steps": [
            {
              "distanceMeters": 320,
              "staticDuration": "82s",
              "polyline": {
                "encodedPolyline": "y_kyH`_XOr@q@xKGnBBZ|AlG"
              },
              "startLocation": {
                "latLng": {
                  "latitude": 51.507334500000006,
                  "longitude": -0.1280107
                }
              },
              "endLocation": {
                "latLng": {
                  "latitude": 51.507207,
                  "longitude": -0.1323681
                }
              },
              "navigationInstruction": {
                "maneuver": "DEPART",
                "instructions": "Head northwest on Trafalgar Sq/A4 toward Spring Gardens\nContinue to follow A4\nLeaving toll zone\nEntering toll zone\nLeaving toll zone in 210m at Haymarket"
              },
              "localizedValues": {
                "distance": {
                  "text": "0.3 km"
                },
                "staticDuration": {
                  "text": "1 min"
                }
              },
# rest of the response removed for readability

Étape 2 : Demande de recherche le long de l'itinéraire

La recherche textuelle de l'API Places propose une requête "Rechercher le long d'un itinéraire" qui vous permet de rechercher des lieux le long d'un itinéraire. Pour effectuer une requête de recherche le long d'un itinéraire, vous devez fournir au minimum les informations suivantes :

  • Masque de champ indiquant les champs renvoyés dans la réponse.
  • Une clé API valide pour l'API activée dans la console Google Cloud
  • Chaîne de texte de recherche indiquant les lieux que vous recherchez, par exemple "restaurant végétarien épicé"
  • Polyligne encodée de l'itinéraire, récupérée à partir de l'appel d'API Routes précédent
  • URL du point de terminaison de l'API Places Text Search
import requests

url = 'https://places.googleapis.com/v1/places:searchText'
api_key = 'YOUR_API_KEY'  # Replace with your actual API key
route_polyline = 'YOUR_ROUTE_POLYLINE'  # Replace with your encoded route polyline

headers = {
    'Content-Type': 'application/json',
    'X-Goog-Api-Key': api_key,
    'X-Goog-FieldMask': 'places.displayName,places.formattedAddress,places.priceLevel'
}

data = {
    "textQuery":
 "Spicy Vegetarian Food",
    "searchAlongRouteParameters": {
        "polyline": {
            "encodedPolyline": route_polyline
        }
    }
}

response = requests.post(url, headers=headers, json=data)

Exemple de données de requête

La requête Search Along Route renvoie une liste de lieux situés sur l'itinéraire. Voici un petit extrait des données d'exemple. La longueur de la réponse peut être limitée en définissant les paramètres du nombre maximal de résultats. Bien sûr, l'ajout de champs augmente la quantité de données reçues. Pour en savoir plus sur la réponse de l'API Places, consultez la documentation.

{
  "places": [
    {
      "formattedAddress": "33 Haymarket, London SW1Y 4HA, UK",
      "displayName": {
        "text": "xxx",
        "languageCode": "en"
      }
    },
    {
      "formattedAddress": "224 Piccadilly, London W1J 9HP, UK",
      "priceLevel": "PRICE_LEVEL_MODERATE",
      "displayName": {
        "text": "yyy",
        "languageCode": "en"
      }
    },
    {
      "formattedAddress": "63 Neal St, London WC2H 9PJ, UK",
      "displayName": {
        "text": "zzz",
        "languageCode": "en"
      }
    },

Exemple de données de réponse

Résumé de l'itinéraire et temps de détour

Trouver uniquement les lieux est une bonne chose, mais il serait utile d'ajouter des informations sur le temps nécessaire pour s'y rendre. La recherche de texte de l'API Places peut également renvoyer un champ routing_summaries qui contient à la fois la durée et la distance du trajet. Le champ de données "Routing summaries" (Récapitulatifs d'itinéraire) est un enfant de la racine de la réponse. Vous ne devez donc pas inclure le préfixe "places." dans le masque de champ.

'X-Goog-FieldMask': 'places.displayName,places.formattedAddress,places.priceLevel,routingSummaries'

Pour obtenir les résumés, vous devez également fournir le paramètre de localisation d'origine pour la recherche, qui est utilisé pour les calculs.

"routingParameters": {
      "origin": {
        "latitude":  -37.8167,
        "longitude": 144.9619
      }
    }

Lorsque vous recevez la réponse, elle comporte une nouvelle section routing summary (récapitulatif de l'itinéraire) contenant des legs (étapes) avec la durée et la distance en mètres.

"routingSummaries": [
    {
      "legs": [
        {
          "duration": "662s",
          "distanceMeters": 3093
        }
      ]
    },

Nous allons ensuite voir comment définir le point de départ de la recherche sur l'itinéraire.

Étape 3 : Obtenez la position deux heures après le début du trajet

Prenons un cas d'utilisation normal où le conducteur souhaite trouver des restaurants qui ne se trouvent pas au début de l'itinéraire, mais plus loin sur la route. Dans notre exemple, le trajet de Londres à Manchester dure environ quatre heures. Le conducteur souhaite trouver un restaurant à deux heures de route. Cette requête nous donne une durée de 120 minutes * 60 secondes = 7 200 secondes.

Dans la réponse de l'API Routes, nous avons la durée de chaque tronçon de l'itinéraire et de chaque étape d'un tronçon. Veillez à inclure le champ legs dans le masque de champ de votre requête. Parcourez les jambes et les pas jusqu'à ce que la durée cumulée atteigne la limite de deux heures ou de 7 200 secondes. Nous avons ensuite trouvé la section et l'étape à définir comme origine de la demande SAR.

Pour accélérer votre travail, vous pouvez essayer la bibliothèque de polylignes pour Python. Vous pouvez l'utiliser pour obtenir les coordonnées du champ de données polyline.endodedPolyline.

Exécutez les commandes suivantes dans le terminal de votre environnement.

> pip install polyline
import requests
import polyline

# We've covered getting a Routes API response earlier,
data = response.json()

  # Extract the first route and its encoded polyline
  route = data["routes"][0]
  polyline_points = polyline.decode(route["polyline"]["encodedPolyline"])

  # Calculate total duration of the route in seconds
  total_duration_seconds = route["duration"]

  # Calculate the desired time offset in seconds, 2h = 120 minutes * 60
  desired_time_offset_seconds = time_offset_minutes * 60

  # Iterate through the legs and steps to find the point at the desired time offset
  elapsed_time_seconds = 0
  for leg in route["legs"]:
      for step in leg["steps"]:
          step_duration_seconds = step["staticDuration"]

          # Check if the desired time offset falls within this step, remove last "s" from string and convert to int
          second_value = int(step_duration_seconds[:-1])
          if elapsed_time_seconds + second_value >= desired_time_offset_seconds:
              # Interpolate to find the exact point within the step
              fraction_of_step = (desired_time_offset_seconds - elapsed_time_seconds) / second_value
              step_polyline_points = polyline.decode(step["polyline"]["encodedPolyline"])
              index = int(len(step_polyline_points) * fraction_of_step)
              return step_polyline_points[index]

          elapsed_time_seconds += second_value

  # If the point is not found (e.g., time offset exceeds route duration)
  return None

Maintenant que nous avons trouvé l'emplacement sur l'itinéraire qui se trouve à deux heures du début du trajet, nous pouvons l'utiliser dans la requête. Il vous suffit d'ajouter la latitude et la longitude dans le paramètre "origin", qui fait lui-même partie du paramètre "routingParameters". Le champ de données "routingSummaries" que nous avons abordé précédemment est recommandé. Vous pouvez également ajouter des paramètres supplémentaires tels que le mode de déplacement et des instructions pour éviter les péages, si vous le souhaitez.


"routingParameters": {
    "origin": {
      "latitude": xx.xxxx,
      "longitude": yy.yyyy
    },
    "travelMode":"DRIVE",
    "routeModifiers": {
      "avoidTolls": true
    }
  }

Itinéraire avec résultats de recherche

Exemple de résultats (icône de voiture ajoutée pour indiquer l'origine de la recherche).

Comme vous pouvez le voir sur l'image, l'API renvoie des lieux qui sont biaisés vers la fin de l'itinéraire, les résultats commençant à peu près à mi-parcours. La recherche est toujours basée sur les mêmes données Google Maps Platform, qui tiennent compte de la pertinence des lieux et de la distance, entre autres facteurs.

Conclusion

Dans ce tutoriel, nous avons appris à combiner deux API Google Maps Platform, Routes et Places, pour planifier un voyage et trouver des restaurants après deux heures de trajet. Pour obtenir les meilleurs résultats, vous devez obtenir une polyligne encodée contenant les coordonnées de latitude et de longitude pour chaque étape du trajet, et définir l'origine de la requête "Rechercher le long de l'itinéraire".

Cette fonctionnalité ajoute un nouvel outil puissant à la recherche de texte et à la recherche à proximité déjà disponibles dans l'API Places. La suite logique serait d'ajouter des services de localisation afin de pouvoir utiliser la position du chauffeur comme point de départ pour trouver l'origine de recherche optimale. De plus, cette fonctionnalité fonctionnerait parfaitement avec un assistant vocal embarqué auquel vous pourriez indiquer vos options de restauration préférées.

Actions suivantes

Lectures complémentaires suggérées :

Participants

Google gère ce document. Le contributeur suivant en est l'auteur initial.

Auteur principal : Mikko Toivanen | Ingénieur de solutions Google Maps Platform