0

I'm using gmaps Api to make a route for a person who have to visit a list of markets (my waypoints) to take note of their stocks. I'm using the user's house location for the origin of the route and the location of the markets as my waypoints. The problem is that I don't know which waypoint is the route's destination because I set the property optimization = true when call the the direction service, but the api needs a destination to trace the route.

What I need is a way to tell the api to use the last waypoint of my optimized route as a destination.

geocodezip
  • 158,664
  • 13
  • 220
  • 245
Pablo García
  • 359
  • 3
  • 9

1 Answers1

1

You could make multiple requests to the directions service, one with each possible waypoint as the final destination, pick the shortest resulting distance.

proof of concept fiddle

code snippet:

var map;
var directionsServices = [];
var directionsDisplays = [];
// constant "start" address
var start = "Paramus, NJ";
// list of possible candidate destinations/waypoints (must be < 9)
var locations = ["67 E Ridgewood Ave, Paramus, NJ 07652",
  "450 Rochelle Ave, Rochelle Park, NJ 07662,",
  "720 River Rd, New Milford, NJ 07646",
  "280 Main St, New Milford, NJ 07646",
  "469 Passaic St, Hackensack, NJ 07601",
  "91 Broadway, Elmwood Park, NJ 07407",
  "206 Market St, Saddle Brook, NJ 07662"
];
var routes = [];

function initialize() {
  var map = new google.maps.Map(
    document.getElementById("map_canvas"), {
      center: new google.maps.LatLng(37.4419, -122.1419),
      zoom: 13,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });
  document.getElementById('info').innerHTML += "<u><b>intermediate results:</b></u><br>";
  getDirections(start, locations, map);
}
google.maps.event.addDomListener(window, "load", initialize);

function getDirections(start, waypoints, map) {
  var requests = [];
  var request = {
    origin: start,
    optimizeWaypoints: true,
    travelMode: google.maps.TravelMode.DRIVING
  };
  for (var j = 0; j < waypoints.length; j++) {
    var waypts = [];
    for (var i = 0; i < waypoints.length; i++) {
      if (i != j) {
        waypts.push({
          location: waypoints[i],
          stopover: true
        });
      }
    }
    requests[j] = {};
    requests[j].destination = waypoints[j];
    requests[j].waypoints = waypts;
    requests[j].origin = start;
    requests[j].optimizeWaypoints = true;
    requests[j].travelMode = google.maps.TravelMode.DRIVING;

    setTimeout(function(request, j) {
      sendDirectionsRequest(request, j, map);
    }(requests[j], j), 3000 * j);
  }
}

function sendDirectionsRequest(request, index, map) {
  var directionsService = new google.maps.DirectionsService();
  directionsServices.push(directionsService);
  directionsService.route(request, function(response, status) {
    if (status === google.maps.DirectionsStatus.OK) {
      var route = response.routes[0];
      routes.push(route);
      var distance = 0;
      var duration = 0;
      for (var i = 0; i < route.legs.length; i++) {
        distance += route.legs[i].distance.value;
        duration += route.legs[i].duration.value;
      }
      route.distance = distance;
      route.duration = duration;
      route.index = index;
      document.getElementById('info').innerHTML += (routes.length - 1) + " dist:" + (route.distance / 1000).toFixed(2) + " km dur:" + (route.duration / 60).toFixed(2) + " min dest:" + index + " loc:" + locations[index] + " waypt order:" + route.waypoint_order + "<br>";
      if (routes.length == locations.length) {
        routes.sort(sortFcn);
        var directionsDisplay = new google.maps.DirectionsRenderer({
          map: map,
          polylineOptions: {
            strokeOpacity: 0.9,
            strokeWeight: 4,
            strokeColor: "black",
            zIndex: 10
          }
        });
        directionsDisplay.setDirections(response);
        directionsDisplay.setMap(map);
        document.getElementById('info').innerHTML += "<u><b>shortest result:</b></u><br>" + routes[0].index + " dist:" + (routes[0].distance / 1000).toFixed(2) + " km dur:" + (routes[0].duration / 60).toFixed(2) + " min dest:" + routes[0].index + " loc:" + locations[index] + " waypt order:" + routes[0].waypoint_order + "<br>";
      }
    } else {
      window.alert('Directions request failed due to ' + status);
    }
  });
}

function sortFcn(a, b) {
  if (a.distance > b.distance) return 1;
  else if (a.distance < b.distance) return -1;
  else return 0;
}
html,
body,
#map_canvas {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="info"></div>
<div id="map_canvas"></div>
geocodezip
  • 158,664
  • 13
  • 220
  • 245
  • You are right! I had thought on this workaround and it work's. but my intension is not to call the service multiple times. Maybe it is the only way. Thanks for your answer. – Pablo García Nov 22 '15 at 20:04
  • After research it's seems to be no way no do this in one call. – Pablo García Nov 27 '15 at 14:36
  • Certainly not in a single call (the answer specifically says "multiple requests to the directions service"). You need to call the directions service N-1 times for N waypoints. Then sort the results to find the shortest (time or distance). – geocodezip Nov 27 '15 at 14:38
  • Not realy. I will call the api one time and get the returning waypoints in optimized order. Then i use the last waypoint in the ordered array and use it as destination. 2 calls are needed. – Pablo García Nov 27 '15 at 14:40