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

Skip to content

ENH: Snap 3D view angle changes when holding Control key#31145

Merged
timhoffm merged 21 commits intomatplotlib:mainfrom
Chirag3841:snap-3d-ctrl
Mar 4, 2026
Merged

ENH: Snap 3D view angle changes when holding Control key#31145
timhoffm merged 21 commits intomatplotlib:mainfrom
Chirag3841:snap-3d-ctrl

Conversation

@Chirag3841
Copy link
Copy Markdown
Contributor

PR summary

PR checklist

Description

This PR adds a Ctrl modifier key to 3D mouse rotation so that when Ctrl is held while dragging, the view angles snap to fixed 5° increments (azimuth/elevation/roll). This makes it easier to return to repeatable camera angles when exploring 3D plots.

A small test is included to verify snapping behavior when Ctrl is pressed.

@Chirag3841 Chirag3841 force-pushed the snap-3d-ctrl branch 2 times, most recently from 5b91598 to 2f47b9a Compare February 13, 2026 15:10
@scottshambaugh
Copy link
Copy Markdown
Contributor

This works really nicely! A few things to add to this:

  • I think the snap angle should be an rcParam rather than hardcoded to 5 degrees
  • Please add a what's new entry for this
  • We should document this behavior somewhere, I think a brief note here is probably the best place for right now: https://matplotlib.org/devdocs/api/toolkits/mplot3d.html

@Chirag3841
Copy link
Copy Markdown
Contributor Author

Chirag3841 commented Feb 24, 2026

@scottshambaugh
I’m facing issues while passing the new parameter in rcParams. Could you please guide me on how to correctly register it?
Currently, I have:
Added "axes3d.snap_rotation": validate_float in the validators dictionary.
Added the following entry in the params list:
_Param(
"axes3d.snap_rotation",
default=0.0,
validator=validate_float,
description="Snap angle (in degrees) for 3D rotation when holding Control."
)

I have also made the corresponding changes in other required files axes3d.py and test file too.
step = mpl.rcParams["axes3d.snap_rotation"]
if (
step > 0
and getattr(event, "key", None)
and "control" in event.key
):
elev = step * round(elev / step)
azim = step * round(azim / step)
roll = step * round(roll / step)
in axes3d.py and monkeypatch.setitem(plt.rcParams, "axes3d.snap_rotation", 5.0) in test file.
However, I am getting an error saying that "axes3d.snap_rotation" is not a valid rcParams key.
Could you please let me know if I am missing any required step?

@scottshambaugh
Copy link
Copy Markdown
Contributor

Could you push what you have right now so I can see the code changes?

@Chirag3841
Copy link
Copy Markdown
Contributor Author

Chirag3841 commented Feb 25, 2026

@scottshambaugh
done now you can check that

Copy link
Copy Markdown
Contributor

@scottshambaugh scottshambaugh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments, to fix the error you're seeing you'll need to add the new rcparam to the list in lib/matplotlib/typing.py around line 225. The instructions we have for adding new params aren't great, we should probably document that better to make it easier.

Comment thread lib/mpl_toolkits/mplot3d/tests/test_axes3d.py Outdated
Comment thread lib/mpl_toolkits/mplot3d/tests/test_axes3d.py Outdated
Comment thread lib/mpl_toolkits/mplot3d/tests/test_axes3d.py Outdated
Comment thread lib/mpl_toolkits/mplot3d/tests/test_axes3d.py Outdated
@Chirag3841
Copy link
Copy Markdown
Contributor Author

Chirag3841 commented Feb 25, 2026

@scottshambaugh
Thanks for your review and suggestion regarding required changes.
Please let me know if any additional changes are required.
I have removed the _snap_rotation flag and the related key press/release handlers, since snapping is now controlled through the axes3d.snap_rotation rcParam instead of using the previously hardcoded 5-degree value.

@scottshambaugh
Copy link
Copy Markdown
Contributor

Hi @Chirag3841, I don't see those changes pushed up yet.

@Chirag3841
Copy link
Copy Markdown
Contributor Author

Chirag3841 commented Feb 25, 2026

IMG_20260225_102617.jpg

Screenshot_2026-02-25-10-29-18-00_99c04817c0de5652397fc8b56c3b3817.jpg

IMG_20260225_102629.jpg

IMG_20260225_103347.jpg

IMG_20260225_102639.jpg

Hi @Chirag3841, I don't see those changes pushed up yet.

I have done that in the last commit which caused multiple errors where 2 nd pic is of test file and remaining of axes3d.py

