1+ import functools
2+
13from matplotlib ._api .deprecation import MatplotlibDeprecationWarning
24import matplotlib .colors as mcolors
35import matplotlib .widgets as widgets
@@ -1112,7 +1114,8 @@ def test_range_slider(orientation):
11121114 assert_allclose (slider .val , [0.1 , 0.34 ])
11131115
11141116
1115- def check_polygon_selector (event_sequence , expected_result , selections_count ):
1117+ def check_polygon_selector (event_sequence , expected_result , selections_count ,
1118+ ** kwargs ):
11161119 """
11171120 Helper function to test Polygon Selector.
11181121
@@ -1129,6 +1132,8 @@ def check_polygon_selector(event_sequence, expected_result, selections_count):
11291132 selections_count : int
11301133 Wait for the tool to call its `onselect` function `selections_count`
11311134 times, before comparing the result to the `expected_result`
1135+ **kwargs
1136+ Keyword arguments are passed to PolygonSelector.
11321137 """
11331138 ax = get_ax ()
11341139
@@ -1138,7 +1143,7 @@ def onselect(vertices):
11381143 ax ._selections_count += 1
11391144 ax ._current_result = vertices
11401145
1141- tool = widgets .PolygonSelector (ax , onselect )
1146+ tool = widgets .PolygonSelector (ax , onselect , ** kwargs )
11421147
11431148 for (etype , event_args ) in event_sequence :
11441149 do_event (tool , etype , ** event_args )
@@ -1159,14 +1164,18 @@ def polygon_remove_vertex(xdata, ydata):
11591164 ('release' , dict (xdata = xdata , ydata = ydata , button = 3 ))]
11601165
11611166
1162- def test_polygon_selector ():
1167+ @pytest .mark .parametrize ('draw_bounding_box' , [False , True ])
1168+ def test_polygon_selector (draw_bounding_box ):
1169+ check_selector = functools .partial (
1170+ check_polygon_selector , draw_bounding_box = draw_bounding_box )
1171+
11631172 # Simple polygon
11641173 expected_result = [(50 , 50 ), (150 , 50 ), (50 , 150 )]
11651174 event_sequence = (polygon_place_vertex (50 , 50 )
11661175 + polygon_place_vertex (150 , 50 )
11671176 + polygon_place_vertex (50 , 150 )
11681177 + polygon_place_vertex (50 , 50 ))
1169- check_polygon_selector (event_sequence , expected_result , 1 )
1178+ check_selector (event_sequence , expected_result , 1 )
11701179
11711180 # Move first vertex before completing the polygon.
11721181 expected_result = [(75 , 50 ), (150 , 50 ), (50 , 150 )]
@@ -1180,7 +1189,7 @@ def test_polygon_selector():
11801189 ('on_key_release' , dict (key = 'control' ))]
11811190 + polygon_place_vertex (50 , 150 )
11821191 + polygon_place_vertex (75 , 50 ))
1183- check_polygon_selector (event_sequence , expected_result , 1 )
1192+ check_selector (event_sequence , expected_result , 1 )
11841193
11851194 # Move first two vertices at once before completing the polygon.
11861195 expected_result = [(50 , 75 ), (150 , 75 ), (50 , 150 )]
@@ -1194,7 +1203,7 @@ def test_polygon_selector():
11941203 ('on_key_release' , dict (key = 'shift' ))]
11951204 + polygon_place_vertex (50 , 150 )
11961205 + polygon_place_vertex (50 , 75 ))
1197- check_polygon_selector (event_sequence , expected_result , 1 )
1206+ check_selector (event_sequence , expected_result , 1 )
11981207
11991208 # Move first vertex after completing the polygon.
12001209 expected_result = [(75 , 50 ), (150 , 50 ), (50 , 150 )]
@@ -1206,7 +1215,7 @@ def test_polygon_selector():
12061215 ('press' , dict (xdata = 50 , ydata = 50 )),
12071216 ('onmove' , dict (xdata = 75 , ydata = 50 )),
12081217 ('release' , dict (xdata = 75 , ydata = 50 ))])
1209- check_polygon_selector (event_sequence , expected_result , 2 )
1218+ check_selector (event_sequence , expected_result , 2 )
12101219
12111220 # Move all vertices after completing the polygon.
12121221 expected_result = [(75 , 75 ), (175 , 75 ), (75 , 175 )]
@@ -1220,7 +1229,7 @@ def test_polygon_selector():
12201229 ('onmove' , dict (xdata = 125 , ydata = 125 )),
12211230 ('release' , dict (xdata = 125 , ydata = 125 )),
12221231 ('on_key_release' , dict (key = 'shift' ))])
1223- check_polygon_selector (event_sequence , expected_result , 2 )
1232+ check_selector (event_sequence , expected_result , 2 )
12241233
12251234 # Try to move a vertex and move all before placing any vertices.
12261235 expected_result = [(50 , 50 ), (150 , 50 ), (50 , 150 )]
@@ -1240,7 +1249,7 @@ def test_polygon_selector():
12401249 + polygon_place_vertex (150 , 50 )
12411250 + polygon_place_vertex (50 , 150 )
12421251 + polygon_place_vertex (50 , 50 ))
1243- check_polygon_selector (event_sequence , expected_result , 1 )
1252+ check_selector (event_sequence , expected_result , 1 )
12441253
12451254 # Try to place vertex out-of-bounds, then reset, and start a new polygon.
12461255 expected_result = [(50 , 50 ), (150 , 50 ), (50 , 150 )]
@@ -1252,10 +1261,11 @@ def test_polygon_selector():
12521261 + polygon_place_vertex (150 , 50 )
12531262 + polygon_place_vertex (50 , 150 )
12541263 + polygon_place_vertex (50 , 50 ))
1255- check_polygon_selector (event_sequence , expected_result , 1 )
1264+ check_selector (event_sequence , expected_result , 1 )
12561265
12571266
1258- def test_polygon_selector_set_props_handle_props ():
1267+ @pytest .mark .parametrize ('draw_bounding_box' , [False , True ])
1268+ def test_polygon_selector_set_props_handle_props (draw_bounding_box ):
12591269 ax = get_ax ()
12601270
12611271 ax ._selections_count = 0
@@ -1266,7 +1276,8 @@ def onselect(vertices):
12661276
12671277 tool = widgets .PolygonSelector (ax , onselect ,
12681278 props = dict (color = 'b' , alpha = 0.2 ),
1269- handle_props = dict (alpha = 0.5 ))
1279+ handle_props = dict (alpha = 0.5 ),
1280+ draw_bounding_box = draw_bounding_box )
12701281
12711282 event_sequence = (polygon_place_vertex (50 , 50 )
12721283 + polygon_place_vertex (150 , 50 )
@@ -1308,7 +1319,8 @@ def onselect(verts):
13081319
13091320# Change the order that the extra point is inserted in
13101321@pytest .mark .parametrize ('idx' , [1 , 2 , 3 ])
1311- def test_polygon_selector_remove (idx ):
1322+ @pytest .mark .parametrize ('draw_bounding_box' , [False , True ])
1323+ def test_polygon_selector_remove (idx , draw_bounding_box ):
13121324 verts = [(50 , 50 ), (150 , 50 ), (50 , 150 )]
13131325 event_sequence = [polygon_place_vertex (* verts [0 ]),
13141326 polygon_place_vertex (* verts [1 ]),
@@ -1321,20 +1333,24 @@ def test_polygon_selector_remove(idx):
13211333 event_sequence .append (polygon_remove_vertex (200 , 200 ))
13221334 # Flatten list of lists
13231335 event_sequence = sum (event_sequence , [])
1324- check_polygon_selector (event_sequence , verts , 2 )
1336+ check_polygon_selector (event_sequence , verts , 2 ,
1337+ draw_bounding_box = draw_bounding_box )
13251338
13261339
1327- def test_polygon_selector_remove_first_point ():
1340+ @pytest .mark .parametrize ('draw_bounding_box' , [False , True ])
1341+ def test_polygon_selector_remove_first_point (draw_bounding_box ):
13281342 verts = [(50 , 50 ), (150 , 50 ), (50 , 150 )]
13291343 event_sequence = (polygon_place_vertex (* verts [0 ]) +
13301344 polygon_place_vertex (* verts [1 ]) +
13311345 polygon_place_vertex (* verts [2 ]) +
13321346 polygon_place_vertex (* verts [0 ]) +
13331347 polygon_remove_vertex (* verts [0 ]))
1334- check_polygon_selector (event_sequence , verts [1 :], 2 )
1348+ check_polygon_selector (event_sequence , verts [1 :], 2 ,
1349+ draw_bounding_box = draw_bounding_box )
13351350
13361351
1337- def test_polygon_selector_redraw ():
1352+ @pytest .mark .parametrize ('draw_bounding_box' , [False , True ])
1353+ def test_polygon_selector_redraw (draw_bounding_box ):
13381354 verts = [(50 , 50 ), (150 , 50 ), (50 , 150 )]
13391355 event_sequence = (polygon_place_vertex (* verts [0 ]) +
13401356 polygon_place_vertex (* verts [1 ]) +
@@ -1352,7 +1368,8 @@ def test_polygon_selector_redraw():
13521368 def onselect (vertices ):
13531369 pass
13541370
1355- tool = widgets .PolygonSelector (ax , onselect )
1371+ tool = widgets .PolygonSelector (ax , onselect ,
1372+ draw_bounding_box = draw_bounding_box )
13561373 for (etype , event_args ) in event_sequence :
13571374 do_event (tool , etype , ** event_args )
13581375 # After removing two verts, only one remains, and the
@@ -1382,6 +1399,56 @@ def onselect(vertices):
13821399 do_event (tool_ref , etype , ** event_args )
13831400
13841401
1402+ def test_polygon_selector_box ():
1403+ # Create a diamond shape
1404+ verts = [(20 , 0 ), (0 , 20 ), (20 , 40 ), (40 , 20 )]
1405+ event_sequence = (polygon_place_vertex (* verts [0 ]) +
1406+ polygon_place_vertex (* verts [1 ]) +
1407+ polygon_place_vertex (* verts [2 ]) +
1408+ polygon_place_vertex (* verts [3 ]) +
1409+ polygon_place_vertex (* verts [0 ]))
1410+
1411+ ax = get_ax ()
1412+
1413+ def onselect (vertices ):
1414+ pass
1415+
1416+ # Create selector
1417+ tool = widgets .PolygonSelector (ax , onselect , draw_bounding_box = True )
1418+ for (etype , event_args ) in event_sequence :
1419+ do_event (tool , etype , ** event_args )
1420+
1421+ # In order to trigger the correct callbacks, trigger events on the canvas
1422+ # instead of the individual tools
1423+ t = ax .transData
1424+ canvas = ax .figure .canvas
1425+
1426+ # Scale to half size using the top right corner of the bounding box
1427+ canvas .button_press_event (* t .transform ((40 , 40 )), 1 )
1428+ canvas .motion_notify_event (* t .transform ((20 , 20 )))
1429+ canvas .button_release_event (* t .transform ((20 , 20 )), 1 )
1430+ np .testing .assert_allclose (
1431+ tool .verts , [(10 , 0 ), (0 , 10 ), (10 , 20 ), (20 , 10 )])
1432+
1433+ # Move using the center of the bounding box
1434+ canvas .button_press_event (* t .transform ((10 , 10 )), 1 )
1435+ canvas .motion_notify_event (* t .transform ((30 , 30 )))
1436+ canvas .button_release_event (* t .transform ((30 , 30 )), 1 )
1437+ np .testing .assert_allclose (
1438+ tool .verts , [(30 , 20 ), (20 , 30 ), (30 , 40 ), (40 , 30 )])
1439+
1440+ # Remove a point from the polygon and check that the box extents update
1441+ np .testing .assert_allclose (
1442+ tool ._box .extents , (20.0 , 40.0 , 20.0 , 40.0 ))
1443+
1444+ canvas .button_press_event (* t .transform ((30 , 20 )), 3 )
1445+ canvas .button_release_event (* t .transform ((30 , 20 )), 3 )
1446+ np .testing .assert_allclose (
1447+ tool .verts , [(20 , 30 ), (30 , 40 ), (40 , 30 )])
1448+ np .testing .assert_allclose (
1449+ tool ._box .extents , (20.0 , 40.0 , 30.0 , 40.0 ))
1450+
1451+
13851452@pytest .mark .parametrize (
13861453 "horizOn, vertOn" ,
13871454 [(True , True ), (True , False ), (False , True )],
0 commit comments