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

Skip to content

Commit 431bed4

Browse files
committed
Change order of mplot3d view angles to match order of rotations
- Change order of mplot3d view angles to azim-elev-roll, the order in which rotations occur: - in axes3d.py - in tests - in documentation - in examples - Add description of rotation to view_angles.rst - Put in ref. to https://github.com/moble/quaternion/wiki/Euler-angles-are-horrible - Update view_init() documentation - Add doc\api\next_api_changes\deprecations warning that Axes3D.view_init preferably should be used with keyword arguments - Add next_whats_new\view_angles_order.rst explaining the new view angles order
1 parent 81756c3 commit 431bed4

File tree

11 files changed

+190
-111
lines changed

11 files changed

+190
-111
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
``Axes3D.view_init``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
... preferably should be used with keyword arguments, azim=, elev=, roll=,
4+
in this order (i.e., the order in which the rotations are applied).
5+
6+
For backwards compatibility, positional arguments in the old sequence
7+
(first elev, then azim) will still be accepted
8+
(but a deprecation warning will be given).

doc/api/toolkits/mplot3d.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ the toolbar pan and zoom buttons are not used.
5353
In addition, help and patches would be greatly appreciated!
5454

5555

56-
`axes3d.Axes3D` (fig[, rect, elev, azim, roll, ...]) 3D Axes object.
56+
`axes3d.Axes3D` (fig[, rect, azim, elev, roll, ...]) 3D Axes object.
5757

5858

5959
.. module:: mpl_toolkits.mplot3d.axis3d

doc/api/toolkits/mplot3d/view_angles.rst

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ How to define the view angle
88
============================
99

1010
The position of the viewport "camera" in a 3D plot is defined by three angles:
11-
*elevation*, *azimuth*, and *roll*. From the resulting position, it always
11+
*azimuth*, *elevation*, and *roll*. From the resulting position, it always
1212
points towards the center of the plot box volume. The angle direction is a
1313
common convention, and is shared with
1414
`PyVista <https://docs.pyvista.org/api/core/camera.html>`_ and
@@ -26,13 +26,26 @@ as well as roll, and all three angles can be set programmatically::
2626

2727
import matplotlib.pyplot as plt
2828
ax = plt.figure().add_subplot(projection='3d')
29-
ax.view_init(elev=30, azim=45, roll=15)
29+
ax.view_init(azim=45, elev=30, roll=15)
30+
31+
Rotation of the plot
32+
====================
33+
34+
The angles relate to the (intrinsic) rotation of the plot via the
35+
quaternion (with angles here given in radians instead of degrees):
36+
37+
*q* = exp( +roll **** / 2) exp( +elev **ŷ** / 2) exp( −azim **** / 2)
38+
39+
i.e., the angles are a kind of Tait-Bryan angles, −z, +y', +x", rather than
40+
classic Euler angles. (If you want to do anything significant with three-dimensional
41+
rotations, you are `well advised <https://github.com/moble/quaternion/wiki/Euler-angles-are-horrible>`_
42+
to stay clear of Tait-Bryan and Euler angles, and to use quaternions instead.)
3043

3144

3245
Primary view planes
3346
===================
3447

35-
To look directly at the primary view planes, the required elevation, azimuth,
48+
To look directly at the primary view planes, the required azimuth, elevation,
3649
and roll angles are shown in the diagram of an "unfolded" plot below. These are
3750
further documented in the `.mplot3d.axes3d.Axes3D.view_init` API.
3851

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Order of view angles
2+
~~~~~~~~~~~~~~~~~~~~
3+
4+
The order of the 'view angles' for three-dimensional plots (with ``mplot3d``)
5+
has been changed to ``azim=, elev=, roll=``. This is consistent with the order
6+
in which the rotations take place [1]. It is suggested to use keyword arguments
7+
(in this order) for the angles, so there will be no confusion as to which angle
8+
is which (even if the order would be different).
9+
10+
11+
For backward compatibility, the old ``elev``, ``azim`` etc. positional arguments
12+
will still be accepted (but it is not recommended).
13+
14+
15+
[1]: See :doc: `/api/toolkits/mplot3d/view_angles` for details. Also, this particular
16+
order appears to be most common; and it is consistent with the ordering in
17+
matplotlib's colors.py - see also :ghissue:`28353`.

