If you're seeing this message, it means we're having trouble loading external resources on our website.

Wenn du hinter einem Webfilter bist, stelle sicher, dass die Domänen *. kastatic.org und *. kasandbox.org nicht blockiert sind.

Hauptinhalt

Einführung in die Vektoren

In diesem Kurs dreht sich alles darum uns die Welt um uns herum anzuschauen und clevere Ideen zu entwickeln wie man dies in Code abbilden kann. Wir beginnen mit der grundlegenden Physik, zum Beispiel wie ein Apfel vom Baum fällt, ein Pendel in der Luft schwingt, die Erde um die Sonne kreist, etc. Für alles was wir hier besprechen braucht man aber den Grundbaustein für die Programmierung von Bewegungen, den Vektor. Und hier beginnen wir nun unsere Geschichte.
Nun, das Wort Vektor bedeutet eigentlich viele verschiedene Dinge. Vektor ist der Name einer New-Wave-Rockband aus den frühen 1980ern aus Sacramento, Kalifornien. Es ist der Name von Frühstücksflocken von Kellog’s aus Kanada. Im Gebiet der Epidemiologie wird ein Organismus, der Infektionen von einem Träger zu anderen überträgt, Vektor genannt. In der Programmiersprache C++ ist ein Vektor (std::vector) die Implementierung einer Array-Datenstruktur welche ihre Größe dynamisch ändern kann. Zwar sind all diese Definitionen interessant, sie sind aber nicht das was wir uns hier anschauen. Was wir hier verwenden sind Euklidsche Vektoren (benannt nach dem griechischen Mathematiker Euklid und auch bekannt als geometrische Vektoren). Wenn du in diesem Kurs den Begriff “Vektor” siehst, kannst du davon ausgehen, dass damit ein Euklidscher Vektor gemeint ist, welcher als eine Größe mit Betrag und Richtung definiert wird.
Ein Vektor wird normalerweise als ein Pfeil gezeichnet, bei welchem die Richtung durch die Pfeilspitze und der Betrag durch die Länge des Pfeils angezeigt wird.
Ein Diagramm eines Vektors mit Länge und Richtung
Abbildung 1,1: Ein Vektor (als Pfeil gezeichnet) hat einen Betrag (Länge des Pfeils) und eine Richtung (wohin er zeigt).
In der obigen Abbildung ist der Vektor als Pfeil von Punkt A nach Punkt B gezeichnet und dient als eine Anleitung wie man von von A nach B reist.

Warum verwenden wir Vektoren?

Bevor wir mehr über Vektoren lernen, betrachten wir ein einfaches Programm, welches uns schön zeigt, weshalb wir mehr über Vektoren lernen müssen. Wenn du auf der Khan Academy den Einführungskurs zu JS gemacht hast, hast du wohl an einem Punkt gelernt ein Programm mit einem einfachen springenden Ball zu schreiben.
Im Beispiel oben sehen wir eine einfache Welt (ein weißes Canvas) in der sich eine runde Form (ein Ball) herumbewegt. Dieser Ball hat einige Eigenschaften, welche im Code als Variablen implementiert sind.
PositionGeschwindigkeit
x und yxSpeed und ySpeed
In einem komplizierteren Programm hätten wir wohl viele Variablen mehr:
BeschleinigungZielpositionWindungReibung
xacceleration und yaccelerationxtarget und ytargetxwind und ywindxfriction und yfriction
Man erkennt sehr schnell, dass wir für jedes Konzept dieser Welt (Wind, Position, Beschleunigung, etc.) zwei Variablen brauchen. Und dies ist erst eine zweidimensionale Welt. In einer 3D-Welt brauchen wir x, y, z, xSpeed, ySpeed, zSpeed, und so weiter.
Wäre es nicht schön, wenn wir unseren Code vereinfachen könnten und weniger Variablen bräuchten?
Anstatt:
var x = 5;
var y = 10;
var xSpeed;
var ySpeed;
bräuchten wir nur zwei Variablen, wobei jede Variable ein Vektor-Objekt mit Informationen in zwei Dimensionen ist.
var position;
var speed;
Dieser erste Schritt zur Verwendung von Vektoren bringt uns noch nicht viel weiter. Nur weil du Vektor-Objekte für deine Variablen verwendest, kann dein Programm noch lange nicht die Physik simulieren. Aber sie vereinfachen deinen Code und bieten dir eine Reihe von Funktionen für gängige mathematische Operationen an, welche du immer und immer wieder benötigst, wenn du Bewegungen programmieren willst.
Als Einführung in Vektoren werden wir nur in zwei Dimensionen leben. Alle diese Beispiele können ganz einfach auf drei Dimensionen erweitert werden. Das Objekt welches wir verwenden (PVector) unterstüzt sogar drei Dimensionen. Nur mit zwei Dimensionen zu beginnen macht den Einstieg aber einfacher.

