Google Maps Roads API 返回重复的坐标和 placeIds
Posted
技术标签:
【中文标题】Google Maps Roads API 返回重复的坐标和 placeIds【英文标题】:Google Maps Roads API returns duplicate coordinates and placeIds 【发布时间】:2015-11-12 15:59:21 【问题描述】:我正在实施谷歌地图道路 API 来获取我点击道路的坐标。但它返回的坐标和位置标识超出了预期。假设我使用方向 API 设置从地点 A 到地点 B 的方向,然后我单击道路上的一些点(比如说 10 个点)来绘制路线。作为响应,Roads API 返回了 10 多个 placeId 和坐标,而我只需要 10 个。这是代码。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=drawing,places"></script>
<script>
//GOOGLE_API_KEY
var apiKey = '';
if(!apiKey)
alert("Please provide API Key");
var map;
var elevator;
var directionsDisplay;
var directionsService;
var placeDetailsService;
var drawingManager;
var placeIdArray = [];
var polylines = [];
var snappedCoordinates = [];
var initialLocation;
var siberia = new google.maps.LatLng(60, 105);
var newyork = new google.maps.LatLng(40.69847032728747, -73.9514422416687);
var browserSupportFlag = new Boolean();
function initialize()
document.getElementById("save").style.display="none";
var mapOptions =
zoom: 17,
center: lat: 40.69847032728747, lng: -73.9514422416687
;
directionsService = new google.maps.DirectionsService();
var polylineOptionsActual = new google.maps.Polyline(
strokeColor: '#FF0000',
strokeOpacity: 0.6,
strokeWeight: 2
);
directionsDisplay = new google.maps.DirectionsRenderer(polylineOptions: polylineOptionsActual);
map = new google.maps.Map(document.getElementById('map'), mapOptions);
directionsDisplay.setMap(map);
//Place Details
placeDetailsService= new google.maps.places.PlacesService(map);
// Create an ElevationService
elevator = new google.maps.ElevationService();
// Adds a Places search box. Searching for a place will center the map on that location
map.controls[google.maps.ControlPosition.RIGHT_TOP].push(
document.getElementById('bar'));
//Start Location Searchbox
var autocomplete = new google.maps.places.Autocomplete(document.getElementById('autocStart'));
autocomplete.bindTo('bounds', map);
autocomplete.addListener('place_changed', function ()
var placeStart = autocomplete.getPlace();
//alert(placeStart.place_id);
placeDetailsService.getDetails(
placeId: placeStart.place_id
, function(place, status)
if (status === google.maps.places.PlacesServiceStatus.OK)
console.log(place.geometry.location);
//alert("Start Location: "+place.geometry.location.G);
document.getElementById("startPlaceLat").value=place.geometry.location.G;
document.getElementById("startPlaceLng").value=place.geometry.location.K;
);
);
//End Location Searchbox
var autocomplete1 = new google.maps.places.Autocomplete(document.getElementById('autocEnd'));
autocomplete1.bindTo('bounds', map);
autocomplete1.addListener('place_changed', function ()
var placeEnd = autocomplete1.getPlace();
//alert(placeEnd.place_id);
placeDetailsService.getDetails(
placeId: placeEnd.place_id
, function(place, status)
if (status === google.maps.places.PlacesServiceStatus.OK)
console.log(place.geometry.location);
//alert("End Location: "+place.geometry.location.G);
document.getElementById("endPlaceLat").value=place.geometry.location.G;
document.getElementById("endPlaceLng").value=place.geometry.location.K;
);
);
// Enables the polyline drawing control. Click on the map to start drawing a
// polyline. Each click will add a new vertice. Double-click to stop drawing.
drawingManager = new google.maps.drawing.DrawingManager(
drawingMode: google.maps.drawing.OverlayType.POLYLINE,
drawingControl: true,
drawingControlOptions:
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.POLYLINE
]
,
polylineOptions:
strokeColor: '#696969',
strokeWeight: 2
);
drawingManager.setMap(map);
// Snap-to-road when the polyline is completed.
drawingManager.addListener('polylinecomplete', function (poly)
var path = poly.getPath();
polylines.push(poly);
placeIdArray = [];
runSnapToRoad(path);
);
// Clear button. Click to remove all polylines.
$('#clear').click(function (ev)
for (var i = 0; i < polylines.length; ++i)
polylines[i].setMap(null);
polylines = [];
ev.preventDefault();
document.getElementById("snappedCoordinatesArray").value = "";
document.getElementById("snappedPaceIdArray").value = "";
document.getElementById("altitudeArray").value = "";
document.getElementById("dataDisplay").style.display = "none";
document.getElementById("autocStart").value = "";
document.getElementById("autocEnd").value = "";
document.getElementById("startPlaceLat").value = "";
document.getElementById("startPlaceLng").value = "";
document.getElementById("endPlaceLat").value = "";
document.getElementById("endPlaceLng").value = "";
document.getElementById("save").style.display="none";
directionsDisplay.set('directions', null);
return false;
);
_init();
// Snap a user-created polyline to roads and draw the snapped path
function runSnapToRoad(path)
var pathValues = [];
for (var i = 0; i < path.getLength(); i++)
pathValues.push(path.getAt(i).toUrlValue());
$.get('https://roads.googleapis.com/v1/snapToRoads',
interpolate: true,
key: apiKey,
path: pathValues.join('|')
, function (data)
processSnapToRoadResponse(data);
drawSnappedPolyline();
//getAndDrawSpeedLimits();
);
// Store snapped polyline returned by the snap-to-road method.
function processSnapToRoadResponse(data)
snappedCoordinates = [];
placeIdArray = [];
for (var i = 0; i < data.snappedPoints.length; i++)
var latlng = new google.maps.LatLng(
data.snappedPoints[i].location.latitude,
data.snappedPoints[i].location.longitude);
//getElevation(latlng);
snappedCoordinates.push(latlng);
placeIdArray.push(data.snappedPoints[i].placeId);
//get Altitude in meters
getElevation(snappedCoordinates);
document.getElementById("snappedCoordinatesArray").value = snappedCoordinates;
document.getElementById("snappedPaceIdArray").value = placeIdArray;
// Draws the snapped polyline (after processing snap-to-road response).
function drawSnappedPolyline()
var snappedPolyline = new google.maps.Polyline(
path: snappedCoordinates,
strokeColor: 'black',
strokeWeight: 3
);
snappedPolyline.setMap(map);
polylines.push(snappedPolyline);
// Gets speed limits (for 100 segments at a time) and draws a polyline
// color-coded by speed limit. Must be called after processing snap-to-road
// response.
function getAndDrawSpeedLimits()
for (var i = 0; i <= placeIdArray.length / 100; i++)
// Ensure that no query exceeds the max 100 placeID limit.
var start = i * 100;
var end = Math.min((i + 1) * 100 - 1, placeIdArray.length);
drawSpeedLimits(start, end);
// Gets speed limits for a 100-segment path and draws a polyline color-coded by
// speed limit. Must be called after processing snap-to-road response.
function drawSpeedLimits(start, end)
var placeIdQuery = '';
for (var i = start; i < end; i++)
placeIdQuery += '&placeId=' + placeIdArray[i];
$.get('https://roads.googleapis.com/v1/speedLimits',
'key=' + apiKey + placeIdQuery,
function (speedData)
processSpeedLimitResponse(speedData, start);
);
// Draw a polyline segment (up to 100 road segments) color-coded by speed limit.
function processSpeedLimitResponse(speedData, start)
var end = start + speedData.speedLimits.length;
for (var i = 0; i < speedData.speedLimits.length - 1; i++)
var speedLimit = speedData.speedLimits[i].speedLimit;
var color = getColorForSpeed(speedLimit);
// Take two points for a single-segment polyline.
var coords = snappedCoordinates.slice(start + i, start + i + 2);
var snappedPolyline = new google.maps.Polyline(
path: coords,
strokeColor: color,
strokeWeight: 6
);
snappedPolyline.setMap(map);
polylines.push(snappedPolyline);
//passDataToObjC();
//Color of the roads depends upon speed limit
function getColorForSpeed(speed_kph)
if (speed_kph <= 40)
return 'purple';
if (speed_kph <= 50)
return 'blue';
if (speed_kph <= 60)
return 'green';
if (speed_kph <= 80)
return 'yellow';
if (speed_kph <= 100)
return 'orange';
return 'red';
//Call Elevation API to get Altitude
function getElevation(snappedCoordinatesArr)
var locations = [];
// Retrieve the latlng and push it on the array
for (var i = 0; i < snappedCoordinatesArr.length; i++)
locations.push(snappedCoordinatesArr[i]);
// Create a LocationElevationRequest object using the array's one value
var positionalRequest =
'locations': locations
//alert(positionalRequest);
// Initiate the location request
elevator.getElevationForLocations(positionalRequest, function (results, status)
if (status == google.maps.ElevationStatus.OK)
// Retrieve the first result
if (results)
var altitudeArr = [];
for (var j = 0; j < results.length; j++)
altitudeArr.push(results[j].elevation);
document.getElementById("altitudeArray").value = altitudeArr;
document.getElementById("dataDisplay").style.display = "block";
document.getElementById("save").style.display="block";
//alert(altitudeArr);
else
alert('No results found');
else
alert('Elevation service failed due to: ' + status);
);
//Call Directions API to draw route
function calcRoute()
var start = document.getElementById("autocStart").value;
var end = document.getElementById('autocEnd').value;
var selectedMode = document.getElementById("travelType").value;
//alert(start);
var request =
origin: start,
destination: end,
travelMode: google.maps.TravelMode[selectedMode]
;
directionsService.route(request, function (response, status)
if (status == google.maps.DirectionsStatus.OK)
directionsDisplay.setDirections(response);
);
//Save Details into Database
function _init()
document.getElementById("geodata-form").onsubmit = function (e)
e.preventDefault();
var f = e.target,
formData = new FormData(f),
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function ()
if (xhr.readyState == 4)
if (xhr.responseText)
alert('Geodata successfully saved.');
document.getElementById("save").style.display="none";
// location.reload();
else
alert('Error occured !');
xhr.open("POST", f.action);
xhr.send(formData);
$(window).load(initialize);
</script>
我创建了一个 JSfiddle here。只需提供一个 google API 密钥,然后告诉我这段代码有什么问题吗?
【问题讨论】:
【参考方案1】:您正在使用 interpolate: true
调用 Roads API。根据the documentation 的说法,这会导致它按照您所说的方式行事。
from the documentation:
interpolate - 是否插入路径以包括形成完整道路几何图形的所有点。当为 true 时,还将返回额外的插值点,从而形成一条平滑地遵循道路几何形状的路径,即使在拐角处和通过隧道也是如此。 插值路径很可能包含比原始路径更多的点。默认为 false。【讨论】:
以上是关于Google Maps Roads API 返回重复的坐标和 placeIds的主要内容,如果未能解决你的问题,请参考以下文章
Google Maps Roads API:让“快速上路”更加宽容
如何使用带有 Google Maps Roads API 的坐标列表计算距离
有没有一种好方法可以最大限度地减少 Google Maps Roads API 的负载?