How to Rotate a Polygon Around Its Center and Find Coordinates

geometrymatricesrotationstrigonometry

First off I am a computer programmer, so excuse my lack of math understanding. Also I know this question has been asked before, but the answers don't seem to apply to this specific situation.

Given a polygon, which is made up of points. For example:

[{"x":301.1848472789287,"y":216.523742955658},{"x":299.92410285162424,"y":241.37037128550003},{"x":296.227787218953,"y":264.523742955658},{"x":290.347798182831,"y":284.40599394956655},{"x":282.68484727892877,"y":299.6621817189641},{"x":273.761151947722,"y":309.25262227940857},{"x":264.18484727892877,"y":312.523742955658},{"x":254.60854261013552,"y":309.25262227940857},{"x":245.6848472789288,"y":299.6621817189641},{"x":238.02189637502653,"y":284.40599394956655},{"x":232.14190733890456,"y":264.523742955658},{"x":228.44559170623327,"y":241.37037128550003},{"x":227.1848472789288,"y":216.52374295565804},{"x":228.44559170623327,"y":191.67711462581605},{"x":232.14190733890456,"y":168.52374295565807},{"x":238.02189637502653,"y":148.64149196174952},{"x":245.68484727892877,"y":133.38530419235195},{"x":254.60854261013552,"y":123.79486363190748},{"x":264.18484727892877,"y":120.52374295565804},{"x":273.761151947722,"y":123.79486363190746},{"x":282.68484727892877,"y":133.38530419235192},{"x":290.347798182831,"y":148.64149196174947},{"x":296.2277872189529,"y":168.52374295565798},{"x":299.92410285162424,"y":191.67711462581596}]

Where each coordinate is in the global coordinate system (top left is 0,0 and right and down is positive).

I want to figure out where each point would be if I were to rotate the polygon around it's center (is that called centroid?). These polygons may be whatever a user decides to draw on the screen, so they might be concave or convex or anything. In the array of coordinates above, it is a circle as a bunch of points.

So basically instead of rotating the shape and keeping the points local, I want to move the points in the global coordinate system, and figure out where they should be when rotated around a point.

I know in the past I used matrix math, but I am just not sure how to do it. I've been at this for weeks now. I believe it's something like moving the shape to 0,0 and rotating it to 0 and doing the rotation matrix on the shape and moving it back but it does not seem to work for me.

Edit: I know the center of the bounding box of the polygon.

Best Answer

Step1. Reorganize your data a bit. Let us store the coordinates $(x_j, y_j)$ of the vertices of the polygon your points in a $2 \times n$ array called $P$, like this $$ P = \begin{bmatrix} x_1 & x_2 & x_{3} & \dots & x_{n} \\ y_1 & y_2 & y_{3} & \dots & y_{n} \\ \end{bmatrix}$$

Step2. Compute the centroid $(a,b)$ that you need. If you are looking for the centroid of the vertices of the polygon you can do it as follows $$\begin{bmatrix} a \\ b \\ \end{bmatrix} = \frac{1}{n} \, \left( \, \, \begin{bmatrix} x_1 \\ y_1 \\ \end{bmatrix} + \begin{bmatrix} x_2 \\ y_2 \\ \end{bmatrix} + \begin{bmatrix} x_3 \\ y_3 \\ \end{bmatrix} + ... + \begin{bmatrix} x_n \\ y_n \\ \end{bmatrix} \, \, \right)$$

Note that there are various notions of centroid, depending on how you view your polygon -- a finite set of mass-points, a frame (a set of points and struts) or as a whole object with equally distributed mass inside the polygon. You can check the formulas on the net.

Step 3. Fill up another $2 \times n$ array $$ C = \begin{bmatrix} a & a & a & \dots & a \\ b & b & b & \dots & b \\ \end{bmatrix}$$

Step 4. Define the $2 \times 2$ rotation matrix of angle $\theta$ (the angle of rotation you choose)

$$ R = \begin{bmatrix} \cos{\theta} & - \sin{\theta} \\ \sin{\theta} & \cos{\theta} \\ \end{bmatrix}$$

Step 5. The rotated polygon around the centroid $(a,b)$ with rotation angle $\theta$ as follows

$$P_{new} = R\cdot \left( P - C \right) + C$$ where $\,\, \cdot \,\,$ is matrix multiplication and $-$ and $+$ are matrix subtraction and addition (basically component-wise).

$P_{new}$ contains the vertices of the rotated polygon.

import numpy as np
  
def R(angle):
    cos_a = np.cos(angle)
    sin_a = np.sin(angle)
    return np.array([[cos_a, -sin_a],
                     [sin_a,  cos_a]])

def rotate(poly, angle, Center):   
    poly_new = (poly - Center).dot(R(angle).T) + Center
    return poly_new

def organize(poly):
    P = np.empty(( len(poly), 2), dtype=float)
    for i in range(len(poly)):
        P[i,0] = poly[i]['x']
        P[i,1] = poly[i]['y']
    return P  

Poly = [{"x":301.1848472789287,"y":216.523742955658},
 {"x":299.92410285162424,"y":241.37037128550003},
 {"x":296.227787218953,"y":264.523742955658},
 {"x":290.347798182831,"y":284.40599394956655},
 {"x":282.68484727892877,"y":299.6621817189641},
 {"x":273.761151947722,"y":309.25262227940857},
 {"x":264.18484727892877,"y":312.523742955658},
 {"x":254.60854261013552,"y":309.25262227940857},
 {"x":245.6848472789288,"y":299.6621817189641},
 {"x":238.02189637502653,"y":284.40599394956655},
 {"x":232.14190733890456,"y":264.523742955658},
 {"x":228.44559170623327,"y":241.37037128550003},
 {"x":227.1848472789288,"y":216.52374295565804},
 {"x":228.44559170623327,"y":191.67711462581605},
 {"x":232.14190733890456,"y":168.52374295565807},
 {"x":238.02189637502653,"y":148.64149196174952},
 {"x":245.68484727892877,"y":133.38530419235195},
 {"x":254.60854261013552,"y":123.79486363190748},
 {"x":264.18484727892877,"y":120.52374295565804},
 {"x":273.761151947722,"y":123.79486363190746},
 {"x":282.68484727892877,"y":133.38530419235192},
 {"x":290.347798182831,"y":148.64149196174947},
 {"x":296.2277872189529,"y":168.52374295565798},
 {"x":299.92410285162424,"y":191.67711462581596}]

P = organize(Poly)
Cntr = np.array([0., 0.])
P_new = rotate(P, np.pi/3, Cntr)
Related Question