尽管很多人不喜欢3D地图,但是仍可以使用 Basemap 和 matplotlib mplot3d [注1] 工具绘制3D地图。
创建基本地图
当使用 matplotlib 绘制3D图时,最重要的一点是,要使用 Axes3D 类。使用 add_collection3d 可以添加地理数据到地图中。
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.basemap import Basemap
map = Basemap()
fig = plt.figure()
ax = Axes3D(fig)
'''
ax.azim = 270
ax.elev = 90
ax.dist = 5
'''
ax.add_collection3d(map.drawcoastlines(linewidth=0.25))
ax.add_collection3d(map.drawcountries(linewidth=0.35))
plt.show()
基本用法。轴的旋转是默认的
轴的旋转设置为由 z 轴向下看,看起来就像是 2D图形
填充多边形
不幸的是, basemap 的 fillcontinents 方法不能返回 add_collection3d 支持的对象(PolyCollection, LineColleciton, PatchCollection),而是 matplotlib.patches.Polygon 对象列表。
解决办法就是创建 PolyCollection 对象。
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.basemap import Basemap
from matplotlib.collections import PolyCollection
map = Basemap()
fig = plt.figure()
ax = Axes3D(fig)
ax.azim = 270
ax.elev = 50
ax.dist = 8
ax.add_collection3d(map.drawcoastlines(linewidth=0.25))
ax.add_collection3d(map.drawcountries(linewidth=0.35))
polys = []
for polygon in map.landpolygons:
polys.append(polygon.get_coords())
lc = PolyCollection(polys, edgecolor='black',
facecolor='#DDDDDD', closed=False)
ax.add_collection3d(lc)
plt.show()
添加3D 条形图
如果没有添加数据到地图上,那么绘制3D地图将没有任何意义。 Axes3D 类有 bar3d 方法用于绘制 3D 条形图。
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.basemap import Basemap
from matplotlib.collections import PolyCollection
import numpy as np
map = Basemap(llcrnrlon=-20,llcrnrlat=0,urcrnrlon=15,urcrnrlat=50,)
fig = plt.figure()
ax = Axes3D(fig)
ax.set_axis_off()
ax.azim = 270
ax.dist = 7
polys = []
for polygon in map.landpolygons:
polys.append(polygon.get_coords())
lc = PolyCollection(polys, edgecolor='black',
facecolor='#DDDDDD', closed=False)
ax.add_collection3d(lc)
ax.add_collection3d(map.drawcoastlines(linewidth=0.25))
ax.add_collection3d(map.drawcountries(linewidth=0.35))
lons = np.array([-13.7, -10.8, -13.2, -96.8, -7.99, 7.5, -17.3, -3.7])
lats = np.array([9.6, 6.3, 8.5, 32.7, 12.5, 8.9, 14.7, 40.39])
cases = np.array([1971, 7069, 6073, 4, 6, 20, 1, 1])
deaths = np.array([1192, 2964, 1250, 1, 5, 8, 0, 0])
places = np.array(['Guinea', 'Liberia', 'Sierra Leone','United States', 'Mali', 'Nigeria', 'Senegal', 'Spain'])
x, y = map(lons, lats)
ax.bar3d(x, y, np.zeros(len(x)), 2, 2, deaths, color= 'r', alpha=0.8)
plt.show()
注1:http://matplotlib.org/mpl_toolkits/mplot3d/