@@ -287,9 +287,7 @@ def set_aspect(self, aspect, adjustable=None, anchor=None, share=False):
287
287
'equalyz' adapt the y and z axes to have equal aspect ratios.
288
288
========= ==================================================
289
289
290
- adjustable : None
291
- Currently ignored by Axes3D
292
-
290
+ adjustable : None or {'box', 'datalim'}, optional
293
291
If not *None*, this defines which parameter will be adjusted to
294
292
meet the required aspect. See `.set_adjustable` for further
295
293
details.
@@ -320,34 +318,65 @@ def set_aspect(self, aspect, adjustable=None, anchor=None, share=False):
320
318
"""
321
319
_api .check_in_list (('auto' , 'equal' , 'equalxy' , 'equalyz' , 'equalxz' ),
322
320
aspect = aspect )
321
+ if adjustable is None :
322
+ adjustable = self ._adjustable
323
+ _api .check_in_list (('box' , 'datalim' ), adjustable = adjustable )
323
324
super ().set_aspect (
324
325
aspect = 'auto' , adjustable = adjustable , anchor = anchor , share = share )
325
326
self ._aspect = aspect
326
327
327
328
if aspect in ('equal' , 'equalxy' , 'equalxz' , 'equalyz' ):
328
- if aspect == 'equal' :
329
- ax_indices = [0 , 1 , 2 ]
330
- elif aspect == 'equalxy' :
331
- ax_indices = [0 , 1 ]
332
- elif aspect == 'equalxz' :
333
- ax_indices = [0 , 2 ]
334
- elif aspect == 'equalyz' :
335
- ax_indices = [1 , 2 ]
329
+ ax_idx = self ._equal_aspect_axis_indices (aspect )
336
330
337
331
view_intervals = np .array ([self .xaxis .get_view_interval (),
338
332
self .yaxis .get_view_interval (),
339
333
self .zaxis .get_view_interval ()])
340
- mean = np .mean (view_intervals , axis = 1 )
341
334
ptp = np .ptp (view_intervals , axis = 1 )
342
- delta = max (ptp [ax_indices ])
343
- scale = self ._box_aspect [ptp == delta ][0 ]
344
- deltas = delta * self ._box_aspect / scale
345
-
346
- for i , set_lim in enumerate ((self .set_xlim3d ,
347
- self .set_ylim3d ,
348
- self .set_zlim3d )):
349
- if i in ax_indices :
350
- set_lim (mean [i ] - deltas [i ]/ 2. , mean [i ] + deltas [i ]/ 2. )
335
+ if adjustable == 'datalim' :
336
+ mean = np .mean (view_intervals , axis = 1 )
337
+ delta = max (ptp [ax_idx ])
338
+ scale = self ._box_aspect [ptp == delta ][0 ]
339
+ deltas = delta * self ._box_aspect / scale
340
+
341
+ for i , set_lim in enumerate ((self .set_xlim3d ,
342
+ self .set_ylim3d ,
343
+ self .set_zlim3d )):
344
+ if i in ax_idx :
345
+ set_lim (mean [i ] - deltas [i ]/ 2. , mean [i ] + deltas [i ]/ 2. )
346
+ else : # 'box'
347
+ # Change the box aspect such that the ratio of the length of
348
+ # the unmodified axis to the length of the diagonal
349
+ # perpendicular to it remains unchanged.
350
+ box_aspect = np .array (self ._box_aspect )
351
+ box_aspect [ax_idx ] = ptp [ax_idx ]
352
+ remaining_ax_idx = {0 , 1 , 2 }.difference (ax_idx )
353
+ if remaining_ax_idx :
354
+ remaining = remaining_ax_idx .pop ()
355
+ old_diag = np .linalg .norm (self ._box_aspect [ax_idx ])
356
+ new_diag = np .linalg .norm (box_aspect [ax_idx ])
357
+ box_aspect [remaining ] *= new_diag / old_diag
358
+ self .set_box_aspect (box_aspect )
359
+
360
+ def _equal_aspect_axis_indices (self , aspect ):
361
+ """
362
+ Get the indices for which of the x, y, z axes are constrained to have
363
+ equal aspect ratios.
364
+
365
+ Parameters
366
+ ----------
367
+ aspect : {'auto', 'equal', 'equalxy', 'equalxz', 'equalyz'}
368
+ See descriptions in docstring for `.set_aspect()`.
369
+ """
370
+ ax_indices = [] # aspect == 'auto'
371
+ if aspect == 'equal' :
372
+ ax_indices = [0 , 1 , 2 ]
373
+ elif aspect == 'equalxy' :
374
+ ax_indices = [0 , 1 ]
375
+ elif aspect == 'equalxz' :
376
+ ax_indices = [0 , 2 ]
377
+ elif aspect == 'equalyz' :
378
+ ax_indices = [1 , 2 ]
379
+ return ax_indices
351
380
352
381
def set_box_aspect (self , aspect , * , zoom = 1 ):
353
382
"""
0 commit comments