本文档介绍了如何查找规划路线沿途的酒店、餐厅或加油站。您将学习如何使用 Routes API 获取路线折线,并将其与 Places API Search Along Route (SAR) 请求搭配使用。您还将了解如何通过设置沿路线的搜索起点(例如在旅程开始 2 小时后)来获得最佳结果。
Routes API
为了搜索沿途地点,我们将使用 Routes API。来自 Routes API 响应的路线数据是一系列从起点到终点的 LatLng 坐标。路线数据包含沿道路网行进的路线段和路线步。
路线也会以编码的折线的形式返回,您可以将其作为输入参数传递给 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 文本搜索具有“沿路线搜索”请求,可让您搜索路线沿途的地点。如需发出“沿路线搜索”请求,您至少需要提供以下信息:
- 响应中返回的字段的字段掩码
- 在 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 文本搜索中的 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 Maps Platform 数据提供支持,该数据会考虑地点相关性和距离等因素。
总结
在本教程中,我们学习了如何将两个 Google Maps Platform API(路线和地点)结合使用,以规划行程并在旅程开始 2 小时后查找用餐地点。需要采取的步骤包括:获取包含路线中每个路段的纬度和经度坐标的编码折线,以及设置“沿途搜索”请求来源以获得最佳结果。
此功能为 Places API 中已有的文本搜索和附近搜索功能添加了一款强大的新工具。接下来,我们可能会添加位置信息服务,以便您可以使用司机位置作为起点来寻找最佳搜索起点。此外,此功能还可与车载语音助理完美搭配使用,您只需说出自己喜欢的餐饮选项即可。
后续操作
- 试用文档中的示例。
- 提供反馈。
建议的延伸阅读材料:
参稿人
Google 负责维护本文档。以下贡献者最初撰写了此内容。
主要作者:Mikko Toivanen | Google Maps Platform 解决方案工程师