2012-08-28 2 views
48

Stellen Sie sich vor, Sie haben zwei Punkte im 2D-Raum und müssen einen dieser Punkte um X Grad drehen, wobei der andere Punkt als Mittelpunkt fungiert.Wie man einen Eckpunkt um einen bestimmten Punkt dreht?

float distX = Math.abs(centerX -point2X); 
float distY = Math.abs(centerY -point2Y); 

float dist = FloatMath.sqrt(distX*distX + distY*distY); 

Bis jetzt habe ich nur die Entfernung zwischen den beiden Punkten gefunden ... irgendwelche Ideen, wo soll ich davon ausgehen?

enter image description here

+0

Werfen Sie einen Blick auf diese .. es könnte helfen, Dinge zu klären: http://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions – Sednus

Antwort

54

Der einfachste Ansatz ist drei Transformationen zu komponieren:

  1. Eine Übersetzung, die von dem gewünschten Winkel
  2. Eine Übersetzung Nummer 1 auf den Ursprung
  3. Rotation um den Ursprung bringt, dass bringt Punkt 1 zurück in seine ursprüngliche Position

Wenn Sie dies alles aus arbeiten, erhalten Sie die folgende Transformation auf:

newX = centerX + (point2x-centerX)*Math.cos(x) - (point2y-centerY)*Math.sin(x); 

newY = centerY + (point2x-centerX)*Math.sin(x) + (point2y-centerY)*Math.cos(x); 

Beachten Sie, dass dies die Annahme macht, dass der Winkel x für eine Drehung im Uhrzeigersinn negativ ist (die sogenannte standard or right-hand orientation für das Koordinatensystem). Wenn das nicht der Fall ist, müssten Sie das Zeichen unter den Bedingungen sin(x) umkehren.

+2

Klingt wie eine OpenGL-Antwort –

+7

@CoreyOgburn - Es ist eine grundlegende Ebene Geometrie Antwort. Ich habe das schon lange gelernt, bevor es ein OpenGL gab :) –

+0

Sicherlich musst du den Winkel im Uhrzeigersinn berücksichtigen ??? – mathematician1975

1
  1. Übersetzen "1" bis 0,0

  2. Rotate

    x = sin (angle) · R; y = cos (Winkel) * r;

  3. es Übersetzen zurück

+2

nicht genau. Das OP möchte sich um einen bestimmten Punkt drehen. Wie @Ted Hopp sagte, muss es eine Übersetzung zum Ursprung geben, Rotation anwenden und dann wieder an den ursprünglichen Ort übersetzen. (Ohne die Übersetzungen wird die Rotation um die 0,0 des Bildschirms sein) – giorashc

+2

Um fair zu sein, hat das OP ein riesiges Bild gepostet, das Punkt 1 am Ursprung anzeigt. –

+1

Wie Sie wissen, um etwas um bestimmte Punkte zu drehen, können Sie einfach diesen Punkt auf "Null" übersetzen, drehen und dann zurück übersetzen ... – Tutankhamen

16

Sie benötigen eine 2-d Rotationsmatrix http://en.wikipedia.org/wiki/Rotation_matrix

Ihr neuer Punkt

newX = centerX + (cosX * (point2X-centerX) + sinX * (point2Y -centerY)) 
newY = centerY + (-sinX * (point2X-centerX) + cosX * (point2Y -centerY)) 

sein wird, weil Sie im Uhrzeigersinn drehen, anstatt gegen den Uhrzeigersinn

+0

Danke, scheint gut zu funktionieren! :) –

8

Angenommen, Sie verwenden das Java G raphics2D API, versuchen Sie diesen Code -

Point2D result = new Point2D.Double(); 
    AffineTransform rotation = new AffineTransform(); 
    double angleInRadians = (angle * Math.PI/180); 
    rotation.rotate(angleInRadians, pivot.getX(), pivot.getY()); 
    rotation.transform(point, result); 
    return result; 

wo Pivot ist der Punkt, den Sie rotieren.

+2

Es gibt auch 'Math.toRadians()' in Java ;-) – Betlista

0

