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
相关产品推荐
相关产品推荐

