4
$\begingroup$

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.

$\endgroup$
4
  • $\begingroup$ Have you found the centriod, or is that part of the exercise? if you have it then $(x',y') = (x cos \theta + y sin\theta, - x sin \theta + y cos \theta)$ $\endgroup$
    – Doug M
    Commented Sep 7, 2016 at 3:41
  • $\begingroup$ @DougM I have the center of the bounding box of the polygon. Is that enough. Also can you explain that formula in more simple terms? $\endgroup$
    – Johnston
    Commented Sep 7, 2016 at 3:43
  • $\begingroup$ The step "rotating it to $0$" seems wrong. What does it even mean? It might be useful to give the coordinates of your centroid, the coordinates of two or three points of the object, and the new coordinates that those points get mapped to using the procedure that "does not seem to work". Sometimes one can guess the bug in the procedure by looking at the results. $\endgroup$
    – David K
    Commented Sep 7, 2016 at 5:08
  • $\begingroup$ Do you want the centroid of the polygon or of its vertices? In general, these are different, although in the case of your sample polygon, it looks like they’re the same. $\endgroup$
    – amd
    Commented Sep 7, 2016 at 6:50

2 Answers 2

8
$\begingroup$

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)
$\endgroup$
6
  • $\begingroup$ In step 2, you find the centroid of the vertices, but this isn’t necessarily the same as the centroid of the polygon with those vertices. The latter is given by a formula that may be found here. $\endgroup$
    – amd
    Commented Sep 7, 2016 at 6:26
  • $\begingroup$ @amd Ok, I didn't know which centroid he was referring to. Whichever he needs. This is just a sketch of the method, one can always adjust it accordingly. $\endgroup$ Commented Sep 7, 2016 at 12:41
  • $\begingroup$ @Futurologist Thank you. I don't necessarily need the centroid unless it aides me in rotating the polygon to it's new points. $\endgroup$
    – Johnston
    Commented Sep 7, 2016 at 13:04
  • 1
    $\begingroup$ @Johnston Then the rotation depends on the choice of angle $\theta$ and the choice of a point $(a,b)$ around which you would like to perform the rotation. Basically, $(a,b)$ is the point that stays fixed when you rotate. The centroid does not play a special role in that. It becomes more important in dynamics (then it is the center of mass), where the motion of an object is determined by the action of various forces including say gravity, making the object move linearly and rotate. $\endgroup$ Commented Sep 7, 2016 at 13:17
  • 1
    $\begingroup$ @Steve This is a rotation matrix of the plane: en.wikipedia.org/wiki/Rotation_matrix $\endgroup$ Commented Nov 12, 2018 at 22:17
2
$\begingroup$

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.

$\endgroup$
1
  • $\begingroup$ absolutely perfect answer, thx u so much. really helpful. $\endgroup$ Commented Mar 27, 2021 at 7:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .