英文:
grid line labeling (labels around the map's border) for a South Polar Stereo projection
问题
我正在使用南极极射投影来创建南极地图。我已经使用Cartopy创建了网格线,但是网格线的标签不是围绕地图的圆形排列,这是我想要的效果。有没有办法使网格线标签遵循南极极射投影的圆形模式?这是我目前正在使用的代码:
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches 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)
# Draw meridian lines with labels around circular boundary
ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1, \
xlocs=range(-180,171,10), ylocs=[], \
color='gray', alpha=0.5, linestyle='--', zorder=10)
# Draw concentric circles (but hide labels) for the parallels of the latitude
ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=False, linewidth=1, \
xlocs=[], ylocs=None, \
color='gray', alpha=0.5, linestyle='--', zorder=10)
# Add circular boundary
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()
输出结果如下:
我期望的效果如下:
英文:
I'm using the South Polar Stereographic projection to create a map of Antarctica. I've been able to create the gridlines using Cartopy, but the labels for the gridlines are not circular around the map, which is what I want. Is there a way to make the gridline labels follow the circular pattern of the South Polar Stereographic projection? Here's the code I'm currently using:
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches 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)
# Draw meridian lines with labels around circular boundary
ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1, \
xlocs=range(-180,171,10), ylocs=[], \
color='gray', alpha=0.5, linestyle='--', zorder=10)
# Draw concentric circles (but hide labels) for the parallels of the latitude
ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=False, linewidth=1, \
xlocs=[], ylocs=None, \
color='gray', alpha=0.5, linestyle='--', zorder=10)
# Add circular boundary
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()
The output looks like
What I am expecting:
答案1
得分: 2
根据我的知识,以下是您提供的代码部分的翻译:
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpath # 用于圆形边界
nonproj = ccrs.PlateCarree() # 用于平面纬度/经度度量
fig = plt.figure(figsize=(7, 7))
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)
# 使网格线成圆形
gls1 = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=False, linewidth=1,
xlocs=range(-180, 171, 10), ylocs=[],
color='gray', alpha=0.5, linestyle='--', zorder=10)
gls2 = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=False, linewidth=1,
xlocs=[], ylocs=None,
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)
def plot_text(p1, p2, ax, ang_d, txt):
"""
在由2个点(p1,p2)定义的位置绘制文本字符串
该字符串以角度'ang_d'旋转
用法:
plot_text([90,-31],[90,-50],ax,45,"45-deg_text")
由swatchai
"""
# 绘制文本的位置
l1 = np.array((p1[0], p1[1]))
l2 = np.array((p2[0], p2[1]))
# 绘制文本
th1 = ax.text(l1[0], l1[1], txt, fontsize=10,
transform=nonproj,
ha="center",
rotation=ang_d, rotation_mode='anchor')
# 在圆形边界外绘制文本标签
for lon in range(-180, 180, 10):
lat = -33 # 通过检查确定的
a1, a2 = -29.5, -39 # 通用使用的文本锚点...
# ... 在某些情况下需要调整
if lon >= 90 and lon <= 170:
plot_text([lon, a1 + 2.35], [lon, a2], ax, -lon - 180, str(lon) + "°E")
# 特殊旋转+移动
elif lon < -90 and lon >= -170:
# 需要a1 + 2来使文本与其他文本一致
plot_text([lon, a1 + 2.5], [lon, a2], ax, -lon + 180, str(-lon) + "°W")
# 特殊旋转+移动
elif lon > 0:
plot_text([lon, a1], [lon, a2], ax, -lon, str(lon) + "°E")
elif lon == 0:
plot_text([lon, a1], [lon, a2], ax, lon, str(lon) + "°")
elif lon == -180:
plot_text([lon, a1 + 2.2], [lon, a2], ax, lon + 180, str(-lon) + "°")
else:
plot_text([lon, a1], [lon, a2], ax, -lon, str(-lon) + "°W")
pass
ax.set_boundary(circle, transform=ax.transAxes)
plt.tight_layout()
plt.show()
希望这可以帮助您理解代码的翻译。
英文:
To my knowledge, there is no shortcut for this kind of plot. Special instructions are needed in many places in the code. You can see comments in the code that I added in various places.
Complete code
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpath #for circular boundary
nonproj = ccrs.PlateCarree() #for plain lat/long degree system
fig = plt.figure(figsize=(7,7))
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)
# Make the gridlines circular
gls1 = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=False, linewidth=1, \
xlocs=range(-180,171,10), ylocs=[], \
color='gray', alpha=0.5, linestyle='--', zorder=10)
gls2 = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=False, linewidth=1, \
xlocs=[], ylocs=None, \
color='gray', alpha=0.5, linestyle='--', zorder=10)
# Add circular boundary
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)
def plot_text(p1, p2, ax, ang_d, txt):
"""
Plot text string at a location defined by 2 points (p1,p2)
The string is rotated by an angle 'ang_d'
usage:
plot_text([90, -31], [90, -50], ax, 45, "45-deg_text")
By swatchai
"""
# Locations to plot text
l1 = np.array((p1[0], p1[1]))
l2 = np.array((p2[0], p2[1]))
# Plot text
th1 = ax.text(l1[0], l1[1], txt, fontsize=10, \
transform=nonproj, \
ha="center", \
rotation=ang_d, rotation_mode='anchor')
# Plot text labels outside circular boundary
for lon in range(-180,180,10):
lat = -33 # determined by inspection
a1, a2 = -29.5, -39 #text anchor for general use ...
#... need adjustments in some cases
if lon>=90 and lon<=170:
plot_text([lon, a1+2.35], [lon, a2], ax, -lon-180, str(lon)+"°E")
# Special rotation+shift
elif lon<-90 and lon>=-170:
# Need a1+2 to move texts in line with others
plot_text([lon, a1+2.5], [lon, a2], ax, -lon+180, str(-lon)+"°W")
# Special rotation+shift
elif lon > 0:
plot_text([lon, a1], [lon, a2], ax, -lon, str(lon)+"°E")
elif lon==0:
plot_text([lon, a1], [lon, a2], ax, lon, str(lon)+"°")
elif lon==-180:
plot_text([lon, a1+2.2], [lon, a2], ax, lon+180, str(-lon)+"°")
else:
plot_text([lon, a1], [lon, a2], ax, -lon, str(-lon)+"°W")
pass
ax.set_boundary(circle, transform=ax.transAxes)
plt.tight_layout()
plt.show()
Output:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论