我正在使用图纸来生成具有立体投影的北极地图,然后在顶部绘制一条线(以显示横截面的位置)。如果我使用下面的代码,那么这条直线不是直线穿过极点,而是沿着一条纬线走。
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
x=[180,0]
y=[50,50]
ax = plt.axes(projection=ccrs.NorthPolarStereo())
ax.set_extent([0, 360, 50, 90], crs=ccrs.PlateCarree())
ax.plot(x,y,transform=ccrs.PlateCarree())
plt.gca().stock_img()
plt.gca().coastlines()
plt.show()
为了解决这个问题,我必须将x和y更改为:
x=[180,180,0,0]
y=[50,90,90,50]
因此北极有两个数据点。对此有更好的解决方案吗?
修改:已附加图片
谢谢,
添
答案 0 :(得分:7)
@ ajdawson的回答是正确的。在这种情况下,使用大地测量变换可以解决问题。
要理解线条不符合预期的原因,我们需要了解PlateCarree变换代表的内容。
首先,让我们观察一下,使用Cartopy以transform=<projection>
形式绘制的所有线条都应该通过相同的地理点,而不管线条被绘制的投影。
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
def main():
x=[180, 180, 0, 0]
y=[50, 90, 90, 50]
# plot2 - North Polar Stereographic
ax = plt.subplot(211, projection=ccrs.NorthPolarStereo())
ax.set_extent([0, 360, 50, 90], crs=ccrs.PlateCarree())
ax.plot(x, y, transform=ccrs.PlateCarree(), color='red', lw=2)
ax.stock_img()
ax.coastlines()
# plot2 - PlateCarree
ax = plt.subplot(212, projection=ccrs.PlateCarree(central_longitude=45))
ax.set_extent([0, 360, -45, 90], crs=ccrs.PlateCarree())
ax.plot(x, y, transform=ccrs.PlateCarree(), color='red', lw=2)
ax.stock_img()
ax.coastlines()
plt.show()
if __name__ == '__main__':
main()
回到PlateCarree地图上绘制原始坐标(在PlateCarree坐标中):
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
def main():
x=[180, 0]
y=[50, 50]
ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=45))
ax.set_extent([0, 360, -45, 90], crs=ccrs.PlateCarree())
ax.plot(x, y, transform=ccrs.PlateCarree(), color='red', lw=2)
ax.stock_img()
ax.coastlines()
plt.tight_layout()
plt.show()
if __name__ == '__main__':
main()
您会发现该线路与原始问题中的坏线路经过相同的地理点。
这应该让你满意的是,Cartopy的行为是合理的并且它不是一个bug,但是它没有回答关于如何你想要绘制你想要的那条线的问题。
@ajdawson已经说过,在你的情况下,画线:
plt.plot([180, 0], [50, 50] , transform=ccrs.Geodetic())
将产生所需的输出。
这是因为大地坐标参考系统在两点之间绘制地球上最短距离的线。但是,有一个纬度,当越过北极时,不会提供最短的距离:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
def main():
ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=45))
ax.set_global()
ax.plot([180, 0], [20, 20], transform=ccrs.Geodetic(), color='red', lw=2, label='Latitude = 20')
ax.plot([180, 0], [0, 0], transform=ccrs.Geodetic(), color='blue', lw=2, label='Latitude = 0')
ax.plot([180, 0], [-20, -20], transform=ccrs.Geodetic(), color='yellow', lw=2, label='Latitude = -20')
ax.outline_patch.set_zorder(2)
plt.legend(loc=8, bbox_to_anchor=(0.65, -0.2), shadow=True, fancybox=True)
ax.stock_img()
ax.coastlines()
plt.tight_layout()
plt.show()
if __name__ == '__main__':
main()
一般来说,如果你想绘制一条始终穿过北极的大地测量线,那么北极应该是该线的坐标之一。
plt.plot([180, 0, 0], [-45, 90, -45] , transform=ccrs.Geodetic())
最后,只是把它扔进混音中,如果你只是想要穿过北极的北极立体投影中的垂直线,那么值得记住存在笛卡尔坐标系(其中值得记住)这些数字不是纬度和经度),所以简单地做:
ax = plt.axes(projection=ccrs.NorthPolarStereo())
plt.axvline()
也会这样做! (但不如大地测量方法可转移)
哇,我的回答很长。我希望你和我在一起,这让整个PlateCarree的事情变得更加清晰!答案 1 :(得分:2)
我认为在绘制此部分而不是Plate Carree时需要使用Geodetic变换:
<!-- language: lang-py -->
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
x=[180,0]
y=[50,50]
ax = plt.axes(projection=ccrs.NorthPolarStereo())
ax.set_extent([0, 360, 50, 90], crs=ccrs.PlateCarree())
ax.plot(x,y,transform=ccrs.Geodetic())
ax.stock_img()
ax.coastlines()
plt.show()
结果如下:
我认为这是处理此问题的正确方法!
安德鲁