Skip to content

Commit f2036d5

Browse files
committed
Let @rotation.setter rotate around center, too; update selector tests
1 parent fc74f95 commit f2036d5

File tree

2 files changed

+36
-9
lines changed

2 files changed

+36
-9
lines changed

lib/matplotlib/tests/test_widgets.py

+26-7
Original file line numberDiff line numberDiff line change
@@ -459,9 +459,11 @@ def test_rectangle_resize_square_center(ax):
459459
def test_selector_rotate(ax, selector_class):
460460
ax.set_aspect(1)
461461
tool = selector_class(ax, interactive=True)
462+
corners = np.array([[100, 130, 130, 100], [100, 100, 140, 140]])
462463
# Draw rectangle
463464
click_and_drag(tool, start=(100, 100), end=(130, 140))
464465
assert_allclose(tool.extents, (100, 130, 100, 140))
466+
assert_allclose(tool.corners, corners, atol=1e-6)
465467
assert len(tool._state) == 0
466468

467469
# Rotate anticlockwise using top-right corner
@@ -474,20 +476,37 @@ def test_selector_rotate(ax, selector_class):
474476
# Extents change as the selector remains rigid in display coordinates
475477
assert_allclose(tool.extents, (110.10, 119.90, 95.49, 144.51), atol=0.01)
476478
assert_allclose(tool.rotation, 25.56, atol=0.01)
479+
angle = tool.rotation
480+
corners_dragged = tool.corners
481+
482+
# Check corners on returning to unrotated position, then rotate back with @setter
483+
tool.rotation = 0
484+
assert tool.rotation == 0
485+
assert_allclose(tool.corners, corners, atol=1e-6)
486+
487+
tool.rotation = angle
488+
assert_allclose(tool.rotation, 25.56, atol=0.01)
489+
assert_allclose(tool.corners, corners_dragged, atol=1e-6)
490+
assert_allclose(tool.extents, (110.10, 119.90, 95.49, 144.51), atol=0.01)
491+
477492
tool.rotation = 45
478493
assert tool.rotation == 45
479-
# Corners should move
494+
# Corners should move again
480495
assert_allclose(tool.corners,
481-
np.array([[110.10, 131.31, 103.03, 81.81],
482-
[95.49, 116.70, 144.98, 123.77]]), atol=0.01)
496+
np.array([[118.54, 139.75, 111.46, 90.25],
497+
[95.25, 116.46, 144.75, 123.54]]), atol=0.01)
483498

484-
# Scale using top-right corner
485-
click_and_drag(tool, start=(110, 145), end=(110, 160))
486-
assert_allclose(tool.extents, (110, 110, 145, 160), atol=0.01)
499+
# Rescale using top-right corner
500+
click_and_drag(tool, start=(111, 145), end=(111, 160))
501+
assert_allclose(tool.corners,
502+
np.array([[118.54, 147.25, 111.46, 82.75],
503+
[95.25, 123.96, 159.75, 131.04]]), atol=0.01)
504+
assert_allclose(tool.extents, (118.54, 111.46, 95.25, 159.75), atol=0.01)
487505

488506
if selector_class == widgets.RectangleSelector:
507+
assert tool._selection_artist.rotation_point == 'xy'
489508
with pytest.raises(ValueError):
490-
tool._selection_artist.rotation_point = 'unvalid_value'
509+
tool._selection_artist.rotation_point = 'invalid_value'
491510

492511

493512
def test_rectangle_add_remove_set(ax):

lib/matplotlib/widgets.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -3636,13 +3636,21 @@ def extents(self, extents):
36363636
@property
36373637
def rotation(self):
36383638
"""
3639-
Rotation in degrees.
3639+
Rotation in degrees (around center).
36403640
"""
36413641
return np.rad2deg(self._rotation)
36423642

36433643
@rotation.setter
36443644
def rotation(self, value):
3645-
self._rotation = np.deg2rad(value)
3645+
new_angle = np.deg2rad(value)
3646+
rot = new_angle - self._rotation
3647+
xc, yc = self._selection_artist.get_center()
3648+
new_geom_state = copy.copy(self._geometry_state)
3649+
new_geom_state.rotation = new_angle
3650+
# Transform the rectangle corner xy so we are rotating about the center.
3651+
new_geom_state.xy = Affine2D().rotate_around(xc, yc, rot).transform(
3652+
self._geometry_state.xy)
3653+
self._geometry_state = new_geom_state
36463654
self._update_selection_artist()
36473655

36483656
def _clip_to_axes(self, x, y):

0 commit comments

Comments
 (0)