@@ -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
0 commit comments