【问题标题】:Plotting line across international dateline with Cartopy使用 Cartopy 绘制跨越国际日期变更线的线
【发布时间】:2021-08-16 05:12:54
【问题描述】:

我正在尝试绘制全球风暴轨迹,但是当风暴越过日期变更线(并且经度从 ~360 到 ~0)时,这条线会一直绕着绘图空间循环。 Here's what the plot looks like. See the weird straight lines near the top. 这是我的代码:

ax = plt.axes(projection=ccrs.Robinson())
ax.set_global()

ax.coastlines()

for i in range(nstorms-1): #loop through each TC
        bidx = start_idx[i]
        eidx = start_idx[i+1]
        plt.plot(clons[bidx:eidx],clats[bidx:eidx],transform=ccrs.PlateCarree())

如果我尝试将转换更改为 Geodetic,它看起来像这样:

【问题讨论】:

  • 嘿,Alyssa,您可以提供一个最小的可重现示例吗? IE。包括其中一个风暴的风暴轨迹数据证明了这个问题?
  • 当然:ax = plt.axes(projection=ccrs.PlateCarree()) ax.set_global() ax.coastlines() lons = [347.87, 349.62, 352.4414, 358.06, 3.69, 7.20] lats = [32.33, 33.63, 34.8, 37.14, 39.25, 42.30] plt.plot(lons,lats,transform=ccrs.PlateCarree())

标签: python matplotlib cartopy


【解决方案1】:

要绘制跨越日期变更线的折线,您需要正确清理经度。例如,值 359 到 2 应调整为 359 到 362。在下面的演示代码中,sanitize_lonlist() 用于在使用它绘制红色锯齿线之前清理经度值列表。

import cartopy.crs as ccrs
import matplotlib.pyplot as plt

def sanitize_lonlist(lons):
    new_list = []
    oldval = 0
    treshold = 10  # used to compare adjacent longitudes
    for ix,ea in enumerate(lons):
        diff = oldval - ea
        if (ix>0):
            if (diff>treshold):
                ea = ea+360
        oldval = ea
        new_list.append(ea)
    return new_list

ax = plt.axes(projection=ccrs.Robinson()) 
ax.set_global() 
ax.coastlines(alpha=0.3)

# sample long/lat data for demo purposes
# xdateline: list of longitudes that cross dateline several times
xdateline = [347,349,352,358,4,7,8,3,359,358,360,3,5,359,1,357,0,8,12,6,357,349]
# ydateline: list of accompanying latitudes
ydateline = range(len(xdateline))

# plot the line crossing dateline using `sanitized` values of longitudes
plt.plot(sanitize_lonlist(xdateline), ydateline, transform=ccrs.PlateCarree(), color='red') 

plt.show()

使用xdateline的原始值来绘制代码行:-

plt.plot(xdateline, ydateline, transform=ccrs.PlateCarree(), color='red')

情节将是:-

【讨论】:

  • 我已经实现了这个方法,它有效,谢谢!
  • @AlyssaStansfield 由于您是新用户,因此您通常没有足够的声誉来投票或发表评论。这是您通过将其标记为accepted 答案来获得一些声誉积分的机会——这也是正确的感谢方式。
  • @AlyssaStansfield 如果您通过添加内容以及任何人都可以使用的(更新的)工作代码来编辑您的问题,那么人们(和我)会很高兴地支持您的问题,因为它很有用给他们。
【解决方案2】:

根据this github issue,这是预期行为,因为PlateCarree 是投影坐标系。

PlateCarree 坐标系是笛卡尔坐标系,其中两点之间的直线是直线(在该坐标系中)。笛卡尔系统不知道日期变更线/反子午线,因此当您要求 -170 和 +170 之间的线时,您会得到一条长度为 340 的线。 PlateCarree 投影绝不会解释这些数字并选择绘制非笛卡尔线

一种解决方案是在绘图调用中使用 Geodetic 变换:

plt.plot(clons[bidx:eidx], clats[bidx:eidx], transform=ccrs.Geodetic())

或者在使用PlateCarree 系统时修改您的数据以使其更有意义,例如通过确定值从 360-> 0 循环的位置,并在此之后将 360 添加到所有值。您可以将它们转移到不同的范围(例如 -180..180),但您会遇到与当前 0/360 相同的数据跨越 +/- 180 的问题。

【讨论】:

  • 如果我只是将转换更改为 Geodetic,它不起作用(请参阅我上面的编辑)。当它们从 360 -> 0 变为时,我将尝试将值移动 360。
猜你喜欢
  • 2021-12-24
  • 1970-01-01
  • 2022-08-03
  • 2012-12-01
  • 2021-10-31
  • 1970-01-01
  • 1970-01-01
  • 2017-12-19
  • 2021-11-28
相关资源
最近更新 更多