Wie bringt man 3D-Oberflächen (dreieckige Schnitte, Pfeile und Text) in einem Matplotlib-3D-Plot in den Vordergrund?Python

Python-Programme
Anonymous
 Wie bringt man 3D-Oberflächen (dreieckige Schnitte, Pfeile und Text) in einem Matplotlib-3D-Plot in den Vordergrund?

Post by Anonymous »

Ich versuche, die klassische HSV-Farbkegel-Matplotlib in Python zu reproduzieren.
Image
Die Idee ist, einen 3D-Kegel im HSV-Raum zu zeichnen, wobei zwei dreieckige Innenflächen entfernt werden, damit wir das Innere des Kegels sehen können.
Alles funktioniert gut, bis auf ein großes Problem:
Ich kann das nicht mitbringen dreieckige Flächen, Pfeile oder Beschriftungen (H, S, V) in den Vordergrund (vorne).
Sie erscheinen immer hinter der Kegeloberfläche, auch wenn ich die Zeichenreihenfolge, Zorder oder set_zsort('max') ändere.

Code: Select all

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import hsv_to_rgb

# --------- parameters ----------
theta_open = np.deg2rad(90)
theta0, theta1 = 0.0, 2*np.pi - theta_open
n_th, n_r = 15000, 20000

# --------- outer cone ----------
theta = np.linspace(theta0, theta1, n_th)
r = np.linspace(0, 1, n_r)
TH, R = np.meshgrid(theta, r)
Z = R
H = (TH % np.pi) / np.pi
S = R
V = Z
RGB = hsv_to_rgb(np.stack((H, S, V), axis=-1))
X = R*np.cos(TH)
Y = R*np.sin(TH)

fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z, facecolors=RGB, linewidth=0, antialiased=False)

# --------- top disk ----------
rt = np.linspace(0, 1, n_r)
th = np.linspace(theta0, theta1, n_th)
THt, Rt = np.meshgrid(th, rt)
Xt = Rt*np.cos(THt); Yt = Rt*np.sin(THt); Zt = np.ones_like(Rt)
Ht = (THt % np.pi) / np.pi; St = Rt; Vt = Zt
ax.plot_surface(Xt, Yt, Zt, facecolors=hsv_to_rgb(np.stack((Ht,St,Vt), axis=-1)),
linewidth=0, antialiased=False)

# --------- internal faces ----------
t = np.linspace(0, 1, n_r)
z = np.linspace(0, 1, n_r)
T, ZI = np.meshgrid(t, z)
Rface = T * ZI

def add_cut_face(theta_const):
Xc = Rface*np.cos(theta_const)
Yc = Rface*np.sin(theta_const)
Zc = ZI
Hc = np.full_like(Rface, (theta_const % np.pi) / np.pi)
Sc = Rface
Vc = ZI
ax.plot_surface(Xc, Yc, Zc,
facecolors=hsv_to_rgb(np.stack((Hc, Sc, Vc), axis=-1)),
edgecolor='none', antialiased=False)
ax.plot([0, np.cos(theta_const)], [0, np.sin(theta_const)], [0,1], 'k', lw=1.6)
ax.plot([0, np.cos(theta_const)], [0, np.sin(theta_const)], [0,0], 'k', lw=1.2)

add_cut_face(theta1)
add_cut_face(theta0)

# --------- axes & arrow ----------
phi = np.linspace(theta0, theta1, 400)
ax.plot(np.cos(phi), np.sin(phi), np.ones_like(phi), 'k', lw=1.0)
ax.plot([0,0],[0,0],[0,1], 'k', lw=2.0)
ax.plot([0,1.15],[0,0],[0,0], 'k', lw=2.0)

phi_arrow = np.linspace(theta0+0.15, theta1-0.35, 120)
ax.plot(0.65*np.cos(phi_arrow), 0.65*np.sin(phi_arrow), np.ones_like(phi_arrow)*1.03, 'k', lw=1.8)
pa = phi_arrow[-1]
ax.quiver(0.65*np.cos(pa), 0.65*np.sin(pa), 1.03,
-0.12*np.sin(pa), 0.12*np.cos(pa), 0,
length=1.0, normalize=False, color='k')

# --------- labels & view ----------
ax.text(0, 0, 1.16, 'V', fontsize=16, fontweight='bold')
ax.text(1.22, 0, 0, 'S', fontsize=16, fontweight='bold')
ax.text(0.15, 0.6, 1.07, 'H', fontsize=16, fontweight='bold')
ax.view_init(elev=25, azim=-55)
ax.set_box_aspect([1,1,1])
ax.axis('off')
plt.tight_layout()
plt.show()
Wie kann ich erzwingen, dass bestimmte Oberflächen, Pfeile und Texte in einem Matplotlib-3D-Plot immer vor allem anderen gerendert werden?
Gibt es eine zuverlässige Möglichkeit:
  • 3D-Oberflächen oben zu zeichnen (dreieckige Flächen),
  • Köcherpfeile und Beschriftungen zu erstellen immer sichtbar (nicht hinter dem Kegel versteckt),
  • oder den Z-Puffer / Tiefentest für bestimmte Elemente deaktivieren?

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post