Поиск по маршруту с помощью Places API

В этом документе описывается, как найти отель, ресторан или заправочную станцию ​​на запланированном маршруте. Вы узнаете, как использовать Routes API для получения полилинии маршрута и использовать ее с запросом Places API Search Along Route (SAR). Также вы узнаете, как получить наилучшие результаты, установив начало поиска по маршруту, например, через 2 часа после начала поездки.

API маршрутов

Для поиска мест по маршруту мы будем использовать Routes API. Данные маршрута из ответа Routes API представляют собой серию координат LatLong от источника до пункта назначения. Данные маршрута содержат участки и ступени, которые следуют за дорожной сетью.

Маршруты также возвращаются в виде закодированной ломаной линии , которую вы передаете в качестве входного параметра в запрос SAR. Кодирование полилиний — это алгоритм сжатия с потерями, который позволяет хранить ряд координат в виде одной строки. Получение ломаной линии из Routes API не является обязательным. Вы можете создать данные самостоятельно, но для целей этого примера API маршрутов — это быстрый и надежный способ получения необходимых данных.

В этом уроке мы используем маршрут из Лондона (-37.8167,144.9619) в Манчестер (-37.8155, 144.9663).

Route from London to Manchester

Маршрут в примере: Лондон — Манчестер.

Шаг 1. Получите маршрут из API маршрутов.

Чтобы получить маршрут из Routes API, вам необходимо предоставить следующую информацию:

  • Места отправления и назначения
  • Способ передвижения (автомобиль, ходьба и т. д.)
  • Любые путевые точки (необязательно)
  • Любые предпочтения (избегать платных дорог, избегать автомагистралей и т. д.)
  • Предпочтение маршрутизации с учетом трафика даст вам наиболее точные оценки, но это требует больших вычислительных затрат и, следовательно, увеличивает задержку ответа.
{"origin":{
    "location": {
        "latLng":{
            "latitude":  -37.8167,
            "longitude": 144.9619
        }
    }
},
"destination":{
    "location": {
        "latLng":{
            "latitude":-37.8155,
            "longitude": 144.9663
        }
    }
},
"routingPreference":"TRAFFIC_AWARE",
"travelMode":"DRIVE"
}

При совершении вызова обязательно включите поле «encodedPolyline» в маску поля заголовков.

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

Полная документация с примерами того, как получить маршрут и получить полилинии маршрута .

После того как вы предоставите эту информацию в запросе, API маршрутов вернет объект маршрута. Объект маршрута будет содержать следующую информацию:

  • Общая дальность маршрута
  • Общая продолжительность маршрута
  • Этапы и ступени маршрута
  • Закодированная полилиния маршрута, этапов и шагов.
{
  "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

Шаг 2. Поиск по запросу маршрута

Текстовый поиск Places API имеет запрос «Поиск вдоль маршрута», который позволяет искать места вдоль маршрута. Чтобы выполнить запрос «Поиск по маршруту», вам необходимо предоставить следующую минимальную информацию:

  • Маска поля, поля которого возвращаются в ответе
  • Действительный ключ API для API, включенного в консоли Google Cloud.
  • Текстовая строка поиска с указанием мест, которые вы ищете, например «пикантный вегетарианский ресторан».
  • Закодированная полилиния маршрута, полученная из предыдущего вызова API Routes.
  • URL-адрес конечной точки API текстового поиска мест
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)

Пример данных запроса

Запрос «Поиск по маршруту» вернет список мест, расположенных вдоль маршрута. Вот краткая часть примеров данных. Длину ответа можно ограничить, установив максимальное количество параметров результатов и добавив больше полей, конечно, увеличится объем получаемых данных. Более подробную информацию об ответе Places API смотрите в документации .

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

Пример данных ответа

Сводка маршрута и время объезда

Найти только локации — это здорово, но будет полезно добавить информацию о том, сколько времени потребуется, чтобы добраться до этих локаций. Текстовый поиск SAR в Places API также может возвращать поле сводки маршрута , которое содержит как продолжительность, так и расстояние поездки. Поле данных сводки маршрутизации является дочерним по отношению к корню ответа, поэтому не следует включать префикс " places. " в маску поля.

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

Чтобы получить сводные данные, вы также должны указать параметр местоположения источника для поиска, который используется для расчетов.

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

Когда вы получите ответ, в нем появится новый раздел со сводкой маршрута , содержащий участки , продолжительность и расстояние которых указаны в метрах.

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

Далее мы рассмотрим, как можно определить, где на маршруте начинать поиск.

Шаг 3. Определите местоположение за 2 часа по маршруту.

Рассмотрим обычный вариант использования, когда водитель хочет найти рестораны не в начале маршрута, а дальше по дороге. В нашем примере поездка из Лондона в Манчестер занимает около 4 часов. Водитель хочет найти ресторан за 2 часа по маршруту. Этот запрос дает нам продолжительность 120 минут * 60 секунд = 7200 секунд.

В ответе API маршрутов у нас есть продолжительность каждого участка маршрута и каждого шага участка. Обязательно включите поле « ноги » в маску поля вашего запроса. Перебирайте ноги и шаги, пока суммарная продолжительность не достигнет предела в 2 часа или 7200 секунд. Затем мы нашли участок и шаг, которые можно указать в качестве источника запроса SAR.

Чтобы ускорить работу, вы можете попробовать библиотеку полилиний для Python . Вы можете использовать его для получения координат из поля данных « polyline.endodedPolyline» .

Выполните следующие команды в терминале вашей среды.

> 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

Теперь, когда мы нашли местоположение на маршруте, который находится в пути через 2 часа, мы можем использовать его в запросе. Просто добавьте широту и долготу в параметр «origin», который, в свою очередь, является частью параметра «routingParameters». Рекомендуется использовать поле данных «routingSummaries», которое мы рассмотрели ранее. Вы также можете добавить дополнительные параметры, такие как режим движения и инструкции, позволяющие избежать платы за проезд, если хотите.


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

Route with search results

Примеры результатов (добавлен значок автомобиля, показывающий источник поиска).

Как вы можете видеть на изображении, API возвращает места, которые смещены к концу маршрута, результаты начинаются примерно с середины поездки. Поиск по-прежнему опирается на те же данные платформы Google Maps, которые среди других факторов учитывают релевантность места и расстояние.

Заключение

В этом уроке мы узнали, как объединить два API платформы Google Maps, «Маршруты» и «Места», чтобы спланировать поездку и найти места, где можно поесть, через 2 часа после начала путешествия. Шаги, которые необходимо предпринять, — это получить закодированную ломаную линию, содержащую координаты широты и долготы для каждого шага пути, и установить источник запроса «Поиск по маршруту», чтобы получить наилучшие результаты.

Эта функция добавляет новый мощный инструмент к уже существующему текстовому поиску и поиску поблизости, доступному в Places API. Логичным продолжением было бы добавление служб определения местоположения, чтобы вы могли использовать местоположение водителя в качестве отправной точки для поиска оптимального источника поиска. Кроме того, эта функция будет отлично работать вместе с автомобильным голосовым помощником, которому вы сможете озвучить предпочитаемые вами варианты питания.

Следующие действия

Рекомендуемая дополнительная литература:

Авторы

Google поддерживает этот документ. Первоначально это написал следующий участник.

Основной автор: Микко Тойванен | Инженер по решениям платформы Google Maps