登录后查看更多精彩内容~
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 clarmy 于 2022-3-6 12:10 编辑
众所周知,Python的matplotlib是一个非常全面的制图库,它不仅可以绘制图表、地图,还可以绘制3D效果图,试想一下,如果你在写论文的时候,可以将立体地形图作为底图,那逼格噌一下子就上来了,今天我就来教大家画一个带有地理坐标属性的立体地形图,啥也不说,咱先上效果图: 上面这张图是展示了基于matplotlib+cartopy的山地阴影图在不同光影参数下的变化效果。这个变化效果有利于我们理解matplotlib对该效果的设计理念。 在我讲解之前,我推荐大家读一下matplotlib官方文档库里的这一篇文章: Topographic hillshading,该文章已经介绍了如何单独基于matplotlib绘制山地阴影图,并给出了不同渲染参数下的渲染效果图。我当初对山地立体图的学习就是从这篇文章开始的。 本教程代码所需依赖: - matplotlib
- cartopy>=0.19.0
- cnmaps
- netCDF4
- numpy
复制代码
神说:要有光光,是三维世界最重要的东西,要绘制山地立体图,首先需要理解matplotlib中的LightSource对象,顾名思义,这个对象就是“光源”,与3D 建模里的光源是同一个东西,它的调用方法是: - from matplotlib.colors import LightSource
- ls = LightSource(azdeg=360, altdeg=30)
复制代码
其中azdeg是方位角,altdeg是高度角,这两个参数可以确定一个光源的投射方向,进而可以知道被光源投射的物体,哪一部分应该是光,哪一部分应该是影,而光影便是实现地形立体效果的金钥匙。 在我们创建了光源以后,就需要基于该光源对地形数据生成光影对象,通常情况下,对于山地阴影,我们有两个方法可以选择,一个是hillshade,另一个是shade,其中hillshade返回的是以0-1的数字代表的光影明暗特征,你可以把它理解为一个灰度图,而shade返回的是一个RGBA数组,也就是彩图,下面我们使用shade来看一个实际的例子: - import netCDF4 as nc
- import numpy as np
- import matplotlib.pyplot as plt
- import cartopy.crs as ccrs
- from matplotlib.colors import LightSource
- from cnmaps import get_map, draw_map
- ds = nc.Dataset('./data/cldasgrid_dem.nc')
- _lon = ds.variables['LON'][:]
- _lat = ds.variables['LAT'][:]
- _dem = ds.variables['elevation'][:]
- lon = _lon[4032: 4662]
- lat = _lat[1635: 2134]
- dem = _dem[1635: 2134, 4032: 4662]
- ls = LightSource(azdeg=360, altdeg=30)
- rgb = ls.shade(dem[::-1], cmap=plt.cm.gist_earth, blend_mode='overlay',
- vert_exag=0.5, dx=10, dy=10, fraction=1.5, vmin=-2300)
- fig = plt.figure(figsize=(8, 8))
- ax = fig.add_subplot(111, projection=ccrs.PlateCarree())
- img = ax.imshow(rgb, extent=(lon.min(),lon.max(),lat.min(),lat.max()), transform=ccrs.PlateCarree())
- draw_map(get_map('河南'), color='w', linewidth=2)
- ax.set_extent(get_map('河南').get_extent(buffer=0))
- plt.show()
复制代码
这样,我们的第一张立体地形图就出来了,是不是很炫酷?此外,如果你调整azdeg和altdeg的值,阴影的方位就会随之改变,就像文章开头那张动图一样,它就是通过修改azdeg的值以达到光线旋转照射的效果的。
|