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?
I am trying to create a Google Map where the user can plot the
Share
Having answered a similar problem a couple of months ago on how to tackle this on the server-side in SQL Server 2008, I am porting the same algorithm to JavaScript using the Google Maps API v2.
For the sake of this example, let’s use a simple 4-point polyline, with a total length of circa 8,800 meters. The snippet below will define this polyline and will render it on the map:
Now before we approach the actual algorithm, we will need a function that returns the destination point when given a start point, an end point, and the distance to travel along that line, Luckily, there are a few handy JavaScript implementations by Chris Veness at Calculate distance, bearing and more between Latitude/Longitude points.
In particular I have adapted the following two methods from the above source to work with Google’s
GLatLngclass:These were used to extend Google’s
GLatLngclass with a methodmoveTowards(), which when given another point and a distance in meters, it will return anotherGLatLngalong that line when the distance is travelled from the original point towards the point passed as a parameter.Having this method, we can now tackle the problem as follows:
If the distance in point 2 is greater the distance we need to travel on the path:
…then the destination point is between this point and the next. Simply apply the
moveTowards()method to the current point, passing the next point and the distance to travel. Return the result and break the iteration.Else:
…the destination point is further in the path from the next point in the iteration. We need to subtract the distance between this point and the next point from the total distance to travel along the path. Continue through the iteration with the modified distance.
You may have noticed that we can easily implement the above recursively, instead of iteratively. So let’s do it:
With the above method, if we define an array of
GLatLngpoints, and we invoke ourmoveAlongPath()function with this array of points and with a distance of 2,500 meters, it will return aGLatLngon that path at 2.5km from the first point.Therefore all we need to do is to call
moveAlongPath()for each check point we need on the path. If you need three markers at 1km, 5km and 10km, you can simply do:Note however that
moveAlongPath()may returnnullif we request a check point further from the total length of the path, so it will be wiser to check for the return value before passing it tonew GMarker().We can put this together for the full implementation. In this example we are dropping a marker every 1,000 meters along the 8.8km path defined earlier:
Screenshot of the above example, showing a marker every 1,000 meters: