Berechnung des Kreuzprodukts eines 2D-Vektors

85

Aus Wikipedia:

Das Kreuzprodukt ist eine binäre Operation an zwei Vektoren in einem dreidimensionalen euklidischen Raum, die zu einem anderen Vektor führt, der senkrecht zu der Ebene ist, die die beiden Eingabevektoren enthält.

Wie berechnet man das Kreuzprodukt zweier 2d-Vektoren , da die Definition nur in drei ( oder sieben, eins und null ) Dimensionen definiert ist?

Ich habe zwei Implementierungen gesehen. Einer gibt einen neuen Vektor zurück (akzeptiert aber nur einen einzelnen Vektor), der andere gibt einen Skalar zurück (ist jedoch eine Berechnung zwischen zwei Vektoren).

Implementierung 1 (gibt einen Skalar zurück):

float CrossProduct(const Vector2D & v1, const Vector2D & v2) const
{
    return (v1.X*v2.Y) - (v1.Y*v2.X);
}

Implementierung 2 (gibt einen Vektor zurück):

Vector2D CrossProduct(const Vector2D & v) const
{
    return Vector2D(v.Y, -v.X);
}

Warum die unterschiedlichen Implementierungen? Wofür würde ich die skalare Implementierung verwenden? Wofür würde ich die Vektorimplementierung verwenden?

Der Grund, den ich frage, ist, dass ich selbst eine Vector2D-Klasse schreibe und nicht weiß, welche Methode ich verwenden soll.

Zack der Mensch
quelle
10
Implementierung 2 ist falsch. Sie benötigen zwei Vektoren, um ein Kreuzprodukt zu bilden.
Bobobobo
7
Implementierung 2 dreht den gegebenen Vektor v um -90 Grad. Ersetzen Sie -90 in x' = x cos θ - y sin θund y' = x sin θ + y cos θ. Eine andere Variation dieser Implementierung wäre, v um +90 Grad zu return Vector2D(-v.Y, v.X);drehen .
Legends2k
3
@ legends2k: Es ist anzumerken, dass Implementierung 2 eine Erweiterung der Verwendung der Determinante zur Bewertung des Kreuzprodukts ist : Entfernen Sie einfach die letzte Zeile und Spalte. Eine solche Erweiterung hat immer N-1Operanden für NDimensionen.
Tim
4
Implementierung 1 berechnet die Größe des Kreuzprodukts.
Mateen Ulhaq
@MateenUlhaq Art, es ist die " signierte Größe"
Moritz Mahringer

Antworten:

100

Implementierung 1 gibt die Größe des Vektors zurück, die sich aus einem regulären 3D-Kreuzprodukt der Eingabevektoren ergeben würde, wobei ihre Z-Werte implizit als 0 angenommen werden (dh der 2D-Raum als Ebene im 3D-Raum behandelt wird). Das 3D-Kreuzprodukt ist senkrecht zu dieser Ebene und hat somit 0 X & Y-Komponenten (daher ist der zurückgegebene Skalar der Z-Wert des 3D-Kreuzproduktvektors).

Es ist zu beachten, dass die Größe des aus dem 3D-Kreuzprodukt resultierenden Vektors auch gleich der Fläche des Parallelogramms zwischen den beiden Vektoren ist, was Implementierung 1 einen weiteren Zweck gibt. Außerdem ist dieser Bereich signiert und kann verwendet werden, um zu bestimmen, ob sich die Drehung von V1 nach V2 gegen den Uhrzeigersinn oder im Uhrzeigersinn bewegt. Es sollte auch beachtet werden, dass die Implementierung 1 die Determinante der 2x2-Matrix ist, die aus diesen beiden Vektoren aufgebaut ist.

Implementierung 2 gibt einen Vektor senkrecht zum Eingabevektor zurück, der sich noch in derselben 2D-Ebene befindet. Kein Kreuzprodukt im klassischen Sinne, aber konsistent im Sinne von "Gib mir einen senkrechten Vektor".

Beachten Sie, dass der euklidische 3D-Raum unter der Kreuzproduktoperation geschlossen ist - das heißt, ein Kreuzprodukt aus zwei 3D-Vektoren gibt einen anderen 3D-Vektor zurück. Beide oben genannten 2D-Implementierungen stimmen auf die eine oder andere Weise nicht mit diesen überein.

Hoffe das hilft...

Drew Hall
quelle
6
Tatsächlich ist die Implementierung 2 ein Kreuzprodukt von v und dem Einheitsvektor, der in die z-Richtung zeigt.
Mattiast
@ Mattiast: Stimmt. Genau so wird die 2D-Perp-Operation in 3D beschrieben.
Drew Hall
@mattiast: Implementierung 2 kann als Erweiterung der Verwendung einer Determinante zur Berechnung des Kreuzprodukts angesehen werden - entfernen Sie einfach die letzte Zeile und Spalte. Es sollte beachtet werden, dass Implementierung 1 äquivalent zu: ist DotProduct(a, CrossProduct(b)), was (sehr elegant!) Mit dem Begriff eines "senkrechten Punktprodukts" übereinstimmt (was diese Implementierung 1 auch [und vielleicht genauer] genannt wird!).
Tim
In Ihrem ersten Absatz ist die Größe der absolute Wert der zurückgegebenen Daten. Es ist nicht ganz dasselbe wie die Z-Komponente. Wie Sie im 2. Absatz hervorheben, können Sie das Vorzeichen des Kreuzes verwenden, um Vampire abzuwehren ... ähm, ich meine, um zu erkennen, wann ein Vektor verlässt, oder um beispielsweise den Umriss eines Polygons zu betreten.
Peter Cordes
68

