如何确定任何 cartopy 投影的可见地图范围?

How to determine visible map extent for any cartopy projection?

当为具有非 Plate Carree 投影的 cartopy 地图设置地图范围时,地图上有超出指定范围的可见区域。可以在这个 jupyter notebook 的最后一张图片中看到一个例子:https://gist.github.com/ajdawson/e75715203148c9b22e436c6017d3c513

使用 Lambert Conformal 投影,图形 window 内的某些区域(未着色)超出指定范围。虽然此示例中的地图范围设置为 [-140, -60, 20, 70],但可见的最小经度在左上角接近 -180。从本质上讲,set_extent() 设置的范围并不是图像中看到的真实 lat/lon 范围。

我想要一种方法来找出每个图像的真实范围。这将是图像中任何地方可见的最大和最小纬度和经度。对于大多数投影,这可以通过找到地图角的 lat/lon 坐标来完成,但如果极点在图中可见(对于任何极坐标投影),该方法将失败。

21 年 9 月 23 日更新
我发现 cartopy 轴有一个 get_extent() 方法可以做到这一点!

示例:

import matplotlib.pyplot as plt
import cartopy.crs as ccrs, cartopy.feature as cfeature

fig = plt.figure()
ax = fig.add_subplot(111, projection=ccrs.LambertConformal())
ax.set_extent([-130, -60, 20, 70], ccrs.PlateCarree())
ax.add_feature(cfeature.COASTLINE)
print(ax.get_extent(crs=ccrs.PlateCarree())) # this is the visible map extent, not the same as what was set using ax.set_extent()

上一个答案 - 一个同样有效的解决方案
我最终想出了一个比原始问题更适合我的应用程序的解决方案。如果我在地图上绘制网格数据,我会从数据坐标转换为地图坐标,然后从地图坐标转换为图形坐标,最后从图形坐标转换为轴坐标。如果格点在(0:1,0:1)之内,则落在可见地图范围内。

import numpy as np
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

lat = np.arange(0,91,1.0)
lon = np.arange(-180,1,1.0)
lons,lats = np.meshgrid(lon,lat)

mapproj = ccrs.LambertConformal() # the map projection
dataproj = ccrs.PlateCarree() # the data projection, PlateCarree for lat/lon data
fig = plt.figure()
ax = fig.add_subplot(111, projection=mapproj)

points = mapproj.transform_points(dataproj, lons, lats)
xpts = points[:,:,0].flatten().tolist()
ypts = points[:,:,1].flatten().tolist()
crs_pts = list(zip(xpts,ypts))
fig_pts = ax.transData.transform(crs_pts)
ax_pts = ax.transAxes.inverted().transform(fig_pts)
x = ax_pts[:,0].reshape(lats.shape)
y = ax_pts[:,1].reshape(lats.shape)

mask = (x>=-0.02) & (x<=1.02) & (y>=-0.02) & (y<=1.02) # add padding for large grid spacings