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

如何向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的节点、边操作工具,将自定义点作为新节点插入图中,并连接到现有路网,步骤如下:

  1. 获取自定义点的最近边
    先找到每个点距离最近的现有路网边,用于后续连接新节点:

    # 获取起点、终点对应的最近边
    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])
    
  2. 添加自定义节点到图中
    给新节点分配唯一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)
    
  3. 拆分原边并连接新节点
    将自定义节点插入到最近边的位置,拆分原边为两段,保证路网连通性:

    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)
    
  4. 直接使用新节点计算路径
    现在可以直接用新增的节点调用最短路径方法,无需再通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:57:12