如何向OSMnx MultiDiGraph添加起点终点以替代nearest_nodes?
问题描述
我想要绘制两个坐标点之间的步行路线,但这两个点并未精确对应图中的现有节点。我的起点和终点坐标如下:
G = ox.graph_from_place("New York, USA", network_type = "walk") origin = (40.76962427551995, -73.98081598273785) # point 1 close to central park destination = (40.76382213760314, -73.97369287403389) # point 2 close to central park origin_node = ox.nearest_nodes(G = G, X = origin[1], Y = origin[0]) destination_node = ox.nearest_nodes(G = G, X = destination[1], Y = destination[0]) route = ox.shortest_path(G, origin_node, destination_node)
请问如何添加上述origin和destination这两个点,使其无需通过nearest_nodes即可使用?需要手动提供哪些信息,具体操作方法是什么?
解决方案
需要手动提供的信息
- 自定义点的经纬度坐标(你已经有了origin和destination)
- 新节点的唯一ID(需避开现有节点ID,比如取现有最大节点ID加值)
- 可选:自定义点连接边的属性(可直接复用最近边的属性,无需手动输入)
具体操作方法
通过OSMnx的节点、边操作工具,将自定义点作为新节点插入图中,并连接到现有路网,步骤如下:
获取自定义点的最近边
先找到每个点距离最近的现有路网边,用于后续连接新节点:# 获取起点、终点对应的最近边 origin_edge = ox.distance.nearest_edges(G, X=origin[1], Y=origin[0]) dest_edge = ox.distance.nearest_edges(G, X=destination[1], Y=destination[0])添加自定义节点到图中
给新节点分配唯一ID,避免与现有节点冲突,同时录入经纬度信息:# 获取现有节点的最大ID,确保新ID唯一 max_node_id = max(G.nodes()) origin_node_new = max_node_id + 1 dest_node_new = max_node_id + 2 # 添加起点节点(x为经度,y为纬度) G.add_node(origin_node_new, x=origin[1], y=origin[0], street_count=0) # 添加终点节点 G.add_node(dest_node_new, x=destination[1], y=destination[0], street_count=0)拆分原边并连接新节点
将自定义节点插入到最近边的位置,拆分原边为两段,保证路网连通性:from geopy.distance import geodesic # 处理起点对应的边 u, v, key = origin_edge # 复制原边的属性(如道路类型、单向规则等) edge_attrs = G.edges[u, v, key] # 计算新节点到原边两端点的距离 dist_u_origin = geodesic((G.nodes[u]['y'], G.nodes[u]['x']), origin).meters dist_v_origin = geodesic((G.nodes[v]['y'], G.nodes[v]['x']), origin).meters # 删除原边,添加拆分后的新边 G.remove_edge(u, v, key) G.add_edge(u, origin_node_new, **edge_attrs, length=dist_u_origin) G.add_edge(origin_node_new, v, **edge_attrs, length=dist_v_origin) # 同理处理终点对应的边 u_dest, v_dest, key_dest = dest_edge edge_attrs_dest = G.edges[u_dest, v_dest, key_dest] dist_u_dest = geodesic((G.nodes[u_dest]['y'], G.nodes[u_dest]['x']), destination).meters dist_v_dest = geodesic((G.nodes[v_dest]['y'], G.nodes[v_dest]['x']), destination).meters G.remove_edge(u_dest, v_dest, key_dest) G.add_edge(u_dest, dest_node_new, **edge_attrs_dest, length=dist_u_dest) G.add_edge(dest_node_new, v_dest, **edge_attrs_dest, length=dist_v_dest)直接使用新节点计算路径
现在可以直接用新增的节点调用最短路径方法,无需再通过nearest_nodes转换:route = ox.shortest_path(G, origin_node_new, dest_node_new) # 可视化路径 ox.plot_graph_route(G, route, node_size=0)
注意事项
- 新节点ID必须唯一,否则会覆盖现有节点数据
- 拆分边时保留原边属性,能保证路径计算符合原有路网规则
- 若无需高精度路径,也可直接将新节点连到最近的现有节点,但路径起点/终点会偏移到现有节点位置
内容的提问来源于stack exchange,提问作者xtlc
相关产品推荐
相关产品推荐

