Skip to content

Add pan and zoom toolbar handling to 3D Axes (Replaces PR#22614) #23449

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 47 commits into from
Oct 10, 2022

Conversation

scottshambaugh
Copy link
Contributor

@scottshambaugh scottshambaugh commented Jul 19, 2022

PR Summary

Starting with @greglucas's work in #22614, I got panning and zooming working again with the toolbar buttons. Closes #110 (the oldest open issue!)

Changes in this PR:

  • Pan and zoom buttons enabled for 3D plots
  • Panning 3D plots reworked in general. Previously there was a 'scaling factor' in how much the plot moved with mouse movement. This has been updated so that if you are using an orthographic projection, the point directly under the mouse stays directly under the mouse. (This is not possible with a perspective projection)
  • [bugfix] Panning with a nonzero roll angle was broken, works now.
  • Made panning button configurable, like the zoom and rotate buttons are
  • Added in 'x' and 'y' key locking for 3d plot panning and zooming
  • [bugfix] Fixed mouse zoom jumping if hovering over a separate subplot
  • Refactor calculating the u, v, w view axes, add these as Axes3D private variables ._view_u, ._view_v, ._view_w
  • Privatize and add deprecation warnings for Axes3D .eye, .vvec, .sx, .sy, and proj3d.view_transformation()
  • Tests for panning and zooming

If this is too much packed in a single PR, I can separate it out into the panning and the zooming features.

Zooming behavior:

  • Edit: All axes now zoom equally.
  • With right mouse button: All axes are zoomed equally.
  • With the bounding box and an aspect ratio of 'auto': The scale factors set by the bounding box extents zoom the data axes such that the data is stretched in the u, v plane parallel to the screen but not in the w axis into/out of the screen. In other words, this zooms in 2D, projected onto the 3D data axes. Aspect ratio is set by the aspect of the bounding box. Note that the bounding box scale factors are calculated with respect to the whole canvas rather than the (shrunk) 3D axis limits.
  • With the bounding box and an aspect ratio of 'equal', 'equalzy', 'equalyz', or 'equalxz': Similar to the above, but the constrained data axes are kept equal, which may induce scaling in the w axis. 'equal' zooms all axes equally.

Please play around with it and see if the behavior is as expected!

Here's my test plot code which you can use:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from itertools import product, combinations

fig, ax = plt.subplots(1, 1, subplot_kw={'projection': '3d'})

# Draw rectangular cuboid with side lengths [1, 1, 2]
r = [0, 1]
scale = np.array([1, 1, 2])
for start, end in combinations(np.array(list(product(r, r, r))), 2):
    if np.sum(np.abs(start - end)) == r[1] - r[0]:
        ax.plot3D(*zip(start*scale, end*scale))

ax.view_init(elev=45, azim=45, roll=0)

ax.set_proj_type('ortho')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')

plt.show(block=True)

PR Checklist

Tests and Styling

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (install flake8-docstrings and run flake8 --docstring-convention=all).

Documentation

  • New features are documented, with examples if plot related.
  • New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • [n/a] API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).

greglucas and others added 10 commits July 19, 2022 13:40
1) This moves the pan logic that was already in the mouse move handler
into the "drag_pan" method to make it available from the toolbar.

2) This expands upon the panning logic to enable a zoom-to-box feature.
The zoom-to-box is done relative to the Axes, so it shrinks/expands
the box as a fraction of each delta, from lower-left Axes to lower-left
zoom-box. Thus, it tries to handle non-centered zooms, which adds more
cases to handle versus the current right-click zoom only scaling from
the center of the projection.
@scottshambaugh scottshambaugh marked this pull request as ready for review July 19, 2022 23:34
@scottshambaugh
Copy link
Contributor Author

scottshambaugh commented Jul 28, 2022

Talked about this in the dev call today, I got a few things to update but this should merge in after #23409 so zooming can respect fixed aspect ratios if those are set.

@scottshambaugh scottshambaugh marked this pull request as draft July 28, 2022 23:07
@scottshambaugh
Copy link
Contributor Author

scottshambaugh commented Oct 4, 2022

Thank you for looking it over @oscargus! I deprecated view_transformation simply because it is no longer used anywhere and is not user-facing. Really, all of plot3d should be privatized. We don't strictly need to move to deprecate it, but I figure dead code should get cleaned up.

The alternative was to rewrite it to match the functionality of what I put in as _view_transformation_uvw, but since all the input variables would be changing that seemed like a fairly dramatic breaking change to make.

@oscargus
Copy link
Member

oscargus commented Oct 5, 2022

OK! Maybe it is better to just deprecate the whole proj3d then? Just thinking that there is a single method deprecated now, while it would be just "as easy" to deprecate the whole submodule? (In terms of writing release notes etc.)