FAILED lib/mpl_toolkits/mplot3d/tests/test_axes3d.py::test_ctrl_rotation_snaps_to_5deg - KeyError: 'elev'
Getting this error too

Comment thread lib/mpl_toolkits/mplot3d/axes3d.py
Comment thread lib/mpl_toolkits/mplot3d/tests/test_axes3d.py Outdated
Comment thread lib/mpl_toolkits/mplot3d/tests/test_axes3d.py Outdated
@Chirag3841
Copy link
Copy Markdown
Contributor Author

@scottshambaugh I resolved that issues in recent PR but still getting valid rc parameter error on local
And 12.3==10 error in elev

Comment thread lib/mpl_toolkits/mplot3d/tests/test_axes3d.py Outdated
@Chirag3841
Copy link
Copy Markdown
Contributor Author

Chirag3841 commented Feb 26, 2026

@scottshambaugh I changed the test file code and added what's a new doc too.

Comment thread lib/mpl_toolkits/mplot3d/tests/test_axes3d.py Outdated
Copy link
Copy Markdown
Contributor

@scottshambaugh scottshambaugh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this looks good to me now! The test failures look unrelated, so no need to worry about those.

@Chirag3841
Copy link
Copy Markdown
Contributor Author

Chirag3841 commented Feb 27, 2026

@scottshambaugh Thanks for your review and support.
Let me know if any changes are required or now .

@Chirag3841
Copy link
Copy Markdown
Contributor Author

Any Update ?

@scottshambaugh
Copy link
Copy Markdown
Contributor

We require 2 maintainers to approve each PR that changes code, so it may take a bit for someone else to look at this.

@Chirag3841
Copy link
Copy Markdown
Contributor Author

We require 2 maintainers to approve each PR that changes code, so it may take a bit for someone else to look at this.

Thanks for the clarification

@timhoffm
Copy link
Copy Markdown
Member

timhoffm commented Feb 28, 2026

Should we support a tuple so that we can set individual snap angles for (elev / azim / roll)?

Also, would a special value make sense to lock that angle? That way, one could e.g. limit the rotation to azim and keep elev and roll fixed. But not sure whether this should be folded into snap.

@Chirag3841
Copy link
Copy Markdown
Contributor Author

@timhoffm That’s an interesting idea but per-angle snapping or locking could potentially be explored separately if we think it warrants expanding the API.

@QuLogic QuLogic changed the title Snap 3d ctrl ENH: Snap 3D view angle changes when holding Control key Mar 2, 2026
@timhoffm
Copy link
Copy Markdown
Member

timhoffm commented Mar 3, 2026

Well, it potentially touches a design decision: If we want per-angle snapping, we'd need to support three-component config

axes3d.snap_rotation: 5.0, 5.0, 5.0

Then we can decide whether we additional want to allow single-component and implicitly broadcast. This is a trade-off: convenience vs. a more complex API and handling logic. It's not worlds difference but something that we only have the freedom to decide before this is released.

I'm slightly on side of always requiring the three values. It's that cumbersome to write them out if one really cares to configure snap.

@Chirag3841
Copy link
Copy Markdown
Contributor Author

Chirag3841 commented Mar 3, 2026

@timhoffm I feel that keeping it as a single float keeps the API simpler and likely covers the most common use case.
However, I understand the design considerations around long-term flexibility. If we think per-angle snapping is important from the start, I’m happy to update the PR to support a 3-component configuration.

@scottshambaugh
Copy link
Copy Markdown
Contributor

My ask for making this angle an rcparam was more for wanting to avoid magic constants than anything else. I could see people wanting to make it e.g. 1 deg rather than 5, but think the per-axis snapping values is going to be used rarely if ever. IMO keeping this simple with a single value is best.

@timhoffm
Copy link
Copy Markdown
Member

timhoffm commented Mar 4, 2026

Ok, if the expectation is that individal angle steps are not needed, let's merge as is.

@timhoffm timhoffm merged commit 726af38 into matplotlib:main Mar 4, 2026
39 of 40 checks passed
@timhoffm timhoffm added this to the v3.11.0 milestone Mar 4, 2026
@Chirag3841
Copy link
Copy Markdown
Contributor Author

Thanks @scottshambaugh and @timhoffm for reviewing and supporting this PR.

@Chirag3841 Chirag3841 deleted the snap-3d-ctrl branch March 5, 2026 02:49
tonybaloney pushed a commit to tonybaloney/swe-complex-matplotlib that referenced this pull request Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ENH]: Modifier key to discretize rotations for 3D plots

3 participants