Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e9991b3

Browse filesBrowse files
committed
Consistent azim-elev-roll order with minimal changes
Implement changes requested for PR #28395: - remove incohesive section from view_angles.rst - move some of the information to .mplot3d.axes3d.Axes3D.view_init - remove redundant kwargs as in .view_init(elev=elev, azim=azim, roll=roll) - cleanup test_axes3d_primary_views() - remove outdated next_whats_new item
1 parent 89a4d55 commit e9991b3
Copy full SHA for e9991b3

File tree

4 files changed

+43
-58
lines changed
Filter options

4 files changed

+43
-58
lines changed

‎doc/api/toolkits/mplot3d/view_angles.rst

Copy file name to clipboardExpand all lines: doc/api/toolkits/mplot3d/view_angles.rst
-22Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,28 +28,6 @@ as well as roll, and all three angles can be set programmatically::
2828
ax = plt.figure().add_subplot(projection='3d')
2929
ax.view_init(elev=30, azim=45, roll=15)
3030

31-
Rotation of the plot
32-
====================
33-
34-
The *azim*, *elev*, *roll* rotation order corresponds to rotation of the scene
35-
observed by a stationary camera. First, a left-handed rotation about the z axis is
36-
applied (*azim*), then a right-handed rotation about the (camera) y axis (*elev*), then a
37-
right-handed rotation about the (camera) x axis (*roll*). Here, the z, y, and x axis are fixed
38-
axes (not the axes that rotate together with the original scene).
39-
40-
This can also be thought of as orbiting a camera around a fixed scene, by reversing
41-
the order of operations. First the camera is rotated about the scene's +x axis
42-
(*roll*), then the +y axis (*elev*), then the −z axis (*azim*).
43-
44-
If you would like to make the connection with quaternions (because
45-
`Euler angles are horrible <https://github.com/moble/quaternion/wiki/Euler-angles-are-horrible>`_):
46-
the *azim*, *elev*, *roll* angles relate to the (intrinsic) rotation of the plot via:
47-
48-
*q* = exp( +roll **** / 2) exp( +elev **ŷ** / 2) exp( −azim **** / 2)
49-
50-
(with angles given in radians instead of degrees). That is, the angles are a kind of
51-
Tait-Bryan angles: −z, +y', +x", rather than classic Euler angles.
52-
5331

5432
Primary view planes
5533
===================

‎doc/users/next_whats_new/view_angles_keyword_arguments.rst

Copy file name to clipboardExpand all lines: doc/users/next_whats_new/view_angles_keyword_arguments.rst
-17Lines changed: 0 additions & 17 deletions
This file was deleted.

‎lib/mpl_toolkits/mplot3d/axes3d.py

