Wie mache ich Vektoren parallel?
-
Hi!
Ich habe einen Punkt A(x,y) in einem unendliche großen Koordinatensystem. Dieser Punkt bildet den Mittelpunkt eines Dreiecks, welches mit dem spitzen Winkel immer "nach rechts", also parallel zur x-Achse zeigt.Dieses Dreieck will ich nun genau in dieselbe Richtung mit dem spitzen Winkel zeigen lassen wie ein Vektor B. Es soll dabei quasi um den Mittelpunkt gedreht werden, sodass das Dreieck parallel zum Vektor B ist.
Nun würde man das ja mit einer Rotationsmatrix machen, aber:
1. Bekomm ich es damit nicht gebacken
2. Will ich nicht immer um einen bestimmten Winkel/Richtung drehen, sondern zu einer bestimmten Richtung. Also wenn das Dreieck nun im 20° Winkel (im Bezug auf die X Achse) gezeichnet wird und ich dann an meine Funktion den Winkel (oder besser noch den Vektor) übergebe mit 15° will ich das Dreieck nicht in Richtung 35° drehen sondern in Richtung 15°.
Klar könnte ich diese Drehung vorher berechnen, aber gibt es da keinen einfacheren Weg mit Vektor Operationen?
-
Es geht recht elegant mit Rotationsmatrizen: Wenn (a,b) dein Vektor ist, der die Richtung angibt, in die du drehen möchtest, kannst du folgende Matrix nehmen:
( a -b ) ( b a )
Die einzige Voraussetzung dafür ist, dass der Vektor (a,b) die Länge 1 hat.
Das funktioniert, weil in den Spalten einer Matrix die Bilder der Einheitsvektoren stehen. Ein diesem Fall wird also der Vektor (1,0) auf (a,b) abgebildet und der Vektor (0,1) auf (-b,a). Der Vektor (-b,a) ist der um 90° rotierte Vektor (a,b), das heißt diese Matrix beschreibt tatsächlich eine Rotation.
-
Danke sieht echt elegant aus, aber irgendwie rennt es nicht so ganz bei mir:
void Triangle::Draw(wxDC &pDC) const{ double xKoord = GetPositionVector().GetXKoord(); //Position double yKoord = GetPositionVector().GetYKoord(); double dXKoord = GetDirectionVector().GetXKoord(); //Richtung double dYKoord = GetDirectionVector().GetYKoord(); wxPoint point[3]; //Dreieck vom Mittelpunkt aus zeichnen point[0] = wxPoint(xKoord - size/2, yKoord + size/2); point[1] = wxPoint(xKoord + size/2 + 5, yKoord); //+5 um auch bei kleinen Größen sichtbaren spitzen Winkel zu haben point[2] = wxPoint(xKoord - size/2, yKoord - size/2); //Hier nun die Drehung for (int i = 0; i < 3; ++i) point[i] = wxPoint(point[i].x * dXKoord - point[i].y * dYKoord, point[i].x * dYKoord + point[i].y * dXKoord); //Per wxWidgets zeichnen... }
Der Richtungsvektor wird schon im Konstruktor bzw. Setter als Einheitsvektor gespeichert, daher sollte das keine Probleme machen.
-
Pille456 schrieb:
Danke sieht echt elegant aus, aber irgendwie rennt es nicht so ganz bei mir:[...]
Was genau soll denn passieren und was passiert stattdessen? Eine Skizze (falls du die postest, bitte png verwenden, kein jpeg!) könnte das vielleicht klarstellen.
-
Joa würde Sinn machen ne Problembeschreibung
Also ich lasse um jedes Dreieck einen Kreis zeichnen, der den selben Mittelpunkt hat wie das Dreieck. Das Problem ist nur, dass nicht ein Dreieck in einem Kreis ist. Da die Position randomisiert ist sehe ich manchmal gar keine Dreieck weil die durch die Transformation dann außerhalb meines Fensterbereiches wären/sind.
Wenn ich dann mal Dreiecke sehe, dann bewegen diese sich auch nicht immer in die Richtung des spitzen Winkels.
Hier ein Screenshot (während der Bewegung):
http://img143.imageshack.us/my.php?image=clipboard02fi5.pngAm zufälligen Setzen der Positionen kann es nicht liegen, da die Kreise zu Beginn immer im richtigen Bereich sind.
-
Hab gerade nochmal bei Wikipedia geschaut und den Verdacht, dass die Drehung immer im Ursprung verläuft, also muss ich quasi den Punkt erst als Ursprung definieren.
Gibt es keinen Weg darum?
Das Objekt das ich drehe muss ja nicht wissen wo es im bezug zum Koordinatensystem steht, es reicht ja zu wissen wo es ist und dass es sich drehen soll..
-
Pille456 schrieb:
Hab gerade nochmal bei Wikipedia geschaut und den Verdacht, dass die Drehung immer im Ursprung verläuft, also muss ich quasi den Punkt erst als Ursprung definieren.
Gibt es keinen Weg darum?Einen Weg drumherum gibt es schon, der sieht oft so aus:
1. Verschiebe das Objekt zum Ursprung.
2. Rotiere das Objekt.
3. Verschiebe das Objekt wieder dahin, wo es herkam.Wenn du das ganze in homogenen Koordinaten machst, kannst du alle drei Schritte in einer einzigen 3x3-Matrix zusammenfassen. Homogene Koordinaten bedeuten hier im Grunde nur, dass du deine 2-elementigen (x,y)-Vektoren zu 3-elementigen (x,y,1)-Vektoren erweiterst, dann kannst du mit einer 3x3-Matrix eine Verschiebung der x/y-Werte ausdrücken. Eine Verschiebung um dx, dy sieht z.B. so aus:
( 1 0 dx ) ( 0 1 dy ) ( 0 0 1 )
Die Rotationsmatrix von oben würde in dieser Geometrie so aussehen:
( a -b 0 ) ( b a 0 ) ( 0 0 1 )
-
Kann sein, dass es gerade einfach zu spät ist oder ich hab gerade zu viel bei google gesucht, aber könntest du mir mal ein Beispiel geben?
-
Angenommen das Dreieck, das du rotieren möchtest, ist an Position (100, 200). Um das jetzt zu rotieren, muss du das zuerst zum Ursprung schieben:
( 1 0 -100 ) A := ( 0 1 -200 ) ( 0 0 1 )
Dann rotieren:
( a -b 0 ) B := ( b a 0 ) ( 0 0 1 )
Dann zurückschieben:
( 1 0 100 ) C := ( 0 1 200 ) ( 0 0 1 )
Jetzt musst du nur noch die Koordinaten deines Dreiecks mit 1 erweitern und dann die Matrizen nacheinander dranmultiplizieren. Angenommen eine Koordinate deines Dreiecks ist (99, 201), dann sieht die Rechnung für die Rotation so aus:
( 99 ) C * B * A * ( 201 ) ( 1 )
Das Ergebnis dieser Multiplikation ist ein Vektor, dessen letzte Komponente wieder 1 ist. Diese Komponente kannst du ignorieren, dann hast du wieder einen normalen 2-dimensionalen Vektor.
-
Das Prinzip habe ich soweit verstanden, aber irgendwie bekomme ich das nicht in einer Zeile unter!
Also ich habs mal durchgerechnet und kam für die Koordinaten auf folgende Gleichungen:xPos, yPos = Mittelpunkt des Dreiecks a,b = Richtungsvektor nX,nY = Koordinaten des Punktes der gedreht werden soll x := a*nX - b*nY + a*xPos - b*yPos + xPos y := b*nX - a*nY + b*yPos + a*yPos + yPos
Problem ist weiterhin dasselbe, also meine Dreiecke sind nicht da wo sie seien sollen.
Wahrscheinlich habe ich mich irgendwo verrechnet, aber kann es auch gerade schlecht nachprüfen weil ich sowas noch nie gemacht habe