mplot3d Blickwinkel#

Wie der Blickwinkel definiert wird#

Die Position der "Kamera" im Ansichtsfenster eines 3D-Plots wird durch drei Winkel definiert: *Elevation*, *Azimut* und *Roll*. Von der resultierenden Position aus blickt sie immer auf das Zentrum des Plotvolumens. Die Winkelrichtung ist eine gängige Konvention und wird mit PyVista und MATLAB geteilt. Beachten Sie, dass ein positiver Rollwinkel die Bildebene im Uhrzeigersinn dreht, sodass sich die 3D-Achsen gegen den Uhrzeigersinn zu drehen scheinen.

../../../_images/mplot3d_view_angles.png

Das Drehen des Plots mit der Maus steuert Azimut, Elevation und Roll, und alle drei Winkel können programmatisch eingestellt werden.

import matplotlib.pyplot as plt
ax = plt.figure().add_subplot(projection='3d')
ax.view_init(elev=30, azim=45, roll=15)

Primäre Ansichtsebenen#

Um direkt auf die primären Ansichtsebenen zu blicken, sind die erforderlichen Winkel für Elevation, Azimut und Roll im folgenden Diagramm eines "entfalteten" Plots dargestellt. Diese sind weiter in der API von mplot3d.axes3d.Axes3D.view_init dokumentiert.

(Quellcode, 2x.png, png)

Rotation mit der Maus#

3D-Plots können durch Ziehen mit der Maus neu ausgerichtet werden. Es gibt verschiedene Möglichkeiten, dies zu erreichen. Der Stil der Mausrotation kann durch Setzen von rcParams["axes3d.mouserotationstyle"] (Standard: 'arcball') festgelegt werden; siehe Matplotlib mit Style-Sheets und rcParams anpassen.

Vor v3.10 entsprach die 2D-Mausposition direkt Azimut und Elevation; so geschieht es auch in MATLAB. Um dies beizubehalten, setzen Sie mouserotationstyle: azel. Dieser Ansatz funktioniert gut für sphärische Plots, bei denen die *z*-Achse speziell behandelt wird; er führt jedoch zu einer Art "Gimbal Lock", wenn man entlang der *z*-Achse blickt: Der Plot reagiert je nach aktueller Ausrichtung unterschiedlich auf Mausbewegungen. Außerdem kann "Roll" nicht gesteuert werden.

Alternativ gibt es verschiedene Mausrotationsstile, bei denen die Maus einen virtuellen "Trackball" bedient. In seiner einfachsten Form (mouserotationstyle: trackball) dreht sich der Trackball um eine ebene Achse senkrecht zur Mausbewegung (es ist, als ob eine Platte auf dem Trackball liegt; die Platte selbst hat eine feste Ausrichtung, aber Sie können die Platte mit der Maus ziehen und so die Kugel drehen). Dies ist praktischer zu handhaben als der azel-Stil. Allerdings kann der Plot nicht einfach entlang der Blickrichtung gedreht werden – man muss die Maus entgegen der gewünschten Drehrichtung in Kreisen bewegen, was kontraintuitiv ist.

Eine andere Variante des Trackballs dreht sich entlang des kürzesten Bogens auf der virtuellen Kugel (mouserotationstyle: sphere). Die Drehung entlang der Blickrichtung ist damit einfach: Greifen Sie die Kugel nahe am Rand statt nahe am Zentrum.

Ken Shoemakes ARCBALL [Shoemake1992] ist ebenfalls verfügbar (mouserotationstyle: Shoemake); er ähnelt dem sphere-Stil, ist aber frei von Hysterese, d.h. wenn die Maus an die ursprüngliche Position zurückkehrt, kehrt auch die Figur zur ursprünglichen Ausrichtung zurück; die Drehung ist unabhängig von den Details des Mauspfads, was wünschenswert sein kann. Allerdings dreht sich Shoemakes Arcball mit doppelter Winkelgeschwindigkeit der Mausbewegung (was besonders bei der Einstellung von Roll auffällt) und hat kein offensichtliches mechanisches Äquivalent; die pfadunabhängige Drehung ist wohl nicht natürlich (wenn auch praktisch) und erfordert gewöhnung. Es ist also ein Kompromiss.

