@@ -2402,14 +2402,14 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True):
24022402 (self ._xmargin and scalex and self ._autoscaleXon ) or
24032403 (self ._ymargin and scaley and self ._autoscaleYon )):
24042404 stickies = [artist .sticky_edges for artist in self .get_children ()]
2405- x_stickies = np .array ([x for sticky in stickies for x in sticky .x ])
2406- y_stickies = np .array ([y for sticky in stickies for y in sticky .y ])
2407- if self .get_xscale ().lower () == 'log' :
2408- x_stickies = x_stickies [x_stickies > 0 ]
2409- if self .get_yscale ().lower () == 'log' :
2410- y_stickies = y_stickies [y_stickies > 0 ]
24112405 else : # Small optimization.
2412- x_stickies , y_stickies = [], []
2406+ stickies = []
2407+ x_stickies = np .sort ([x for sticky in stickies for x in sticky .x ])
2408+ y_stickies = np .sort ([y for sticky in stickies for y in sticky .y ])
2409+ if self .get_xscale ().lower () == 'log' :
2410+ x_stickies = x_stickies [x_stickies > 0 ]
2411+ if self .get_yscale ().lower () == 'log' :
2412+ y_stickies = y_stickies [y_stickies > 0 ]
24132413
24142414 def handle_single_axis (scale , autoscaleon , shared_axes , interval ,
24152415 minpos , axis , margin , stickies , set_bound ):
@@ -2450,29 +2450,34 @@ def handle_single_axis(scale, autoscaleon, shared_axes, interval,
24502450 locator = axis .get_major_locator ()
24512451 x0 , x1 = locator .nonsingular (x0 , x1 )
24522452
2453+ # Prevent margin addition from crossing a sticky value. Small
2454+ # tolerances (whose values come from isclose()) must be used due to
2455+ # floating point issues with streamplot.
2456+ def tol (x ): return 1e-5 * abs (x ) + 1e-8
2457+ # Index of largest element < x0 + tol, if any.
2458+ i0 = stickies .searchsorted (x0 + tol (x0 )) - 1
2459+ x0bound = stickies [i0 ] if i0 != - 1 else None
2460+ # Index of smallest element > x1 - tol, if any.
2461+ i1 = stickies .searchsorted (x1 - tol (x1 ))
2462+ x1bound = stickies [i1 ] if i1 != len (stickies ) else None
2463+
24532464 # Add the margin in figure space and then transform back, to handle
24542465 # non-linear scales.
24552466 minpos = getattr (bb , minpos )
24562467 transform = axis .get_transform ()
24572468 inverse_trans = transform .inverted ()
2458- # We cannot use exact equality due to floating point issues e.g.
2459- # with streamplot.
2460- do_lower_margin = not np .any (np .isclose (x0 , stickies ))
2461- do_upper_margin = not np .any (np .isclose (x1 , stickies ))
24622469 x0 , x1 = axis ._scale .limit_range_for_scale (x0 , x1 , minpos )
24632470 x0t , x1t = transform .transform ([x0 , x1 ])
2464-
2465- if np .isfinite (x1t ) and np .isfinite (x0t ):
2466- delta = (x1t - x0t ) * margin
2467- else :
2468- # If at least one bound isn't finite, set margin to zero
2469- delta = 0
2470-
2471- if do_lower_margin :
2472- x0t -= delta
2473- if do_upper_margin :
2474- x1t += delta
2475- x0 , x1 = inverse_trans .transform ([x0t , x1t ])
2471+ delta = (x1t - x0t ) * margin
2472+ if not np .isfinite (delta ):
2473+ delta = 0 # If a bound isn't finite, set margin to zero.
2474+ x0 , x1 = inverse_trans .transform ([x0t - delta , x1t + delta ])
2475+
2476+ # Apply sticky bounds.
2477+ if x0bound is not None :
2478+ x0 = max (x0 , x0bound )
2479+ if x1bound is not None :
2480+ x1 = min (x1 , x1bound )
24762481
24772482 if not self ._tight :
24782483 x0 , x1 = locator .view_limits (x0 , x1 )
0 commit comments