Mermoz
Mermoz

Reputation: 15494

Matplotlib: rotating a patch

I wanted to rotate a Rectangle in matplotlib but when I apply the transformation, the rectangle doesn't show anymore:

rect = mpl.patches.Rectangle((0.0120,0),0.1,1000)
t = mpl.transforms.Affine2D().rotate_deg(45)
rect.set_transform(t)

is this a known bug or do I make a mistake?

Upvotes: 18

Views: 33616

Answers (3)

Fifteen12
Fifteen12

Reputation: 85

Although this is old, I wanted to add this for completeness. You can also rotate a Rectangle through the class's built in methods. Use the set_angle function to determine the angle to rotate and the rotation_point property to set the point of rotation.

from matplotlib.patches import Rectangle

rect1 = Rectangle(xy=(0, 0), width=2, height=1, color='blue')
rect2 = Rectangle(xy=(0, 0), width=2, height=1, angle=45, rotation_point='xy', color='red')
rect3 = Rectangle(xy=(0, 0), width=2, height=1, color='green')
rect3.set_angle(90)

Rotated rectangles

Notice that you can also easily change the point that the patch is rotated around by calling the rotation_point method. Official documentation is here.

Upvotes: 2

Nick
Nick

Reputation: 2432

The patch in the provided code makes it hard to tell what's going on, so I've made a clear demonstration that I worked out from a matplotlib example:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib as mpl

fig = plt.figure()
ax = fig.add_subplot(111)

r1 = patches.Rectangle((0,0), 20, 40, color="blue", alpha=0.50)
r2 = patches.Rectangle((0,0), 20, 40, color="red",  alpha=0.50)

t2 = mpl.transforms.Affine2D().rotate_deg(-45) + ax.transData
r2.set_transform(t2)

ax.add_patch(r1)
ax.add_patch(r2)

plt.xlim(-20, 60)
plt.ylim(-20, 60)

plt.grid(True)

plt.show()

enter image description here

Upvotes: 31

mjhm
mjhm

Reputation: 16705

Apparently the transforms on patches are composites of several transforms for dealing with scaling and the bounding box. Adding the transform to the existing plot transform seems to give something more like what you'd expect. Though it looks like there's still an offset to work out.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib as mpl
fig = plt.figure()
ax = fig.add_subplot(111)

rect = patches.Rectangle((0.0120,0),0.1,1000)

t_start = ax.transData
t = mpl.transforms.Affine2D().rotate_deg(-45)
t_end = t_start + t

rect.set_transform(t_end)

print repr(t_start)
print repr(t_end)
ax.add_patch(rect)

plt.show()

Upvotes: 9

Related Questions