class_docstr: Constrained delaunay triangulation
  
  Implementation based on [1]_.
  
  Parameters
  ----------
  pts : array
      Nx2 array of points.
  edges : array
      Nx2 array of edges (dtype=int).
  
  Notes
  -----
  * Delaunay legalization is not yet implemented. This produces a proper
    triangulation, but adding legalisation would produce fewer thin
    triangles.
  * The pts and edges arrays may be modified.
  
  References
  ----------
  .. [1] Domiter, V. and Žalik, B. Sweep‐line algorithm for constrained
     Delaunay triangulation
class_docstr_tok: ["Constrained","delaunay","triangulation","Implementation","based","on","[","1","]","_.","Parameters","--","--","--","--","--","pts",":","array","Nx2","array","of","points",".","edges",":","array","Nx2","array","of","edges","(","dtype=int",")",".","Notes","--","--","-","*","Delaunay","legalization","is","not","yet","implemented",".","This","produces","a","proper","triangulation",",","but","adding","legalisation","would","produce","fewer","thin","triangles",".","*","The","pts","and","edges","arrays","may","be","modified",".","References","--","--","--","--","--","..","[","1","]","Domiter",",","V.","and","\u017dalik",",","B.","Sweep\u2010line","algorithm","for","constrained","Delaunay","triangulation"]
code: def _add_tri(self, a, b, c):
      # sanity check
      assert a != b and b != c and c != a
  
      # ignore flat tris
      pa = self.pts[a]
      pb = self.pts[b]
      pc = self.pts[c]
      if np.all(pa == pb) or np.all(pb == pc) or np.all(pc == pa):
          return
  
      # check this tri is unique
      for t in permutations((a, b, c)):
          if t in self.tris:
              raise Exception(
                  "Cannot add %s; already have %s" % ((a, b, c), t)
              )
  
      # TODO: should add to edges_lookup after legalization??
      if self._iscounterclockwise(a, b, c):
          assert (a, b) not in self._edges_lookup
          assert (b, c) not in self._edges_lookup
          assert (c, a) not in self._edges_lookup
          self._edges_lookup[(a, b)] = c
          self._edges_lookup[(b, c)] = a
          self._edges_lookup[(c, a)] = b
      else:
          assert (b, a) not in self._edges_lookup
          assert (c, b) not in self._edges_lookup
          assert (a, c) not in self._edges_lookup
          self._edges_lookup[(b, a)] = c
          self._edges_lookup[(c, b)] = a
          self._edges_lookup[(a, c)] = b
  
      tri = (a, b, c)
  
      self.tris[tri] = None
  
imports: from __future__ import division, print_function
  from itertools import permutations
  import numpy
  from collections import OrderedDict
label_desc: Use image node_id 26 for calling the Triangulation obj's underlying member method code with example usage: obj._add_tri(a, b, c) without return types