Google 地图道路 API returns 重复坐标和 placeId

Google Maps Roads API returns duplicate coordinates and placeIds

我正在实施 google 地图道路 API 以获取我在道路上单击的坐标。但它 returns 比预期的坐标和 placeids 多。假设我使用方向 API 设置从地点 A 到地点 B 的方向,然后我单击道路上的一些点(比如说 10 个点)来绘制路线。作为响应,道路 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 键然后告诉我这段代码有什么问题?

您正在用 interpolate: true 呼叫道路 API。根据 the documentation,这会导致它按照您所说的方式运行。

from the documentation:

  • interpolate — 是否对路径进行插值以包括形成完整道路几何的所有点。如果为 true,还将返回额外的插值点,从而形成一条平滑地遵循道路几何形状的路径,即使在拐角处和穿过隧道也是如此。 内插路径很可能包含比原始路径更多的点。默认为假。