2016-02-29 147 views
0

我正在使用matplotlib底图制作飞机数据的3D图。我发现了一个解决方法,即basemap.drawmeridians和basemap.drawparallels不能用于3D轴。然而,我最终难以理解。除非设置了ax.set_zlims关键字,否则手动绘制的经络和平行线不能与轴线对齐。因此,没有关键字设置图像的grid is displaced,同时与关键字设置的grid lines up3D matplotlib底图子午线和平行绘图

相关的代码:

fig = plt.gcf() 
ax = fig.add_subplot(111, projection='3d') 

# Create a basemap instance 
bm = Basemap(projection=proj, resolution=resolution, 
      area_thresh=area_thresh, 
      llcrnrlon=corners[0], urcrnrlon=corners[2], 
      llcrnrlat=corners[1], urcrnrlat=corners[3], 
      lon_0=lon_0, lat_0=lat_0, ax=ax) 

# Now we need to create a "fake" axes instance because 
# the drawmeridians and drawparallels will not otherwise work 
ax2D = Axes(fig, [0, 0, 1, 1]) 
bm2 = Basemap(projection=proj, resolution=resolution, 
       area_thresh=area_thresh, 
       llcrnrlon=corners[0], urcrnrlon=corners[2], 
       llcrnrlat=corners[1], urcrnrlat=corners[3], 
       lon_0=lon_0, lat_0=lat_0, ax=ax2D) 

llxc, llyc = bm2(corners[0], corners[1]) 
urxc, uryc = bm2(corners[2], corners[3]) 
if xpad is None: 
    xpad = 1. 
xoffset = ((urxc - llxc)/100.) * xpad 
if ypad is None: 
    ypad = 1. 
yoffset = ((uryc - llyc)/100.) * ypad 

# Check the customizations for the basemap 
if meridians: 
    lons = np.arange(corners[0], corners[2], lon_spacing) 
    latax = np.full(np.shape(lons), corners[1]) 
    bmlon = bm2.drawmeridians(lons, labels=[1, 0, 0, 1] 
    xm, ym = bm2(lons, latax) 
    llxm, llym = bm2(lons[0], corners[1]) 
    urxm, urym = bm2(lons[-1], corners[3]) 
    for i, mm in enumerate(bmlon.keys()): 
     ax.plot([xm[i], xm[i]], [llym, urym], zs=0., 
       color='0.92', ls=':') 
     ax.text(xm[i], llym - yoffset, 0., np.str(mm), 
       horizontalalignment='center', verticalalignment='top') 
if parallels: 
    lats = np.arange(corners[1], corners[3], lat_spacing) 
    lonax = np.full(np.shape(lats), corners[2]) 
    bmlat = bm2.drawparallels(lats, labels=[1, 0, 0, 1]) 
    xp, yp = bm2(lonax, lats) 
    llxp, llyp = bm2(corners[0], lats[0]) 
    urxp, uryp = bm2(corners[2], lats[-1]) 
    for i, pp in enumerate(bmlat.keys()): 
     ax.plot([llxp, urxp], [xm[i], xm[i]], zs=0., 
       color='0.88', ls=':') 
     ax.text(urxc + xoffset, yp[i], 0., np.str(pp), 
       horizontalalignment='left', verticalalignment='center') 

ax.add_collection3d(bm.drawstates()) 

p = ax.plot(x, y, altmask, color=track_color, 
      linewidth=lw, linestyle=ls, alpha=alpha) 

# Label the axes 
ax.set_xlabel('Longitude') 
ax.set_ylabel('Latitude') 
ax.set_zlabel('Altitude (m)') 

ax.set_xlim3d(np.min(x), np.max(x)) 
ax.set_ylim3d(np.min(y), np.max(y)) 
ax.set_zlim3d(min_altitude, max_altitude) 

回答

0

其实你并不需要创建一个虚拟2D底图。如果你设置x和y滴答作为经线和平行线阵列,那么python应该正确标记底图。

给这个代码一展身手:

# -*- coding: utf-8 -*- 
import numpy as np 
import matplotlib.pyplot as plt 
from mpl_toolkits.mplot3d import Axes3D 
from mpl_toolkits.basemap import Basemap 

fig = plt.figure() 
ax = fig.gca(projection='3d') 
extent = [-180,180,-90,90] 
bm = Basemap(llcrnrlon=extent[0], llcrnrlat=extent[2], 
      urcrnrlon=extent[1], urcrnrlat=extent[3], 
      projection='cyl', resolution='l', fix_aspect=False, ax=ax) 
ax.add_collection3d(bm.drawcoastlines(linewidth=0.25)) 
ax.add_collection3d(bm.drawcountries(linewidth=0.35)) 
ax.view_init(azim = 230, elev = 50) 
ax.set_xlabel(u'Longitude (°E)', labelpad=10) 
ax.set_ylabel(u'Latitude (°N)', labelpad=10) 
ax.set_zlabel(u'Altitude (ft)', labelpad=20) 
# Add meridian and parallel gridlines 
lon_step = 30 
lat_step = 30 
meridians = np.arange(extent[0], extent[1]+lon_step, lon_step) 
parallels = np.arange(extent[2], extent[3]+lat_step, lat_step) 
ax.set_yticks(parallels) 
ax.set_yticklabels(parallels) 
ax.set_xticks(meridians) 
ax.set_xticklabels(meridians) 
ax.set_zlim(0., 40000.) 
plt.show() 

enter image description here