2012-08-28 41 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代价非常高,所以如果你想知道的话,用这种方法将度数转换为用查找表管理的弧度。因此它具有非常高的性能。