class_docstr: Mixin to provide labelling capability to `.ContourSet`.
class_docstr_tok: ["Mixin","to","provide","labelling","capability","to","`",".ContourSet","`","."]
docstr: Calculate the appropriate label rotation given the linecontour
  coordinates in screen units, the index of the label location and the
  label width.
  
  If *lc* is not None or empty, also break contours and compute
  inlining.
  
  *spacing* is the empty space to leave around the label, in pixels.
  
  Both tasks are done together to avoid calculating path lengths
  multiple times, which is relatively costly.
  
  The method used here involves computing the path length along the
  contour in pixel coordinates and then looking approximately (label
  width / 2) away from central point to determine rotation and then to
  break contour if desired.
docstr_tok: ["Calculate","the","appropriate","label","rotation","given","the","linecontour","coordinates","in","screen","units",",","the","index","of","the","label","location","and","the","label","width",".","If","*","lc","*","is","not","None","or","empty",",","also","break","contours","and","compute","inlining",".","*","spacing","*","is","the","empty","space","to","leave","around","the","label",",","in","pixels",".","Both","tasks","are","done","together","to","avoid","calculating","path","lengths","multiple","times",",","which","is","relatively","costly",".","The","method","used","here","involves","computing","the","path","length","along","the","contour","in","pixel","coordinates","and","then","looking","approximately","(","label","width","\/","2",")","away","from","central","point","to","determine","rotation","and","then","to","break","contour","if","desired","."]
code: def calc_label_rot_and_inline(self, slc, ind, lw, lc=None, spacing=5):
      """
      Calculate the appropriate label rotation given the linecontour
      coordinates in screen units, the index of the label location and the
      label width.
  
      If *lc* is not None or empty, also break contours and compute
      inlining.
  
      *spacing* is the empty space to leave around the label, in pixels.
  
      Both tasks are done together to avoid calculating path lengths
      multiple times, which is relatively costly.
  
      The method used here involves computing the path length along the
      contour in pixel coordinates and then looking approximately (label
      width / 2) away from central point to determine rotation and then to
      break contour if desired.
      """
  
      if lc is None:
          lc = []
      # Half the label width
      hlw = lw / 2.0
  
      # Check if closed and, if so, rotate contour so label is at edge
      closed = _is_closed_polygon(slc)
      if closed:
          slc = np.concatenate([slc[ind:-1], slc[: ind + 1]])
          if len(lc):  # Rotate lc also if not empty
              lc = np.concatenate([lc[ind:-1], lc[: ind + 1]])
          ind = 0
  
      # Calculate path lengths
      pl = np.zeros(slc.shape[0], dtype=float)
      dx = np.diff(slc, axis=0)
      pl[1:] = np.cumsum(np.hypot(dx[:, 0], dx[:, 1]))
      pl = pl - pl[ind]
  
      # Use linear interpolation to get points around label
      xi = np.array([-hlw, hlw])
      if closed:  # Look at end also for closed contours
          dp = np.array([pl[-1], 0])
      else:
          dp = np.zeros_like(xi)
  
      # Get angle of vector between the two ends of the label - must be
      # calculated in pixel space for text rotation to work correctly.
      (dx,), (dy,) = (
          np.diff(np.interp(dp + xi, pl, slc_col)) for slc_col in slc.T
      )
      rotation = np.rad2deg(np.arctan2(dy, dx))
  
      if self.rightside_up:
          # Fix angle so text is never upside-down
          rotation = (rotation + 90) % 180 - 90
  
      # Break contour if desired
      nlc = []
      if len(lc):
          # Expand range by spacing
          xi = dp + xi + np.array([-spacing, spacing])
  
          # Get (integer) indices near points of interest; use -1 as marker
          # for out of bounds.
          I = np.interp(xi, pl, np.arange(len(pl)), left=-1, right=-1)
          I = [np.floor(I[0]).astype(int), np.ceil(I[1]).astype(int)]
          if I[0] != -1:
              xy1 = [np.interp(xi[0], pl, lc_col) for lc_col in lc.T]
          if I[1] != -1:
              xy2 = [np.interp(xi[1], pl, lc_col) for lc_col in lc.T]
  
          # Actually break contours
          if closed:
              # This will remove contour if shorter than label
              if all(i != -1 for i in I):
                  nlc.append(np.vstack([xy2, lc[I[1] : I[0] + 1], xy1]))
          else:
              # These will remove pieces of contour if they have length zero
              if I[0] != -1:
                  nlc.append(np.vstack([lc[: I[0] + 1], xy1]))
              if I[1] != -1:
                  nlc.append(np.vstack([xy2, lc[I[1] :]]))
  
          # The current implementation removes contours completely
          # covered by labels.  Uncomment line below to keep
          # original contour if this is the preferred behavior.
          # if not len(nlc): nlc = [lc]
  
      return rotation, nlc
  
imports: from contextlib import ExitStack
  import functools
  import math
  from numbers import Integral
  import numpy
  from numpy import ma
  import matplotlib
  from matplotlib import _api, _docstring
  from matplotlib.backend_bases import MouseButton
  from matplotlib.lines import Line2D
  from matplotlib.path import Path
  from matplotlib.text import Text
  import matplotlib.ticker
  import matplotlib.cm
  import matplotlib.colors
  import matplotlib.collections
  import matplotlib.font_manager
  import matplotlib.cbook
  import matplotlib.patches
  import matplotlib.transforms
label_desc: Use image node_id 8 for calling the ContourLabeler obj's underlying member method code with example usage: obj.calc_label_rot_and_inline(slc, ind, lw, lc, spacing) and returns: rotation,  nlc