在 cartopy 中设置穿越日期变更线的地图 [英] Setting up a map which crosses the dateline in cartopy

查看:58
本文介绍了在 cartopy 中设置穿越日期变更线的地图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到了以下电子邮件,并希望确保每个人都可以找到该问题的答案:

I received the following email and wanted to make sure the answer to this question was available to everybody:

我想使用 cartopy 设置一个简单的纬度经度地图,该地图跨越日期变更线并在左侧显示东亚,在右侧显示北美西部.下面的谷歌地图大致就是我所追求的:

I would like to setup a simple latitude longitude map, using cartopy, which crosses the dateline and shows east Asia on the left hand side with the west of North America on the right. The following google map is roughly what I am after:

https://maps.google.co.uk/?ll=56.559482,-175.253906&spn=47.333523,133.066406&t=m&z=4

这可以用Cartopy完成吗?

Can this be done with Cartopy?

推荐答案

好问题.这可能会时不时地出现,因此在实际上回答您的特定问题之前,我将逐步进行此步骤.为了将来参考,以下示例是使用 cartopy v0.5 编写的.

Good question. This is probably something which will come up time-and-time again, so I will go through this step-by-step before actually answering your specific question. For future reference, the following examples were written with cartopy v0.5.

首先,重要的是要注意默认的纬度经度"(或更专业的 PlateCarree)投影在 -180 到 180 的前向范围内工作.这意味着您无法绘制标准PlateCarree投影超出了此范围.这样做有几个充分的理由,其中大部分归结为这样一个事实,即在投影矢量和栅格(例如简单的海岸线)时,cartopy必须做更多的工作.不幸的是,您试图生成的图恰恰需要此功能.要在图片中添加此限制,默认的PlateCarree投影如下所示:

Firstly, it is important to note that the default "latitude longitude" (or more technically PlateCarree) projection works in the forward range of -180 to 180. This means that you cannot plot the standard PlateCarree projection beyond this. There are several good reasons for this, most of which boil down to the fact that cartopy would have to do a lot more work when projecting both vectors and rasters (simple coastlines for example). Unfortunately the plot you are trying to produce requires precisely this functionality. To put this limitation into pictures, the default PlateCarree projection looks like:

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

proj = ccrs.PlateCarree(central_longitude=0)

ax1 = plt.axes(projection=proj)
ax1.stock_img()
plt.title('Global')

plt.show()

您可以在此地图上绘制的任何单个矩形在法律上都可以是放大区域(此处有一些更高级的代码,但是图片价值1000字):

Any single rectangle that you can draw on this map can legally be a zoomed in area (there is some slightly more advanced code in here, but the picture is worth a 1000 words):

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import shapely.geometry as sgeom

box = sgeom.box(minx=-90, maxx=45, miny=15, maxy=70)
x0, y0, x1, y1 = box.bounds

proj = ccrs.PlateCarree(central_longitude=0)

ax1 = plt.subplot(211, projection=proj)
ax1.stock_img()
ax1.add_geometries([box], proj, facecolor='coral', 
                   edgecolor='black', alpha=0.5)
plt.title('Global')

ax2 = plt.subplot(212, projection=proj)
ax2.stock_img()
ax2.set_extent([x0, x1, y0, y1], proj)
plt.title('Zoomed in area')

plt.show()

不幸的是,您想要的图需要 2 个带有此投影的矩形:

Unfortunately the plot you want would require 2 rectangles with this projection:

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import shapely.geometry as sgeom

box = sgeom.box(minx=120, maxx=260, miny=15, maxy=80)

proj = ccrs.PlateCarree(central_longitude=0)

ax1 = plt.axes(projection=proj)
ax1.stock_img()
ax1.add_geometries([box], proj, facecolor='coral', 
                   edgecolor='black', alpha=0.5)
plt.title('Target area')

plt.show()

因此,不可能使用标准 PlateCarree 定义绘制跨越日期变更线的地图.相反,我们可以更改 PlateCarree 定义的中心经度,以允许绘制我们目标区域的单个框:

Hence it is not possible to draw a map that crosses the dateline using the standard PlateCarree definition. Instead we could change the PlateCarree definition's central longitude to allow a single box to be drawn of the area we are targeting:

import cartopy.crs as ccrs
import matplotlib.pyplot as plt
import shapely.geometry as sgeom

box = sgeom.box(minx=120, maxx=260, miny=15, maxy=80)
x0, y0, x1, y1 = box.bounds

proj = ccrs.PlateCarree(central_longitude=180)
box_proj = ccrs.PlateCarree(central_longitude=0)

ax1 = plt.subplot(211, projection=proj)
ax1.stock_img()
ax1.add_geometries([box], box_proj, facecolor='coral', 
                   edgecolor='black', alpha=0.5)
plt.title('Global')

ax2 = plt.subplot(212, projection=proj)
ax2.stock_img()
ax2.set_extent([x0, x1, y0, y1], box_proj)
plt.title('Zoomed in area')

plt.show()

希望向您展示什么要实现目标地图,上面的代码可能有点复杂以实现您的目标,因此为了稍微简化,我将编写代码生成想要的图将是这样的:

Hopefully that shows you what it is you have to do to achieve your target map, the code above might be a little complex to achieve your goal, so to simplify slightly, the code I would write to produce the plot you want would be something like:

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

ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180))
ax.set_extent([120, 260, 15, 80], crs=ccrs.PlateCarree())

# add some features to make the map a little more polished
ax.add_feature(cartopy.feature.LAND)
ax.add_feature(cartopy.feature.OCEAN)
ax.coastlines('50m')

plt.show()

这是一个很长的答案,希望我不仅回答了这个问题,而且使地图制作和Cartopy的一些更复杂的细节更加清晰,以帮助解决您将来可能遇到的任何问题.

This was a long answer, hopefully I have not only answered the question, but made some of the more complex details of map production and cartopy more clear to help smooth any future problems you may have.

干杯,

这篇关于在 cartopy 中设置穿越日期变更线的地图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