Programmierung mit PVector

Eine Möglichkeit, dir einen Vektor vorzustellen, ist als Weg zwischen zwei Punkten. Stellt dir vor, wie du jemanden erklärst, von einem Punkt zum anderen zu laufen.
Hier findest du ein paar Vektoren und ihre Beschreibungen:
Diagramme von Vektoren
Abbildung 1,2
| (-15, 3) | Laufe fünfzehn Schritte nach Westen; drehe nach rechts und laufe drei Schritte nach Norden | | (3, 4) | Laufe drei Schritte nach Osten; drehe nach links und laufe vier Schritte nach Norden | | (2, -1) | Laufe zwei Schritte nach Osten; drehe nach rechts und laufe einen Schritt nach Süden |
Wenn du schon Bewegungen programmiert hast, hast du dies sehr wahrscheinlich schon früher gemacht. Für jeden Frame der Animation (d. h. einen Zyklus der draw()-Schleife von ProcessingJS) verschiebst du jedes Objekt auf dem Bildschirm um eine bestimmte Anzahl von Pixeln horizontal und um eine bestimmte Anzahl von Pixeln vertikal.
Diagramm, in welchem ein Vektor benutzt wird, um die neue Position zu bestimmen
Abbildung 1,3
Für jeden Frame:
neue Position = Geschwindigkeit angewandt auf den aktuellen Ort
Wenn Geschwindigkeit ein Vektor ist (die Differenz zwischen zwei Punkten), was ist dann die Position? Ist sie ebenfalls ein Vektor? Genau genommen könnte man sagen, dass die Position kein Vektor ist, da sie nicht beschreibt wie man von einem Punkt an einen anderen kommt. Sie beschreibt einfach einen Punkt im Raum.
Eine Position kann aber durch den Weg vom Ursprung an diese Position beschrieben werden. Daher kann eine Position ein Vektor sein, welcher die Differenz zwischen dem Ursprung und der Position beschreibt.
Diagramm, in welchem die Position als Vektor dargestellt wird
Abbildung 1,4
Betrachten wir nun die Daten welche sowohl der Position als auch der Geschwindigkeit zugrundeliegen. Im Beispiel mit dem springenden Ball hatten wir die folgenden:
PositionGeschwindigkeit
x und yxSpeed und ySpeed
Beachte, dass wir für beide die gleichen Daten speichern: zwei Dezimalzahlen, ein x und ein y. Wenn wir selbst eine Vektor-Klasse schreiben würden, würden wir mit sowas beginnen:
var Vector = function(x, y) {
    this.x = x;
    this.y = y;
};
Im Grunde ist PVector ein einfacher Weg zwei Werte zu speichern (oder drei, wie wir im 3D-Beispiel sehen werden).
Und so wird …
var x = 100;
var y = 100;
var xSpeed = 1;
var ySpeed = 3.3;
zu …
var position = new PVector(100,100);
var velocity = new PVector(1,3.3);
Nun da wir zwei Vektor-Objekte (position für Position und velocity für Geschwindigkeit) haben, können wir den Algorithmus für die Bewegung implementieren (position = position + velocity). Im Beispiel 1.1, ohne Vektoren, hatten wir:
x = x + xSpeed;
y = y + ySpeed;
In einer idealen Welt könnten wird dies nun so schreiben:
position = position + velocity;
In JavaScript ist der Additionsoperator + aber für einfache Werte (Zahlen und Strings) reserviert. In anderen Programmiersprachen können Operatoren "überladen" werden, leider nicht in JavaScript. Zum Glück enthält das PVector-Objekt praktische Methoden für gängige mathematische Operationen wie z. B. add().

Vektoraddition

