Skip to content

Commit a12357a

Browse files
Commonize 3D zmargin handling with x and y axes
1 parent 7d04cf5 commit a12357a

38 files changed

Lines changed: 31 additions & 41 deletions

lib/matplotlib/mpl-data/stylelib/classic.mplstyle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,9 @@ axes.prop_cycle : cycler('color', 'bgrcmyk')
216216
# single letter, long name, or
217217
# web-style hex
218218
axes.autolimit_mode : round_numbers
219-
axes.xmargin : 0 # x margin. See `axes.Axes.margins`
220-
axes.ymargin : 0 # y margin See `axes.Axes.margins`
219+
axes.xmargin : 0 # x margin. See `axes.Axes.margins`
220+
axes.ymargin : 0 # y margin. See `axes.Axes.margins`
221+
axes.zmargin : 0 # z margin. See `axes.Axes.margins`
221222
axes.spines.bottom : True
222223
axes.spines.left : True
223224
axes.spines.right : True

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,10 @@ def __init__(
153153

154154
self.xy_viewLim = Bbox.unit()
155155
self.zz_viewLim = Bbox.unit()
156-
xymargin = 0.05 * 10/11 # match mpl3.8 appearance
157-
self.xy_dataLim = Bbox([[xymargin, xymargin],
158-
[1 - xymargin, 1 - xymargin]])
159-
# z-limits are encoded in the x-component of the Bbox, y is un-used
160-
self.zz_dataLim = Bbox.unit()
156+
self._xmargin = mpl.rcParams['axes.xmargin']
157+
self._ymargin = mpl.rcParams['axes.ymargin']
158+
self._zmargin = mpl.rcParams['axes.zmargin']
159+
self._init_dataLims()
161160

162161
# inhibit autoscale_view until the axes are defined
163162
# they can't be defined until Axes.__init__ has been called
@@ -598,6 +597,25 @@ def margins(self, *margins, x=None, y=None, z=None, tight=True):
598597
scalez=(z is not None)
599598
)
600599

600+
def _init_dataLims(self):
601+
"""Reset dataLim bboxes for empty-plot defaults.
602+
603+
The per-axis padding ensures that the margin expansion in autoscale_view
604+
cancels out exactly, landing on [0, 1] for empty plots.
605+
"""
606+
def pad(margin):
607+
# Note margin is validated to be > -0.5 in rcParams and set_x/y/zmargin
608+
return margin / (1 + 2 * margin) if margin > 0 else 0
609+
610+
xpad = pad(self._xmargin)
611+
ypad = pad(self._ymargin)
612+
zpad = pad(self._zmargin)
613+
self.xy_dataLim = Bbox([[xpad, ypad],
614+
[1 - xpad, 1 - ypad]])
615+
# z-limits are encoded in the x-component of the Bbox, y is un-used
616+
self.zz_dataLim = Bbox([[zpad, 0],
617+
[1 - zpad, 1]])
618+
601619
def autoscale(self, enable=True, axis='both', tight=None):
602620
"""
603621
Convenience method for simple axis view autoscaling.
@@ -1135,18 +1153,6 @@ def _set_axis_scale(self, axis, value, **kwargs):
11351153
**kwargs
11361154
Forwarded to scale constructor.
11371155
"""
1138-
# For non-linear scales on the z-axis, switch from the [0, 1] +
1139-
# margin=0 representation to the same xymargin + margin=0.05
1140-
# representation that x/y use. Both produce identical linear limits,
1141-
# but only the xymargin form has valid positive lower bounds for log
1142-
# etc. This must happen before _set_axes_scale because that triggers
1143-
# autoscale_view internally.
1144-
if (axis is self.zaxis and value != 'linear'
1145-
and np.array_equal(self.zz_dataLim.get_points(), [[0, 0], [1, 1]])):
1146-
xymargin = 0.05 * 10/11
1147-
self.zz_dataLim = Bbox([[xymargin, xymargin],
1148-
[1 - xymargin, 1 - xymargin]])
1149-
self._zmargin = self._xmargin
11501156
axis._set_axes_scale(value, **kwargs)
11511157

11521158
def set_xscale(self, value, **kwargs):
@@ -1549,16 +1555,8 @@ def shareview(self, other):
15491555
def clear(self):
15501556
# docstring inherited.
15511557
super().clear()
1552-
if self._focal_length == np.inf:
1553-
self._zmargin = mpl.rcParams['axes.zmargin']
1554-
else:
1555-
self._zmargin = 0.
1556-
1557-
xymargin = 0.05 * 10/11 # match mpl3.8 appearance
1558-
self.xy_dataLim = Bbox([[xymargin, xymargin],
1559-
[1 - xymargin, 1 - xymargin]])
1560-
# z-limits are encoded in the x-component of the Bbox, y is un-used
1561-
self.zz_dataLim = Bbox.unit()
1558+
self._zmargin = mpl.rcParams['axes.zmargin'] # x, y are set in super().clear()
1559+
self._init_dataLims()
15621560
self._view_margin = 1/48 # default value to match mpl3.8
15631561
self.autoscale_view()
15641562

@@ -3228,9 +3226,6 @@ def scatter(self, xs, ys, zs=0, zdir='z', s=20, c=None, depthshade=None,
32283226
depthshade_minalpha=depthshade_minalpha,
32293227
axlim_clip=axlim_clip,
32303228
)
3231-
if self._zmargin < 0.05 and xs.size > 0:
3232-
self.set_zmargin(0.05)
3233-
32343229
self.auto_scale_xyz(xs, ys, zs, had_data)
32353230

32363231
return patches
-11.4 KB
Loading
-7.23 KB
Loading
-14.2 KB
Loading
-4.81 KB
Loading
-12.5 KB
Loading
-7.3 KB
Loading
-13.9 KB
Loading
-9.07 KB
Loading

0 commit comments

Comments
 (0)