如何围绕某个点旋转顶点?

时间:2012-08-28 14:16:05

标签: java math geometry

想象一下,你在二维空间中有两个点,你需要将其中一个点旋转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

6 个答案:

答案 0 :(得分:60)

最简单的方法是组成三个转换:

  1. 将第1点带入原点的翻译
  2. 以所需角度围绕原点旋转
  3. 将第1点带回原位的翻译
  4. 当你全力以赴时,你最终会得到以下转变:

    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)的条款的签名。

答案 1 :(得分:18)

您需要一个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))

因为你顺时针旋转而不是逆时针旋转

答案 2 :(得分:9)

假设您使用的是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;

其中pivot是您要转动的点。

答案 3 :(得分:2)

  1. 将“1”翻译为0,0

  2. 旋转

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

  3. 将其翻译回来

答案 4 :(得分:0)

这是一种旋转2D中任何其他点的任何点的方法。请注意,在3D中,这可以用作围绕z轴的旋转,因为它不会改变,所以正在进入的点的z坐标。也可以轻松实现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)))
}

答案 5 :(得分:0)

这是一个关心旋转方向的版本。右(顺时针)为负,左(逆时针)为正。您可以发送一个点或二维向量,并在此方法(最后一行)中设置其基元,以避免内存分配以提高性能。您可能需要将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,并且以这种方式将度数转换为使用查找表管理的弧度,如果您想知道。因此它具有非常高的性能。