5

我正在使用 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]

所以在北极有两个数据点。有没有更好的解决方案?

编辑:附上图片 想要什么

谢谢,

蒂姆

4

2 回答 2

7

@ajdawson's answer is correct. Using the Geodetic transform, in this case, will do the trick.

To understand the reason the line wasn't as you expected it to look, we need to understand what the PlateCarree transform represents.

Firstly, lets observe that all lines drawn in the transform=<projection> form, using Cartopy, should pass through the same Geographic points irrespective of the projection that the line is being drawn on.

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

So going back to drawing your original coordinates (which were in PlateCarree coordinates) on a PlateCarree map:

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

You will find that the line passes through the same geographic points as your bad line in the original question.

This should satisfy you that Cartopy is behaving rationally and it is not a bug, but it doesn't answer the question about how you would go about drawing the line you desire.

@ajdawson has already said that, in your case, drawing the line:

plt.plot([180, 0], [50, 50] , transform=ccrs.Geodetic())

will result in the desired output.

That is because the Geodetic coordinate reference system draws the line of shortest distance on the globe between two points. However, there will be a latitude which, when crossed, passing through the north pole does not provide the shortest distance:

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

Generally, if you wanted to draw a Geodetic line which always crosses the North Pole, then the north pole should be one of the coordinates of the line.

plt.plot([180, 0, 0], [-45, 90, -45] , transform=ccrs.Geodetic())

Finally, just to throw it into the mix, if you just wanted a vertical line in a North Polar Stereographic projection which crosses the North Pole, it is worth remembering that there exists a Cartesian coordinate system (in which it is worth remembering that the numbers are not latitude and longitudes), so simply doing:

ax = plt.axes(projection=ccrs.NorthPolarStereo())
plt.axvline()

Will also do the trick! (but is less transferable than the Geodetic approach)

Wow, my answer got long. I hope your still with me and that makes the whole PlateCarree thing clearer!

于 2013-01-15T10:45:57.557 回答
3

我认为您在绘制此部分而不是 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()

结果如下所示:

北极上空的剖面

我认为无论如何这是处理这个问题的正确方法!

安德鲁

于 2013-01-14T20:05:28.390 回答