That deprecation may naturally be better off in a different PR though. (Sorry, could have thought of that earlier, but didn't realize that proj3d was not really user material.)

Btw, do you know what happens if I squash-merge the commits? Will it still contain both you and @greglucas as authors? (That doesn't happen on Gitlab I've noticed...)

@oscargus
Copy link
Member

oscargus commented Oct 5, 2022

I've found some libraries that use proj3d though, e.g.,

Most seem to use proj_transform though, so maybe it is enough to keep that?

Which may mean that there is no big deal if one method is deprecated here and some others in another PR.

@oscargus
Copy link
Member

oscargus commented Oct 5, 2022

Thinking a bit more about it I suggest the following for now:

  • Rewrite the deprecation note to (only) consider the privatized attributes instead.
  • Deprecate suitable parts of proj3d in another PR (which of course you do not have to write). I think those needs another discussion.

@scottshambaugh
Copy link
Contributor Author

Sounds good to me, I undeprecated view_transformation for now, rewrote the API change note, and opened #24098 to track that work forward.

@scottshambaugh
Copy link
Contributor Author

I don't believe that a squash merge would preserve that... I can rebase to just squash all mine if that make sense but might be a few days till I can get back to my personal computer for the CLI.

Copy link
Member

@oscargus oscargus left a comment

Choose a reason for hiding this comment

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

Subject to wording in deprecation notice and uncertainty how to deal with the multiple commits, especially the merge commits.

" The only time we are really strict about it is ... to remove upstream merges."

Not sure if it holds here or if the size of this PR means that we can ignore it.

Co-authored-by: Oscar Gustafsson <oscar.gustafsson@gmail.com>
@scottshambaugh scottshambaugh force-pushed the pan-zoom-3d branch 3 times, most recently from 56ca03a to ad52d28 Compare October 8, 2022 22:49
@scottshambaugh
Copy link
Contributor Author

Cool, docs are building with that notice now.

@timhoffm
Copy link
Member

timhoffm commented Oct 9, 2022

I'm not following the squash discussion. Is this only about crediting multiple people in the squash commit? That is done by Co-authored-by lines. Important: This needs two empty lines before. When you squash via the GitHub UI you can edit the commit message. AFAIR the co-author lines are in there by default.

@oscargus oscargus merged commit 4896ec1 into matplotlib:main Oct 10, 2022
@oscargus
Copy link
Member

Thanks @timhoffm for the clarification/reminder! You are correct that they are there by default, but not two empty in front of it (I added those though, to be on the safe side).

(Context: I did something similar in GitLab and there it wasn't added by default so I had to do a force push on the main branch. DId want to avoid that there...)

chahak13 pushed a commit to chahak13/matplotlib that referenced this pull request Oct 18, 2022
…plotlib#23449)

* ENH: Add pan and zoom toolbar handling to 3D Axes

1) This moves the pan logic that was already in the mouse move handler
into the "drag_pan" method to make it available from the toolbar.

2) This expands upon the panning logic to enable a zoom-to-box feature.
The zoom-to-box is done relative to the Axes, so it shrinks/expands
the box as a fraction of each delta, from lower-left Axes to lower-left
zoom-box. Thus, it tries to handle non-centered zooms, which adds more
cases to handle versus the current right-click zoom only scaling from
the center of the projection.

* Rewrite zooming with bounding box

* Rewrite 3d panning to work with a roll angle

* Whats new for zoom and pan buttons

* Make pan button configurable

* Do not jump when zooming and mouse goes over other subplot

* Rework zooming for 3d plots

* Handle x/y lock when zooming and panning

* Update tests

* Docstrings

* Dont assume a scale_z

* Limit zoom box

* Test zoom pan key modifiers

* Save some calculation by saving view axes

* Deprecation warnings for Axes3D.eye, .vvec

* Remove Axes3D._prepare_view_from_bbox for now

* Comments and docstrings

* Switch from uvn to uvw

* Save aspect to axes

* Constrain zooming with mouse when one of the equal aspect ratios is set

* Cleanup

* Cleanup

* Consolidate finding equal aspect axis indices

* linting

* More intuitive scaling

* Box zoom keeps existing aspect ratios

* Linting

* Code review comments

* Revert parameters for view_transformation

* Fix new 3d pan/zoom view going on view stack twice

* Better clipping

* Test 3d toolbar navigation

* Privatize helper functions

* Deprecations

* Code review changes

* Deprecation note

* Undeprecate proj3d.view_transformation

* Undeprecate proj3d.view_transformation

* Update doc/api/next_api_changes/deprecations/23449-SS.rst


