3D matplotlib底图子午线和平行绘图

时间:2016-02-29 21:23:07

标签: axes matplotlib-basemap

我正在使用matplotlib底图制作飞机数据的3D图。我找到了一种方法,即basemap.drawmeridians和basemap.drawparallels不能与3D轴一起使用。但是,我对最后一个问题感到难过。除非设置了ax.set_zlims关键字,否则手动绘制的子午线和平行线不会与轴对齐。因此,如果没有关键字,请将图片设为grid is displaced,而使用关键字设置grid lines up

相关代码:

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)

1 个答案:

答案 0 :(得分:0)

实际上,您不需要创建虚拟2​​D底图。如果将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