Places API を使用したルート沿いの検索

このドキュメントでは、計画したルート沿いのホテル、レストラン、ガソリン スタンドを検索する方法について説明します。Routes API を使用してルートのポリラインを取得し、それを Places APISearch Along Route(SAR)リクエストで使用する方法について説明します。また、ルートに沿って検索の出発地を設定して(たとえば、旅行開始から 2 時間後など)、最適な結果を得る方法についても説明します。

Routes API

ルート沿いの場所を検索するために、Routes API を使用します。Routes API レスポンスのルートデータは、出発地から目的地までの LatLong 座標の連続です。ルートデータには、道路網に沿ったレッグとステップが含まれます。

ルートは エンコードされたポリラインとしても返されます。これは、SAR リクエストへの入力パラメータとして渡します。ポリライン エンコードは、一連の座標を 1 つの文字列として保存できる非可逆圧縮アルゴリズムです。Routes API からポリラインを取得することは必須ではありません。データは自分で作成することもできますが、この例では、必要なデータを迅速かつ確実に取得できる Routes API を使用します。

このチュートリアルでは、ロンドン(-37.8167,144.9619)からマンチェスター(-37.8155, 144.9663)までのルートを使用します。

ロンドンからマンチェスターへのルート

例のルート: ロンドンからマンチェスター

ステップ 1: Routes 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"
}

ルートを取得する方法とルートのポリラインを取得する方法の例を含む完全なドキュメント。

リクエストでこの情報を提供すると、Routes 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 のテキスト検索には、ルート沿いの場所を検索できる Search Along Route リクエストがあります。ルート沿い検索リクエストを行うには、次の最小限の情報を提供する必要があります。

  • レスポンスで返されるフィールドのフィールド マスク
  • Google Cloud コンソールで有効になっている API の有効な API キー
  • 探している場所を示す検索テキスト文字列(「辛いベジタリアン レストラン」など)
  • 前の Routes API 呼び出しから取得したルートのエンコードされたポリライン
  • Places Text Search API エンドポイントの URL
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)

リクエストデータの例

Search Along Route リクエストは、ルート沿いにある場所のリストを返します。以下は、サンプルデータの一部です。レスポンスの長さは、結果の最大数パラメータを設定することで制限できます。もちろん、フィールドを追加すると、受信するデータ量が増えます。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"
      }
    },

レスポンス データの例

ルートの概要と迂回時間

場所を見つけるだけでも便利ですが、これらの場所に行くのにかかる時間を追加するとさらに便利になります。Places API のテキスト検索の SAR は、移動時間と距離の両方を含むルートの概要フィールドを返すこともできます。ルーティングの概要データ フィールドはレスポンス ルートの子であるため、フィールド マスクに「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 秒 = 7,200 秒の期間を取得します。

Routes API のレスポンスには、ルートの各区間と区間の各ステップの所要時間が含まれています。リクエストのフィールド マスクに「legs」フィールドを含めるようにしてください。累積時間が 2 時間または 7,200 秒の上限に達するまで、レッグとステップをループします。これで、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
    }
  }

検索結果を含むルート

結果の例(検索元を示すために車のアイコンを追加)。

画像でわかるように、API はルートの終点に偏った場所を返します。結果は旅行の中間あたりから始まります。検索は、場所の関連性や距離などの要素を考慮した Google Maps Platform のデータに基づいて行われます。

まとめ

このチュートリアルでは、Google Maps Platform API のルートとプレイスを組み合わせて、旅行を計画し、旅行開始から 2 時間後に食事をする場所を見つける方法を学びました。必要な手順は、各ステップの緯度と経度の座標を含むエンコードされたポリラインを取得し、最適な結果を得るためにルート沿い検索リクエストの出発地を設定することです。

この機能により、Places API で利用可能な既存のテキスト検索と周辺検索に、強力な新しいツールが追加されます。論理的なフォローアップとして、位置情報サービスを追加して、最適な検索起点を見つけるための出発点としてドライバーの位置情報を使用することが考えられます。また、この機能は、車載の音声アシスタントと連携して、好みの食事オプションを音声で指定するのに最適です。

次のアクション

  • ドキュメントの例を試す
  • フィードバックを送信します。

おすすめの参考資料:

投稿者

このドキュメントは Google が管理しています。この投稿は、次の投稿者が作成したものです。

主な著者: Mikko Toivanen | Google Maps Platform ソリューション エンジニア