Co-authored-by: Greg Lucas <greg.m.lucas@gmail.com>
Co-authored-by: Scott Shambaugh <scottshambaugh@users.noreply.github.com>
Co-authored-by: Oscar Gustafsson <oscar.gustafsson@gmail.com>
pratimugale pushed a commit to pratimugale/matplotlib that referenced this pull request Oct 24, 2022
…plotlib#23449)

* ENH: Add pan and zoom toolbar handling to 3D Axes

1) This moves the pan logic that was already in the mouse move handler
into the "drag_pan" method to make it available from the toolbar.

2) This expands upon the panning logic to enable a zoom-to-box feature.
The zoom-to-box is done relative to the Axes, so it shrinks/expands
the box as a fraction of each delta, from lower-left Axes to lower-left
zoom-box. Thus, it tries to handle non-centered zooms, which adds more
cases to handle versus the current right-click zoom only scaling from
the center of the projection.

* Rewrite zooming with bounding box

* Rewrite 3d panning to work with a roll angle

* Whats new for zoom and pan buttons

* Make pan button configurable

* Do not jump when zooming and mouse goes over other subplot

* Rework zooming for 3d plots

* Handle x/y lock when zooming and panning

* Update tests

* Docstrings

* Dont assume a scale_z

* Limit zoom box

* Test zoom pan key modifiers

* Save some calculation by saving view axes

* Deprecation warnings for Axes3D.eye, .vvec

* Remove Axes3D._prepare_view_from_bbox for now

* Comments and docstrings

* Switch from uvn to uvw

* Save aspect to axes

* Constrain zooming with mouse when one of the equal aspect ratios is set

* Cleanup

* Cleanup

* Consolidate finding equal aspect axis indices

* linting

* More intuitive scaling

* Box zoom keeps existing aspect ratios

* Linting

* Code review comments

* Revert parameters for view_transformation

* Fix new 3d pan/zoom view going on view stack twice

* Better clipping

* Test 3d toolbar navigation

* Privatize helper functions

* Deprecations

* Code review changes

* Deprecation note

* Undeprecate proj3d.view_transformation

* Undeprecate proj3d.view_transformation

* Update doc/api/next_api_changes/deprecations/23449-SS.rst


Co-authored-by: Greg Lucas <greg.m.lucas@gmail.com>
Co-authored-by: Scott Shambaugh <scottshambaugh@users.noreply.github.com>
Co-authored-by: Oscar Gustafsson <oscar.gustafsson@gmail.com>
melissawm pushed a commit to melissawm/matplotlib that referenced this pull request Dec 19, 2022
…plotlib#23449)

* ENH: Add pan and zoom toolbar handling to 3D Axes

1) This moves the pan logic that was already in the mouse move handler
into the "drag_pan" method to make it available from the toolbar.

2) This expands upon the panning logic to enable a zoom-to-box feature.
The zoom-to-box is done relative to the Axes, so it shrinks/expands
the box as a fraction of each delta, from lower-left Axes to lower-left
zoom-box. Thus, it tries to handle non-centered zooms, which adds more
cases to handle versus the current right-click zoom only scaling from
the center of the projection.

* Rewrite zooming with bounding box

* Rewrite 3d panning to work with a roll angle

* Whats new for zoom and pan buttons

* Make pan button configurable

* Do not jump when zooming and mouse goes over other subplot

* Rework zooming for 3d plots

* Handle x/y lock when zooming and panning

* Update tests

* Docstrings

* Dont assume a scale_z

* Limit zoom box

* Test zoom pan key modifiers

* Save some calculation by saving view axes

* Deprecation warnings for Axes3D.eye, .vvec

* Remove Axes3D._prepare_view_from_bbox for now

* Comments and docstrings

* Switch from uvn to uvw

* Save aspect to axes

* Constrain zooming with mouse when one of the equal aspect ratios is set

* Cleanup

* Cleanup

* Consolidate finding equal aspect axis indices

* linting

* More intuitive scaling

* Box zoom keeps existing aspect ratios

* Linting

* Code review comments

* Revert parameters for view_transformation

* Fix new 3d pan/zoom view going on view stack twice

* Better clipping

* Test 3d toolbar navigation

* Privatize helper functions

* Deprecations

* Code review changes

* Deprecation note

* Undeprecate proj3d.view_transformation

* Undeprecate proj3d.view_transformation

* Update doc/api/next_api_changes/deprecations/23449-SS.rst


Co-authored-by: Greg Lucas <greg.m.lucas@gmail.com>
Co-authored-by: Scott Shambaugh <scottshambaugh@users.noreply.github.com>
Co-authored-by: Oscar Gustafsson <oscar.gustafsson@gmail.com>
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.

pan and zoom are broken for mplot3d
5 participants