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

Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
2 changes: 1 addition & 1 deletion lib/matplotlib/mpl-data/matplotlibrc
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@
# See also https://matplotlib.org/stable/api/toolkits/mplot3d/view_angles.html#rotation-with-mouse
#axes3d.trackballsize: 0.667 # trackball diameter, in units of the Axes bbox
#axes3d.trackballborder: 0.2 # trackball border width, in units of the Axes bbox (only for 'sphere' and 'arcball' style)

#axes3d.snap_rotation: 0.0 # Snap angle (degrees) for 3D rotation when holding Control.
## ***************************************************************************
## * AXIS *
## ***************************************************************************
Expand Down
7 changes: 7 additions & 0 deletions lib/matplotlib/rcsetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,7 @@ def _convert_validator_spec(key, conv):
"axes3d.mouserotationstyle": ["azel", "trackball", "sphere", "arcball"],
"axes3d.trackballsize": validate_float,
"axes3d.trackballborder": validate_float,
"axes3d.snap_rotation": validate_float,

# scatter props
"scatter.marker": _validate_marker,
Expand Down Expand Up @@ -2143,6 +2144,12 @@ class _Param:
description="trackball border width, in units of the Axes bbox (only for "
"'sphere' and 'arcball' style)"
),
_Param(
"axes3d.snap_rotation",
default=0.0,
validator=validate_float,
description="Snap angle (in degrees) for 3D rotation when holding Control."
),
_Param(
"xaxis.labellocation",
default="center",
Expand Down
1 change: 1 addition & 0 deletions lib/matplotlib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@
"axes3d.grid",
"axes3d.mouserotationstyle",
"axes3d.trackballborder",
"axes3d.snap_rotation",
"axes3d.trackballsize",
"axes3d.xaxis.panecolor",
"axes3d.yaxis.panecolor",
Expand Down
4 changes: 4 additions & 0 deletions lib/mpl_toolkits/mplot3d/axes3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -1597,6 +1597,10 @@ def _on_move(self, event):

q = dq * q
elev, azim, roll = np.rad2deg(q.as_cardan_angles())
step = mpl.rcParams["axes3d.snap_rotation"]
if step > 0 and getattr(event, "key", None) == "control":
elev = step * round(elev / step)
azim = step * round(azim / step)
Comment thread
scottshambaugh marked this conversation as resolved.

# update view
vertical_axis = self._axis_names[self._vertical_axis]
Expand Down
69 changes: 69 additions & 0 deletions lib/mpl_toolkits/mplot3d/tests/test_axes3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -2785,3 +2785,72 @@ def test_axis_get_tightbbox_includes_offset_text():
f"bbox.x1 ({bbox.x1}) should be >= offset_bbox.x1 ({offset_bbox.x1})"
assert bbox.y1 >= offset_bbox.y1 - 1e-6, \
f"bbox.y1 ({bbox.y1}) should be >= offset_bbox.y1 ({offset_bbox.y1})"


def test_ctrl_rotation_snaps_to_5deg(monkeypatch):
Comment thread
scottshambaugh marked this conversation as resolved.
Outdated
fig = plt.figure()
ax = fig.add_subplot(projection="3d")
fig.canvas.draw()

# Initial angles
initial_elev = 12.3
initial_azim = 33.7

ax.elev = initial_elev
ax.azim = initial_azim

# Enable snapping
monkeypatch.setitem(
plt.rcParams,
"axes3d.snap_rotation",
5,
)
monkeypatch.setitem(
plt.rcParams,
"axes3d.mouserotationstyle",
"azel",
)

captured = {}

# Capture snapped values
def fake_view_init(elev=None, azim=None, **kwargs):
captured["elev"] = kwargs.get("elev", elev)
captured["azim"] = kwargs.get("azim", azim)

monkeypatch.setattr(ax, "view_init", fake_view_init)
Comment thread
scottshambaugh marked this conversation as resolved.
Outdated

press_event = MouseEvent(
"button_press_event",
fig.canvas,
x=100,
y=100,
button=1,
)
press_event.inaxes = ax
ax._button_press(press_event)

ax._sx, ax._sy = press_event.x, press_event.y

move_event = MouseEvent(
"motion_notify_event",
fig.canvas,
x=120,
y=120,
button=1,
key="control",
)
move_event.inaxes = ax


ax._on_move(move_event)

step = plt.rcParams["axes3d.snap_rotation"]

expected_elev = step * round(initial_elev / step)
expected_azim = step * round(initial_azim / step)

assert captured["elev"] == pytest.approx(expected_elev)
assert captured["azim"] == pytest.approx(expected_azim)
Comment thread
scottshambaugh marked this conversation as resolved.
Outdated

plt.close(fig)
Loading