Copy file name to clipboardExpand all lines: lib/mpl_toolkits/mplot3d/axes3d.py
+38-14Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,15 +1119,44 @@ def view_init(self, elev=None, azim=None, roll=None, vertical_axis="z",
11191119
A roll angle of 0, 90, 180, or 270 degrees will rotate these views
11201120
while keeping the axes at right angles.
11211121
1122-
It is recommended to provide these parameter as keyword arguments:
1122+
The *azim*, *elev*, *roll* angles correspond to rotations of the scene
1123+
observed by a stationary camera, as follows (assuming a default vertical
1124+
axis of 'z'). First, a left-handed rotation about the z axis is applied
1125+
(*azim*), then a right-handed rotation about the (camera) y axis (*elev*),
1126+
then a right-handed rotation about the (camera) x axis (*roll*). Here,
1127+
the z, y, and x axis are fixed axes (not the axes that rotate together
1128+
with the original scene).
1129+
1130+
If you would like to make the connection with quaternions (because
1131+
`Euler angles are horrible
1132+
<https://github.com/moble/quaternion/wiki/Euler-angles-are-horrible>`_):
1133+
the *azim*, *elev*, *roll* angles relate to the (intrinsic) rotation of
1134+
the plot via:
1135+
1136+
*q* = exp(+roll **x̂** / 2) exp(+elev **ŷ** / 2) exp(−azim **ẑ** / 2)
1137+
1138+
(with angles given in radians instead of degrees). That is, the angles
1139+
are a kind of `Tait-Bryan angles
1140+
<https://en.wikipedia.org/wiki/Euler_angles#Tait%E2%80%93Bryan_angles>`_:
1141+
−z, +y', +x", rather than classic `Euler angles
1142+
<https://en.wikipedia.org/wiki/Euler_angles>`_.
1143+
1144+
To avoid confusion, it makes sense to provide the view angles as keyword
1145+
arguments:
11231146
``.view_init(azim=-60, elev=30, roll=0, ...)``
1124-
in this order (i.e., the order in which the rotations actually are
1125-
applied).
1147+
This specific order is consistent with the order in which the rotations
1148+
actually are applied. Moreover, this particular order appears to be most
1149+
common, see :ghissue:`28353`, and it is consistent with the ordering in
1150+
`matplotlib.colors.LightSource`.
1151+
11261152
For backwards compatibility, positional arguments in the old sequence
1127-
(first elev, then azim) will still be accepted; unfortunately,
1128-
this order does not match the actual order of the applied rotations,
1129-
and it differs from that used in other programs (`azim, elev`).
1130-
It would be nice if the sensible ordering could take over eventually.
1153+
(first ``elev``, then ``azim``) will still be accepted; but preferably,
1154+
use keyword arguments, to avoid confusion as to which angle is which.
1155+
Unfortunately, the order of the positional arguments does not match
1156+
the actual order of the applied rotations, and it differs from that
1157+
used in other programs (``azim, elev``). It would be nice if the sensible
1158+
(keyword) ordering could take over eventually.
1159+
11311160
11321161
Parameters
11331162
----------
@@ -1599,13 +1628,8 @@ def _on_move(self, event):
15991628
elev = np.rad2deg(elev)
16001629
roll = np.rad2deg(roll)
16011630
vertical_axis = self._axis_names[self._vertical_axis]
1602-
self.view_init(
1603-
elev=elev,
1604-
azim=azim,
1605-
roll=roll,
1606-
vertical_axis=vertical_axis,
1607-
share=True,
1608-
)
1631+
self.view_init(elev, azim, roll, vertical_axis=vertical_axis,
1632+
share=True)
16091633
self.stale = True
16101634

16111635
# Pan

‎lib/mpl_toolkits/mplot3d/tests/test_axes3d.py

Copy file name to clipboardExpand all lines: lib/mpl_toolkits/mplot3d/tests/test_axes3d.py
+5-5Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,12 @@ def test_axes3d_primary_views():
127127
# When viewing primary planes, draw the two visible axes so they intersect
128128
# at their low values
129129
fig, axs = plt.subplots(2, 3, subplot_kw={'projection': '3d'})
130-
for i, ax in enumerate(axs.flat):
130+
for ax, (azim, elev, roll) in zip(axs.flat, views):
131131
ax.set_xlabel('x')
132132
ax.set_ylabel('y')
133133
ax.set_zlabel('z')
134134
ax.set_proj_type('ortho')
135-
ax.view_init(elev=views[i][1], azim=views[i][0], roll=views[i][2])
135+
ax.view_init(elev, azim, roll)
136136
plt.tight_layout()
137137

138138

@@ -176,7 +176,7 @@ def test_bar3d_shaded():
176176
)
177177
for ax, (azim, elev, roll) in zip(axs, views):
178178
ax.bar3d(x2d, y2d, x2d * 0, 1, 1, z, shade=True)
179-
ax.view_init(elev=elev, azim=azim, roll=roll)
179+
ax.view_init(elev, azim, roll)
180180
fig.canvas.draw()
181181

182182

@@ -1832,11 +1832,11 @@ def test_shared_view(fig_test, fig_ref):
18321832
ax2 = fig_test.add_subplot(132, projection="3d", shareview=ax1)
18331833
ax3 = fig_test.add_subplot(133, projection="3d")
18341834
ax3.shareview(ax1)
1835-
ax2.view_init(elev=elev, azim=azim, roll=roll, share=True)
1835+
ax2.view_init(elev, azim, roll, share=True)
18361836

18371837
for subplot_num in (131, 132, 133):
18381838
ax = fig_ref.add_subplot(subplot_num, projection="3d")
1839-
ax.view_init(elev=elev, azim=azim, roll=roll)
1839+
ax.view_init(elev, azim, roll)
18401840

18411841

18421842
def test_shared_axes_retick():

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.