How to rotate a vertex around a certain point?

JavaMathGeometry

Java Problem Overview


Imagine you have two points in 2d space and you need to rotate one of these points by X degrees with the other point acting as a center.

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

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

So far I just got to finding the distance between the two points... any ideas where should I go from that?

enter image description here

Java Solutions


Solution 1 - Java

The easiest approach is to compose three transformations:

  1. A translation that brings point 1 to the origin
  2. Rotation around the origin by the required angle
  3. A translation that brings point 1 back to its original position

When you work this all out, you end up with the following transformation (where x is the desired angle of rotation in radians):

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

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

Note that this makes the assumption that the angle x is negative for clockwise rotation (the so-called standard or right-hand orientation for the coordinate system). If that's not the case, then you would need to reverse the sign on the terms involving sin(x).

Solution 2 - Java

You need a 2-d rotation matrix http://en.wikipedia.org/wiki/Rotation_matrix

Your new point will be

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

because you are rotating clockwise rather than anticlockwise

Solution 3 - Java

Assuming you are usign the Java Graphics2D API, try this code -

    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;

where pivot is the point you are rotating around.

Solution 4 - Java

  1. Translate "1" to 0,0

  2. Rotate

    x = sin(angle) * r; y = cos(angle) * r;

  3. Translate it back

Solution 5 - Java

Here a version that cares the rotate direction. Right (clockwise) is negative and left (counter clockwise) is positive. You can send a point or a 2d vector and set its primitives in this method (last line) to avoid memory allocation for performance. You may need to replace vector2 and mathutils to libraries you use or to java's built-in point class and you can use math.toradians() instead of 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);
}

Note that this way has more performance than the way you tried in your post. Because you use sqrt that is very costly and in this way converting from degrees to radians managed with a lookup table, if you wonder. And so it has very high performance.

Solution 6 - Java

Here is a way to rotate any point about any other point in 2D. Note that in 3D this can be used as rotation about z axis, z-coordinate of a point being ingored since it doesn't change. Rotation about x-axis and y-axis in 3D can be also easily implemented.

The code is in JavaScript. The commented lines at the beginning are a test set for the function. They also serve as an example of usage.

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRoger TravisView Question on Stackoverflow
Solution 1 - JavaTed HoppView Answer on Stackoverflow
Solution 2 - Javamathematician1975View Answer on Stackoverflow
Solution 3 - JavaSlavchoView Answer on Stackoverflow
Solution 4 - JavaTutankhamenView Answer on Stackoverflow
Solution 5 - Javaömer.bozkurtView Answer on Stackoverflow
Solution 6 - JavaJan KokesView Answer on Stackoverflow