Kurz gesagt: Es ist eine Kurzschreibweise für einen mathematischen Hack.

Lange Erklärung:

Sie können kein Kreuzprodukt mit Vektoren im 2D-Raum erstellen. Die Operation ist dort nicht definiert.

Oft ist es jedoch interessant, das Kreuzprodukt zweier Vektoren unter der Annahme zu bewerten, dass die 2D-Vektoren durch Setzen ihrer Z-Koordinate auf Null auf 3D erweitert werden. Dies entspricht der Arbeit mit 3D-Vektoren in der xy-Ebene.

Wenn Sie die Vektoren auf diese Weise erweitern und das Kreuzprodukt eines solchen erweiterten Vektorpaars berechnen, werden Sie feststellen, dass nur die z-Komponente einen aussagekräftigen Wert hat: x und y sind immer Null.

Aus diesem Grund wird die Z-Komponente des Ergebnisses häufig einfach als Skalar zurückgegeben. Dieser Skalar kann zum Beispiel verwendet werden, um die Wicklung von drei Punkten im 2D-Raum zu finden.

Aus rein mathematischer Sicht existiert das Kreuzprodukt im 2D-Raum nicht, die skalare Version ist der Hack und ein 2D-Kreuzprodukt, das einen 2D-Vektor zurückgibt, macht überhaupt keinen Sinn.

Nils Pipenbrinck
quelle
"Zum Beispiel, um die Wicklung von drei Punkten im 2D-Raum zu finden" @Nils Pipenbrinck, was meinst du mit Wicklung in diesem Zusammenhang?
Nader Belal
1
@NaderBelal Ich nehme an, das Wickeln hier würde bedeuten - wenn wir von Punkt a nach b nach c gehen, werden wir in Bezug auf den Winkel, den wir gerade überspannt haben, im oder gegen den Uhrzeigersinn gehen.
Amit Tomar
12

Eine weitere nützliche Eigenschaft des Kreuzprodukts besteht darin, dass seine Größe mit dem Sinus des Winkels zwischen den beiden Vektoren zusammenhängt:

| axb | = | a | . | b | . Sinus (Theta)

oder

Sinus (Theta) = | axb | / (| a |. | b |)

Also, bei der Umsetzung 1 oben, wenn aund bim Voraus bekannt sind Einheitsvektoren zu sein , dann ist das Ergebnis dieser Funktion ist genau das sine () Wert.

Alnitak
quelle
1
... das ist auch die doppelte Fläche des Dreiecks zwischen Vektor a und Vektor b.
Tim Lovell-Smith
5

Implementierung 1 ist das Perp-Punkt-Produkt der beiden Vektoren. Die beste mir bekannte Referenz für 2D-Grafiken ist die exzellente Graphics Gems- Serie. Wenn Sie Scratch-2D-Arbeiten ausführen, ist es sehr wichtig, diese Bücher zu haben. Band IV enthält einen Artikel mit dem Titel "The Pleasures of Perp Dot Products", in dem viele Verwendungszwecke behandelt werden.

Eine Hauptanwendung des Perp-Punktprodukts besteht darin, die Skalierung sindes Winkels zwischen den beiden Vektoren zu erhalten, genau wie das Punktprodukt die Skalierung cosdes Winkels zurückgibt . Natürlich können Sie das Punktprodukt und das Perp-Punktprodukt zusammen verwenden, um den Winkel zwischen zwei Vektoren zu bestimmen.

Hier ist ein Beitrag dazu und hier ist der Artikel von Wolfram Math World.

Bill Burdick
quelle
3

Ich verwende in meiner Berechnung ein 2D-Kreuzprodukt, um die neue korrekte Drehung für ein Objekt zu finden, auf das ein Kraftvektor an einem beliebigen Punkt relativ zu seinem Massenschwerpunkt einwirkt. (Der Skalar Z eins.)


quelle
3

Eine nützliche 2D-Vektoroperation ist ein Kreuzprodukt, das einen Skalar zurückgibt. Ich benutze es, um zu sehen, ob zwei aufeinanderfolgende Kanten in einem Polygon nach links oder rechts gebogen sind.

Aus der Chipmunk2D- Quelle:

/// 2D vector cross product analog.
/// The cross product of 2D vectors results in a 3D vector with only a z component.
/// This function returns the magnitude of the z value.
static inline cpFloat cpvcross(const cpVect v1, const cpVect v2)
{
        return v1.x*v2.y - v1.y*v2.x;
}
Bram
quelle