NetworkX在OSM网络中存在路径却提示无最短路径的问题求助
问题
我使用NetworkX在OSM(OpenStreetMap)网络中查找最短路径时,除相邻节点外始终报错:
networkx.exception.NetworkXNoPath: No path between 208769027 and 208769047. No path found
但我确认这两个节点间存在路径——同一图文件在QGIS中可成功找到最短路径。以下是我的项目代码(需保存为GPKG格式),尝试多种NetworkX算法均无效,恳请解决。
import os os.environ['USE_PYGEOS'] = '0' import osmnx as ox import networkx as nx import fiona import shapely.geometry as geom import geopandas as gpd import traceback from data_utils import create_folder def load_osm_network(network_paramaters): print("Loading OSM network") # Retrieve the street network graph if(network_paramaters["bbox"] !=None): north, south, east, west = network_paramaters["bbox"] G = ox.graph_from_bbox(north, south, east, west, network_type=network_paramaters["network_type"], simplify=True) else: G = ox.graph_from_place(network_paramaters["place_name"], network_type=network_paramaters["network_type"], simplify=False) G = ox.project_graph(G, to_crs="EPSG:4171") print("OSM network loaded, saving into file..") # Save the graph data as a GeoPackage file create_folder("./data/osm") ox.save_graph_geopackage(G, filepath=network_paramaters["output_file"]) lyon_network_parameters = { "place_name" : "Lyon, France", "network_type" : "drive", "bbox": None, "output_file": "./data/osm/lyon_drive.gpkg" } bbox_network_parameters = { "place_name": "Lyon, France", "network_type": "walk", "bbox": (45.76091,45.74938, 4.89007,4.86426), "output_file" : "./data/osm/bbox_default_crs.gpkg" } load_osm_network(lyon_network_parameters) load_osm_network(bbox_network_parameters) def shortest_path(graph_file_path, shortest_path_file_path, origin_point, destination_point): # Load the graph data from the GeoPackage file gdf_edges = gpd.read_file(graph_file_path, layer='edges') gdf_nodes = gpd.read_file(graph_file_path, layer="nodes") gdf_edges = gdf_edges.set_index(['u', 'v', 'key']) gdf_nodes = gdf_nodes.set_index(['osmid']) G = ox.graph_from_gdfs(gdf_nodes, gdf_edges) origin_node = ox.nearest_nodes(G, X=origin_point[1], Y=origin_point[0]) destination_node = ox.nearest_nodes(G, X=destination_point[1], Y=destination_point[0]) print(origin_node) print(destination_node) print("type G : ", type(G)) try: # Calculate the shortest path astar's algorithm #shortest_path = nx.astar_path(G, origin_node, destination_node, heuristic=manhattan_distance, weight="length") # Calculate the shortest path using Dijkstra's algorithm shortest_path = nx.shortest_path(G, source=origin_node, target=destination_node, weight="length") print(type(shortest_path)) print(shortest_path) # Convert the shortest path to a LineString geometry route_edges = ox.utils_graph.get_route_edge_attributes(G, shortest_path) gdf_route_edges = gpd.GeoDataFrame(route_edges, crs=G.graph['crs'], geometry='geometry') gdf_route_edges.to_file(shortest_path_file_path, driver='GPKG') print("Shortest path found") except nx.NetworkXNoPath: traceback.print_exc() print("No path found") #create_folder("./data/osm/shortest_path/") origin_point = (45.7587161, 4.8737715) destination_point = (45.7596251,4.8743205) shortest_path("./data/osm/bbox_default_crs.gpkg", "./data/osm/shortest_path/_bbox_first_trial.gpkg", origin_point=origin_point, destination_point=destination_point)
解决方案
处理有向图限制:OSMnx默认生成有向图(DiGraph),步行场景下部分单向道路的限制会导致路径中断。可以将图转为无向图:
# 在shortest_path函数中加载图后添加 G = G.to_undirected()或者在加载网络时直接指定生成无向图,修改
ox.graph_from_bbox的参数:G = ox.graph_from_bbox(north, south, east, west, network_type=network_paramaters["network_type"], simplify=True, directed=False)修复图加载逻辑:手动读取GDF再构建图容易出现索引不匹配的问题,改用OSMnx自带的加载方法:
# 替换shortest_path函数中的图加载代码 G = ox.load_graph_geopackage(graph_file_path)检查图简化的影响:bbox网络加载时使用了
simplify=True,简化过程可能会移除关键节点/边导致连通性断裂。尝试将simplify设为False,或者后续手动简化并验证连通性:G = ox.graph_from_bbox(north, south, east, west, network_type=network_paramaters["network_type"], simplify=False) # 手动简化 G = ox.simplify_graph(G)验证节点连通性:在查找路径前先确认节点是否在同一连通分量:
# 在shortest_path函数中获取origin_node和destination_node后添加 print("节点连通性:", nx.has_path(G.to_undirected(), origin_node, destination_node)) # 查看连通分量 for component in nx.connected_components(G.to_undirected()): if origin_node in component: print("起点所在分量大小:", len(component)) print("终点在该分量中:", destination_node in component) break统一CRS设置:确保保存和加载过程中CRS属性完整传递,避免坐标偏差导致节点匹配错误。
内容的提问来源于stack exchange,提问作者Yannis Barba
相关产品推荐
相关产品推荐

