@@ -1213,19 +1213,21 @@ def _set_view_from_bbox(self, bbox, direction='in',
1213
1213
dy = abs (start_y - stop_y )
1214
1214
scale_u = dx / (self .bbox .max [0 ] - self .bbox .min [0 ])
1215
1215
scale_v = dy / (self .bbox .max [1 ] - self .bbox .min [1 ])
1216
- scale_w = max (scale_u , scale_v )
1217
1216
1218
1217
# Limit box zoom to reasonable range, protect for divide by zero below
1219
- scale_u = np .clip (scale_u , 1e-2 , 1e2 )
1220
- scale_v = np .clip (scale_v , 1e-2 , 1e2 )
1218
+ scale_u = np .clip (scale_u , 1e-2 , 1 )
1219
+ scale_v = np .clip (scale_v , 1e-2 , 1 )
1221
1220
1221
+ # Keep aspect ratios equal
1222
+ scale = max (scale_u , scale_v )
1223
+
1224
+ # Zoom out
1222
1225
if direction == 'out' :
1223
- scale_u = 1 / scale_u
1224
- scale_v = 1 / scale_v
1226
+ scale = 1 / scale
1225
1227
1226
- self ._zoom_data_limits ( scale_u , scale_v , scale_w )
1228
+ self .zoom_data_limits ( scale , scale , scale )
1227
1229
1228
- def _zoom_data_limits (self , scale_u , scale_v , scale_w ):
1230
+ def zoom_data_limits (self , scale_u , scale_v , scale_w ):
1229
1231
"""
1230
1232
Zoom in or out of a 3D plot.
1231
1233
Will scale the data limits by the scale factors, where scale_u,
@@ -1237,19 +1239,23 @@ def _zoom_data_limits(self, scale_u, scale_v, scale_w):
1237
1239
'equalyz', or 'equalxz', the relevant axes are constrained to zoom
1238
1240
equally.
1239
1241
"""
1240
- # Convert from the scale factors in the view frame to the data frame
1241
- R = np .array ([self ._view_u , self ._view_v , self ._view_w ])
1242
- S = np .array ([scale_u , scale_v , scale_w ]) * np .eye (3 )
1243
- scale = np .linalg .norm (R .T @ S , axis = 1 )
1242
+ scale = np .array ([scale_u , scale_v , scale_w ])
1243
+
1244
+ # Only perform frame conversion if unequal scale factors
1245
+ if not np .allclose (scale , scale_u ):
1246
+ # Convert from the scale factors in the view frame to the data frame
1247
+ R = np .array ([self ._view_u , self ._view_v , self ._view_w ])
1248
+ S = scale * np .eye (3 )
1249
+ scale = np .linalg .norm (R .T @ S , axis = 1 )
1244
1250
1245
- # Set the constrained scale factors to the factor closest to 1
1246
- if self ._aspect in ('equal' , 'equalxy' , 'equalxz' , 'equalyz' ):
1247
- ax_idx = self ._equal_aspect_axis_indices (self ._aspect )
1248
- scale [ax_idx ] = scale [ax_idx ][np .argmin (np .abs (scale [ax_idx ] - 1 ))]
1251
+ # Set the constrained scale factors to the factor closest to 1
1252
+ if self ._aspect in ('equal' , 'equalxy' , 'equalxz' , 'equalyz' ):
1253
+ ax_idx = self ._equal_aspect_axis_indices (self ._aspect )
1254
+ scale [ax_idx ] = scale [ax_idx ][np .argmin (np .abs (scale [ax_idx ] - 1 ))]
1249
1255
1250
- self ._scale_axis_limits (scale [0 ], scale [1 ], scale [2 ])
1256
+ self .scale_axis_limits (scale [0 ], scale [1 ], scale [2 ])
1251
1257
1252
- def _scale_axis_limits (self , scale_x , scale_y , scale_z ):
1258
+ def scale_axis_limits (self , scale_x , scale_y , scale_z ):
1253
1259
"""
1254
1260
Keeping the center of the x, y, and z data axes fixed, scale their
1255
1261
limits by scale factors. A scale factor > 1 zooms out and a scale
0 commit comments