代码优先:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
ax = plt.axes(projection=ccrs.Mercator())
ax.set_extent([72, 135, 18, 53])
ax.annotate('hello', xy=(100, 49), xycoords='data',
transform=ccrs.PlateCarree(), zorder=12)
plt.show()
结果不是预期的结果,我对我的方法有其他怀疑。所以我的问题是:
如果我想绘制一张类似于网络地图的地图(例如谷歌地图)。地图区域可能与中国一样大,大部分都不是全球性的。谷歌搜索后,这些网站大多使用“网络墨卡托”投影。所以我想我应该在这里使用plt.axes(projection=ccrs.Mercator()
,对吗?或者如果我错了我该怎么用?
我要绘制的坐标数据类似于121°E,49°N(在绘制航线之前将度数转换为十进制),未投影,WGS84坐标系统,可能来自GPS。我使用transform=ccrs.PlateCarree()
是对的吗?或者如果我错了我该怎么用?
上面的annotate
没有显示任何内容。在评论ax.set_extent
行之后,将“hello”文本绘制在零(0,0)点处。我想要的是在点(100°E,49°N)如何纠正?
答案 0 :(得分:12)
首先 - 感谢代码 - 这使得解决问题变得容易得多。
说实话,我认为注释之前并没有真正使用过Cartopy,所以这可能就是为什么你会遇到这个问题 - 你真的很开心;)
看起来matplotlib的Axes.annotate
方法应该归咎于此 - 它会使https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/axes/_axes.py#L651周围的变换成为核心。这主要是因为注释具有特殊关键字,用于独立定义坐标和文本位置的变换(请参阅http://matplotlib.org/users/annotations_intro.html#annotating-text中的xycoords
和textcoords
)。
当我们深入研究Annotate类时,我们会发现Annotate的_get_xy_transform
(https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/text.py#L1446)可以处理各种(一些未记录的)表单作为textcoords
的值,包括转换实例。
好的,到目前为止,非常好。看起来你可以通过一个坐标系来xycoords
,一切都应该是hunky-dory。遗憾的是,annotate不知道如何将matopy坐标系转换为matplotlib变换,就像matplotlib的其余部分所做的那样,所以我们必须预先为annotate函数做到这一点。
要从任何折纸坐标系创建matplotlib变换,对于任何轴,我们都可以这样做:
ax = plt.axes(projection=ccrs.Mercator())
crs = ccrs.PlateCarree()
transform = crs._as_mpl_transform(ax)
我们现在可以将此转换传递给annotate方法,我们应该在预期位置使用文本和箭头。我已经采取了一些自由来强调注释的一些功能:
import cartopy.feature
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
ax = plt.axes(projection=ccrs.Mercator())
ax.set_extent([65, 125, 5, 40])
ax.add_feature(cartopy.feature.OCEAN)
ax.add_feature(cartopy.feature.LAND)
ax.add_feature(cartopy.feature.BORDERS, linestyle=':', edgecolor='gray')
ax.coastlines()
ax.plot(116.4, 39.95, 'ob', transform=ccrs.PlateCarree())
transform = ccrs.PlateCarree()._as_mpl_transform(ax)
ax.annotate('Beijing', xy=(116.4, 39.9), xycoords=transform,
ha='right', va='top')
ax.annotate('Delhi', xy=(113, 40.5), xytext=(77.23, 28.61),
arrowprops=dict(facecolor='gray',
arrowstyle="simple",
connectionstyle="arc3,rad=-0.2",
alpha=0.5),
xycoords=transform,
ha='right', va='top')
plt.show()
回答你的其他问题:
如果我想绘制一张看起来像网络地图的地图(例如谷歌地图)
cartopy.crs中有一个新的常量,它完全定义了Google Mercator(cartopy.crs.GOOGLE_MERCATOR
)。这只是Mercator投影的一个实例,只有一些调整,使其与Google Mercator(https://github.com/SciTools/cartopy/blob/master/lib/cartopy/crs.py#L889)完全相同。
我想绘制的坐标数据是121°E,49°N(转换为 当然是在绘制前的十进制度),未投影,WGS84 coords系统,可能来自GPS。我是对的 变换= ccrs.PlateCarree()?或者如果我错了我该怎么用?
我建议你最好使用大地坐标系 - 这个坐标系默认使用WGS84基准面,它可以让你最准确地表示你的WGS84纬度和经度。虽然,在你正在绘制它们的尺度上,我想你会很难注意到它们之间的差异(中纬度地区的最大差异约为22Km)。
HTH,