Looking for matplotlib Keywords? Try Ask4Keywords

matplotlibTracés en trois dimensions


Remarques

Le traçage tridimensionnel dans matplotlib a toujours été un peu compliqué, car le moteur de rendu est intrinsèquement 2d. Le fait que les configurations 3D soient rendues en traçant un segment 2d après l'autre implique que les problèmes liés à la profondeur apparente des objets sont souvent rendus . Le cœur du problème est que deux objets non connectés peuvent être soit complètement en arrière, soit complètement l'un en face de l'autre, ce qui conduit à des artefacts comme le montre la figure ci-dessous de deux anneaux entrelacés (cliquez pour gif animé):

Tracé 3D de deux anneaux entrelacés montrant un artefact

Cela peut cependant être corrigé. Cet artefact n'existe que lors du traçage de plusieurs surfaces sur le même tracé, chacune étant représentée sous la forme d'une forme 2D plate, avec un seul paramètre déterminant la distance de vue. Vous remarquerez qu'une seule surface compliquée ne souffre pas du même problème.

La manière de remédier à cela consiste à joindre les objets du tracé en utilisant des ponts transparents:

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

Deux surfaces se croisant entrer la description de l'image ici

Tracés en trois dimensions Exemples Liés