Question

I need to get the latitude/longitude of a position at X percentage along a straight polyline segment between two other lat/lng points.

The closest I have come so far is using the following (for 40% along the line):

google.maps.geometry.spherical.interpolate(startLatLng, endLatLng, 0.4);

This works perfectly for short distances, however for a long polyline segment the latlng returned is outside of where the polyline travels, since it's working out the shortest distance along the earth's surface instead of the shortest distance across a flat map.

Any help on this would be appreciated, hopefully I'm just missing something obvious.

Was it helpful?

Solution

There must be some proven and tested method out there to do this, but here is a way you could do it with the Maps API:

  1. Convert the lat/lng coordinates to pixels
  2. Interpolate in the pixel plane
  3. Convert back to lat/lng

This is mostly pretty straightforward; the one hassle is figuring out how to deal with lines that cross the 180 meridian or a pole.

Here's some semi-tested code that may give you a place to start:

function mercatorInterpolate( map, latLngFrom, latLngTo, fraction ) {
    // Get projected points
    var projection = map.getProjection();
    var pointFrom = projection.fromLatLngToPoint( latLngFrom );
    var pointTo = projection.fromLatLngToPoint( latLngTo );
    // Adjust for lines that cross the 180 meridian
    if( Math.abs( pointTo.x - pointFrom.x ) > 128 ) {
        if( pointTo.x > pointFrom.x )
            pointTo.x -= 256;
        else
            pointTo.x += 256;
    }
    // Calculate point between
    var x = pointFrom.x + ( pointTo.x - pointFrom.x ) * fraction;
    var y = pointFrom.y + ( pointTo.y - pointFrom.y ) * fraction;
    var pointBetween = new google.maps.Point( x, y );
    // Project back to lat/lng
    var latLngBetween = projection.fromPointToLatLng( pointBetween );
    return latLngBetween;
}

I'm not 100% sure about the part that handles lines that cross the 180 meridian, but it works OK in the few quick tests I tried.

OTHER TIPS

See this discussion in the Google Maps API v3 group

And this example from it

This suggested code takes the projection into account for the mid-point:

google.maps.event.addListener(map, 'projection_changed', function() {
  var projection = map.getProjection();
  if (!projection) return;

  // Project
  var startLatLng = startMarker.getPosition();
  var endLatLng = endMarker.getPosition();
  var startPoint = projection.fromLatLngToPoint(startLatLng);
  var endPoint = projection.fromLatLngToPoint(endLatLng);

  // Average
  var midPoint = new google.maps.Point(
      (startPoint.x + endPoint.x) / 2,
      (startPoint.y + endPoint.y) / 2);

  // Unproject
  var midLatLng = projection.fromPointToLatLng(midPoint);
  midMarker.setPosition(midLatLng);

}); 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top