@@ -56,6 +56,7 @@ class Axes3D(Axes):
56
56
57
57
_axis_names = ("x" , "y" , "z" )
58
58
Axes ._shared_axes ["z" ] = cbook .Grouper ()
59
+ Axes ._shared_axes ["view" ] = cbook .Grouper ()
59
60
60
61
vvec = _api .deprecate_privatize_attribute ("3.7" )
61
62
eye = _api .deprecate_privatize_attribute ("3.7" )
@@ -66,6 +67,7 @@ def __init__(
66
67
self , fig , rect = None , * args ,
67
68
elev = 30 , azim = - 60 , roll = 0 , sharez = None , proj_type = 'persp' ,
68
69
box_aspect = None , computed_zorder = True , focal_length = None ,
70
+ shareview = None ,
69
71
** kwargs ):
70
72
"""
71
73
Parameters
@@ -111,6 +113,8 @@ def __init__(
111
113
or infinity (numpy.inf). If None, defaults to infinity.
112
114
The focal length can be computed from a desired Field Of View via
113
115
the equation: focal_length = 1/tan(FOV/2)
116
+ shareview : Axes3D, optional
117
+ Other Axes to share view angles with.
114
118
115
119
**kwargs
116
120
Other optional keyword arguments:
@@ -142,6 +146,10 @@ def __init__(
142
146
self ._shared_axes ["z" ].join (self , sharez )
143
147
self ._adjustable = 'datalim'
144
148
149
+ self ._shareview = shareview
150
+ if shareview is not None :
151
+ self ._shared_axes ["view" ].join (self , shareview )
152
+
145
153
if kwargs .pop ('auto_add_to_figure' , False ):
146
154
raise AttributeError (
147
155
'auto_add_to_figure is no longer supported for Axes3D. '
@@ -757,7 +765,8 @@ def clabel(self, *args, **kwargs):
757
765
"""Currently not implemented for 3D axes, and returns *None*."""
758
766
return None
759
767
760
- def view_init (self , elev = None , azim = None , roll = None , vertical_axis = "z" ):
768
+ def view_init (self , elev = None , azim = None , roll = None , vertical_axis = "z" ,
769
+ share = False ):
761
770
"""
762
771
Set the elevation and azimuth of the axes in degrees (not radians).
763
772
@@ -804,29 +813,34 @@ def view_init(self, elev=None, azim=None, roll=None, vertical_axis="z"):
804
813
constructor is used.
805
814
vertical_axis : {"z", "x", "y"}, default: "z"
806
815
The axis to align vertically. *azim* rotates about this axis.
816
+ share : bool, default: False
817
+ If ``True``, apply the settings to all Axes with shared views.
807
818
"""
808
819
809
820
self ._dist = 10 # The camera distance from origin. Behaves like zoom
810
821
811
822
if elev is None :
812
- self .elev = self .initial_elev
813
- else :
814
- self .elev = elev
815
-
823
+ elev = self .initial_elev
816
824
if azim is None :
817
- self .azim = self .initial_azim
818
- else :
819
- self .azim = azim
820
-
825
+ azim = self .initial_azim
821
826
if roll is None :
822
- self .roll = self .initial_roll
823
- else :
824
- self .roll = roll
825
-
826
- self ._vertical_axis = _api .check_getitem (
827
+ roll = self .initial_roll
828
+ vertical_axis = _api .check_getitem (
827
829
dict (x = 0 , y = 1 , z = 2 ), vertical_axis = vertical_axis
828
830
)
829
831
832
+ if share :
833
+ axes = {sibling for sibling
834
+ in self ._shared_axes ['view' ].get_siblings (self )}
835
+ else :
836
+ axes = [self ]
837
+
838
+ for ax in axes :
839
+ ax .elev = elev
840
+ ax .azim = azim
841
+ ax .roll = roll
842
+ ax ._vertical_axis = vertical_axis
843
+
830
844
def set_proj_type (self , proj_type , focal_length = None ):
831
845
"""
832
846
Set the projection type.
@@ -975,6 +989,23 @@ def sharez(self, other):
975
989
self .set_zlim (z0 , z1 , emit = False , auto = other .get_autoscalez_on ())
976
990
self .zaxis ._scale = other .zaxis ._scale
977
991
992
+ def shareview (self , other ):
993
+ """
994
+ Share the view angles with *other*.
995
+
996
+ This is equivalent to passing ``shareview=other`` when
997
+ constructing the Axes, and cannot be used if the view angles are
998
+ already being shared with another Axes.
999
+ """
1000
+ _api .check_isinstance (maxes ._base ._AxesBase , other = other )
1001
+ if self ._shareview is not None and other is not self ._shareview :
1002
+ raise ValueError ("view angles are already shared" )
1003
+ self ._shared_axes ["view" ].join (self , other )
1004
+ self ._shareview = other
1005
+ vertical_axis = {0 : "x" , 1 : "y" , 2 : "z" }[other ._vertical_axis ]
1006
+ self .view_init (elev = other .elev , azim = other .azim , roll = other .roll ,
1007
+ vertical_axis = vertical_axis , share = True )
1008
+
978
1009
def clear (self ):
979
1010
# docstring inherited.
980
1011
super ().clear ()
@@ -1107,8 +1138,9 @@ def _on_move(self, event):
1107
1138
roll = np .deg2rad (self .roll )
1108
1139
delev = - (dy / h )* 180 * np .cos (roll ) + (dx / w )* 180 * np .sin (roll )
1109
1140
dazim = - (dy / h )* 180 * np .sin (roll ) - (dx / w )* 180 * np .cos (roll )
1110
- self .elev = self .elev + delev
1111
- self .azim = self .azim + dazim
1141
+ elev = self .elev + delev
1142
+ azim = self .azim + dazim
1143
+ self .view_init (elev = elev , azim = azim , roll = roll , share = True )
1112
1144
self .stale = True
1113
1145
1114
1146
elif self .button_pressed in self ._pan_btn :
0 commit comments