如何用OSMnx正确投影GPS坐标?解决投影后节点匹配问题
OSMnx投影路网后匹配GPS点到最近节点的解决方案
问题描述
我正在用osmnx对法国安纳西(Annecy)建模,测试开发最短路径算法。为了获取正确的距离,必须使用ox.project_graph对路网图进行投影,但投影后无法找到城市边界内任意GPS点对应的最近节点。
核心疑问:有没有单独投影单个坐标点的方法?
问题根源:原始图的坐标是经纬度(WGS84,EPSG:4326),投影后的图坐标数值完全不同,但找不到单独转换GPS点坐标的方法,导致用原始经纬度去投影后的图里找最近节点时出错,得到错误的路径结果。
原始未投影图的最短路径代码(正常运行)
import osmnx as ox import networkx as nx graphe_ville = ox.graph.graph_from_bbox(45.949160, 45.868544, 6.176136, 6.071052, network_type='drive', simplify=True, truncate_by_edge=False, clean_periphery =True) graphe_ville = ox.add_edge_speeds(graphe_ville) graphe_ville = ox.add_edge_travel_times(graphe_ville) x_start, y_start = (6.148903, 45.909408) x_arrival, y_arrival = (6.127705, 45.905936) Start = ox.distance.nearest_nodes(graphe_ville, x_start, y_start) Arrival = ox.distance.nearest_nodes(graphe_ville, x_arrival, y_arrival) path = nx.dijkstra_path(graphe_ville,Start,Arrival) fig, ax = ox.plot_graph_route(graphe_ville, path, route_linewidth=4,node_size=1, figsize=(7,7), bgcolor='#FFFFFF', node_color='#111111')
运行效果:
投影后获取正确距离的代码
import osmnx as ox import networkx as nx city_graph = ox.graph.graph_from_bbox(45.949160, 45.868544, 6.176136, 6.071052, network_type='drive', simplify=True, truncate_by_edge=False, clean_periphery =True) city_graph = ox.project_graph(city_graph) # 获取正确距离 city_graph = ox.consolidate_intersections(city_graph, rebuild_graph=True, tolerance=15, dead_ends=True) # 简化节点(如环岛) city_graph = ox.add_edge_speeds(city_graph) city_graph = ox.add_edge_travel_times(city_graph) fig, ax = ox.plot_graph(city_graph, figsize=(7,7), bgcolor='#FFFFFF', node_color='#111111')
运行效果:
投影后错误计算路径的代码及问题
在上述投影代码后添加以下代码计算同两点路径,会得到错误的路径结果:
x_start, y_start = (6.148903, 45.909408) x_arrival, y_arrival = (6.127705, 45.905936) Start = ox.distance.nearest_nodes(graphe_ville, x_start, y_start) Arrival = ox.distance.nearest_nodes(graphe_ville, x_arrival, y_arrival) path = nx.dijkstra_path(graphe_ville,Start,Arrival) fig, ax = ox.plot_graph_route(graphe_ville, path, route_linewidth=4,node_size=1, figsize=(7,7), bgcolor='#FFFFFF', node_color='#111111')
错误效果:
解决方案
要解决这个问题,关键是把GPS经纬度点转换为和投影后路网一致的坐标系,具体步骤如下:
1. 获取投影坐标系信息
投影后的路网图会自带坐标系参数,通过city_graph.graph['crs']即可获取对应的pyproj.CRS对象。
2. 转换GPS点坐标到投影坐标系
使用pyproj的Transformer类,将WGS84经纬度转换为投影坐标系的坐标,再用转换后的坐标查找最近节点。完整示例代码如下:
import osmnx as ox import networkx as nx from pyproj import Transformer # 加载并投影路网 city_graph = ox.graph.graph_from_bbox(45.949160, 45.868544, 6.176136, 6.071052, network_type='drive', simplify=True, truncate_by_edge=False, clean_periphery =True) city_graph = ox.project_graph(city_graph) city_graph = ox.consolidate_intersections(city_graph, rebuild_graph=True, tolerance=15, dead_ends=True) city_graph = ox.add_edge_speeds(city_graph) city_graph = ox.add_edge_travel_times(city_graph) # 创建坐标系转换器:WGS84经纬度 -> 投影坐标系 crs_proj = city_graph.graph['crs'] crs_wgs84 = 'EPSG:4326' # GPS经纬度对应的标准坐标系 transformer = Transformer.from_crs(crs_wgs84, crs_proj, always_xy=True) # 转换目标GPS点坐标 x_start_wgs84, y_start_wgs84 = (6.148903, 45.909408) x_arrival_wgs84, y_arrival_wgs84 = (6.127705, 45.905936) x_start_proj, y_start_proj = transformer.transform(x_start_wgs84, y_start_wgs84) x_arrival_proj, y_arrival_proj = transformer.transform(x_arrival_wgs84, y_arrival_wgs84) # 查找投影路网中的最近节点 Start = ox.distance.nearest_nodes(city_graph, x_start_proj, y_start_proj) Arrival = ox.distance.nearest_nodes(city_graph, x_arrival_proj, y_arrival_proj) # 计算最短路径并绘图 path = nx.dijkstra_path(city_graph, Start, Arrival) fig, ax = ox.plot_graph_route(city_graph, path, route_linewidth=4, node_size=1, figsize=(7,7), bgcolor='#FFFFFF', node_color='#111111')
关键注意事项
- 必须设置
always_xy=True,因为OSMnx始终使用x(经度)、y(纬度)的坐标顺序,和pyproj的默认顺序一致,避免坐标错位。 - 查找最近节点时,务必使用投影后的图
city_graph,而非原始未投影的图。
内容的提问来源于stack exchange,提问作者AliStonks
相关产品推荐
相关产品推荐

