How to add markers on Google Maps polylines based on distance along the line?

google maps rectangle
google maps polygon area
google maps marker
google maps directionsrenderer
google maps javascript api
polyline google maps android
google maps draw line between markers
google maps polyline getpath

I am trying to create a Google Map where the user can plot the route he walked/ran/bicycled and see how long he ran. The GPolyline class with it’s getLength() method is very helpful in this regard (at least for Google Maps API V2), but I wanted to add markers based on distance, for example a marker for 1 km, 5 km, 10 km, etc., but it seems that there is no obvious way to find a point on a polyline based on how far along the line it is. Any suggestions?

Complex Polylines | Maps JavaScript API, Distance Matrix API Google Maps Platform Click two or more points on the map to draw polylines. You can experiment with this code in JSFiddle by clicking the <> icon in the This example creates an interactive map which constructs a polyline based on Add a new marker at the new plotted point on the polyline. I am trying to create a Google Map where the user can plot the route he walked/ran/bicycled and see how long he ran. The GPolyline class with it’s getLength() method is very helpful in this regard

I found out why I had the inexactitude. Actually in V3 of GMap, we don't have the function "getLength" anymore that return the length in Km or Meters of the polyLine.

here's the prototypes for the required function - hope this helps any further:

google.maps.Polygon.prototype.Distance = function() {
   var dist = 0;
   for (var i=1; i < this.getPath().getLength(); i++) {
      dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i-1));
   }
   return dist;
}

google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
    //var R = 6371; // km (change this constant to get miles)
    var R = 6378100; // meters
    var lat1 = this.lat();
    var lon1 = this.lng();
    var lat2 = newLatLng.lat();
    var lon2 = newLatLng.lng();
    var dLat = (lat2-lat1) * Math.PI / 180;
    var dLon = (lon2-lon1) * Math.PI / 180;
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
      Math.cos(lat1 * Math.PI / 180 ) * Math.cos(lat2 * Math.PI / 180 ) *
      Math.sin(dLon/2) * Math.sin(dLon/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;
    return d;
}

source

Simple Polylines | Maps JavaScript API, Distance Matrix API Marker Animations · Marker Animations With setTimeout() · Info Windows This example creates a two-pixel-wide red polyline that shows the path of the first You can experiment with this code in JSFiddle by clicking the <> icon in the Always set the map height explicitly to define the size of the div Add a polyline to draw a line on the map. A Polyline is a series of connected line segments. Polylines are useful to represent routes, paths, or other connections between locations on the map. Create a PolylineOptions object and add points to it.

Possibly the best approach would be to calculate where these points are.

As a basic algorithm you could iterate over all the points in the Polyline, and calculate the cumulative distance - if the next segment puts you over your distance, you can interpolate the point where the distance has been reached - then simply add a point of interest to your map for that.

Calculating distance with the Maps Javascript API, How to calculate distances on a map with the Maps JavaScript API are relatively close to each other, and even roughly how far a place is based on the map's scale. To visualize the calculation, we can draw a Polyline between the two markers. Add the following lines after the markers in the JavaScript:. How to create a custom Google Map with Route Planner and Location Markers - [ Google Maps Tutorial ] - Duration: 19:44. DCP Web Designers 217,476 views

I have used Martin Zeitler method to work with Google Map V3 and its working fine.

 function init() {
       var mapOptions = {
            zoom: 15,
            center: new google.maps.LatLng(-6.208437004433984, 106.84543132781982),
            suppressInfoWindows: true,
                     };

        // Get all html elements for map
        var mapElement = document.getElementById('map1');

        // Create the Google Map using elements
        map = new google.maps.Map(mapElement, mapOptions);

        var nextMarkerAt = 0;     // Counter for the marker checkpoints.
        var nextPoint = null;     // The point where to place the next marker.


        while (true) {

            var routePoints = [ new google.maps.LatLng(47.656, -122.360),
                                new google.maps.LatLng(47.656, -122.343),
                                new google.maps.LatLng(47.690, -122.310),
                                new google.maps.LatLng(47.690, -122.270)];

                nextPoint = moveAlongPath(routePoints, nextMarkerAt);

            if (nextPoint) {
              //Adding marker from localhost
                MarkerIcon = "http://192.168.1.1/star.png";
                var marker = new google.maps.Marker
                    ({position: nextPoint,
                        map: map,
                        icon: MarkerIcon
                    });
                // Add +1000 meters for the next checkpoint.
                nextMarkerAt +=1000;

            }
            else {
                // moveAlongPath returned null, so there are no more check points.
                break;
            }
        }
 }


   Number.prototype.toRad = function () {
        return this * Math.PI / 180;
    }

    Number.prototype.toDeg = function () {
        return this * 180 / Math.PI;
    }

    function moveAlongPath(point, distance, index) {
        index = index || 0;  // Set index to 0 by default.

        var routePoints = [];

        for (var i = 0; i < point.length; i++) {
            routePoints.push(point[i]);
        }

        if (index < routePoints.length) {
            // There is still at least one point further from this point.

            // Construct a GPolyline to use the getLength() method.
            var polyline = new google.maps.Polyline({
                path: [routePoints[index], routePoints[index + 1]],
                strokeColor: '#FF0000',
                strokeOpacity: 0.8,
                strokeWeight: 2,
                fillColor: '#FF0000',
                fillOpacity: 0.35
            });

            // Get the distance from this point to the next point in the polyline.
            var distanceToNextPoint = polyline.Distance();

            if (distance <= distanceToNextPoint) {
                // distanceToNextPoint is within this point and the next.
                // Return the destination point with moveTowards().
                return moveTowards(routePoints, distance,index);
            }
            else {
                // The destination is further from the next point. Subtract
                // distanceToNextPoint from distance and continue recursively.
                return moveAlongPath(routePoints,
                    distance - distanceToNextPoint,
                    index + 1);
            }
        }
        else {
            // There are no further points. The distance exceeds the length
            // of the full path. Return null.
            return null;
        }
    }

    function moveTowards(point, distance,index) {

        var lat1 = point[index].lat.toRad();
        var lon1 = point[index].lng.toRad();
        var lat2 = point[index+1].lat.toRad();
        var lon2 = point[index+1].lng.toRad();
        var dLon = (point[index + 1].lng - point[index].lng).toRad();

        // Find the bearing from this point to the next.
        var brng = Math.atan2(Math.sin(dLon) * Math.cos(lat2),
            Math.cos(lat1) * Math.sin(lat2) -
            Math.sin(lat1) * Math.cos(lat2) *
            Math.cos(dLon));

        var angDist = distance / 6371000;  // Earth's radius.

        // Calculate the destination point, given the source and bearing.
        lat2 = Math.asin(Math.sin(lat1) * Math.cos(angDist) +
            Math.cos(lat1) * Math.sin(angDist) *
            Math.cos(brng));

        lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(angDist) *
            Math.cos(lat1),
            Math.cos(angDist) - Math.sin(lat1) *
            Math.sin(lat2));

        if (isNaN(lat2) || isNaN(lon2)) return null;



        return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());
    }

    google.maps.Polyline.prototype.Distance = function () {
        var dist = 0;
        for (var i = 1; i < this.getPath().getLength(); i++) {
            dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1));
        }
        return dist;
    }

    google.maps.LatLng.prototype.distanceFrom = function (newLatLng) {
        //var R = 6371; // km (change this constant to get miles)
        var R = 6378100; // meters
        var lat1 = this.lat();
        var lon1 = this.lng();
        var lat2 = newLatLng.lat();
        var lon2 = newLatLng.lng();
        var dLat = (lat2 - lat1) * Math.PI / 180;
        var dLon = (lon2 - lon1) * Math.PI / 180;
        var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
            Math.sin(dLon / 2) * Math.sin(dLon / 2);
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        var d = R * c;
        return d;
    }

