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()
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)
Post a Comment for "Rotating Rectangles Around Point With Matplotlib"