如何基于带经纬度的NetworkX铁路网络图生成地理示意图
印度铁路地理示意图最优实现方案
直接放弃Graphviz,采用Matplotlib + NetworkX原生接口实现即可,全程几乎不需要手动调整坐标,性能和配置灵活度完全覆盖你的需求,比Graphviz适配性高很多。
核心优势
- 你要求的plate carrée投影不需要复杂坐标转换,直接将节点经度映射为X轴值、纬度映射为Y轴值即可,完全不需要依赖布局引擎做自动排布,从根源上避免布局计算的性能损耗和位置偏差。
- 所有标签(节点标签、边标签)支持全局统一配置位置规则,不需要逐个元素手动调整坐标,4字符以内的短标签几乎不会出现严重遮挡,少量重叠可以用自动避让工具一键处理。
- 渲染性能远高于Graphviz的neato/fdp引擎,哪怕是包含数千个站点、上万条线路的全印度铁路网,渲染耗时也在秒级。
具体实现步骤
- 坐标预处理:遍历NetworkX图的所有节点,直接取每个节点存储的经纬度生成位置字典
pos,格式为{节点名称: (经度, 纬度)},不需要做其他坐标转换。 - 节点绘制:调用
nx.draw_networkx_nodes传入pos参数,设置节点样式为实心圆点即可,节点大小、颜色可以全局统一配置。 - 节点标签:调用
nx.draw_networkx_labels传入标签字典,全局设置标签相对节点的偏移量,默认放在节点右上方即可;如果需要自动避让重叠标签,引入adjustText库可以一键完成所有标签的位置微调,不需要手动修改单个标签坐标,标签自动截断为4字符长度即可满足要求。 - 边绘制:默认调用
nx.draw_networkx_edges画直线即可;如果线路密集想要更好的视觉效果,添加参数connectionstyle='arc3,rad=0.05'即可自动生成统一弧度的微弯曲线,不需要单独为每条边配置弧度。 - 边标签:调用
nx.draw_networkx_edge_labels传入线路名称字典,标签会自动放置在每条边的中点位置,字体大小全局统一配置即可,同样支持自动避让。
最小实现代码示例
import networkx as nx import matplotlib.pyplot as plt from adjustText import adjust_text # 可选依赖,用于标签自动避让 # 以下为示例逻辑,替换为你实际的铁路网络数据即可 G = nx.Graph() # 节点添加时存入经纬度属性 G.add_node("德里", lat=28.61, lon=77.21) G.add_node("孟买", lat=19.07, lon=72.87) G.add_node("金奈", lat=13.08, lon=80.27) # 边添加时存入线路名称属性 G.add_edge("德里", "孟买", line_name="德孟干线") G.add_edge("德里", "金奈", line_name="德金干线") G.add_edge("孟买", "金奈", line_name="孟金干线") # 生成plate carrée投影坐标,无额外转换 pos = {node: (attr["lon"], attr["lat"]) for node, attr in G.nodes(data=True)} plt.figure(figsize=(10, 12), dpi=100) # 绘制圆点节点 nx.draw_networkx_nodes(G, pos, node_size=35, node_color="#222222") # 绘制边,开启微弧度曲线效果 nx.draw_networkx_edges(G, pos, width=1.2, edge_color="#555555", connectionstyle="arc3,rad=0.03") # 绘制节点短标签,自动截断为4字符 node_labels = {node: node[:4] for node in G.nodes()} nx.draw_networkx_labels( G, pos, labels=node_labels, font_size=9, bbox=dict(facecolor="white", edgecolor="none", pad=0.2) ) # 绘制边标签,默认放在边中点 edge_labels = {(u, v): attr["line_name"] for u, v, attr in G.edges(data=True)} nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=7, label_pos=0.5) # 可选:开启标签自动避让,解决局部重叠问题 text_objs = [t for t in plt.gca().texts] adjust_text(text_objs, arrowprops=dict(arrowstyle="-", color="gray", lw=0.4)) plt.axis("off") plt.tight_layout() plt.show()
额外可选优化
如果需要更贴近真实地理参考,可以将印度国境线、省界等底图要素按相同的经纬度坐标垫在绘图最下层,不需要修改现有铁路和节点的绘制逻辑,也不需要额外调整坐标。
内容的提问来源于stack exchange,提问作者yofara
相关产品推荐
相关产品推荐

