Rotating a polygon around the origin (its center)

187 views Asked by At

I'm trying to rotate a polygon around its center. To make things easy, I positioned it in the origin of the canvas so that I don't have to translate it back and forth. This is the rotation function I came up with:

        """
        rotates robot's vertices around its center point
        """
        # configure angle parameters
        angle = np.deg2rad(phi)

        rotated_vertices = []
        for vertex in vertices:
            # translate points to the origin
            x_new = vertex[0]
            y_new = vertex[1]

            x_new = x_new*np.cos(angle) - y_new*np.sin(angle)
            y_new = x_new*np.sin(angle) + y_new*np.cos(angle)

            rotated_vertices.append([x_new, y_new])

        return rotated_vertices

This applies a simple rotation to each vertex (x, y) in a set of vertices that make up the polygon. As I start to increase the angle of rotation, the shape begin to get distorted until it ends up being a line. I have the samples below:

Rotations angle = 0 enter image description here Rotation angle = 50 enter image description here Rotation angle = 70 enter image description here

Thank you in advance. I'm not sure what I'm doing wrong

2

There are 2 answers

0
M Ciel On

Well, you update the xnew first then use the rotated xnew to compute ynew, and that's where it goes wrong.

        x_new = x_new*np.cos(angle) - y_new*np.sin(angle)
        y_new = x_new*np.sin(angle) + y_new*np.cos(angle)

Instead, do something like

            x_rotated = x*np.cos(angle) - y*np.sin(angle)
            y_rotated = x*np.sin(angle) + y*np.cos(angle)

Also, a few points here: you are already using numpy, so why don't you just define a rotation matrix and and use numpy's matmul? That would usually avoid time waste on such error:

import numpy as np
phi = 45
vertices = [(-5, -5), (-5, 5), (0, 6), (5, 5), (5, -5), (0, -6)]
angle = np.deg2rad(phi)

def get_rotate_2d(rad):
    return np.asarray([[np.cos(rad), -np.sin(rad)],
                       [np.sin(rad), np.cos(rad)],
                       ])


vertices_numpy = np.asarray(vertices)
rot_mat = get_rotate_2d(angle)
rotated_vertices = (rot_mat@vertices_numpy.T).T

Also, for any abstraction of the geometric operation, I would suggest shapely. For your problem here, with shapely you only need a few lines to utilize its affine transformation

import shapely
from shapely.affinity import rotate
vertices = [(-5, -5), (-5, 5), (0, 6), (5, 5), (5, -5), (0, -6)]
p0 = shapely.Polygon(vertices)
phi = 45
p_ratated = rotate(p0, angle=phi, origin='center')

0
Raida On

Your formulas are fine.

The problem comes from the usage of x_new and y_new on them, specially for the calculation of y_new which is using the rotated value of x and not the original one.

Try this instead:

x_new = vertex[0] * cos(angle) - vertex[1] * sin(angle)
y_new = vertex[0] * sin(angle) + vertex[1] * cos(angle)