diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index f72e2950100f..1480aacfec4d 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1898,55 +1898,42 @@ def apply_aspect(self, position=None): box_aspect = fig_aspect * (position.height / position.width) data_ratio = box_aspect / aspect - y_expander = data_ratio * xsize / ysize - 1 - # If y_expander > 0, the dy/dx viewLim ratio needs to increase - if abs(y_expander) < 0.005: + y_expander = data_ratio * xsize / ysize + # If y_expander > 1, the dy/dx viewLim ratio needs to increase + if abs(y_expander - 1) < 0.005: return - dL = self.dataLim - x0, x1 = x_trf.transform(dL.intervalx) - y0, y1 = y_trf.transform(dL.intervaly) - xr = 1.05 * (x1 - x0) - yr = 1.05 * (y1 - y0) - - xmarg = xsize - xr - ymarg = ysize - yr - Ysize = data_ratio * xsize - Xsize = ysize / data_ratio - Xmarg = Xsize - xr - Ymarg = Ysize - yr - # Setting these targets to, e.g., 0.05*xr does not seem to help. - xm = 0 - ym = 0 - + # What axes do we adjust? + # - We can't adjust shared axes because it's too easy to break sharing + # given the sequential handling of axes (that may be possible if we + # first collected all the constraints on all axes and considered them + # all at once). + # - Assuming no constraints from sharing, prefer expanding axes rather + # than shrinking them, as the latter can hide plot elements. shared_x = self in self._shared_x_axes shared_y = self in self._shared_y_axes - # Not sure whether we need this check: if shared_x and shared_y: raise RuntimeError("adjustable='datalim' is not allowed when both " "axes are shared") - - # If y is shared, then we are only allowed to change x, etc. - if shared_y: - adjust_y = False - else: - if xmarg > xm and ymarg > ym: - adjy = ((Ymarg > 0 and y_expander < 0) or - (Xmarg < 0 and y_expander > 0)) - else: - adjy = y_expander > 0 - adjust_y = shared_x or adjy # (Ymarg > xmarg) - - if adjust_y: - yc = 0.5 * (ymin + ymax) - y0 = yc - Ysize / 2.0 - y1 = yc + Ysize / 2.0 - self.set_ybound(y_trf.inverted().transform([y0, y1])) + if shared_x: + adjust = "y" + elif shared_y: + adjust = "x" + elif y_expander > 1: + adjust = "y" + else: # y_expander < 1 + adjust = "x" + + if adjust == "y": + yc = (ymin + ymax) / 2 + ymin = yc - (yc - ymin) * y_expander + ymax = yc + (ymax - yc) * y_expander + self.set_ybound(*map(y_trf.inverted().transform, (ymin, ymax))) else: - xc = 0.5 * (xmin + xmax) - x0 = xc - Xsize / 2.0 - x1 = xc + Xsize / 2.0 - self.set_xbound(x_trf.inverted().transform([x0, x1])) + xc = (xmin + xmax) / 2 + xmin = xc - (xc - xmin) / y_expander + xmax = xc + (xmax - xc) / y_expander + self.set_xbound(*map(x_trf.inverted().transform, (xmin, xmax))) def axis(self, *args, emit=True, **kwargs): """ diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 3736888fdde5..7ddf3afcea4a 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -5039,6 +5039,13 @@ def test_pie_frame_grid(): frame=True, center=(3, 5)) # Set aspect ratio to be equal so that pie is drawn as a circle. plt.axis('equal') + plt.gcf().canvas.draw() + xmin, xmax = plt.xlim() + ymin, ymax = plt.ylim() + assert xmin < 0 and xmax > 7 and ymin == 0 and ymax == 7 + # These limits reproduce an old, buggy implementation of axis("equal"). + plt.xlim(0, 7) + plt.ylim(0.7903225806451615, 6.209677419354838) @image_comparison(['pie_rotatelabels_true.png'])
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: