Zoeken…


Opmerkingen

Driedimensionaal plotten in matplotlib is van oudsher een beetje een kludge, omdat de rendering-engine inherent 2d is. Het feit dat 3D-instellingen worden weergegeven door het ene deel na het andere uit te zetten, impliceert dat er vaak weergaveproblemen zijn met betrekking tot de schijnbare diepte van objecten. De kern van het probleem is dat twee niet-verbonden objecten zich volledig achter elkaar of volledig voor elkaar kunnen bevinden, wat leidt tot artefacten zoals weergegeven in de onderstaande afbeelding van twee met elkaar verbonden ringen (klik voor geanimeerde gif):

3d plot van twee met elkaar verbonden ringen die artefact tonen

Dit kan echter worden opgelost. Dit artefact bestaat alleen bij het plotten van meerdere oppervlakken op dezelfde plot - omdat elk wordt weergegeven als een platte 2D-vorm, met een enkele parameter die de kijkafstand bepaalt. U zult merken dat een enkel gecompliceerd oppervlak niet hetzelfde probleem ondervindt.

De manier om dit te verhelpen is om de plotobjecten samen te voegen met behulp van transparante bruggen:

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()

Twee oppervlakken kruisen elkaar voer hier de afbeeldingsbeschrijving in

Driedimensionale assen maken

Matplotlib-assen zijn standaard tweedimensionaal. Om driedimensionale plots te maken, moeten we de Axes3D klasse importeren uit de mplot3d-toolkit , die een nieuw soort projectie voor een assen mogelijk maakt, namelijk '3d' :

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

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

Naast de eenvoudige generalisaties tweedimensionale plots (zoals lijngrafieken , spreidingsdiagrammen , staafdiagrammen , contourplots ), verschillende oppervlakte plotten werkwijzen zijn bijvoorbeeld 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()

Axes3D met oppervlakte plot



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow