@@ -56,6 +56,7 @@ class Axes3D(Axes):
5656
5757 _axis_names = ("x" , "y" , "z" )
5858 Axes ._shared_axes ["z" ] = cbook .Grouper ()
59+ Axes ._shared_axes ["view" ] = cbook .Grouper ()
5960
6061 vvec = _api .deprecate_privatize_attribute ("3.7" )
6162 eye = _api .deprecate_privatize_attribute ("3.7" )
@@ -66,6 +67,7 @@ def __init__(
6667 self , fig , rect = None , * args ,
6768 elev = 30 , azim = - 60 , roll = 0 , sharez = None , proj_type = 'persp' ,
6869 box_aspect = None , computed_zorder = True , focal_length = None ,
70+ shareview = None ,
6971 ** kwargs ):
7072 """
7173 Parameters
@@ -111,6 +113,8 @@ def __init__(
111113 or infinity (numpy.inf). If None, defaults to infinity.
112114 The focal length can be computed from a desired Field Of View via
113115 the equation: focal_length = 1/tan(FOV/2)
116+ shareview : Axes3D, optional
117+ Other Axes to share view angles with.
114118
115119 **kwargs
116120 Other optional keyword arguments:
@@ -142,6 +146,10 @@ def __init__(
142146 self ._shared_axes ["z" ].join (self , sharez )
143147 self ._adjustable = 'datalim'
144148
149+ self ._shareview = shareview
150+ if shareview is not None :
151+ self ._shared_axes ["view" ].join (self , shareview )
152+
145153 if kwargs .pop ('auto_add_to_figure' , False ):
146154 raise AttributeError (
147155 'auto_add_to_figure is no longer supported for Axes3D. '
@@ -757,7 +765,8 @@ def clabel(self, *args, **kwargs):
757765 """Currently not implemented for 3D axes, and returns *None*."""
758766 return None
759767
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 ):
761770 """
762771 Set the elevation and azimuth of the axes in degrees (not radians).
763772
@@ -804,29 +813,34 @@ def view_init(self, elev=None, azim=None, roll=None, vertical_axis="z"):
804813 constructor is used.
805814 vertical_axis : {"z", "x", "y"}, default: "z"
806815 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.
807818 """
808819
809820 self ._dist = 10 # The camera distance from origin. Behaves like zoom
810821
811822 if elev is None :
812- self .elev = self .initial_elev
813- else :
814- self .elev = elev
815-
823+ elev = self .initial_elev
816824 if azim is None :
817- self .azim = self .initial_azim
818- else :
819- self .azim = azim
820-
825+ azim = self .initial_azim
821826 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 (
827829 dict (x = 0 , y = 1 , z = 2 ), vertical_axis = vertical_axis
828830 )
829831
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+
830844 def set_proj_type (self , proj_type , focal_length = None ):
831845 """
832846 Set the projection type.
@@ -964,7 +978,7 @@ def sharez(self, other):
964978 Axes, and cannot be used if the z-axis is already being shared with
965979 another Axes.
966980 """
967- _api .check_isinstance (maxes . _base . _AxesBase , other = other )
981+ _api .check_isinstance (Axes3D , other = other )
968982 if self ._sharez is not None and other is not self ._sharez :
969983 raise ValueError ("z-axis is already shared" )
970984 self ._shared_axes ["z" ].join (self , other )
@@ -975,6 +989,23 @@ def sharez(self, other):
975989 self .set_zlim (z0 , z1 , emit = False , auto = other .get_autoscalez_on ())
976990 self .zaxis ._scale = other .zaxis ._scale
977991
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 (Axes3D , 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+
9781009 def clear (self ):
9791010 # docstring inherited.
9801011 super ().clear ()
@@ -1107,8 +1138,9 @@ def _on_move(self, event):
11071138 roll = np .deg2rad (self .roll )
11081139 delev = - (dy / h )* 180 * np .cos (roll ) + (dx / w )* 180 * np .sin (roll )
11091140 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 )
11121144 self .stale = True
11131145
11141146 elif self .button_pressed in self ._pan_btn :
0 commit comments