user3534342 user3534342 - 3 months ago 31
Javascript Question

JavaScript Google Maps polylines : issue in connecting all given GPS locations

I am using Javascript in html page to display GPS locations with markers and all these GPS locations are connected by polyline using driving mode. All the markers are being displayed in the output but polyline is not working properly.

The issue is, only few locations are connected by polylines and few of the them are being skipped without connecting .Anyone could point out where the issue is ?

html code

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">

function Call2function(){

var msg ="41.077354,-81.511337:41.080647,-81.516579:41.077435,-81.521561:41.075253,-81.521492:41.074604,-81.520309:41.07415,-81.516335:41.073158,-81.514931:41.070534,-81.516563:41.066677,-81.516502:41.063942,-81.516502:41.06514,-81.513458:41.067383,-81.513412:41.069546,-81.513397:41.070778,-81.513382:41.072514,-81.512619:41.071106,-81.507614:41.073326,-81.506195:41.075886,-81.506058:41.077274,-81.507652:41.077354,-81.511337";
var input_msg=msg.split(":");
var mylatlongg = new Array();
latlongg =input_msg[0].split(",");

var mapOptions = {
center: new google.maps.LatLng(mylatlongg[0],mylatlongg[1]),
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
var infoWindow = new google.maps.InfoWindow();
var lat_lng = new Array();
var latlngbounds = new google.maps.LatLngBounds();
for (i = 0; i<input_msg.length; i++) {
var data = input_msg[i];
var laaty = input_msg[i].split(",")
var myLatlng = new google.maps.LatLng(laaty[0], laaty[1]);
lat_lng.push(myLatlng);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'location'
});
latlngbounds.extend(marker.position);
}
map.setCenter(latlngbounds.getCenter());
map.fitBounds(latlngbounds);

//***********ROUTING****************//

//Intialize the Path Array
var path = new google.maps.MVCArray();

//Intialize the Direction Service
var service = new google.maps.DirectionsService();

//Set the Path Stroke Color
var poly = new google.maps.Polyline({ map: map, strokeColor: '#4986E7' });

//Loop and Draw Path Route between the Points on MAP
for (var i = 0; i < lat_lng.length; i++) {
if ((i + 1) < lat_lng.length) {
var src = lat_lng[i];
var des = lat_lng[i + 1];
// path.push(src);
poly.setPath(path);
service.route({
origin: src,
destination: des,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}, function (result, status) {
if (status == google.maps.DirectionsStatus.OK) {
for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
path.push(result.routes[0].overview_path[i]);
}
}
});
}


}

}
google.maps.event.addDomListener(window, 'load', Call2function);

</script>
<div id="dvMap" style="width: 600px; height: 600px">
</div>
</body>
</html>

Answer

The directions service is subject to a quota and a rate limit. You aren't checking the status returned by the service (OVER_QUERY_LIMIT)

You might want to use waypoints (up to 8 are supported in a single directions request with the free API), you currently only have 20 points, you should be able to do the route with 3 requests.

See the example in this related question:Google Maps API to get bus route

fiddle with error checking

service.route({
   origin: src,
   destination: des,
   travelMode: google.maps.DirectionsTravelMode.DRIVING
  }, function (result, status) {
   if (status == google.maps.DirectionsStatus.OK) {
     for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
       path.push(result.routes[0].overview_path[i]);
     }
   } else {
     document.getElementById('info').innerHTML += status + "<br>";
   }
});

working fiddle (based off of example in this answer)

code snippet:

