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 _initialize(self):
      self._normalize()
      # Initialization (sec. 3.3)
  
      # sort points by y, then x
      flat_shape = self.pts.shape[0] * self.pts.shape[1]
      pts = self.pts.reshape(flat_shape).view(
          [("x", np.float32), ("y", np.float32)]
      )
      order = np.argsort(pts, order=("y", "x"))
      pts = pts[order]
      # update edges to match new point order
      invorder = np.argsort(order)
      self.edges = invorder[self.edges]
      self.pts = pts.view(np.float32).reshape(len(pts), 2)
  
      # make artificial points P-1 and P-2
      xmax = self.pts[:, 0].max()
      xmin = self.pts[:, 0].min()
      ymax = self.pts[:, 1].max()
      ymin = self.pts[:, 1].min()
      xa = (xmax - xmin) * 0.3
      ya = (ymax - ymin) * 0.3
      p1 = (xmin - xa, ymin - ya)
      p2 = (xmax + xa, ymin - ya)
  
      # prepend artificial points to point list
      newpts = np.empty((self.pts.shape[0] + 2, 2), dtype=float)
      newpts[0] = p1
      newpts[1] = p2
      newpts[2:] = self.pts
      self.pts = newpts
      self.edges += 2
  
      # find topmost point in each edge
      self._tops = self.edges.max(axis=1)
      self._bottoms = self.edges.min(axis=1)
  
      # inintialize sweep front
      # values in this list are indexes into self.pts
      self._front = [0, 2, 1]
  
      # empty triangle list.
      # This will contain [(a, b, c), ...] where a,b,c are indexes into
      # self.pts
      self.tris = OrderedDict()
  
      # For each triangle, maps (a, b): c
      # This is used to look up the thrid point in a triangle, given any
      # edge. Since each edge has two triangles, they are independently
      # stored as (a, b): c and (b, a): d
      self._edges_lookup = {}
  
imports: from __future__ import division, print_function
  from itertools import permutations
  import numpy
  from collections import OrderedDict
label_desc: Use image node_id 3 for calling the Triangulation obj's underlying member method code with example usage: obj._initialize() without return types