Google Maps Roads API returns duplicate coordinates and placeIds

泄露秘密 提交于 2019-12-13 07:21:23

问题


I'm implementing google maps roads API to pick up the coordinates where I clicked on the roads. But it returns more than expected coordinates and placeids. Suppose I set a direction from place A to place B using directions API then I clicked some points (lets say 10 points) on the roads to draw the route. In response the roads API is returning more than 10 placeIds and coordinates where I need only 10. Here is the code.

<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>

I have created a JSfiddle here. Just give a google API key and then tell me whats wrong with this code?


回答1:


You are calling the Roads API with interpolate: true. According to the documentation, that causes it to behave the way you say it is.

from the documentation:

  • interpolate — Whether to interpolate a path to include all points forming the full road-geometry. When true, additional interpolated points will also be returned, resulting in a path that smoothly follows the geometry of the road, even around corners and through tunnels. Interpolated paths will most likely contain more points than the original path. Defaults to false.


来源:https://stackoverflow.com/questions/32094030/google-maps-roads-api-returns-duplicate-coordinates-and-placeids

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!