pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/matplotlib/matplotlib/commit/726af3868cd83b731045c8c17920ce324254b2c9

css" /> ENH: Snap 3D view angle changes when holding Control key (#31145) · matplotlib/matplotlib@726af38 · GitHub
Skip to content

Commit 726af38

Browse files
authored
ENH: Snap 3D view angle changes when holding Control key (#31145)
* Snap 3D rotation to 5 degree increments with Ctrl * Snap 3D rotation to 5 degree increments with Ctrl * Trigger CI rerun * Add rcParam axes3d.snap_rotation for configurable 3D rotation snapping * Add axes3d.snap_rotation rcParam and rotation snapping test * Add axes3d.snap_rotation rcParam and rotation snapping test * Update snap rotation test using MouseEvent interaction * Update snap rotation test * Add snap rotation interaction test * update test file * Include roll in snap_rotation and simplify snapping test * changes in test file * test update * set default to five * set default to five * use test_pan method * test file updated * test file debug * add next whats new * Re-trigger CI for coverage sync * test exact val
1 parent e3d6dfc commit 726af38

File tree

6 files changed

+91
-1
lines changed

6 files changed

+91
-1
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Snapping 3D rotation angles with Control key
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
3D axes rotation now supports snapping to fixed angular increments
5+
when holding the ``Control`` key during mouse rotation.
6+
7+
The snap step size is controlled by the new
8+
``axes3d.snap_rotation`` rcParam (default: 5.0 degrees).
9+
Setting it to 0 disables snapping.
10+
11+
For example::
12+
13+
mpl.rcParams["axes3d.snap_rotation"] = 10
14+
15+
will snap elevation, azimuth, and roll angles to multiples
16+
of 10 degrees while rotating with the mouse.

lib/matplotlib/mpl-data/matplotlibrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@
451451
# See also https://matplotlib.org/stable/api/toolkits/mplot3d/view_angles.html#rotation-with-mouse
452452
#axes3d.trackballsize: 0.667 # trackball diameter, in units of the Axes bbox
453453
#axes3d.trackballborder: 0.2 # trackball border width, in units of the Axes bbox (only for 'sphere' and 'arcball' style)
454-
454+
#axes3d.snap_rotation: 5.0 # Snap angle (degrees) for 3D rotation when holding Control.
455455
## ***************************************************************************
456456
## * AXIS *
457457
## ***************************************************************************

lib/matplotlib/rcsetup.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,6 +1184,7 @@ def _convert_validator_spec(key, conv):
11841184
"axes3d.mouserotationstyle": ["azel", "trackball", "sphere", "arcball"],
11851185
"axes3d.trackballsize": validate_float,
11861186
"axes3d.trackballborder": validate_float,
1187+
"axes3d.snap_rotation": validate_float,
11871188

11881189
# scatter props
11891190
"scatter.marker": _validate_marker,
@@ -2193,6 +2194,12 @@ class _Subsection:
21932194
"'sphere' and 'arcball' style)"
21942195
),
21952196
_Section("Axis"),
2197+
_Param(
2198+
"axes3d.snap_rotation",
2199+
default=5.0,
2200+
validator=validate_float,
2201+
description="Snap angle (in degrees) for 3D rotation when holding Control."
2202+
),
21962203
_Param(
21972204
"xaxis.labellocation",
21982205
default="center",

lib/matplotlib/typing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@
222222
"axes3d.grid",
223223
"axes3d.mouserotationstyle",
224224
"axes3d.trackballborder",
225+
"axes3d.snap_rotation",
225226
"axes3d.trackballsize",
226227
"axes3d.xaxis.panecolor",
227228
"axes3d.yaxis.panecolor",

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,11 @@ def _on_move(self, event):
15981598

15991599
q = dq * q
16001600
elev, azim, roll = np.rad2deg(q.as_cardan_angles())
1601+
step = mpl.rcParams["axes3d.snap_rotation"]
1602+
if step > 0 and getattr(event, "key", None) == "control":
1603+
elev = step * round(elev / step)
1604+
azim = step * round(azim / step)
1605+
roll = step * round(roll / step)
16011606

16021607
# update view
16031608
vertical_axis = self._axis_names[self._vertical_axis]

lib/mpl_toolkits/mplot3d/tests/test_axes3d.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2783,3 +2783,64 @@ def test_axis_get_tightbbox_includes_offset_text():
27832783
f"bbox.x1 ({bbox.x1}) should be >= offset_bbox.x1 ({offset_bbox.x1})"
27842784
assert bbox.y1 >= offset_bbox.y1 - 1e-6, \
27852785
f"bbox.y1 ({bbox.y1}) should be >= offset_bbox.y1 ({offset_bbox.y1})"
2786+
2787+
2788+
def test_ctrl_rotation_snaps_to_5deg():
2789+
fig = plt.figure()
2790+
ax = fig.add_subplot(projection='3d')
2791+
2792+
initial = (12.3, 33.7, 2.2)
2793+
ax.view_init(*initial)
2794+
fig.canvas.draw()
2795+
2796+
s = 0.25
2797+
step = plt.rcParams["axes3d.snap_rotation"]
2798+
2799+
# First rotation without Ctrl
2800+
with mpl.rc_context({'axes3d.mouserotationstyle': 'azel'}):
2801+
MouseEvent._from_ax_coords(
2802+
"button_press_event", ax, (0, 0), MouseButton.LEFT
2803+
)._process()
2804+
2805+
MouseEvent._from_ax_coords(
2806+
"motion_notify_event",
2807+
ax,
2808+
(s * ax._pseudo_w, s * ax._pseudo_h),
2809+
MouseButton.LEFT,
2810+
)._process()
2811+
2812+
fig.canvas.draw()
2813+
2814+
rotated_elev = ax.elev
2815+
rotated_azim = ax.azim
2816+
rotated_roll = ax.roll
2817+
2818+
# Reset before ctrl rotation
2819+
ax.view_init(*initial)
2820+
fig.canvas.draw()
2821+
2822+
# Now rotate with Ctrl
2823+
with mpl.rc_context({'axes3d.mouserotationstyle': 'azel'}):
2824+
MouseEvent._from_ax_coords(
2825+
"button_press_event", ax, (0, 0), MouseButton.LEFT
2826+
)._process()
2827+
2828+
MouseEvent._from_ax_coords(
2829+
"motion_notify_event",
2830+
ax,
2831+
(s * ax._pseudo_w, s * ax._pseudo_h),
2832+
MouseButton.LEFT,
2833+
key="control"
2834+
)._process()
2835+
2836+
fig.canvas.draw()
2837+
2838+
expected_elev = step * round(rotated_elev / step)
2839+
expected_azim = step * round(rotated_azim / step)
2840+
expected_roll = step * round(rotated_roll / step)
2841+
2842+
assert ax.elev == pytest.approx(expected_elev)
2843+
assert ax.azim == pytest.approx(expected_azim)
2844+
assert ax.roll == pytest.approx(expected_roll)
2845+
2846+
plt.close(fig)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

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:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy