Python 3D切片图xy平面网格下方渲染地理底图实现方法
3D Contourf切片叠加Cartopy地理底图实现方案
核心思路:Matplotlib 3D轴原生不支持Cartopy投影的直接渲染,通过「离屏渲染底图→作为纹理贴到z轴最低处xy平面」的方式实现,不需要修改你原有3D切片的绘图逻辑。
- 提前记录你现有3D图的核心参数:xy平面对应的经纬度范围
lon_min, lon_max, lat_min, lat_max,以及z轴上低于所有contourf切片的基底高度z_base(底图就放在这个高度,避免遮挡数据)
步骤1:离屏渲染匹配范围的Cartopy底图
新建临时二维Cartopy轴绘制你需要的底图要素,关闭所有轴装饰后导出为像素数组,不需要显示这个临时画布:
import numpy as np import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature from mpl_toolkits.mplot3d import Axes3D # 替换为你自己的实际参数 lon_min, lon_max = 110, 125 lat_min, lat_max = 20, 35 z_base = -1 # 确保该值小于你所有contourf切片的最小z坐标 # 离屏渲染底图 fig_tmp = plt.figure(figsize=(8, 8), dpi=200) ax_tmp = fig_tmp.add_subplot(111, projection=ccrs.PlateCarree()) ax_tmp.set_extent([lon_min, lon_max, lat_min, lat_max], crs=ccrs.PlateCarree()) # 按需添加底图要素:海岸线、行政边界、地形等 ax_tmp.add_feature(cfeature.COASTLINE.with_scale('10m'), linewidth=0.8) ax_tmp.add_feature(cfeature.BORDERS.with_scale('10m'), linewidth=0.5) ax_tmp.axis('off') # 关闭所有刻度、边框、标签 # 提取渲染后的底图像素数组 fig_tmp.canvas.draw() bg_array = np.array(fig_tmp.canvas.buffer_rgba()) plt.close(fig_tmp) # 关闭临时画布,不弹出显示
步骤2:将底图贴到3D轴的基底平面
在你原有的3D轴对象上,生成z值恒为z_base的平面网格,将底图作为表面纹理贴到该平面,强制关闭光照、设置最低渲染层级:
# ax3d 为你原有绘制3D contourf切片的Axes3D对象 # 生成匹配底图像素维度的平面网格 lon_mesh, lat_mesh = np.meshgrid( np.linspace(lon_min, lon_max, bg_array.shape[1]), np.linspace(lat_min, lat_max, bg_array.shape[0]) ) z_mesh = np.full_like(lon_mesh, z_base) # 绘制底图平面 ax3d.plot_surface( lon_mesh, lat_mesh, z_mesh, rstride=1, cstride=1, facecolors=bg_array / 255, # 将0-255像素值转换为matplotlib支持的0-1范围 shade=False, # 关闭3D光照效果,避免底图偏暗 zorder=-1000 # 设置最低渲染层级,确保不遮挡上层数据切片 )
步骤3:绘制原有3D Contourf切片
你之前写的3D等高线切片代码不需要做任何修改,直接运行即可,所有切片会自动显示在底图上方。
常见问题排查
- 底图拉伸变形:检查临时Cartopy轴设置的
extent经纬度范围是否和3D轴xy平面的范围完全一致- 底图颜色偏暗:确认
shade=False参数已添加,默认3D表面会自动叠加光照阴影- 底图遮挡数据切片:调小
plot_surface的zorder数值,数值越小层级越低- 底图模糊:提高临时画布的
dpi参数即可,注意不要设置过高导致渲染卡顿
内容的提问来源于stack exchange,提问作者Mara
相关产品推荐
相关产品推荐

