matplotlib
Tredimensionella tomter
Sök…
Anmärkningar
Tredimensionell plottning i matplotlib har historiskt sett varit lite av en kludge, eftersom återgivningsmotorn i sig är 2d. Det faktum att 3d-uppsättningar görs genom att plotta en 2d-bit efter den andra innebär att det ofta finns problem som är relaterade till objektets tydliga djup. Kärnan i problemet är att två icke-anslutna objekt antingen kan vara helt bakom eller helt framför varandra, vilket leder till artefakter som visas i figuren nedan för två sammanlänkade ringar (klicka för animerad gif):
Detta kan dock fixas. Denna artefakt existerar endast när man plottar flera ytor på samma tomt - eftersom var och en görs som en platt 2D-form, med en enda parameter som bestämmer visningsavståndet. Du kommer att märka att en enda komplicerad yta inte lider av samma problem.
Sättet att åtgärda detta är att sammanfoga plotobjekten tillsammans med transparenta broar:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from scipy.special import erf
fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(0, 6, 0.25)
Y = np.arange(0, 6, 0.25)
X, Y = np.meshgrid(X, Y)
Z1 = np.empty_like(X)
Z2 = np.empty_like(X)
C1 = np.empty_like(X, dtype=object)
C2 = np.empty_like(X, dtype=object)
for i in range(len(X)):
for j in range(len(X[0])):
z1 = 0.5*(erf((X[i,j]+Y[i,j]-4.5)*0.5)+1)
z2 = 0.5*(erf((-X[i,j]-Y[i,j]+4.5)*0.5)+1)
Z1[i,j] = z1
Z2[i,j] = z2
# If you want to grab a colour from a matplotlib cmap function,
# you need to give it a number between 0 and 1. z1 and z2 are
# already in this range, so it just works as is.
C1[i,j] = plt.get_cmap("Oranges")(z1)
C2[i,j] = plt.get_cmap("Blues")(z2)
# Create a transparent bridge region
X_bridge = np.vstack([X[-1,:],X[-1,:]])
Y_bridge = np.vstack([Y[-1,:],Y[-1,:]])
Z_bridge = np.vstack([Z1[-1,:],Z2[-1,:]])
color_bridge = np.empty_like(Z_bridge, dtype=object)
color_bridge.fill((1,1,1,0)) # RGBA colour, onlt the last component matters - it represents the alpha / opacity.
# Join the two surfaces flipping one of them (using also the bridge)
X_full = np.vstack([X, X_bridge, np.flipud(X)])
Y_full = np.vstack([Y, Y_bridge, np.flipud(Y)])
Z_full = np.vstack([Z1, Z_bridge, np.flipud(Z2)])
color_full = np.vstack([C1, color_bridge, np.flipud(C2)])
surf_full = ax.plot_surface(X_full, Y_full, Z_full, rstride=1, cstride=1,
facecolors=color_full, linewidth=0,
antialiased=False)
plt.show()
Skapa tredimensionella axlar
Matplotlib-axlar är som standard tvådimensionella. För att skapa tredimensionella tomter måste vi importera Axes3D
klassen från mplot3d-verktygssatsen , som möjliggör en ny typ av projektion för en axel, nämligen '3d'
:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
Förutom de enkla generaliseringarna av tvådimensionella tomter (såsom linjeplottor , spridningsdiagram , stavdiagram , konturdiagram ) finns flera ytplottningsmetoder tillgängliga, till exempel ax.plot_surface
:
# generate example data
import numpy as np
x,y = np.meshgrid(np.linspace(-1,1,15),np.linspace(-1,1,15))
z = np.cos(x*np.pi)*np.sin(y*np.pi)
# actual plotting example
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# rstride and cstride are row and column stride (step size)
ax.plot_surface(x,y,z,rstride=1,cstride=1,cmap='hot')
ax.set_xlabel(r'$x$')
ax.set_ylabel(r'$y$')
ax.set_zlabel(r'$\cos(\pi x) \sin(\pi y)$')
plt.show()