jQuery(function() {
  var msg = "41.077354,-81.511337:41.080647,-81.516579:41.077435,-81.521561:41.075253,-81.521492:41.074604,-81.520309:41.07415,-81.516335:41.073158,-81.514931:41.070534,-81.516563:41.066677,-81.516502:41.063942,-81.516502:41.06514,-81.513458:41.067383,-81.513412:41.069546,-81.513397:41.070778,-81.513382:41.072514,-81.512619:41.071106,-81.507614:41.073326,-81.506195:41.075886,-81.506058:41.077274,-81.507652:41.077354,-81.511337";
  var input_msg = msg.split(":");

  var map = new window.google.maps.Map(document.getElementById("dvMap"));

  // new up complex objects before passing them around
  var directionsDisplay = new window.google.maps.DirectionsRenderer({
    suppressMarkers: true
  });
  var directionsService = new window.google.maps.DirectionsService();

  Tour_startUp(input_msg);

  window.tour.loadMap(map, directionsDisplay);
  window.tour.fitBounds(map);

  if (input_msg.length > 1)
    window.tour.calcRoute(directionsService, directionsDisplay);
});

function Tour_startUp(stops) {
  if (!window.tour) window.tour = {
    updateStops: function(newStops) {
      stops = newStops;
    },
    // map: google map object
    // directionsDisplay: google directionsDisplay object (comes in empty)
    loadMap: function(map, directionsDisplay) {
      var myOptions = {
        zoom: 13,
        center: new window.google.maps.LatLng(51.507937, -0.076188), // default to London
        mapTypeId: window.google.maps.MapTypeId.ROADMAP
      };
      map.setOptions(myOptions);
      directionsDisplay.setMap(map);
    },
    fitBounds: function(map) {
      var bounds = new window.google.maps.LatLngBounds();

      // extend bounds for each record
      jQuery.each(stops, function(key, val) {
        var latlng = val.split(",");
        var myLatlng = new window.google.maps.LatLng(latlng[0], latlng[1]);
        bounds.extend(myLatlng);
      });
      map.fitBounds(bounds);
    },
    calcRoute: function(directionsService, directionsDisplay) {
      var batches = [];
      var itemsPerBatch = 10; // google API max = 10 - 1 start, 1 stop, and 8 waypoints
      var itemsCounter = 0;
      var wayptsExist = stops.length > 0;

      while (wayptsExist) {
        var subBatch = [];
        var subitemsCounter = 0;

        for (var j = itemsCounter; j < stops.length; j++) {
          subitemsCounter++;
          var latlng = stops[j].split(",");
          subBatch.push({
            location: new window.google.maps.LatLng(latlng[0], latlng[1]),
            stopover: true
          });
          if (subitemsCounter == itemsPerBatch)
            break;
        }

        itemsCounter += subitemsCounter;
        batches.push(subBatch);
        wayptsExist = itemsCounter < stops.length;
        // If it runs again there are still points. Minus 1 before continuing to
        // start up with end of previous tour leg
        itemsCounter--;
      }

      // now we should have a 2 dimensional array with a list of a list of waypoints
      var combinedResults;
      var unsortedResults = [{}]; // to hold the counter and the results themselves as they come back, to later sort
      var directionsResultsReturned = 0;

      for (var k = 0; k < batches.length; k++) {
        var lastIndex = batches[k].length - 1;
        var start = batches[k][0].location;
        var end = batches[k][lastIndex].location;

        // trim first and last entry from array
        var waypts = [];
        waypts = batches[k];
        waypts.splice(0, 1);
        waypts.splice(waypts.length - 1, 1);

        var request = {
          origin: start,
          destination: end,
          waypoints: waypts,
          travelMode: window.google.maps.TravelMode.WALKING
        };
        (function(kk) {
          directionsService.route(request, function(result, status) {
            if (status == window.google.maps.DirectionsStatus.OK) {

              var unsortedResult = {
                order: kk,
                result: result
              };
              unsortedResults.push(unsortedResult);

              directionsResultsReturned++;

              if (directionsResultsReturned == batches.length) // we've received all the results. put to map
              {
                // sort the returned values into their correct order
                unsortedResults.sort(function(a, b) {
                  return parseFloat(a.order) - parseFloat(b.order);
                });
                var count = 0;
                for (var key in unsortedResults) {
                  if (unsortedResults[key].result != null) {
                    if (unsortedResults.hasOwnProperty(key)) {
                      if (count == 0) // first results. new up the combinedResults object
                        combinedResults = unsortedResults[key].result;
                      else {
                        // only building up legs, overview_path, and bounds in my consolidated object. This is not a complete
                        // directionResults object, but enough to draw a path on the map, which is all I need
                        combinedResults.routes[0].legs = combinedResults.routes[0].legs.concat(unsortedResults[key].result.routes[0].legs);
                        combinedResults.routes[0].overview_path = combinedResults.routes[0].overview_path.concat(unsortedResults[key].result.routes[0].overview_path);

                        combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getNorthEast());
                        combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getSouthWest());
                      }
                      count++;
                    }
                  }
                }
                directionsDisplay.setDirections(combinedResults);
                var legs = combinedResults.routes[0].legs;
                // alert(legs.length);
                for (var i = 0; i < legs.length; i++) {
                  var markerletter = "A".charCodeAt(0);
                  markerletter += i;
                  markerletter = String.fromCharCode(markerletter);
                  createMarker(directionsDisplay.getMap(), legs[i].start_location, "marker" + i, "some text for marker " + i + "<br>" + legs[i].start_address, markerletter);
                }
                var i = legs.length;
                var markerletter = "A".charCodeAt(0);
                markerletter += i;
                markerletter = String.fromCharCode(markerletter);
                createMarker(directionsDisplay.getMap(), legs[legs.length - 1].end_location, "marker" + i, "some text for the " + i + "marker<br>" + legs[legs.length - 1].end_address, markerletter);
              }
            }
          });
        })(k);
      }
    }
  };
}
var infowindow = new google.maps.InfoWindow({
  size: new google.maps.Size(150, 50)
});

