Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Do not add padding to 3D axis limits when limits are manually set #25272

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/api/toolkits/mplot3d/axes3d.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,18 @@ Axis limits and direction

get_zaxis
get_xlim
set_xlim
get_ylim
set_ylim
get_zlim
set_zlim
get_w_lims
invert_zaxis
zaxis_inverted
get_xbound
set_xbound
get_ybound
set_ybound
get_zbound
set_zbound

Expand Down
18 changes: 18 additions & 0 deletions doc/users/next_whats_new/3d_axis_limits.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Setting 3D axis limits now set the limits exactly
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Previously, setting the limits of a 3D axis would always add a small margin to
the limits. Limits are now set exactly by default. The newly introduced rcparam
``axes3d.automargin`` can be used to revert to the old behavior where margin is
automatically added.

.. plot::
:include-source: true
:alt: Example of the new behavior of 3D axis limits, and how setting the rcparam reverts to the old behavior.

import matplotlib.pyplot as plt
fig, axs = plt.subplots(1, 2, subplot_kw={'projection': '3d'})
plt.rcParams['axes3d.automargin'] = False # the default in 3.9.0
axs[0].set(xlim=(0, 1), ylim=(0, 1), zlim=(0, 1), title='New Behavior')
plt.rcParams['axes3d.automargin'] = True
axs[1].set(xlim=(0, 1), ylim=(0, 1), zlim=(0, 1), title='Old Behavior')
19 changes: 15 additions & 4 deletions lib/matplotlib/axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -855,13 +855,14 @@ def _get_autoscale_on(self):
def _set_autoscale_on(self, b):
"""
Set whether this Axis is autoscaled when drawing or by
`.Axes.autoscale_view`.
`.Axes.autoscale_view`. If b is None, then the value is not changed.

Parameters
----------
b : bool
"""
self._autoscale_on = b
if b is not None:
self._autoscale_on = b

def get_children(self):
return [self.label, self.offsetText,
Expand Down Expand Up @@ -1244,8 +1245,7 @@ def _set_lim(self, v0, v1, *, emit=True, auto):
# Mark viewlims as no longer stale without triggering an autoscale.
for ax in self._get_shared_axes():
ax._stale_viewlims[name] = False
if auto is not None:
self._set_autoscale_on(bool(auto))
self._set_autoscale_on(auto)

if emit:
self.axes.callbacks.process(f"{name}lim_changed", self.axes)
Expand Down Expand Up @@ -1292,6 +1292,17 @@ def _update_ticks(self):
if view_low > view_high:
view_low, view_high = view_high, view_low

if (hasattr(self, "axes") and self.axes.name == '3d'
and mpl.rcParams['axes3d.automargin']):
# In mpl3.8, the margin was 1/48. Due to the change in automargin
# behavior in mpl3.9, we need to adjust this to compensate for a
# zoom factor of 2/48, giving us a 23/24 modifier. So the new
# margin is 0.019965277777777776 = 1/48*23/24.
margin = 0.019965277777777776
delta = view_high - view_low
view_high = view_high - delta * margin
view_low = view_low + delta * margin

interval_t = self.get_transform().transform([view_low, view_high])

ticks_to_draw = []
Expand Down
5 changes: 3 additions & 2 deletions lib/matplotlib/mpl-data/matplotlibrc
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,9 @@
#axes.autolimit_mode: data # If "data", use axes.xmargin and axes.ymargin as is.
# If "round_numbers", after application of margins, axis
# limits are further expanded to the nearest "round" number.
#polaraxes.grid: True # display grid on polar axes
#axes3d.grid: True # display grid on 3D axes
#polaraxes.grid: True # display grid on polar axes
#axes3d.grid: True # display grid on 3D axes
#axes3d.automargin: False # automatically add margin when manually setting 3D axis limits

#axes3d.xaxis.panecolor: (0.95, 0.95, 0.95, 0.5) # background pane on 3D axes
#axes3d.yaxis.panecolor: (0.90, 0.90, 0.90, 0.5) # background pane on 3D axes
Expand Down
3 changes: 2 additions & 1 deletion lib/matplotlib/mpl-data/stylelib/classic.mplstyle
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ axes.spines.left : True
axes.spines.right : True
axes.spines.top : True
polaraxes.grid : True # display grid on polar axes
axes3d.grid : True # display grid on 3d axes
axes3d.grid : True # display grid on 3D axes
axes3d.automargin : False # automatically add margin when manually setting 3D axis limits

date.autoformatter.year : %Y
date.autoformatter.month : %b %Y
Expand Down
6 changes: 4 additions & 2 deletions lib/matplotlib/rcsetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -1094,8 +1094,10 @@ def _convert_validator_spec(key, conv):
"axes.ymargin": _validate_greaterthan_minushalf, # margin added to yaxis
"axes.zmargin": _validate_greaterthan_minushalf, # margin added to zaxis

"polaraxes.grid": validate_bool, # display polar grid or not
"axes3d.grid": validate_bool, # display 3d grid
"polaraxes.grid": validate_bool, # display polar grid or not
"axes3d.grid": validate_bool, # display 3d grid
"axes3d.automargin": validate_bool, # automatically add margin when
# manually setting 3D axis limits

"axes3d.xaxis.panecolor": validate_color, # 3d background pane
"axes3d.yaxis.panecolor": validate_color, # 3d background pane
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/tests/test_collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ def test_EllipseCollection():
@image_comparison(['polycollection_close.png'], remove_text=True, style='mpl20')
def test_polycollection_close():
from mpl_toolkits.mplot3d import Axes3D # type: ignore
plt.rcParams['axes3d.automargin'] = True

vertsQuad = [
[[0., 0.], [0., 1.], [1., 1.], [1., 0.]],
Expand Down
5 changes: 5 additions & 0 deletions lib/matplotlib/ticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2106,6 +2106,11 @@ def _raw_ticks(self, vmin, vmax):
steps = steps[igood]

raw_step = ((_vmax - _vmin) / nbins)
if hasattr(self.axis, "axes") and self.axis.axes.name == '3d':
# Due to the change in automargin behavior in mpl3.9, we need to
# adjust the raw step to match the mpl3.8 appearance. The zoom
# factor of 2/48, gives us the 23/24 modifier.
raw_step = raw_step * 23/24
large_steps = steps >= raw_step
if mpl.rcParams['axes.autolimit_mode'] == 'round_numbers':
# Classic round_numbers mode may require a larger step.
Expand Down
Loading