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 una polilínea de ruta y usarla con una solicitud de API de Places de Search Along Route (SAR). 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 iniciar el viaje.

API de Routes

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

Las rutas también se muestran como una polilínea codificada, que pasas como parámetro de entrada a la solicitud de SAR. La codificación de polilíneas 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 la polilínea de la API de Routes. Puedes crear los datos tú mismo, pero, para los fines de este ejemplo, la API de Routes es una forma rápida y segura de obtener los datos requeridos.

En este instructivo, usamos una ruta de Londres (-37.8167,144.9619) a Mánchester (-37.8155, 144.9663).

Ruta de Londres a Mánchester

Ruta del ejemplo: Londres a Mánchester

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 (automóvil, a pie, etcétera)
  • Cualquier punto de referencia (opcional)
  • Cualquier preferencia (evitar peajes, evitar autopistas, etc.)
  • La preferencia de ruta que tiene en cuenta el tráfico te brindará las estimaciones más precisas, pero es una operación más pesada desde el punto de vista computacional 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 campos de los 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 rutas.

Una vez que proporciones esta información en la solicitud, la API de Routes devolverá 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
  • Las etapas y los pasos de la ruta
  • Es 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 Search Along the Route

La API de Places Text Search tiene una solicitud de Search Along Route que te permite buscar lugares a lo largo de una ruta. Para realizar una solicitud de Search Along Route, 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 qué lugares buscas, por ejemplo, "restaurante vegetariano picante".
  • La polilínea codificada de la ruta, recuperada de la llamada anterior a la API de Routes
  • Es la URL del extremo de la API de 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)

Datos de ejemplo de la solicitud

La solicitud de Search Along Route devolverá una lista de lugares ubicados a lo largo de la ruta. Aquí se muestra una parte breve de los datos de ejemplo. La longitud de la respuesta se puede limitar configurando la cantidad máxima de parámetros de resultados, y agregar más campos, por supuesto, 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"
      }
    },

Ejemplo de datos de respuesta

Resumen de la ruta y tiempos de desvío

Encontrar solo las ubicaciones es genial, pero sería útil agregar la información sobre cuánto tiempo lleva ir a ellas. La SAR en la API de Places Text Search también puede devolver un campo resúmenes de rutas que contiene la duración y la distancia del viaje. El campo de datos de resúmenes de rutas 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, tendrá una nueva sección con el resumen de la ruta que contiene tramos con duración y distancia en metros.

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

A continuación, veremos cómo puedes definir en qué punto de la ruta comenzar la búsqueda.

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

Considera un caso de uso normal en el que el conductor quiere encontrar restaurantes que no estén al comienzo de la ruta, sino más adelante. En nuestro ejemplo, el viaje de Londres a Manchester dura aproximadamente 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 de cada paso de un tramo. Asegúrate de incluir el campo "legs" en la máscara de campo de tu solicitud. Itera a través de 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 tramo y el paso que se deben establecer como el origen de la solicitud de SAR.

Para acelerar tu trabajo, puedes probar la biblioteca de polilíneas para Python. Puedes usarlo para obtener las coordenadas del campo de datos "polyline.encodedPolyline".

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 se encuentra a 2 horas del viaje, podemos usarla en la solicitud. Solo tienes que 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

Ejemplo de resultados (se agregó el ícono de un automóvil para mostrar el origen de la búsqueda).

Como puedes ver en la imagen, la API devuelve lugares que se sesgan hacia el final de la ruta, y los resultados comienzan aproximadamente a mitad del viaje. La búsqueda sigue potenciada por 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 necesarios son obtener una polilínea codificada que contenga las coordenadas de latitud y longitud de cada paso del camino, y establecer el origen de la solicitud de Search Along Route para obtener los mejores resultados.

Esta función agrega una nueva y potente herramienta a la búsqueda de texto y a la búsqueda cercana ya existentes en la API de Places. El siguiente paso 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 en el automóvil al que le indicarías tus opciones de restaurantes preferidas.

Próximas acciones

Lecturas adicionales sugeridas:

Colaboradores

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

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