如何判断Shapely点是否属于NetworkX生成的亚琛步行最短路径
问题
我需要判断一个Shapely Point是否属于通过NetworkX的shortest_path()函数获取的德国亚琛市步行最短路径。路径起点为Node 7192074686,终点为Node 32885719。2022年,在Jülicher Straße / Lombardenstraße / Dennewartstraße的人行横道(POINT (10.77901 53.90290),WSG84坐标系)发生一起事故。
当前我的思路是查找该点的最近节点,再计算其与nx.shortest_path()返回的路径中各节点的距离,但由于节点并非完全匹配,需要设置阈值,这带来两个问题:
- a) 阈值该如何设定?这取决于网络中节点的密度;
- b) 路径中的多个节点可能对应同一事故点。
现有获取网络并计算最短路径的代码:
import networkx as nx import osmnx as ox # 获取原始路网 network = ox.graph_from_place("Aachen, Germany", network_type="walk") # 设置起点和终点节点 start_node = 7192074686 end_node = 32885719 # 计算最短路径 path_nodes = nx.shortest_path(G=network, source=start_node, end=end_node, weight="length")
解决方案
核心思路:直接检查点是否在路径的道路边线上
比起匹配节点,直接判断事故点是否落在路径的道路边线(而非节点)上更贴合实际场景——事故发生在人行横道,属于道路路段,不一定正好对应路网节点。以下是具体实现步骤:
1. 提取路径对应的道路边线几何
先将路径节点列表转换为路径包含的边,再提取每条边的Shapely几何对象:
import shapely.geometry as sg # 从路径节点生成连续的边对 path_edges = list(zip(path_nodes[:-1], path_nodes[1:])) # 提取每条边的几何并转为Shapely LineString path_line_strings = [] for u, v in path_edges: # 兼容OSMnx路网的双向边情况 if (u, v) in network.edges: edge_data = network.edges[u, v, 0] else: edge_data = network.edges[v, u, 0] geom = sg.shape(edge_data['geometry']) path_line_strings.append(geom)
2. 带缓冲阈值判断点是否在路径上
考虑到GPS数据存在误差,我们可以给道路边线加一个小缓冲(根据精度调整),再判断事故点是否在缓冲区内:
# 定义事故点(WSG84坐标系) accident_point = sg.Point(10.77901, 53.90290) # 转换为UTM坐标系(解决经纬度无法直接用米做缓冲的问题) utm_crs = ox.utils_geo.project_geometry(accident_point, crs="EPSG:4326").crs accident_point_utm = accident_point.transform(utm_crs) path_line_strings_utm = [line.transform(utm_crs) for line in path_line_strings] # 设置缓冲距离(民用GPS精度一般1-3米,这里取0.5米) buffer_distance = 0.5 # 遍历路径边线检查 is_on_path = False for line in path_line_strings_utm: if line.buffer(buffer_distance).contains(accident_point_utm): is_on_path = True print("事故点在路径上") break if not is_on_path: print("事故点不在路径上")
解决你提出的两个问题
- 阈值设定:缓冲距离根据GPS数据精度确定,民用GPS设0.5-2米即可,高精度RTK数据可缩小到0.1米,无需依赖节点密度。
- 多节点对应同一点:直接判断点与道路边线的关系,无需考虑路径节点数量,只要点在某段路径边的缓冲区内,就判定为在路径上。
高效备选方案:匹配最近边
如果路径较长,遍历所有边效率低,可先找到事故点的最近边,再检查该边是否属于路径:
# 获取事故点的最近边及距离 nearest_edge, dist_to_edge = ox.get_nearest_edge(network, accident_point, return_dist=True) nearest_u, nearest_v, _ = nearest_edge # 检查最近边是否在路径边列表中(兼容双向边) edge_in_path = ((nearest_u, nearest_v) in path_edges) or ((nearest_v, nearest_u) in path_edges) # 结合距离阈值判断 if edge_in_path and dist_to_edge < 0.5: print("事故点在路径上") else: print("事故点不在路径上")
内容的提问来源于stack exchange,提问作者user22694771
相关产品推荐
相关产品推荐

