2012-08-28 38 views
48

想象一下,在2d空間中有兩個點,並且需要將這些點中的一個旋轉X度,而另一個點作爲中心。如何旋轉某個點的頂點?

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

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

到目前爲止,我只是找到兩點之間的距離......任何想法,我應該從哪裏去?

enter image description here

+0

看看這個..它可能有助於清理:http://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions – Sednus

回答

54

最簡單的方法是組成三個轉變:

  1. ,通過所需的角度
  2. 一個翻譯帶來1點到原點圍繞原點
  3. 平面旋轉的翻譯是使點1回到其原始位置

當你工作出這一切,你結束了以下轉變:

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

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

注意,這使得假設角度x爲負順時針旋轉(所謂standard or right-hand orientation的座標系)。如果情況並非如此,那麼您需要對涉及sin(x)的條款進行反向標記。

+2

聽起來像一個OpenGL答案 –

+7

@CoreyOgburn - 這是一個基本的平面幾何的答案。我很久以前就知道這是一個OpenGL :) –

+0

當然,你需要考慮到順時針角度? – mathematician1975

1
  1. 翻譯 「1」 爲0,0

  2. 旋轉

    X = SIN(角)* R; y = cos(角度)* r;

  3. 翻譯回

+2

不準確。 OP想要圍繞特定點旋轉。正如@Ted Hopp所說,必須對原點進行翻譯,應用旋轉,然後再翻譯成原始位置。 (沒有翻譯,旋轉將在屏幕的0,0附近) – giorashc

+2

公平地說,OP確實張貼了一張巨大的圖片,指出原點的點1。 –

+1

如您所知,要旋轉某個特定點周圍的東西,您可以將該點轉換爲「零」,旋轉,然後將其轉回... – Tutankhamen

16

你需要一個2-d旋轉矩陣http://en.wikipedia.org/wiki/Rotation_matrix

你的新點將

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

,因爲你按順時針方向旋轉,而不是逆時針

+0

謝謝,似乎工作很棒! :) –

8

假設您正在使用Java G raphics2D API,請嘗試此代碼 -

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; 

其中pivot是您旋轉的點。

+2

Java中還有'Math.toRadians()';-) – Betlista

0

這是一種在2D中旋轉任何其他點的任意點的方法。請注意,在3D中,這可以用作圍繞z軸的旋轉,因爲它不會更改,因此該點的z座標將被加入。圍繞x軸和y軸的3D旋轉也可以輕鬆實現。

該代碼是用JavaScript編寫的。開頭的註釋行是該函數的測試集。它們也可以作爲使用的一個例子。

//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

這裏有一個關心旋轉方向的版本。右(順時針)爲負,左(逆時針)爲正。您可以發送一個點或一個2D矢量,並在此方法中設置其基元(最後一行)以避免爲性能分配內存。您可能需要將vector2和mathutils替換爲您使用的庫或Java的內置點類,並且可以使用math.toradians()而不是mathutils。

/** 
* 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); 
} 

請注意,這種方式比您在帖子中嘗試的方式具有更多的性能。因爲你使用的sqrt代價非常高,所以如果你想知道的話,用這種方法將度數轉換爲用查找表管理的弧度。因此它具有非常高的性能。