如何根据沿线距离在谷歌地图折线上添加标记?
我正在尝试创建一个谷歌地图,用户可以在其中绘制他步行/跑步/骑自行车的路线,并查看他跑了多长时间。带有 getLength()
方法的 GPolyline
类在这方面非常有帮助(至少对于 Google Maps API V2),但我想根据距离添加标记,例如例如 1 公里、5 公里、10 公里等的标记,但似乎没有明显的方法可以根据折线上的距离来查找折线上的点。有什么建议吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
回答了类似的问题几个月前,关于如何在 SQL Server 2008 的服务器端解决这个问题,我使用 Google 地图 API v2。
在本示例中,我们使用一条简单的 4 点折线,总长度约为 8,800 米。下面的代码片段将定义这条折线并将其渲染在地图上:
现在,在我们采用实际算法之前,我们需要一个函数,在给定起点、终点以及沿该点行驶的距离时返回目的地点幸运的是,Chris Veness 在 计算距离,有一些方便的 JavaScript 实现,纬度/经度点之间的方位角和更多信息。
特别是,我从上述来源改编了以下两种方法来与 Google 的
GLatLng
类一起使用:这些用于通过方法
moveTowards()
扩展 Google 的GLatLng
类,当给定另一个点和距离时,该方法以米为单位,当从原始点向作为参数传递的点行进的距离时,它将沿着该线返回另一个 GLatLng 。有了这个方法,我们现在可以按如下方式解决问题:
如果点 2 的距离大于我们需要在路径上行驶的距离:
...那么目标点就在这个点和下一个点之间。只需将
moveTowards()
方法应用于当前点,并传递下一个点和要行进的距离。返回结果并中断迭代。其他:
...目标点距离迭代中的下一个点更远。我们需要从沿着路径行驶的总距离中减去这一点和下一点之间的距离。继续使用修改后的距离进行迭代。
您可能已经注意到,我们可以轻松地递归实现上述内容,而不是迭代。那么让我们这样做:
使用上面的方法,如果我们定义一个
GLatLng
点数组,并使用该点数组和一个距离调用moveAlongPath()
函数2,500 米,它将在距离第一个点 2.5 公里的路径上返回GLatLng
。因此,我们需要做的就是为路径上需要的每个检查点调用 moveAlongPath() 。如果您需要 1 公里、5 公里和 10 公里处的三个标记,您可以简单地执行以下操作:
但是请注意,如果我们请求距离总数更远的检查点,
moveAlongPath()
可能会返回null
路径的长度,因此在将返回值传递给 new GMarker() 之前检查它是明智的做法。我们可以将其整合在一起以进行全面实施。在此示例中,我们沿着前面定义的 8.8 公里路径每 1,000 米放置一个标记:
上例的屏幕截图,显示每 1,000 米一个标记:
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:
这些是所需函数的原型:
源
These are the prototypes for the required functions:
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.
我已经使用 Martin Zeitler 方法来处理 Google Map V3,并且工作正常。
I have used Martin Zeitler method to work with Google Map V3 and its working fine.
我想将 Daniel Vassalo 的答案移植到 iOS,但它无法正常工作,并且一些标记被放错位置,直到我更改
为
因此,如果有人无法弄清楚为什么标记放错了位置,请尝试一下,也许会有所帮助。
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.