You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用OSMnx绘制小范围Bounding Box时触发ValueError求助

OSMnx+Matplotlib小范围边界框绘图报错解决

问题现象

使用OSMnx结合Matplotlib绘制街区级小范围地理数据时,触发ValueError: aspect must be finite and positive,但切换到较大范围边界框时程序能正常运行。需求是生成包含道路、建筑、水体和铁路轨道的PNG图像。

报错原因定位

从报错堆栈可追踪到核心问题:

  1. 调用ox.plot_footprints()时,若传入的features GeoDataFrame为空(比如当前小边界范围内没有匹配的水体/道路/铁路要素),gdf.total_bounds会返回全NaN的数组
  2. 基于NaN值计算y_coord后,1 / np.cos(y_coord * np.pi / 180)得到非有限值,触发Matplotlib设置轴比例的参数校验错误

修复方案

  1. 手动初始化Matplotlib画布和轴,避免依赖ox.plot_footprints()创建绘图环境
  2. 对每个获取的要素GeoDataFrame做非空检查,仅当存在有效要素时执行绘图
  3. 提前计算并设置正确的轴比例,确保小范围边界框也能正常渲染

修复后完整代码

import osmnx as ox
import matplotlib.pyplot as plt
import geopandas as gpd
import pandas as pd
import os
import numpy as np

def plot_features_bbox(title="", include_water=True, include_roads=True, include_railways=True, include_buildings=True):
    # 边界框坐标
    north = 50.954088
    south = 50.942151
    west = 6.913769
    east = 6.927888
    
    dpi = 400
    figsize = (80, 30)
    
    # 手动初始化画布和轴
    fig, ax = plt.subplots(figsize=figsize, dpi=dpi)
    ax.set_facecolor("#FBFBEF")
    
    # 设置轴范围
    ax.set_xlim(west, east)
    ax.set_ylim(south, north)
    
    # 计算并设置正确的轴比例
    y_coord = np.mean([south, north])
    ax.set_aspect(1 / np.cos(y_coord * np.pi / 180))

    # 颜色和线宽配置
    water_color = '#5882FA'
    road_color = '#688A08'
    railway_color = '#848484'
    building_color = '#FE9A2E'
    road_linewidth = 4.8
    railway_linewidth = 2.0

    # 绘制水体
    if include_water:
        water = ox.geometries_from_bbox(north, south, east, west, tags={'natural': 'water'})
        if not water.empty:
            water = water[water["geometry"].type.isin({"Polygon", "MultiPolygon"})]
            water.plot(ax=ax, facecolor=water_color, edgecolor=water_color)

    # 绘制道路
    G = None
    if include_roads:
        G = ox.graph_from_bbox(north, south, east, west, network_type='drive', simplify=True, truncate_by_edge=True)
        if len(G.edges) > 0:
            ox.plot_graph(G, ax=ax, node_size=0, edge_color=road_color, edge_linewidth=road_linewidth,
                          bgcolor="#FBFBEF", show=False, close=False)

    # 绘制铁路
    railways = None
    if include_railways:
        railways = ox.graph_from_bbox(north, south, east, west, network_type='all',
                                       simplify=True, retain_all=True, truncate_by_edge=True,
                                       clean_periphery=False, custom_filter='["railway"~"rail"]')
        if len(railways.edges) > 0:
            ox.plot_graph(railways, ax=ax, node_size=0, edge_color=railway_color, edge_linewidth=railway_linewidth,
                          bgcolor="#FBFBEF", show=False, close=False)

    # 绘制建筑
    if include_buildings:
        buildings_gdf = ox.geometries_from_bbox(north, south, east, west, tags={'building': True})
        if not buildings_gdf.empty:
            buildings_gdf.plot(ax=ax, facecolor=building_color, alpha=0.7, linewidth=0)

    # 添加标题文本
    ax.text(0.5, 0.1, title, fontsize=10, ha='center', va='center', transform=ax.transAxes, fontname='Courier New',
           bbox=dict(facecolor='white', edgecolor='black', boxstyle='round,pad=0.6'), color='black')

    # 添加白色边框
    ax.add_patch(plt.Rectangle((west, south), east - west, north - south, fill=False, color='white', linewidth=50))
    
    fig.tight_layout(pad=0)

    # 保存图像
    output_path = r'C:\Users\..'
    os.makedirs(output_path, exist_ok=True)
    output_filename = os.path.join(output_path, "ehrenfeld.png")
    fig.savefig(output_filename, dpi=dpi, format="png", bbox_inches='tight', facecolor=fig.get_facecolor(), transparent=False)

    plt.close(fig)
    return output_filename


output_filename = plot_features_bbox(title="Hier kann \n dein Text \n stehen.", include_water=True, include_roads=True, include_railways=True, include_buildings=True)
print(f"Die Ausgabe wurde in der Datei '{output_filename}' gespeichert.")

关键修复点

  • 手动创建画布和轴,直接设置轴范围和比例,规避空GeoDataFrame导致的计算错误
  • 对每个地理要素(水体、道路、铁路、建筑)添加非空校验,确保仅在有数据时执行绘图
  • 拆分原有的要素合并逻辑,单独处理每个要素的获取与绘制,提升代码健壮性

内容的提问来源于stack exchange,提问作者cc_schr_gis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 19:15:54