galleries/examples/mplot3d/2dcollections3d.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@
4343

4444
# Customize the view angle so it's easier to see that the scatter points lie
4545
# on the plane y=0
46-
ax.view_init(elev=20., azim=-35, roll=0)
46+
ax.view_init(azim=-35, elev=20., roll=0)
4747

4848
plt.show()

galleries/examples/mplot3d/box3d.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
)
6969

7070
# Set zoom and angle view
71-
ax.view_init(40, -30, 0)
71+
ax.view_init(azim=-30, elev=40, roll=0)
7272
ax.set_box_aspect(None, zoom=0.9)
7373

7474
# Colorbar

galleries/examples/mplot3d/rotate_axes3d_sgskip.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,19 @@
3333
angle_norm = (angle + 180) % 360 - 180
3434

3535
# Cycle through a full rotation of elevation, then azimuth, roll, and all
36-
elev = azim = roll = 0
36+
azim = elev = roll = 0
3737
if angle <= 360:
3838
elev = angle_norm
3939
elif angle <= 360*2:
4040
azim = angle_norm
4141
elif angle <= 360*3:
4242
roll = angle_norm
4343
else:
44-
elev = azim = roll = angle_norm
44+
azim = elev = roll = angle_norm
4545

4646
# Update the axis view and title
47-
ax.view_init(elev, azim, roll)
48-
plt.title('Elevation: %d°, Azimuth: %d°, Roll: %d°' % (elev, azim, roll))
47+
ax.view_init(azim=azim, elev=elev, roll=roll)
48+
plt.title('Azimuth: %d°, Elevation: %d°, Roll: %d°' % (azim, elev, roll))
4949

5050
plt.draw()
5151
plt.pause(.001)

galleries/examples/mplot3d/view_planes_3d.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
======================
55
66
This example generates an "unfolded" 3D plot that shows each of the primary 3D
7-
view planes. The elevation, azimuth, and roll angles required for each view are
7+
view planes. The azimuth, elevation, and roll angles required for each view are
88
labeled. You could print out this image and fold it into a box where each plane
99
forms a side of the box.
1010
"""
@@ -16,13 +16,13 @@ def annotate_axes(ax, text, fontsize=18):
1616
ax.text(x=0.5, y=0.5, z=0.5, s=text,
1717
va="center", ha="center", fontsize=fontsize, color="black")
1818

19-
# (plane, (elev, azim, roll))
20-
views = [('XY', (90, -90, 0)),
21-
('XZ', (0, -90, 0)),
22-
('YZ', (0, 0, 0)),
23-
('-XY', (-90, 90, 0)),
24-
('-XZ', (0, 90, 0)),
25-
('-YZ', (0, 180, 0))]
19+
# (plane, (azim, elev, roll))
20+
views = [('XY', (-90, 90, 0)),
21+
('XZ', (-90, 0, 0)),
22+
('YZ', (0, 0, 0)),
23+
('-XY', (90, -90, 0)),
24+
('-XZ', (90, 0, 0)),
25+
('-YZ', (180, 0, 0))]
2626

2727
layout = [['XY', '.', 'L', '.'],
2828
['XZ', 'YZ', '-XZ', '-YZ'],
@@ -34,7 +34,7 @@ def annotate_axes(ax, text, fontsize=18):
3434
axd[plane].set_ylabel('y')
3535
axd[plane].set_zlabel('z')
3636
axd[plane].set_proj_type('ortho')
37-
axd[plane].view_init(elev=angles[0], azim=angles[1], roll=angles[2])
37+
axd[plane].view_init(azim=angles[0], elev=angles[1], roll=angles[2])
3838
axd[plane].set_box_aspect(None, zoom=1.25)
3939

4040
label = f'{plane}\n{angles}'
@@ -50,7 +50,8 @@ def annotate_axes(ax, text, fontsize=18):
5050
axd[plane].set_xticklabels([])
5151
axd[plane].set_xlabel('')
5252

53-
label = 'mplot3d primary view planes\n' + 'ax.view_init(elev, azim, roll)'
53+
label = 'mplot3d primary view planes\n' + \
54+
'ax.view_init(azim=azim, elev=elev, roll=roll)'
5455
annotate_axes(axd['L'], label, fontsize=18)
5556
axd['L'].set_axis_off()
5657

0 commit comments

Comments
 (0)