使用 Places API 沿路搜尋

本文件說明如何在預定路線中找到飯店、餐廳或加油站。您將瞭解如何使用 Routes API 取得路線多邊形,並將其用於 Places API 沿路搜尋 (SAR) 要求。您也將瞭解如何設定沿路搜尋起點,例如行程開始後 2 小時,以便取得最佳結果。

Routes API

為了搜尋沿途地點,我們將使用 Routes API。來自 Routes API 回應的路線資料,是從起點到目的地的一系列 LatLong 座標。路線資料包含沿著道路網路的路段和步驟。

路線也會以已編碼的多邊形形式傳回,您可以將其做為輸入參數傳遞至 SAR 要求。折線編碼是一種有損壓縮演算法,可讓您將一系列座標儲存為單一字串。您不一定要從 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 Text Search 提供「沿路搜尋」要求,可讓您搜尋沿路的地點。如要執行沿路搜尋要求,您必須提供下列最低限度的資訊:

  • 回應中傳回的欄位欄位遮罩
  • 在 Google Cloud 控制台中啟用的 API 的有效 API 金鑰
  • 搜尋文字字串,指出你要尋找的地點,例如「辛辣素食餐廳」
  • 從先前的 Routes API 呼叫擷取的路線編碼折線
  • Places Text Search 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"
      }
    },

回應資料範例

路線摘要和繞路時間

雖然只找到地點就很棒,但如果能加入前往這些地點所需的時間資訊,會更有幫助。Places API Text Search 中的 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 秒 = 7200 秒的時間長度。

在 Routes API 回應中,我們有路線的每個航段和每個航段的步驟持續時間。請務必在要求的欄位遮罩中加入「legs」欄位。重複執行腿部和步驟,直到累積時間達到 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
    }
  }

路線與搜尋結果

結果範例 (新增汽車圖示,以顯示搜尋來源)。

如圖所示,API 會傳回偏向路線終點的結果,也就是從行程中段開始的結果。搜尋功能仍會使用相同的 Google 地圖平台資料,考量地點相關性和距離等其他因素。

結語

在本教學課程中,我們學習如何結合兩個 Google 地圖平台 API (路徑和地點),規劃行程並在行程開始後 2 小時找到可用餐的地點。您必須採取的步驟包括取得已編碼的折線,其中包含路線每個步驟的經緯度座標,並設定沿路搜尋要求的來源,以便取得最佳結果。

這項功能可為 Places API 現有的文字搜尋和附近搜尋功能,新增強大的全新工具。接下來,您可以新增位置服務,以便使用駕駛員的位置做為起點,找出最佳搜尋起點。此外,這項功能還能與車內語音助理完美搭配,讓你以語音表達偏好的用餐選項。

後續行動

建議參閱以下文章:

貢獻者

本文件由 Google 維護。以下是原作者。

主要作者:Mikko Toivanen | Google 地圖平台解決方案工程師