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?
相关问题
- Is there a limit to how many levels you can nest i
- How to toggle on Order in ReactJS
- void before promise syntax
- Keeping track of variable instances
- Can php detect if javascript is on or not?
here's the prototypes for the required function - hope this helps any further:
source
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.
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
GLatLng
class:These were used to extend Google's
GLatLng
class with a methodmoveTowards()
, which when given another point and a distance in meters, it will return anotherGLatLng
along 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
GLatLng
points, and we invoke ourmoveAlongPath()
function with this array of points and with a distance of 2,500 meters, it will return aGLatLng
on 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 returnnull
if 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:
I have used Martin Zeitler method to work with Google Map V3 and its working fine.
I wanted to port Daniel Vassalo's answer to iOS, but it wasn't worked properly and some markers were misplaced until I changed
to
So if anyone having a trouble to figure out why are the markers are misplaced, try this and maybe it will help.