Buscar en la ruta con la API de Places

En este documento, se describe cómo encontrar un hotel, un restaurante o una estación de servicio a lo largo de una ruta planificada. Aprenderás a usar la API de Routes para obtener un polilínea de ruta y usarlo con la solicitud Search Along Route (SAR) de la API de Places. También aprenderás a obtener los mejores resultados configurando el origen de la búsqueda a lo largo de la ruta, por ejemplo, 2 horas después de iniciado el viaje.

API de Routes

Para buscar lugares a lo largo de la ruta, usaremos la API de Routes. Los datos de ruta de la respuesta de la API de Routes son una serie de coordenadas de latitud y longitud desde el origen hasta el destino. Los datos de ruta contienen tramos y pasos que siguen la red de rutas.

Las rutas también se muestran como un polilínea codificada, que pasas como un parámetro de entrada a la solicitud de SAR. La codificación de polilínea es un algoritmo de compresión con pérdida que te permite almacenar una serie de coordenadas como una sola cadena. No es obligatorio obtener el polilinea de la API de Routes. Puedes crear los datos por tu cuenta, pero, a los efectos de este ejemplo, la API de Routes es una forma rápida y segura de obtener los datos necesarios.

En este instructivo, usaremos una ruta de Londres (-37.8167,144.9619) a Manchester (-37.8155, 144.9663).

Ruta de Londres a Manchester

Ruta del ejemplo: Londres a Manchester

Paso 1: Obtén una ruta de la API de Routes

Para obtener una ruta de la API de Routes, deberás proporcionar la siguiente información:

  • Las ubicaciones de origen y destino
  • El medio de transporte (conducir, caminar, etcétera)
  • Cualquier punto de referencia (opcional)
  • Cualquier preferencia (evitar peajes, evitar autopistas, etcétera)
  • La preferencia de enrutamiento consciente del tráfico te brindará las estimaciones más precisas, pero es una operación más pesada en términos de procesamiento y, por lo tanto, aumenta la latencia de la respuesta.
{"origin":{
    "location": {
        "latLng":{
            "latitude":  -37.8167,
            "longitude": 144.9619
        }
    }
},
"destination":{
    "location": {
        "latLng":{
            "latitude":-37.8155,
            "longitude": 144.9663
        }
    }
},
"routingPreference":"TRAFFIC_AWARE",
"travelMode":"DRIVE"
}

Cuando realices la llamada, asegúrate de incluir el campo "encodedPolyline" en la máscara de campo de encabezados.

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

La documentación completa con ejemplos de cómo obtener una ruta y obtener polilíneas de ruta.

Una vez que hayas proporcionado esta información en la solicitud, la API de Routes mostrará un objeto de ruta. El objeto de ruta contendrá la siguiente información:

  • La distancia total de la ruta
  • La duración total de la ruta
  • Los tramos y pasos de la ruta
  • La polilínea codificada de la ruta, los tramos y los pasos
{
  "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

Paso 2: Solicitud de búsqueda a lo largo de la ruta

La Búsqueda de texto de la API de Places tiene una solicitud de Búsqueda a lo largo de la ruta que te permite buscar lugares a lo largo de una ruta. Para realizar una solicitud de búsqueda a lo largo de una ruta, deberás proporcionar la siguiente información mínima:

  • Máscara de campo de los campos que se muestran en la respuesta
  • Una clave de API válida para la API habilitada en la consola de Google Cloud
  • Cadena de texto de búsqueda que indica los lugares que buscas, por ejemplo, "restaurante vegetariano picante"
  • La polilínea codificada de la ruta, recuperada de la llamada anterior a la API de Routes
  • URL del extremo de la API de Text Search de Places
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)

Datos de solicitud de ejemplo

La solicitud de búsqueda a lo largo de una ruta mostrará una lista de lugares que se encuentran a lo largo de la ruta. Esta es una parte breve de los datos de ejemplo. La longitud de la respuesta se puede limitar si se establece la cantidad máxima de parámetros de resultados y, por supuesto, si se agregan más campos, aumenta la cantidad de datos recibidos. Para obtener más detalles sobre la respuesta de la API de Places, consulta la documentación.

{
  "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"
      }
    },

Datos de respuesta de ejemplo

Resumen de enrutamiento y tiempos de desvío

Encontrar solo las ubicaciones es genial, pero será útil agregar la información sobre cuánto tiempo lleva ir a estas ubicaciones. La SAR en Text Search de la API de Places también puede mostrar un campo de resumen de planificación de ruta que contiene la duración y la distancia que se debe recorrer. El campo de datos de resúmenes de planificación de ruta es secundario de la raíz de la respuesta, por lo que no debes incluir el prefijo "places." en la máscara de campo.

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

Para obtener los resúmenes, también debes proporcionar el parámetro de ubicación de origen para la búsqueda que se usa en los cálculos.

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

Cuando recibas la respuesta, verás una sección nueva con el resumen de planificación de ruta, que contiene etapas con la duración y la distancia en metros.

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

A continuación, veremos cómo puedes definir dónde comenzar la búsqueda a lo largo de la ruta.

Paso 3: Obtén la ubicación 2 horas a lo largo de la ruta

Considera un caso de uso normal en el que el conductor quiere encontrar restaurantes no al comienzo de la ruta, sino más adelante. En nuestro ejemplo, el viaje de Londres a Manchester dura alrededor de 4 horas. El conductor quiere encontrar un restaurante a 2 horas de la ruta. Esta solicitud nos proporciona la duración de 120 minutos × 60 segundos = 7,200 segundos.

En la respuesta de la API de Routes, tenemos la duración de cada tramo de la ruta y cada paso de un tramo. Asegúrate de incluir el campo "legs" en la máscara de campo de tu solicitud. Realiza un bucle por las piernas y los pasos hasta que la duración acumulada alcance el límite de 2 horas o 7,200 segundos. Luego, encontramos la etapa y el paso que se establecerán como el origen de la solicitud de SAR

Para acelerar tu trabajo, te recomendamos que pruebes la biblioteca de polilíneas para Python. Puedes usarlo para obtener las coordenadas del campo de datos "polyline.endodedPolyline".

Ejecuta los siguientes comandos en la terminal de tu entorno.

> 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

Ahora que encontramos la ubicación en la ruta que está a 2 horas del viaje, podemos usarla en la solicitud. Solo debes agregar la latitud y la longitud en el parámetro "origin", que a su vez forma parte del parámetro "routingParameters". Se recomienda el campo de datos "routingSummaries", que analizamos anteriormente. También puedes agregar parámetros adicionales, como el modo de viaje y las instrucciones para evitar peajes, si lo deseas.


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

Ruta con resultados de la búsqueda

Resultados de ejemplo (se agregó el ícono de automóvil para mostrar el origen de la búsqueda)

Como puedes ver en la imagen, la API muestra lugares sesgados hacia el final de la ruta, y los resultados comienzan a aparecer a mitad del viaje. La búsqueda sigue aprovechando los mismos datos de Google Maps Platform, que tienen en cuenta la relevancia del lugar y la distancia, entre otros factores.

Conclusión

En este instructivo, aprendimos a combinar dos APIs de Google Maps Platform, Routes y Places, para planificar un viaje y encontrar lugares para comer después de 2 horas de viaje. Los pasos que se deben seguir son obtener una polilínea codificada que contenga las coordenadas de latitud y longitud de cada paso del recorrido y establecer el origen de la solicitud de búsqueda a lo largo de la ruta para obtener los mejores resultados.

Esta función agrega una nueva herramienta potente a la búsqueda de texto y la búsqueda de Nearby existentes en la API de Places. El seguimiento lógico sería agregar servicios de ubicación para que puedas usar la ubicación del conductor como punto de partida para encontrar el origen de búsqueda óptimo. Además, esta función funcionaría perfectamente junto con un asistente de voz integrado en el vehículo al que le dirías tus opciones de restaurantes preferidas.

Próximos pasos

Lecturas adicionales sugeridas:

Colaboradores

Google mantiene este documento. El siguiente colaborador lo escribió originalmente.

Autor principal: Mikko Toivanen | Ingeniero de Soluciones de Google Maps Platform