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 _finalize(self):
      # Finalize (sec. 3.5)
  
      # (i) Add bordering triangles to fill hull
      front = list(OrderedDict.fromkeys(self._front))
  
      idx = len(front) - 2
      k = 1
      while k < idx - 1:
          # if edges lie in counterclockwise direction, then signed area
          # is positive
          if self._iscounterclockwise(
              front[k], front[k + 1], front[k + 2]
          ):
              self._add_tri(front[k], front[k + 1], front[k + 2])
              front.pop(k + 1)
              idx -= 1
              continue
          k += 1
  
      # (ii) Remove all triangles not inside the hull
      #      (not described in article)
  
      tris = []  # triangles to check
      tri_state = {}  # 0 for outside, 1 for inside
  
      # find a starting triangle
      for t in self.tris:
          if 0 in t or 1 in t:
              tri_state[t] = 0
              tris.append(t)
              break
  
      while tris:
          next_tris = []
          for t in tris:
              v = tri_state[t]
              for i in (0, 1, 2):
                  edge = (t[i], t[(i + 1) % 3])
                  pt = t[(i + 2) % 3]
                  t2 = self._adjacent_tri(edge, pt)
                  if t2 is None:
                      continue
                  t2a = t2[1:3] + t2[0:1]
                  t2b = t2[2:3] + t2[0:2]
                  if (
                      t2 in tri_state
                      or t2a in tri_state
                      or t2b in tri_state
                  ):
                      continue
                  if self._is_constraining_edge(edge):
                      tri_state[t2] = 1 - v
                  else:
                      tri_state[t2] = v
                  next_tris.append(t2)
          tris = next_tris
  
      for t, v in tri_state.items():
          if v == 0:
              self._remove_tri(*t)
  
imports: from __future__ import division, print_function
  from itertools import permutations
  import numpy
  from collections import OrderedDict
label_desc: Use image node_id 5 for calling the Triangulation obj's underlying member method code with example usage: obj._finalize() without return types