如何为南极立体投影创建圆形网格线标签?
南极极地投影网格线标签圆形环绕解决方案
我使用South Polar Stereographic投影制作南极地图,已通过Cartopy生成网格线,但网格线标签未呈圆形环绕地图,希望标签能贴合该投影的圆形样式。当前使用的代码如下:
import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature import numpy as np import matplotlib.path as mpath fig = plt.figure(figsize=(12,8)) ax = plt.axes(projection=ccrs.SouthPolarStereo()) ax.set_extent([-180, 180, -90, -30], ccrs.PlateCarree()) ax.add_feature(cfeature.LAND, color='darkgrey') ax.add_feature(cfeature.OCEAN, color='lightblue') ax.add_feature(cfeature.COASTLINE, linewidth=1.25) # 生成网格线 gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1, color='gray', alpha=0.5, linestyle='--', zorder=10) # 添加圆形边界 theta = np.linspace(0, 2*np.pi, 100) center, radius = [0.5, 0.5], 0.5 verts = np.vstack([np.sin(theta), np.cos(theta)]).T circle = mpath.Path(verts * radius + center) ax.set_boundary(circle, transform=ax.transAxes) plt.tight_layout() plt.show()
问题原因
Cartopy默认的网格线标签布局逻辑是为平面投影设计的,在极射投影这类圆形边界的投影中,无法自动让标签沿着圆形边缘排列,导致标签分布杂乱。
解决方案
通过自定义标签绘制逻辑,计算每个标签的位置并调整旋转角度,让标签贴合圆形边界:
import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature import numpy as np import matplotlib.path as mpath from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER fig = plt.figure(figsize=(12,8)) ax = plt.axes(projection=ccrs.SouthPolarStereo()) ax.set_extent([-180, 180, -90, -30], ccrs.PlateCarree()) ax.add_feature(cfeature.LAND, color='darkgrey') ax.add_feature(cfeature.OCEAN, color='lightblue') ax.add_feature(cfeature.COASTLINE, linewidth=1.25) # 设置圆形边界 theta = np.linspace(0, 2*np.pi, 100) center, radius = [0.5, 0.5], 0.5 verts = np.vstack([np.sin(theta), np.cos(theta)]).T circle = mpath.Path(verts * radius + center) ax.set_boundary(circle, transform=ax.transAxes) # 生成网格线但关闭默认标签绘制 gl = ax.gridlines(crs=ccrs.PlateCarree(), linewidth=1, color='gray', alpha=0.5, linestyle='--', zorder=10) gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.draw_labels = False # 自定义绘制圆形环绕的标签 # 定义要显示的经度间隔和固定纬度标签 lon_labels = np.arange(-180, 181, 30) lat_label = -30 # 对应地图范围的南纬30度 # 绘制经度标签 center_ax = ax.transAxes.transform((0.5, 0.5)) # 地图中心的像素坐标 for lon in lon_labels: # 将经纬度转换为投影坐标 x_proj, y_proj = ax.projection.transform_point(lon, lat_label, ccrs.PlateCarree()) # 计算标签相对于中心的角度,用于旋转标签使其贴合圆形 x_pixel, y_pixel = ax.transData.transform((x_proj, y_proj)) angle = np.degrees(np.arctan2(x_pixel - center_ax[0], y_pixel - center_ax[1])) + 90 # 绘制标签 ax.text(x_proj, y_proj, f'{lon}°', ha='center', va='center', rotation=angle, transform=ax.projection, zorder=11) # 绘制纬度标签 x_lat, y_lat = ax.projection.transform_point(0, lat_label, ccrs.PlateCarree()) ax.text(x_lat, y_lat, f'{abs(lat_label)}°S', ha='center', va='bottom', transform=ax.projection, zorder=11) plt.tight_layout() plt.show()
关键说明
- 先关闭网格线的默认标签绘制,改用
ax.text手动添加标签 - 通过投影转换计算标签在极射投影下的准确位置
- 根据标签相对于地图中心的像素角度,旋转标签使其贴合圆形边缘
- 可根据需求调整经度间隔、标签字体样式、颜色等参数
内容的提问来源于stack exchange,提问作者Rony Golder
相关产品推荐
相关产品推荐

