OSMnx中添加自定义节点后路由返回None的问题排查
自定义节点在OSMnx路径规划中返回None的问题解决
你遇到的问题核心是:仅添加孤立节点到路网中,该节点没有与任何现有边连接,导致没有可达路径,因此shortest_path返回None。要实现自定义节点的路径规划,必须将节点接入现有路网,而不是单纯添加孤立节点。
错误原因分析
你只执行了G.add_node(test,x=l1,y=l2),这个节点是完全孤立的,和路网中的其他节点没有任何边连接。路径规划算法找不到从这个节点到目标节点的路径,自然返回None。
解决步骤与代码实现
要让自定义节点能参与路径规划,需要将它插入到路网的某条边上,拆分原边为两段,同时维护边的属性(如长度)。以下是完整的修正代码:
import geopandas as gpd import networkx as nx import osmnx as ox import numpy as np import matplotlib.pyplot as plt from shapely.geometry import Point, LineString # 加载本地OSM路网(有向图) G = ox.graph.graph_from_xml('map_3.osm', bidirectional=False, simplify=True, retain_all=False) # 自定义节点的经纬度坐标 custom_lon = 8.3906217 custom_lat = 48.9829172 custom_node_id = 10000001 # 自定义节点ID,确保不与现有节点ID重复 # 1. 找到自定义节点最近的路网边(而非最近节点) nearest_edge = ox.distance.nearest_edges(G, custom_lon, custom_lat) u, v, edge_key = nearest_edge # 2. 获取原边的属性与几何信息 original_edge = G.get_edge_data(u, v, edge_key) original_geom = original_edge['geometry'] # 3. 创建自定义节点的几何对象 custom_point = Point(custom_lon, custom_lat) # 4. 获取原边两端节点的坐标 u_point = Point(G.nodes[u]['x'], G.nodes[u]['y']) v_point = Point(G.nodes[v]['x'], G.nodes[v]['y']) # 5. 计算拆分后两段新边的长度(注意:如果是经纬度坐标系,距离单位是度数;投影坐标系则是米) length_u_to_custom = u_point.distance(custom_point) length_custom_to_v = custom_point.distance(v_point) # 6. 添加自定义节点到图中 G.add_node( custom_node_id, x=custom_lon, y=custom_lat, street_count=0 # 与其他节点保持一致的属性,可根据需求调整 ) # 7. 删除原边,添加两条拆分后的新边 G.remove_edge(u, v, edge_key) # 添加原起点到自定义节点的边,复制原边属性并更新长度与几何 edge_attrs_u = original_edge.copy() edge_attrs_u['length'] = length_u_to_custom edge_attrs_u['geometry'] = LineString([u_point, custom_point]) G.add_edge(u, custom_node_id, **edge_attrs_u) # 添加自定义节点到原终点的边,同样更新属性 edge_attrs_v = original_edge.copy() edge_attrs_v['length'] = length_custom_to_v edge_attrs_v['geometry'] = LineString([custom_point, v_point]) G.add_edge(custom_node_id, v, **edge_attrs_v) # 8. 使用自定义节点进行路径规划 origin_node1 = custom_node_id destination_node = ox.distance.nearest_nodes(G, 8.390791842821093, 48.98715746773447) route = ox.distance.shortest_path(G, origin_node1, destination_node, weight='length') # 绘图验证路径 bbox = ox.utils_geo.bbox_from_point(point=(48.985338, 8.393094), dist=700) fig, ax = ox.plot_graph_route( G, route, route_color='r', bbox=bbox, route_linewidth=6, route_alpha=0.5, orig_dest_size=100, node_size=0, bgcolor='k' ) plt.show()
关键注意事项
- 坐标系一致性:确保自定义节点的坐标与路网坐标系一致(如果路网是投影坐标系,需先将经纬度转换为对应投影坐标)
- 路网方向性:由于你创建的是有向图(
bidirectional=False),添加新边时要保持与原边一致的方向,否则可能出现单向不可达的情况 - 边属性维护:必须更新新边的
length属性,否则路径规划时weight='length'无法正常工作 - 节点ID唯一性:自定义节点ID要避免与现有节点ID重复,防止覆盖原有节点
内容的提问来源于stack exchange,提问作者Sanketh J
相关产品推荐
相关产品推荐

