Im letzten Block hast du gelernt, wie du ebene Darstellungen erstellst. Natürlich besteht 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 nun Anschauen.
plot3
funktioniert wie plot, akzeptiert aber 3 Koordinaten.
x = -10:10; y = 0:20; plot3(x,y,x+y)
Du siehst, wieder wird für jedes i jeweils ein Punkt am Ort (xi,yi,xi+yi) gezeichnet.
t=0:pi/36:12*pi; plot(cos(t),sin(t))
Der Befehl oben zeichnet einen Kreis.
Zeichne alle Plots gleichzeitig aber in verschiedene Grafik-Fenster.
Hinweis: Mit der Maus kannst du die Grafik drehen um sie besser anschauen zu können.
plot3(cos(t),sin(t),t) figure plot3(cos(t).*t.^2,sin(t),t) figure plot3(cos(t).*t.^2,sin(t).*t.^2,t) % Das sind bloss Beispiele, es gibt natürlich diverse Möglichkeiten.
Vielleicht hättest du erwartet, dass das erste Beispiel mehr Punkte in der ganzen Ebene zeichnet. Dafür müssten dein x und dein y aber für jeden Punkt der Grundfläche ein Koordinatenpaar enthalten.
X = [ 0 1 2 0 1 2 0 1 2 ]; Y = [ 0 0 0 1 1 1 2 2 2 ]; plot3(X,Y,X+Y, '+')
Du bekommst 9 Punkte die in einer Ebene liegen.
Solche Vektoren (oder Matrizen) einzugeben kann jedoch sehr mühsam werden.
Der Befehl [X Y] = meshgrid(xy)
löst dieses Problem für dich.
Sind x und z zwei Vektoren, so gibt dir meshgrid zwei Matrizen mit allen Kombinationen zurück.
x = [ 0 1 2 ]; y = x; [ X Y ] = meshgrid(x,y) X Y plot3(X,Y,X+Y, '+')
Noch sind wir aber nicht am Ziel. Denn eigentlich möchten wir eine richtige Fläche und nicht bloss Punkte. Dies ist mit plot nicht möglich. Du kannst aber die Befehle mesh oder surf verwenden.
mesh(X,Y,X+Y) figure surf(X,Y,X+Y) colorbar
Worin unterscheiden sich die beiden Befehle? Was macht colorbar?
Sind X und Y Matrizen wie du sie von Meshgrid bekommst und haben sie eine
Schrittlänge von 1, so kannst du sowohl bei bei mesh
wie
auch bei surf
die ersten beiden Argumente weglassen.
[X Y] = meshgrid(-10:10, -10:10) mesh(X+Y) colorbar
Erstelle von den folgenden Funktionen je eine Grafik
Verwende für die 3D-Darstellung sowohl mesh
als auch surf
.
Zeichne zudem für jede Funktion einen Subplot mit Höhenlinien.
Hinweis: Für die Höhenlinien brauchst du den den Befehl contour
.
x=-10:10; y=-10:10; [X,Y]=meshgrid(x,y); f1=X.^2+Y.^2; f2=X.^2-Y.^2; f3=sin(X/3).*cos(Y/3); rows=1; cols=3; figure subplot(rows, cols, 1) mesh(f1) subplot(rows, cols, 2) surf(f1) colorbar subplot(rows, cols, 3) contour(f1) figure subplot(rows, cols, 1) mesh(f2) subplot(rows, cols, 2) surf(f2) colorbar subplot(rows, cols, 3) contour(f2) figure subplot(rows, cols, 1) mesh(f3) subplot(rows, cols, 2) surf(f3) colorbar subplot(rows, cols, 3) contour(f3)
In der Lösung der letzten Aufgabe fällt auf, dass du drei beinahe identische Blöcke hast. Damit hast du wieder das Problem, dass eine kleine Anpassung Änderungen an diversen Stellen nach sich zieht. Natürlich lässt sich auch das vermeiden. Die einfachste Möglichkeit ist wohl eine eigene Funktion mit den nötigen Befehlen zu definieren.
Um eine Funktion zu definieren, musst du eine neue Datei erstellen. Die Datei muss den gleichen Namen haben wie deine Funktion. Als Beispiel erstellen wir eine Funktion, die zwei Zahlen nimmt und diese durch einander dividiert.
% Datei: myDiv.m function c = myDiv(a, b) c = a/b
Hinweis: Die Datei mit der Funktion muss sich natürlich an einem Ort befinden,
an dem sie auch gefunden wird. Am Besten wohl im aktiven Verzeichnis (pwd
).
Ausserdem solltest du aufpassen, dass du keine bestehende Funktion überschreibst.
Namen wie sin oder plot sind deshalb wohl keine gute Idee.
Nun wollen wir aber die Beispiel-Funktion etwas genauer anschauen.
Eine Funktion beginnt mit einer Zeile wie function c = myDiv(a, b)
.
Das Schlüsselwort function leitet eine Funktionsdefinition ein.
c gibt an welche Variable am Ende zurückgegeben werden soll.
Du könntest hier auch einen Vektor ([a b c]
) angeben oder ganz auf eine Rückgabe verzichten (ohne c =
).
myDiv ist dann der Funktionsname und muss wie gesagt mit dem Dateinamen identisch sein.
(a, b) sind schliesslich die Argumente, welche die Funktion erwartet.
Danach (a/b) folgen die Anweisungen die ausgeführt werden sollen.
In Octave kannst du das Ende einer Funktion wird mit endfunction markieren.
Das erhöht die Lesbarkeit, reduziert aber die Kompatibilität mit Matlab.
Um die Funktion nun aufzurufen tippst du einfach
myDiv(1, 2)
Passe Aufgabe 2 so an, dass der ganze Zeichenblock in eine Funktion verpackt ist und du diese einfach je für f1, f2 und f3 einmal aufrufst. Deine Funktion hat also keinen Rückgabewert.
% Datei: myPlot.m function myPlot(f) rows=1; cols=3; figure subplot(rows, cols, 1) mesh(f) subplot(rows, cols, 2) surf(f) colorbar subplot(rows, cols, 3) contour(f)
x=-10:10; y=-10:10; [X,Y]=meshgrid(x,y); f1=X.^2+Y.^2; f2=X.^2-Y.^2; f3=sin(X/3).*cos(Y/3); myPlot(f1) myPlot(f2) myPlot(f3)
Unsere Beispiel-Funktion myDiv hat ein Problem, wenn du sie mit b = 0 verwendest.
Auch sonst wird es wohl oft vorkommen, dass du unterschiedliche Befehle ausführen möchtest,
abhängig vom Wert einer Variable oder einer anderen Bedingung.
Dafür gibt es if-else
.
a = 1 if (a > 0) disp('positiv') elseif (a == 0) disp('null') else disp('negativ') end
Pass a und die Bedingungen an, bis du verstehst was wo passiert. Beachte besonders, dass du mit == auf Gleichheit testest. Mit = klappt das nicht.
Passe nun myDiv so an, dass du Division durch Null abfangen kannst. Gibt in dem Fall 0 zurück und zeige eine Fehlermeldung an.
% Datei: myDiv.m function c = myDiv(a, b) if (b == 0) c = 0; disp('Fehler: Division durch Null') else c = a/b; end
Welche der folgenden Bedingungen sind true
Schreibe jeweils einen if-Block um die Bedingung zu testen.
if (-1 < 0) disp('-1 < 0: true') end if (0 <= 0) disp('0 <= 0: true') end if (0 >= 0) disp('0 >= 0: true') end if (0 > 0) disp('0 < 0: true') end if (1 ~= 0) disp('1 ~= 0: true') end if (-1) disp('-1: true') end if (0) disp('0: true') end if (1) disp('1: true') end if (2) disp('2: true') end if ("hallo") disp('"hallo": true') end if (a = 1) disp('a=1: true') end if (1 == "1") disp('1=="1": true') end if ("foo" == "bar") disp('"foo"=="bar": true') end
In den Beispielen oben hast du gesehen, wie du mit disp
Text ausgeben kannst.
Mit disp
kannst du aber auch mehr als ein Text ausgeben.
Wenn du disp einen Vektor mit Strings (Zeichenketten) übergibst, werden diese aneinandergereiht
disp(['hallo', ' ', 'welt'])
Für komplexere Ausgaben gibt es zudem noch printf
und seine Varianten.
Wir werden auf diese Befehle hier aber nicht weiter eingehen.
Du findest mehr Infos zu ihnen in der Hilfe.
Mit der Eingabe von Werten sollten wir uns aber schon etwas beschäftigen. Ein ganz einfaches Beispiel könnte so aussehen
% dies muss in ein eigenes m-File a = input('a = ') b = input('b = ') disp('a+b =') myDiv(a,b)
Wenn du dieses m-File nun ausführst, wirst du nach a und b gefragt und bekommst dann a/b ausgegeben.
Programmiere in einem M-File folgende Quiz-Frage:
Wann war der erste Mensch auf dem Mond?
Eine mögliche Programmstruktur ist:
(Lösung der Quiz-Frage: 20. Juli 1969)
Hinweis: du kannst mehrere Dinge gleichzeitig testen, indem du die
einzelnen Tests mit &&
verknüpfst.
if (a == 1) && (b == 2)
t=20; m=7; j=69; disp('Wann war der erste Mensch auf dem Mond?') disp(' ') jahr=input('Geben Sie das Jahr [00..99] an. '); disp(' ') monat=input('Geben Sie den Monat [1..12] an. '); disp(' ') tag=input('Geben Sie den Tag [1..31] an. '); if (jahr == j) && (monat == m) && (tag == t) disp('Sie haben richtig geraten.') elseif (jahr == j) && (monat == m) && (tag ~= t) disp(['Das Jahr und der Monat sind',... 'zwar korrekt, aber nicht der Tag!']) elseif (jahr == j) && (monat ~= m) && (tag == t) disp(['Das Jahr und der Tag sind zwar',... 'korrekt, aber nicht der Monat!']) elseif (jahr ~= j) && (monat == m) && (tag == t) disp(['Der Monat und der Tag sind zwar',... 'korrekt, aber nicht das Jahr!']) elseif (jahr == j) && (monat ~= m) && (tag ~= t) disp('Nur das Jahr ist korrekt.') elseif (jahr ~= j) && (monat == m) && (tag ~= t) disp('Nur der Monat ist korrekt.') elseif (jahr ~= j) && (monat ~= m) && (tag == t) disp('Nur der Tag ist korrekt.') elseif (jahr ~= j) && (monat ~= m) && (tag ~= t) disp(['Hatten Sie in Geschichte einen',... 'Fensterplatz?']) end disp('Es war am 20. Juli 1969.')
Hinweis: Du siehst, dass ich Zeilen einrücke, wenn diese Teil einer Funktion oder eines (if-)Blockes sind. Das ist freiwillig, erhöht aber die Lesbarkeit und macht es damit deutlich einfacher Probleme zu finden. Du solltest dir das deshalb ebenfalls angewöhnen.