@@ -53,6 +53,7 @@ class Axes3D(Axes):
53
53
def __init__ (
54
54
self , fig , rect = None , * args ,
55
55
azim = - 60 , elev = 30 , sharez = None , proj_type = 'persp' ,
56
+ box_aspect = None , aspect = 'auto_pb' ,
56
57
** kwargs ):
57
58
"""
58
59
Parameters
@@ -91,11 +92,7 @@ def __init__(
91
92
self .zz_viewLim = Bbox .unit ()
92
93
self .xy_dataLim = Bbox .unit ()
93
94
self .zz_dataLim = Bbox .unit ()
94
- if 'pb_aspect' in kwargs :
95
- self .pb_aspect = np .asarray (kwargs ['pb_aspect' ])
96
- else :
97
- # chosen for similarity with the previous initial view
98
- self .pb_aspect = np .array ([4 , 4 , 3 ]) / 3.5
95
+
99
96
# inhibit autoscale_view until the axes are defined
100
97
# they can't be defined until Axes.__init__ has been called
101
98
self .view_init (self .initial_elev , self .initial_azim )
@@ -105,8 +102,9 @@ def __init__(
105
102
self ._shared_z_axes .join (self , sharez )
106
103
self ._adjustable = 'datalim'
107
104
108
- kwargs .setdefault ('aspect' , 'auto_pb' )
109
- super ().__init__ (fig , rect , frameon = True , * args , ** kwargs )
105
+ super ().__init__ (fig , rect , frameon = True ,
106
+ box_aspect = box_aspect , aspect = aspect ,
107
+ * args , ** kwargs )
110
108
# Disable drawing of axes by base class
111
109
super ().set_axis_off ()
112
110
# Enable drawing of axes by Axes3D class
@@ -353,8 +351,43 @@ def set_anchor(self, anchor, share=False):
353
351
ax ._anchor = anchor
354
352
ax .stale = True
355
353
356
- def set_pb_aspect (self , pb_aspect , zoom = 1 ):
357
- self .pb_aspect = pb_aspect * 1.8 * zoom / proj3d .mod (pb_aspect )
354
+ def set_box_aspect (self , aspect , zoom = 1 ):
355
+ """
356
+ Set the axes box aspect.
357
+
358
+ The box aspect is the ratio of the axes height to the axes width in
359
+ physical units. This is not to be confused with the data
360
+ aspect, set via `~.Axes.set_aspect`.
361
+
362
+ Parameters
363
+ ----------
364
+ aspect : 3-tuple of floats on None
365
+ Changes the physical dimensions of the Axes, such that the ratio
366
+ of the size of the axis in physical units is x:y:z
367
+
368
+ The input will be normalized to a unit vector.
369
+
370
+ If None, it is approximately ::
371
+
372
+ ax.set_box_aspect(aspect=(4, 4, 3), zoom=1)
373
+
374
+ zoom : float
375
+ Control the "zoom" of the
376
+
377
+ See Also
378
+ --------
379
+ matplotlib.axes.Axes3D.set_aspect
380
+ for a description of aspect handling.
381
+ """
382
+ if aspect is None :
383
+ aspect = zoom * np .asarray ((4 , 4 , 3 )) / 3.5
384
+ else :
385
+ aspect = np .asarray (aspect , dtype = float )
386
+ # default scale tuned to match the
387
+ aspect *= 1.829 * zoom / np .linalg .norm (aspect )
388
+
389
+ self ._box_aspect = aspect
390
+ self .stale = True
358
391
359
392
def apply_aspect (self , position = None ):
360
393
if position is None :
@@ -434,6 +467,7 @@ def get_axis_position(self):
434
467
return xhigh , yhigh , zhigh
435
468
436
469
def _on_units_changed (self , scalex = False , scaley = False , scalez = False ):
470
+
437
471
"""
438
472
Callback for processing changes to axis units.
439
473
@@ -981,8 +1015,6 @@ def set_proj_type(self, proj_type):
981
1015
982
1016
def get_proj (self ):
983
1017
"""Create the projection matrix from the current viewing position."""
984
- # chosen for similarity with the initial view before gh-8896
985
-
986
1018
# elev stores the elevation angle in the z plane
987
1019
# azim stores the azimuth angle in the x,y plane
988
1020
#
@@ -998,10 +1030,11 @@ def get_proj(self):
998
1030
# transform to uniform world coordinates 0-1, 0-1, 0-1
999
1031
worldM = proj3d .world_transformation (xmin , xmax ,
1000
1032
ymin , ymax ,
1001
- zmin , zmax , pb_aspect = self .pb_aspect )
1033
+ zmin , zmax ,
1034
+ pb_aspect = self ._box_aspect )
1002
1035
1003
1036
# look into the middle of the new coordinates
1004
- R = self .pb_aspect / 2
1037
+ R = self ._box_aspect / 2
1005
1038
1006
1039
xp = R [0 ] + np .cos (razim ) * np .cos (relev ) * self .dist
1007
1040
yp = R [1 ] + np .sin (razim ) * np .cos (relev ) * self .dist
0 commit comments