var icons = new Array();
icons["red"] = new google.maps.MarkerImage("mapIcons/marker_red.png",
  // This marker is 20 pixels wide by 34 pixels tall.
  new google.maps.Size(20, 34),
  // The origin for this image is 0,0.
  new google.maps.Point(0, 0),
  // The anchor for this image is at 9,34.
  new google.maps.Point(9, 34));



function getMarkerImage(iconStr) {
    if ((typeof(iconStr) == "undefined") || (iconStr == null)) {
      iconStr = "red";
    }
    if (!icons[iconStr]) {
      icons[iconStr] = new google.maps.MarkerImage("http://www.google.com/mapfiles/marker" + iconStr + ".png",
        // This marker is 20 pixels wide by 34 pixels tall.
        new google.maps.Size(20, 34),
        // The origin for this image is 0,0.
        new google.maps.Point(0, 0),
        // The anchor for this image is at 6,20.
        new google.maps.Point(9, 34));
    }
    return icons[iconStr];

  }
  // Marker sizes are expressed as a Size of X,Y
  // where the origin of the image (0,0) is located
  // in the top left of the image.

// Origins, anchor positions and coordinates of the marker
// increase in the X direction to the right and in
// the Y direction down.

var iconImage = new google.maps.MarkerImage('mapIcons/marker_red.png',
  // This marker is 20 pixels wide by 34 pixels tall.
  new google.maps.Size(20, 34),
  // The origin for this image is 0,0.
  new google.maps.Point(0, 0),
  // The anchor for this image is at 9,34.
  new google.maps.Point(9, 34));
var iconShadow = new google.maps.MarkerImage('http://www.google.com/mapfiles/shadow50.png',
  // The shadow image is larger in the horizontal dimension
  // while the position and offset are the same as for the main image.
  new google.maps.Size(37, 34),
  new google.maps.Point(0, 0),
  new google.maps.Point(9, 34));
