通过Cartopy立体投影直线穿过杆

时间:2013-01-14 11:27:02

标签: matplotlib cartopy

我正在使用图纸来生成具有立体投影的北极地图,然后在顶部绘制一条线(以显示横截面的位置)。如果我使用下面的代码,那么这条直线不是直线穿过极点,而是沿着一条纬线走。

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]

因此北极有两个数据点。对此有更好的解决方案吗?

修改:已附加图片 What is desired

谢谢,

2 个答案:

答案 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()

output image - north polar stereo next to PlateCarree

回到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()

PlateCarree line

您会发现该线路与原始问题中的坏线路经过相同的地理点。

这应该让你满意的是,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()

Non-north pole crossing geodetic lines

一般来说,如果你想绘制一条始终穿过北极的大地测量线,那么北极应该是该线的坐标之一。

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()

结果如下:

section over North Pole

我认为这是处理此问题的正确方法!

安德鲁