3D-Grafiken

Block 9

Einfache 3D-Grafiken

Zum Schluss beschäftigen wir uns noch einmal mit Grafiken. Bisher haben wir nur ebene Darstellungen erstellt. Python bietet dir auch die Möglichkeit 3D-Darstellungen zu erstellen. Wie in 2 Dimensionen basieren auch hier die Darstellungen auf einzelnen Punkten. Die wichtigsten Befehle werden wir im Folgenden anschauen.

Ein Achsen-Objekt erstellen

Die Befehle für 3D-Grafiken sind nicht in Pylab integriert. Um sie zu verwenden, musst du deshalb ein zusätzliches Paket importieren. Ausserdem musst du die Objekt-Syntax verwenden.

Zur Erinnerung: Bisher haben wir beim Erstellen von Grafiken jeweils Pylab die Objekte verwalten lassen. Pylab merkt sich ob bereits ein Grafikfenster und ein Achsenobjekt besteht. Falls nötig wird ein neues Objekt erstellt. Führst du einen Grafik-Befehl aus, wählt Pylab dann automatisch die Plot-Methode des jüngsten Achsenobjekts. So ist plot eigentlich eine Methode der Achsenobjekte und auch figure() erzeugt ein eigenes Objekt.

Um eine 3D-Grafik zu erstellen, musst du als erstes ein 3D-Achsenobjekt erzeugen.

from mpl_toolkits.mplot3d import Axes3D Axes3D(figure())

Anschliessend kannst du plot wie gewohnt verwenden.

x = rand(20) y = rand(20) plot(x,y,x+y)

Du siehst, wieder wird für jedes i jeweils ein Punkt am Ort (xi,yi,xi+yi) gezeichnet.

Das Beispiel oben funktioniert und hat die gleiche Struktur wie für ein 2D-Plot. Leider kannst du so aber nicht auf alle 3D-Fähigkeiten zugreifen. Dafür musst du das Achsenobjekt einer Variable zuweisen. Jetzt musst du aber 3D-Achsen erstellen.

from pylab import * from mpl_toolkits.mplot3d import Axes3D fig = figure() ax = Axes3D(fig) x = rand(20) y = rand(20) ax.plot(x, y, x+y, '.') ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') show()

Hinweis: Das Beispiel oben sollte problemlos funktionieren, wenn du es als Skript ausführst. In einer interaktiven Session kann es sein, dass das Grafikfenster nicht aktualisiert wird. In dem Fall, meldest du dich am besten bei uns.

Aufgabe 1

t=frange(0,12*pi,pi/36) plot(cos(t),sin(t))

Der Befehl oben zeichnet einen Kreis.

  1. Verwandle den Kreis in eine Helix, in dem du eine passende z-Komponente hinzufügst
  2. Passe den Code so an, dass aus der Helix ein Wirbel wird, der nach unten immer enger wird.

Zeichne alle Plots gleichzeitig aber in verschiedene Grafik-Fenster. Dabei könnte eine Hilfsfunktion nützlich sein.

Hinweis: Mit der Maus kannst du die Grafik drehen um sie besser anschauen zu können.

Lösung anzeigen

from pylab import * from mpl_toolkits.mplot3d import Axes3D def plot3d(x,y,z): ax = Axes3D(figure()) ax.plot(x, y, z) t=frange(0,12*pi,pi/36) plot3d(cos(t),sin(t),t) plot3d(cos(t)*t**2,sin(t),t) plot3d(cos(t)*t**2,sin(t)*t**2,t) show() # Das sind bloss Beispiele, es gibt diverse Möglichkeiten.

Flächen darstellen

Oft wirst du 3D-Grafiken verwenden, weil du eine Funktion z = f(x,y) darstellen möchtest. Dafür brauchst du ein Koordinatenpaar für jeden Punkt der Grundfläche.

ax = Axes3D(figure()) X = array([0, 1, 2, 0, 1, 2, 0, 1, 2]) Y = array([0, 0, 0, 1, 1, 1, 2, 2, 2]) ax.plot(X,Y,X+Y, '+')

Du bekommst 9 Punkte die eine schiefe Ebene bilden. Es ist wichtig, dass du diese Befehle verstehst. Überlege dir deshalb, was genau passiert. Wie lautet der Befehl um den Punkt in der Mitte der Ebene rot zu übermalen?

