@@ -1119,15 +1119,44 @@ def view_init(self, elev=None, azim=None, roll=None, vertical_axis="z",
1119
1119
A roll angle of 0, 90, 180, or 270 degrees will rotate these views
1120
1120
while keeping the axes at right angles.
1121
1121
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:
1123
1146
``.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
+
1126
1152
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
+
1131
1160
1132
1161
Parameters
1133
1162
----------
@@ -1599,13 +1628,8 @@ def _on_move(self, event):
1599
1628
elev = np .rad2deg (elev )
1600
1629
roll = np .rad2deg (roll )
1601
1630
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 )
1609
1633
self .stale = True
1610
1634
1611
1635
# Pan
0 commit comments