Henriksen et al. [Henriksen2002] bieten einen Überblick. Zusammenfassend

Stil

traditionell [1]

inkl. Roll [2]

einheitlich [3]

pfadunabhängig [4]

mechanisches Gegenstück [5]

azel

✔️

✔️

✔️

trackball

[6]

✔️

✔️

sphere

✔️

✔️

✔️

arcball

✔️

✔️

✔️

Sie können einen der verschiedenen Mausrotationsstile ausprobieren, indem Sie

import matplotlib as mpl
mpl.rcParams['axes3d.mouserotationstyle'] = 'trackball'  # 'azel', 'trackball', 'sphere', or 'arcball'

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm

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

X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)

surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)

plt.show()

Alternativ können Sie eine Datei matplotlibrc mit folgendem Inhalt erstellen:

axes3d.mouserotationstyle: trackball

(oder einem der anderen Stile anstelle von trackball), und dann eines der 3D-Plotting-Beispiele ausführen.

Die Größe des virtuellen Trackballs, der Sphäre oder des Arcballs kann durch Setzen von rcParams["axes3d.trackballsize"] (Standard: 0.667) angepasst werden. Dies gibt an, wie viel Mausbewegung erforderlich ist, um einen bestimmten Drehwinkel zu erzielen (in der Nähe des Zentrums), und es bestimmt, wo sich der Rand der Sphäre oder des Arcballs befindet (wie weit vom Zentrum entfernt, also wie nah am Plotrand). Die Größe wird in Einheiten der Achsenbegrenzungsbox angegeben, d.h. um den Arcball über die gesamte Begrenzungsbox spannen zu lassen, setzen Sie ihn auf 1. Eine Größe von etwa 2/3 scheint vernünftig zu funktionieren; dies ist der Standard.

Sowohl Arcballs (mouserotationstyle: sphere und mouserotationstyle: arcball) haben einen wahrnehmbaren Rand; der Rand kann durch Angabe einer Randbreite, rcParams["axes3d.trackballborder"] (Standard: 0.2), weniger abrupt gemacht werden. Dies funktioniert ähnlich wie Gavin Bells Arcball, der ursprünglich für OpenGL [Bell1988] geschrieben wurde und in Blender und Meshlab verwendet wird. Bells Arcball erweitert die sphärische Kontrollfläche des Arcballs um eine Hyperbel; die beiden sind glatt verbunden. Die Hyperbel erstreckt sich jedoch bis über den Rand des Plots hinaus. Im mplot3d Sphere- und Arcball-Stil erstreckt sich der Rand bis zu einem Radius von trackballsize/2 + trackballborder. Jenseits des Rands funktioniert der Stil wie ursprünglich: er steuert nur den Roll. Eine Randbreite von etwa 0,2 scheint gut zu funktionieren; dies ist der Standard. Um den ursprünglichen Shoemake-Arcball mit einem scharfen Rand zu erhalten, setzen Sie die Randbreite auf 0. Für einen erweiterten Rand, ähnlich Bells Arcball, bei dem der Übergang vom Arcball zum Rand bei 45° stattfindet, setzen Sie die Randbreite auf \(\sqrt 2 \approx 1.414\). Der Rand ist ein Kreisbogen, der zylindrisch (wie ein Donut) um die Arcball-Kugel gewickelt ist und glatt mit der Kugel verbunden ist, ähnlich wie bei Bells Hyperbel.

[Shoemake1992]

Ken Shoemake, "ARCBALL: A user interface for specifying three-dimensional rotation using a mouse", in Proceedings of Graphics Interface '92, 1992, pp. 151-156, https://doi.org/10.20380/GI1992.18

[Bell1988]

Gavin Bell, in den Beispielen der GLUT (OpenGL Utility Toolkit) Bibliothek, markkilgard/glut

[Henriksen2002]

Knud Henriksen, Jon Sporring, Kasper Hornbæk, "Virtual Trackballs Revisited", in IEEE Transactions on Visualization and Computer Graphics, Volume 10, Issue 2, März-April 2004, S. 206-216, https://doi.org/10.1109/TVCG.2004.1260772 [Volltext];