@@ -1990,14 +1990,10 @@ def on_key_press(self, event):
19901990 self .update ()
19911991 return
19921992 for (state , modifier ) in self ._state_modifier_keys .items ():
1993- if modifier in key .split ('+' ):
1994- # rotate and data_coordinates are enable/disable
1995- # on key press
1996- if (state in ['rotate' , 'data_coordinates' ] and
1997- state in self ._state ):
1998- self ._state .discard (state )
1999- else :
2000- self ._state .add (state )
1993+ # 'rotate' and 'data_coordinates' are added in _default_state
1994+ if (modifier in key .split ('+' ) and
1995+ state not in ['rotate' , 'data_coordinates' ]):
1996+ self ._state .add (state )
20011997 self ._on_key_press (event )
20021998
20031999 def _on_key_press (self , event ):
@@ -2007,9 +2003,9 @@ def on_key_release(self, event):
20072003 """Key release event handler and validator."""
20082004 if self .active :
20092005 key = event .key or ''
2006+ key = key .replace ('ctrl' , 'control' )
20102007 for (state , modifier ) in self ._state_modifier_keys .items ():
2011- if (modifier in key .split ('+' ) and
2012- state not in ['rotate' , 'data_coordinates' ]):
2008+ if modifier in key .split ('+' ):
20132009 self ._state .discard (state )
20142010 self ._on_key_release (event )
20152011
@@ -2795,7 +2791,8 @@ def __init__(self, ax, onselect, drawtype='box',
27952791 self ._interactive = interactive
27962792 self .drag_from_anywhere = drag_from_anywhere
27972793 self .ignore_event_outside = ignore_event_outside
2798- self ._rotation = 0
2794+ self ._rotation = 0.0
2795+ self ._aspect_ratio_correction = 1.0
27992796
28002797 if drawtype == 'none' : # draw a line but make it invisible
28012798 _api .warn_deprecated (
@@ -2814,6 +2811,7 @@ def __init__(self, ax, onselect, drawtype='box',
28142811 _props = props
28152812 self .visible = _props .pop ('visible' , self .visible )
28162813 self ._to_draw = self ._init_shape (** _props )
2814+ self ._set_aspect_ratio_correction ()
28172815 self .ax .add_patch (self ._to_draw )
28182816 if drawtype == 'line' :
28192817 _api .warn_deprecated (
@@ -2909,6 +2907,7 @@ def _press(self, event):
29092907 self .set_visible (True )
29102908
29112909 self ._extents_on_press = self .extents
2910+ self ._rotation_on_press = self ._rotation
29122911
29132912 return False
29142913
@@ -2984,13 +2983,8 @@ def _onmove(self, event):
29842983 dy = event .ydata - eventpress .ydata
29852984 refmax = None
29862985 if 'data_coordinates' in state :
2987- aspect_ratio = 1
29882986 refx , refy = dx , dy
29892987 else :
2990- figure_size = self .ax .get_figure ().get_size_inches ()
2991- ll , ur = self .ax .get_position () * figure_size
2992- width , height = ur - ll
2993- aspect_ratio = height / width * self .ax .get_data_ratio ()
29942988 refx = event .xdata / (eventpress .xdata + 1e-6 )
29952989 refy = event .ydata / (eventpress .ydata + 1e-6 )
29962990
@@ -3001,8 +2995,9 @@ def _onmove(self, event):
30012995 a = np .array ([eventpress .xdata , eventpress .ydata ])
30022996 b = np .array (self .center )
30032997 c = np .array ([event .xdata , event .ydata ])
3004- self ._rotation = (np .arctan2 (c [1 ]- b [1 ], c [0 ]- b [0 ]) -
3005- np .arctan2 (a [1 ]- b [1 ], a [0 ]- b [0 ]))
2998+ angle = (np .arctan2 (c [1 ]- b [1 ], c [0 ]- b [0 ]) -
2999+ np .arctan2 (a [1 ]- b [1 ], a [0 ]- b [0 ]))
3000+ self ._rotation = self ._rotation_on_press + angle
30063001
30073002 # resize an existing shape
30083003 elif self ._active_handle and self ._active_handle != 'C' :
@@ -3017,10 +3012,10 @@ def _onmove(self, event):
30173012 refmax = max (refx , refy , key = abs )
30183013 if self ._active_handle in ['E' , 'W' ] or refmax == refx :
30193014 dw = event .xdata - center [0 ]
3020- dh = dw / aspect_ratio
3015+ dh = dw
30213016 else :
30223017 dh = event .ydata - center [1 ]
3023- dw = dh * aspect_ratio
3018+ dw = dh
30243019 else :
30253020 dw = sizepress [0 ] / 2
30263021 dh = sizepress [1 ] / 2
@@ -3053,10 +3048,10 @@ def _onmove(self, event):
30533048 refmax = max (refx , refy , key = abs )
30543049 if self ._active_handle in ['E' , 'W' ] or refmax == refx :
30553050 sign = np .sign (event .ydata - y0 )
3056- y1 = y0 + sign * abs (x1 - x0 ) / aspect_ratio
3051+ y1 = y0 + sign * abs (x1 - x0 )
30573052 else :
30583053 sign = np .sign (event .xdata - x0 )
3059- x1 = x0 + sign * abs (y1 - y0 ) * aspect_ratio
3054+ x1 = x0 + sign * abs (y1 - y0 )
30603055
30613056 # move existing shape
30623057 elif self ._active_handle == 'C' :
@@ -3083,9 +3078,9 @@ def _onmove(self, event):
30833078 if 'square' in state :
30843079 refmax = max (refx , refy , key = abs )
30853080 if refmax == refx :
3086- dy = dx / aspect_ratio
3081+ dy = dx
30873082 else :
3088- dx = dy * aspect_ratio
3083+ dx = dy
30893084
30903085 # from center
30913086 if 'center' in state :
@@ -3102,6 +3097,18 @@ def _onmove(self, event):
31023097
31033098 self .extents = x0 , x1 , y0 , y1
31043099
3100+ def _on_key_press (self , event ):
3101+ key = event .key or ''
3102+ key = key .replace ('ctrl' , 'control' )
3103+ for (state , modifier ) in self ._state_modifier_keys .items ():
3104+ if modifier in key .split ('+' ):
3105+ if state in ['rotate' , 'data_coordinates' ]:
3106+ if state in self ._default_state :
3107+ self ._default_state .discard (state )
3108+ else :
3109+ self ._default_state .add (state )
3110+ self ._set_aspect_ratio_correction ()
3111+
31053112 @property
31063113 def _rect_bbox (self ):
31073114 if self ._drawtype == 'box' :
@@ -3112,8 +3119,19 @@ def _rect_bbox(self):
31123119 y0 , y1 = min (y ), max (y )
31133120 return x0 , y0 , x1 - x0 , y1 - y0
31143121
3122+ def _set_aspect_ratio_correction (self ):
3123+ if 'data_coordinates' in self ._state | self ._default_state :
3124+ self ._aspect_ratio_correction = 1
3125+ else :
3126+ self ._aspect_ratio_correction = self .ax ._get_aspect_ratio ()
3127+ self ._to_draw ._aspect_ratio_correction = self ._aspect_ratio_correction
3128+
31153129 def _get_rotation_transform (self ):
3116- return Affine2D ().rotate_around (* self .center , self ._rotation )
3130+ return Affine2D ().translate (- self .center [0 ], - self .center [1 ]) \
3131+ .scale (1 , self ._aspect_ratio_correction ) \
3132+ .rotate (self ._rotation ) \
3133+ .scale (1 , 1 / self ._aspect_ratio_correction ) \
3134+ .translate (* self .center )
31173135
31183136 @property
31193137 def corners (self ):
@@ -3285,7 +3303,7 @@ def _draw_shape(self, extents):
32853303 self ._to_draw .center = center
32863304 self ._to_draw .width = 2 * a
32873305 self ._to_draw .height = 2 * b
3288- self ._to_draw .set_angle ( self .rotation )
3306+ self ._to_draw .angle = self .rotation
32893307 else :
32903308 rad = np .deg2rad (np .arange (31 ) * 12 )
32913309 x = a * np .cos (rad ) + center [0 ]
0 commit comments