I've got an app which is receiving limited waypoint data and although the Google Maps Road Snapping does an admirable job of guessing the correct roads based on that data, I'm still experiencing a level of inaccuracy that won't work for our app.
In this example the purple markers represent the real-world "source" waypoints that are being sent in, while the blue markers show the snapped waypoint data coming back from Google based on the data from the source waypoints. I'm using the snapped blue waypoints to generate a polyline to show the route (purple polyline), unfortunately the snapped waypoints and subsequent route should really look more like the red polyline.
I have manually tested this on the online demo of the API with similar "source" waypoints and the route still snaps to the incorrect one, so I can only assume that there simply isn't enough data for Google to snap accurately. The question is, is there any way to improve the odds of a correct snap, given limited data like this? Is there a way I could possibly interpolate the limited source waypoints to attempt to "guide" Google to provide a more accurate snap?
Here's code similar to what I'm using - JSFiddle is here
//setup vars
var trip = [{
"lat": -27.068,
"lng": 153.1483
}, {
"lat": -27.0642,
"lng": 153.1546
}, {
"lat": -27.0552,
"lng": 153.156
}, {
"lat": -27.0518,
"lng": 153.1563
}, {
"lat": -27.0503,
"lng": 153.1552
}, {
"lat": -27.0457,
"lng": 153.1456
}, {
"lat": -27.042,
"lng": 153.1463
}, {
"lat": -27.0349,
"lng": 153.1476
}];
var unsnappedWaypoints = [];
var snappedWaypoints = [];
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 14,
center: {
lat: 0,
lng: 0
}
});
var bounds = new google.maps.LatLngBounds();
//add each waypoint to an array of lat/lngs
$.each(trip, function(key, waypoint) {
unsnappedWaypoints.push(waypoint.lat + ',' + waypoint.lng);
var marker = new google.maps.Marker({
map: map,
icon: 'http://mt.google.com/vt/icon/name=icons/spotlight/spotlight-ad.png',
position: {
lat: waypoint.lat,
lng: waypoint.lng
}
});
});
//perform Google Maps API call with joined array for snapped results
$.ajax({
url: 'https://roads.googleapis.com/v1/snapToRoads?path=' + unsnappedWaypoints.join('|') + '&key=AIzaSyA1JWR3ohBFQ_P7F5eSMSJb0dwV9PbB3pA&interpolate=true',
crossDomain: true,
dataType: 'jsonp'
}).done(function(response) {
//iterate through returned waypoints to create array of lat/lngs for polyline
$.each(response, function(key, snappedPoints) {
$.each(snappedPoints, function(key, snappedPoint) {
snappedWaypoints.push({
lat: snappedPoint.location.latitude,
lng: snappedPoint.location.longitude
});
//add snapped waypoints to map to show difference between originals and returned
var marker = new google.maps.Marker({
map: map,
icon: 'http://mt.google.com/vt/icon?color=ff004C13&name=icons/spotlight/spotlight-waypoint-blue.png',
position: {
lat: snappedPoint.location.latitude,
lng: snappedPoint.location.longitude
}
});
//increase the bounds to take into account waypoints
bounds.extend(new google.maps.LatLng(snappedPoint.location.latitude, snappedPoint.location.longitude));
});
});
//create polyline from snapped waypoints
var tripRoute = new google.maps.Polyline({
path: snappedWaypoints,
gseodesic: true,
strokeColor: '#663496',
strokeOpacity: 1.0,
strokeWeight: 2
});
tripRoute.setMap(map);
//fit these bounds to the map
map.fitBounds(bounds);
});