簡體   English   中英

如何圍繞某個點旋轉頂點?

[英]How to rotate a vertex around a certain point?

想象一下,您在 2d 空間中有兩個點,您需要將其中一個點旋轉 X 度,另一個點作為中心。

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

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

到目前為止,我只是找到了兩點之間的距離......我應該從哪里開始的任何想法?

在此處輸入圖片說明

最簡單的方法是組合三個轉換:

  1. 將第 1 點帶到原點的翻譯
  2. 繞原點旋轉所需角度
  3. 將第 1 點帶回其原始位置的翻譯

全部解決后,您將得到以下轉換(其中x是以弧度為單位的所需旋轉角度):

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對於順時針旋轉(坐標系的所謂標准或右手方向)為負。 如果情況並非如此,那么您需要在涉及sin(x)的條款上反轉符號。

你需要一個二維旋轉矩陣http://en.wikipedia.org/wiki/Rotation_matrix

你的新觀點將是

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

因為你是順時針旋轉而不是逆時針旋轉

假設您使用的是 Java Graphics2D 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;

其中樞軸是您旋轉的點。

  1. 將“1”轉換為 0,0

  2. 旋轉

    x = 罪(角度)* r; y = cos(角度) * r;

  3. 翻譯回來

這是一個關心旋轉方向的版本。 右(順時針)為負,左(逆時針)為正。 您可以發送一個點或一個二維向量並在此方法(最后一行)中設置其基元以避免內存分配以提高性能。 您可能需要將 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 非常昂貴,並且以這種方式從度數轉換為使用查找表管理的弧度,如果您想知道的話。 因此它具有非常高的性能。

這是一種在 2D 中圍繞任何其他點旋轉任何點的方法。 請注意,在 3D 中,這可以用作繞 z 軸的旋轉,一個點的 z 坐標是 ingored,因為它不會改變。 也可以輕松實現 3D 中繞 x 軸和 y 軸的旋轉。

代碼在 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)))
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM