书接上回,为了增加多路径的可视化效果和坐标匹配最近点来实现最短路可视化,我们使用图形化工具matplotlib结合OSMnx的绘图功能来展示整个路网图,并特别高亮显示计算出的最短路径。
多起终点最短路路径并计算距离和时间
完整代码#运行环境 Python 3.11
import operator
import igraph as ig # 引入igraph库,用于图的复杂网络分析与可视化
import networkx as nx # 引入networkx库,用于构建与操作复杂网络
import matplotlib.pyplot as plt # 引入matplotlib.pyplot,用于数据可视化
import osmnx as ox # 引入osmnx库,用于处理OpenStreetMap数据
from osmnx import routing # 从osmnx导入路由模块
from pyproj import CRS # 引入pyproj库中的CRS类,用于处理坐标参考系统# 设置matplotlib的字体,以便支持中文显示
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体# 设置权重属性为道路长度,用于后续路径计算
weight = "length"# 定义绘制地图的地点,本例中为厦门思明区
place = "Siming Qu, Xiamen,Fujian,China"# 使用osmnx的graph_from_place函数,根据地点和驾驶网络类型创建图形G
G = ox.graph_from_place(place, network_type="drive")# 保存原始的OSM节点ID,并将G中的节点标签转换为整数,因为igraph需要整数索引
osmids = list(G.nodes)
G = nx.relabel.convert_node_labels_to_integers(G) # 节点重标记
osmid_values = {old_id: new_id for old_id, new_id in zip(G.nodes, osmids)} # 创建旧ID到新ID的映射
nx.set_node_attributes(G, osmid_values, "osmid") # 将OSM ID作为属性添加回每个节点# 在igraph中创建一个新图G_ig,复制G中的所有节点和边,并设定边的权重及节点的OSM ID属性
G_ig = ig.Graph(directed=True)
G_ig.add_vertices(G.nodes) # 添加节点
G_ig.add_edges(G.edges()) # 添加边
G_ig.vs["osmid"] = osmids # 设置节点的OSM ID属性
G_ig.es[weight] = list(nx.get_edge_attributes(G, weight).values()) # 设置边的权重属性# 使用osmnx绘制原始地图,但不显示,仅用于保存图像文件
fig, ax = ox.plot_graph(G, show=False, close=True, edge_color="#999999", edge_alpha=0.5, node_size=0, figsize=(10, 10))# 为图中的边补充缺失的速度信息,并据此计算通行时间
G = ox.add_edge_speeds(G)
G = ox.add_edge_travel_times(G)# 定义三个起始和结束节点对,用于计算最短路径
orig_dest_pairs = [(list(G)[10], list(G)[114]), (list(G)[0], list(G)[1123]), (list(G)[100], list(G)[2100])]
# 计算每一对节点间的最短路径,优化目标为通行时间
routes = [ox.shortest_path(G, orig, dest, weight="travel_time") for orig, dest in orig_dest_pairs]# 使用不同的颜色绘制这三条路径在地图上
route_colors = ["r", "y", "c"]
fig, ax = ox.plot_graph_routes(G, routes, route_colors=route_colors, route_linewidth=6, node_size=0, show=False, close=False)# 定义新函数calculate_path_stats,用于获取路径的GeoDataFrame,转换坐标系后计算总距离和通行时间
def calculate_path_stats(route, G):gdf_route = routing.route_to_gdf(G, route) # 将路径转化为GeoDataFrameproj_crs = CRS.from_epsg(3857) # 定义适合测量距离的Web Mercator坐标系gdf_route_proj = gdf_route.to_crs(proj_crs) # 将GeoDataFrame投影到新坐标系distance = gdf_route_proj.length.sum() # 计算路径总长度travel_time = gdf_route['travel_time'].sum() # 计算路径总通行时间return distance, travel_time# 应用新函数计算并打印每条路径的总距离和通行时间
stats = {f"Route {i+1}": calculate_path_stats(route, G) for i, route in enumerate(routes)}
for i, (route_name, (distance, travel_time)) in enumerate(stats.items(), start=1):print(f"{route_name}: 距离 = {distance:.2f} 米, 通行时间 = {travel_time:.2f} 秒")# 显示最终的地图,包含三条计算出的最短路径
plt.title('节点间最短路径')
plt.axis('off') # 隐藏坐标轴以聚焦于路径
plt.show()
多起终点最短路路径可视化展示;
计算出最短路距离和通行时间;
任意二点坐标最短路
路网底图和出行类型需要改的话改这里,出行方式包括'walk'、bike'、'drive';
G_nx = ox.graph_from_place("Siming Qu, Xiamen,Fujian,China", network_type="drive")
需要调整坐标的话改这个就好,坐标用的wgs84,可以用这个直接拾取新的坐标地图坐标系转换 - 在线工具 (tool.lu);
# 定义起点和终点的经纬度坐标
origin = (24.463087, 118.092150) # 起点坐标
destination = (24.477719, 118.138935) # 终点坐标
完整代码#运行环境 Python 3.11
import osmnx as ox # 导入osmnx库,用于空间网络分析和可视化
import networkx as nx # 导入networkx库,用于图论计算# 使用osmnx.graph_from_place函数,根据地点名称和道路类型创建路网图
# 参数是地点名称(厦门市思明区)和网络类型(驾驶道路)
G2 = ox.graph_from_place("Siming Qu, Xiamen,Fujian,China", network_type="drive")# 定义起点和终点的经纬度坐标
origin = (24.463087, 118.092150) # 起点坐标
destination = (24.477719, 118.138935) # 终点坐标# 使用ox.distance.nearest_nodes函数,找到离起点和终点最近的路网图中的节点
# 注意:经纬度顺序在函数调用中是(y, x),即先经度后纬度,与中国常用的坐标表示相反
origin_node = ox.distance.nearest_nodes(G2, origin[1], origin[0]) # 起点最近节点
destination_node = ox.distance.nearest_nodes(G2, destination[1], destination[0]) # 终点最近节点# 计算路网图中从起点节点到终点节点的最短路径
route = ox.shortest_path(G2, origin_node, destination_node)# 使用osmnx.plot_graph_route函数绘制路网图,并突出显示计算出的最短路径
# 参数包括路网图G2、最短路径route、路径的颜色、节点的大小(设置为0以不显示节点)
fig, ax = ox.plot_graph_route(G2, route, route_color="c", node_size=0)
二点坐标最短路结果如下图所示;
文章仅用于分享个人学习成果与个人存档之用,分享知识,如有侵权,请联系作者进行删除。所有信息均基于作者的个人理解和经验,不代表任何官方立场或权威解读。