2017-08-08 47 views
3

OSMnx提供瞭解決方案來計算兩個節點之間的最短路徑,但我想要與街道上的點相同(我從車輛記錄GPS座標)。我知道還有一種方法可以獲得最近的節點,但是我對這個問題有兩個問題。 i)當計算出的最近節點是考慮到該點的街道時? (我假設不是) ii)如果我想實現這樣的事情,我想知道街道(邊緣)如何表現爲曲線(貝塞爾曲線也許?)。是否有可能獲得邊緣的曲線(或曲線方程)?是否可以在OSMnx中將座標適合街道?

我在這裏問這個問題,因爲OSMnx的貢獻的指導方針問它。

回答

2

OSMnx中的街道和節點分別是shapely.geometry.LineStringshapely.geometry.Point對象,所以沒有曲線,只有座標序列。你所描述的技術術語是Map Matching。地圖匹配有多種不同的方式,最簡單的就是幾何地圖匹配,在這種匹配中您可以找到GPS點最近的幾何圖形(節點或邊緣)。 point to point地圖匹配可以使用內置的osmnx功能ox.get_nearest_node()輕鬆實現。如果你擁有高密度的GPS軌道,這種方法可以相當好地工作。對於point to line地圖匹配,你必須使用勻稱的功能。這種方法的問題是速度很慢。您可以使用空間索引加速算法,但對於大多數目的來說,速度還不夠快。請注意,幾何圖匹配在所有方法中都是最不準確的。我幾個星期前寫了一個函數,它可以使用邊界GeoDataFrame和節點GeoDataFrame進行簡單的點到線地圖匹配,您可以從OSMnx中獲取這些邊。我放棄了這個想法,現在我正在研究一種新算法(希望速度更快),我將在完成後發佈在GitHub上。同時,這可能對你或其他人有所幫助,所以我在這裏發佈。這是遺棄代碼的早期版本,沒有經過足夠的測試和未優化。試一試,讓我知道它是否適合你。

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 
+0

期待在推送到GitHub時看到您的新算法。 – gboeing

+0

只要我有一些可觀的東西,我會讓你知道的。 –

相關問題