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

OSMnx中使用consolidate_intersections时如何排除含特定属性的边以保留桥梁

OSMnx中使用consolidate_intersections时如何排除含特定属性的边以保留桥梁

这个问题我之前做城市路网简化项目的时候刚好碰到过,简直感同身受——既要用足够大的阈值把那些零散的普通路口合并干净,结果短桥梁愣是被误删,调低阈值又完全达不到简化效果。给你分享两个亲测有效的方案:

方案一:拆分路网分别处理(最稳妥,无需修改源码)

核心思路就是把桥梁边和普通路网彻底分开,只对普通路网执行路口合并,最后再把桥梁边加回去,这样桥梁边完全不受合并逻辑的影响:

  1. 从原始路网中拆分出纯桥梁子图和纯非桥梁子图
    先复制原图,然后分别移除不需要的边,得到两个独立的子图:

    import osmnx as ox
    import pandas as pd
    
    # 假设你已经加载好原始路网G,比如:
    # G = ox.graph_from_place("上海市黄浦区", network_type="drive")
    
    # 提取仅包含桥梁边的子图
    G_bridges = G.copy()
    non_bridge_edges = [(u, v, k) for u, v, k, d in G.edges(keys=True, data=True) if d.get("bridge") != "yes"]
    G_bridges.remove_edges_from(non_bridge_edges)
    
    # 提取仅包含非桥梁边的子图
    G_non_bridges = G.copy()
    bridge_edges = [(u, v, k) for u, v, k, d in G.edges(keys=True, data=True) if d.get("bridge") == "yes"]
    G_non_bridges.remove_edges_from(bridge_edges)
    
  2. 对非桥梁子图执行路口合并
    这里就可以放心用你需要的大阈值,完全不用担心桥梁被合并:

    # 用你原来的阈值,比如tolerance=15米(根据你的需求调整)
    G_non_bridges_consolidated = ox.consolidate_intersections(
        G_non_bridges,
        tolerance=15,
        rebuild_graph=True,
        dead_ends=True  # 保留死胡同节点,避免桥梁端点被误删
    )
    
  3. 合并处理后的非桥梁路网和原始桥梁路网
    把两个子图转成GeoDataFrame合并,再转回图结构即可:

    # 转换为GeoDataFrame方便合并
    nodes_non_bridge, edges_non_bridge = ox.graph_to_gdfs(G_non_bridges_consolidated)
    nodes_bridge, edges_bridge = ox.graph_to_gdfs(G_bridges)
    
    # 合并节点(优先保留处理后的非桥梁节点,避免重复)
    nodes_combined = pd.concat([nodes_non_bridge, nodes_bridge]).drop_duplicates(subset="osmid", keep="first")
    # 合并所有边
    edges_combined = pd.concat([edges_non_bridge, edges_bridge])
    
    # 转回路网图
    G_final = ox.gdfs_to_graph(nodes_combined, edges_combined)
    

这个方法的好处是完全不修改OSMnx的原生逻辑,兼容性拉满,而且桥梁边100%保留原始状态。

方案二:自定义合并逻辑(进阶玩法)

如果你不想拆分路网,也可以自己封装一个带节点过滤的合并函数——核心是在OSMnx的合并逻辑中,跳过所有属于桥梁边的节点:

  1. 先给所有桥梁边的端点标记一个“保护”属性:

    # 遍历所有桥梁边,给两端节点加上protected标记
    for u, v, k, d in G.edges(keys=True, data=True):
        if d.get("bridge") == "yes":
            G.nodes[u]["protected"] = True
            G.nodes[v]["protected"] = True
    
  2. 参考OSMnx原生的consolidate_intersections函数,修改节点聚类的逻辑,在生成合并簇的时候,排除所有带有protected=True属性的节点。这样合并操作就不会碰桥梁的端点,自然也就不会合并桥梁边了。

不过这个方案需要你对OSMnx的源码有一定了解,适合需要高度自定义的场景,一般来说方案一完全够用。

小提醒

合并后可以用ox.plot_graph(G_final)检查一下,如果发现桥梁边的端点和合并后的普通路网节点不匹配,用空间匹配把桥梁端点替换成最近的合并节点就行,比如用geopandas.sjoin_nearest。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 09:57:58