前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Cartopy 系列教程:3D 地图绘制

Cartopy 系列教程:3D 地图绘制

作者头像
bugsuse
发布2020-04-21 17:47:38
2.4K0
发布2020-04-21 17:47:38
举报
文章被收录于专栏:气象杂货铺气象杂货铺

Basemap 的 mpl3d 绘制3D地图时非常强大,但目前仍然存在一些小问题,比如在填充陆地时有时会出现问题。

虽然 Cartopy 中没有提供直接绘制 3D 地图的方法,但是使用 Cartopy 同样可以绘制 3D 地图。下面就逐步看一下如何绘制:

首先,获取 shp 文件及相应的几何图形(geometries)

代码语言:javascript
复制
feature = cartopy.feature.NaturalEarthFeature('physical', 'coastline', '110m')
geoms = feature.geometries()

然后,转换为目标投影

代码语言:javascript
复制
target_projection = ccrs.PlateCarree()
geoms = [target_projection.project_geometry(geom, feature.crs)
         for geom in geoms]

因为这些都是均匀的几何图形,我们需要将其转换为 matplotlib path

代码语言:javascript
复制
from cartopy.mpl.patch import geos_to_path
import itertools

paths = list(itertools.chain.from_iterable(geos_to_path(geom)
                                             for geom in geoms))

完成这些后,只是创建了 PathCollection,然后要添加这些到 axes,但是 Axes3D 似乎并不支持 PathCollection 实例。因此,需要构建 LineCollection 实例,这也是 basemap 所使用的方法。因为 LineCollection 不支持 paths,所以需要使用 segments:

代码语言:javascript
复制
segments = []
for path in paths:
    vertices = [vertex for vertex, _ in path.iter_segments()]
    vertices = np.asarray(vertices)
    segments.append(vertices)

将以上代码整合起来后,就可以得到和使用 basemap 一样的结果

代码语言:javascript
复制
import itertools

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
import numpy as np

import cartopy.feature
from cartopy.mpl.patch import geos_to_path
import cartopy.crs as ccrs


fig = plt.figure()
ax = Axes3D(fig, xlim=[-180, 180], ylim=[-90, 90])
ax.set_zlim(bottom=0)

target_projection = ccrs.PlateCarree()

feature = cartopy.feature.NaturalEarthFeature('physical', 'coastline', '110m')
geoms = feature.geometries()

geoms = [target_projection.project_geometry(geom, feature.crs)
         for geom in geoms]

paths = list(itertools.chain.from_iterable(geos_to_path(geom) for geom in geoms))

# At this point, we start working around mpl3d's slightly broken interfaces.
# So we produce a LineCollection rather than a PathCollection.
segments = []
for path in paths:
    vertices = [vertex for vertex, _ in path.iter_segments()]
    vertices = np.asarray(vertices)
    segments.append(vertices)

lc = LineCollection(segments, color='black')

ax.add_collection3d(lc)

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Height')

plt.show()

从上面可以发现, mpl3d 似乎能很好的解决 PathCollection 问题,后面我们可以试一下填充 polygon:

最重要的一点是转换 paths 为 polygon,然后传递给 PolyCollection 对象:

代码语言:javascript
复制
concat = lambda iterable: list(itertools.chain.from_iterable(iterable))

polys = concat(path.to_polygons() for path in paths)
lc = PolyCollection(polys, edgecolor='black',
                    facecolor='green', closed=False)

完整代码如下:

代码语言:javascript
复制
import itertools

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection, PolyCollection
import numpy as np

import cartopy.feature
from cartopy.mpl.patch import geos_to_path
import cartopy.crs as ccrs


fig = plt.figure()
ax = Axes3D(fig, xlim=[-180, 180], ylim=[-90, 90])
ax.set_zlim(bottom=0)


concat = lambda iterable: list(itertools.chain.from_iterable(iterable))

target_projection = ccrs.PlateCarree()

feature = cartopy.feature.NaturalEarthFeature('physical', 'land', '110m')
geoms = feature.geometries()

geoms = [target_projection.project_geometry(geom, feature.crs)
         for geom in geoms]

paths = concat(geos_to_path(geom) for geom in geoms)

polys = concat(path.to_polygons() for path in paths)

lc = PolyCollection(polys, edgecolor='black',
                    facecolor='green', closed=False)

ax.add_collection3d(lc)

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Height')

plt.show()

结果如下图:

以上内容得益于 stackoverflow。


注:http://stackoverflow.com/questions/23785408/3d-cartopy-similar-to-matplotlib-basemap/23914781#23914781

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-03-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 气象杂货铺 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档