1212import numpy as np
1313
1414from matplotlib import (
15- artist , colors as mcolors , lines , text as mtext , path as mpath )
15+ artist , cbook , colors as mcolors , lines , text as mtext , path as mpath )
1616from matplotlib .collections import (
1717 LineCollection , PolyCollection , PatchCollection , PathCollection )
1818from matplotlib .colors import Normalize
@@ -49,13 +49,12 @@ def get_dir_vector(zdir):
4949 - 'y': equivalent to (0, 1, 0)
5050 - 'z': equivalent to (0, 0, 1)
5151 - *None*: equivalent to (0, 0, 0)
52- - an iterable (x, y, z) is returned unchanged.
52+ - an iterable (x, y, z) is converted to a NumPy array, if not already
5353
5454 Returns
5555 -------
5656 x, y, z : array-like
57- The direction vector. This is either a numpy.array or *zdir* itself if
58- *zdir* is already a length-3 iterable.
57+ The direction vector.
5958 """
6059 if zdir == 'x' :
6160 return np .array ((1 , 0 , 0 ))
@@ -66,7 +65,7 @@ def get_dir_vector(zdir):
6665 elif zdir is None :
6766 return np .array ((0 , 0 , 0 ))
6867 elif np .iterable (zdir ) and len (zdir ) == 3 :
69- return zdir
68+ return np . array ( zdir )
7069 else :
7170 raise ValueError ("'x', 'y', 'z', None or vector of length 3 expected" )
7271
@@ -95,22 +94,55 @@ def __init__(self, x=0, y=0, z=0, text='', zdir='z', **kwargs):
9594 mtext .Text .__init__ (self , x , y , text , ** kwargs )
9695 self .set_3d_properties (z , zdir )
9796
97+ def get_position_3d (self ):
98+ """Return the (x, y, z) position of the text."""
99+ return self ._x , self ._y , self ._z
100+
101+ def set_position_3d (self , xyz , zdir = None ):
102+ """
103+ Set the (*x*, *y*, *z*) position of the text.
104+
105+ Parameters
106+ ----------
107+ xyz : (float, float, float)
108+ The position in 3D space.
109+ zdir : {'x', 'y', 'z', None, 3-tuple}
110+ The direction of the text. If unspecified, the zdir will not be
111+ changed.
112+ """
113+ super ().set_position (xyz [:2 ])
114+ self .set_z (xyz [2 ])
115+ if zdir is not None :
116+ self ._dir_vec = get_dir_vector (zdir )
117+
118+ def set_z (self , z ):
119+ """
120+ Set the *z* position of the text.
121+
122+ Parameters
123+ ----------
124+ z : float
125+ """
126+ self ._z = z
127+ self .stale = True
128+
98129 def set_3d_properties (self , z = 0 , zdir = 'z' ):
99- x , y = self .get_position ()
100- self ._position3d = np .array ((x , y , z ))
130+ self ._z = z
101131 self ._dir_vec = get_dir_vector (zdir )
102132 self .stale = True
103133
104134 @artist .allow_rasterization
105135 def draw (self , renderer ):
136+ position3d = np .array ((self ._x , self ._y , self ._z ))
106137 proj = proj3d .proj_trans_points (
107- [self ._position3d , self ._position3d + self ._dir_vec ], renderer .M )
138+ [position3d , position3d + self ._dir_vec ],
139+ renderer .M )
108140 dx = proj [0 ][1 ] - proj [0 ][0 ]
109141 dy = proj [1 ][1 ] - proj [1 ][0 ]
110142 angle = math .degrees (math .atan2 (dy , dx ))
111- self . set_position (( proj [0 ][0 ], proj [1 ][0 ]))
112- self . set_rotation ( _norm_text_angle (angle ))
113- mtext .Text .draw (self , renderer )
143+ with cbook . _setattr_cm ( self , _x = proj [0 ][0 ], _y = proj [1 ][0 ],
144+ _rotation = _norm_text_angle (angle )):
145+ mtext .Text .draw (self , renderer )
114146 self .stale = False
115147
116148 def get_tightbbox (self , renderer ):
0 commit comments