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

NetworkX如何按条件合并边以简化OSM路网并保留边属性

NetworkX路网简化:合并度数为2的过渡节点实现方案

实现思路

  • 第一步:筛选所有度数≠2的节点作为保留节点,这类节点属于路网的端点或分叉点,具备拓扑意义;度数为2的节点仅用于定义边的曲线形态,可合并消去
  • 第二步:遍历每个保留节点作为起点,沿着过渡节点延伸路径,直到遇到下一个保留节点作为终点,形成完整的可合并边链
  • 第三步:按规则聚合边链的属性:
    • speed_kph、slope取边链中所有边对应属性的平均值
    • geometry调用shapely.ops.linemerge合并所有LineString为完整线串
    • highway属性取边链的公共值(OSM同一条连续道路类型一致)
  • 第四步:将所有保留节点和聚合后的边加入新图,完成路网简化

完整实现代码

import networkx as nx
import numpy as np
from shapely.ops import linemerge

def simplify_road_network(G):
    # 筛选需要保留的节点(端点/分叉点,度数不等于2)
    keep_nodes = [n for n in G.nodes if G.degree(n) != 2]
    # 记录已处理的边,避免重复计算
    processed_edges = set()
    new_G = nx.Graph()
    # 先添加所有保留节点
    new_G.add_nodes_from(keep_nodes)
    
    # 遍历每个保留节点,寻找可合并的边链
    for start_node in keep_nodes:
        for neighbor in G.neighbors(start_node):
            # 跳过已经处理过的边对
            if (start_node, neighbor) in processed_edges or (neighbor, start_node) in processed_edges:
                continue
            # 初始化边链存储
            path_edges = []
            current_node = neighbor
            prev_node = start_node
            
            # 沿着路径延伸直到遇到下一个保留节点
            while True:
                # 存储当前边的属性
                edge_data = G.get_edge_data(prev_node, current_node)
                path_edges.append(edge_data)
                # 标记边为已处理
                processed_edges.add((prev_node, current_node))
                # 遇到保留节点则终止延伸
                if current_node in keep_nodes:
                    end_node = current_node
                    break
                # 度数为2的节点只有两个邻居,排除上一个节点即为下一个节点
                next_nodes = list(nx.neighbors(G, current_node))
                next_node = next_nodes[0] if next_nodes[0] != prev_node else next_nodes[1]
                prev_node, current_node = current_node, next_node
            
            # 聚合边链属性
            merged_attr = {}
            merged_attr['highway'] = path_edges[0]['highway']
            merged_attr['speed_kph'] = np.mean([e['speed_kph'] for e in path_edges])
            merged_attr['slope'] = np.mean([e['slope'] for e in path_edges])
            merged_attr['geometry'] = linemerge([e['geometry'] for e in path_edges])
            
            # 把聚合后的边加入新图
            new_G.add_edge(start_node, end_node, **merged_attr)
    return new_G

测试调用

使用你提供的示例路网测试,输出结果和你预期的简化路网完全一致:

# 此处省略你示例中G的构造代码,直接调用函数即可
simplified_G = simplify_road_network(G)

# 验证结果
print("保留节点:", list(simplified_G.nodes))
print("边数量:", simplified_G.number_of_edges())

注意事项

  • 若你的路网中存在不同highway类型的路段连续通过度数为2的节点的情况,可以在聚合前加属性一致性校验,避免错误合并不同类型道路
  • 若存在全为度数2节点的环形路径,可以额外加逻辑单独处理这类特殊场景

内容的提问来源于stack exchange,提问作者Laurent

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 04:45:08