Hier ist eine Möglichkeit, einen Punkt um einen beliebigen anderen Punkt in 2D zu drehen. Beachten Sie, dass dies in 3D als Drehung um die Z-Achse verwendet werden kann, wobei die Z-Koordinate eines Punktes als ingoriert gilt, da er sich nicht ändert. Die Drehung um die x-Achse und y-Achse in 3D kann ebenfalls einfach implementiert werden.

Der Code ist in JavaScript. Die kommentierten Zeilen am Anfang sind ein Testset für die Funktion. Sie dienen auch als ein Anwendungsbeispiel.

//A = new Array(0,0) 
//S = new Array(-1,0) 
//fi = 90 
//alert("rotujBod: " + rotatePoint(A, S, fi)) 

function rotatePoint(A, S, fi) { 
/** IN points A - rotated point, S - centre, fi - angle of rotation (rad) 
* points in format [Ax, Ay, Az], angle fi (float) 
*  OUT point B 
*/ 
    r = Math.sqrt((A[0] - S[0])*(A[0] - S[0]) + (A[1] - S[1])*(A[1] - S[1])) 
    originOfRotation = new Array(S[0] + r, S[1]) 
    if (A[1] < S[1]) { 
     A2 = new Array(A[0], -1*A[1]) 
     originalAngle = -1*sizeOfAngle(originOfRotation, S, A2) 
    } else { 
    originalAngle = sizeOfAngle(originOfRotation, S, A) 
    } 
    x = S[0] + r*Math.cos(fi + originalAngle) 
    y = S[1] + r*Math.sin(fi + originalAngle) 
    B = new Array(x, y) 
    return(B) 
} 

function sizeOfAngle(A, S, B) { 
    ux = A[0] - S[0] 
    uy = A[1] - S[1] 
    vx = B[0] - S[0] 
    vy = B[1] - S[1] 
    if((Math.sqrt(ux*ux + uy*uy)*Math.sqrt(vx*vx + vy*vy)) == 0) {return 0} 
    return Math.acos((ux*vx + uy*vy)/(Math.sqrt(ux*ux + uy*uy)*Math.sqrt(vx*vx + vy*vy))) 
} 
0

Hier eine Version, die die Drehrichtung interessiert.Rechts (im Uhrzeigersinn) ist negativ und links (gegen den Uhrzeigersinn) ist positiv. Sie können einen Punkt oder einen 2D-Vektor senden und seine Grundelemente in dieser Methode (letzte Zeile) festlegen, um eine Speicherzuordnung für die Leistung zu vermeiden. Möglicherweise müssen Sie vector2 und mathutils zu den von Ihnen verwendeten Bibliotheken oder zu Javas eingebauter Punktklasse ersetzen, und Sie können math.toradians() anstelle von mathutils verwenden.

/** 
* rotates the point around a center and returns the new point 
* @param cx x coordinate of the center 
* @param cy y coordinate of the center 
* @param angle in degrees (sign determines the direction + is counter-clockwise - is clockwise) 
* @param px x coordinate of point to rotate 
* @param py y coordinate of point to rotate 
* */ 

public static Vector2 rotate_point(float cx,float cy,float angle,float px,float py){ 
    float absangl=Math.abs(angle); 
    float s = MathUtils.sin(absangl * MathUtils.degreesToRadians); 
    float c = MathUtils.cos(absangl * MathUtils.degreesToRadians); 

    // translate point back to origin: 
    px -= cx; 
    py -= cy; 

    // rotate point 
    float xnew; 
    float ynew; 
    if (angle > 0) { 
     xnew = px * c - py * s; 
     ynew = px * s + py * c; 
    } 
    else { 
     xnew = px * c + py * s; 
     ynew = -px * s + py * c; 
    } 

    // translate point back: 
    px = xnew + cx; 
    py = ynew + cy; 
    return new Vector2(px, py); 
} 

Beachten Sie, dass dieser Weg mehr Leistung bietet, als Sie in Ihrem Beitrag probiert haben. Weil Sie sqrt verwenden, das sehr kostspielig ist und auf diese Weise von Graden in Radianten umwandelt, die mit einer Nachschlagetabelle verwaltet werden, wenn Sie sich fragen. Und so hat es sehr hohe Leistung.