如何对OSMNX返回的Edges GeoDataFrame中LineString几何要素排序
问题:按顺序合并OSMNX道路边为连续LineString
场景与问题
通过OSMNX获取特定道路的边GeoDataFrame后,直接合并为MultiLineString再用folium绘图时出现混乱,核心原因是edges中的LineString顺序无序,导致拼接时连接逻辑随机。
原始获取数据代码:
import osmnx as ox # 获取特定道路的图 cf = '["highway"!~"motorway"]["ref"~"TF-563"]' G = ox.graph_from_place('Tenerife, Spain', network_type='walk', simplify=False, custom_filter=cf) # 添加长度权重 G = ox.distance.add_edge_lengths(G) # 获取图的节点和边 nodes, edges = ox.convert.graph_to_gdfs(G, nodes=True)
解决方案:利用图的节点连接关系排序边
OSMNX的图结构中,每条边都包含起点(u)和终点(v)字段,我们可以通过节点的连通关系,将边按道路的实际走向排序,再合并为连续的LineString:
import networkx as nx from shapely.ops import linemerge # 找到道路的端点(度数为1的节点,适用于非环状道路) start_node = [n for n in G.nodes if G.degree(n) == 1][0] # 获取从端点出发的最长路径,对应整条道路的节点顺序 path = nx.dag_longest_path(G.reverse(), source=start_node) # 根据路径节点对匹配并排序边的几何要素 ordered_geoms = [] for u, v in zip(path[:-1], path[1:]): # 优先匹配u->v方向的边 edge_mask = (edges['u'] == u) & (edges['v'] == v) if edge_mask.any(): geom = edges.loc[edge_mask, 'geometry'].iloc[0] else: # 若为反向边,匹配后反转坐标保证走向一致 edge_mask = (edges['u'] == v) & (edges['v'] == u) geom = edges.loc[edge_mask, 'geometry'].iloc[0].reverse() ordered_geoms.append(geom) # 合并排序后的LineString为连续的单条线 merged_line = linemerge(ordered_geoms)
用folium绘制连续道路
使用合并后的LineString绘图,即可得到和edges.plot()一致的连续效果:
import folium m = folium.Map(location=[28.105040, -16.610664], zoom_start=15) # 转换坐标为folium需要的(lat, lon)格式 coords = [(coord[1], coord[0]) for coord in merged_line.coords] folium.PolyLine(coords, color="blue").add_to(m) m
注意事项
- 若道路是环状(无度数为1的节点),可随机选择一个节点作为起点,调整路径获取逻辑
shapely.ops.linemerge会自动处理相邻LineString的衔接,比手动拼接坐标更可靠
内容的提问来源于stack exchange,提问作者Ellio
相关产品推荐
相关产品推荐