// Shapes define the clickable region of the icon.
// The type defines an HTML &lt;area&gt; element 'poly' which
// traces out a polygon as a series of X,Y points. The final
// coordinate closes the poly by connecting to the first
// coordinate.
var iconShape = {
  coord: [9, 0, 6, 1, 4, 2, 2, 4, 0, 8, 0, 12, 1, 14, 2, 16, 5, 19, 7, 23, 8, 26, 9, 30, 9, 34, 11, 34, 11, 30, 12, 26, 13, 24, 14, 21, 16, 18, 18, 16, 20, 12, 20, 8, 18, 4, 16, 2, 15, 1, 13, 0],
  type: 'poly'
};


function createMarker(map, latlng, label, html, color) {
  // alert("createMarker("+latlng+","+label+","+html+","+color+")");
  var contentString = '<b>' + label + '</b><br>' + html;
  var marker = new google.maps.Marker({
    position: latlng,
    map: map,
    shadow: iconShadow,
    icon: getMarkerImage(color),
    shape: iconShape,
    title: label,
    zIndex: Math.round(latlng.lat() * -100000) << 5
  });
  marker.myname = label;

  google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(contentString);
    infowindow.open(map, marker);
  });
  return marker;
}


function Call2function() {

    var msg = "41.077354,-81.511337:41.080647,-81.516579:41.077435,-81.521561:41.075253,-81.521492:41.074604,-81.520309:41.07415,-81.516335:41.073158,-81.514931:41.070534,-81.516563:41.066677,-81.516502:41.063942,-81.516502:41.06514,-81.513458:41.067383,-81.513412:41.069546,-81.513397:41.070778,-81.513382:41.072514,-81.512619:41.071106,-81.507614:41.073326,-81.506195:41.075886,-81.506058:41.077274,-81.507652:41.077354,-81.511337";
    var input_msg = msg.split(":");
    var mylatlongg = new Array();
    latlongg = input_msg[0].split(",");

    var mapOptions = {
      center: new google.maps.LatLng(mylatlongg[0], mylatlongg[1]),
      zoom: 12,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
    var infoWindow = new google.maps.InfoWindow();
    var lat_lng = new Array();
    var latlngbounds = new google.maps.LatLngBounds();
    document.getElementById('info').innerHTML = "total points: " + input_msg.length + "<br>";
    for (i = 0; i < input_msg.length; i++) {
      var data = input_msg[i];
      var laaty = input_msg[i].split(",")
      var myLatlng = new google.maps.LatLng(laaty[0], laaty[1]);
      lat_lng.push(myLatlng);
      var marker = new google.maps.Marker({
        position: myLatlng,
        map: map,
        title: 'location'
      });
      latlngbounds.extend(marker.position);
    }
    map.setCenter(latlngbounds.getCenter());
    map.fitBounds(latlngbounds);

    //***********ROUTING****************//

    //Intialize the Path Array
    var path = new google.maps.MVCArray();

    //Intialize the Direction Service
    var service = new google.maps.DirectionsService();

    //Set the Path Stroke Color
    var poly = new google.maps.Polyline({
      map: map,
      strokeColor: '#4986E7'
    });

    //Loop and Draw Path Route between the Points on MAP
    for (var i = 0; i < lat_lng.length; i++) {
      if ((i + 1) < lat_lng.length) {
        var src = lat_lng[i];
        var des = lat_lng[i + 1];
        // path.push(src);
        poly.setPath(path);
        service.route({
          origin: src,
          destination: des,
          travelMode: google.maps.DirectionsTravelMode.DRIVING
        }, function(result, status) {
          if (status == google.maps.DirectionsStatus.OK) {
            for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
              path.push(result.routes[0].overview_path[i]);
            }
          } else {
            document.getElementById('info').innerHTML += status + "<br>";
          }
        });
      }
    }
  }
  // google.maps.event.addDomListener(window, 'load', Call2function);
html,
body,
#map_canvas {
  height: 500px;
  width: 500px;
  margin: 0px;
  padding: 0px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="dvMap" style="width: 600px; height: 600px"></div>
<div id="info"></div>

Comments