Rotate polygon around center and get the coordinates

12.4k Views Asked by At

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.

2

There are 2 best solutions below

6
On 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)
1
On

Once you’ve found the centroid, rotating around that point is straightforward. It can be accomplished by translating to the origin, rotating, and translating back, just as you say.

Let the coordinates of the centroid be $(x_c,y_c)$. Since you’re used to matrix math, I’ll express the transformation in those terms: $$\begin{bmatrix}x'\\y'\end{bmatrix}=\begin{bmatrix}\cos\theta&-\sin\theta\\\sin\theta&\cos\theta\end{bmatrix}\cdot\left(\begin{bmatrix}x\\y\end{bmatrix}-\begin{bmatrix}x_c\\y_c\end{bmatrix}\right)+\begin{bmatrix}x_c\\y_c\end{bmatrix}.$$ You can use homogeneous coordinates to package up the translations and rotation into a single matrix: $$\begin{bmatrix}1&0&x_c\\0&1&y_c\\0&0&1\end{bmatrix}\cdot\begin{bmatrix}\cos\theta&-\sin\theta&0\\\sin\theta&\cos\theta&0\\0&0&1\end{bmatrix}\cdot\begin{bmatrix}1&0&-x_c\\0&1&-y_c\\0&0&1\end{bmatrix} = \begin{bmatrix}\cos\theta&-sin\theta&x_c-x_c\cos\theta-y_c\sin\theta\\\sin\theta&\cos\theta&y_c-x_c\sin\theta+y_c\cos\theta\\0&0&1\end{bmatrix}.$$

As Futurologist suggests in his answer, you can bulk-process all of the vertices by concatenating them into a single matrix. If you’re using homogeneous coordinates, to do this you would left-multiply the matrix $$\begin{bmatrix}x_1&x_2&\cdots&x_n\\y_1&y_2&\cdots&y_n\\1&1&\cdots&1\end{bmatrix}$$ by the $3\times3$ transformation matrix computed above.