Arrays wie X und Y oben einzugeben kann schnell mühsam werden. Der Befehl X, Y = meshgrid(x, y) vereinfacht diese Aufgabe. Sind x und y zwei 1d-Arrays mit Punkten entlang dieser Achsen, so gibt dir meshgrid(x,y) zwei Arrays mit allen Punkten damit aufgespannten Ebene zurück. Leider erwartet plot dann wieder 1d-Arrays. Die nötige Umwandlung erledigst du am einfachsten mit ravel() oder X.reshape(-1).

from pylab import * from mpl_toolkits.mplot3d import Axes3D ax = Axes3D(figure()) x = frange(1,10,0.5) y = x X, Y = meshgrid(x,y) print("X", X) print("Y", Y) ax.plot(ravel(X),ravel(Y),ravel(X+Y), '+') show()

Zum Glück werden wir plot selten verwenden. Denn eigentlich möchten wir eine richtige Fläche und nicht bloss Punkte. Dafür kannst du plot_wireframe(X,Y,X+Y) oder plot_surface(X,Y,X+Y) verwenden. Dies Befehle verstehen auch 2D-Arrays, so dass du Rückgabewerte von meshgrid direkt verwenden kannst. Das folgende Beispiel zeigt dir auch gleich, wie du für 3D-Darstellungen Subplots erstellst.

from pylab import * from mpl_toolkits.mplot3d import Axes3D import matplotlib.cm as cm # NEU! fig = figure() ax1 = fig.add_subplot(1,2,1, projection='3d') ax2 = fig.add_subplot(1,2,2, projection='3d') x = frange(1,10,0.5) X, Y = meshgrid(x,x) ax1.plot_wireframe(X,Y,X+Y) surf = ax2.plot_surface(X,Y,X+Y, cmap=cm.jet, cstride=1, rstride=1, linewidth=0) fig.colorbar(surf) show()

Worin unterscheiden sich die beiden Befehle? Was machen die weiteren Argumente zu plot_surface? Passe sie an und schaue was passiert. Weitere Möglichkeiten für cmap findest du in der Hilfe.

Aufgabe 2

Erstelle eine Grafik der folgenden Funktion
f(x,y) = x2 + y2
Verwende für die 3D-Darstellung sowohl plot_wireframe als auch plot_surface. Zeichne zudem einen Subplot mit Höhenlinien. (Dafür brauchst du den den Befehl contour.)

Lösung anzeigen

from pylab import * from mpl_toolkits.mplot3d import Axes3D import matplotlib.cm as cm x=arange(-10,10) X,Y=meshgrid(x,x) f1=X**2+Y**2 rows=1 cols=3 fig = figure() ax = [] ax.append(fig.add_subplot(rows,cols,1, projection='3d')) wire = ax[0].plot_wireframe(X,Y,f1) ax.append(fig.add_subplot(rows,cols,2, projection='3d')) surf = ax[1].plot_surface(X,Y,f1, cmap=cm.jet, cstride=1, rstride=1, linewidth=0) fig.colorbar(surf) ax.append(fig.add_subplot(rows,cols,3)) cont = ax[2].contour(X,Y,f1) fig.colorbar(cont) show()

Aufgaben zur Vertiefung

Funktionen in 3D

Erstelle möglichst informative Grafiken für folgende Funktionen
f(x,y) = x2 - y2
f(x,y) = sin(x/3)*cos(y/3)
Verwende für die 3D-Darstellung plot_wireframe, plot_surface und/oder contour. Versehe deine Plots mit Achsenbeschriftung und Titel.

Modul für 3D-Plots in Pylab Syntax

Die Datei tools3d.py enthält ein Python-Modul, das die Befehle wireframe und surface definiert. Mit diesen Befehlen kannst du auch 3D-Plots in gewohnter Pylab-Syntax erstellen.

Lade das Modul herunter und verwende pydoc und doctest um das Modul zu untersuchen. Verstehst du was die einzelnen Zeilen der Datei machen? Vereinfache schliesslich deine Lösung zur letzten Aufgabe mit dem neuen Modul.