Bevor wir uns das PVector-Objekt und seine Methode add() anschauen, wiederholen wir kurz die Vektoraddition wie man sie in Mathe- und Physikbüchern findet.
Vektoren werden üblicherweise fett oder mit einem Pfeil darüber geschrieben. In diesem Kurs wollen wir zum Unterscheiden von Vektoren von Skalaren (Skalare sind einfache Werte wie eine ganze oder Dezimalzahl) die Pfeil-Notation verwenden.
  • Vektor: u, with, vector, on top
  • Skalar: x
Nehmen wir an, dass ich die folgenden zwei Vektoren habe:
Diagramm zweier Vektoren
Abbildung 1,5
Jeder Vektor hat zwei Komponenten, ein x und ein y. Um zwei Vektoren zu addieren, addieren wir einfach beide x und beide y.
Abbildung 1,6
Mit anderen Worten:
w, with, vector, on top, equals, u, with, vector, on top, plus, v, with, vector, on top
auch geschrieben werden als:
wx=ux+vxwy=uy+vy \text{w}_x = \text{u}_x + \text{v}_x\\ \text{w}_y = \text{u}_y + \text{v}_y
Dann ersetzen wir u und v mit ihren Werten aus Abbildung 1,6 und wir erhalten:
wx=5+3wy=2+4 \text{w}_x = 5 + 3\\ \text{w}_y = 2 + 4
was bedeutet, dass:
wx=8wy=6 \text{w}_x = 8\\ \text{w}_y = 6
Und schlussendlich schreiben wir dies als Vektor:
w, with, vector, on top, equals, left parenthesis, 8, comma, 6, right parenthesis
Nun da wir verstehen wie zwei Vektoren addiert werden, können wir uns anschauen wie die Addition im Objekt PVector implementiert ist. Wir schreiben eine Methode add() welche als Parameter ein weiteres Objekt vom Typ PVector akzeptiert und einfach die Komponenten x und y addiert.
var Vector = function(x, y) {
    this.x = x;
    this.y = y;
};

Vector.prototype.add = function(v) {
  this.y = this.y + v.y;
  this.x = this.x + v.x;
};
Nun da wir sehen wie add() in PVector implementiert ist, können wir uns unser Beispiel vom springenden Ball mit seinem Algorithmus position + velocity nochmals anschauen und als Vektoraddition implementieren.
position.add(velocity);
Und schon haben wir das Beispiel vom springenden Ball mit PVector umgeschrieben! Schau dir den Code and und beachte die Unterschiede.
Wir müssen einen wichtigen Punkt beim Umstieg auf die Programmierung mit Vektoren beachten. Obwohl wir das Objekt PVector zum Beschreiben von zwei Werten (x und y für Position und x und y für Geschwindigkeit) verwenden, müssen wir immer wieder auf die Komponenten x und y von jedem PVector direkt zugreifen. Wenn wir ein Objekt in ProcessingJS darstellen, gibt es keine Möglichkeit dies so zu Programmieren:
ellipse(position, 16, 16);
Die Funktion ellipse() akzeptiert kein Argument vom Typ PVector. Eine Ellipse kann nur mit zwei Skalarwerten, einer x-Koordinate und einer y-Koordinate, gezeichnet werden. Daher müssen wir ins PVector-Objekt eintauchen und die Komponenten x und y mit der Punktnotation aus der objektorientierten Programmierung herausholen:
ellipse(position.x, position.y, 16, 16);
Das gleiche Problem stellt sich, wenn wir prüfen wollen, ob der Kreis mit dem Rand des Fensters kollidiert. Wir müssen auf die Komponenten von beiden Vektoren zugreifen: position und velocity.
if ((position.x > width) || (position.x < 0)) {
  velocity.x = velocity.x * -1;
}
Nun magst du vielleicht etwas enttäuscht sein. Nach dem Umstieg zu Vektoren erscheint der Code jetzt viel komplizierter als vorher. Obwohl dies ein vernünftiger und gültiger Einwand ist, musst du beachten, dass wir noch nicht alle Möglichkeiten und Vorteile der Programmierung mit Vektoren gelernt haben. Das Beispiel des springenden Balls anzuschauen und die Vektoraddition zu implementieren ist erst der erste Schritt.
Wenn wir tiefer in die komplexe Welt von mehreren Objekten und Kräften (welche wir schon bald lernen) eintauchen, wirst du die Vorteile von PVector sehr schnell erkennen.

Der Kurs "Natürliche Simulationen" ist eine Bearbeitung von "The Nature of Code" von Daniel Shiffman, und wird unter der Creative Commons Attribution-NonCommercial 3,0 Unported Lizenz verwendet.