在 NorthPolarStereo 投影中使用 Cartopy 绘制圆圈
Drawing circles with Cartopy in NorthPolarStereo projection
我想在 Cartopy 中以 NorthPolarStereo 投影绘制圆,提供以纬度、经度为单位的中心和半径。
Basemap , and for Cartopy in Ortographic projection 提供了类似的优秀问题和答案。但是,我想在 Cartopy 中使用 NorthPolarStereo。尝试后一种方法,只需更改投影即可使圆固定在北极,而忽略您为其中心提供的坐标。
关于如何使用 NorthPolarStereo 投影在 Cartopy 中绘制圆,提供其中心和半径的经纬度单位的任何想法?
import numpy as np
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
# example: draw circle with 45 degree radius around the North pole
lat = 72
lon = 100
r = 20
# Define the projection used to display the circle:
proj = ccrs.NorthPolarStereo(central_longitude=lon)
def compute_radius(ortho, radius_degrees):
phi1 = lat + radius_degrees if lat <= 0 else lat - radius_degrees
_, y1 = ortho.transform_point(lon, phi1, ccrs.PlateCarree())
return abs(y1)
# Compute the required radius in projection native coordinates:
r_ortho = compute_radius(proj, r)
# We can now compute the correct plot extents to have padding in degrees:
pad_radius = compute_radius(proj, r + 5)
# define image properties
width = 800
height = 800
dpi = 96
resolution = '50m'
# create figure
fig = plt.figure(figsize=(width / dpi, height / dpi), dpi=dpi)
ax = fig.add_subplot(1, 1, 1, projection=proj)
ax.set_xlim([-pad_radius, pad_radius])
ax.set_ylim([-pad_radius, pad_radius])
ax.imshow(np.tile(np.array([[cfeature.COLORS['water'] * 255]], dtype=np.uint8), [2, 2, 1]), origin='upper', transform=ccrs.PlateCarree(), extent=[-180, 180, -180, 180])
ax.add_feature(cfeature.NaturalEarthFeature('physical', 'land', resolution, edgecolor='black', facecolor=cfeature.COLORS['land']))
ax.add_patch(mpatches.Circle(xy=[lon, lat], radius=r_ortho, color='red', alpha=0.3, transform=proj, zorder=30))
plt.show()
圆固定在北极,不会移动
圆心坐标必须是投影坐标。所以,需要进行坐标变换。
相关代码如下:
# Note: lat = 72, lon = 100
# proj = ccrs.NorthPolarStereo(central_longitude=lon)
projx1, projy1 = proj.transform_point(lon, lat, ccrs.Geodetic()) #get proj coord of (lon,lat)
ax.add_patch(mpatches.Circle(xy=[projx1, projy1], radius=r_ortho, color='red', \
alpha=0.3, transform=proj, zorder=30))
输出图将是:
备用解决方案
由于使用的投影是conformal
,所以上面的Tissot Indicatrix图总是一个圆。这样,您需要的圆可以用 Indicatrix 表示。这是您可以尝试的代码:
ax.tissot(rad_km=r_ortho/1000, lons=lon, lats=lat, n_samples=48, color='green', \
alpha=0.3, zorder=31)
编辑 1
替换错误函数的代码:
import pyproj
def compute_radius(val_degree):
"""
Compute surface distance in meters for a given angular value in degrees
"""
geod84 = pyproj.Geod(ellps='WGS84')
lat0, lon0 = 0, 90
_, _, dist_m = geod84.inv(lon0, lat0, lon0+val_degree, lat0)
return dist_m
compute_radius(1) # get: 111319.49079327357 (meters)
我想在 Cartopy 中以 NorthPolarStereo 投影绘制圆,提供以纬度、经度为单位的中心和半径。
Basemap
关于如何使用 NorthPolarStereo 投影在 Cartopy 中绘制圆,提供其中心和半径的经纬度单位的任何想法?
import numpy as np
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
# example: draw circle with 45 degree radius around the North pole
lat = 72
lon = 100
r = 20
# Define the projection used to display the circle:
proj = ccrs.NorthPolarStereo(central_longitude=lon)
def compute_radius(ortho, radius_degrees):
phi1 = lat + radius_degrees if lat <= 0 else lat - radius_degrees
_, y1 = ortho.transform_point(lon, phi1, ccrs.PlateCarree())
return abs(y1)
# Compute the required radius in projection native coordinates:
r_ortho = compute_radius(proj, r)
# We can now compute the correct plot extents to have padding in degrees:
pad_radius = compute_radius(proj, r + 5)
# define image properties
width = 800
height = 800
dpi = 96
resolution = '50m'
# create figure
fig = plt.figure(figsize=(width / dpi, height / dpi), dpi=dpi)
ax = fig.add_subplot(1, 1, 1, projection=proj)
ax.set_xlim([-pad_radius, pad_radius])
ax.set_ylim([-pad_radius, pad_radius])
ax.imshow(np.tile(np.array([[cfeature.COLORS['water'] * 255]], dtype=np.uint8), [2, 2, 1]), origin='upper', transform=ccrs.PlateCarree(), extent=[-180, 180, -180, 180])
ax.add_feature(cfeature.NaturalEarthFeature('physical', 'land', resolution, edgecolor='black', facecolor=cfeature.COLORS['land']))
ax.add_patch(mpatches.Circle(xy=[lon, lat], radius=r_ortho, color='red', alpha=0.3, transform=proj, zorder=30))
plt.show()
圆固定在北极,不会移动
圆心坐标必须是投影坐标。所以,需要进行坐标变换。
相关代码如下:
# Note: lat = 72, lon = 100
# proj = ccrs.NorthPolarStereo(central_longitude=lon)
projx1, projy1 = proj.transform_point(lon, lat, ccrs.Geodetic()) #get proj coord of (lon,lat)
ax.add_patch(mpatches.Circle(xy=[projx1, projy1], radius=r_ortho, color='red', \
alpha=0.3, transform=proj, zorder=30))
输出图将是:
备用解决方案
由于使用的投影是conformal
,所以上面的Tissot Indicatrix图总是一个圆。这样,您需要的圆可以用 Indicatrix 表示。这是您可以尝试的代码:
ax.tissot(rad_km=r_ortho/1000, lons=lon, lats=lat, n_samples=48, color='green', \
alpha=0.3, zorder=31)
编辑 1
替换错误函数的代码:
import pyproj
def compute_radius(val_degree):
"""
Compute surface distance in meters for a given angular value in degrees
"""
geod84 = pyproj.Geod(ellps='WGS84')
lat0, lon0 = 0, 90
_, _, dist_m = geod84.inv(lon0, lat0, lon0+val_degree, lat0)
return dist_m
compute_radius(1) # get: 111319.49079327357 (meters)