19

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?

2
  • could you elaborate on the question, what exactly are you trying to do here? Commented Nov 26, 2010 at 14:05
  • I want to add a Rectangle to my ax (this works fine) but instead of a straight rectangle, I want it to be tilted of 45 degrees. The final aim is to represent a "cut" in the axis. Commented Nov 26, 2010 at 14:11

3 Answers 3

32

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

Sign up to request clarification or add additional context in comments.

4 Comments

I just wanted to compliment you on a crisp answer that illustrates exactly what to do. Thank you.
Thanks, the code is great! Could you explain why the red rectangle isn't a rectangle anymore, but rather a parallelogram (angles are not 90˚ visually)? Is it some matplotlib-specific logic?
@OlhaPavliuk I believe it's because the x & y axes are not scaled exactly the same. Notice the grid shows rectangles instead of squares.
add plt.gca().set_aspect('equal', adjustable='box')
9

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()

5 Comments

I don't see why you need to add the ax.transData?
I'm honestly in the dark about it as well. I would have thought that t_start = rect.get_transform() would have been the right incantation, but that didn't work either.
I think the answer is correct, so I'll just add this comment about why: the fact that it didn't work before is that if you attach a patch without transform, this is defaulted to transData, as you can see from the add_path documentation. So if you do set it before, you need to add this to your transform. @mjhm: if you want to use rect.get_transform() for t_start, then you have to create the Rectangle with a transform= option.
I think that rect.get_transform will work fine if you do ax.add_patch(rect) first
When you specify a transform for a graphics primitive, it replaces the normal transform that the plotting system uses by default to map user co-ordinates to the display. So, after your transform you need to add the transform that takes your (already transformed) co-ordinates and maps them to the display.
2

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.