-1

For example, given a route between Miami and New York (driving), I'd like to figure out the lat/long of a location along that same route after some number of miles.

Does Google's API provide anyway of finding a location using a given route and asking for a location some miles into it?

Adnan
  • 814
  • 1
  • 6
  • 8

1 Answers1

0

related questions:

Uses http://www.geocodezip.com/scripts/v3_epoly.js

A 3rd party library written for the Google Maps Javascript API v2 by Mike Williams, ported to v3.
Documentation for the v2 version

Has this method:

  • .GetPointAtDistance() returns a LatLng at the specified distance along the path. The distance is specified in metres Returns null if the path is shorter than that

live example

screenshot of marker 250 km into route

code snippet:

var directionDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var polyline = null;
var marker;
var infowindow;

function createMarker(latlng, label, html) {
  var contentString = '<b>' + label + '</b><br>' + html;
  var marker = new google.maps.Marker({
    position: latlng,
    map: map,
    title: label,
    zIndex: Math.round(latlng.lat() * -100000) << 5,
    contentString: contentString
  });
  marker.myname = label;
  // gmarkers.push(marker);

  google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(this.contentString);
    infowindow.open(map, marker);
  });
  return marker;
}
var myLatLng = null;
var lat;
var lng;
var zoom = 2;
var maptype;

function initialize() {
  infowindow = new google.maps.InfoWindow();
  myLatLng = new google.maps.LatLng(37.422104808, -122.0838851);
  maptype = google.maps.MapTypeId.ROADMAP;
  var myOptions = {
    zoom: zoom,
    center: myLatLng,
    mapTypeId: maptype
  };
  directionsDisplay = new google.maps.DirectionsRenderer({
    suppressMarkers: true
  });

  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  polyline = new google.maps.Polyline({
    path: [],
    strokeColor: '#FF0000',
    strokeWeight: 3
  });
  directionsDisplay.setMap(map);
  calcRoute();
}

function calcRoute() {

  var start = document.getElementById("start").value;
  var end = document.getElementById("end").value;
  var travelMode = google.maps.DirectionsTravelMode.DRIVING

  var request = {
    origin: start,
    destination: end,
    travelMode: travelMode
  };
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      polyline.setPath([]);
      var bounds = new google.maps.LatLngBounds();
      startLocation = new Object();
      endLocation = new Object();
      directionsDisplay.setDirections(response);
      var route = response.routes[0];
      var summaryPanel = document.getElementById("directions_panel");
      summaryPanel.innerHTML = "";

      // For each route, display summary information.
      var path = response.routes[0].overview_path;
      var legs = response.routes[0].legs;
      for (i = 0; i < legs.length; i++) {
        if (i == 0) {
          startLocation.latlng = legs[i].start_location;
          startLocation.address = legs[i].start_address;
        }
        endLocation.latlng = legs[i].end_location;
        endLocation.address = legs[i].end_address;
        var steps = legs[i].steps;
        for (j = 0; j < steps.length; j++) {
          var nextSegment = steps[j].path;
          for (k = 0; k < nextSegment.length; k++) {
            polyline.getPath().push(nextSegment[k]);
            bounds.extend(nextSegment[k]);
          }
        }
      }

      polyline.setMap(map);

      computeTotalDistance(response);
      putMarkerOnRoute(parseFloat(document.getElementById('distance').value));
    } else {
      alert("directions response " + status);
    }
  });
}

var totalDist = 0;
var totalTime = 0;

function computeTotalDistance(result) {
  totalDist = 0;
  totalTime = 0;
  var myroute = result.routes[0];
  for (i = 0; i < myroute.legs.length; i++) {
    totalDist += myroute.legs[i].distance.value;
    totalTime += myroute.legs[i].duration.value;
  }
  totalDist = totalDist / 1000.
  document.getElementById("total").innerHTML = "total distance is: " + totalDist + " km<br>total time is: " + (totalTime / 60).toFixed(2) + " minutes<br>average speed is: " + (totalDist / (totalTime / 3600)).toFixed(2) + " kph";
  document.getElementById("totalTime").value = (totalTime / 60.).toFixed(2);
}

function putMarkerOnRoute(distance) {
  if (distance > totalDist)
    distance = totalDist;
  time = distance / totalDist * totalTime / 60;
  if (!marker) {
    marker = createMarker(polyline.GetPointAtDistance(distance * 1000), "distance: " + distance, "marker");
  } else {
    marker.setPosition(polyline.GetPointAtDistance(distance * 1000));
    marker.setTitle("time:" + time.toFixed(2));
    marker.contentString = "<b>time: " + time.toFixed(2) + "</b><br>distance: " + (distance).toFixed(2) + " km<br>marker";
    google.maps.event.trigger(marker, "click");
  }
}
google.maps.event.addDomListener(window, 'load', initialize);
// from v3_epoly.js
// === A method which returns a GLatLng of a point a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polyline.prototype.GetPointAtDistance = function(metres) {
  // some awkward special cases
  if (metres == 0) return this.getPath().getAt(0);
  if (metres < 0) return null;
  if (this.getPath().getLength() < 2) return null;
  var dist = 0;
  var olddist = 0;
  for (var i = 1;
    (i < this.getPath().getLength() && dist < metres); i++) {
    olddist = dist;
    dist += google.maps.geometry.spherical.computeDistanceBetween(this.getPath().getAt(i), this.getPath().getAt(i - 1));
  }
  if (dist < metres) {
    return null;
  }
  var p1 = this.getPath().getAt(i - 2);
  var p2 = this.getPath().getAt(i - 1);
  var m = (metres - olddist) / (dist - olddist);
  return new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m);
}
html {
  height: 100%
}

body {
  height: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry&v=weekly"></script>
<div id="tools">
  start:
  <input type="text" name="start" id="start" value="Hyderabad" /> end:
  <input type="text" name="end" id="end" value="Bangalore" />
  <input type="submit" onclick="calcRoute();" /><br /> distance:
  <input type="text" name="distance" id="distance" value="100" />
  <input type="submit" onclick="putMarkerOnRoute(parseFloat(document.getElementById('distance').value));" /> &nbsp;total time:<input type="text" name="totalTime" id="totalTime" value="0" />
</div>
<div id="map_canvas" style="float:left;width:70%;height:80%;"></div>
<div id="control_panel" style="float:right;width:30%;text-align:left;padding-top:20px">
  <div id="directions_panel" style="margin:20px;background-color:#FFEE77;"></div>
  <div id="total"></div>
geocodezip
  • 158,664
  • 13
  • 220
  • 245
  • Though I suppose this does not take into account variable speed limits that Google presumably will include in their calculation of duration of travel over a route that traverses several highways / roads – Adnan Jan 21 '21 at 21:59
  • No, it is just a straight proportion. You can make an additional request to the directions service to get a better estimate. – geocodezip Jan 21 '21 at 22:29