Moving a point along google map Polyline, Based on the velocity of the car and delta time, I calculated the car has moved away from point A towards B by a distance D in meters. If I know the  As a basic algorithm you could iterate over all the points in the Polyline, and calculate the cumulative distance - if the next segment puts you over your distance, you can interpolate the point where the distance has been reached - then simply add a point of interest to your map for that.

I wanted to port Daniel Vassalo's answer to iOS, but it wasn't worked properly and some markers were misplaced until I changed

var dLon = (point.lng() - this.lng()).toRad();

to

var dLon = point.lng().toRad() - this.lng().toRad();

So if anyone having a trouble to figure out why are the markers are misplaced, try this and maybe it will help.

Creating a Polyline Using Geolocation and the Google Maps API, In Getting Directions Using the Google Maps API, I explained how to create a is google.maps.Polyline . It draws a line that connects several points, using This is very easy because you simply need to create a new Polyline object The number will be once positive and once negative using based on the  Long click the Google Map to clear all the existing polylines and markers in the Google Map. This application is developed in Eclipse 4.2.1 with ADT plugin ( 21.1.0 ) and Android SDK ( 21.1.0 ) and is tested in a real Android Phone with Android ( 2.3.6 ).

Google Maps JavaScript API Example, The marker wil snap to the polyline at all times. /** * Snap marker to closest point on a line. * * Based on Distance to line example by * Marcelo, maps.forum.nu and added distance along line to nearest point calculation * * * Usage: * * Create​  Creating a Polyline Using Geolocation and the Google Maps API In Getting Directions Using the Google Maps API , I explained how to create a service that lets a user find a route from one address

Google Maps Overlays, Add the marker to the map by using the setMap() method: A Polyline is a line that is drawn through a series of coordinates in an ordered sequence. A polyline​  Simple Polylines This example creates a two-pixel-wide red polyline that shows the path of the first trans-Pacific flight between Oakland, CA, and Brisbane, Australia. Read the documentation .

Drawing Route Lines on Google Maps Between Two Locations in , Note: This post assumes you already have the maps set up in your lines on a Google Map (thanks to the Flutter Polyline Points Package!) If you wish to manage a set of markers, you should create an array to hold the markers. Using this array, you can then call setMap () on each marker in the array in turn when you need to remove the markers. You can delete the markers by removing them from the map and then setting the array's length to 0,

Comments
  • I am using Google Map Api V3, your formula seems to be good, but when I zoom to the road level, I can see a distance between the line drawn by google and my marker. Is there any reason why it's like that?
  • @Nordes: Does this happen with the example above? I tried to zoom in to the maximum zoom level, and the markers appear to be on the line. Screenshot: img408.imageshack.us/img408/8687/gmapnospace.png
  • I will try with all your code. Actually, I am only using the "haversine" formula that you've made in JS. Maybe I did a miscalculation somewhere. I will get back to you once I try with your code.
  • I found out why I had the inexactitude. Actually in V3 of GMap, we don't have the function "getLength" anymore that return the length in Km or Meters of the polyLine. Also, if we stay with small length of line, it seems to be correct, but when we do a big line (200km diagonally), we can see that we have some space between the line and the markers. This is because of the Haversine formula. The formula use an "approximation" of the earth radius (6731 km).
  • @Nordes: Oh yes, that's it. I think the getLength() function also assumes a spherical earth, so the same should happen in the v2 demo with larger distances. Assuming a spherical earth makes the math much simpler.
  • Yeah, that should be workable – I was just hoping there was some sort of sneaky way to make the API to do it :)
  • @mikl I may be a masochist saying this, but I reckon it's more fun to work out solutions like this, where there isn't an obvious API method