1717
1818import pytest
1919
20-
2120@pytest .fixture
2221def ax ():
2322 return get_ax ()
@@ -84,19 +83,20 @@ def test_rectangle_selector(ax, kwargs):
8483
8584 # purposely drag outside of axis for release
8685 do_event (tool , 'release' , xdata = 250 , ydata = 250 , button = 1 )
86+ do_event (tool , 'onmove' , xdata = 250 , ydata = 250 , button = 1 )
8787
8888 if kwargs .get ('drawtype' , None ) not in ['line' , 'none' ]:
8989 assert_allclose (tool .geometry ,
90- [[100. , 100 , 199 , 199 , 100 ],
90+ [[100 , 100 , 199 , 199 , 100 ],
9191 [100 , 199 , 199 , 100 , 100 ]],
9292 err_msg = tool .geometry )
9393
9494 onselect .assert_called_once ()
9595 (epress , erelease ), kwargs = onselect .call_args
9696 assert epress .xdata == 100
9797 assert epress .ydata == 100
98- assert erelease .xdata == 199
99- assert erelease .ydata == 199
98+ assert erelease .xdata == 200
99+ assert erelease .ydata == 200
100100 assert kwargs == {}
101101
102102
@@ -193,10 +193,16 @@ def test_rectangle_selector_set_props_handle_props(ax):
193193 assert artist .get_alpha () == 0.3
194194
195195
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 ):
197203 tool = widgets .RectangleSelector (ax , onselect = noop , interactive = True )
198204 # Create rectangle
199- click_and_drag (tool , start = ( 0 , 10 ), end = ( 100 , 120 ) )
205+ click_and_drag (tool , start = start , end = end )
200206 assert_allclose (tool .extents , (0.0 , 100.0 , 10.0 , 120.0 ))
201207
202208 # resize NE handle
@@ -317,16 +323,16 @@ def test_rectangle_resize_center(ax, add_state):
317323 xdata_new , ydata_new = xdata + xdiff , ydata + ydiff
318324 click_and_drag (tool , start = (xdata , ydata ), end = (xdata_new , ydata_new ),
319325 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 ) )
322328
323329
324330@pytest .mark .parametrize ('add_state' , [True , False ])
325331def test_rectangle_resize_square (ax , add_state ):
326332 tool = widgets .RectangleSelector (ax , onselect = noop , interactive = True )
327333 # Create rectangle
328334 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 ) )
330336
331337 if add_state :
332338 tool .add_state ('square' )
@@ -341,8 +347,8 @@ def test_rectangle_resize_square(ax, add_state):
341347 xdata_new , ydata_new = xdata + xdiff , ydata + ydiff
342348 click_and_drag (tool , start = (xdata , ydata ), end = (xdata_new , ydata_new ),
343349 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 ) )
346352
347353 # resize E handle
348354 extents = tool .extents
@@ -391,11 +397,12 @@ def test_rectangle_resize_square(ax, add_state):
391397 xdata_new , ydata_new = xdata + xdiff , ydata + ydiff
392398 click_and_drag (tool , start = (xdata , ydata ), end = (xdata_new , ydata_new ),
393399 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 ]))
396402
397403
398404def test_rectangle_resize_square_center (ax ):
405+ ax .set_aspect (1 )
399406 tool = widgets .RectangleSelector (ax , onselect = noop , interactive = True )
400407 # Create rectangle
401408 click_and_drag (tool , start = (70 , 65 ), end = (120 , 115 ))
@@ -461,6 +468,7 @@ def test_rectangle_resize_square_center(ax):
461468@pytest .mark .parametrize ('selector_class' ,
462469 [widgets .RectangleSelector , widgets .EllipseSelector ])
463470def test_rectangle_rotate (ax , selector_class ):
471+ ax .set_aspect (1 )
464472 tool = selector_class (ax , onselect = noop , interactive = True )
465473 # Draw rectangle
466474 click_and_drag (tool , start = (100 , 100 ), end = (130 , 140 ))
@@ -474,19 +482,19 @@ def test_rectangle_rotate(ax, selector_class):
474482 click_and_drag (tool , start = (130 , 140 ), end = (120 , 145 ))
475483 do_event (tool , 'on_key_press' , key = 'r' )
476484 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 )
479487 assert_allclose (tool .rotation , 25.56 , atol = 0.01 )
480488 tool .rotation = 45
481489 assert tool .rotation == 45
482490 # Corners should move
483491 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 )
486494
487495 # Scale using top-right corner
488496 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 )
490498
491499 if selector_class == widgets .RectangleSelector :
492500 with pytest .raises (ValueError ):
@@ -508,36 +516,38 @@ def test_rectangle_add_remove_set(ax):
508516
509517@pytest .mark .parametrize ('use_data_coordinates' , [False , True ])
510518def 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 ()
512523
513524 tool = widgets .RectangleSelector (ax , onselect = noop , interactive = True ,
514525 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 ))
518526 tool .add_state ('square' )
519527 tool .add_state ('center' )
528+ # Create rectangle, width 50 in data coordinates
529+ click_and_drag (tool , start = (70 , 65 ), end = (120 , 75 ))
520530
521531 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 ))
531533 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 ])
541551
542552
543553def test_ellipse (ax ):
@@ -1644,6 +1654,7 @@ def test_polygon_selector_verts_setter(fig_test, fig_ref, draw_bounding_box):
16441654 ]
16451655 for (etype , event_args ) in event_sequence :
16461656 do_event (tool_ref , etype , ** event_args )
1657+ np .testing .assert_allclose (tool_ref .verts , verts )
16471658
16481659
16491660def test_polygon_selector_box (ax ):
@@ -1658,10 +1669,19 @@ def test_polygon_selector_box(ax):
16581669 * polygon_place_vertex (* verts [0 ]),
16591670 ]
16601671
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+
16611680 # Create selector
16621681 tool = widgets .PolygonSelector (ax , onselect = noop , draw_bounding_box = True )
16631682 for (etype , event_args ) in event_sequence :
16641683 do_event (tool , etype , ** event_args )
1684+ np .testing .assert_allclose (tool .verts , verts , atol = atol )
16651685
16661686 # In order to trigger the correct callbacks, trigger events on the canvas
16671687 # instead of the individual tools
@@ -1676,7 +1696,7 @@ def test_polygon_selector_box(ax):
16761696 MouseEvent (
16771697 "button_release_event" , canvas , * t .transform ((20 , 20 )), 1 )._process ()
16781698 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 )
16801700
16811701 # Move using the center of the bounding box
16821702 MouseEvent (
@@ -1686,20 +1706,20 @@ def test_polygon_selector_box(ax):
16861706 MouseEvent (
16871707 "button_release_event" , canvas , * t .transform ((30 , 30 )), 1 )._process ()
16881708 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 )
16901710
16911711 # Remove a point from the polygon and check that the box extents update
16921712 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 )
16941714
16951715 MouseEvent (
16961716 "button_press_event" , canvas , * t .transform ((30 , 20 )), 3 )._process ()
16971717 MouseEvent (
16981718 "button_release_event" , canvas , * t .transform ((30 , 20 )), 3 )._process ()
16991719 np .testing .assert_allclose (
1700- tool .verts , [(20 , 30 ), (30 , 40 ), (40 , 30 )])
1720+ tool .verts , [(20 , 30 ), (30 , 40 ), (40 , 30 )], atol = atol )
17011721 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 )
17031723
17041724
17051725def test_polygon_selector_clear_method (ax ):
0 commit comments