You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 18:47:15