2929# per level.
3030
3131
32+ class ClabelText (text .Text ):
33+ """
34+ Unlike the ordinary text, the get_rotation returns an updated
35+ angle in the pixel coordinate assuming that the input rotation is
36+ an angle in data coordinate (or whatever transform set).
37+ """
38+ def get_rotation (self ):
39+ angle = text .Text .get_rotation (self )
40+ trans = self .get_transform ()
41+ x , y = self .get_position ()
42+ new_angles = trans .transform_angles (np .array ([angle ]),
43+ np .array ([[x , y ]]))
44+ return new_angles [0 ]
45+
46+
3247class ContourLabeler :
3348 '''Mixin to provide labelling capability to ContourSet'''
3449
@@ -95,6 +110,12 @@ def clabel(self, *args, **kwargs):
95110 if *True* (default), label rotations will always be plus
96111 or minus 90 degrees from level.
97112
113+ *use_clabeltext*:
114+ if *True* (default is False), ClabelText class (instead of
115+ matplotlib.Text) is used to create labels. ClabelText
116+ recalculates rotation angles of texts during the drawing time,
117+ therefore this can be used if aspect of the axes changes.
118+
98119 .. plot:: mpl_examples/pylab_examples/contour_demo.py
99120 """
100121
@@ -117,6 +138,8 @@ def clabel(self, *args, **kwargs):
117138 self .labelFmt = kwargs .get ('fmt' , '%1.3f' )
118139 _colors = kwargs .get ('colors' , None )
119140
141+ self ._use_clabeltext = kwargs .get ('use_clabeltext' , False )
142+
120143 # Detect if manual selection is desired and remove from argument list
121144 self .labelManual = kwargs .get ('manual' ,False )
122145
@@ -435,13 +458,29 @@ def calc_label_rot_and_inline( self, slc, ind, lw, lc=None, spacing=5 ):
435458
436459 return (rotation ,nlc )
437460
438-
439- def add_label (self ,x ,y ,rotation ,lev ,cvalue ):
461+ def _get_label_text (self ,x ,y ,rotation ):
440462 dx ,dy = self .ax .transData .inverted ().transform_point ((x ,y ))
441463 t = text .Text (dx , dy , rotation = rotation ,
442464 horizontalalignment = 'center' ,
443465 verticalalignment = 'center' )
444-
466+ return t
467+
468+ def _get_label_clabeltext (self ,x ,y ,rotation ):
469+ # x, y, rotation is given in pixel coordinate. Convert them to
470+ # the data coordinate and create a label using ClabelText
471+ # class. This way, the roation of the clabel is along the
472+ # contour line always.
473+ transDataInv = self .ax .transData .inverted ()
474+ dx ,dy = transDataInv .transform_point ((x ,y ))
475+ drotation = transDataInv .transform_angles (np .array ([rotation ]),
476+ np .array ([[x ,y ]]))
477+ t = ClabelText (dx , dy , rotation = drotation [0 ],
478+ horizontalalignment = 'center' ,
479+ verticalalignment = 'center' )
480+
481+ return t
482+
483+ def _add_label (self , t , x , y , lev , cvalue ):
445484 color = self .labelMappable .to_rgba (cvalue ,alpha = self .alpha )
446485
447486 _text = self .get_text (lev ,self .labelFmt )
@@ -453,6 +492,28 @@ def add_label(self,x,y,rotation,lev,cvalue):
453492 # Add label to plot here - useful for manual mode label selection
454493 self .ax .add_artist (t )
455494
495+ def add_label (self ,x ,y ,rotation ,lev ,cvalue ):
496+ """
497+ Addd contour label using Text class.
498+ """
499+
500+ t = self ._get_label_text (x ,y ,rotation )
501+ self ._add_label (t , x , y , lev , cvalue )
502+
503+ def add_label_clabeltext (self ,x ,y ,rotation ,lev ,cvalue ):
504+ """
505+ Addd contour label using ClabelText class.
506+ """
507+ # x, y, rotation is given in pixel coordinate. Convert them to
508+ # the data coordinate and create a label using ClabelText
509+ # class. This way, the roation of the clabel is along the
510+ # contour line always.
511+
512+ t = self ._get_label_clabeltext (x ,y ,rotation )
513+ self ._add_label (t , x , y , lev , cvalue )
514+
515+
516+
456517 def pop_label (self ,index = - 1 ):
457518 '''Defaults to removing last label, but any index can be supplied'''
458519 self .labelCValues .pop (index )
@@ -462,6 +523,11 @@ def pop_label(self,index=-1):
462523 def labels (self , inline , inline_spacing ):
463524 trans = self .ax .transData # A bit of shorthand
464525
526+ if self ._use_clabeltext :
527+ add_label = self .add_label_clabeltext
528+ else :
529+ add_label = self .add_label
530+
465531 for icon , lev , fsize , cvalue in zip (
466532 self .labelIndiceList , self .labelLevelList , self .labelFontSizeList ,
467533 self .labelCValueList ):
@@ -493,7 +559,7 @@ def labels(self, inline, inline_spacing):
493559 inline_spacing )
494560
495561 # Actually add the label
496- self . add_label (x ,y ,rotation ,lev ,cvalue )
562+ add_label (x ,y ,rotation ,lev ,cvalue )
497563
498564 # If inline, add new contours
499565 if inline :
0 commit comments