@@ -139,7 +139,11 @@ def __init__(
139
139
140
140
# inhibit autoscale_view until the axes are defined
141
141
# they can't be defined until Axes.__init__ has been called
142
- self .view_init (self .initial_elev , self .initial_azim , self .initial_roll )
142
+ self .view_init (
143
+ elev = self .initial_elev ,
144
+ azim = self .initial_azim ,
145
+ roll = self .initial_roll ,
146
+ )
143
147
144
148
self ._sharez = sharez
145
149
if sharez is not None :
@@ -1094,25 +1098,37 @@ def clabel(self, *args, **kwargs):
1094
1098
def view_init (self , elev = None , azim = None , roll = None , vertical_axis = "z" ,
1095
1099
share = False ):
1096
1100
"""
1097
- Set the elevation and azimuth of the Axes in degrees (not radians).
1101
+ Set the azimuth, elevation, and roll of the Axes, in degrees (not radians).
1098
1102
1099
1103
This can be used to rotate the Axes programmatically.
1100
1104
1101
- To look normal to the primary planes, the following elevation and
1102
- azimuth angles can be used. A roll angle of 0, 90, 180, or 270 deg
1103
- will rotate these views while keeping the axes at right angles.
1105
+ To look normal to the primary planes, the following azimuth and
1106
+ elevation angles can be used:
1104
1107
1105
1108
========== ==== ====
1106
- view plane elev azim
1109
+ view plane azim elev
1107
1110
========== ==== ====
1108
- XY 90 - 90
1109
- XZ 0 -90
1110
- YZ 0 0
1111
- -XY - 90 90
1112
- -XZ 0 90
1113
- -YZ 0 180
1111
+ XY - 90 90
1112
+ XZ -90 0
1113
+ YZ 0 0
1114
+ -XY 90 - 90
1115
+ -XZ 90 0
1116
+ -YZ 180 0
1114
1117
========== ==== ====
1115
1118
1119
+ A roll angle of 0, 90, 180, or 270 degrees will rotate these views
1120
+ while keeping the axes at right angles.
1121
+
1122
+ It is recommended to provide these parameter as keyword arguments:
1123
+ ``.view_init(azim=-60, elev=30, roll=0, ...)``
1124
+ in this order (i.e., the order in which the rotations actually are
1125
+ applied).
1126
+ 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.
1131
+
1116
1132
Parameters
1117
1133
----------
1118
1134
elev : float, default: None
@@ -1145,10 +1161,10 @@ def view_init(self, elev=None, azim=None, roll=None, vertical_axis="z",
1145
1161
1146
1162
self ._dist = 10 # The camera distance from origin. Behaves like zoom
1147
1163
1148
- if elev is None :
1149
- elev = self .initial_elev
1150
1164
if azim is None :
1151
1165
azim = self .initial_azim
1166
+ if elev is None :
1167
+ elev = self .initial_elev
1152
1168
if roll is None :
1153
1169
roll = self .initial_roll
1154
1170
vertical_axis = _api .check_getitem (
@@ -1163,8 +1179,8 @@ def view_init(self, elev=None, azim=None, roll=None, vertical_axis="z",
1163
1179
axes = [self ]
1164
1180
1165
1181
for ax in axes :
1166
- ax .elev = elev
1167
1182
ax .azim = azim
1183
+ ax .elev = elev
1168
1184
ax .roll = roll
1169
1185
ax ._vertical_axis = vertical_axis
1170
1186
@@ -1229,15 +1245,15 @@ def get_proj(self):
1229
1245
# Look into the middle of the world coordinates:
1230
1246
R = 0.5 * box_aspect
1231
1247
1232
- # elev: elevation angle in the z plane.
1233
1248
# azim: azimuth angle in the xy plane.
1249
+ # elev: elevation angle in the z plane.
1234
1250
# Coordinates for a point that rotates around the box of data.
1235
1251
# p0, p1 corresponds to rotating the box only around the vertical axis.
1236
1252
# p2 corresponds to rotating the box only around the horizontal axis.
1237
- elev_rad = np .deg2rad (self .elev )
1238
1253
azim_rad = np .deg2rad (self .azim )
1239
- p0 = np .cos (elev_rad ) * np .cos (azim_rad )
1240
- p1 = np .cos (elev_rad ) * np .sin (azim_rad )
1254
+ elev_rad = np .deg2rad (self .elev )
1255
+ p0 = np .cos (azim_rad ) * np .cos (elev_rad )
1256
+ p1 = np .sin (azim_rad ) * np .cos (elev_rad )
1241
1257
p2 = np .sin (elev_rad )
1242
1258
1243
1259
# When changing vertical axis the coordinates changes as well.
@@ -1339,8 +1355,13 @@ def shareview(self, other):
1339
1355
self ._shared_axes ["view" ].join (self , other )
1340
1356
self ._shareview = other
1341
1357
vertical_axis = self ._axis_names [other ._vertical_axis ]
1342
- self .view_init (elev = other .elev , azim = other .azim , roll = other .roll ,
1343
- vertical_axis = vertical_axis , share = True )
1358
+ self .view_init (
1359
+ elev = other .elev ,
1360
+ azim = other .azim ,
1361
+ roll = other .roll ,
1362
+ vertical_axis = vertical_axis ,
1363
+ share = True ,
1364
+ )
1344
1365
1345
1366
def clear (self ):
1346
1367
# docstring inherited.
@@ -1392,8 +1413,8 @@ def _set_view(self, view):
1392
1413
# docstring inherited
1393
1414
props , (elev , azim , roll ) = view
1394
1415
self .set (** props )
1395
- self .elev = elev
1396
1416
self .azim = azim
1417
+ self .elev = elev
1397
1418
self .roll = roll
1398
1419
1399
1420
def format_zdata (self , z ):
@@ -1430,11 +1451,11 @@ def _rotation_coords(self):
1430
1451
"""
1431
1452
Return the rotation angles as a string.
1432
1453
"""
1433
- norm_elev = art3d ._norm_angle (self .elev )
1434
1454
norm_azim = art3d ._norm_angle (self .azim )
1455
+ norm_elev = art3d ._norm_angle (self .elev )
1435
1456
norm_roll = art3d ._norm_angle (self .roll )
1436
- coords = (f"elevation= { norm_elev :.0f} \N{DEGREE SIGN} , "
1437
- f"azimuth= { norm_azim :.0f} \N{DEGREE SIGN} , "
1457
+ coords = (f"azimuth= { norm_azim :.0f} \N{DEGREE SIGN} , "
1458
+ f"elevation= { norm_elev :.0f} \N{DEGREE SIGN} , "
1438
1459
f"roll={ norm_roll :.0f} \N{DEGREE SIGN} "
1439
1460
).replace ("-" , "\N{MINUS SIGN} " )
1440
1461
return coords
@@ -1561,10 +1582,10 @@ def _on_move(self, event):
1561
1582
return
1562
1583
1563
1584
# Convert to quaternion
1564
- elev = np .deg2rad (self .elev )
1565
1585
azim = np .deg2rad (self .azim )
1586
+ elev = np .deg2rad (self .elev )
1566
1587
roll = np .deg2rad (self .roll )
1567
- q = _Quaternion .from_cardan_angles (elev , azim , roll )
1588
+ q = _Quaternion .from_cardan_angles (azim , elev , roll )
1568
1589
1569
1590
# Update quaternion - a variation on Ken Shoemake's ARCBALL
1570
1591
current_vec = self ._arcball (self ._sx / w , self ._sy / h )
@@ -1573,7 +1594,7 @@ def _on_move(self, event):
1573
1594
q = dq * q
1574
1595
1575
1596
# Convert to elev, azim, roll
1576
- elev , azim , roll = q .as_cardan_angles ()
1597
+ azim , elev , roll = q .as_cardan_angles ()
1577
1598
azim = np .rad2deg (azim )
1578
1599
elev = np .rad2deg (elev )
1579
1600
roll = np .rad2deg (roll )
@@ -3662,10 +3683,10 @@ def _extract_errs(err, data, lomask, himask):
3662
3683
quiversize = np .mean (np .diff (quiversize , axis = 0 ))
3663
3684
# quiversize is now in Axes coordinates, and to convert back to data
3664
3685
# coordinates, we need to run it through the inverse 3D transform. For
3665
- # consistency, this uses a fixed elevation, azimuth , and roll.
3686
+ # consistency, this uses a fixed azimuth, elevation , and roll.
3666
3687
with cbook ._setattr_cm (self , elev = 0 , azim = 0 , roll = 0 ):
3667
3688
invM = np .linalg .inv (self .get_proj ())
3668
- # elev= azim=roll=0 produces the Y-Z plane, so quiversize in 2D 'x' is
3689
+ # azim=elev =roll=0 produces the Y-Z plane, so quiversize in 2D 'x' is
3669
3690
# 'y' in 3D, hence the 1 index.
3670
3691
quiversize = np .dot (invM , [quiversize , 0 , 0 , 0 ])[1 ]
3671
3692
# Quivers use a fixed 15-degree arrow head, so scale up the length so
@@ -4000,7 +4021,7 @@ def rotate_from_to(cls, r1, r2):
4000
4021
return q
4001
4022
4002
4023
@classmethod
4003
- def from_cardan_angles (cls , elev , azim , roll ):
4024
+ def from_cardan_angles (cls , azim , elev , roll ):
4004
4025
"""
4005
4026
Converts the angles to a quaternion
4006
4027
q = exp((roll/2)*e_x)*exp((elev/2)*e_y)*exp((-azim/2)*e_z)
@@ -4027,4 +4048,4 @@ def as_cardan_angles(self):
4027
4048
azim = np .arctan2 (2 * (- qw * qz + qx * qy ), qw * qw + qx * qx - qy * qy - qz * qz )
4028
4049
elev = np .arcsin ( 2 * ( qw * qy + qz * qx )/ (qw * qw + qx * qx + qy * qy + qz * qz )) # noqa E201
4029
4050
roll = np .arctan2 (2 * ( qw * qx - qy * qz ), qw * qw - qx * qx - qy * qy + qz * qz ) # noqa E201
4030
- return elev , azim , roll
4051
+ return azim , elev , roll
0 commit comments