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