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)
Best Answer
I assume what you want to do is simulate the effect of taking your 2D shape, putting it into 3D space, rotating it somehow, then projecting it orthogonally back into its original 2D plane.
The general idea is to pick your favourite 3D rotation, represented as a $3\times3$ linear transformation matrix, then cut out the top $2\times2$ submatrix and use that as a 2D linear transformation.
Example: Rotation around the Z axis by angle $\alpha$.
The $3\times3$ matrix corresponding to this rotation looks like this:
$$\begin{pmatrix}\cos\alpha&-\sin\alpha&0\\\sin\alpha&\cos\alpha&0\\0&0&1\end{pmatrix}$$
The top left $2\times2$ submatrix is $\begin{pmatrix}\cos\alpha&-\sin\alpha\\\sin\alpha&\cos\alpha\end{pmatrix}$, which corresponds to a 2D rotation by angle $\alpha$.
Example: Rotation around the Y axis by angle $\alpha$.
The $3\times3$ matrix corresponding to this rotation looks like this:
$$\begin{pmatrix}\cos\alpha&0&-\sin\alpha\\0&1&0\\\sin\alpha&0&\cos\alpha\end{pmatrix}$$
The top left $2\times 2$ submatrix is $\begin{pmatrix}\cos\alpha&0\\0&1\end{pmatrix}$, which corresponds to an X-axis scaling by $\cos\alpha$.
Case you might be interested in: Rotation around the X axis by $\alpha$, then around the Y axis by $\beta$.
The $3\times3$ matrix corresponding to this rotation looks like this:
$$\begin{pmatrix}\cos\beta&0&-\sin\beta\\0&1&0\\\sin\beta&0&\cos\beta\end{pmatrix} \times \begin{pmatrix}1&0&0\\0&\cos\alpha&-\sin\alpha\\0&\sin\alpha&\cos\alpha\end{pmatrix} = \begin{pmatrix}\cos\beta&-\sin\alpha \sin\beta&-\cos\alpha \sin\beta\\ 0&\cos\alpha&-\sin\alpha\\ \sin\beta&\cos\beta \sin\alpha&\cos\alpha \cos\beta\end{pmatrix}.$$
The top left $2\times 2$ submatrix is $\begin{pmatrix}\cos\beta&-\sin\alpha\sin\beta\\0&\cos\alpha\end{pmatrix}$. This can be decomposed into a series of axis-aligned scalings and skewings like this:
$$\begin{pmatrix}\cos\beta&-\sin\alpha\sin\beta\\0&\cos\alpha\end{pmatrix} = \begin{pmatrix}1&0\\0&\cos\alpha\end{pmatrix} \times \begin{pmatrix}1&-\sin\alpha\sin\beta\\0&1\end{pmatrix} \times \begin{pmatrix}\cos\beta&0\\0&1\end{pmatrix}$$
So you can simulate the effect by scaling the shape in X direction by a factor of $\cos\beta$, then skewing it parallel to the X axis by a factor of $-\sin\alpha\sin\beta$, then scaling the shape in Y direction by a factor of $\cos\alpha$.
Of course, if you have the relative corner coordinates available, then it's probably simpler to just use the entries of the 2x2 matrix directly to transform them:
\begin{align}x_{new} &= \cos\beta\cdot x_{old} -\sin\alpha\cdot\sin\beta\cdot y_{old}\\y_{new} &= \cos\alpha\cdot y_{old}\end{align}