Ricerca…


Osservazioni

Il plottaggio tridimensionale in matplotlib è stato storicamente un po 'un kludge, in quanto il motore di rendering è intrinsecamente 2d. Il fatto che le configurazioni 3d siano renderizzate tracciando un blocco 2d dopo l'altro implica che spesso ci sono problemi di rendering relativi alla profondità apparente degli oggetti. Il nocciolo del problema è che due oggetti non connessi possono essere completamente dietro, o completamente uno di fronte all'altro, il che porta a artefatti come mostrato nella figura sottostante di due anelli interbloccati (fare clic per le GIF animate):

Trama 3D di due anelli interconnessi che mostrano artefatto

Questo può tuttavia essere risolto. Questo artefatto esiste solo quando si tracciano più superfici sullo stesso grafico, poiché ciascuna viene rappresentata come una forma 2D piatta, con un singolo parametro che determina la distanza di visualizzazione. Noterai che una singola superficie complicata non ha lo stesso problema.

Il modo per ovviare a questo è unire gli oggetti della trama usando ponti trasparenti:

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

Due superfici che si incrociano l'una con l'altra inserisci la descrizione dell'immagine qui

Creazione di assi tridimensionali

Gli assi Matplotlib sono bidimensionali per impostazione predefinita. Per creare grafici tridimensionali, dobbiamo importare la classe Axes3D dal toolkit mplot3d , che abiliterà un nuovo tipo di proiezione per un asse, ovvero '3d' :

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

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

Oltre alle generalizzazioni dirette di grafici bidimensionali (come grafici a linee , grafici a dispersione , grafici a barre , grafici di contorno ), sono disponibili diversi metodi di tracciatura superficiale , ad esempio 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 con trama di superficie



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow