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

TGr*_*ham 4 matplotlib cartopy

我正在使用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()
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,我必须将x和y更改为:

x=[180,180,0,0]
y=[50,90,90,50]
Run Code Online (Sandbox Code Playgroud)

所以北极有两个数据点.有更好的解决方案吗?

编辑:附加图像 什么是期望的

谢谢,

蒂姆

pel*_*son 7

@ ajdawson的回答是正确的.在这种情况下,使用大地测量变换就可以了.

要理解线条不符合预期的原因,我们需要了解PlateCarree变换代表什么.

首先,让我们观察一下transform=<projection>,使用Cartopy 在表单中绘制的所有线条都应该通过相同的地理点,而不管绘制线条的投影如何.

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()
Run Code Online (Sandbox Code Playgroud)

输出图像 -  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()
Run Code Online (Sandbox Code Playgroud)

PlateCarree线

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

这应该让你满意的是,Cartopy的行为是合理的并且它不是一个bug,但它并没有回答关于你如何绘制你想要的线的问题.

@ajdawson已经说过,在你的情况下,绘制线:

plt.plot([180, 0], [50, 50] , transform=ccrs.Geodetic())
Run Code Online (Sandbox Code Playgroud)

将产生所需的输出.

这是因为大地坐标参考系统在两点之间绘制地球上最短距离的线.但是,当穿过北极时,将有一个纬度不提供最短距离:

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()
Run Code Online (Sandbox Code Playgroud)

非北极穿越大地线

通常,如果您想绘制始终穿过北极的大地测量线,那么北极应该是该线的坐标之一.

plt.plot([180, 0, 0], [-45, 90, -45] , transform=ccrs.Geodetic())
Run Code Online (Sandbox Code Playgroud)

最后,只是把它扔进混音中,如果你只是想要穿过北极的北极立体投影中的垂直线,那么值得记住存在笛卡尔坐标系(其中值得记住的是数字)不是纬度和经度),所以干脆做:

ax = plt.axes(projection=ccrs.NorthPolarStereo())
plt.axvline()
Run Code Online (Sandbox Code Playgroud)

也会做的伎俩!(但比大地测量法更不易转移)

哇,我的答案很长.我希望你和我在一起,这让整个PlateCarree的事情变得更加清晰!


ajd*_*son 3

我认为在绘制此部分时您需要使用大地测量变换而不是 Plate Carree:

<!-- 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()
Run Code Online (Sandbox Code Playgroud)

结果如下:

北极部分

我认为无论如何这都是正确的处理方式!

安德鲁