是否可以在OSMnx中将坐标拟合到街道? [英] Is it possible to fit a coordinate to a street in OSMnx?

查看:209
本文介绍了是否可以在OSMnx中将坐标拟合到街道?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

OSMnx提供了解决方案来计算两个节点之间的最短路径,但是我想对街道上的点也是如此(我从车辆记录了GPS坐标).我知道还有一种获取最接近节点的方法,但是我的这个问题有两个问题.

OSMnx provides solution to calculate the shortest path between two nodes, but I would like to the same with points on streets (I have GPS coordinates recorded from vehicles). I know there is also a method to get the closest node, but I have two question for this problem of mine.

i)计算最近的节点时,是否也考虑了该点的街道? (我认为不是) ii)如果要实现这样的功能,我想知道如何将一条街道(边缘)表示为一条曲线(也许是贝塞尔曲线).是否可以获取边缘的曲线(或曲线方程)?

i) When closest node computed is the street where the point is also taken into consideration? (I assume not) ii) If I wanted to implement something like this, I like to know how a street (edge) is represented as a curve (Bézier curve maybe?). Is it possible to get the curve (or the equation of the curve) of an edge?

我在这里问这个问题,是因为OSMnx的编写准则对此提出了要求.

I asked this question here, because the guidelines for contributing of OSMnx asked it.

推荐答案

OSMnx中的街道和节点是shapely.geometry.LineStringshapely.geometry.Point对象,因此没有曲线,只有坐标序列.您所描述的技术术语是Map Matching.地图匹配有多种方式,最简单的一种是几何地图匹配,您可以在其中找到最接近GPS点的几何(节点或边).使用内置的osmnx函数ox.get_nearest_node()可以轻松实现point to point地图匹配.如果您有大量密集的GPS轨道,则此方法可能会相当不错.对于point to line地图匹配,您必须使用形状函数.这种方法的问题在于它非常慢.您可以使用空间索引来加快算法的运行速度,但对于大多数用途而言,它的速度仍然不够快.请注意,在所有方法中,几何图匹配都是最不准确的.几周前,我编写了一个函数,该函数使用可以从OSMnx获得的edge GeoDataFrame和node GeoDataFrame进行简单的点到线地图匹配.我放弃了这个想法,现在我正在研究一种新算法(希望更快),该算法将在完成后在GitHub上发布.同时,这可能对您或其他人有帮助,所以我在这里发布.这是废弃代码的早期版本,没有经过充分测试和优化.试试看,让我知道它是否适合您.

Streets and node in OSMnx are shapely.geometry.LineString, and shapely.geometry.Point objects, so there is no curve, only sequence of coordinates. The technical term for what you described is Map Matching. There are different ways of map matching, the simplest one being geometric map matching in which you find nearest geometry (node or edge) to the GPS point. point to point map matching can be easily achieved using built-in osmnx function ox.get_nearest_node(). If you have a luxury of dense GPS tracks, this approach could work reasonably good. For point to line map matching you have to use shapely functions. The problem with this approach is that it is very slow. you can speed up the algorithm using spatial index, but still, it will not be fast enough for most purposes. Note that geometric map matching are least accurate among all approaches. I wrote a function a few weeks ago that does simple point to line map matching using edge GeoDataFrame and node GeoDataFrame that you can get from OSMnx. I abandoned this idea and now I am working on a new algorithm (hopefully much faster), which I will publish on GitHub upon completion. Meanwhile, this may be of some help for you or someone else, so I post it here. This is an early version of abandoned code, not tested enough and not optimized. give it a try and let me know if it works for you.

def GeoMM(traj, gdfn, gdfe):
"""
performs map matching on a given sequence of points

Parameters
----------

Returns
-------
list of tuples each containing timestamp, projected point to the line, the edge to which GPS point has been projected, the geometry of the edge))

"""

traj = pd.DataFrame(traj, columns=['timestamp', 'xy'])
traj['geom'] = traj.apply(lambda row: Point(row.xy), axis=1)
traj = gpd.GeoDataFrame(traj, geometry=traj['geom'], crs=EPSG3740)
traj.drop('geom', axis=1, inplace=True)

n_sindex = gdfn.sindex

res = []
for gps in traj.itertuples():
    tm = gps[1]
    p = gps[3]
    circle = p.buffer(150)
    possible_matches_index = list(n_sindex.intersection(circle.bounds))
    possible_matches = gdfn.iloc[possible_matches_index]
    precise_matches = possible_matches[possible_matches.intersects(circle)]
    candidate_nodes = list(precise_matches.index)

    candidate_edges = []
    for nid in candidate_nodes:
        candidate_edges.append(G.in_edges(nid))
        candidate_edges.append(G.out_edges(nid))

    candidate_edges = [item for sublist in candidate_edges for item in sublist]
    dist = []
    for edge in candidate_edges:
        # get the geometry
        ls = gdfe[(gdfe.u == edge[0]) & (gdfe.v == edge[1])].geometry
        dist.append([ls.distance(p), edge, ls])

    dist.sort()
    true_edge = dist[0][1]
    true_edge_geom = dist[0][2].item()
    pp = true_edge_geom.interpolate(true_edge_geom.project(p)) # projected point
    res.append((tm, pp, true_edge, true_edge_geom))


    return res

这篇关于是否可以在OSMnx中将坐标拟合到街道?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