如何旋转某个点的顶点?
想象一下,在2D空间中有两个点,并且需要将这些点中的一个旋转X度,另一个点作为中心。
float distX = Math.abs( centerX -point2X ); float distY = Math.abs( centerY -point2Y ); float dist = FloatMath.sqrt( distX*distX + distY*distY );
到目前为止,我只是要find两点之间的距离…任何想法,我应该从哪里去?
最简单的方法是组成三个转换:
- 将原点引入第1点的翻译
- 围绕原点旋转所需的angular度
- 使点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);
请注意,这使得假定angular度x
对于顺时针旋转是负的(所谓的坐标系的标准或右手方向 )。 如果情况并非如此,那么你就需要在涉及sin(x)
的条件上改变符号。
你需要一个二维matrixhttp://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”翻译为0,0
-
旋转
x = sin(angular度)* r; y = cos(angular度)* r;
-
翻译回来
这是一种旋转2D中任何其他点的方法。 请注意,在3D中,这可以用作围绕z轴的旋转,因为它不会改变,所以该点的z坐标。 围绕x轴和y轴的3D旋转也可以很容易地实现。
该代码是在JavaScript中。 开始的注释行是为该函数设置的一个testing集。 他们也作为使用的一个例子。
//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))) }
这里是一个关心旋转方向的版本。 右(顺时针)为负,左(逆时针)为正。 你可以发送一个点或一个2Dvector,并在这个方法(最后一行)中设置它的原语,以避免内存分配的性能。 您可能需要将vector2和mathutilsreplace为您使用的库或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是非常昂贵的,如果你想知道,用这种方式从度数转换成弧度,用查找表来pipe理。 所以它有很高的性能。