19
19
20
20
import time
21
21
import numpy as np
22
+
22
23
from matplotlib import path , verbose
23
- from cbook import is_sequence_of_strings
24
+ from matplotlib . cbook import is_sequence_of_strings
24
25
25
26
class BlockingInput (object ):
26
27
"""
@@ -267,46 +268,38 @@ def button1(self,event):
267
268
268
269
if event .inaxes == cs .ax :
269
270
conmin ,segmin ,imin ,xmin ,ymin = cs .find_nearest_contour (
270
- event .x , event .y , cs .label_indices )[:5 ]
271
+ event .x , event .y , cs .labelIndiceList )[:5 ]
271
272
272
273
# Get index of nearest level in subset of levels used for labeling
273
- lmin = cs .label_indices .index (conmin )
274
+ lmin = cs .labelIndiceList .index (conmin )
274
275
276
+ # Coordinates of contour
275
277
paths = cs .collections [conmin ].get_paths ()
276
278
lc = paths [segmin ].vertices
277
279
278
- # Figure out label rotation. This is very cludgy.
279
- # Ideally, there would be one method in ContourLabeler
280
- # that would figure out the best rotation for a label at a
281
- # point, but the way automatic label rotation is done is
282
- # quite mysterious to me and doesn't seem easy to
283
- # generalize to non-automatic label placement. The method
284
- # used below is not very robust! It basically looks one
285
- # point before and one point after label location on
286
- # contour and takes mean of angles of two vectors formed.
287
- # This produces "acceptable" results, but not nearly as
288
- # nice as automatic method.
289
- ll = lc [max (0 ,imin - 1 ):imin + 2 ] # Get points around point
290
- dd = np .diff (ll ,axis = 0 )
291
- rotation = np .mean ( np .arctan2 (dd [:,1 ], dd [:,0 ]) ) * 180 / np .pi
292
- if rotation > 90 :
293
- rotation = rotation - 180
294
- if rotation < - 90 :
295
- rotation = 180 + rotation
296
-
297
- cs .add_label (xmin ,ymin ,rotation ,cs .label_levels [lmin ],
298
- cs .label_cvalues [lmin ])
280
+ # In pixel/screen space
281
+ slc = cs .ax .transData .transform (lc )
282
+
283
+ # Get label width for rotating labels and breaking contours
284
+ lw = cs .get_label_width (cs .labelLevelList [lmin ],
285
+ cs .labelFmt , cs .labelFontSizeList [lmin ])
286
+
287
+ # Figure out label rotation.
288
+ rotation ,nlc = cs .calc_label_rot_and_inline (
289
+ slc , imin , lw , lc if self .inline else [],
290
+ self .inline_spacing )
291
+
292
+ cs .add_label (xmin ,ymin ,rotation ,cs .labelLevelList [lmin ],
293
+ cs .labelCValueList [lmin ])
299
294
300
295
if self .inline :
301
- # Get label width for breaking contours
302
- lw = cs .get_label_width (cs .label_levels [lmin ],
303
- cs .fmt , cs .fslist [lmin ])
304
- # Break contour
305
- new = cs .break_linecontour (lc ,rotation ,lw ,imin )
306
- if len (new [0 ]):
307
- paths [segmin ] = path .Path (new [0 ])
308
- if len (new [1 ]):
309
- paths .extend ([path .Path (new [1 ])])
296
+ # Remove old, not looping over paths so we can do this up front
297
+ paths .pop (segmin )
298
+
299
+ # Add paths if not empty or single point
300
+ for n in nlc :
301
+ if len (n )> 1 :
302
+ paths .append ( path .Path (n ) )
310
303
311
304
self .fig .canvas .draw ()
312
305
else : # Remove event if not valid
@@ -320,14 +313,21 @@ def button3(self,event):
320
313
broken contour - once humpty-dumpty is broken, he can't be put
321
314
back together. In inline mode, this does nothing.
322
315
"""
316
+ # Remove this last event - not too important for clabel use
317
+ # since clabel normally doesn't have a maximum number of
318
+ # events, but best for cleanliness sake.
319
+ BlockingInput .pop (self )
320
+
323
321
if self .inline :
324
322
pass
325
323
else :
326
324
self .cs .pop_label ()
327
325
self .cs .ax .figure .canvas .draw ()
328
326
329
- def __call__ (self ,inline ,n = - 1 ,timeout = - 1 ):
327
+ def __call__ (self ,inline ,inline_spacing = 5 , n = - 1 ,timeout = - 1 ):
330
328
self .inline = inline
329
+ self .inline_spacing = inline_spacing
330
+
331
331
BlockingMouseInput .__call__ (self ,n = n ,timeout = timeout ,
332
332
show_clicks = False )
333
333
0 commit comments