17
17
18
18
import pytest
19
19
20
-
21
20
@pytest .fixture
22
21
def ax ():
23
22
return get_ax ()
@@ -84,19 +83,20 @@ def test_rectangle_selector(ax, kwargs):
84
83
85
84
# purposely drag outside of axis for release
86
85
do_event (tool , 'release' , xdata = 250 , ydata = 250 , button = 1 )
86
+ do_event (tool , 'onmove' , xdata = 250 , ydata = 250 , button = 1 )
87
87
88
88
if kwargs .get ('drawtype' , None ) not in ['line' , 'none' ]:
89
89
assert_allclose (tool .geometry ,
90
- [[100. , 100 , 199 , 199 , 100 ],
90
+ [[100 , 100 , 199 , 199 , 100 ],
91
91
[100 , 199 , 199 , 100 , 100 ]],
92
92
err_msg = tool .geometry )
93
93
94
94
onselect .assert_called_once ()
95
95
(epress , erelease ), kwargs = onselect .call_args
96
96
assert epress .xdata == 100
97
97
assert epress .ydata == 100
98
- assert erelease .xdata == 199
99
- assert erelease .ydata == 199
98
+ assert erelease .xdata == 200
99
+ assert erelease .ydata == 200
100
100
assert kwargs == {}
101
101
102
102
@@ -193,10 +193,16 @@ def test_rectangle_selector_set_props_handle_props(ax):
193
193
assert artist .get_alpha () == 0.3
194
194
195
195
196
- def test_rectangle_resize (ax ):
196
+ # Should give same results if rectangle is created from any two
197
+ # opposite corners
198
+ @pytest .mark .parametrize ('start, end' , [[(0 , 10 ), (100 , 120 )],
199
+ [(100 , 120 ), (0 , 10 )],
200
+ [(0 , 120 ), (100 , 10 )],
201
+ [(100 , 10 ), (0 , 120 )]])
202
+ def test_rectangle_resize (ax , start , end ):
197
203
tool = widgets .RectangleSelector (ax , onselect = noop , interactive = True )
198
204
# Create rectangle
199
- click_and_drag (tool , start = ( 0 , 10 ), end = ( 100 , 120 ) )
205
+ click_and_drag (tool , start = start , end = end )
200
206
assert_allclose (tool .extents , (0.0 , 100.0 , 10.0 , 120.0 ))
201
207
202
208
# resize NE handle
@@ -317,16 +323,16 @@ def test_rectangle_resize_center(ax, add_state):
317
323
xdata_new , ydata_new = xdata + xdiff , ydata + ydiff
318
324
click_and_drag (tool , start = (xdata , ydata ), end = (xdata_new , ydata_new ),
319
325
key = use_key )
320
- assert tool .extents == (xdata_new , extents [1 ] - xdiff ,
321
- ydata_new , extents [3 ] - ydiff )
326
+ assert_allclose ( tool .extents , (xdata_new , extents [1 ] - xdiff ,
327
+ ydata_new , extents [3 ] - ydiff ) )
322
328
323
329
324
330
@pytest .mark .parametrize ('add_state' , [True , False ])
325
331
def test_rectangle_resize_square (ax , add_state ):
326
332
tool = widgets .RectangleSelector (ax , onselect = noop , interactive = True )
327
333
# Create rectangle
328
334
click_and_drag (tool , start = (70 , 65 ), end = (120 , 115 ))
329
- assert tool .extents == (70.0 , 120.0 , 65.0 , 115.0 )
335
+ assert_allclose ( tool .extents , (70.0 , 120.0 , 65.0 , 115.0 ) )
330
336
331
337
if add_state :
332
338
tool .add_state ('square' )
@@ -341,8 +347,8 @@ def test_rectangle_resize_square(ax, add_state):
341
347
xdata_new , ydata_new = xdata + xdiff , ydata + ydiff
342
348
click_and_drag (tool , start = (xdata , ydata ), end = (xdata_new , ydata_new ),
343
349
key = use_key )
344
- assert tool .extents == (extents [0 ], xdata_new ,
345
- extents [2 ], extents [3 ] + xdiff )
350
+ assert_allclose ( tool .extents , (extents [0 ], xdata_new ,
351
+ extents [2 ], extents [3 ] + xdiff ) )
346
352
347
353
# resize E handle
348
354
extents = tool .extents
@@ -391,11 +397,12 @@ def test_rectangle_resize_square(ax, add_state):
391
397
xdata_new , ydata_new = xdata + xdiff , ydata + ydiff
392
398
click_and_drag (tool , start = (xdata , ydata ), end = (xdata_new , ydata_new ),
393
399
key = use_key )
394
- assert_allclose (tool .extents , (extents [ 0 ] + ydiff , extents [1 ],
395
- ydata_new , extents [3 ]))
400
+ assert_allclose (tool .extents , (xdata_new , extents [1 ],
401
+ extents [ 2 ] + xdiff , extents [3 ]))
396
402
397
403
398
404
def test_rectangle_resize_square_center (ax ):
405
+ ax .set_aspect (1 )
399
406
tool = widgets .RectangleSelector (ax , onselect = noop , interactive = True )
400
407
# Create rectangle
401
408
click_and_drag (tool , start = (70 , 65 ), end = (120 , 115 ))
@@ -461,6 +468,7 @@ def test_rectangle_resize_square_center(ax):
461
468
@pytest .mark .parametrize ('selector_class' ,
462
469
[widgets .RectangleSelector , widgets .EllipseSelector ])
463
470
def test_rectangle_rotate (ax , selector_class ):
471
+ ax .set_aspect (1 )
464
472
tool = selector_class (ax , onselect = noop , interactive = True )
465
473
# Draw rectangle
466
474
click_and_drag (tool , start = (100 , 100 ), end = (130 , 140 ))
@@ -474,19 +482,19 @@ def test_rectangle_rotate(ax, selector_class):
474
482
click_and_drag (tool , start = (130 , 140 ), end = (120 , 145 ))
475
483
do_event (tool , 'on_key_press' , key = 'r' )
476
484
assert len (tool ._state ) == 0
477
- # Extents shouldn't change ( as shape of rectangle hasn't changed)
478
- assert tool .extents == ( 100 , 130 , 100 , 140 )
485
+ # Extents change as the selector remains rigid in display coordinates
486
+ assert_allclose ( tool .extents , ( 110.10 , 119.90 , 95.49 , 144.51 ), atol = 0.01 )
479
487
assert_allclose (tool .rotation , 25.56 , atol = 0.01 )
480
488
tool .rotation = 45
481
489
assert tool .rotation == 45
482
490
# Corners should move
483
491
assert_allclose (tool .corners ,
484
- np .array ([[118.53 , 139.75 , 111.46 , 90.25 ],
485
- [95.25 , 116.46 , 144.75 , 123.54 ]]), atol = 0.01 )
492
+ np .array ([[110.10 , 131.31 , 103.03 , 81.81 ],
493
+ [95.49 , 116.70 , 144.98 , 123.77 ]]), atol = 0.01 )
486
494
487
495
# Scale using top-right corner
488
496
click_and_drag (tool , start = (110 , 145 ), end = (110 , 160 ))
489
- assert_allclose (tool .extents , (100 , 139.75 , 100 , 151.82 ), atol = 0.01 )
497
+ assert_allclose (tool .extents , (110 , 110 , 145 , 160 ), atol = 0.01 )
490
498
491
499
if selector_class == widgets .RectangleSelector :
492
500
with pytest .raises (ValueError ):
@@ -508,36 +516,38 @@ def test_rectangle_add_remove_set(ax):
508
516
509
517
@pytest .mark .parametrize ('use_data_coordinates' , [False , True ])
510
518
def test_rectangle_resize_square_center_aspect (ax , use_data_coordinates ):
511
- ax .set_aspect (0.8 )
519
+ ax = get_ax ()
520
+ ax .set_aspect (0.5 )
521
+ # Need to call a draw to update ax.transData
522
+ plt .gcf ().canvas .draw ()
512
523
513
524
tool = widgets .RectangleSelector (ax , onselect = noop , interactive = True ,
514
525
use_data_coordinates = use_data_coordinates )
515
- # Create rectangle
516
- click_and_drag (tool , start = (70 , 65 ), end = (120 , 115 ))
517
- assert_allclose (tool .extents , (70.0 , 120.0 , 65.0 , 115.0 ))
518
526
tool .add_state ('square' )
519
527
tool .add_state ('center' )
528
+ # Create rectangle, width 50 in data coordinates
529
+ click_and_drag (tool , start = (70 , 65 ), end = (120 , 75 ))
520
530
521
531
if use_data_coordinates :
522
- # resize E handle
523
- extents = tool .extents
524
- xdata , ydata , width = extents [1 ], extents [3 ], extents [1 ] - extents [0 ]
525
- xdiff , ycenter = 10 , extents [2 ] + (extents [3 ] - extents [2 ]) / 2
526
- xdata_new , ydata_new = xdata + xdiff , ydata
527
- ychange = width / 2 + xdiff
528
- click_and_drag (tool , start = (xdata , ydata ), end = (xdata_new , ydata_new ))
529
- assert_allclose (tool .extents , [extents [0 ] - xdiff , xdata_new ,
530
- ycenter - ychange , ycenter + ychange ])
532
+ assert_allclose (tool .extents , (20 , 120 , 15 , 115 ))
531
533
else :
532
- # resize E handle
533
- extents = tool .extents
534
- xdata , ydata = extents [1 ], extents [3 ]
535
- xdiff = 10
536
- xdata_new , ydata_new = xdata + xdiff , ydata
537
- ychange = xdiff * 1 / tool ._aspect_ratio_correction
538
- click_and_drag (tool , start = (xdata , ydata ), end = (xdata_new , ydata_new ))
539
- assert_allclose (tool .extents , [extents [0 ] - xdiff , xdata_new ,
540
- 46.25 , 133.75 ])
534
+ assert_allclose (tool .extents , (20 , 120 , - 35 , 165 ))
535
+
536
+ # resize E handle
537
+ extents = tool .extents
538
+ xdata , ydata = extents [1 ], extents [3 ]
539
+ xdiff = 10
540
+ xdata_new , ydata_new = xdata + xdiff , ydata
541
+ if use_data_coordinates :
542
+ # In data coordinates the difference should be equal in both directions
543
+ ydiff = xdiff
544
+ else :
545
+ # In display coordinates, the change in data coordinates should be
546
+ # different in each direction
547
+ ydiff = xdiff / tool .ax ._get_aspect_ratio ()
548
+ click_and_drag (tool , start = (xdata , ydata ), end = (xdata_new , ydata_new ))
549
+ assert_allclose (tool .extents , [extents [0 ] - xdiff , xdata_new ,
550
+ extents [2 ] - ydiff , extents [3 ] + ydiff ])
541
551
542
552
543
553
def test_ellipse (ax ):
@@ -1644,6 +1654,7 @@ def test_polygon_selector_verts_setter(fig_test, fig_ref, draw_bounding_box):
1644
1654
]
1645
1655
for (etype , event_args ) in event_sequence :
1646
1656
do_event (tool_ref , etype , ** event_args )
1657
+ np .testing .assert_allclose (tool_ref .verts , verts )
1647
1658
1648
1659
1649
1660
def test_polygon_selector_box (ax ):
@@ -1658,10 +1669,19 @@ def test_polygon_selector_box(ax):
1658
1669
* polygon_place_vertex (* verts [0 ]),
1659
1670
]
1660
1671
1672
+ # Set smaller axes limits to reduce errors in converting from data to
1673
+ # display coords. The canvas size is 640 x 640, so we need a tolerance of
1674
+ # (data width / canvas width) = 50 / 640 ~ 0.08 when comparing points in
1675
+ # data space
1676
+ ax .set_xlim (- 5 , 45 )
1677
+ ax .set_ylim (- 5 , 45 )
1678
+ atol = 0.08
1679
+
1661
1680
# Create selector
1662
1681
tool = widgets .PolygonSelector (ax , onselect = noop , draw_bounding_box = True )
1663
1682
for (etype , event_args ) in event_sequence :
1664
1683
do_event (tool , etype , ** event_args )
1684
+ np .testing .assert_allclose (tool .verts , verts , atol = atol )
1665
1685
1666
1686
# In order to trigger the correct callbacks, trigger events on the canvas
1667
1687
# instead of the individual tools
@@ -1676,7 +1696,7 @@ def test_polygon_selector_box(ax):
1676
1696
MouseEvent (
1677
1697
"button_release_event" , canvas , * t .transform ((20 , 20 )), 1 )._process ()
1678
1698
np .testing .assert_allclose (
1679
- tool .verts , [(10 , 0 ), (0 , 10 ), (10 , 20 ), (20 , 10 )])
1699
+ tool .verts , [(10 , 0 ), (0 , 10 ), (10 , 20 ), (20 , 10 )], atol = atol )
1680
1700
1681
1701
# Move using the center of the bounding box
1682
1702
MouseEvent (
@@ -1686,20 +1706,20 @@ def test_polygon_selector_box(ax):
1686
1706
MouseEvent (
1687
1707
"button_release_event" , canvas , * t .transform ((30 , 30 )), 1 )._process ()
1688
1708
np .testing .assert_allclose (
1689
- tool .verts , [(30 , 20 ), (20 , 30 ), (30 , 40 ), (40 , 30 )])
1709
+ tool .verts , [(30 , 20 ), (20 , 30 ), (30 , 40 ), (40 , 30 )], atol = atol )
1690
1710
1691
1711
# Remove a point from the polygon and check that the box extents update
1692
1712
np .testing .assert_allclose (
1693
- tool ._box .extents , (20.0 , 40.0 , 20.0 , 40.0 ))
1713
+ tool ._box .extents , (20.0 , 40.0 , 20.0 , 40.0 ), atol = atol )
1694
1714
1695
1715
MouseEvent (
1696
1716
"button_press_event" , canvas , * t .transform ((30 , 20 )), 3 )._process ()
1697
1717
MouseEvent (
1698
1718
"button_release_event" , canvas , * t .transform ((30 , 20 )), 3 )._process ()
1699
1719
np .testing .assert_allclose (
1700
- tool .verts , [(20 , 30 ), (30 , 40 ), (40 , 30 )])
1720
+ tool .verts , [(20 , 30 ), (30 , 40 ), (40 , 30 )], atol = atol )
1701
1721
np .testing .assert_allclose (
1702
- tool ._box .extents , (20.0 , 40.0 , 30.0 , 40.0 ))
1722
+ tool ._box .extents , (20.0 , 40.0 , 30.0 , 40.0 ), atol = atol )
1703
1723
1704
1724
1705
1725
def test_polygon_selector_clear_method (ax ):
0 commit comments