Skip to content Skip to sidebar Skip to footer

Rotating Rectangles Around Point With Matplotlib

I wanted to rotate Rectangles with matplotlib, but the normal patch always rotates around the lower left corner of the Rectangle. Is there a way to describe more general transforma

Solution 1:

Same as the other answer, just without subclassing and using private attributes.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D

height = 0.1
width = 1
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.set_xlim([-width * 1.2, width * 1.2])
ax.set_ylim([-width * 1.2, width * 1.2])
ax.plot(0, 0,  color='r', marker='o', markersize=10)
point_of_rotation = np.array([0, height/2])          # A# point_of_rotation = np.array([width/2, height/2])  # B# point_of_rotation = np.array([width/3, height/2])  # C# point_of_rotation = np.array([width/3, 2*height])  # Dfor deg inrange(0, 360, 45):
    rec = plt.Rectangle(-point_of_rotation, width=width, height=height, 
                        color=str(deg / 360), alpha=0.9,
                        transform=Affine2D().rotate_deg_around(*(0,0), deg)+ax.transData)
    ax.add_patch(rec)
plt.show()

enter image description here

Solution 2:

I created a custom Rectangle class which has as additional argument the relative point of rotation - relative means measured in the frame defined by the original lower left coordinates of the rectangle (x0, y0) and the angle.

rec = RotatingRectangle((0, 0), width=1, height=0.1, rel_point_of_rot=(0, 0.05), angle=45)

creates an rectangle where the the relative point (0, 0.05) [the midpoint of the left side] is shifted to the center (0, 0) and than a rotation of 45 deg is performed around this point.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

classRotatingRectangle(Rectangle):
    def__init__(self, xy, width, height, rel_point_of_rot, **kwargs):
        super().__init__(xy, width, height, **kwargs)
        self.rel_point_of_rot = rel_point_of_rot
        self.xy_center = self.get_xy()
        self.set_angle(self.angle)

    def_apply_rotation(self):
        angle_rad = self.angle * np.pi / 180
        m_trans = np.array([[np.cos(angle_rad), -np.sin(angle_rad)],
                            [np.sin(angle_rad), np.cos(angle_rad)]])
        shift = -m_trans @ self.rel_point_of_rot
        self.set_xy(self.xy_center + shift)

    defset_angle(self, angle):
        self.angle = angle
        self._apply_rotation()

    defset_rel_point_of_rot(self, rel_point_of_rot):
        self.rel_point_of_rot = rel_point_of_rot
        self._apply_rotation()

    defset_xy_center(self, xy):
        self.xy_center = xy
        self._apply_rotation()

height = 0.1
width = 1
fig, ax = plt.subplots()
ax.set_aspect('equal')
ax.set_xlim([-width * 1.2, width * 1.2])
ax.set_ylim([-width * 1.2, width * 1.2])
ax.plot(0, 0,  color='r', marker='o', markersize=10)
point_of_rotation = np.array([0, height/2])          # A# point_of_rotation = np.array([width/2, height/2])  # B# point_of_rotation = np.array([width/3, height/2])  # C# point_of_rotation = np.array([width/3, 2*height])  # Dfor deg inrange(0, 360, 45):
    rec = RotatingRectangle((0, 0), width=width, height=height, 
                            rel_point_of_rot=point_of_rotation,
                            angle=deg, color=str(deg / 360), alpha=0.9)
    ax.add_patch(rec)

rectanglesrectanglesrectanglesrectangles

Post a Comment for "Rotating Rectangles Around Point With Matplotlib"