From 9ba8c2d1c63e53c025cff11df5bc70f270c3b5f8 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Sat, 18 May 2002 18:52:32 +0000
Subject: [PATCH] remove tetgen from cvs until we actually use it...

---
 Tetgen/Makefile      |    68 -
 Tetgen/constrain.cpp |  3479 -------------
 Tetgen/defines.h     |   175 -
 Tetgen/linklist.cpp  |  1149 -----
 Tetgen/linklist.h    |   470 --
 Tetgen/predicate.cpp |  2945 -----------
 Tetgen/quality.cpp   |  1723 -------
 Tetgen/tetlib.cpp    | 10847 -----------------------------------------
 Tetgen/tetlib.h      |  1301 -----
 Tetgen/tetmain.cpp   |    11 -
 Tetgen/trilib.cpp    |  5602 ---------------------
 Tetgen/trilib.h      |   515 --
 12 files changed, 28285 deletions(-)
 delete mode 100644 Tetgen/Makefile
 delete mode 100644 Tetgen/constrain.cpp
 delete mode 100644 Tetgen/defines.h
 delete mode 100644 Tetgen/linklist.cpp
 delete mode 100644 Tetgen/linklist.h
 delete mode 100644 Tetgen/predicate.cpp
 delete mode 100644 Tetgen/quality.cpp
 delete mode 100644 Tetgen/tetlib.cpp
 delete mode 100644 Tetgen/tetlib.h
 delete mode 100644 Tetgen/tetmain.cpp
 delete mode 100644 Tetgen/trilib.cpp
 delete mode 100644 Tetgen/trilib.h

diff --git a/Tetgen/Makefile b/Tetgen/Makefile
deleted file mode 100644
index adff2be3b3..0000000000
--- a/Tetgen/Makefile
+++ /dev/null
@@ -1,68 +0,0 @@
-# makefile for Tetgen
-#
-# Type "make" to compile tetgen.
-#
-# After compiling, type "tetgen -h" to read instructions
-#   for using this programs.
-#
-# Type "make clean" to delete all object(*.o) files.
-
-# BIN is the directory where you want to put the executable programs.
-# SRC is the directory in which the *.cpp source files are. 
-
-BIN = ../bin/
-SRC = ./
-
-# CC should be set to the name of your favorite C++ compiler.
-
-CC = g++
-
-# CSWITCHES is a list of all switches passed to the C++ compiler.  
-#   You'd best using the best level of optimization.  
-#
-# By default, Tetgen use double precision floating point numbers.  
-#   If you prefer single precision, use the -DSINGLE switch.
-#   Double precision uses more memory, but improves the resolution of
-#   the meshes you can generate with Tetgen.  It also reduces the
-#   likelihood of a floating exception due to overflow.
-#
-# If yours is not a Unix system, use the -DNO_TIMER switch to eliminate 
-#   the Unix-specific timer code.
-#
-# If you are modifying Tetgen, I recommend using the -DSELF_CHECK switch
-#   while you are debugging.  Defining the SELF_CHECK symbol causes
-#   Tetgen to include self-checking code.  Tetgen will execute more
-#   slowly, however, so be sure to remove this switch before compiling a
-#   production version.
-#
-
-CSWITCHES = -O
-
-# Objects in lexicographic order.
-
-OBJS = constrain.o \
-       linklist.o \
-       predicate.o \
-       quality.o \
-       tetlib.o \
-       trilib.o 
-
-# RM should be set to the name of your favorite rm (file deletion program).
-
-RM = /bin/rm
-
-# The action starts here.
-
-all: tetlib tetgen
-
-.cpp.o:
-	$(CC) $(CSWITCHES) -c $<
-
-tetlib: $(OBJS)
-	ar r ../lib/Tetgen.a $(OBJS)
-
-tetgen: tetmain.o $(OBJS)
-	$(CC) $(CSWITCHES) -o $(BIN)tetgen tetmain.o $(OBJS) -lm
-
-clean:
-	$(RM) $(SRC)*.o
diff --git a/Tetgen/constrain.cpp b/Tetgen/constrain.cpp
deleted file mode 100644
index fc9c96fed0..0000000000
--- a/Tetgen/constrain.cpp
+++ /dev/null
@@ -1,3479 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// constrain.cpp    Implement the boundary-constranied Delaunay mesh         //
-//                  generation routines.                                     //
-//                                                                           //
-// Tetgen Version 1.0 beta                                                   //
-// November, 2001                                                            //
-//                                                                           //
-// Si hang                                                                   //
-// Email: sihang@weboo.com                                                   //
-// http://www.weboo.com/sh/tetgen.htm                                        //
-//                                                                           //
-// You are free to use, copy and modify the sources under certain            //
-// circumstances, provided this copyright notice remains intact.             //
-// See the file LICENSE for details.                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Unlike the two-dimension case that is guaranteed to recover the segment,  //
-// the three-dimension case has no such guarantee to recover the segment and //
-// facet. The Schonart polyhedron[1] is an example of polyhedron which can   //
-// not be triangulated without adding internal point. So in three-dimension, //
-// boundary-constrained mesh generation is a complex problem which can be    //
-// defined in many ways and several solutions can be proposed.               //
-//                                                                           //
-// Currently, there exist several methods to solve this problem. Weatherill  //
-// [2] and Borouchaki[3] retriangulated the elements intersected by a        //
-// constrained face so as to create a triangulation of the face. In this     //
-// case, the Steiner points are created on the boundary. George et al. [4]   //
-// and Owen[5] regenerated the missing edges and faces in boundary by means  //
-// of local transformations and the possible Steiner points insertion inside //
-// the domain. Shewchuk[6] thought of the constrained boundary triangulation //
-// problem as a subproblem of mesh improvement in his Delaunay refinement    //
-// algorithm and proposed a method to recover boundary only need inserting   //
-// points on segments.                                                       //
-//                                                                           //
-// The method I used to recover segments and facets is relatively derived    //
-// from above methods. It has two stages: Segment recover and Facet recover. //
-// It can be simply described below, the detail please refer to my thesis:   //
-//                                                                           //
-// We use the 'edge flip' + 'stitching' method to recover missing segments.  //
-// For each missing segment, try edge flip operations(flip23, flip22 and     //
-// flip44) first. Under most cases, after one or a series of flip operations,//
-// the missing segment can be recovered. If edge flips failed, inserting a   //
-// vertex into the mesh at the midpoint of the segment (more accurately, at  //
-// the midpoint of the place where the segment should be). After the mesh is //
-// adjusted to maintain the Delaunay property, the two resulting subsegments //
-// may appear in the mesh. If not, the whole procedure is repeated           //
-// recursively for each missing subsegment until the original segment is     //
-// represented by a contiguous linear sequence of edges of the mesh. We are  //
-// assure of eventual success because the Delaunay triangulation always      //
-// connects a vertex to its nearest neighbour; once the spacing of vertices  //
-// along a segment is sufficiently small, its entire length will be          //
-// represented.                                                              //
-//                                                                           //
-// When all missing subsegments are recovered missing facets are recovered   //
-// in an analogous manner. For each facet, it is necessary maintain a        //
-// two-dimensional Delaunay triangulation of its vertices, independent from  //
-// the tetrahedralization in which we hope its subfaces will eventually      //
-// appear. For each triangular subface in a facet triangulation, look for    //
-// a matching face in the tetrahedralization. If there could't find a match  //
-// subface, we can sure this subface is missing from current mesh. When we   //
-// find a subface is missing from the mesh, a local re-meshing method is     //
-// used to recovery all missing subfaces (start from this subface). Please   //
-// refer to Usermanual chapter 4.4.2 for detail description of this methhod. //
-//                                                                           //
-// However, There is no guarantee to recover facets in all condition of my   //
-// implementation now. Acctually, It's a KNOWN BUG now there are still valid //
-// input files for which Tetgen program can not produce a valid mesh. If     //
-// you come across one of these, please send it to sihang@weboo.com so that  //
-// I can continue to make the code more robust, thank you.                   //
-//                                                                           //
-// Refernces:                                                                //
-//                                                                           //
-// [1] E. Schonardt, Uber die Zerlegung von Dreieckspolyedern inTetraeder,   //
-//     Mathematische Annalen, vol 98, pp. 309-312, 1928.                     //
-// [2] N.P. Weatherill and O. Hassan, Efficient three-dimensional Delaunay   //
-//     triangulation with automatic point creation and imposed boundary con- //
-//     straints, Int. J. Numer. Meth. in Eng., vol 37, pp. 2005-2039, 1994.  //
-// [3] H. Borouchaki, Triangulation sous contraintes en dimension quelconque,//
-//     Rapport de Recherche INRIA, RR-2373, 1994.                            //
-// [4] P.L. George, F. Hecht and E. Saltel, Automatic mesh generator with    //
-//     specified boundary, Comp. Meth. in Appl. Mech. and Eng., vol 13,      //
-//     pp. 269-288, 1991.                                                    //
-// [5] Steven J. Owen, Constrained Triangulation: Application to Hex-Domaint //
-//     Mesh Generation. Proceedings, 8th International Meshing Roundtable,   //
-//     South Lake Tahoe, CA, U.S.A., pp.31-41, October 1999                  //
-// [6] Jonathan Richard Shewchuk, Tetrahedral Mesh Generation by Delaunay    //
-//     Refinement. Proceedings of the Fourteenth Annual Symopsium on Comput- //
-//     ional Geometry (Minneapolis, Minnesota), pages 86-95, Association for //
-//     Computing Machinery, June, 1998.                                      //
-// [7] Jonathan Richard Shewchuk, A Condition Guaranteeing the Existence of  //
-//     Higher-Dimensional Constrained Delaunay Triangulations. Proceedings   //
-//     of the Fourteenth Annual Symopsium on Computional Geometry (Minneapo- //
-//     lis, Minnesota), pages 76-85, Association for Computing Machinery,    //
-//     June, 1998.                                                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-#include "tetlib.h"
-
-///////////////////////////////////////////////////////////////////////////////
-// Segment/Facet (Boundary) Constrained Routines.                            //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// finddirection()    Find the first tetrahedron on the path from one point  //
-//                    to another.                                            //
-//                                                                           //
-// Finds the tetrahedron that intersects a line segment drawn from the       //
-// origin of 'searchtet' to the point 'endpoint', and returns the result in  //
-// 'searchtet'.  The origin of 'searchtet' does not change, even though the  //
-// tetrahedron returned may differ from the one passed in. This routine is   //
-// used to find the direction to move in to get from one point to another.   //
-//                                                                           //
-// The return value notes whether the destination, apex or oppo of the found //
-// tetrahedron is collinear with the two points in question.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum mesh3d::finddirectionresult
-mesh3d::finddirection(triface *searchtet, point3d tend)
-{
-  triface checktet;
-  point3d tstart, tright, tleft, toppo;
-  int baseorient, rightorient, leftorient, forwardorient;
-  int rightflag, leftflag, forwardflag;
-  int basezeroflag, rightzeroflag, leftzeroflag, forwardzeroflag;
-
-  tstart = org(*searchtet);
-  adjustedgering(*searchtet, CCW);
-  if (tstart != org(*searchtet)) {
-    enextself(*searchtet);
-  }
-  tright = dest(*searchtet);
-  if (tright == tend) {
-    return RIGHTCOLLINEAR;
-  }
-  tleft = apex(*searchtet);
-  if (tleft == tend) {
-    return LEFTCOLLINEAR;
-  }
-
-  // Base plane is the plane include face(tstart, tright, tleft), the normal
-  //   is direct to toppo(toppo is above the base plane).
-  basezeroflag = 0;
-  // Is 'tend' below the base plane?
-  baseorient = iorient3d(tstart, tright, tleft, tend);
-  if (baseorient > 0) {
-    // Get another side's tetrahdera of base face, so 'tend' is above the
-    //   base plane, need reset tright and tleft.
-    symself(*searchtet);
-    assert(searchtet->tet != dummytet);
-    findversion(searchtet, tstart, tleft, 0);
-    tright = tleft;
-    tleft = apex(*searchtet);
-  } else if (baseorient == 0) {
-    basezeroflag = 1;
-  }
-
-  if (verbose > 2) {
-    printf("    Find direction to point %d, from tet(%d, %d, %d, %d).\n",
-           pointmark(tend), pointmark(tstart), pointmark(tright),
-           pointmark(tleft), pointmark(oppo(*searchtet)));
-  }
-
-  // Repeat turn right and turn left until find a satisfied tetrahedron.
-  while (true) {
-    toppo = oppo(*searchtet);
-    if (toppo == tend) {
-      return TOPCOLLINEAR;
-    }
-    // Must reset 'rightflag' and 'leftflag' at each start time. Because
-    //   we not always turn the same side in three-dimensional case.
-    rightflag = leftflag = forwardflag = 0;
-    rightzeroflag = leftzeroflag = 0; forwardzeroflag = 0;
-
-    // Is 'endpoint' to the right?
-    rightorient = iorient3d(tend, tstart, tright, toppo);
-    if (rightorient == 0) {
-      rightzeroflag = 1;
-    } else {
-      rightflag = rightorient > 0;
-    }
-    // Is 'endpoint' to the left?
-    leftorient = iorient3d(tstart, tend, tleft, toppo);
-    if (leftorient == 0) {
-      leftzeroflag = 1;
-    } else {
-      leftflag = leftorient > 0;
-    }
-    // Is 'endpoint' forward to the opposite?
-    forwardorient = iorient3d(tright, toppo, tleft, tend);
-    if (forwardorient == 0) {
-      forwardzeroflag = 1;
-    } else {
-      forwardflag = forwardorient > 0;
-    }
-
-    // Check zero flag first.
-    if (basezeroflag) {
-      if (rightzeroflag && forwardflag) {
-        return RIGHTCOLLINEAR;
-      } else if (leftzeroflag && forwardflag) {
-        return LEFTCOLLINEAR;
-      } else if (forwardflag) {
-        if ((rightflag == 0) && (leftflag == 0)) {
-          return WITHIN;
-        }
-      }
-    }
-
-    if (rightzeroflag) {
-      if (leftzeroflag && forwardflag) {
-        return TOPCOLLINEAR;
-      }
-      if (!leftflag && forwardflag) {
-        // This condition is tend coplanar with the right side(may be WITHIN
-        //   ) of this tet, and we can't turn left side(because the leftflag
-        //   is 0). The only choice is try to turn right. Check if there has
-        //   a boundary on the right.
-        fnext(*searchtet, checktet);
-        if (issymexist(&checktet)) {
-          rightflag = 1; // Here leftflag = 0;
-        } else {
-          // Hit a boundary when try turn right, take the right side as
-          //   base plane, then continue...
-          fnextself(*searchtet);
-          esymself(*searchtet);  // Don't miss the tstart.
-          enextself(*searchtet);
-          tleft = tright;
-          tright = toppo;
-          basezeroflag = 1;
-          if (verbose > 2) {
-            printf("    Take right as base palne. Get tet(%d, %d, %d, %d).\n",
-                   pointmark(tstart), pointmark(tright),
-                   pointmark(tleft), pointmark(oppo(*searchtet)));
-          }
-          continue;
-        }
-      }
-    } else if (leftzeroflag) {
-      if (rightzeroflag && forwardflag) {
-        return TOPCOLLINEAR;
-      }
-      if (!rightflag && forwardflag) {
-        // This condition is tend coplanar with the left side(may be WITHIN
-        //   ) of this tet, and we can't turn right side(because the right-
-        //   flag is 0). The only choice is try to turn left. Check if there
-        //   has a boundary on the left.
-        checktet = *searchtet;
-        enext2fnextself(checktet);
-        if (issymexist(&checktet)) {
-          leftflag = 1; // Here rightflag = 0;
-        } else {
-          // Hit a boundary when try turn left, take the left side as
-          //   base plane, then continue...
-          enext2fnextself(*searchtet);
-          esymself(*searchtet); // Don't miss the tstart.
-          tright = tleft;
-          tleft = toppo;
-          basezeroflag = 1;
-          if (verbose > 2) {
-            printf("    Take left as base palne. Get tet(%d, %d, %d, %d).\n",
-                   pointmark(tstart), pointmark(tright),
-                   pointmark(tleft), pointmark(oppo(*searchtet)));
-          }
-          continue;
-        }
-      }
-    } else {
-      // None zero flag(!rightzeroflag && !leftzeroflag) cases.
-      if (!rightflag && !leftflag) {
-        // Both rightflag = 0 and leftflag = 0. This mean tend is both below
-        //   the right side and left side. There have two conditions, decide
-        //   by current forwardflag.
-        if (forwardflag) {
-          return ACROSS;
-        } else {
-          // 'searchtet' faces directly away from `tend'.  We could go left
-          //   or right. Ask whether it's a tetrahedron or a boundary on the
-          //   right.
-          fnext(*searchtet, checktet);
-          if (issymexist(&checktet)) {
-            rightflag = 1; // leftflag = 0;
-          } else {
-            leftflag = 1;  // rightflag = 0;
-          }
-        }
-      } else if (rightflag && leftflag) {
-        // 'searchtet' faces directly away from `tend'.  We could go left
-        //   or right. Ask whether it's a tetrahedron or a boundary on the
-        //   right.
-        fnext(*searchtet, checktet);
-        if (issymexist(&checktet)) {
-          leftflag = 0;  // rightflag = 1;
-        } else {
-          rightflag = 0; // leftflag = 1;
-        }
-      }
-    }
-
-    if (rightflag) {
-      // Turn right once.
-      fnextself(*searchtet);
-      symself(*searchtet);
-      assert(searchtet->tet != dummytet);
-      findversion(searchtet, tstart, tright, 0);
-      tleft = toppo;
-      basezeroflag = rightzeroflag;
-      if (verbose > 2) {
-        printf("    Turn right side.");
-      }
-    } else {
-      assert(leftflag);
-      // Turn left once.
-      enext2fnextself(*searchtet);
-      symself(*searchtet);
-      assert(searchtet->tet != dummytet);
-      findversion(searchtet, tstart, toppo, 0);
-      tright = toppo;
-      basezeroflag = leftzeroflag;
-      if (verbose > 2) {
-        printf("    Turn left side.");
-      }
-    }
-    if (verbose > 2) {
-      printf(" Get tet(%d, %d, %d, %d).\n",
-           pointmark(tstart), pointmark(tright),
-           pointmark(tleft), pointmark(oppo(*searchtet)));
-    }
-#ifdef SELF_CHECK
-    baseorient = iorient3d(tstart, tright, tleft, tend);
-    if (baseorient > 0) {
-      printf("Internal error in finddirection():\n");
-      printf("  'baseorient' shouldn't below the base plane.\n");
-      internalerror();
-    }
-#endif // defined SELF_CHECK
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// segmentintersection()    Find the intersection of an existing segment and //
-//                          a segment that is being inserted. Insert a point //
-//                          at the intersection, splitting an existing shell //
-//                          edge(subsegment).                                //
-//                                                                           //
-// The segment being inserted connects the apex of splittet to endpoint2.    //
-// splitsubseg is the subsegment being split, the edge being split connects  //
-// the origin and destination of splittet.                                   //
-//                                                                           //
-// On completion, splittet is a handle having the newly inserted             //
-// intersection point as its origin, and endpoint1 as its destination.       //
-//                                                                           //
-// Use line and plane intersection algorithm to calculate the intersection   //
-// point of two segment in 3-space:                                          //
-//   If the plane is defined as:                                             //
-//     a*x + b*y + c*z + d = 0           (1)                                 //
-//   and the line is defined as:                                             //
-//     x = x1 + (x2 - x1)*t = x1 + e*t                                       //
-//     y = y1 + (y2 - y1)*t = y1 + f*t   (2)                                 //
-//     z = z1 + (z2 - z1)*t = z1 + g*t                                       //
-//   Then just substitute (2) into the plane equation (1). You end up with:  //
-//     t = - (a*x1 + b*y1 + c*z1 + d)/(a*e + b*f + c*g)                      //
-//   When the denominator is zero, the line is contained in the plane if the //
-//   numerator is also zero (the point at t=0 satisfies the plane equation), //
-//   otherwise the line is parallel to the plane.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::segmentintersection(triface *splittet, face *splitshseg,
-                                 point3d endpoint2)
-{
-  point3d endpoint1, torg, tdest;
-  point3d leftpoint, rightpoint, oppopoint;
-  point3d newpoint;
-  enum insertsiteresult success;
-  enum finddirectionresult collinear;
-  enum locateresult locval;
-  REAL a, b, c, d, e, f, g, t;
-  REAL v12[3], v34[3], norm0[3], norm1[3];
-  int i;
-
-  segmentintersectioncount++;
-
-  // Find the other three segment endpoints.
-  endpoint1 = apex(*splittet);
-  torg = org(*splittet);
-  tdest = dest(*splittet);
-
-  // Segment intersection formulae; see the graphic algorithm faq.
-  Sub3D(tdest, torg, v12);
-  Sub3D(endpoint2, endpoint1, v34);
-  Cross3D(v12, v34, norm0);
-  Cross3D(v34, norm0, norm1);
-
-  a = norm1[0];
-  b = norm1[1];
-  c = norm1[2];
-  d = -(a * endpoint1[0] + b * endpoint1[1] + c * endpoint1[2]);
-  e = v12[0];
-  f = v12[1];
-  g = v12[2];
-  t = -(a * torg[0] + b * torg[1] + c * torg[2] + d) / (a * e + b * f + c * g);
-
-  // Create the new point.
-  newpoint = (point3d) points.alloc();
-  // Interpolate its coordinate and attributes.
-  for (i = 0; i < 3 + nextras; i++) {
-    newpoint[i] = torg[i] + t * v12[i];
-  }
-  setpointmark(newpoint, mark(*splitshseg));
-  if (verbose > 1) {
-    // For debug, need use the pointmark to keep point's index.
-    setpointmark(newpoint, points.items);
-  }
-  if (verbose > 1) {
-    printf("  Splitting edge (%.12g, %.12g, %.12g) (%.12g, %.12g, %.12g)\n",
-           torg[0], torg[1], torg[2], tdest[0], tdest[1], tdest[2]);
-    printf("    at (%.12g, %.12g, %.12g).\n", newpoint[0], newpoint[1],
-           newpoint[2]);
-  }
-  // Insert the intersection point.  This should always succeed.
-  success = insertsite(newpoint, splittet, (face*) NULL, splitshseg);
-  if (success != SUCCESSFUL) {
-    printf("Internal error in segmentintersection():");
-    printf("  Fail to split a segment.\n");
-    internalerror();
-  }
-  if (steinerleft > 0) {
-    steinerleft--;
-  }
-  // Find newpoint in splittet, set it as origin of splittet,
-  if (!findorg(splittet, newpoint)) {
-    splittet->ver = 0;
-    for (splittet->loc = 0; splittet->loc < 4; splittet->loc++) {
-      if (isaboveplane(splittet, newpoint)) break;
-    }
-    assert(splittet->loc < 4);
-    locval = preciselocate(newpoint, splittet);
-    assert(locval == ONVERTEX);
-  }
-  setpoint2tet(newpoint, encode(*splittet));
-
-  // Inserting the point may have caused edge flips.  We wish to rediscover
-  //   the edge connecting endpoint1 to the new intersection point.
-  collinear = finddirection(splittet, endpoint1);
-  rightpoint = dest(*splittet);
-  leftpoint = apex(*splittet);
-  oppopoint = oppo(*splittet);
-  if (leftpoint == endpoint1) {
-    enext2self(*splittet);
-    esymself(*splittet);
-  } else if (oppopoint == endpoint1) {
-    fnextself(*splittet);
-    enext2self(*splittet);
-    esymself(*splittet);
-  } else if (rightpoint != endpoint1) {
-    printf("Internal error in segmentintersection():\n");
-    printf("  Topological inconsistency after splitting a segment.\n");
-    internalerror();
-  }
-  // 'splittet' should have destination endpoint1.
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// scoutsegment()    Scout the first tetrahedron on the path from one        //
-//                   endpoint to another, and check for completion(reaching  //
-//                   the second endpoint), a collinear point, and the        //
-//                   intersection of two segments or the intersection of a   //
-//                   segment and a facet.                                    //
-//                                                                           //
-// Returns one if the entire segment is successfully  inserted,  and zero if //
-// the job must be finished by conformingedge() or constrainededge().        //
-//                                                                           //
-// If the first tetrahedron on the path has the second endpoint as its       //
-// destination, apex or opposite, a subsegment is inserted and the job is    //
-// done.                                                                     //
-//                                                                           //
-// If the first tetrahedron  on the path has a  destination or apex that     //
-// lies on the segment, a subsegment is inserted connecting the first        //
-// endpoint to the collinear point, and the search is continued from the     //
-// collinear point.                                                          //
-//                                                                           //
-// If the first tetrahedron on the path has a subsegment opposite its origin,//
-// then there is a segment that intersects the segment being inserted. Their //
-// intersection point is inserted, splitting the subsegment.                 //
-//                                                                           //
-// If the first tetrahedron on the path has a subface opposite its origin,   //
-// then there is a facet that intersects the segment being inserted. Their   //
-// intersection point is inserted, splitting the subface.                    //
-//                                                                           //
-// Otherwise, return zero.                                                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::scoutsegment(triface *searchtet, point3d endpoint2, int newmark)
-{
-  triface crosstet;
-  face crossface, crossedge;
-  point3d leftpoint, rightpoint, oppopoint;
-  point3d endpoint1;
-  enum finddirectionresult collinear;
-
-  endpoint1 = org(*searchtet);
-  if (verbose > 2) {
-    printf("    Scout segment from %d to %d.\n",
-           pointmark(endpoint1), pointmark(endpoint2));
-  }
-  collinear = finddirection(searchtet, endpoint2);
-  rightpoint = dest(*searchtet);
-  leftpoint = apex(*searchtet);
-  oppopoint = oppo(*searchtet);
-  if ((oppopoint == endpoint2) || (leftpoint == endpoint2) ||
-      (rightpoint == endpoint2)) {
-    if (oppopoint == endpoint2) {
-      fnextself(*searchtet);
-      enext2self(*searchtet);
-    } else if (leftpoint == endpoint2) {
-      enext2self(*searchtet);
-    }
-    // Insert a subsegment, if there isn't already one there.
-    insertsubsegment(searchtet, newmark);
-    return 1;
-  } else if (collinear == LEFTCOLLINEAR) {
-    // We've collided with a point between the segment's endpoints.
-    // Make the collinear point be the tetrahedron's origin.
-    enext2self(*searchtet);
-    insertsubsegment(searchtet, newmark);
-    // Insert the remainder of the segment.
-    return scoutsegment(searchtet, endpoint2, newmark);
-  } else if (collinear == RIGHTCOLLINEAR) {
-    // We've collided with a point between the segment's endpoints.
-    insertsubsegment(searchtet, newmark);
-    // Make the collinear point be the tetrahedron's origin.
-    enextself(*searchtet);
-    // Insert the remainder of the segment.
-    return scoutsegment(searchtet, endpoint2, newmark);
-  } else if (collinear == TOPCOLLINEAR) {
-    // We've collided with a point between the segment's endpoints.
-    // Make the collinear point be the tetrahedron's origin.
-    fnextself(*searchtet);
-    enext2self(*searchtet);
-    insertsubsegment(searchtet, newmark);
-    // Insert the remainder of the segment.
-    return scoutsegment(searchtet, endpoint2, newmark);
-  } else if (collinear == ACROSS) {
-    // Check for a crossing subface.
-    enextfnext(*searchtet, crosstet);
-    tspivot(crosstet, crossface);
-    if ((crossface.sh != dummysh) && !isnonsolid(crossface)) {
-      /*// Insert a point at the intersection.
-      segmentfacetintersection(&crosstet, &crossface, endpoint2);
-      *searchtet = crosstet;
-      insertsubsegment(searchtet, newmark);
-      // Insert the remainder of the segment.
-      return scoutsegment(searchtet, endpoint2, newmark); */
-      printf("Segment-Facet intersection has not implemented now.\n");
-      exit(1);
-    } else {
-      // Try to do flip23 on the acrossing face.
-      if (categorizeface(crosstet) == T23) {
-        if (verbose > 1) {
-          printf("  Do face-edge swap (T23).\n");
-        }
-        usefliplist = 1;
-        flip23(crosstet);
-        usefliplist = 0;
-        findorg(searchtet, endpoint1);
-        assert(org(*searchtet) == endpoint1);
-        return scoutsegment(searchtet, endpoint2, newmark);
-      }
-    }
-  } else {
-    assert(collinear == WITHIN);
-    // Check for a crossing segment.
-    enextfnext(*searchtet, crosstet);
-    tsspivot(&crosstet, &crossedge);
-    if (crossedge.sh != dummysh) {
-      // Insert a point at the intersection.
-      segmentintersection(&crosstet, &crossedge, endpoint2);
-      *searchtet = crosstet;
-      insertsubsegment(searchtet, newmark);
-      // Insert the remainder of the segment.
-      return scoutsegment(searchtet, endpoint2, newmark);
-    } else {
-      // Try to do flip22 or flip44 on the acrossing edge.
-      point3d fliporg, flipdest;
-      enum facecategory fc;
-
-      fliporg = org(crosstet);
-      flipdest = dest(crosstet);
-      fc = categorizeface(crosstet);
-      if ((fc == T22) || (fc == T44)) {
-        // Check the flipface does not changed by categorizeface().
-        if (((org(crosstet) == fliporg) && (dest(crosstet) == flipdest))
-            || ((org(crosstet) == flipdest) && (dest(crosstet) == fliporg))) {
-          if (verbose > 1) {
-            printf("  Do face-edge swap (%s).\n", fc == T22 ? "T22" : "T44");
-          }
-          usefliplist = 1;
-          if (fc == T22) {
-            flip22(crosstet);
-          } else {
-            flip44(crosstet);
-          }
-          usefliplist = 0;
-          findorg(searchtet, endpoint1);
-          assert(org(*searchtet) == endpoint1);
-          return scoutsegment(searchtet, endpoint2, newmark);
-        }
-      }
-    }
-  }
-  // Can't find such segment, job must be completed by insert points.
-  return 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// conformingedge()    Force a segment into a conforming Delaunay            //
-//                     triangulation by inserting a point at its midpoint,   //
-//                     and recursively forcing in the two half-segments if   //
-//                     necessary.                                            //
-//                                                                           //
-// Generates a sequence of edges connecting `endpoint1' to `endpoint2'.      //
-// `newmark' is the boundary marker of the segment, assigned to each new     //
-// splitting point and shell edge.                                           //
-//                                                                           //
-// Note that conformingedge() does not always maintain the conforming        //
-// Delaunay property.  Once inserted, segments are locked into place; points //
-// inserted later (to force other segments in) may render these fixed        //
-// segments non-Delaunay.  The conforming Delaunay property will be restored //
-// by enforcequality() by splitting encroached segments.                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::conformingedge(point3d endpoint1, point3d endpoint2, int newmark)
-{
-  triface searchtet1, searchtet2;
-  face brokenshseg, brokenshface;
-  point3d newpoint;
-  point3d midpoint1, midpoint2;
-  enum insertsiteresult success;
-  enum locateresult locval;
-  int result1, result2;
-  int i;
-
-  if (verbose > 2) {
-    printf("    Forcing segment into triangulation by recursive splitting:");
-    printf(" %d, %d\n", pointmark(endpoint1), pointmark(endpoint2));
-  }
-  // Create a new point to insert in the middle of the segment.
-  newpoint = (point3d) points.alloc();
-  // Interpolate coordinates and attributes.
-  for (i = 0; i < 3 + nextras; i++) {
-    newpoint[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
-  }
-  setpointmark(newpoint, newmark);
-  if (verbose > 1) {
-    // For debug, need use the pointmark to keep point's index.
-    setpointmark(newpoint, points.items);
-  }
-  // Find a boundary tetrahedron to search from.
-  searchtet1.tet = (tetrahedron *) NULL;
-  // Attempt to insert the new point.
-  success = insertsite(newpoint, &searchtet1, (face *) NULL, (face *) NULL);
-  if (success == DUPLICATE) {
-    if (verbose > 2) {
-      printf("    Segment intersects existing point (%.12g, %.12g, %.12g).\n",
-             newpoint[0], newpoint[1], newpoint[2]);
-    }
-    // Use the point that's already there.
-    points.dealloc(newpoint);
-    newpoint = org(searchtet1);
-  } else {
-    if (success == VIOLATINGEDGE) {
-      if (verbose > 2) {
-        printf("    Two segments intersect at (%.12g, %.12g, %.12g).\n",
-               newpoint[0], newpoint[1], newpoint[2]);
-      }
-      // By fluke, we've landed right on another segment.  Split it.
-      tsspivot(&searchtet1, &brokenshseg);
-      success = insertsite(newpoint, &searchtet1, (face*) NULL, &brokenshseg);
-      if (success != SUCCESSFUL) {
-        printf("Internal error in conformingedge():");
-        printf("  Failure to split a segment.\n");
-        internalerror();
-      }
-    } else if (success == VIOLATINGFACE) {
-      if (verbose > 2) {
-        printf("    Segments intersect a subface at (%.12g, %.12g, %.12g).\n",
-               newpoint[0], newpoint[1], newpoint[2]);
-      }
-      // By fluke, we've landed right on a subface.  Split it.
-      tspivot(searchtet1, brokenshface);
-      success = insertsite(newpoint, &searchtet1, &brokenshface, (face*) NULL);
-      if (success != SUCCESSFUL) {
-        printf("Internal error in conformingedge():");
-        printf("  Failure to split a subface.\n");
-        internalerror();
-      }
-    }
-    // The point has been inserted successfully.
-    if (steinerleft > 0) {
-      steinerleft--;
-    }
-    // Find newpoint in searchtet1, set it as origin of splittet,
-    if (!findorg(&searchtet1, newpoint)) {
-      searchtet1.ver = 0;
-      for (searchtet1.loc = 0; searchtet1.loc < 4; searchtet1.loc++) {
-        if (isaboveplane(&searchtet1, newpoint)) break;
-      }
-      assert(searchtet1.loc < 4);
-      locval = preciselocate(newpoint, &searchtet1);
-      assert(locval == ONVERTEX);
-    }
-    setpoint2tet(newpoint, encode(searchtet1));
-  }
-
-  searchtet2 = searchtet1;
-  result1 = scoutsegment(&searchtet1, endpoint1, newmark);
-  result2 = scoutsegment(&searchtet2, endpoint2, newmark);
-  if (!result1) {
-    // The origin of searchtet1 may have changed if a collision with an
-    //   intervening vertex on the segment occurred.
-    midpoint1 = org(searchtet1);
-    conformingedge(midpoint1, endpoint1, newmark);
-  }
-  if (!result2) {
-    // The origin of searchtet2 may have changed if a collision with an
-    //   intervening vertex on the segment occurred.
-    midpoint2 = org(searchtet2);
-    conformingedge(midpoint2, endpoint2, newmark);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertsegment()    Insert a PLC segment into a triangulation.             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::insertsegment(point3d endpoint1, point3d endpoint2, int newmark)
-{
-  triface searchtet1, searchtet2;
-  tetrahedron encodedtet;
-  point3d checkpoint;
-
-  if (verbose > 1) {
-    printf("  Connecting %d to %d.\n", pointmark(endpoint1),
-           pointmark(endpoint2));
-  }
-
-  // Find a tetrahedron whose origin is the segment's first endpoint.
-  checkpoint = (point3d) NULL;
-  encodedtet = point2tet(endpoint1);
-  if (encodedtet != (tetrahedron) NULL) {
-    decode(encodedtet, searchtet1);
-    if (findorg(&searchtet1, endpoint1)) {
-      checkpoint = org(searchtet1);
-    }
-  }
-  if (checkpoint != endpoint1) {
-    // Find a boundary tetrahedron to search from.
-    searchtet1.tet = dummytet;
-    searchtet1.loc = 0;
-    symself(searchtet1);
-    // Search for the segment's first endpoint by point location.
-    if (locate(endpoint1, &searchtet1) != ONVERTEX) {
-      printf("Internal error in insertsegment():  Unable to locate point\n");
-      printf("  (%.12g, %.12g, %.12g) in triangulation.\n",
-             endpoint1[0], endpoint1[1], endpoint1[2]);
-      internalerror();
-    }
-  }
-  // Remember this tetrahedron to improve subsequent point location.
-  recenttet = searchtet1;
-  // Scout the beginnings of a path from the first endpoint
-  //   toward the second.
-  if (scoutsegment(&searchtet1, endpoint2, newmark)) {
-    // The segment was easily inserted.
-    if (!fliplist->empty()) {
-      // Restore Delaunayness if necessary.
-      dofliplist();
-    }
-    return;
-  }
-  // The first endpoint may have changed if a collision with an intervening
-  //   vertex on the segment occurred.
-  endpoint1 = org(searchtet1);
-
-  // Find a tetrahedron whose origin is the segment's second endpoint.
-  checkpoint = (point3d) NULL;
-  encodedtet = point2tet(endpoint2);
-  if (encodedtet != (tetrahedron) NULL) {
-    decode(encodedtet, searchtet2);
-    if (findorg(&searchtet2, endpoint2)) {
-      checkpoint = org(searchtet2);
-    }
-  }
-  if (checkpoint != endpoint2) {
-    // Find a boundary tetrahedron to search from.
-    searchtet2.tet = dummytet;
-    searchtet2.loc = 0;
-    symself(searchtet2);
-    // Search for the segment's second endpoint by point location.
-    if (locate(endpoint2, &searchtet2) != ONVERTEX) {
-      printf("Internal error in insertsegment():  Unable to locate point\n");
-      printf("  (%.12g, %.12g, %.12g) in triangulation.\n",
-             endpoint2[0], endpoint2[1], endpoint2[2]);
-      internalerror();
-    }
-  }
-  // Remember this tetrahedron to improve subsequent point location.
-  recenttet = searchtet2;
-  // Scout the beginnings of a path from the second endpoint
-  //   toward the first.
-  if (scoutsegment(&searchtet2, endpoint1, newmark)) {
-    // The segment was easily inserted.
-    if (!fliplist->empty()) {
-      // Restore Delaunayness if necessary.
-      dofliplist();
-    }
-    return;
-  }
-  // The second endpoint may have changed if a collision with an intervening
-  //   vertex on the segment occurred.
-  endpoint2 = org(searchtet2);
-
-  // Insert vertices to force the segment into the triangulation.
-  conformingedge(endpoint1, endpoint2, newmark);
-  if (!fliplist->empty()) {
-    // Restore Delaunayness if necessary.
-    dofliplist();
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getsteinersinseg()    Find all steiner points in a given segment. Return  //
-//                       in a List.                                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::getsteinersinseg(point3d endpoint1, point3d endpoint2,
-                              list* steinerpoints)
-{
-  triface searchtet;
-  tetrahedron encodedtet;
-  point3d checkpoint;
-  point3d leftpoint, rightpoint, oppopoint;
-  enum finddirectionresult collinear;
-
-  if (verbose > 2) {
-    printf("    Get steiner points in segment from %d to %d.\n",
-           pointmark(endpoint1), pointmark(endpoint2));
-  }
-
-  // Find a tetrahedron whose origin is the endpoint1.
-  checkpoint = (point3d) NULL;
-  encodedtet = point2tet(endpoint1);
-  if (encodedtet != (tetrahedron) NULL) {
-    decode(encodedtet, searchtet);
-    if (findorg(&searchtet, endpoint1)) {
-      checkpoint = org(searchtet);
-    }
-  }
-  if (checkpoint != endpoint1) {
-    // Find a boundary tetrahedron to search from.
-    searchtet.tet = dummytet;
-    searchtet.loc = 0;
-    symself(searchtet);
-    // Search for the segment's first endpoint by point location.
-    if (locate(endpoint1, &searchtet) != ONVERTEX) {
-      printf("Internal error in insertsegment():  Unable to locate point\n");
-      printf("  (%.12g, %.12g, %.12g) in triangulation.\n",
-             endpoint1[0], endpoint1[1], endpoint1[2]);
-      internalerror();
-    }
-  }
-  // Remember this tetrahedron to improve subsequent point location.
-  recenttet = searchtet;
-
-  while (true) {
-    collinear = finddirection(&searchtet, endpoint2);
-    rightpoint = dest(searchtet);
-    leftpoint = apex(searchtet);
-    oppopoint = oppo(searchtet);
-    if ((oppopoint == endpoint2) || (leftpoint == endpoint2) ||
-        (rightpoint == endpoint2)) {
-      // We are reach the endpoint2, end of searching.
-      return;
-    } else if (collinear == LEFTCOLLINEAR) {
-      // We've collided with a point between the segment's endpoints.
-      steinerpoints->append(&leftpoint);
-      // Make the collinear point be the tetrahedron's origin.
-      enext2self(searchtet);
-    } else if (collinear == RIGHTCOLLINEAR) {
-      // We've collided with a point between the segment's endpoints.
-      steinerpoints->append(&rightpoint);
-      // Make the collinear point be the tetrahedron's origin.
-      enextself(searchtet);
-    } else if (collinear == TOPCOLLINEAR) {
-      // We've collided with a point between the segment's endpoints.
-      steinerpoints->append(&oppopoint);
-      // Make the collinear point be the tetrahedron's origin.
-      fnextself(searchtet);
-      enext2self(searchtet);
-    } else {  // collinear == ACROSS or collinear == WITHIN
-      printf("Internal error in getsteinersinseg(): Segment is missing.\n");
-      internalerror();
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getdiagonalapexindex()    Get the diagonal point index of the specified   //
-//                           triangle edge(that is, get the neighbour tri    //
-//                           at this edge, then get this edge's apex in it)  //
-//                           in the input triangulateio structure.           //
-//                                                                           //
-// It required that the input triangulateio structure must be created by     //
-// triangle with a switch -n, so triangle will generates a list of triangle  //
-// neighbors in the 'neighborlist' field of triangulateio structure.         //
-//                                                                           //
-// If the diagonal point exist, return the index in pointlist (>= 0), other- //
-// wise, return -1.                                                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::
-getdiagonalapexindex(triangulateio* out, int triindex, int edgeorient)
-{
-  int tribase, ntribase;
-  int ntriindex;
-  int iorg, idest;
-  int nidiag;
-
-  tribase = triindex * 3;
-  ntriindex = out->neighborlist[tribase + minus1mod3[edgeorient]];
-  if (ntriindex == -1) {
-    return -1;
-  }
-  ntribase = ntriindex * 3;
-
-  iorg = out->trianglelist[tribase + edgeorient];
-  idest = out->trianglelist[tribase + plus1mod3[edgeorient]];
-
-  nidiag = out->trianglelist[ntribase];
-  if ((nidiag != iorg) && (nidiag != idest)) {
-    return nidiag;
-  }
-  nidiag = out->trianglelist[ntribase + 1];
-  if ((nidiag != iorg) && (nidiag != idest)) {
-    return nidiag;
-  }
-  nidiag = out->trianglelist[ntribase + 2];
-  if ((nidiag != iorg) && (nidiag != idest)) {
-    return nidiag;
-  }
-  return -1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getneighbourtriedge()    Get the neighbour triangle's index and edge of   //
-//                          the specified triangle edge(that is, get the     //
-//                          neighbour tri at this edge, then get this edge's //
-//                          orient) from the input triangulateio structure.  //
-//                                                                           //
-// It required that the input triangulateio structure must be created by     //
-// triangle with a switch -n, so triangle will generates a list of triangle  //
-// neighbors in the 'neighborlist' field of triangulateio structure.         //
-//                                                                           //
-// If the neighbour tri exist and the edge orient is found, return 1, other- //
-// wise, return -1.                                                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::
-getneighbourtriedge(struct triangulateio* out, int triindex, int edgeorient,
-                    int* ntriindex, int* nedgeorient)
-{
-  int tribase, ntribase;
-  int iorg, idest;
-  int niorg, nidest;
-  int i;
-
-  tribase = triindex * 3;
-  *ntriindex = out->neighborlist[tribase + minus1mod3[edgeorient]];
-  if (*ntriindex == -1) {
-    return -1;
-  }
-  ntribase = *ntriindex * 3;
-
-  iorg = out->trianglelist[tribase + edgeorient];
-  idest = out->trianglelist[tribase + plus1mod3[edgeorient]];
-
-  *nedgeorient = -1;
-  for (i = 0; i < 3; i++) {
-    niorg = out->trianglelist[ntribase + i];
-    nidest = out->trianglelist[ntribase + plus1mod3[i]];
-    if ((niorg == idest) && (nidest == iorg)) {
-      *nedgeorient = i;
-      return 1;
-    }
-  }
-
-  return -1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// swapdiagonal()   To do an edge flip in the input triangulateio structure. //
-//                                                                           //
-// It required that the input triangulateio structure must be created by     //
-// triangle with a switch -n, so triangle will generates a list of triangle  //
-// neighbors in the 'neighborlist' field of triangulateio structure.         //
-//                                                                           //
-//              nleftcasing                                                  //
-//                                                                           //
-//          dest  norg__ napex             dest ______   napex               //
-//              |\ \     |                     |     / /|                    //
-//              | \ \<----- nswapedge          |    / / |                    //
-// rightcasing  |  \ \   |                     |   / /  |                    //
-//              |   \ \  | nrightcasing        |  / /   |                    //
-//    swapedge ----->\ \ |                     | / /    |                    //
-//              |_____\ \|                     |/ /_____|                    //
-//          apex    org  ndest             apex          ndest               //
-//                                                                           //
-//             leftcasing                                                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::
-swapdiagonal(struct triangulateio* out, int triindex, int fixedge, int swapedge)
-{
-  int tribase, ntribase;
-  int ntriindex;
-  int nswapedge;
-  int org, dest, apex;
-  int norg, ndest, napex;
-  int rightcasing, leftcasing;
-  int nrightcasing, nleftcasing;
-
-  tribase = triindex * 3;
-  ntriindex = out->neighborlist[tribase + minus1mod3[swapedge]];
-  if (ntriindex == -1) {
-    return 0; // ntriindex does not exist.
-  }
-  ntribase = ntriindex * 3;
-
-  org = out->trianglelist[tribase + swapedge];
-  dest = out->trianglelist[tribase + plus1mod3[swapedge]];
-  apex = out->trianglelist[tribase + minus1mod3[swapedge]];
-  // Find edge(sorg, sdest)'s orient in ntriindex.
-  napex = -1;
-  for (nswapedge = 0; nswapedge < 3; nswapedge++) {
-    norg = out->trianglelist[ntribase + nswapedge];
-    ndest = out->trianglelist[ntribase + plus1mod3[nswapedge]];
-    if ((norg == dest) && (ndest == org)) {
-      napex = out->trianglelist[ntribase + minus1mod3[nswapedge]];
-      break;
-    }
-  }
-  if (napex == -1) {
-    return 0; // ntriindex does not contain the swap edge.
-  }
-  rightcasing = out->neighborlist[tribase + swapedge];
-  leftcasing = out->neighborlist[tribase + plus1mod3[swapedge]];
-  nrightcasing = out->neighborlist[ntribase + nswapedge];
-  nleftcasing = out->neighborlist[ntribase + plus1mod3[nswapedge]];
-
-  if (fixedge == plus1mod3[swapedge]) {
-    // Right edge (dest, apex) of swap edge is fixed (not change).
-    //   org <-- napex
-    out->trianglelist[tribase + swapedge] = napex;
-    //   leftcasing <-- ntriindex
-    out->neighborlist[tribase + plus1mod3[swapedge]] = ntriindex;
-    //   ntriindex <-- nleftcasing
-    out->neighborlist[tribase + minus1mod3[swapedge]] = nleftcasing;
-    //   norg <-- apex
-    out->trianglelist[ntribase + nswapedge] = apex;
-    //   nleftcasing <-- triindex
-    out->neighborlist[ntribase + plus1mod3[nswapedge]] = triindex;
-    //   triindex <-- leftcasing
-    out->neighborlist[ntribase + minus1mod3[nswapedge]] = leftcasing;
-  } else if (fixedge == minus1mod3[swapedge]) {
-    // Left edge (apex, org) of swap edge is fixed (not change).
-    //   dest <--> napex
-    out->trianglelist[tribase + plus1mod3[swapedge]] = napex;
-    //   rightcasing <-- ntriindex
-    out->neighborlist[tribase + swapedge] = ntriindex;
-    //   ntriindex <-- nrightcasing
-    out->neighborlist[tribase + minus1mod3[swapedge]] = nrightcasing;
-    //   ndest <--> apex
-    out->trianglelist[ntribase + plus1mod3[nswapedge]] = apex;
-    //   nrightcasing <-- triindex
-    out->neighborlist[ntribase + nswapedge] = triindex;
-    //   triindex <-- rightcasing
-    out->neighborlist[ntribase + minus1mod3[nswapedge]] = rightcasing;
-  } else {
-    return 0;  // Wrong fixedge number.
-  }
-  return 1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// matchface()     Matching the subface of a tetrahedron that has the same   //
-//                 vertexs as inputs. If such face be found, a subface is    //
-//                 inserted and the job is done.                             //
-//                                                                           //
-// If searchtet->tet == dummytet, the subface is defined by 'torg', 'tdest'  //
-// and 'tapex'. If searchtet->tet != dummytet, the subface is defined by     //
-// 'searchtet->org()', 'searchtet->dest()' and 'tapex'.                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum mesh3d::matchfaceresult
-mesh3d::matchface(point3d torg, point3d tdest, point3d tapex,
-                  triface* searchtet, int newmark)
-{
-  triface spintet;
-  tetrahedron encodedtet;
-  point3d checkpoint;
-  point3d leftpoint, rightpoint, oppopoint;
-  enum finddirectionresult collinear;
-  int hitbdry;
-
-  if (searchtet->tet == dummytet) {
-    // Find a tetrahedron whose origin is the face's org.
-    checkpoint = (point3d) NULL;
-    encodedtet = point2tet(torg);
-    if (encodedtet != (tetrahedron) NULL) {
-      decode(encodedtet, *searchtet);
-      if (findorg(searchtet, torg)) {
-        checkpoint = org(*searchtet);
-      }
-    }
-    if (checkpoint != torg) {
-      // Find a boundary tetrahedron to search from.
-      searchtet->tet = dummytet;
-      searchtet->loc = 0;
-      symself(*searchtet);
-      // Search for the segment's first endpoint by point location.
-      if (locate(torg, searchtet) != ONVERTEX) {
-        printf("Internal error in insertsegment():  Unable to locate point\n");
-        printf("  (%.12g, %.12g, %.12g) in triangulation.\n",
-               torg[0], tdest[1], tapex[2]);
-        internalerror();
-      }
-    }
-    // Remember this tetrahedron to improve subsequent point location.
-    recenttet = *searchtet;
-    collinear = finddirection(searchtet, tdest);
-    rightpoint = dest(*searchtet);
-    leftpoint = apex(*searchtet);
-    oppopoint = oppo(*searchtet);
-    if ((oppopoint == tdest) || (leftpoint == tdest) ||
-        (rightpoint == tdest)) {
-      if (oppopoint == tdest) {
-        fnextself(*searchtet);
-        enext2self(*searchtet);
-        esymself(*searchtet);
-      } else if (leftpoint == tdest) {
-        enext2self(*searchtet);
-        esymself(*searchtet);
-      }
-    } else {
-      return EDGEMISSING;
-    }
-    // Here the origin of 'searchtet' must be is torg.
-    assert(org(*searchtet) == torg);
-  }
-
-  if (apex(*searchtet) != tapex) {
-    // Spin around edge torg and tdest, to find a face that contain tapex.
-    spintet = *searchtet;
-    hitbdry = 0;
-    while (true) {
-      if (fnextself(spintet)) {
-        if (apex(spintet) == apex(*searchtet)) {
-          break; // Rewind, can leave now.
-        }
-        if (apex(spintet) == tapex) {
-          // This is the face we looking for.
-          *searchtet = spintet;
-          break;
-        }
-      } else {
-        hitbdry ++;
-        if(hitbdry >= 2) {
-          break;
-        } else {
-          esym(*searchtet, spintet);
-        }
-      }
-    }
-  }
-  if (apex(*searchtet) == tapex) {
-    // Insert a subface, if there isn't already one there.
-    insertsubface(searchtet, newmark, 1);
-    return FACEMATCHING;
-  } else {
-    return APEXMISSING;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertfieldpoint()    Generate and insert a field(steiner) point into     //
-//                       current mesh to form a triangulation for the input  //
-//                       triangular faces.                                   //
-//                                                                           //
-// This routine is called when gift-wrapping failed. The recover facet job   //
-// will be done(not neccessary) by insert field point to mesh.               //
-//                                                                           //
-// An important thing is the new field point must lies 'below' all the faces //
-// (giftfaces) (that is visivle from all faces) and lies 'in' the hole.      //
-//                                                                           //
-// The 'crosstetlist' is a list which keeps all crossing tets, that can help //
-// us to determine if the new field point is located in the hole.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::insertfieldpoint(int numberofgiftfaces, triface* giftfaces,
-                             int numberofgiftpoints, point3d* giftpoints,
-                             list* crosstetlist)
-{
-  link *unfinfacelist;
-  triface newtet, otherface, *checktetptr;
-  face checksh;
-  point3d newpoint;
-  enum locateresult loc;
-  int findex;
-  int i, j;
-
-  if (verbose > 1) {
-    printf("  Generate field point to complete recover face.\n");
-  }
-  // Create the new point.
-  newpoint = (point3d) points.alloc();
-  // It's a inner point.
-  setpointmark(newpoint, 0);
-  if (verbose > 1) {
-    // For debug, need use the pointmark to keep point's index.
-    setpointmark(newpoint, points.items);
-  }
-  newpoint[0] = newpoint[1] = newpoint[2] = 0.0;
-  for (i = 0; i < numberofgiftpoints; i++) {
-    newpoint[0] += giftpoints[i][0];
-    newpoint[1] += giftpoints[i][1];
-    newpoint[2] += giftpoints[i][2];
-    // Interpolate its coordinate and attributes.
-    for (j = 3; j < 3 + nextras; j++) {
-      newpoint[j] += giftpoints[i][j];
-    }
-  }
-  newpoint[0] /= numberofgiftpoints;
-  newpoint[1] /= numberofgiftpoints;
-  newpoint[2] /= numberofgiftpoints;
-  // Interpolate its coordinate and attributes.
-  for (j = 3; j < 3 + nextras; j++) {
-    newpoint[j] /= numberofgiftpoints;
-  }
-
-  // Check if newpoint lies in the hole.
-  for (i = 0; i < crosstetlist->len(); i++) {
-    checktetptr = (triface*) (*crosstetlist)[i];
-    loc = isintet(org(*checktetptr), dest(*checktetptr), apex(*checktetptr),
-                  oppo(*checktetptr), newpoint);
-    if (loc != OUTSIDE) {
-      break;
-    }
-  }
-  if (i >= crosstetlist->len()) {
-    // This new point is outside the hole.
-    if (!quiet) {
-      printf("Internal error in insertfieldpoint(): \n");
-      printf("  The barycenter of each corner points locates outside the\n");
-      printf("    polyhedra of this corner point and their bounding faces.\n");
-      internalerror();
-    }
-    pointdealloc(newpoint);
-    return 0;
-  }
-  // Check if newpoint lies below(is visible from) the all giftface.
-  for (i = 0; i < numberofgiftfaces; i++) {
-    if (!isbelowplane(&(giftfaces[i]), newpoint)) {
-      break;
-    }
-  }
-  if (i < numberofgiftfaces) {
-    if (!quiet) {
-      printf("Internal error in insertfieldpoint(): \n");
-      printf("  The barycenter of each corner points does not visible from\n");
-      printf("    all bounding faces of the polyhedra.\n");
-      internalerror();
-    }
-    pointdealloc(newpoint);
-    return 0;
-  }
-
-  if (verbose > 1) {
-    printf("  Create new point (%.12g, %.12g, %.12g) %d.\n",
-           newpoint[0], newpoint[1], newpoint[2], pointmark(newpoint));
-  }
-
-  // Setup a list for keeping all unfinished faces.
-  unfinfacelist = new link(sizeof(triface));
-  // Set user-defined compare function for comparing faces.
-  unfinfacelist->setcomp((compfunc) &issameface);
-
-  // Create a initial tet use giftfaces[0] and newpoint.
-  maketetrahedron(&newtet);
-  setorg(newtet, dest(giftfaces[0]));
-  setdest(newtet, org(giftfaces[0]));
-  setapex(newtet, apex(giftfaces[0]));
-  setoppo(newtet, newpoint);
-  // Make the connection between giftfaces[i] and newtet.
-  bond(newtet, giftfaces[0]);
-  tspivot(giftfaces[0], checksh);
-  if (checksh.sh != dummysh) {
-    sesymself(checksh);
-    tsbond(newtet, checksh);
-  }
-  // Add the new tetrahedron's three faces to unfinished faces list.
-  //   Keep 'newpoint' be apex of each faces.
-  otherface = newtet;
-  fnextself(otherface);
-  unfinfacelist->add(&otherface);
-  otherface = newtet;
-  enextfnextself(otherface);
-  unfinfacelist->add(&otherface);
-  otherface = newtet;
-  enext2fnextself(otherface);
-  unfinfacelist->add(&otherface);
-  if (verbose > 2) {
-    printf("    Creating newtet ");
-    dump(&newtet);
-  }
-  for (i = 1; i < numberofgiftfaces; i++) {
-    maketetrahedron(&newtet);
-    setorg(newtet, dest(giftfaces[i]));
-    setdest(newtet, org(giftfaces[i]));
-    setapex(newtet, apex(giftfaces[i]));
-    setoppo(newtet, newpoint);
-    // Make the connection between giftfaces[i] and newtet.
-    bond(newtet, giftfaces[i]);
-    tspivot(giftfaces[i], checksh);
-    if (checksh.sh != dummysh) {
-      sesymself(checksh);
-      tsbond(newtet, checksh);
-    }
-    // Check and bond three inner faces of newtet.
-    otherface = newtet;
-    fnextself(otherface);
-    findex = unfinfacelist->hasitem(&otherface);
-    if ((findex > 0) && (findex <= unfinfacelist->len())) {
-      checktetptr = (triface *) unfinfacelist->getnitem(findex);
-      bond(otherface, *checktetptr);
-      unfinfacelist->del(findex);  // Remove it.
-    } else {
-      unfinfacelist->add(&otherface);
-    }
-    otherface = newtet;
-    enextfnextself(otherface);
-    findex = unfinfacelist->hasitem(&otherface);
-    if ((findex > 0) && (findex <= unfinfacelist->len())) {
-      checktetptr = (triface *) unfinfacelist->getnitem(findex);
-      bond(otherface, *checktetptr);
-      unfinfacelist->del(findex);  // Remove it.
-    } else {
-      unfinfacelist->add(&otherface);
-    }
-    otherface = newtet;
-    enext2fnextself(otherface);
-    findex = unfinfacelist->hasitem(&otherface);
-    if ((findex > 0) && (findex <= unfinfacelist->len())) {
-      checktetptr = (triface *) unfinfacelist->getnitem(findex);
-      bond(otherface, *checktetptr);
-      unfinfacelist->del(findex);  // Remove it.
-    } else {
-      unfinfacelist->add(&otherface);
-    }
-    if (verbose > 2) {
-      printf("    Creating newtet ");
-      dump(&newtet);
-    }
-  }
-  assert(unfinfacelist->len() == 0);
-
-  delete unfinfacelist;
-  return 1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// recoverface()    Recover a subface that is missing from the volume mesh.  //
-//                                                                           //
-// This is done by local re-triangulate the missing faces area. Use gift-    //
-// wrapping algorithm do local triangulation.                                //
-//                                                                           //
-// This function follow these steps:                                         //
-//                                                                           //
-// (1) Identify all missing faces from 2D surface mesh, and all vertexs of   //
-//     these missing faces. The missing face will be found one by one start  //
-//     from the input triedge(triindex and edgeorient, this edge must exist  //
-//     in current tetrahedralization). Check other 2 edges are existed. If   //
-//     find oneof edges is missing, this edge's neighbour face is a missing  //
-//     face, take the neighbour triedge and keep it. Then loop untill all    //
-//     missing faces be found. We use a list(missingfacelist) to keep all    //
-//     missingface's index in 2D mesh(out), use a list(equatorpointlist) to  //
-//     keep all the vertexs of missing faces.                                //
-//                                                                           //
-// (2) Identify all the cross edges. These edges penerate all the missing    //
-//     faces and cause they cannot present in current tetrahedralization.    //
-//     The cross edges will be found one by one. A loop is used untill all   //
-//     cross edges are found. We use a list(crossedgelist) to keep all the   //
-//     cross edges.                                                          //
-//                                                                           //
-// (3) Identify all the cross tetrahedra and classify north and sourth       //
-//     points of endpoints of cross edges. We can identify the cross tets    //
-//     from cross edges. Each cross edge has a set of tetrahedra surrounding //
-//     it in the mesh. The identify all cross tets procedure proceeds by     //
-//     interrogating the tetrahedra around each cross edge. At the same time,//
-//     we can identify the endpoint of a cross edge's location (north or     //
-//     sourth). We use a list(crosstetlist) to keep all cross tetrahedra,    //
-//     two list(northpointlist and sourthpointlist) to keep the endpoints of //
-//     cross edges respectly.                                                //
-//                                                                           //
-// (4) Identify and classify all the casing tets(tet which adjoining the     //
-//     cross tets but not a cross tet). Casing tets will be used to generate //
-//     giftfaces. Pay special attention to protect subsegments for all cross //
-//     tets. Because they will be deleted before do gift-wrapping. There has //
-//     a special codes to protect subsegments from cross tets to casing tets //
-//     and dellocate inner nonsolid subfaces (Here we can't use preservesub- //
-//     segment() routine directly). If a casing tet doesnot exist, this will //
-//     happened when a cross tet lies on boundary.  We create a fake tet for //
-//     holding the casing tet's face temporarily. After gift-wrapping, do a  //
-//     remove fake tets job. At last,  We can delete all crosstets. So the   //
-//     memory can be re-used for later re-generation. We use two list(north- //
-//     cassinglist and sourthcassinglist) to keep all the casing tets.       //
-//                                                                           //
-// (5) Create all the equatorcasing tets. At first, there not exist equator- //
-//     casing tet. So like above, temporarily create a fake tetrahedron(oppo //
-//     = null) for holding this equator face. After re-triangulation, they   //
-//     will be removed. First, all casing tets are faceing toward 'tsourth', //
-//     because we triangulating the 'tnorth' side first. We use a list(equa- //
-//     tcasinglist) to keep all equator casing tets.                         //
-//                                                                           //
-// (6) Do local re-meshing at both north and sourth side of this facet. The  //
-//     well-known Gift-wrapping algorithm is used at here.                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::recoverface(list* pointlist, triangulateio* out, int triindex,
-                        int edgeorient)
-{
-  list *missingfacelist;
-  list *crossedgelist, *crosstetlist;
-  list *equatorpointlist, *northpointlist, *sourthpointlist;
-  list *equatorcasinglist, *northcasinglist, *sourthcasinglist;
-  list *backtracelist;
-  triface *giftfaces;
-  triface crossedge, crosstet;
-  triface starttet, spintet;
-  triface checkface, *checkfaceptr;
-  face checksh, checkshseg;
-  point3d torg, tdest, tapex;
-  point3d tnorth, tsourth, tother;
-  point3d *giftpoints;
-  enum matchfaceresult match;
-  int numberofgiftfaces, numberofgiftpoints;
-  int *iptr, iorg, idest, iapex;
-  int hitbdry, orient1, orient2;
-  int edgecount, successbonded;
-  int i, j, index, errorflag;
-
-  if (verbose > 1) {
-    printf("  Recover missing subfaces by local re-triangulation.\n");
-  }
-
-  // Step (1):
-  if (verbose > 2) {
-    printf("    Identify all missing subfaces.\n");
-  }
-  equatorpointlist = new list("point");
-  missingfacelist = new list(sizeof(int) * 2);
-
-  iptr = (int*) missingfacelist->alloc();
-  iptr[0] = triindex;
-  iptr[1] = edgeorient;
-  for (i = 0; i < missingfacelist->len(); i++) {
-    iptr = (int*) (*missingfacelist)[i];
-    triindex = iptr[0];
-    edgeorient = iptr[1];
-    index = triindex * 3;
-    iorg = out->trianglelist[index + edgeorient];
-    idest = out->trianglelist[index + plus1mod3[edgeorient]];
-    iapex = out->trianglelist[index + minus1mod3[edgeorient]];
-    torg = *(point3d*)(*pointlist)[iorg];
-    tdest = *(point3d*)(*pointlist)[idest];
-    tapex = *(point3d*)(*pointlist)[iapex];
-    if (verbose > 2) {
-      printf("    Subface (%d, %d, %d) is missing.\n",
-             pointmark(torg), pointmark(tdest), pointmark(tapex));
-    }
-    if (equatorpointlist->hasitem(&torg) == -1) {
-      equatorpointlist->append(&torg);
-    }
-    if (equatorpointlist->hasitem(&tdest) == -1) {
-      equatorpointlist->append(&tdest);
-    }
-    if (equatorpointlist->hasitem(&tapex) == -1) {
-      equatorpointlist->append(&tapex);
-    }
-    // Skip the current edge; Check other edges are existing.
-    starttet.tet = dummytet;
-    match = matchface(tdest, tapex, torg, &starttet, 0);
-    assert(match != FACEMATCHING);
-    if (match == EDGEMISSING) {
-      // There must exist another missing face.
-      iptr = (int*) missingfacelist->alloc();
-      // Get neighbour triangle's index and edgeorient.
-      getneighbourtriedge(out, triindex, plus1mod3[edgeorient],
-                          &iptr[0], &iptr[1]);
-      assert((iptr[0] != -1) && (iptr[1] != -1));
-    }
-    starttet.tet = dummytet;
-    match = matchface(tapex, torg, tdest, &starttet, 0);
-    assert(match != FACEMATCHING);
-    if (match == EDGEMISSING) {
-      // There must exist another missing face.
-      iptr = (int*) missingfacelist->alloc();
-      // Get neighbour triangle's index and edgeorient.
-      getneighbourtriedge(out, triindex, minus1mod3[edgeorient],
-                          &iptr[0], &iptr[1]);
-      assert((iptr[0] != -1) && (iptr[1] != -1));
-    }
-  }
-
-  // Step (2):
-  if (verbose > 2) {
-    printf("    Identify all the cross edges.\n");
-  }
-  crossedgelist = new list(sizeof(triface));
-  crossedgelist->setcomp((compfunc) &issameedge);
-
-  // Find one cross edge which cause this subface missing. Here we can
-  //   search from starttet. (starttet hold one of existing edges of the
-  //   last found missing face: torg, tdest, tapex.)
-
-  // First find one of points in 'torg', 'tdest' and 'tapex', which does
-  //   not belong to 'starttet'.
-  if (isfacehaspoint(&starttet, torg)) {
-    if (isfacehaspoint(&starttet, tdest)) {
-      tnorth = tapex;
-    } else {
-      tnorth = tdest;
-    }
-  } else {
-    tnorth = torg;
-  }
-  // Find which (fnext) direction we should go.
-  if (!isaboveplane(&starttet, tnorth)) {
-    esymself(starttet);
-  }
-  spintet = starttet;
-  hitbdry = 0;
-  orient1 = iorient3d(torg, tdest, tapex, apex(spintet));
-  errorflag = 0;
-  while (true) {
-    if (fnextself(spintet)) {
-      if (apex(spintet) == apex(starttet)) {
-        errorflag = 1;
-        break;
-      }
-      orient2 = iorient3d(torg, tdest, tapex, apex(spintet));
-      if (orient1 == 0) {
-        if (orient2 != 0) orient1 = orient2;
-      } else {
-        if ((orient2 != 0) && (orient1 != orient2)) {
-          crossedge = spintet;
-          adjustedgering(crossedge, CCW);
-          enextfnextself(crossedge);
-          enextself(crossedge);
-          break;
-        }
-      }
-    } else {
-      hitbdry ++;
-      if (hitbdry >= 2) {
-        errorflag = 1;
-        break;
-      } else {
-        esym(starttet, spintet);
-      }
-    }
-  }
-  if (errorflag) {
-    // No cross edge be found. It may cause by co-circular points of this
-    //   facet(The Delaunay triangulation is not unique).
-    if (verbose > 1) {
-      printf("  No cross edge be found, return anyway.\n");
-    }
-    delete equatorpointlist;
-    delete missingfacelist;
-    delete crossedgelist;
-    return 0;
-  }
-  // Get all other cross edges.
-  if (verbose > 2) {
-    printf("    Queueing cross edge (%d, %d).\n",
-           pointmark(org(crossedge)), pointmark(dest(crossedge)));
-  }
-  crossedgelist->append(&crossedge);
-  // Walk around this edge, identifying all other incident cross edges.
-  //   Note: Here we should not hit boundry.
-  for (i = 0; i < crossedgelist->len(); i++) {
-    spintet = starttet = *(triface*)(*crossedgelist)[i];
-    while (fnextself(spintet)) {
-      if (apex(spintet) == apex(starttet)) {
-        break; // Rewind, can leave now.
-      }
-      // Grab other vertex of this face.
-      tother = apex(spintet);
-      // If vertex is not one of equators(and should not coplanar with
-      //   them), there's another bad edge here. Identify it and store it.
-      if (equatorpointlist->hasitem(&tother) == -1) {
-        // Find which edge is across the plane in spintet.
-        orient1 = iorient3d(torg, tdest, tapex, org(spintet));
-        orient2 = iorient3d(torg, tdest, tapex, tother);
-        crossedge = spintet;
-        if (orient1 != orient2) {
-          // edge tother and 'org' is the cross edge.
-          enext2self(crossedge);
-          esymself(crossedge);
-        } else {
-          // egde 'dest' and tother is the cross edge.
-          enextself(crossedge);
-          esymself(crossedge);
-        }
-        if (crossedgelist->hasitem(&crossedge) == -1) {
-          if (verbose > 2) {
-            printf("    Queueing cross edge (%d, %d).\n",
-                   pointmark(org(crossedge)), pointmark(dest(crossedge)));
-          }
-          crossedgelist->append(&crossedge);
-        }
-      }
-    }
-  }
-
-  // Step (3):
-  if (verbose > 2) {
-    printf("    Classify all the north and sourth points and\n");
-    printf("      identify all the cross(to be dead) tetrahedra.\n");
-  }
-  crosstetlist = new list(sizeof(triface));
-  crosstetlist->setcomp((compfunc) &compare2tets);
-  northpointlist = new list("point");
-  sourthpointlist = new list("point");
-
-  for (i = 0; i < crossedgelist->len(); i++) {
-    spintet = starttet = *(triface*)(*crossedgelist)[i];
-    orient1 = iorient3d(torg, tdest, tapex, org(spintet));
-    assert(orient1 != 0);
-    if (orient1 < 0) {
-      tnorth = org(spintet);
-      tsourth = dest(spintet);
-    } else { // orient1 > 0
-      tnorth = dest(spintet);
-      tsourth = org(spintet);
-    }
-    if (northpointlist->hasitem(&tnorth) == -1) {
-      if (verbose > 2) {
-        printf("    Queueing north point %d.\n", pointmark(tnorth));
-      }
-      northpointlist->append(&tnorth);
-    }
-    if (sourthpointlist->hasitem(&tsourth) == -1) {
-      if (verbose > 2) {
-        printf("    Queueing sourth point %d.\n", pointmark(tsourth));
-      }
-      sourthpointlist->append(&tsourth);
-    }
-    if (crosstetlist->hasitem(&spintet) == -1) {
-      if (verbose > 2) {
-        printf("    Queueing cross tet (%d, %d, %d, %d).\n",
-               pointmark(org(spintet)), pointmark(dest(spintet)),
-               pointmark(apex(spintet)), pointmark(oppo(spintet)));
-      }
-      crosstetlist->append(&spintet);
-    }
-    while (fnextself(spintet)) {
-      if (apex(spintet) == apex(starttet)) {
-        break; // Rewind, can leave now.
-      }
-      if (crosstetlist->hasitem(&spintet) == -1) {
-        if (verbose > 2) {
-          printf("    Queueing cross tet (%d, %d, %d, %d).\n",
-                 pointmark(org(spintet)), pointmark(dest(spintet)),
-                 pointmark(apex(spintet)), pointmark(oppo(spintet)));
-        }
-        crosstetlist->append(&spintet);
-      }
-    }
-  }
-
-  // Step (4):
-  if (verbose > 2) {
-    printf("    Identifying and classifying north and sourth casing faces.\n");
-  }
-  northcasinglist = new list(sizeof(triface));
-  sourthcasinglist = new list(sizeof(triface));
-
-  for (i = 0; i < crosstetlist->len(); i++) {
-    crosstet = *(triface*) (*crosstetlist)[i];
-    if (verbose > 2) {
-      printf("    Get cross tet (%d, %d, %d, %d).\n",
-             pointmark(org(crosstet)), pointmark(dest(crosstet)),
-             pointmark(apex(crosstet)), pointmark(oppo(crosstet)));
-    }
-    // Check each face of this crosstet to see if there exist casing face.
-    //   If a face's neighbour tet not in crosstetlist, then it's a casing
-    //   face. At the same time, find the inner subface if exist and delete
-    //   it, don't forget to protect subsegment before delete subface.
-    for (j = 0; j < 4; j++) {
-      crosstet.loc = j;
-      sym(crosstet, checkface);
-      tspivot(crosstet, checksh);
-      // Here checkface maybe hold 'dummytet'.
-      if (crosstetlist->hasitem(&checkface) == -1) {
-        // It's a casing face of the cavity.
-        adjustedgering(crosstet, CCW);
-        torg = org(crosstet);
-        tdest = dest(crosstet);
-        tapex = apex(crosstet);
-        if (checkface.tet == dummytet) {
-          // This side of crosstet is a boundary face, we need it.
-          //   Temporarily create a fake tetrahedron(oppo = null) for
-          //   holding the face. After re-generation, it will be removed.
-          maketetrahedron(&checkface);
-          checkface.loc = 0; // For sure.
-          setorg(checkface, tdest);
-          setdest(checkface, torg);
-          setapex(checkface, tapex);
-          // setoppo(checkface, NULL);
-          if (verbose > 2) {
-            printf("    Creating a fake tet for holding face(%d, %d, %d).\n",
-                   pointmark(tdest), pointmark(torg), pointmark(tapex));
-          }
-          // Temporarily bond them for later protect segments.
-          bond(checkface, crosstet);
-          if (checksh.sh != dummysh) {
-            sesymself(checksh);
-            tsbond(checkface, checksh);
-          }
-        }
-        adjustedgering(checkface, CCW);
-        if ((northpointlist->hasitem(&torg) >= 0) ||
-            (northpointlist->hasitem(&tdest) >= 0) ||
-            (northpointlist->hasitem(&tapex) >= 0)) {
-          if (verbose > 2) {
-            printf("    Queuing northcasing face (%d, %d, %d).\n",
-                   pointmark(org(checkface)), pointmark(dest(checkface)),
-                   pointmark(apex(checkface)));
-          }
-          northcasinglist->append(&checkface);
-        } else {
-          if (verbose > 2) {
-            printf("    Queuing sourthcasing face (%d, %d, %d).\n",
-                   pointmark(org(checkface)), pointmark(dest(checkface)),
-                   pointmark(apex(checkface)));
-          }
-          sourthcasinglist->append(&checkface);
-        }
-      } else {
-        // Its a inner face. Check if there exist(to be dead) subface.
-        if (checksh.sh != dummysh) {
-          assert(isnonsolid(checksh));
-          // Protect subsegment if there need.
-          findversion(&crosstet, &checksh, 0); // For same enext() direction.
-          edgecount = 0;
-          while (edgecount < 3) {
-            sspivot(checksh, checkshseg);
-            if (checkshseg.sh != dummysh) {
-              face tmpchecksh;
-              spivot(checkshseg, tmpchecksh);
-              if (tmpchecksh.sh == checksh.sh) {
-                // We must protect this subsegment, otherwise the pointer
-                //   in checkshseg will be invalid after deallocate checksh.
-                spintet = crosstet;
-                hitbdry = 0;
-                successbonded = 0;
-                while (true) {
-                  if (fnextself(spintet)) {
-                    if (apex(spintet) == apex(crosstet)) {
-                      break;
-                    }
-                    tspivot(spintet, tmpchecksh);
-                    if (tmpchecksh.sh != dummysh) {
-                      findversion(&tmpchecksh, &spintet);
-                      ssbond(tmpchecksh, checkshseg);
-                      successbonded = 1;
-                      break;
-                    }
-                  } else {
-                    hitbdry ++;
-                    if (hitbdry >= 2) {
-                      break;
-                    } else {
-                      esym(crosstet, spintet);
-                    }
-                  }
-                }
-                if (!successbonded) {
-                  // Can't find a exist subface to hold this subsegment.
-                  //   We must insert a new (nonsolid) subface which must
-                  //   be inserted at a face which its tet is not in
-                  //   crosstetlist.
-                  // Note:
-                  //   (1) If we find such face, still need check if it's
-                  //   a face of fake tet(oppo() = NULL), if so, we need
-                  //   insert the new subface at its real face side, so
-                  //   during the gift-wrapping stage, it will be bonded
-                  //   automatically and we can safely remove the fake tet.
-                  //   (2) If we can't find such face,
-                  spintet = crosstet;
-                  hitbdry = 0;
-                  while (true) {
-                    if (fnextself(spintet)) {
-                      if (apex(spintet) == apex(crosstet)) {
-                        break;
-                      }
-                      if (crosstetlist->hasitem(&spintet) == -1) {
-                        if (spintet.tet[7] == NULL) {
-                          // It's a fake tet. the subface should insert at
-                          //   its real face(that is, loc = 0).
-                          spintet.loc = 0;
-                          if (verbose > 2) {
-                            printf("    Creating a nonsolid subface at fake");
-                            printf(" tet (%d, %d %d)\n",
-                                   pointmark(org(spintet)),
-                                   pointmark(dest(spintet)),
-                                   pointmark(apex(spintet)));
-                          }
-                        } else {
-                          if (verbose > 2) {
-                            printf("    Creating a nonsolid subface at");
-                            printf(" casing tet (%d, %d, %d, %d)\n",
-                                   pointmark(org(spintet)),
-                                   pointmark(dest(spintet)),
-                                   pointmark(apex(spintet)),
-                                   pointmark(oppo(spintet)));
-                          }
-                        }
-                        if (verbose > 2) {
-                           printf("      for holding subsegment (%d, %d).\n",
-                                  pointmark(sorg(checkshseg)),
-                                  pointmark(sdest(checkshseg)));
-                        }
-                        insertsubface(&spintet, NONSOLIDFLAG, 1);
-                        successbonded = 1;
-                        break;
-                      }
-                    } else {
-                      hitbdry ++;
-                      if (hitbdry >= 2) {
-                        break;
-                      } else {
-                        esym(crosstet, spintet);
-                      }
-                    }
-                  }
-                  if (!successbonded) {
-                    // We can't find a face suitable for holding subsegment.
-                    //   Find a boundary face around this subsegment(spintet
-                    //   ) and create a fake tet at this face, then insert
-                    //   a new subface at this fake tet. We can sure, this
-                    //   fake tet will be added to casing face list later.
-                    triface tmpfaketet;
-                    int count = 1000;
-                    while (fnextself(spintet) && count) count--;
-                    if (count <= 0) {
-                      if (verbose) {
-                        printf("Warnning in recoverface():\n");
-                        printf("  We can't find a face suitable for holding");
-                        printf(" subsegment, skip anyway.\n");
-                      }
-                    } else {
-                      adjustedgering(spintet, CCW);
-                      torg = org(spintet);
-                      tdest = dest(spintet);
-                      tapex = apex(spintet);
-                      maketetrahedron(&tmpfaketet);
-                      tmpfaketet.loc = 0; // For sure.
-                      setorg(tmpfaketet, tdest);
-                      setdest(tmpfaketet, torg);
-                      setapex(tmpfaketet, tapex);
-                      // setoppo(tmpfaketet, NULL);
-                      if (verbose > 2) {
-                        printf("    Creating a fake tet for holding");
-                        printf(" subface (%d, %d, %d).\n", pointmark(tdest),
-                               pointmark(torg), pointmark(tapex));
-                      }
-                      bond(tmpfaketet, spintet);
-                      if (verbose > 2) {
-                        printf("    Creating a nonsolid subface (%d, %d, %d)\n",
-                               pointmark(torg), pointmark(tdest),
-                               pointmark(tapex));
-                        printf("      for holding subsegment (%d, %d).\n",
-                               pointmark(sorg(checkshseg)),
-                               pointmark(sdest(checkshseg)));
-                      }
-                      // Insert a new subface, and it will automatically bond
-                      //   the subsegment(set autobond flag be '1').
-                      insertsubface(&spintet, NONSOLIDFLAG, 1);
-                      successbonded = 1;
-                    }
-                  }
-                  // assert(successbonded);
-                }
-              }
-            }
-            senextself(checksh);
-            enextself(crosstet);
-            edgecount++;
-          }
-          // This subface can be dealloced now. Before dealloc, we must
-          //   dissolve it from two side tetrahedra.
-          tsdissolve(crosstet);
-          tsdissolve(checkface);
-          if (verbose > 2) {
-            printf("    Deleting subface (%d, %d, %d) (nonsolid).\n",
-                   pointmark(sorg(checksh)), pointmark(sdest(checksh)),
-                   pointmark(sapex(checksh)));
-          }
-          shellfacedealloc(&subfaces, checksh.sh);
-        }
-      }
-    }
-  }
-  assert(northcasinglist->len());
-  assert(sourthcasinglist->len());
-
-  // Step (5):
-  if (verbose > 2) {
-    printf("    Creating casing faces for missing faces(at equator).\n");
-  }
-  equatorcasinglist = new list(sizeof(triface));
-
-  for (i = 0; i < missingfacelist->len(); i++) {
-    iptr = (int*) (*missingfacelist)[i];
-    index = iptr[0] * 3;
-    iorg = out->trianglelist[index + edgeorient];
-    idest = out->trianglelist[index + plus1mod3[edgeorient]];
-    iapex = out->trianglelist[index + minus1mod3[edgeorient]];
-    torg = *(point3d*)(*pointlist)[iorg];
-    tdest = *(point3d*)(*pointlist)[idest];
-    tapex = *(point3d*)(*pointlist)[iapex];
-    maketetrahedron(&checkface);
-    orient1 = iorient3d(torg, tdest, tapex, tsourth);
-    assert(orient1 != 0);
-    if (orient1 < 0) {
-      setorg(checkface, torg);
-      setdest(checkface, tdest);
-    } else {
-      setorg(checkface, tdest);
-      setdest(checkface, torg);
-    }
-    setapex(checkface, tapex);
-    if (verbose > 2) {
-      printf("    Creating and queuing equatorcasing face (%d, %d, %d).\n",
-             pointmark(org(checkface)), pointmark(dest(checkface)),
-             pointmark(apex(checkface)));
-    }
-    equatorcasinglist->append(&checkface);
-  }
-  assert(equatorcasinglist->len());
-
-  // Step (6):
-  //   Generate giftfaces, giftpoints and giftpointdegrees at north side.
-  numberofgiftfaces = equatorcasinglist->len() + northcasinglist->len();
-  numberofgiftpoints = equatorpointlist->len() + northpointlist->len();
-  giftfaces = new triface[numberofgiftfaces];
-  giftpoints = new point3d[numberofgiftpoints];
-  // Create a backtrace list to keep all new tets be created during
-  //   gift-wrapping stage, so we can delete them if gift-wrapping failed.
-  backtracelist = new list(sizeof(triface));
-
-  //   Generate giftfaces.
-  for (i = 0; i < equatorcasinglist->len(); i++) {
-    giftfaces[i] = *(triface*)(*equatorcasinglist)[i];
-  }
-  for (j = i; j < numberofgiftfaces; j++) {
-    giftfaces[j] = *(triface*)(*northcasinglist)[j - i];
-    dissolve(giftfaces[j]);
-  }
-  //   Generate giftpoints.
-  for (i = 0; i < equatorpointlist->len(); i++) {
-    giftpoints[i] = *(point3d*)(*equatorpointlist)[i];
-  }
-  for (j = i; j < numberofgiftpoints; j++) {
-    giftpoints[j] = *(point3d*)(*northpointlist)[j - i];
-  }
-
-  errorflag = giftwrapping(numberofgiftfaces, giftfaces, numberofgiftpoints,
-                           giftpoints, NULL, 0, backtracelist);
-  if (errorflag == 0) {
-    if (verbose > 2) {
-      printf("    Badly, gift-wrapping failed, clear all new tets that");
-      printf(" created during gift-wrapping.\n");
-    }
-    for (i = 0; i < backtracelist->len(); i++) {
-      checkfaceptr = (triface*)(*backtracelist)[i];
-      if (verbose > 2) {
-        printf("    Deleting new tet (%d, %d, %d, %d).\n",
-               pointmark(org(*checkfaceptr)), pointmark(dest(*checkfaceptr)),
-               pointmark(apex(*checkfaceptr)), pointmark(oppo(*checkfaceptr)));
-      }
-      tetrahedrondealloc(checkfaceptr->tet);
-    }
-    if (!insertfieldpoint(numberofgiftfaces, giftfaces, numberofgiftpoints,
-                          giftpoints, crosstetlist)) {
-      printf("Internalerror in recoverface(): Insert field point failed.\n");
-      internalerror();
-    }
-  }
-
-  if (verbose > 2) {
-    printf("    Removing and replacing fake tets at equator with real tets.\n");
-  }
-  for (i = 0; i < equatorcasinglist->len(); i++) {
-    checkfaceptr = (triface*)(*equatorcasinglist)[i];
-    assert(oppo(*checkfaceptr) == (point3d) NULL);
-    sym(*checkfaceptr, starttet);
-    dissolve(starttet);
-    // Remove fake tet.
-    tetrahedrondealloc(checkfaceptr->tet);
-    // Replace fake tet with a real tet.
-    adjustedgering(starttet, CCW);
-    *checkfaceptr = starttet;
-    // Set a hit pointer in vertexs of face.
-    torg = org(starttet);
-    tdest = dest(starttet);
-    tapex = apex(starttet);
-    setpoint2tet(torg, encode(starttet));
-    setpoint2tet(tdest, encode(starttet));
-    setpoint2tet(tapex, encode(starttet));
-    if (verbose > 2) {
-      printf("    Changing (%d, %d, %d).\n",
-             pointmark(torg), pointmark(tdest), pointmark(tapex));
-    }
-  }
-  delete [] giftfaces;
-  delete [] giftpoints;
-  backtracelist->clear();
-
-  //   Generate giftfaces, giftpoints and giftpointdegrees at sourth side.
-  numberofgiftfaces = equatorcasinglist->len() + sourthcasinglist->len();
-  numberofgiftpoints = equatorpointlist->len() + sourthpointlist->len();
-  giftfaces = new triface[numberofgiftfaces];
-  giftpoints = new point3d[numberofgiftpoints];
-
-  //   Generate giftfaces.
-  for (i = 0; i < equatorcasinglist->len(); i++) {
-    giftfaces[i] = *(triface*)(*equatorcasinglist)[i];
-  }
-  for (j = i; j < numberofgiftfaces; j++) {
-    giftfaces[j] = *(triface*)(*sourthcasinglist)[j - i];
-    dissolve(giftfaces[j]);
-  }
-  //   Generate giftpoints.
-  for (i = 0; i < equatorpointlist->len(); i++) {
-    giftpoints[i] = *(point3d*)(*equatorpointlist)[i];
-  }
-  for (j = i; j < numberofgiftpoints; j++) {
-    giftpoints[j] = *(point3d*)(*sourthpointlist)[j - i];
-  }
-
-  errorflag = giftwrapping(numberofgiftfaces, giftfaces, numberofgiftpoints,
-                           giftpoints, NULL, 0, backtracelist);
-  if (errorflag == 0) {
-    if (verbose > 2) {
-      printf("    Badly, gift-wrapping failed, clear all new tets that");
-      printf(" created during gift-wrapping.\n");
-    }
-    for (i = 0; i < backtracelist->len(); i++) {
-      checkfaceptr = (triface*)(*backtracelist)[i];
-      if (verbose > 2) {
-        printf("    Deleting new tet (%d, %d, %d, %d).\n",
-               pointmark(org(*checkfaceptr)), pointmark(dest(*checkfaceptr)),
-               pointmark(apex(*checkfaceptr)), pointmark(oppo(*checkfaceptr)));
-      }
-      tetrahedrondealloc(checkfaceptr->tet);
-    }
-    if (!insertfieldpoint(numberofgiftfaces, giftfaces, numberofgiftpoints,
-                          giftpoints, crosstetlist)) {
-      printf("Internalerror in recoverface(): Generate field point failed.\n");
-      internalerror();
-    }
-  }
-
-  if (verbose > 2) {
-    printf("    Removing and replacing fake tets in north with dummytet.\n");
-  }
-  for (i = 0; i < northcasinglist->len(); i++) {
-    checkface = *(triface*)(*northcasinglist)[i];
-    if (oppo(checkface) == (point3d) NULL) {
-      if (verbose > 2) {
-        printf("    Changing (%d, %d, %d).\n",
-               pointmark(org(checkface)), pointmark(dest(checkface)),
-               pointmark(apex(checkface)));
-      }
-      sym(checkface, starttet);
-      dissolve(starttet);
-      tspivot(checkface, checksh);
-      if (checksh.sh != dummysh) {
-        stdissolve(checksh);
-      }
-      tetrahedrondealloc(checkface.tet);
-      checkface = starttet;
-    }
-    // Set a hit pointer in vertexs of face.
-    torg = org(checkface);
-    tdest = dest(checkface);
-    tapex = apex(checkface);
-    setpoint2tet(torg, encode(checkface));
-    setpoint2tet(tdest, encode(checkface));
-    setpoint2tet(tapex, encode(checkface));
-  }
-
-  if (verbose > 2) {
-    printf("    Removing and replacing fake tets in sourth with dummytet.\n");
-  }
-  for (i = 0; i < sourthcasinglist->len(); i++) {
-    checkface = *(triface*)(*sourthcasinglist)[i];
-    if (oppo(checkface) == (point3d) NULL) {
-      if (verbose > 2) {
-        printf("    Changing (%d, %d, %d).\n",
-               pointmark(org(checkface)), pointmark(dest(checkface)),
-               pointmark(apex(checkface)));
-      }
-      sym(checkface, starttet);
-      dissolve(starttet);
-      tspivot(checkface, checksh);
-      if (checksh.sh != dummysh) {
-        stdissolve(checksh);
-      }
-      tetrahedrondealloc(checkface.tet);
-      checkface = starttet;
-    }
-    // Set a hit pointer in vertexs of face.
-    torg = org(checkface);
-    tdest = dest(checkface);
-    tapex = apex(checkface);
-    setpoint2tet(torg, encode(checkface));
-    setpoint2tet(tdest, encode(checkface));
-    setpoint2tet(tapex, encode(checkface));
-  }
-
-  // We can delete all crosstets in crosstetlist.
-  for (i = 0; i < crosstetlist->len(); i++) {
-    crosstet = *(triface*)(*crosstetlist)[i];
-    if (verbose > 2) {
-      printf("    Deleting tet (%d, %d, %d, %d).\n",
-             pointmark(org(crosstet)), pointmark(dest(crosstet)),
-             pointmark(apex(crosstet)), pointmark(oppo(crosstet)));
-    }
-    tetrahedrondealloc(crosstet.tet);
-  }
-
-  delete [] giftfaces;
-  delete [] giftpoints;
-  delete missingfacelist;
-  delete crossedgelist;
-  delete crosstetlist;
-  delete equatorpointlist;
-  delete northpointlist;
-  delete sourthpointlist;
-  delete equatorcasinglist;
-  delete northcasinglist;
-  delete sourthcasinglist;
-  delete backtracelist;
-  return 1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertfacet()     Force the facet of PLC existing in tetrahedralization.  //
-//                                                                           //
-// First, we need form a triangulation of the PSLG facet. Obviously, we can  //
-// not only consider the verteices of a facet given in the .poly or .smesh   //
-// file. Which vertices of the tetrahedralization need to be considered in a //
-// facet triangulation?  The answer can be found from Shewchuk's paper [6]:  //
-//   ...                                                                     //
-//   It is a fact, albeit somewhat nonintuitive, that if a facet appears in  //
-// a Delaunay tetrahedralization as a union of faces, then the triangulation //
-// of the facet is determined solely by the vertices of the tetrahedralizat- //
-// ion that lies in the plane of the facet.  If a vertex lies close to a     //
-// facet, but not in the same plane, it may cause a subfacet to be missing,  //
-// but it can not affect the shape of the triangulation if all subfacets are //
-// present. The detail please see Jonathan's Ph.D. thesis page 92.           //
-//   Hence the facet triangulation need only consider vertices lying in the  //
-// plane of the facet. Furthermore, because each facet is segment-bounded,   //
-// and segment are recovered (in the tetrahedralization) before facets, each //
-// facet triangulation can saftly ignore vertices that lie outside the facet //
-// (even in the same plane). The only addtional vertices to be considered    //
-// are those that were inserted on segments to force segments and other      //
-// facets into the mesh.                                                     //
-//   Unfortunately, if a facet triangulation is not unique because of        //
-// cocircularity degeneracies, then foregoing statement about extraplanar    //
-// vertices having no effect on the triangulation does not apply. To be      //
-// specific, suppose a facet triangulation has four or more cocircular       //
-// vertices, which are triangulate one way, whereas the tetrahedralization   //
-// contains a set of faces that triangulate the same vertices with a         //
-// diffrent (but also Delaunay) set of triangles. An aggressive implementat- //
-// ion might identify these cases and correct the facet triangulation so     //
-// that it matches the tetrahedralization (it is not always possible to      //
-// force the tetrahedralization to match the triangulation). However,        //
-// inserting a new vertex at the center of the collective circumcircle is    //
-// always available as a lazy alternative. Here I use the first method.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::insertfacet(list* facetseglist, list* holelist, int boundmark,
-                         int facenumber)
-{
-  list *pointlist, *conlist;
-  list *indexlist, *steinerlist;
-  queue *matchlist;
-  triface searchtet;
-  point3d torg, tdest, tapex, tfarapex;
-  point3d *segendpoints;
-  enum matchfaceresult match;
-  struct triangulateio in, out;
-  REAL norm[3], xaxi[3], yaxi[3];
-  REAL v0[3], v1[3], dsin;
-  REAL *holecoords;
-  int *indexofsegendpoints, *indexofconpoints;
-  int iorg, idest, iapex, ifarapex;
-  int edgeorient, isswapable, maxlooptimes;
-  int i, j, index;
-
-  // Set a pointlist and conlist for PSLG facet. 'pointlist' keep all the
-  //   pointers of points. 'conlist' keep each segment's endpoint index in
-  //   'pointlist'.
-  pointlist = new list("point");
-  conlist = new list(sizeof(int) * 2);
-
-  // First form a PSLG from the input 'facetseglist'.  Remeber, at this
-  //   time, every segment is existed in the domain and is represented by
-  //   a contiguous linear sequence of edges of the tetrahedralization. We
-  //   must get all the steiner vertexs in the segment not merely get the
-  //   segment's endpoints.
-  indexlist = new list(sizeof(int) * 2);
-  for (i = 0; i < facetseglist->len(); i++) {
-    segendpoints = (point3d*) (*facetseglist)[i];
-    indexofsegendpoints = (int*) indexlist->alloc();
-    if (segendpoints[1] == (point3d) NULL) {
-      // It's a isolate point in PSLG.
-      pointlist->append(&segendpoints[0]);
-      // We don't need this point's index.
-      indexofsegendpoints[0] = indexofsegendpoints[1] = -1;
-    } else {
-      indexofsegendpoints[0] = pointlist->hasitem(&segendpoints[0]);
-      if (indexofsegendpoints[0] == -1) {
-        pointlist->append(&segendpoints[0]);
-        indexofsegendpoints[0] = pointlist->len() - 1;
-      }
-      indexofsegendpoints[1] = pointlist->hasitem(&segendpoints[1]);
-      if (indexofsegendpoints[1] == -1) {
-        pointlist->append(&segendpoints[1]);
-        indexofsegendpoints[1] = pointlist->len() - 1;
-      }
-    }
-  }
-  // Get all steiner points in segments and make connection infomation.
-  steinerlist = new list("point", 10, 5);
-  for (i = 0; i < facetseglist->len(); i++) {
-    segendpoints = (point3d*) (*facetseglist)[i];
-    if (segendpoints[1] != (point3d) NULL) {
-      getsteinersinseg(segendpoints[0], segendpoints[1], steinerlist);
-      indexofsegendpoints = (int*) (*indexlist)[i];
-      indexofconpoints = (int*) conlist->alloc();
-      indexofconpoints[0] = indexofsegendpoints[0];
-      for (j = 0; j < steinerlist->len(); j++) {
-        pointlist->append((*steinerlist)[j]);
-        indexofconpoints[1] = pointlist->len() - 1;
-        indexofconpoints = (int*) conlist->alloc();
-        indexofconpoints[0] = pointlist->len() - 1;
-      }
-      indexofconpoints[1] = indexofsegendpoints[1];
-      steinerlist->clear();
-    }
-  }
-  delete steinerlist;
-  delete indexlist;
-
-  // Create the 2D mesh that will know what the correct subfaces are.
-  if (verbose > 1) {
-    printf("  Generate %d surface mesh: %d points, %d segments",
-           facenumber, pointlist->len(), conlist->len());
-    if (holelist) {
-      printf(", %d holes.", holelist->len());
-    }
-    printf("\n");
-  }
-  triangulateioinit(&in);
-  triangulateioinit(&out);
-  if ((pointlist->len() == 3) && (conlist->len() == 3)) {
-    // The facet is a triangle, this case we need not do surface mesh and
-    //   set the output mesh directly.
-    out.numberoftriangles = 1;
-    out.trianglelist = new int[3];
-    out.trianglelist[0] = 0;
-    out.trianglelist[1] = 1;
-    out.trianglelist[2] = 2;
-    out.neighborlist = new int[3];
-    out.neighborlist[0] = -1;
-    out.neighborlist[1] = -1;
-    out.neighborlist[2] = -1;
-  } else {
-    in.numberofpoints = pointlist->len();
-    in.pointlist = new REAL[in.numberofpoints * 2];
-    in.numberofsegments = conlist->len();
-    in.segmentlist = new int[in.numberofsegments * 2];
-    index = 0;
-    for (i = 0; i < in.numberofsegments; i ++) {
-      indexofconpoints = (int*) (*conlist)[i];
-      in.segmentlist[index++] = indexofconpoints[0];
-      in.segmentlist[index++] = indexofconpoints[1];
-    }
-    // Determine normal, we need find two not coliner vectors from
-    //   input points.
-    torg = *(point3d*)(*pointlist)[in.segmentlist[0]];
-    tdest = *(point3d*)(*pointlist)[in.segmentlist[1]];
-    Sub3D(tdest, torg, v0);
-    Normalize3D(v0);
-    index = 2;
-    dsin = 0;
-    for (i = 1; fabs(dsin) <= usertolerance; i++) {
-      torg = *(point3d*)(*pointlist)[in.segmentlist[index++]];
-      tdest = *(point3d*)(*pointlist)[in.segmentlist[index++]];
-      Sub3D(tdest, torg, v1);
-      Normalize3D(v1);
-      Cross3D(v0, v1, norm);
-      dsin = Mag3D(norm);
-      if (!(fabs(dsin) <= usertolerance)) Scale3D(norm, 1./dsin);
-      if (i >= in.numberofsegments) {
-        printf("Recover Error: Can't find normal for %d facet.\n", facenumber);
-        recovererror();
-      }
-    }
-    // Project onto a plane
-    Assign3D(v1, xaxi);
-    Cross3D(norm, xaxi, yaxi);
-    index = 0;
-    for (i = 0; i < in.numberofpoints; i ++) {
-      torg = *(point*)(*pointlist)[i];
-      in.pointlist[index++] = Dot3D(torg, xaxi);
-      in.pointlist[index++] = Dot3D(torg, yaxi);
-    }
-    if (holelist) {
-      if (holelist->len() > 0) {
-        in.numberofholes = holelist->len();
-        in.holelist = new REAL[in.numberofholes * 2];
-        index = 0;
-        for (i = 0; i < in.numberofholes; i++) {
-          holecoords = (REAL *) (*holelist)[i];
-          in.holelist[index++] = Dot3D(holecoords, xaxi);
-          in.holelist[index++] = Dot3D(holecoords, yaxi);
-        }
-      }
-    }
-    index = 0;
-    // Now create the 2D mesh.
-    surfmesh->triangulate(&in, &out, NULL);
-    if (surfmesh->triangles.items <= 0) {
-      printf("Recover error: Can't form a surface mesh for facet %d.\n",
-             facenumber);
-      recovererror();
-    }
-    if (verbose > 1) {
-      printf("  Surface mesh result: %d triangles.\n",
-             surfmesh->triangles.items);
-    }
-    surfmesh->trianglerestart();
-  }
-
-  // Set up a list to keep all the subface's index.
-  matchlist = new queue("int");
-  for (i = 0; i < out.numberoftriangles; i++) {
-    matchlist->push(&i);
-  }
-  // To recover each of faces by swapping.  In this case, though,
-  //   no point insertion is ever needed.
-  maxlooptimes = out.numberoftriangles * 4; // Set a emergency break times.
-  if (maxlooptimes <= 0) {
-    // int type Overflow, set it be the largest int number.
-    maxlooptimes = 0x7fffffff;
-  }
-  while (matchlist->get(&i) && maxlooptimes) {
-    maxlooptimes--;
-    index = i * 3;
-    iorg = out.trianglelist[index++];
-    idest = out.trianglelist[index++];
-    iapex = out.trianglelist[index++];
-    torg = *(point3d*)(*pointlist)[iorg];
-    tdest = *(point3d*)(*pointlist)[idest];
-    tapex = *(point3d*)(*pointlist)[iapex];
-    if (verbose > 1) {
-      printf("  Matching subface (%d, %d, %d).\n",
-             pointmark(torg), pointmark(tdest), pointmark(tapex));
-    }
-    edgeorient = 0;
-    searchtet.tet = dummytet;
-    match = matchface(torg, tdest, tapex, &searchtet, boundmark);
-    if (match == EDGEMISSING) {
-      // edge (torg, tdest) is missing. Check if other edges are missing.
-      searchtet.tet = dummytet;
-      match = matchface(tdest, tapex, torg, &searchtet, boundmark);
-      if (match == EDGEMISSING) {
-        searchtet.tet = dummytet;
-        match = matchface(tapex, torg, tdest, &searchtet, boundmark);
-        if (match == EDGEMISSING) {
-          // All edges of subface are missing. Push back to list to
-          //   handle it later.
-          matchlist->push(&i);
-          continue;
-        } else {
-          // edge (tapex, torg) exist, both other 2 edges are missing.
-          assert(match == APEXMISSING);
-          edgeorient = 2;
-        }
-      } else {
-        // edge (tdest, tapex) exist.
-        assert(match == APEXMISSING);
-        edgeorient = 1;
-      }
-    }
-    if (match == APEXMISSING) {
-      // Two edges are missing. Check if there exist degenerate case.
-      //   'searchtet' must be a handle of the exist edge.
-      ifarapex = getdiagonalapexindex(&out, i, plus1mod3[edgeorient]);
-      if (ifarapex != -1) {
-        // Before repair the degenerate case, we should ensure that the
-        //   new triangle is valid (it's three corners appear in counter-
-        //   clockwise direction). Sep. 5, 2001.
-        // Thanks Prof. Renato Cardoso Mesquita (renato@cpdee.ufmg.br).
-        isswapable = 1;
-        if (edgeorient == 0) {
-          if (orient2d(&(in.pointlist[iorg * 2]), &(in.pointlist[idest * 2]),
-                       &(in.pointlist[ifarapex * 2])) <= 0) {
-            isswapable = 0;
-          }
-        } else if (edgeorient == 1) {
-          if (orient2d(&(in.pointlist[idest * 2]), &(in.pointlist[iapex * 2]),
-                       &(in.pointlist[ifarapex * 2])) <= 0) {
-            isswapable = 0;
-          }
-        } else { // edgeorient == 2
-          if (orient2d(&(in.pointlist[iapex * 2]), &(in.pointlist[iorg * 2]),
-                       &(in.pointlist[ifarapex * 2])) <= 0) {
-            isswapable = 0;
-          }
-        }
-        if (isswapable) {
-          tfarapex = *(point3d*)(*pointlist)[ifarapex];
-          match = matchface(NULL, NULL, tfarapex, &searchtet, boundmark);
-          if (match == FACEMATCHING) {
-            swapdiagonal(&out, i, edgeorient, plus1mod3[edgeorient]);
-            continue;
-          }
-        }
-      }
-      ifarapex = getdiagonalapexindex(&out, i, minus1mod3[edgeorient]);
-      if (ifarapex != -1) {
-        // Before repair the degenerate case, we should ensure that the
-        //   new triangle is valid (it's three corners appear in counter-
-        //   clockwise direction). Sep. 5, 2001.
-        // Thanks Prof. Renato Cardoso Mesquita (renato@cpdee.ufmg.br).
-        isswapable = 1;
-        if (edgeorient == 0) {
-          if (orient2d(&(in.pointlist[iorg * 2]), &(in.pointlist[idest * 2]),
-                       &(in.pointlist[ifarapex * 2])) <= 0) {
-            isswapable = 0;
-          }
-        } else if (edgeorient == 1) {
-          if (orient2d(&(in.pointlist[idest * 2]), &(in.pointlist[iapex * 2]),
-                       &(in.pointlist[ifarapex * 2])) <= 0) {
-            isswapable = 0;
-          }
-        } else { // edgeorient == 2
-          if (orient2d(&(in.pointlist[iapex * 2]), &(in.pointlist[iorg * 2]),
-                       &(in.pointlist[ifarapex * 2])) <= 0) {
-            isswapable = 0;
-          }
-        }
-        if (isswapable) {
-          tfarapex = *(point3d*)(*pointlist)[ifarapex];
-          match = matchface(NULL, NULL, tfarapex, &searchtet, boundmark);
-          if (match == FACEMATCHING) {
-            swapdiagonal(&out, i, edgeorient, minus1mod3[edgeorient]);
-            continue;
-          }
-        }
-      }
-      // Subface is missing.
-      matchlist->push(&i);
-      // Recover the missing face.
-      recoverface(pointlist, &out, i, edgeorient);
-    }
-  }
-
-  if (maxlooptimes == 0) {
-    printf("Recover error in insertfacet():\n");
-    printf("  Failed to recover facet %d.\n", facenumber);
-    recovererror();
-  }
-  triangulateiodeinit(&in);
-  triangulateiodeinit(&out);
-  delete matchlist;
-  delete pointlist;
-  delete conlist;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// formskeleton()    Create the shell segments and subfaces of a triangula-  //
-//                   tion, including PLC edges, facets and facets on the     //
-//                   convex hull.                                            //
-//                                                                           //
-// The PLC edges and facets are read from a .poly or .smesh file. The return //
-// value is the number of facets in the file.                                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::formskeleton(FILE *polyfile)
-{
-  list **seglist, **holelist;
-  point3d *segendpoints;
-  REAL *holecoords;
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-  int *boundmarkers;
-  int facets, polygons, segments, inholes;
-  int facetmarkers;
-  int head, end1, end2, end3;
-  int i, j, k;
-
-  if (poly || smesh) {
-    // Read number of facets and number of boundary markers from a .poly or
-    //   .smesh file.
-    stringptr = readline(inputline, polyfile, inpolyfilename);
-    facets = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      facetmarkers = 0;
-    } else {
-      facetmarkers = (int) strtol (stringptr, &stringptr, 0);
-    }
-  } else {
-    facets = 0;
-  }
-
-  if (facets > 0) {
-    if (!quiet) {
-      printf("Inserting segments into Delaunay triangulation.\n");
-    }
-    // Compute a mapping from points to tetrahedra.
-    makepointmap();
-    // For each facet, create a list for keeping the endpoints of
-    //   segments of each facet, and create a list for keeping the
-    //   holes point (coordinates) of each facet.
-    boundmarkers = new int[facets];
-    seglist = new list*[facets];
-    holelist = new list*[facets];
-    for (i = 0; i < facets; i++) {
-      boundmarkers[i] = 0;
-      seglist[i] = NULL;
-      holelist[i] = NULL;
-    }
-
-    if (poly) {
-      // For each facet, read and insert all segments.
-      for (i = 1; i <= facets; i++) {
-        seglist[i - 1] = new list(sizeof(point3d) * 2);
-        // Read number of polygons, number of holes and boundary marker of
-        //   this facets.
-        // Note: I assume each polygon in facet at least has two endpoints.
-        stringptr = readline(inputline, polyfile, inpolyfilename);
-        polygons = (int) strtol (stringptr, &stringptr, 0);
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          inholes = 0;
-          boundmarkers[i - 1] = 0;  // no boundary marker for this facet.
-        } else {
-          inholes = (int) strtol (stringptr, &stringptr, 0);
-          if (facetmarkers == 1) {
-            stringptr = findfield(stringptr);
-            if (*stringptr == '\0') {
-              boundmarkers[i - 1] = 0;  // no boundary marker for this facet.
-            } else {
-              boundmarkers[i - 1] = (int) strtol (stringptr, &stringptr, 0);
-            }
-          }
-        }
-
-        // For each polygon in this facet, raed and insert all segments.
-        for (j = 1; j <= polygons; j++) {
-          // Read number of segments of a polygon.
-          stringptr = readline(inputline, polyfile, inpolyfilename);
-          segments = (int) strtol (stringptr, &stringptr, 0);
-          if (segments <= 1) {
-            printf("File I/O Error:  Wrong vertex number of polygon %d", j);
-            printf(" in facet %d in %s.\n", i, inpolyfilename);
-            if (segments == 1) {
-              printf("  If you want define a isolate point in facet, you can\n");
-              printf("  define a degenrate segment(with two same endpoints)\n ");
-              printf("  in stead of.\n");
-            }
-            exit(1);
-          }
-          // Read and insert the segments.
-          stringptr = findfield(stringptr);
-          if (*stringptr == '\0') {
-            // Try load another non-empty line to continue
-            stringptr = readline(inputline, polyfile, inpolyfilename);
-            if (*stringptr == '\0') {
-              printf("File I/O Error:  No endpoints for polygon %d", j);
-              printf(" in facet %d in %s.\n", i, inpolyfilename);
-              exit(1);
-            } else {
-              head = end1 = (int) strtol (stringptr, &stringptr, 0);
-            }
-          } else {
-            head = end1 = (int) strtol (stringptr, &stringptr, 0);
-          }
-          for (k = 1; k < segments; k++) {
-            stringptr = findfield(stringptr);
-            if (*stringptr == '\0') {
-              // Try load another non-empty line to continue
-              stringptr = readline(inputline, polyfile, inpolyfilename);
-              if (*stringptr == '\0') {
-                printf("File I/O Error:  Missing %d endpoints for", segments - k);
-                printf(" polygon %d in facet %d in %s.\n", j, i, inpolyfilename);
-                exit(1);
-              } else {
-                end2 = (int) strtol (stringptr, &stringptr, 0);
-              }
-            } else {
-              end2 = (int) strtol (stringptr, &stringptr, 0);
-            }
-            if ((end1 < firstnumber) || (end1 >= firstnumber + inpoints)) {
-              if (!quiet) {
-                printf("Warning:  Invalid endpoint %d of polygon %d", k, j);
-                printf(" in facet %d in %s.\n", i, inpolyfilename);
-              }
-            } else if ((end2 < firstnumber) || (end2 >= firstnumber + inpoints)) {
-              if (!quiet) {
-                printf("Warning:  Invalid endpoint %d of polygon %d", k + 1, j);
-                printf(" in facet %d in %s.\n", i, inpolyfilename);
-              }
-            } else {
-              segendpoints = (point3d *) seglist[i - 1]->alloc();
-              segendpoints[0] = getpoint(end1);
-              segendpoints[1] = getpoint(end2);
-              if (segendpoints[0] == segendpoints[1]) {
-                if (segments == 2) {
-                  // A degenrate edge, it represent an isolate point in facet.
-                  segendpoints[1] = (point3d) NULL;
-                } else {
-                  printf("Warning:  Polygon %d has two identical endpoints", j);
-                  printf(" in facet %d in %s.\n", i, inpolyfilename);
-                }
-              } else {
-                insertsegment(segendpoints[0], segendpoints[1], boundmarkers[i-1]);
-              }
-            }
-            end1 = end2;
-          }
-          if (segments > 2) {
-            if (((end2 >= firstnumber) && (end2 < firstnumber + inpoints))
-                  && ((head >= firstnumber) && (head < firstnumber + inpoints))) {
-              segendpoints = (point3d *) seglist[i - 1]->alloc();
-              segendpoints[0] = getpoint(end2);
-              segendpoints[1] = getpoint(head);
-              if (segendpoints[0] == segendpoints[1]) {
-                if (segments == 2) {
-                  // A degenrate edge, it represent an isolate point in the facet.
-                  segendpoints[1] = (point3d) NULL;
-                } else {
-                  printf("Warning:  Polygon %d has two identical endpoints", j);
-                  printf(" in facet %d in %s.\n", i, inpolyfilename);
-                }
-              } else {
-                insertsegment(segendpoints[0], segendpoints[1], boundmarkers[i-1]);
-              }
-            }
-          }
-        }
-
-        // Read the holes' coordinates.
-        if (inholes > 0) {
-          holelist[i - 1] = new list(sizeof(REAL) * 3);
-          for (j = 1; j <= inholes; j++) {
-            holecoords = (REAL *) holelist[i - 1]->alloc();
-            stringptr = readline(inputline, polyfile, inpolyfilename);
-            stringptr = findfield(stringptr);
-            if (*stringptr == '\0') {
-              printf("File I/O Error:  Hole %d in facet %d", j, i);
-              printf(" has no coordinates in %s.\n", inpolyfilename);
-              exit(1);
-            } else {
-              holecoords[0] = (REAL) strtod (stringptr, &stringptr);
-            }
-            stringptr = findfield(stringptr);
-            if (*stringptr == '\0') {
-              printf("File I/O Error:  Hole %d in facet %d", j, i);
-              printf(" is missing its y-coordinate in %s.\n", inpolyfilename);
-              exit(1);
-            } else {
-              holecoords[1] = (REAL) strtod (stringptr, &stringptr);
-            }
-            stringptr = findfield(stringptr);
-            if (*stringptr == '\0') {
-              printf("File I/O Error:  Hole %d in facet %d", j, i);
-              printf(" is missing its z-coordinate in %s.\n", inpolyfilename);
-              exit(1);
-            } else {
-              holecoords[2] = (REAL) strtod (stringptr, &stringptr);
-            }
-          }
-        }
-      } // end inserting all segments loop.
-    } else if (smesh) {
-      // Read all input triangular facets and its boundary markers.
-      for (i = 1; i <= facets; i++) {
-        // Read three endpoints of this facet.
-        stringptr = readline(inputline, polyfile, insmeshfilename);
-        segments = (int) strtol (stringptr, &stringptr, 0);
-        if (segments <= 1) {
-          printf("File I/O Error:  Wrong vertex number of facet %d", i);
-          printf(" in %s.\n", insmeshfilename);
-          if (segments == 1) {
-            printf("  If you want define a isolate point in facet, you can\n");
-            printf("  define a degenrate segment(with two same endpoints)\n ");
-            printf("  in stead of.\n");
-          }
-          exit(1);
-        }
-        seglist[i - 1] = new list(sizeof(point3d) * 2, segments);
-        // In smesh files, we obtain facet's boundary mark at last.
-        boundmarkers[i-1] = 0;
-        // Read and insert the segments.
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          // Try load another non-empty line to continue
-          stringptr = readline(inputline, polyfile, insmeshfilename);
-          if (*stringptr == '\0') {
-            printf("File I/O Error:  No endpoints for facet %d", i);
-            printf(" in %s.\n", insmeshfilename);
-            exit(1);
-          } else {
-            head = end1 = (int) strtol (stringptr, &stringptr, 0);
-          }
-        } else {
-          head = end1 = (int) strtol (stringptr, &stringptr, 0);
-        }
-        for (k = 1; k < segments; k++) {
-          stringptr = findfield(stringptr);
-          if (*stringptr == '\0') {
-            // Try load another non-empty line to continue
-            stringptr = readline(inputline, polyfile, inpolyfilename);
-            if (*stringptr == '\0') {
-              printf("File I/O Error:  Missing %d endpoints for", segments - k);
-              printf(" facet %d in %s.\n", i, insmeshfilename);
-              exit(1);
-            } else {
-              end2 = (int) strtol (stringptr, &stringptr, 0);
-            }
-          } else {
-            end2 = (int) strtol (stringptr, &stringptr, 0);
-          }
-          if ((end1 < firstnumber) || (end1 >= firstnumber + inpoints)) {
-            if (!quiet) {
-              printf("Warning:  Invalid endpoint %d of facet %d", k, i);
-              printf(" in %s.\n", insmeshfilename);
-            }
-          } else if ((end2 < firstnumber) || (end2 >= firstnumber + inpoints)) {
-            if (!quiet) {
-              printf("Warning:  Invalid endpoint %d of facet %d", k + 1, i);
-              printf(" in %s.\n", insmeshfilename);
-            }
-          } else {
-            segendpoints = (point3d *) seglist[i - 1]->alloc();
-            segendpoints[0] = getpoint(end1);
-            segendpoints[1] = getpoint(end2);
-            if (segendpoints[0] == segendpoints[1]) {
-              if (segments == 2) {
-                // A degenrate edge, it represent an isolate point in facet.
-                segendpoints[1] = (point3d) NULL;
-              } else {
-                printf("Warning:  Facet %d has two identical endpoints", i);
-                printf(" in %s.\n", insmeshfilename);
-              }
-            } else {
-              insertsegment(segendpoints[0], segendpoints[1], boundmarkers[i-1]);
-            }
-          }
-          end1 = end2;
-        }
-        if (segments > 2) {
-          if (((end2 >= firstnumber) && (end2 < firstnumber + inpoints))
-                && ((head >= firstnumber) && (head < firstnumber + inpoints))) {
-            segendpoints = (point3d *) seglist[i - 1]->alloc();
-            segendpoints[0] = getpoint(end2);
-            segendpoints[1] = getpoint(head);
-            if (segendpoints[0] == segendpoints[1]) {
-              if (segments == 2) {
-                // A degenrate edge, it represent an isolate point in the facet.
-                segendpoints[1] = (point3d) NULL;
-              } else {
-                printf("Warning:  Facet %d has two identical endpoints", i);
-                printf(" in %s.\n", insmeshfilename);
-              }
-            } else {
-              insertsegment(segendpoints[0], segendpoints[1], boundmarkers[i-1]);
-            }
-          }
-        }
-        // Read facet's boundary marker at last.
-        if (facetmarkers == 1) {
-          stringptr = findfield(stringptr);
-          if (*stringptr == '\0') {
-            boundmarkers[i - 1] = 0;  // no boundary marker for this facet.
-          } else {
-            boundmarkers[i - 1] = (int) strtol (stringptr, &stringptr, 0);
-          }
-        }
-      }
-    }
-
-    // At this point, we can sure there are no missing segments in the
-    //   tetrahedralization(that is: every segment is existed in the domain
-    //   and is represented by a contiguous linear sequence of edges of the
-    //   tetrahedralization).
-    if (!quiet) {
-      printf("Inserting facets into Delaunay triangulation.\n");
-    }
-    // Re-compute a mapping from points to tetrahedra.
-    makepointmap();
-    // Set up a 2D mesh object. Switches are chosen to read a PSLG (p),
-    //   numbers all items starting from zero (rather than one) (z),
-    //   generates a list of triangle neighbors (n), no terminal output
-    //   except errors (Q). suppresses use of exact arithmetic (X),
-    //   suppresses output of segments (P), suppresses node output (N).
-    // surfmesh = new mesh2d("pznQXPN");
-    surfmesh = new mesh2d("pznQPN");
-
-    for (i = 0; i < facets; i++) {
-      if (seglist[i]->len() > 2) {
-        insertfacet(seglist[i], holelist[i], boundmarkers[i], i + 1);
-      }
-      delete seglist[i];
-      if (holelist[i]) {
-        delete holelist[i];
-      }
-    }
-    delete [] boundmarkers;
-    delete [] seglist;
-    delete [] holelist;
-  }
-
-  return facets;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Segment/Facet (Boundary) Constrained Routines.                            //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Carving out Holes and Concavities Routines.                               //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// infecthull()    Virally infect all of the tetrahedra of the convex hull   //
-//                 that are not protected by subfaces.  Where there are      //
-//                 subfaces, set boundary markers as appropriate.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::infecthull()
-{
-  triface tetloop, tsymtet;
-  tetrahedron **deadtet;
-  face hullface;
-  point3d horg, hdest, hapex;
-
-  if (verbose) {
-    printf("  Marking concavities (external tetrahedra) for elimination.\n");
-  }
-  tetrahedrons.traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    // Is this tetrahedron on the hull?
-    for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
-      sym(tetloop, tsymtet);
-      if (tsymtet.tet == dummytet) {
-        // Is the tetrahedron protected by a subface?
-        tspivot(tetloop, hullface);
-        if ((hullface.sh == dummysh) || (isnonsolid(hullface))) {
-          // The tetrahedron is not protected; infect it.
-          if (!infected(tetloop)) {
-            infect(tetloop);
-            deadtet = (tetrahedron **) viri.alloc();
-            *deadtet = tetloop.tet;
-            break;  // Go and get next tet.
-          }
-        } else {
-          // The tetrahedron is protected; set boundary markers if appropriate.
-          if (mark(hullface) == 0) {
-            setmark(hullface, 1);
-            horg = sorg(hullface);
-            hdest = sdest(hullface);
-            hapex = sapex(hullface);
-            if (pointmark(horg) == 0) {
-              setpointmark(horg, 1);
-            }
-            if (pointmark(hdest) == 0) {
-              setpointmark(hdest, 1);
-            }
-            if (pointmark(hapex) == 0) {
-              setpointmark(hapex, 1);
-            }
-          }
-        }
-      }
-    }
-    tetloop.tet = tetrahedrontraverse();
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// plague()    Spread the virus from all infected tetrahedra to any          //
-//             neighbors not protected by subfaces.  Delete all infected     //
-//             tetrahedra.                                                   //
-//                                                                           //
-// This is the procedure that actually creates holes and concavities.        //
-//                                                                           //
-// This procedure operates in two phases.  The first phase identifies all    //
-// the tetrahedra that will die, and marks them as infected.  They are       //
-// marked to ensure that each tetrahedron is added to the virus pool only    //
-// once, so the procedure will terminate.                                    //
-//                                                                           //
-// The second phase actually eliminates the infected tetrahedra.  It also    //
-// eliminates orphaned segments and points(not done now).                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::plague()
-{
-  triface testtet;
-  triface neighbor;
-  triface spintet, swaptet, livetet;
-  tetrahedron **virusloop;
-  tetrahedron **deadtet;
-  face neighborshell;
-  face testseg, testface;
-  point3d testpoint;
-  point3d norg, ndest, napex;
-  point3d deadorg, deaddest, deadapex, deadoppo;
-  int killseg, killorg;
-  int edgecount, successbonded, hitbdry;
-
-  if (verbose) {
-    printf("  Marking neighbors of marked tetrahedra.\n");
-  }
-  // Loop through all the infected tetrahedra, spreading the virus to
-  //   their neighbors, then to their neighbors' neighbors.
-  viri.traversalinit();
-  virusloop = (tetrahedron **) viri.traverse();
-  while (virusloop != (tetrahedron **) NULL) {
-    testtet.tet = *virusloop;
-    // A tetrahedron is marked as infected by messing with one of its
-    //   vertices(opposite), setting it to an illegal value.  Hence, we
-    //   have to temporarily uninfect this tetrahedron so that we can get
-    //   the proper vertex of this tetrahedron.
-    uninfect(testtet);
-    if (verbose > 2) {
-      // Assign the tetrahedron an orientation for convenience in
-      //   checking its points.
-      testtet.loc = 0;
-      deadorg = org(testtet);
-      deaddest = dest(testtet);
-      deadapex = apex(testtet);
-      deadoppo = oppo(testtet);
-      printf("    Checking (%d, %d, %d, %d)\n", pointmark(deadorg),
-             pointmark(deaddest), pointmark(deadapex), pointmark(deadoppo));
-    }
-    // Check each of the tetrahedron's four neighbors.
-    for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
-      // Find the neighbor.
-      sym(testtet, neighbor);
-      // Check for a shell between the tetrahedron and its neighbor.
-      tspivot(testtet, neighborshell);
-      // Check if the neighbor is nonexistent or already infected.
-      if ((neighbor.tet == dummytet) || infected(neighbor)) {
-        if (neighborshell.sh != dummysh) {
-          // There is a subface separating the tetrahedron from its neighbor,
-          //   but both tetrahedra are dying, so the subface dies too.
-          //   Before deallocte the subface, check each of the three sides
-          //   of the subface for preserving subsegments if there need. This
-          //   is done by spinning around each edge, checking if it is still
-          //   connected to at least one live tetrahedron.
-          neighborshell.shver = 0;
-          // For keep the same enext() direction.
-          findversion(&testtet, &neighborshell, 0);
-          for (edgecount = 0; edgecount < 3; edgecount++) {
-            sspivot(neighborshell, testseg);
-            if (testseg.sh != dummysh) {
-              spivot(testseg, testface);
-              if (testface.sh == neighborshell.sh) {
-                killseg = 1;
-                spintet = testtet;
-                successbonded = hitbdry = 0;
-                while (true) {
-                  if (fnextself(spintet)) {
-                    if (apex(spintet) == apex(testtet)) {
-                      break; // Rewind, can leave now.
-                    }
-                    if (spintet.tet == testtet.tet) {
-                      continue;
-                    }
-                    if (!infected(spintet)) {
-                      // A live tetrahedron.  The segment survives.
-                      killseg = 0;
-                      tspivot(spintet, testface);
-                      if (testface.sh == dummysh) {
-                        livetet = spintet;
-                        adjustedgering(livetet, CCW);
-                        fnextself(livetet);
-                        tspivot(livetet, testface);
-                      }
-                      if (testface.sh != dummysh) {
-                        findversion(&testface, &spintet);
-                        ssbond(testface, testseg);
-                        successbonded = 1;
-                        break;
-                      }
-                    }
-                  } else {
-                    hitbdry ++;
-                    if(hitbdry >= 2) {
-                      break;
-                    } else {
-                      esym(testtet, spintet);
-                    }
-                  }
-                }
-                if (killseg) {
-                  if (verbose > 1) {
-                    printf("  Deleting subsegment (%d, %d)\n",
-                           pointmark(sorg(testseg)),
-                           pointmark(sdest(testseg)));
-                  }
-                  shellfacedealloc(&subsegs, testseg.sh);
-                } else {
-                  if (!successbonded) {
-                    // Badly, We must insert a nonsolid subface for holding
-                    //   this subsegment; otherwise, it will missing after
-                    //   removing all infected tetrahedra.
-                    insertsubface(&livetet, NONSOLIDFLAG, 1);
-                    tspivot(livetet, testface);
-                    findversion(&testface, &testtet);
-                    ssbond(testface, testseg);
-                  }
-                }
-              }
-            }
-            senextself(neighborshell);
-            enextself(testtet);
-          }
-          shellfacedealloc(&subfaces, neighborshell.sh);
-          if (neighbor.tet != dummytet) {
-            // Make sure the subface doesn't get deallocated again later
-            //  when the infected neighbor is visited.
-            tsdissolve(neighbor);
-          }
-        }
-      } else {                   // The neighbor exists and is not infected.
-        if ((neighborshell.sh == dummysh) || (isnonsolid(neighborshell))) {
-          // There is no subface protecting the neighbor, so
-          //   the neighbor becomes infected.
-          if (verbose > 2) {
-            deadorg = org(neighbor);
-            deaddest = dest(neighbor);
-            deadapex = apex(neighbor);
-            deadoppo = oppo(neighbor);
-            printf("    Marking (%d, %d, %d, %d)\n", pointmark(deadorg),
-             pointmark(deaddest), pointmark(deadapex), pointmark(deadoppo));
-          }
-          infect(neighbor);
-          // Ensure that the neighbor's neighbors will be infected.
-          deadtet = (tetrahedron **) viri.alloc();
-          *deadtet = neighbor.tet;
-        } else {               // The neighbor is protected by a subface.
-          // Remove this tetrahedron from the subface.
-          stdissolve(neighborshell);
-          // The subface becomes a boundary.  Set markers accordingly.
-          if (mark(neighborshell) == 0) {
-            setmark(neighborshell, 1);
-          }
-          norg = org(neighbor);
-          ndest = dest(neighbor);
-          napex = apex(neighbor);
-          if (pointmark(norg) == 0) {
-            setpointmark(norg, 1);
-          }
-          if (pointmark(ndest) == 0) {
-            setpointmark(ndest, 1);
-          }
-          if (pointmark(napex) == 0) {
-            setpointmark(napex, 1);
-          }
-        }
-      }
-    }
-    // Remark the tetrahedron as infected, so it doesn't get added to the
-    //   virus pool again.
-    infect(testtet);
-    virusloop = (tetrahedron **) viri.traverse();
-  }
-
-  if (verbose) {
-    printf("  Deleting marked tetrahedra.\n");
-  }
-  viri.traversalinit();
-  virusloop = (tetrahedron **) viri.traverse();
-  while (virusloop != (tetrahedron **) NULL) {
-    testtet.tet = *virusloop;
-
-    // Check each of the four corners of the tetrahedron for elimination.
-    // To be finished...
-
-    // Record changes in the number of boundary faces, and disconnect
-    //   dead tetrahedra from their neighbors.
-    for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
-      sym(testtet, neighbor);
-      if (neighbor.tet == dummytet) {
-        // There is no neighboring tetrahedron on this face, so this face
-        //   is a boundary face.  This tetrahedron is being deleted, so this
-        //   boundary face is deleted.
-        hullsize--;
-      } else {
-        // Disconnect the tetrahedron from its neighbor.
-        dissolve(neighbor);
-        // There is a neighboring tetrahedron on this face, so this face
-        //   becomes a boundary face when this tetrahedron is deleted.
-        hullsize++;
-      }
-    }
-    // Return the dead tetrahedron to the pool of tetrahedra.
-    tetrahedrondealloc(testtet.tet);
-    virusloop = (tetrahedron **) viri.traverse();
-  }
-  // Empty the virus pool.
-  viri.restart();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// regionplague()    Spread regional attributes and/or volume constraints    //
-//                   (from a .poly file) throughout the mesh.                //
-//                                                                           //
-// This procedure operates in two phases.  The first phase spreads an        //
-// attribute and/or an volume constraint through a (segment-bounded) region. //
-// The tetrahedra are marked to ensure that each tetrahedra is added to the  //
-// virus pool only once, so the procedure will terminate.                    //
-//                                                                           //
-// The second phase uninfects all infected tetrahedra, returning them to     //
-// normal.                                                                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::regionplague(REAL attribute, REAL volume)
-{
-  triface testtet;
-  triface neighbor;
-  tetrahedron **virusloop;
-  tetrahedron **regiontet;
-  face neighborshell;
-  point3d regionorg, regiondest, regionapex, regionoppo;
-
-  if (verbose > 1) {
-    printf("  Marking neighbors of marked tetrahedra.\n");
-  }
-  // Loop through all the infected tetrahedra, spreading the attribute
-  //   and/or volume constraint to their neighbors, then to their neighbors'
-  //   neighbors.
-  viri.traversalinit();
-  virusloop = (tetrahedron **) viri.traverse();
-  while (virusloop != (tetrahedron **) NULL) {
-    testtet.tet = *virusloop;
-    // A tetrahedron is marked as infected by messing with one of its
-    //   vertices(opposite), setting it to an illegal value.  Hence, we
-    //   have to temporarily uninfect this tetrahedron so that we can get
-    //   the proper vertex of this tetrahedron.
-    uninfect(testtet);
-    if (regionattrib) {
-      // Set an attribute.
-      setelemattribute(testtet.tet, eextras, attribute);
-    }
-    if (varvolume) {
-      // Set an volume constraint.
-      setvolumebound(testtet.tet, volume);
-    }
-    if (verbose > 2) {
-      // Assign the tetrahedron an orientation for convenience in
-      //   checking its points.
-      testtet.loc = 0;
-      regionorg = org(testtet);
-      regiondest = dest(testtet);
-      regionapex = apex(testtet);
-      regionoppo = oppo(testtet);
-      printf("    Checking (%d, %d, %d, %d)\n", pointmark(regionorg),
-        pointmark(regiondest), pointmark(regionapex), pointmark(regionoppo));
-    }
-    // Check each of the tetrahedron's four neighbors.
-    for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
-      // Find the neighbor.
-      sym(testtet, neighbor);
-      // Check for a subface between the tetrahedron and its neighbor.
-      tspivot(testtet, neighborshell);
-      // Make sure the neighbor exists, is not already infected, and
-      //   isn't protected by a subface, or is protected by a nonsolid
-      //   subface.
-      if ((neighbor.tet != dummytet) && !infected(neighbor)
-          && ((neighborshell.sh == dummysh) || (isnonsolid(neighborshell)))) {
-        if (verbose > 2) {
-          regionorg = org(neighbor);
-          regiondest = dest(neighbor);
-          regionapex = apex(neighbor);
-          regionoppo = oppo(neighbor);
-          printf("    Marking (%d, %d, %d, %d)\n", pointmark(regionorg),
-            pointmark(regiondest), pointmark(regionapex), pointmark(regionoppo));
-        }
-        // Infect the neighbor.
-        infect(neighbor);
-        // Ensure that the neighbor's neighbors will be infected.
-        regiontet = (tetrahedron **) viri.alloc();
-        *regiontet = neighbor.tet;
-      }
-    }
-    // Remark the tetrahedron as infected, so it doesn't get added to the
-    //   virus pool again.
-    infect(testtet);
-    virusloop = (tetrahedron **) viri.traverse();
-  }
-
-  // Uninfect all tetrahedra.
-  if (verbose > 1) {
-    printf("  Unmarking marked tetrahedra.\n");
-  }
-  viri.traversalinit();
-  virusloop = (tetrahedron **) viri.traverse();
-  while (virusloop != (tetrahedron **) NULL) {
-    testtet.tet = *virusloop;
-    uninfect(testtet);
-    virusloop = (tetrahedron **) viri.traverse();
-  }
-  // Empty the virus pool.
-  viri.restart();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// carveholes()    Find the holes and infect them.  Find the volume          //
-//                 constraints and infect them.  Infect the convex hull.     //
-//                 Spread the infection and kill tetrahedra.  Spread the     //
-//                 volume constraints.                                       //
-//                                                                           //
-// This routine mainly calls other routines to carry out all these functions.//                                                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::carveholes(REAL *holelist, int holes, REAL *regionlist,
-                        int regions)
-{
-  triface searchtet;
-  tetrahedron *tptr;
-  triface *holetets;
-  triface *regiontets;
-  tetrahedron **holetet;
-  tetrahedron **regiontet;
-  enum locateresult intersect;
-  int i;
-
-  if (!(quiet || (noholes && convex))) {
-    printf("Removing unwanted tetrahedra.\n");
-    if (verbose && (holes > 0)) {
-      printf("  Marking holes for elimination.\n");
-    }
-  }
-
-  if ((holes > 0) && !noholes) {
-    // Allocate storage for the tetrahedra in which hole points fall.
-    holetets = (triface *) new triface[holes];
-  }
-
-  if (regions > 0) {
-    // Allocate storage for the tetrahedra in which region points fall.
-    regiontets = (triface *) new triface[regions];
-  }
-
-  // Now, we have to find all the holes and regions BEFORE we infect hull
-  //   and carve the holes, because locate() won't work when there exist
-  //   infect tetrahedra and the tetrahedronlization is no longer convex.
-
-  if ((holes > 0) && !noholes) {
-    // Infect each tetrahedron in which a hole lies.
-    for (i = 0; i < 3 * holes; i += 3) {
-      // Ignore holes that aren't within the bounds of the mesh.
-      if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
-          && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)
-          && (holelist[i + 2] >= zmin) && (holelist[i + 2] <= zmax)) {
-        // Start searching from some tetrahedron on the outer boundary.
-        searchtet.tet = dummytet;
-        searchtet.loc = 0;
-        symself(searchtet);
-        // Ensure that the hole is above the boundary face; otherwise,
-        //   locate() will falsely report that the hole falls within the
-        //   starting tetrahedron.
-        adjustedgering(searchtet, CCW);
-        if (isaboveplane(&searchtet, &holelist[i])) {
-          // Find a tetrahedron that contains the hole.
-          intersect = locate(&holelist[i], &searchtet);
-          if ((intersect != OUTSIDE) && (!infected(searchtet))) {
-            // Record the tetrahedron for processing carve hole.
-            holetets[i / 3] = searchtet;
-          }
-        }
-      }
-    }
-  }
-
-  if (regions > 0) {
-    // Find the starting tetrahedron for each region.
-    for (i = 0; i < regions; i++) {
-      regiontets[i].tet = dummytet;
-      // Ignore region points that aren't within the bounds of the mesh.
-      if ((regionlist[5 * i] >= xmin) && (regionlist[5 * i] <= xmax) &&
-          (regionlist[5 * i + 1] >= ymin) && (regionlist[5 * i + 1] <= ymax) &&
-          (regionlist[5 * i + 2] >= zmin) && (regionlist[5 * i + 2] <= zmax)) {
-        // Start searching from some tetrahedron on the outer boundary.
-        searchtet.tet = dummytet;
-        searchtet.loc = 0;
-        symself(searchtet);
-        // Ensure that the region point above the boundary  face; otherwise,
-        //   locate() will falsely report that the region point falls within
-        //   the starting tetrahedron.
-        adjustedgering(searchtet, CCW);
-        if (isaboveplane(&searchtet, &regionlist[5 * i])) {
-          // Find a tetrahedron that contains the region point.
-          intersect = locate(&regionlist[5 * i], &searchtet);
-          if ((intersect != OUTSIDE) && (!infected(searchtet))) {
-            // Record the tetrahedron for processing after the
-            //   holes have been carved.
-            regiontets[i] = searchtet;
-          }
-        }
-      }
-    }
-  }
-
-  if (((holes > 0) && !noholes) || !convex || (regions > 0)) {
-    // Initialize a pool of viri to be used for holes, concavities,
-    //   regional attributes, and/or regional volume constraints.
-    viri.init(sizeof(tetrahedron *), VIRUSPERBLOCK, POINTER, 0);
-  }
-
-  if (!convex) {
-    // Mark as infected any unprotected tetrahedra on the boundary.
-    //   This is one way by which concavities are created.
-    infecthull();
-  }
-
-  if ((holes > 0) && !noholes) {
-    // Infect the hole tetrahedron.  This is done by marking the
-    //  tetrahedron as infect and including the tetrahedron in
-    //  the virus pool.
-    for (i = 0; i < holes; i++) {
-      infect(holetets[i]);
-      holetet = (tetrahedron **) viri.alloc();
-      *holetet = holetets[i].tet;
-    }
-  }
-
-  if (viri.items > 0) {
-    // Carve the holes and concavities.
-    plague();
-  }
-  // The virus pool should be empty now.
-
-  if (regions > 0) {
-    if (!quiet) {
-      if (regionattrib) {
-        if (varvolume) {
-          printf("Spreading regional attributes and volume constraints.\n");
-        } else {
-          printf("Spreading regional attributes.\n");
-        }
-      } else {
-        printf("Spreading regional volume constraints.\n");
-      }
-    }
-    if (regionattrib && !refine) {
-      // Assign every tetrahedron a regional attribute of zero.
-      tetrahedrons.traversalinit();
-      tptr = tetrahedrontraverse();
-      while (tptr != (tetrahedron *) NULL) {
-        setelemattribute(tptr, eextras, 0.0);
-        tptr = tetrahedrontraverse();
-      }
-    }
-    for (i = 0; i < regions; i++) {
-      if (regiontets[i].tet != dummytet) {
-        // Make sure the tetrahedron under consideration still exists.
-        //   It may have been eaten by the virus.
-        if (!isdead(&(regiontets[i]))) {
-          // Put one tetrahedron in the virus pool.
-          infect(regiontets[i]);
-          regiontet = (tetrahedron **) viri.alloc();
-          *regiontet = regiontets[i].tet;
-          // Apply one region's attribute and/or volume constraint.
-          regionplague(regionlist[5 * i + 3], regionlist[5 * i + 4]);
-          // The virus pool should be empty now.
-        }
-      }
-    }
-    if (regionattrib && !refine) {
-      // Note the fact that each tetrahedron has an additional attribute.
-      eextras++;
-    }
-  }
-
-  // Free up memory.
-  if (((holes > 0) && !noholes) || !convex || (regions > 0)) {
-    viri.deinit();
-  }
-  if ((holes > 0) && !noholes) {
-    delete [] holetets;
-  }
-  if (regions > 0) {
-    delete [] regiontets;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Carving out Holes and Concavities Routines.                               //
-///////////////////////////////////////////////////////////////////////////////
diff --git a/Tetgen/defines.h b/Tetgen/defines.h
deleted file mode 100644
index 289dec79ae..0000000000
--- a/Tetgen/defines.h
+++ /dev/null
@@ -1,175 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// defines.h    Header file for all the Tetgen source files needed.          //
-//              Defines switches (Optional) used at compilation time.        //
-//              Includes the most general used head files for all C/C++      //
-//              program code needed. Defines marcos used throughout all      //
-//              the source files.                                            //
-//                                                                           //
-// Tetgen Version 1.0 beta                                                   //
-// July, 2001                                                                //
-//                                                                           //
-// Si hang                                                                   //
-// Email: sihang@weboo.com                                                   //
-// http://www.weboo.com/sh/tetgen.htm                                        //
-//                                                                           //
-// You are free to use, copy and modify the sources under certain            //
-// circumstances, provided this copyright notice remains intact.             //
-// See the file LICENSE for details.                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef definesH
-#define definesH
-
-// If yours is not a Unix system,  define the  NO_TIMER  compiler  switch to
-//   remove the Unix-specific timing code.
-
-// #define NO_TIMER
-
-// Define to disable assertions. Generally the assert() operater only be
-//   used in developping stage, to catch the casual mistakes in programming.
-
-// #define NDEBUG
-
-// To insert lots of self-checks for internal errors, define the SELF_CHECK
-//   symbol.  This will slow down the program significantly.  It is best to
-//   define the symbol using the -DSELF_CHECK compiler switch, but you could
-//   write "#define SELF_CHECK" below.  If you are modifying this code, I
-//   recommend you turn self-checks on.
-
-// #define SELF_CHECK
-
-// For single precision ( which will save some  memory and  reduce paging ),
-//   define the symbol  SINGLE  by using the  -DSINGLE compiler switch or by
-//   writing "#define SINGLE" below.
-//
-// For double precision ( which will allow you to refine meshes to a smaller
-//   edge length), leave SINGLE undefined.
-//
-// Double precision  uses  more  memory,  but improves the resolution of the
-//   meshes you can  generate with Triangle.  It also reduces the likelihood
-//   of a  floating  exception due to overflow.   Finally, it is much faster
-//   than  single precision on  64-bit  architectures like the DEC Alpha.  I
-//   recommend double precision unless you want to generate a mesh for which
-//   you do not have enough memory.
-
-// #define SINGLE
-
-#ifdef SINGLE
-  #define REAL float
-#else
-  #define REAL double
-#endif 	// not defined SINGLE
-
-// numbers that speaks for theirself.
-
-#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
-
-#define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
-
-#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
-
-// For efficiency, a variety of data structures are allocated in bulk.  The
-//   following constants determine how many of each structure is allocated
-//   at once.
-
-#define TRIPERBLOCK 4092           // Number of triangles allocated at once.
-#define SHELLEPERBLOCK 508       // Number of shell edges allocated at once.
-#define POINTPERBLOCK 4092            // Number of points allocated at once.
-#define VIRUSPERBLOCK 1020   // Number of virus triangles allocated at once.
-#define TETPERBLOCK 8188        // Number of tetrahedrons allocated at once.
-#define SUBFACEPERBLOCK 1020        // Number of subfaces allocated at once.
-#define SUBSEGPERBLOCK 1020      // Number of subsegments allocated at once.
-#define POINTPERBLOCK 4092            // Number of points allocated at once.
-// Number of encroached segments allocated at once.
-#define BADSEGMENTPERBLOCK 252
-// Number of encroached segments allocated at once.
-#define BADSHELLFACEPERBLOCK 508
-// Number of skinny triangles allocated at once.
-#define BADTRIPERBLOCK 4092
-// Number of skinny tetrahedras allocated at once.
-#define BADTETPERBLOCK 8188
-
-// The point marker DEADPOINT  is an arbitrary number chosen large enough to
-//   (hopefully) not conflict with user boundary markers.  Make sure that it
-//   is small enough to fit into your machine's integer size.
-
-#define DEADPOINT -1073741824
-
-// The nonsolid flag  NONSOLIDFLAG is an arbitrary number chosen large enou-
-//   gh to (hopefully)not conflict with user boundary markers.Make sure that
-//   it is small enough to fit into your machine's integer size.
-
-#define NONSOLIDFLAG  -1342177279
-
-// Maximum number of characters in a file name (including the null).
-
-#ifndef FILENAMESIZE
-  #define FILENAMESIZE 512
-#endif
-
-// Maximum number of characters in a line  read  from a file ( including the
-//   null).
-
-#ifndef INPUTLINESIZE
-  #define INPUTLINESIZE 512
-#endif
-
-// Constant for algorithms based on random sampling.  This constant
-//   have been chosen empirically to optimize its respective algorithms.
-
-// Used for the point location scheme of Mucke, Saias, and Zhu, to decide
-//   how large a random sample of triangles to inspect.
-#define SAMPLEFACTOR 11
-
-// Here is the most general used head files for all C/C++ program code
-//   needed.
-
-#include <stdio.h>                  // standard IO: FILE, NULL (*), EOF, ...
-#include <stdlib.h>        // standard lib: abort(), system(), getenv(), ...
-#include <string.h>        // declarations for string manipulation functions.
-#include <math.h>                     // math lib: sin(), sqrt(), pow(), ...
-#include <assert.h>
-#ifndef NO_TIMER
-  #include <sys/time.h>
-#else
-  #include <time.h>            // definitions/declarations for time routines.
-#endif // defined NO_TIMER
-#ifdef INTEL_MSC_TURBOC
-  #include <float.h>                 // some compilers will not need float.h.
-#endif // defined INTEL_MSC_TURBOC
-
-// If you will compile and run this code on Intel CPUs, Maybe there is some
-//   choices must be made by user to correctly execute Jonathan Schewck's
-//   code for arbitrary floating-point precision arithmetic and robust geom-
-//   etric predicates.  For more detail please see:
-//
-//            http://www.cs.cmu.edu/~quake/robust.pc.html.
-
-// If you use Microsoft C/C++ or TOURB C/C++ or BORLAND C/C++, define the
-//   symbol INTEL_MSC_TURBOC  by using -DINTEL_MSC_TURBOC compiler switch
-//   or by writing #define INTEL_MSC_TURBOC as follows.
-
-// #define INTEL_MSC_TURBOC
-
-// If you use gcc running under Linux, define the symbol INTEL_GCC_LINUX. Be
-//   sure to undefine the symbol INTEL_MSC_TURBOC.
-
-// #define INTEL_GCC_LINUX
-
-// If you use gcc but not running under linux, use the following symbol. Be
-//   sure to undefine the symbol INTEL_MSC_TURBOC and INTEL_GCC_LINUX.
-
-// #define INTEL_GCC
-
-// Routines for Arbitrary Precision Floating-point Arithmetic and Fast
-//   Robust Geometric Predicates.
-
-void exactinit();
-REAL orient2d(REAL* pa, REAL* pb, REAL* pc);
-REAL incircle(REAL* pa, REAL* pb, REAL* pc, REAL* pd);
-REAL orient3d(REAL* pa, REAL* pb, REAL* pc, REAL* pd);
-REAL insphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe);
-
-#endif // #ifndef definesH
diff --git a/Tetgen/linklist.cpp b/Tetgen/linklist.cpp
deleted file mode 100644
index 24d9aa23cc..0000000000
--- a/Tetgen/linklist.cpp
+++ /dev/null
@@ -1,1149 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// linklist.cpp    Implement link, list, queue, stack, memorypool data types //
-//                 which declared in linklist.h.                             //
-//                                                                           //
-// Si hang                                                                   //
-// Email: sihang@weboo.com                                                   //
-// http://www.weboo.com/sh/tetgen.htm                                        //
-//                                                                           //
-// Please see linklist.h for a detail description.                           //
-//                                                                           //
-// You are free to use, copy and modify the sources under certain            //
-// circumstances, provided this copyright notice remains intact.             //
-// See the file LICENSE for details.                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-#include <stdio.h>                             // Defined function printf().
-#include <stdlib.h>                             // Defined function qsort().
-#include <string.h>                 // Defined function strncmp(), strcmp().
-#include "linklist.h"
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Predefined linar order functions for most primitive data types.           //                                                               //
-//                                                                           //
-// Return -1 if x < y; Return +1 if x > y; Return Zero if x == y.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int compare2ints(const void* pi1, const void* pi2)
-{
-  if(*(int*)pi1 < *(int*)pi2) {
-    return -1;
-  } else if(*(int*)pi1 > *(int*)pi2) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-int compare2unsignedlongs(const void* pl1, const void* pl2)
-{
-  if(*(unsigned long*)pl1 < *(unsigned long*)pl2) {
-    return -1;
-  } else if(*(unsigned long*)pl1 > *(unsigned long*)pl2) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-int compare2chars(const void* pc1, const void* pc2)
-{
-  if(*(char*)pc1 < *(char*)pc2) {
-    return -1;
-  } else if(*(char*)pc1 > *(char*)pc2) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-int compare2strings(const void* pstr1, const void* pstr2)
-{
-  return strcmp(*(char**)pstr1, *(char**)pstr2);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// setpredefineddatatype()                                                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void setpredefineddatatype(char* strdatatype, int *itembytes, compfunc *comp)
-{
-  if (strncmp(strdatatype, "int", 3) == 0) {
-    *itembytes = sizeof(int);
-    *comp = compare2ints;
-  } else if (strncmp(strdatatype, "unsigned long", 13) == 0) {
-    *itembytes = sizeof(unsigned long);
-    *comp = compare2unsignedlongs;
-  } else if (strncmp(strdatatype, "char", 4) == 0) {
-    *itembytes = sizeof(char);
-    *comp = compare2chars;
-  } else if (strncmp(strdatatype, "string", 6) == 0) {
-    *itembytes = sizeof(char*);
-    *comp = compare2strings;
-  } else if (strncmp(strdatatype, "point", 5) == 0) {
-    // This type is for my tetrahedra program used, actually type is REAL*.
-    *itembytes = sizeof(unsigned long);
-    *comp = compare2unsignedlongs;
-  } else {
-    printf("Sorry, this data type %s is unknown by list now.\n", strdatatype);
-    assert(0);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// class list implementation                                                 //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-list::list(char* strdatatype, int _maxitems, int _expandsize)
-{
-  int bytesofint = sizeof(int);
-
-  assert(strdatatype && (_maxitems > 0) && (_expandsize > 0));
-
-  comp = (compfunc) NULL;
-  setpredefineddatatype(strdatatype, &itembytes, &comp);
-  assert(comp && (itembytes > 0));
-
-  if(itembytes % bytesofint) {
-    itemints  = itembytes / bytesofint + 1;
-  } else {
-    itemints  = itembytes / bytesofint;
-  }
-
-  maxitems = _maxitems;
-  expandsize = _expandsize;
-  base = new void*[maxitems * itemints];
-  items = 0;
-}
-
-list::list(int _itembytes, int _maxitems, int _expandsize)
-{
-  assert((_itembytes > 0) && (_maxitems > 0) && (_expandsize > 0));
-
-  int bytesofint = sizeof(int);
-  itembytes = _itembytes;
-  if(itembytes % bytesofint) {
-    itemints  = itembytes / bytesofint + 1;
-  } else {
-    itemints  = itembytes / bytesofint;
-  }
-  comp = NULL;
-
-  maxitems = _maxitems;
-  expandsize = _expandsize;
-  base = new void*[maxitems * itemints];
-  items = 0;
-}
-
-list::~list()
-{
-  delete [] base;
-}
-
-list::list(list& src)
-{
-  assert(src.items > 0);
-  itembytes = src.itembytes;
-  itemints = src.itemints;
-  maxitems = src.maxitems;
-  expandsize = src.expandsize;
-  items = src.items;
-  base = new void*[maxitems * itemints];
-  memcpy(base, src.base, items * itemints * sizeof(int));
-}
-
-void* list::operator[](int index)
-{
-  assert(index >= 0 && index < items);
-  return (void*) (base + index * itemints);
-}
-
-void* list::getitem(int index)
-{
-  assert(index >= 0 && index < items);
-  return (void*) (base + index * itemints);
-}
-
-void* list::alloc()
-{
-  if (items == maxitems) {
-    // No space available, need re-allocate.
-    void **newbase = new void*[(maxitems + expandsize) * itemints];
-    memcpy(newbase, base, maxitems * itemints * sizeof(int));
-    delete [] base;
-    base = newbase;
-    maxitems += expandsize;
-  }
-  items++;
-  return (base + (items - 1) * itemints);
-}
-
-void list::append(void* newitem)
-{
-  if (items == maxitems) {
-    // No space available, need re-allocate.
-    void **newbase = new void*[(maxitems + expandsize) * itemints];
-    memcpy(newbase, base, maxitems * itemints * sizeof(int));
-    delete [] base;
-    base = newbase;
-    maxitems += expandsize;
-  }
-  memcpy((void*) (base + items * itemints), newitem, itembytes);
-  items++;
-}
-
-// Insert an item before index 'befireindex'. 'beforeindex' should be a
-//   value from 1 to listlength. If 'beforeindex' == listlength, insert
-//   operation is equal to append operation.
-
-void list::insert(int beforeindex, void* insertitem)
-{
-  assert(beforeindex > 0 && beforeindex <= items);
-  if (beforeindex == items) {
-    append(insertitem);
-    return;
-  }
-  if (items == maxitems) {
-    // No space available, need re-allocate.
-    void **newbase = new void*[(maxitems + expandsize) * itemints];
-    memcpy(newbase, base, maxitems * itemints * sizeof(int));
-    delete [] base;
-    base = newbase;
-    maxitems += expandsize;
-  }
-  // Do block move.
-  memmove((void*) (base + (beforeindex + 1) * itemints),   // dest
-          (void*) (base + beforeindex * itemints),         // src
-          (items - beforeindex) * itemints * sizeof(int)); // size in bytes
-  // Insert the insertitem.
-  memcpy((void*) (base + beforeindex * itemints), insertitem, itembytes);
-  items++;
-}
-
-// Delete an item from the list. 'deleteindex' should be a value from
-//   0 to listlength-1.
-
-void list::del(int deleteindex)
-{
-  assert(deleteindex >= 0 && deleteindex < items);
-  if (deleteindex != (items - 1)) {
-    // Do block move.
-    memmove((void*) (base + deleteindex * itemints),       // dest
-            (void*) (base + (deleteindex + 1) * itemints), // src
-            (items - deleteindex - 1) * itemints * sizeof(int));
-  }
-  items--;
-}
-
-// To remove a specific item from the list when its index is unknown. The
-//   value returned is the index of the item in the Items array before it
-//   was removed. After an item is removed, all the items that follow it
-//   are moved up in index position and the Count(items) is reduced by one.
-// If the Items array contains more than one copy of the pointer, only the
-//   first copy is deleted.
-
-int list::remove(void *removeitem)
-{
-  int index = hasitem(removeitem);
-  if (index != -1) {
-    del(index);
-  }
-  return index;
-}
-
-// Return 0 to listlength - 1 if 'checkitem' existed in list,
-// Return -1 if 'checkitem' not exist.
-
-int list::hasitem(void* checkitem)
-{
-  int i;
-
-  for (i = 0; i < items; i ++) {
-    if (comp) {
-      if ((*comp)((void*)(base + i * itemints), checkitem) == 0) return i;
-    } else {
-      if (compare2ints((void*)(base + i * itemints), checkitem) == 0) return i;
-    }
-  }
-  return -1;
-}
-
-// Return 0 to listlength - 1 if 'finditem' existed in list,
-// Return -1 if 'finditem' not exist.
-
-int list::indexof(void* finditem)
-{
-  return hasitem(finditem);
-}
-
-// Performs a QuickSort on the list based on the comparison function.
-
-void list::sort()
-{
-  qsort((void*)base, (size_t)items, (size_t)(itemints * sizeof(int)), comp);
-}
-
-void list::simplify()
-{
-  compfunc compare;
-  void *pathitem, *checkitem;
-  int i, j;
-
-  if(comp) {
-    compare = (compfunc) comp;
-  } else {
-    compare = (compfunc) compare2ints;  // Use default compare function.
-  }
-
-  for (i = 0; i < items; i++) {
-    pathitem = (*this)[i];
-    for (j = i + 1; j < items; j++) {
-      checkitem = (*this)[j];
-      if ((*compare)(pathitem, checkitem) == 0) {
-        del(j);
-        j--;
-      }
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// class list implementation                                                 //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// class link implementation                                                 //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                     Constructor, Destructor                               //
-///////////////////////////////////////////////////////////////////////////////
-
-link::link(char* strdatatype, int itemcount)
-{
-  int _itembytes;
-
-  assert(strdatatype && (itemcount > 0));
-
-  _itembytes = 0;
-  comp = (compfunc) NULL;
-  setpredefineddatatype(strdatatype, &_itembytes, &comp);
-  assert(comp && (_itembytes > 0));
-
-  poolinit(_itembytes, itemcount);
-  init();
-}
-
-link::link(int _itembytes, int itemcount)
-{
-  assert((_itembytes > 0) && (itemcount > 0));
-
-  poolinit(_itembytes, itemcount);
-  init();
-  comp = NULL;
-}
-
-link::~link()
-{
-  while (firstblock != (void**)NULL) {
-    nowblock = (void **) *firstblock;
-    delete [] firstblock;
-    firstblock = nowblock;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                        Member Functions                                   //
-///////////////////////////////////////////////////////////////////////////////
-
-void link::poolinit(int bytes, int itemcount)
-{
-  itembytes = bytes;
-  itemsperblock = itemcount;
-
-  int bytesofint = sizeof(int);
-  if(itembytes % bytesofint)
-    itemints  = itembytes / bytesofint + 1;
-  else
-    itemints  = itembytes / bytesofint;
-  // In double link, each items need 2 pointer spaces. So actually one
-  //   item's total space is: itemints + 2 (ints).
-  firstblock = new void*[1 + (itemints + 2) * itemsperblock];
-  *firstblock = (void*) NULL;
-  maxitems = itemsperblock;
-  poolrestart();
-}
-
-void link::poolrestart()
-{
-  // Set the currently active block.
-  nowblock = firstblock;
-  // Find the first item in the pool.  Increment by the size of (void *).
-  nextitem = (void*) (nowblock + 1);
-  // There are lots of unallocated items left in this block.
-  unallocateditems = itemsperblock;
-  // The stack of deallocated items is empty.
-  deaditemstack = (void*) NULL;
-}
-
-void* link::alloc()
-{
-  void *newitem;
-  void **newblock;
-
-  // First check the linked list of dead items.  If the list is not
-  //   empty, allocate an item from the list rather than a fresh one.
-  if (deaditemstack != (void *) NULL) {
-    newitem = deaditemstack;               // Take first item in list.
-    deaditemstack = * (void **) deaditemstack;
-  } else {
-    // Check if there are any free items left in the current block.
-    if (unallocateditems == 0) {
-      // Check if another block must be allocated.
-      if (*nowblock == (void *) NULL) {
-        // Allocate a new block of items, pointed to by the previous block.
-        newblock = new void*[1 + (itemints + 2) * itemsperblock];
-        *nowblock = (void *) newblock;
-        // The next block pointer is NULL.
-        *newblock = (void *) NULL;
-        maxitems += itemsperblock;
-      }
-      // Move to the new block.
-      nowblock = (void **) *nowblock;
-      // Find the first item in the block.
-      //   Increment by the size of (VOID *).
-      nextitem = (void *)(nowblock + 1);
-      // There are lots of unallocated items left in this block.
-      unallocateditems = itemsperblock;
-    }
-    // Allocate a new item.
-    newitem = nextitem;
-    // Advance `nextitem' pointer to next free item in block.
-    nextitem = (void *) ((void **) nextitem + itemints + 2);
-    unallocateditems--;
-  }
-
-  return newitem;
-}
-
-void link::dealloc(void* dyingitem)
-{
-  // Push freshly killed item onto stack.
-  *((void **) dyingitem) = deaditemstack;
-  deaditemstack = dyingitem;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                          Member Functions                                 //
-///////////////////////////////////////////////////////////////////////////////
-
-void link::init()
-{
-  head = (void**) alloc();
-  tail = (void**) alloc();
-  *head = (void*) tail;
-  *(head + 1) = NULL;
-  *tail = NULL;
-  *(tail + 1) = (void*) head;
-  nextlinkitem = *head;
-  curpos = 1;
-  items = 0;
-}
-
-int link::move(int i)
-{ // i > 0 move forward, i < 0 move backward.
-  void** nownode = (void**)nextlinkitem;
-  if(i > 0) {
-    int j = 0;
-    while((j < i) && *nownode) {
-      nownode = (void**)*nownode;
-      j++;
-    }
-    if((j > i) || !(*nownode)) return 0;
-    nextlinkitem = (void*)nownode;
-    curpos += i;
-  } else if(i < 0) {
-    int j = 0;
-    i = -i;
-    while((j < i) && *(nownode+1)) {
-      nownode = (void**)*(nownode+1);
-      j++;
-    }
-    if((j > i) || !(*(nownode+1))) return 0;
-    nextlinkitem = (void*)nownode;
-    curpos -= i;
-  }
-  return 1;
-}
-
-int link::locate(int i)
-{
-  if((i == 0) || (i > items)) return 0;
-
-  int headdist = i - 1, taildist = items - i, curdist = i - curpos;
-  int abscurdist = curdist >= 0 ? curdist : -curdist;
-
-  int mindist;
-  if(headdist > taildist) { // 1000
-    if(taildist > abscurdist) {
-      mindist = curdist;
-    } else {
-      // taildist <= abs(curdist)
-      mindist = -taildist;
-      goend();
-    }
-  } else { // 1000 else
-    // headdist <= taildist
-    if(headdist > abscurdist) {
-      mindist = curdist;
-    } else {
-      // headdist <= abs(curdist)
-      mindist = headdist;
-      rewind();
-    }
-  } // 1000
-
-  return move(mindist);
-}
-
-void link::add(void* elem)
-{
-  void **newnode = tail;
-  memcpy((void*)(newnode + 2), elem, itembytes);
-  tail = (void**) alloc();
-  // To do init jobs after 'new' operater
-  for(int i = 0; i < itemints + 2; i ++) {
-    *((int *) (tail + i))  = 0;
-  }
-  *tail = NULL;
-  *newnode = (void*) tail;
-  *(tail + 1) = (void*) newnode;
-  items++;
-}
-
-void link::insert(int index, void* elem)
-{
-  if(!locate(index)) assert(0);
-  void **nownode = (void**) nextlinkitem;
-
-  // Insert a node before 'nownode'.
-  void **newnode = (void**) alloc();
-  // To do init jobs after 'new' operater
-  for(int i = 0; i < itemints + 2; i ++) {
-    *((int *) (newnode + i))  = 0;
-  }
-  memcpy((void*)(newnode + 2), elem, itembytes);
-
-  *(void**)(*(nownode + 1)) = (void*)newnode;
-  *newnode = (void*) nownode;
-  *(newnode + 1) = *(nownode+1);
-  *(nownode + 1) = (void*)newnode;
-  items++;
-
-  nextlinkitem = (void*) newnode;
-}
-
-void link::del(int index)
-{
-  if(!locate(index)) assert(0);
-  void **deadnode = (void**)nextlinkitem;
-
-  // now delete the nownode
-  void **nextnode = (void**)*deadnode;
-  void **prevnode = (void**)*(deadnode + 1);
-  *prevnode = (void*)nextnode;
-  *(nextnode + 1) = (void*)prevnode;
-
-  dealloc((void*) deadnode);
-  items--;
-
-  nextlinkitem = (void*) nextnode;
-}
-
-void* link::getitem()
-{
-  if (nextlinkitem == (void*)tail) return NULL;
-  void **nownode = (void**)nextlinkitem;
-  nextlinkitem = *nownode;
-  curpos += 1;
-  return (void*)(nownode + 2);
-}
-
-void* link::getnitem(int n)
-{
-  if(!locate(n)) return NULL;
-  return (void*)((void**)nextlinkitem + 2);
-}
-
-void link::setnitem(int n, void* elem)
-{
-  assert(locate(n));
-  void **nownode = (void**) nextlinkitem;
-  // now set the nownode's data field with the new data
-  memcpy((void*)(nownode + 2), elem, itembytes);
-}
-
-int link::hasitem(void* testitem)
-{
-  void *pathitem;
-  int count;
-
-  rewind();
-  pathitem = getitem();
-  count = 0;
-  while (pathitem) {
-    count ++;
-    if (comp) {
-      if ((*comp)(pathitem, testitem) == 0) return count;
-    } else {
-      if (compare2ints(pathitem, testitem) == 0) return count;
-    }
-    pathitem = getitem();
-  }
-  return -1;
-}
-
-void link::sort()
-{
-  compfunc compare;
-  if(comp) {
-    compare = (compfunc) comp;
-  } else {
-    compare = (compfunc) compare2ints;  // Use default compare function.
-  }
-
-  unsigned char *table;
-  table = new unsigned char[items * itembytes];
-  rewind();
-  void *pathitem = getitem();
-  int count = 0;
-  while(pathitem) {
-    memcpy(&table[count * itembytes], pathitem, itembytes);
-    pathitem = getitem();
-    count ++;
-  }
-  if(count != items) assert(0);
-
-  qsort (table, (size_t) items, (size_t) itembytes, compare);
-
-  clear();
-  for(int i = 0; i < count; i ++) {
-    add(&table[i * itembytes]);
-  }
-  delete [] table;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// class link implementation                                                 //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// class queue implementation                                                //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-int queue::get(void* retitem)
-{
-  void* tmpitem = link::getnitem(1);
-  if(tmpitem == NULL) return 0;
-  memcpy(retitem, tmpitem, itembytes);
-  link::del(1);
-  return 1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// class queue implementation                                                //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// class stack implementation                                                //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                     Constructor, Destructor                               //
-///////////////////////////////////////////////////////////////////////////////
-
-stack::stack(char* strdatatype, int _itemsperblock)
-{
-  int _itembytes;
-
-  assert(strdatatype && _itemsperblock > 0);
-
-  _itembytes = 0;
-  comp = (compfunc) NULL;
-  setpredefineddatatype(strdatatype, &_itembytes, &comp);
-  assert(comp && (_itembytes > 0));
-
-  init(_itembytes, _itemsperblock);
-}
-
-stack::stack(int _itembytes, int _itemsperblock)
-{
-  assert(_itembytes > 0 && _itemsperblock > 0);
-  init(_itembytes, _itemsperblock);
-  comp = NULL;
-}
-
-stack::~stack()
-{
-  while (firstblock != (void**)NULL) {
-    nowblock = (void **) *firstblock;
-    delete [] firstblock;
-    firstblock = nowblock;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                        Member Functions                                   //
-///////////////////////////////////////////////////////////////////////////////
-
-void stack::init(int bytes, int _itemsperblock)
-{
-  int bytesofint = sizeof(int);
-  itembytes = bytes;
-  if(itembytes % bytesofint)
-    itemints  = itembytes / bytesofint + 1;
-  else
-    itemints  = itembytes / bytesofint;
-  itemsperblock = _itemsperblock;
-  firstblock = new void*[2 + itemints*itemsperblock];
-  *firstblock = (void*) NULL;
-  *(firstblock + 1) = (void*) NULL;
-  restart();
-}
-
-void stack::restart()
-{
-  // clear items count
-  items = 0;
-  // find the maxitem's count we can save now.
-  maxitems = itemsperblock;
-  nowblock = firstblock;
-  while(*nowblock != (void*) NULL) {
-    maxitems += itemsperblock;
-    nowblock = (void**) *nowblock;
-  }
-  // Set the currently active block.
-  nowblock = firstblock;
-  // Find the first item in the pool.  Increment by the size of (void *).
-  top = (void*)(nowblock + 2);
-  // There are lots of unused items left in this block.
-  unuseditems = itemsperblock;
-}
-
-void stack::push(void* newitem)
-{
-  if( unuseditems == 0 ) {
-    // nowblock is out of space
-    if( items < maxitems ) {
-      // next block is available, just move to it
-      nowblock = (void**)*nowblock;
-    } else {
-      // we need allocte an new block for extend allocating space
-      void **newblock = new void*[2 + itemints*itemsperblock];
-      // set pointer to newblock and point back
-      *nowblock = (void*) newblock;
-      *newblock = (void*) NULL;
-      *(newblock + 1) = (void*) nowblock;
-      // move to newblock
-      nowblock = newblock;
-      // don't forget to extend maxitems
-      maxitems += itemsperblock;
-    }
-    top = (void*)(nowblock + 2);
-    // There are lots of unused items left in this block.
-    unuseditems = itemsperblock;
-  }
-  // save newitem
-  memcpy(top, newitem, itembytes);
-  items ++;
-  unuseditems --;
-  // move top to next available item
-  if(unuseditems) top = (void *) ((void **) top + itemints);
-}
-
-void* stack::topitem()
-{
-  if(items == 0) return NULL;
-  void* retitem;
-  if (unuseditems == 0) {
-    // this time need attention, because last Push() operator didn't move
-    // top to next block, so top is still point to the last pushed item
-    retitem = top;
-  } else if (unuseditems == itemsperblock) {
-    // this time need move back a block
-    void** prevblock = (void**)*(nowblock + 1);
-    // top is point to the last item of the block
-    retitem = (void*)(prevblock + 2 + itemints * (itemsperblock - 1));
-  } else {
-    // normal case in a block
-    retitem = (void*) ((void**) top - itemints);
-  }
-  return retitem;
-}
-
-int stack::pop(void* retitem)
-{
-  if(items == 0) return 0;
-  if(unuseditems == 0) {
-    // this time need attention, because last Push() operator didn't move
-    // top to next block, so top is still point to the last pushed item
-  } else if(unuseditems == itemsperblock){
-    // this time need move back a block
-    nowblock = (void**)*(nowblock + 1);
-    // top is point to the last item of the block
-    top = (void*)(nowblock + 2 + itemints * (itemsperblock - 1));
-    unuseditems = 0;
-  } else {
-    // normal case in a block
-    top = (void*) ((void**) top - itemints);
-  }
-  // get wanted item
-  memcpy(retitem, top, itembytes);
-  items --;
-  unuseditems ++;
-  return 1;
-}
-
-int stack::hasitem(void* testitem)
-{
-  void** pathblock = firstblock;
-  void* pathitem = (void*) (pathblock + 2);
-  int pathitemsleft = itemsperblock;
-
-  while(pathitem != top) {
-    // Check whether any untraversed items remain in the current block.
-    if (pathitemsleft == 0) {
-      // Find the next block.
-      pathblock = (void **) *pathblock;
-      // Find the first item in the block.  Increment by the size of (VOID *).
-      pathitem = (void *) (pathblock + 2);
-      // Set the number of items left in the current block.
-      pathitemsleft = itemsperblock;
-    }
-    if (comp) {
-      if ((*comp)(pathitem, testitem) == 0) return 1;
-    } else {
-      if (compare2ints(pathitem, testitem) == 0) return 1;
-    }
-    // Find the next item in the block.
-    pathitem = (void*) ((void**) pathitem + itemints);
-    pathitemsleft--;
-  }
-  return -1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// class stack implementation                                                //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// class memorypool implementation                                           //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-memorypool::memorypool()
-{
-  firstblock = nowblock = (void**) NULL;
-  nextitem = (void*) NULL;
-  deaditemstack = (void*) NULL;
-  pathblock = (void**) NULL;
-  pathitem = (void*) NULL;
-  itemwordtype = POINTER;
-  alignbytes = 0;
-  itembytes = itemwords = 0;
-  itemsperblock = 0;
-  items = maxitems = 0;
-  unallocateditems = 0;
-  pathitemsleft = 0;
-}
-
-memorypool::memorypool(int bytecount, int itemcount, enum wordtype wtype,
-  int alignment)
-{
-  assert(bytecount > 0 && itemcount > 0);
-  init(bytecount, itemcount, wtype, alignment);
-}
-
-memorypool::~memorypool()
-{
-  while (firstblock != (void **) NULL) {
-    nowblock = (void **) *(firstblock);
-    delete [] firstblock;
-    firstblock = nowblock;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// init()   Initialize a pool of memory for allocation of items.             //
-//                                                                           //
-// This routine initializes the machinery for allocating items.  A `pool' is //
-// created whose records have size at least `bytecount'. Items will be allo- //
-// cated in `itemcount'-item blocks. Each item is assumed to be a collection //
-// of words, and either pointers or floating-point values are assumed to be  //
-// the "primary" word type.  (The "primary" word type is used to determine   //
-// alignment of items.)  If `alignment' isn't zero, all items will be `alig- //
-// nment'-byte aligned in memory.  `alignment' must be either a multiple or  //
-// a factor of the primary word size; powers of two are safe. `alignment' is //
-// normally used to create a few unused bits at the bottom  of each item's   //
-// pointer, in which information may be stored.                              //
-//                                                                           //
-//  Don't change this routine unless you understand it.                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void memorypool::init(int bytecount, int itemcount, enum wordtype wtype,
-  int alignment)
-{
-  int wordsize;
-
-  // Initialize values in the pool.
-  itemwordtype = wtype;
-  wordsize = (itemwordtype == POINTER) ? sizeof(void *) : sizeof(REALTYPE);
-  // Find the proper alignment, which must be at least as large as:
-  //   - The parameter `alignment'.
-  //   - The primary word type, to avoid unaligned accesses.
-  //   - sizeof(void *), so the stack of dead items can be maintained
-  //       without unaligned accesses.
-  if (alignment > wordsize) {
-    alignbytes = alignment;
-  } else {
-    alignbytes = wordsize;
-  }
-  if (sizeof(void *) > alignbytes) {
-    alignbytes = sizeof(void *);
-  }
-  itemwords = ((bytecount + alignbytes - 1) / alignbytes)
-              * (alignbytes / wordsize);
-  itembytes = itemwords * wordsize;
-  itemsperblock = itemcount;
-
-  // Allocate a block of items.  Space for `itemsperblock' items and one
-  //   pointer (to point to the next block) are allocated, as well as space
-  //   to ensure alignment of the items.
-  firstblock = (void**)
-    (new BYTE[itemsperblock * itembytes + sizeof(void *) + alignbytes]);
-  // Set the next block pointer to NULL.
-  *firstblock = (void *) NULL;
-  restart();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// restart()   Deallocate all items in a pool.                               //
-//                                                                           //
-// The pool is returned to its starting state, except that no memory is      //
-// freed to the operating system.  Rather, the previously allocated blocks   //
-// are ready to be reused.                                                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void memorypool::restart()
-{
-  unsigned long alignptr;
-
-  items = 0;
-  maxitems = 0;
-
-  // Set the currently active block.
-  nowblock = firstblock;
-  // Find the first item in the pool.  Increment by the size of (void *).
-  alignptr = (unsigned long) (nowblock + 1);
-  // Align the item on an `alignbytes'-byte boundary.
-  nextitem = (void *)
-    (alignptr + (unsigned long) alignbytes
-     - (alignptr % (unsigned long) alignbytes));
-  // There are lots of unallocated items left in this block.
-  unallocateditems = itemsperblock;
-  // The stack of deallocated items is empty.
-  deaditemstack = (void *) NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// deinit()   Free to the operating system all memory taken by a pool.       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void memorypool::deinit()
-{
-  while (firstblock != (void **) NULL) {
-    nowblock = (void **) *(firstblock);
-    delete [] firstblock;
-    firstblock = nowblock;
-  }
-
-  firstblock = nowblock = (void**) NULL;
-  nextitem = (void*) NULL;
-  deaditemstack = (void*) NULL;
-  pathblock = (void**) NULL;
-  pathitem = (void*) NULL;
-  itemwordtype = POINTER;
-  alignbytes = 0;
-  itembytes = itemwords = 0;
-  itemsperblock = 0;
-  items = maxitems = 0;
-  unallocateditems = 0;
-  pathitemsleft = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// alloc()   Allocate space for an item.                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* memorypool::alloc()
-{
-  void *newitem;
-  void **newblock;
-  unsigned long alignptr;
-
-  // First check the linked list of dead items.  If the list is not
-  //   empty, allocate an item from the list rather than a fresh one.
-  if (deaditemstack != (void *) NULL) {
-    newitem = deaditemstack;               // Take first item in list.
-    deaditemstack = * (void **) deaditemstack;
-  } else {
-    // Check if there are any free items left in the current block.
-    if (unallocateditems == 0) {
-      // Check if another block must be allocated.
-      if (*(nowblock) == (void *) NULL) {
-        // Allocate a new block of items, pointed to by the previous block.
-        newblock = (void**)
-          (new BYTE[itemsperblock * itembytes + sizeof(void *) + alignbytes]);
-        *(nowblock) = (void *) newblock;
-        // The next block pointer is NULL.
-        *newblock = (void *) NULL;
-      }
-      // Move to the new block.
-      nowblock = (void **) *(nowblock);
-      // Find the first item in the block.
-      //   Increment by the size of (void *).
-      alignptr = (unsigned long) (nowblock + 1);
-      // Align the item on an `alignbytes'-byte boundary.
-      nextitem = (void *)
-        (alignptr + (unsigned long) alignbytes
-         - (alignptr % (unsigned long) alignbytes));
-      // There are lots of unallocated items left in this block.
-      unallocateditems = itemsperblock;
-    }
-    // Allocate a new item.
-    newitem = nextitem;
-    // Advance `nextitem' pointer to next free item in block.
-    if (itemwordtype == POINTER) {
-      nextitem = (void *) ((void **) nextitem + itemwords);
-    } else {
-      nextitem = (void *) ((REALTYPE *) nextitem + itemwords);
-    }
-    unallocateditems--;
-    maxitems++;
-  }
-  items++;
-  return newitem;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dealloc()     Deallocate space for an item.                               //
-//                                                                           //
-// The deallocated space is stored in a queue for later reuse.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void memorypool::dealloc(void* dyingitem)
-{
-  // Push freshly killed item onto stack.
-  *((void **) dyingitem) = deaditemstack;
-  deaditemstack = dyingitem;
-  items--;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// traversalinit()    Prepare to traverse the entire list of items.          //
-//                                                                           //
-// This routine is used in conjunction with traverse().                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void memorypool::traversalinit()
-{
-  unsigned long alignptr;
-
-  // Begin the traversal in the first block.
-  pathblock = firstblock;
-  // Find the first item in the block.  Increment by the size of (void *).
-  alignptr = (unsigned long) (pathblock + 1);
-  // Align with item on an `alignbytes'-byte boundary.
-  pathitem = (void *)
-    (alignptr + (unsigned long) alignbytes
-     - (alignptr % (unsigned long) alignbytes));
-  // Set the number of items left in the current block.
-  pathitemsleft = itemsperblock;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// traverse()     Find the next item in the list.                            //
-//                                                                           //
-// This routine is used in conjunction with traversalinit().  Be forewarned  //
-// that this routine successively returns all items in the list, including   //
-// deallocated ones on the deaditemqueue. It's up to you to figure out which //
-// ones are actually dead.  Why?  I don't want to allocate extra space just  //
-// to demarcate dead items. It can usually be done more space-efficiently by //
-// a routine that knows something about the structure of the item.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* memorypool::traverse()
-{
-  void *newitem;
-  unsigned long alignptr;
-
-  // Stop upon exhausting the list of items.
-  if (pathitem == nextitem) {
-    return (void *) NULL;
-  }
-  // Check whether any untraversed items remain in the current block.
-  if (pathitemsleft == 0) {
-    // Find the next block.
-    pathblock = (void **) *(pathblock);
-    // Find the first item in the block.  Increment by the size of (void *).
-    alignptr = (unsigned long) (pathblock + 1);
-    // Align with item on an `alignbytes'-byte boundary.
-    pathitem = (void *)
-      (alignptr + (unsigned long) alignbytes
-       - (alignptr % (unsigned long) alignbytes));
-    // Set the number of items left in the current block.
-    pathitemsleft = itemsperblock;
-  }
-  newitem = pathitem;
-  // Find the next item in the block.
-  if (itemwordtype == POINTER) {
-    pathitem = (void *) ((void **) pathitem + itemwords);
-  } else {
-    pathitem = (void *) ((REALTYPE *) pathitem + itemwords);
-  }
-  pathitemsleft--;
-  return newitem;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// class memorypool implementation                                           //
-///////////////////////////////////////////////////////////////////////////////
diff --git a/Tetgen/linklist.h b/Tetgen/linklist.h
deleted file mode 100644
index 599b5f2115..0000000000
--- a/Tetgen/linklist.h
+++ /dev/null
@@ -1,470 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// linklist.h    Defines some commonly usefed data types, such as link, list //
-//               queue and stack, etc.                                       //
-//                                                                           //
-// Si hang                                                                   //
-// Email: sihang@weboo.com                                                   //
-// http://www.weboo.com/sh/tetgen.htm                                        //
-//                                                                           //
-// You are free to use, copy and modify the sources under certain            //
-// circumstances, provided this copyright notice remains intact.             //
-// See the file LICENSE for details.                                         //
-//                                                                           //
-//   A given programming language will have a number of data types available //
-// along with some operations on them. C/C++ include int, float/double, char,//
-// etc. We don't normally worry about how these datatypes and operations are //
-// implemented, but just know what we can do with them.  However, most real  //
-// programming tasks require more complex and sophisticated data types. If   //
-// the programming language we used doesn't provide them, we'll have to      //
-// define them ourself. Once we've defined such data types, we again don't   //
-// want to worry about how they're implemented, just know what operations    //
-// are allowed on that data type. There is huge range of reasonable courses, //
-// textbooks and online sources on data structures and algorithms[1][2][3]   //
-// [4][5].                                                                   //
-//                                                                           //
-//   In this file, we defined some basic and most useful data types in our   //
-// common programming task. They are list, (double) link, queue, stack and   //
-// memorypool. where memorypool is a special data type for deal with large   //
-// memory blocks and was frequently used in the Tetgen Mesh program. All the //
-// data types defined here can be used with arbitrary data types, include    //
-// built-in and user defined datatypes.                                      //
-//                                                                           //
-//   I didn't use the Standard Template Library (STL)[2] of C++ language     //
-// provided to implement these data types. Although the STL is powerful and  //
-// elegant. But it need all the data types be known at compilation time, so  //
-// it can not compile each data types to seperate object files (*.o) until   //
-// the real date types are constructed. And it duplicate code which will     //
-// increase the code length and compilation time.                            //
-//                                                                           //
-//   The basic idea for implementing arbitrary datatypes is to use the       //
-// generic pointer type of C++ 'void*'. LEDA[4]'s solution is to consider    //
-// a data structure whose containers have a slot for storing objects of a    //
-// type T, which T are not stored directly in the containers of the data     //
-// structure but on the heap. The data slots of the containers have type     //
-// 'void*', and contain pointers to the objects on the heap. Type casting is //
-// used to bridge the gap between the untyped world of the data slots (all   //
-// data is void*) and the typed world of the heap. So to implement a single  //
-// data types, there need 2 seperate classes in LEDA, one represents the     //
-// abstract data type (data slots) and the other represents the real data    //
-// type (data on the heap), these two classes can be compiled seperately     //
-// into object files (*.o) then link them together when in use.              //
-//                                                                           //
-//   My implementation was diffrent with LEDA's. As a fact, I implemented    //
-// the data slots directly on the heap (dynamic memory). Any data type is    //
-// internally represented by a set of bytes, the size of data type is        //
-// determined at running time. Use a pointer (type of void*) to access each  //
-// data slot. No type casing is needed, it is up to user to determinte which //
-// type is. This scheme simplified the implementation but less convient in   //
-// use than LEDA's. Users have to provide the size of data types to the      //
-// constructor and there still can not deal with some kinds of data types    //
-// (like a structure/class contains pointers as its member variables).       //
-// Anyway, I don't mean to provide more general data types at here, anybody  //
-// is welcome to make any improvement on it. Thank you.                      //
-//                                                                           //
-// References:                                                               //
-//                                                                           //
-// [1] A.V. Aho, J.E. Hopcroft, and J.D. Ullman. Data Structures and         //
-//     Algorithms. Addison-Wesley, 1983.                                     //
-// [2] Joseph Bergin, Joe Bergin, F. B. Schneider, Data Structure Programm-  //
-//     ing : With the Standard Template Library in C++ (Undergraduate Texts  //
-//     in Computer Science). Springer Verlag, June 1998.                     //
-// [3] Bruno R. Preiss, Data Structures and Algorithms with Object-Oriented  //
-//     Design Patterns in C++. John Wiley & Sons; August 31, 1998.           //
-// [4] K. Mehlhorn and S. Naher, The LEDA Platform of Combinatorial and      //
-//     Geometric Computing. Cambridge University Press, 1999.                //
-// [5] Data Structures and Algorithms, Online source,                        //
-//     http://www.cee.hw.ac.uk/~alison/ds.html.                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef linklistH
-#define linklistH
-
-#ifndef NULL
-  #define NULL 0
-#endif
-
-#ifndef BYTE
-  #define BYTE char
-#endif
-
-#ifdef SINGLE
-  #define REALTYPE float
-#else
-  #define REALTYPE double
-#endif
-
-// Uncomment the following line to disable assertions.
-
-// #define NDEBUG
-
-#include <assert.h>
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Define a line-order function type, used in list, link.                    //
-//                                                                           //
-// A function: int cmp(const T &, const T &),  is said to realize a linear   //
-// order on the type T if there is a linear order <= on T such that for all  //
-// x and y in T satisfy the following relation:                              //
-//                                                                           //
-//                  -1  if x < y.                                            //
-//    comp(x, y) =   0  if x is equivalent to y.                             //
-//                  +1  if x > y.                                            //
-//                                                                           //
-// For many primitive data types (like int, unsigned long, ...) a function   //
-// compare is predefined and defines the so-called default ordering of the   //
-// type. The default ordering is the usual "less than or equal" for the      //
-// numerical types, the lexicographic ordering for strings, and the          //
-// lexicographic ordering of the Cartesian coordinates for points. For all   //
-// other types T there is no default ordering, and the user has to define    //
-// the function compare if a linear order on T is required.                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-typedef int (*compfunc) (const void *, const void *);
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Class list                                                                //
-//                                                                           //
-// Any data type list with dynamic re-allocation.                            //
-//                                                                           //
-// base-->  __________     list, which stores an array of pointers(void*),   //
-//         |_        _|    is ofen used to maintain lists of objects. list   //
-//         |_ data 0 _|    introduces properties and methods to:             //
-//         |__________|      > Add or delete the objects in the list.        //
-//         |_        _|      > Rearrange the objects in the list.            //
-//         |_ data 1 _|      > Locate and access objects in the list.        //
-//         |__________|      > Sort the objects in the list.                 //
-//         |_        _|                                                      //
-//         |_ data 2 _|    Note: The index of list is zero-based. Where 0 is //
-//         |__________|          the index of the first object, 1 is the     //
-//         |_        _|          index of second object, and so on.          //
-//         |_        _|                                                      //
-//         |__________|                                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-class list {
-
-    void **base;
-    int  itembytes, itemints;
-    long items, maxitems;
-    long expandsize;
-    compfunc comp;
-
-  public:
-
-    list(char*, int _maxitems = 256, int _expandsize = 128);
-    list(int _itembytes, int _maxitems = 256, int _expandsize = 128);
-    list(list&);
-    ~list();
-
-    list& operator=(list&);
-    int  getitembytes() { return itembytes; }
-    int  getitemints() { return itemints; }
-    long getmaxitems() { return maxitems; }
-    long getexpandsize() { return expandsize; }
-    void setexpandsize(int size) { assert(size); expandsize = size; }
-    void setcomp(compfunc compf) { assert(compf); comp = compf; }
-
-    void *operator[](int index);
-    void *getitem(int index);
-    void clear() { items = 0; }
-    int  len() { return items; }
-    void *alloc();
-    void append(void*);
-    void insert(int, void*);
-    void del(int);
-    int  remove(void*);
-    int  hasitem(void*);
-    int  indexof(void*);
-    void sort();
-    void simplify();
-
-    friend void mergelist(list*, list*, list&, compfunc compf = NULL);
-    friend void splitlist(list*, int, list&, list&, compfunc compf = NULL);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Class link                                                                //
-//                                                                           //
-// Any data type double link list build on a memory pool.                    //
-//                                                                           //
-// This class's storage scheme is same with class memorypool. It implement a //
-// double link list on the pool. Item traverse is through pointers stored in //
-// each item's 'next' and 'prev' field.  So do not need traverseinit() and   //
-// traverse().                                                               //
-//                                                                           //
-//   head-> _________      _________      _________      _________<-tail     //
-//         |__next___|--> |__next___|--> |__next___|--> |__NULL___|          //
-//         |__NULL___|<-- |__prev___|<-- |__prev___|<-- |__prev___|          //
-//         |         |    |_       _|    |_       _|    |         |          //
-//         |         |    |_ Data1 _|    |_ Data2 _|    |         |          //
-//         |_________|    |_________|    |_________|    |_________|          //
-//                                                                           //
-//                                                                           //
-// Note: The index of link is one-based. Where 1 is the index of the first   //
-//       object, 2 is the index of second object, and so on. 0 is used to    //
-//       indicate a void link.                                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-class link {
-
-  protected:
-
-    void **firstblock, **nowblock;
-    void *nextitem;
-    void *deaditemstack;
-    int  itemsperblock;
-    int  unallocateditems;
-    long maxitems;
-
-    void **head, **tail;
-    void *nextlinkitem;
-    int  itembytes, itemints;
-    long items;
-    int  curpos;
-    compfunc comp;
-
-  protected:
-
-    void *alloc();
-    void dealloc(void*);
-    void poolinit(int, int);
-    void poolrestart();
-
-  public:
-
-    link(char*, int itemcount = 256);
-    link(int _itembytes, int itemcount = 256);
-    ~link();
-
-    int getitembytes() { return itembytes; }
-    int getitemints() { return itemints; }
-    void setcomp(compfunc compf) { assert(compf); comp = compf; }
-
-    void init();
-    void clear() { poolrestart(); init(); }
-    int  len() { return items; }
-    int  move(int);
-    int  locate(int);
-    void add(void*);
-    void insert(int, void*);
-    void del(int);
-    void rewind() { nextlinkitem = *head; curpos= 1; }
-    void goend() { nextlinkitem = *(tail+1); curpos = items; }
-    void *getitem();
-    void *getnitem(int);
-    void setnitem(int, void*);
-    int  hasitem(void*);
-    void sort();
-};
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Class queue                                                               //
-//                                                                           //
-// Unbounded any data type queue with dynamic re-allocation.                 //
-//                                                                           //
-//                ___________     ___________     ___________                //
-//     Get() <-- |_         _|<--|_         _|<--|_         _| <-- Push()    //
-//               |_  Data0  _|   |_  Data1  _|   |_  Data2  _|               //
-//               |___________|   |___________|   |___________|               //
-//                                                                           //
-//                queue head                       queue tail                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Class queue Member Functions                                              //
-//                                                                           //
-// > Empty()                                                                 //
-//   Tests if queue is empty.                                                //
-// > Push()                                                                  //
-//   Adds a new top element (Stack and queue operation!).                    //
-// > Bot()                                                                   //
-//   Returns the bottom element (queue operation!) but does not remove it.   //
-// > Get()                                                                   //
-//   Returns the bottom element (queue operation!) and removes it.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-class queue : public link {
-
-  public:
-
-    queue(char* str, int itemcount = 256) : link(str, itemcount) {};
-    queue(int _itembytes, int itemcount = 256) : link(_itembytes, itemcount) {};
-
-    int  empty() { return items == 0; }
-    void push(void* newitem) { link::add(newitem); };
-    void *bot() { return link::getnitem(1); };
-    int  get(void*);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Class stack                                                               //
-//                                                                           //
-// Unbounded any data type stack with dynamic re-allocation.                 //
-//                                                                           //
-//           firstblock                         nowblock                     //
-//           __________       __________       __________                    //
-//          |__next____|---> |__next____|---> |__NULL____|                   //
-//          |__NULL____|<--- |__prev____|<--- |__prev____|                   //
-// Base---> |_        _|     |_        _|     |_        _|                   //
-//          |_ data 0 _|     |_ data 3 _|     |_ data 6 _|                   //
-//          |__________|     |__________|     |__________|                   //
-//          |_        _|     |_        _|     |_        _| <--- top          //
-//          |_ data 1 _|     |_ data 4 _|     |_        _|                   //
-//          |__________|     |__________|     |__________|                   //
-//          |_        _|     |_        _|     |_        _|                   //
-//          |_ data 2 _|     |_ data 5 _|     |_        _|                   //
-//          |__________|     |__________|     |__________|                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Class stack Member Functions                                              //
-//                                                                           //
-// > Clear()                                                                 //
-//   Clears the contents of stack.                                           //
-// > Empty()                                                                 //
-//   Tests if stack is empty.                                                //
-// > Top()                                                                   //
-//   Returns the top element (stack operation!) but does not pop it.         //
-// > Pop()                                                                   //
-//   Returns the top element (stack operation!) and pops it.                 //
-// > Push()                                                                  //
-//   Adds a new top element (stack and queue operation!).                    //
-// > Len()                                                                   //
-//   Returns the number of elements in stack.                                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-class stack {
-
-    void **firstblock, **nowblock;
-    void *top;
-    int  itembytes, itemints;
-    int  itemsperblock;
-    int  unuseditems;
-    long items, maxitems;
-    compfunc comp;
-
-  public:
-
-    stack(char*, int _itemsperblock = 256);
-    stack(int _itembytes, int _itemsperblock = 256);
-    ~stack();
-
-    void setcomp(compfunc compf) { assert(compf); comp = compf; }
-
-    void init(int, int);
-    void restart();
-    int  len() { return items; }
-    int  empty() { return items == 0; }
-    void push(void*);
-    void *topitem();
-    int  pop(void*);
-    int  hasitem(void*);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Labels that signify whether a record consists primarily of pointers or of //
-//   floating-point words.  Used to make decisions about data alignment.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum wordtype {POINTER, FLOATINGPOINT};
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// class memorypool                                                          //
-//                                                                           //
-// A type used to allocate memory.  firstblock is the first block of items.  //
-//   nowblock is the block from which items are currently being allocated.   //
-//   nextitem points to the next slab of free memory for an item.            //
-//   deaditemstack is the head of a linked list (stack) of deallocated items //
-//   that can be recycled.  unallocateditems is the number of items that     //
-//   remain to be allocated from nowblock.                                   //
-//                                                                           //
-// Traversal is the process of walking through the entire list of items, and //
-//   is separate from allocation.  Note that a traversal will visit items on //
-//   the "deaditemstack" stack as well as live items.  pathblock points to   //
-//   the block currently being traversed.  pathitem points to the next item  //
-//   to be traversed.  pathitemsleft is the number of items that remain to   //
-//   be traversed in pathblock.                                              //
-//                                                                           //
-// itemwordtype is set to POINTER or FLOATINGPOINT, and is used to suggest   //
-//   what sort of word the record is primarily made up of.  alignbytes       //
-//   determines how new records should be aligned in memory.  itembytes and  //
-//   itemwords are the length of a record in bytes (after rounding up) and   //
-//   words.  itemsperblock is the number of items allocated at once in a     //
-//   single block.  items is the number of currently allocated items.        //
-//   maxitems is the maximum number of items that have been allocated at     //
-//   once; it is the current number of items plus the number of records kept //
-//   on deaditemstack.                                                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// memorypool member functions:                                              //
-//                                                                           //
-// > init()                                                                  //
-//   Initialize a pool of memory for allocation of items.                    //
-// > restart()                                                               //
-//   Deallocate all items in a pool.                                         //
-// > alloc()                                                                 //
-//   Allocate space for an item.                                             //
-// > dealloc()                                                               //
-//   Deallocate space for an item.                                           //
-// > traversalinit()                                                         //
-//   Prepare to traverse the entire list of items.                           //
-// > traverse()                                                              //
-//   Find the next item in the list.                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-class memorypool {
-
-  public:
-
-    void **firstblock, **nowblock;
-    void *nextitem;
-    void *deaditemstack;
-    void **pathblock;
-    void *pathitem;
-    wordtype itemwordtype;
-    int  alignbytes;
-    int  itembytes, itemwords;
-    int  itemsperblock;
-    long items, maxitems;
-    int  unallocateditems;
-    int  pathitemsleft;
-
-  public:
-
-    memorypool();
-    memorypool(int, int, enum wordtype, int);
-    ~memorypool();
-
-    void init(int, int, enum wordtype, int);
-    void restart();
-    void deinit();
-    void *alloc();
-    void dealloc(void*);
-    void traversalinit();
-    void *traverse();
-};
-
-#endif // #ifndef linklistH
diff --git a/Tetgen/predicate.cpp b/Tetgen/predicate.cpp
deleted file mode 100644
index 1fa2a405c1..0000000000
--- a/Tetgen/predicate.cpp
+++ /dev/null
@@ -1,2945 +0,0 @@
-/*****************************************************************************/
-/*                                                                           */
-/*  Routines for Arbitrary Precision Floating-point Arithmetic               */
-/*  and Fast Robust Geometric Predicates                                     */
-/*  (predicates.c)                                                           */
-/*                                                                           */
-/*  May 18, 1996                                                             */
-/*                                                                           */
-/*  Placed in the public domain by                                           */
-/*  Jonathan Richard Shewchuk                                                */
-/*  School of Computer Science                                               */
-/*  Carnegie Mellon University                                               */
-/*  5000 Forbes Avenue                                                       */
-/*  Pittsburgh, Pennsylvania  15213-3891                                     */
-/*  jrs@cs.cmu.edu                                                           */
-/*                                                                           */
-/*  This file contains C implementation of algorithms for exact addition     */
-/*    and multiplication of floating-point numbers, and predicates for       */
-/*    robustly performing the orientation and incircle tests used in         */
-/*    computational geometry.  The algorithms and underlying theory are      */
-/*    described in Jonathan Richard Shewchuk.  "Adaptive Precision Floating- */
-/*    Point Arithmetic and Fast Robust Geometric Predicates."  Technical     */
-/*    Report CMU-CS-96-140, School of Computer Science, Carnegie Mellon      */
-/*    University, Pittsburgh, Pennsylvania, May 1996.  (Submitted to         */
-/*    Discrete & Computational Geometry.)                                    */
-/*                                                                           */
-/*  This file, the paper listed above, and other information are available   */
-/*    from the Web page http://www.cs.cmu.edu/~quake/robust.html .           */
-/*                                                                           */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  Using this code:                                                         */
-/*                                                                           */
-/*  First, read the short or long version of the paper (from the Web page    */
-/*    above).                                                                */
-/*                                                                           */
-/*  Be sure to call exactinit() once, before calling any of the arithmetic   */
-/*    functions or geometric predicates.  Also be sure to turn on the        */
-/*    optimizer when compiling this file.                                    */
-/*                                                                           */
-/*                                                                           */
-/*  Several geometric predicates are defined.  Their parameters are all      */
-/*    points.  Each point is an array of two or three floating-point         */
-/*    numbers.  The geometric predicates, described in the papers, are       */
-/*                                                                           */
-/*    orient2d(pa, pb, pc)                                                   */
-/*    orient2dfast(pa, pb, pc)                                               */
-/*    orient3d(pa, pb, pc, pd)                                               */
-/*    orient3dfast(pa, pb, pc, pd)                                           */
-/*    incircle(pa, pb, pc, pd)                                               */
-/*    incirclefast(pa, pb, pc, pd)                                           */
-/*    insphere(pa, pb, pc, pd, pe)                                           */
-/*    inspherefast(pa, pb, pc, pd, pe)                                       */
-/*                                                                           */
-/*  Those with suffix "fast" are approximate, non-robust versions.  Those    */
-/*    without the suffix are adaptive precision, robust versions.  There     */
-/*    are also versions with the suffices "exact" and "slow", which are      */
-/*    non-adaptive, exact arithmetic versions, which I use only for timings  */
-/*    in my arithmetic papers.                                               */
-/*                                                                           */
-/*                                                                           */
-/*  An expansion is represented by an array of floating-point numbers,       */
-/*    sorted from smallest to largest magnitude (possibly with interspersed  */
-/*    zeros).  The length of each expansion is stored as a separate integer, */
-/*    and each arithmetic function returns an integer which is the length    */
-/*    of the expansion it created.                                           */
-/*                                                                           */
-/*  Several arithmetic functions are defined.  Their parameters are          */
-/*                                                                           */
-/*    e, f           Input expansions                                        */
-/*    elen, flen     Lengths of input expansions (must be >= 1)              */
-/*    h              Output expansion                                        */
-/*    b              Input scalar                                            */
-/*                                                                           */
-/*  The arithmetic functions are                                             */
-/*                                                                           */
-/*    grow_expansion(elen, e, b, h)                                          */
-/*    grow_expansion_zeroelim(elen, e, b, h)                                 */
-/*    expansion_sum(elen, e, flen, f, h)                                     */
-/*    expansion_sum_zeroelim1(elen, e, flen, f, h)                           */
-/*    expansion_sum_zeroelim2(elen, e, flen, f, h)                           */
-/*    fast_expansion_sum(elen, e, flen, f, h)                                */
-/*    fast_expansion_sum_zeroelim(elen, e, flen, f, h)                       */
-/*    linear_expansion_sum(elen, e, flen, f, h)                              */
-/*    linear_expansion_sum_zeroelim(elen, e, flen, f, h)                     */
-/*    scale_expansion(elen, e, b, h)                                         */
-/*    scale_expansion_zeroelim(elen, e, b, h)                                */
-/*    compress(elen, e, h)                                                   */
-/*                                                                           */
-/*  All of these are described in the long version of the paper; some are    */
-/*    described in the short version.  All return an integer that is the     */
-/*    length of h.  Those with suffix _zeroelim perform zero elimination,    */
-/*    and are recommended over their counterparts.  The procedure            */
-/*    fast_expansion_sum_zeroelim() (or linear_expansion_sum_zeroelim() on   */
-/*    processors that do not use the round-to-even tiebreaking rule) is      */
-/*    recommended over expansion_sum_zeroelim().  Each procedure has a       */
-/*    little note next to it (in the code below) that tells you whether or   */
-/*    not the output expansion may be the same array as one of the input     */
-/*    expansions.                                                            */
-/*                                                                           */
-/*                                                                           */
-/*  If you look around below, you'll also find macros for a bunch of         */
-/*    simple unrolled arithmetic operations, and procedures for printing     */
-/*    expansions (commented out because they don't work with all C           */
-/*    compilers) and for generating random floating-point numbers whose      */
-/*    significand bits are all random.  Most of the macros have undocumented */
-/*    requirements that certain of their parameters should not be the same   */
-/*    variable; for safety, better to make sure all the parameters are       */
-/*    distinct variables.  Feel free to send email to jrs@cs.cmu.edu if you  */
-/*    have questions.                                                        */
-/*                                                                           */
-/*****************************************************************************/
-
-#include "defines.h"
-
-/* On some machines, the exact arithmetic routines might be defeated by the  */
-/*   use of internal extended precision floating-point registers.  Sometimes */
-/*   this problem can be fixed by defining certain values to be volatile,    */
-/*   thus forcing them to be stored to memory and rounded off.  This isn't   */
-/*   a great solution, though, as it slows the arithmetic down.              */
-/*                                                                           */
-/* To try this out, write "#define INEXACT volatile" below.  Normally,       */
-/*   however, INEXACT should be defined to be nothing.  ("#define INEXACT".) */
-
-#define INEXACT                          /* Nothing */
-/* #define INEXACT volatile */
-
-/* Which of the following two methods of finding the absolute values is      */
-/*   fastest is compiler-dependent.  A few compilers can inline and optimize */
-/*   the fabs() call; but most will incur the overhead of a function call,   */
-/*   which is disastrously slow.  A faster way on IEEE machines might be to  */
-/*   mask the appropriate bit, but that's difficult to do in C.              */
-
-#define Absolute(a)  ((a) >= 0.0 ? (a) : -(a))
-/* #define Absolute(a)  fabs(a) */
-
-/* Many of the operations are broken up into two pieces, a main part that    */
-/*   performs an approximate operation, and a "tail" that computes the       */
-/*   roundoff error of that operation.                                       */
-/*                                                                           */
-/* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(),    */
-/*   Split(), and Two_Product() are all implemented as described in the      */
-/*   reference.  Each of these macros requires certain variables to be       */
-/*   defined in the calling routine.  The variables `bvirt', `c', `abig',    */
-/*   `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because   */
-/*   they store the result of an operation that may incur roundoff error.    */
-/*   The input parameter `x' (or the highest numbered `x_' parameter) must   */
-/*   also be declared `INEXACT'.                                             */
-
-#define Fast_Two_Sum_Tail(a, b, x, y) \
-  bvirt = x - a; \
-  y = b - bvirt
-
-#define Fast_Two_Sum(a, b, x, y) \
-  x = (REAL) (a + b); \
-  Fast_Two_Sum_Tail(a, b, x, y)
-
-#define Fast_Two_Diff_Tail(a, b, x, y) \
-  bvirt = a - x; \
-  y = bvirt - b
-
-#define Fast_Two_Diff(a, b, x, y) \
-  x = (REAL) (a - b); \
-  Fast_Two_Diff_Tail(a, b, x, y)
-
-#define Two_Sum_Tail(a, b, x, y) \
-  bvirt = (REAL) (x - a); \
-  avirt = x - bvirt; \
-  bround = b - bvirt; \
-  around = a - avirt; \
-  y = around + bround
-
-#define Two_Sum(a, b, x, y) \
-  x = (REAL) (a + b); \
-  Two_Sum_Tail(a, b, x, y)
-
-#define Two_Diff_Tail(a, b, x, y) \
-  bvirt = (REAL) (a - x); \
-  avirt = x + bvirt; \
-  bround = bvirt - b; \
-  around = a - avirt; \
-  y = around + bround
-
-#define Two_Diff(a, b, x, y) \
-  x = (REAL) (a - b); \
-  Two_Diff_Tail(a, b, x, y)
-
-#define Split(a, ahi, alo) \
-  c = (REAL) (splitter * a); \
-  abig = (REAL) (c - a); \
-  ahi = c - abig; \
-  alo = a - ahi
-
-#define Two_Product_Tail(a, b, x, y) \
-  Split(a, ahi, alo); \
-  Split(b, bhi, blo); \
-  err1 = x - (ahi * bhi); \
-  err2 = err1 - (alo * bhi); \
-  err3 = err2 - (ahi * blo); \
-  y = (alo * blo) - err3
-
-#define Two_Product(a, b, x, y) \
-  x = (REAL) (a * b); \
-  Two_Product_Tail(a, b, x, y)
-
-/* Two_Product_Presplit() is Two_Product() where one of the inputs has       */
-/*   already been split.  Avoids redundant splitting.                        */
-
-#define Two_Product_Presplit(a, b, bhi, blo, x, y) \
-  x = (REAL) (a * b); \
-  Split(a, ahi, alo); \
-  err1 = x - (ahi * bhi); \
-  err2 = err1 - (alo * bhi); \
-  err3 = err2 - (ahi * blo); \
-  y = (alo * blo) - err3
-
-/* Two_Product_2Presplit() is Two_Product() where both of the inputs have    */
-/*   already been split.  Avoids redundant splitting.                        */
-
-#define Two_Product_2Presplit(a, ahi, alo, b, bhi, blo, x, y) \
-  x = (REAL) (a * b); \
-  err1 = x - (ahi * bhi); \
-  err2 = err1 - (alo * bhi); \
-  err3 = err2 - (ahi * blo); \
-  y = (alo * blo) - err3
-
-/* Square() can be done more quickly than Two_Product().                     */
-
-#define Square_Tail(a, x, y) \
-  Split(a, ahi, alo); \
-  err1 = x - (ahi * ahi); \
-  err3 = err1 - ((ahi + ahi) * alo); \
-  y = (alo * alo) - err3
-
-#define Square(a, x, y) \
-  x = (REAL) (a * a); \
-  Square_Tail(a, x, y)
-
-/* Macros for summing expansions of various fixed lengths.  These are all    */
-/*   unrolled versions of Expansion_Sum().                                   */
-
-#define Two_One_Sum(a1, a0, b, x2, x1, x0) \
-  Two_Sum(a0, b , _i, x0); \
-  Two_Sum(a1, _i, x2, x1)
-
-#define Two_One_Diff(a1, a0, b, x2, x1, x0) \
-  Two_Diff(a0, b , _i, x0); \
-  Two_Sum( a1, _i, x2, x1)
-
-#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
-  Two_One_Sum(a1, a0, b0, _j, _0, x0); \
-  Two_One_Sum(_j, _0, b1, x3, x2, x1)
-
-#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
-  Two_One_Diff(a1, a0, b0, _j, _0, x0); \
-  Two_One_Diff(_j, _0, b1, x3, x2, x1)
-
-#define Four_One_Sum(a3, a2, a1, a0, b, x4, x3, x2, x1, x0) \
-  Two_One_Sum(a1, a0, b , _j, x1, x0); \
-  Two_One_Sum(a3, a2, _j, x4, x3, x2)
-
-#define Four_Two_Sum(a3, a2, a1, a0, b1, b0, x5, x4, x3, x2, x1, x0) \
-  Four_One_Sum(a3, a2, a1, a0, b0, _k, _2, _1, _0, x0); \
-  Four_One_Sum(_k, _2, _1, _0, b1, x5, x4, x3, x2, x1)
-
-#define Four_Four_Sum(a3, a2, a1, a0, b4, b3, b1, b0, x7, x6, x5, x4, x3, x2, \
-                      x1, x0) \
-  Four_Two_Sum(a3, a2, a1, a0, b1, b0, _l, _2, _1, _0, x1, x0); \
-  Four_Two_Sum(_l, _2, _1, _0, b4, b3, x7, x6, x5, x4, x3, x2)
-
-#define Eight_One_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b, x8, x7, x6, x5, x4, \
-                      x3, x2, x1, x0) \
-  Four_One_Sum(a3, a2, a1, a0, b , _j, x3, x2, x1, x0); \
-  Four_One_Sum(a7, a6, a5, a4, _j, x8, x7, x6, x5, x4)
-
-#define Eight_Two_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b1, b0, x9, x8, x7, \
-                      x6, x5, x4, x3, x2, x1, x0) \
-  Eight_One_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b0, _k, _6, _5, _4, _3, _2, \
-                _1, _0, x0); \
-  Eight_One_Sum(_k, _6, _5, _4, _3, _2, _1, _0, b1, x9, x8, x7, x6, x5, x4, \
-                x3, x2, x1)
-
-#define Eight_Four_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b4, b3, b1, b0, x11, \
-                       x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0) \
-  Eight_Two_Sum(a7, a6, a5, a4, a3, a2, a1, a0, b1, b0, _l, _6, _5, _4, _3, \
-                _2, _1, _0, x1, x0); \
-  Eight_Two_Sum(_l, _6, _5, _4, _3, _2, _1, _0, b4, b3, x11, x10, x9, x8, \
-                x7, x6, x5, x4, x3, x2)
-
-/* Macros for multiplying expansions of various fixed lengths.               */
-
-#define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
-  Split(b, bhi, blo); \
-  Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
-  Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
-  Two_Sum(_i, _0, _k, x1); \
-  Fast_Two_Sum(_j, _k, x3, x2)
-
-#define Four_One_Product(a3, a2, a1, a0, b, x7, x6, x5, x4, x3, x2, x1, x0) \
-  Split(b, bhi, blo); \
-  Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
-  Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
-  Two_Sum(_i, _0, _k, x1); \
-  Fast_Two_Sum(_j, _k, _i, x2); \
-  Two_Product_Presplit(a2, b, bhi, blo, _j, _0); \
-  Two_Sum(_i, _0, _k, x3); \
-  Fast_Two_Sum(_j, _k, _i, x4); \
-  Two_Product_Presplit(a3, b, bhi, blo, _j, _0); \
-  Two_Sum(_i, _0, _k, x5); \
-  Fast_Two_Sum(_j, _k, x7, x6)
-
-#define Two_Two_Product(a1, a0, b1, b0, x7, x6, x5, x4, x3, x2, x1, x0) \
-  Split(a0, a0hi, a0lo); \
-  Split(b0, bhi, blo); \
-  Two_Product_2Presplit(a0, a0hi, a0lo, b0, bhi, blo, _i, x0); \
-  Split(a1, a1hi, a1lo); \
-  Two_Product_2Presplit(a1, a1hi, a1lo, b0, bhi, blo, _j, _0); \
-  Two_Sum(_i, _0, _k, _1); \
-  Fast_Two_Sum(_j, _k, _l, _2); \
-  Split(b1, bhi, blo); \
-  Two_Product_2Presplit(a0, a0hi, a0lo, b1, bhi, blo, _i, _0); \
-  Two_Sum(_1, _0, _k, x1); \
-  Two_Sum(_2, _k, _j, _1); \
-  Two_Sum(_l, _j, _m, _2); \
-  Two_Product_2Presplit(a1, a1hi, a1lo, b1, bhi, blo, _j, _0); \
-  Two_Sum(_i, _0, _n, _0); \
-  Two_Sum(_1, _0, _i, x2); \
-  Two_Sum(_2, _i, _k, _1); \
-  Two_Sum(_m, _k, _l, _2); \
-  Two_Sum(_j, _n, _k, _0); \
-  Two_Sum(_1, _0, _j, x3); \
-  Two_Sum(_2, _j, _i, _1); \
-  Two_Sum(_l, _i, _m, _2); \
-  Two_Sum(_1, _k, _i, x4); \
-  Two_Sum(_2, _i, _k, x5); \
-  Two_Sum(_m, _k, x7, x6)
-
-/* An expansion of length two can be squared more quickly than finding the   */
-/*   product of two different expansions of length two, and the result is    */
-/*   guaranteed to have no more than six (rather than eight) components.     */
-
-#define Two_Square(a1, a0, x5, x4, x3, x2, x1, x0) \
-  Square(a0, _j, x0); \
-  _0 = a0 + a0; \
-  Two_Product(a1, _0, _k, _1); \
-  Two_One_Sum(_k, _1, _j, _l, _2, x1); \
-  Square(a1, _j, _1); \
-  Two_Two_Sum(_j, _1, _l, _2, x5, x4, x3, x2)
-
-REAL splitter;     /* = 2^ceiling(p / 2) + 1.  Used to split floats in half. */
-REAL epsilon;                /* = 2^(-p).  Used to estimate roundoff errors. */
-/* A set of coefficients used to calculate maximum roundoff errors.          */
-REAL resulterrbound;
-REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
-REAL o3derrboundA, o3derrboundB, o3derrboundC;
-REAL iccerrboundA, iccerrboundB, iccerrboundC;
-REAL isperrboundA, isperrboundB, isperrboundC;
-
-/*****************************************************************************/
-/*                                                                           */
-/*  exactinit()   Initialize the variables used for exact arithmetic.        */
-/*                                                                           */
-/*  `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in   */
-/*  floating-point arithmetic.  `epsilon' bounds the relative roundoff       */
-/*  error.  It is used for floating-point error analysis.                    */
-/*                                                                           */
-/*  `splitter' is used to split floating-point numbers into two half-        */
-/*  length significands for exact multiplication.                            */
-/*                                                                           */
-/*  I imagine that a highly optimizing compiler might be too smart for its   */
-/*  own good, and somehow cause this routine to fail, if it pretends that    */
-/*  floating-point arithmetic is too much like real arithmetic.              */
-/*                                                                           */
-/*  Don't change this routine unless you fully understand it.                */
-/*                                                                           */
-/*****************************************************************************/
-
-void exactinit()
-{
-/* Here is the code configure Intel CPUs to correctly execute my code. For   */
-/*  detail please see:                                                       */
-/*    http://www.cs.cmu.edu/~quake/robust.pc.html                            */
-
-#ifdef INTEL_MSC_TURBOC
-#ifdef SINGLE
-  _control87(PC_24, MCW_PC);    /* set FPU control word for single precision */
-#else /* not SINGLE */
-  _control87(PC_53, MCW_PC);    /* set FPU control word for double precision */
-#endif /* not SINGLE */
-#endif /* defined INTEL_MSC_TURBOC */
-
-#ifdef INTEL_GCC_LINUX
-#include <i386/fpu_control.h>
-#ifdef SINGLE
-__setfpucw(4210);               /* set FPU control word for single precision */
-#else /* not SINGLE */
-__setfpucw(4722);               /* set FPU control word for double precision */
-#endif /* not SINGLE */
-#endif /* defined INTEL_GCC_LINUX */
-
-#ifdef INTEL_GCC
-#include <i386/fpu_control.h>
-void set_ctrlword(v)
-int v;
-{
-  asm("fldcw %0" :: "m" (v));
-}
-#ifdef SINGLE
-set_ctrlword(4210);             /* set FPU control word for single precision */
-#else /* not SINGLE */
-set_ctrlword(4722);             /* set FPU control word for double precision */
-#endif /* not SINGLE */
-#endif /* defined INTEL_GCC */
-
-  REAL half;
-  REAL check, lastcheck;
-  int every_other;
-
-  every_other = 1;
-  half = 0.5;
-  epsilon = 1.0;
-  splitter = 1.0;
-  check = 1.0;
-  /* Repeatedly divide `epsilon' by two until it is too small to add to    */
-  /*   one without causing roundoff.  (Also check if the sum is equal to   */
-  /*   the previous sum, for machines that round up instead of using exact */
-  /*   rounding.  Not that this library will work on such machines anyway. */
-  do {
-    lastcheck = check;
-    epsilon *= half;
-    if (every_other) {
-      splitter *= 2.0;
-    }
-    every_other = !every_other;
-    check = 1.0 + epsilon;
-  } while ((check != 1.0) && (check != lastcheck));
-  splitter += 1.0;
-
-  /* Error bounds for orientation and incircle tests. */
-  resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
-  ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
-  ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
-  ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
-  o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
-  o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
-  o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
-  iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
-  iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
-  iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
-  isperrboundA = (16.0 + 224.0 * epsilon) * epsilon;
-  isperrboundB = (5.0 + 72.0 * epsilon) * epsilon;
-  isperrboundC = (71.0 + 1408.0 * epsilon) * epsilon * epsilon;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  grow_expansion()   Add a scalar to an expansion.                         */
-/*                                                                           */
-/*  Sets h = e + b.  See the long version of my paper for details.           */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
-/*  properties as well.  (That is, if e has one of these properties, so      */
-/*  will h.)                                                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-int grow_expansion(int elen, REAL* e, REAL b, REAL* h)
-/* e and h can be the same. */
-{
-  REAL Q;
-  INEXACT REAL Qnew;
-  int eindex;
-  REAL enow;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-
-  Q = b;
-  for (eindex = 0; eindex < elen; eindex++) {
-    enow = e[eindex];
-    Two_Sum(Q, enow, Qnew, h[eindex]);
-    Q = Qnew;
-  }
-  h[eindex] = Q;
-  return eindex + 1;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  grow_expansion_zeroelim()   Add a scalar to an expansion, eliminating    */
-/*                              zero components from the output expansion.   */
-/*                                                                           */
-/*  Sets h = e + b.  See the long version of my paper for details.           */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
-/*  properties as well.  (That is, if e has one of these properties, so      */
-/*  will h.)                                                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-int grow_expansion_zeroelim(int elen, REAL* e, REAL b, REAL* h)
-/* e and h can be the same. */
-{
-  REAL Q, hh;
-  INEXACT REAL Qnew;
-  int eindex, hindex;
-  REAL enow;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-
-  hindex = 0;
-  Q = b;
-  for (eindex = 0; eindex < elen; eindex++) {
-    enow = e[eindex];
-    Two_Sum(Q, enow, Qnew, hh);
-    Q = Qnew;
-    if (hh != 0.0) {
-      h[hindex++] = hh;
-    }
-  }
-  if ((Q != 0.0) || (hindex == 0)) {
-    h[hindex++] = Q;
-  }
-  return hindex;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  expansion_sum()   Sum two expansions.                                    */
-/*                                                                           */
-/*  Sets h = e + f.  See the long version of my paper for details.           */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), maintains the nonadjacent property as well.  (That is,   */
-/*  if e has one of these properties, so will h.)  Does NOT maintain the     */
-/*  strongly nonoverlapping property.                                        */
-/*                                                                           */
-/*****************************************************************************/
-
-int expansion_sum(int elen, REAL* e, int flen, REAL* f, REAL* h)
-/* e and h can be the same, but f and h cannot. */
-{
-  REAL Q;
-  INEXACT REAL Qnew;
-  int findex, hindex, hlast;
-  REAL hnow;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-
-  Q = f[0];
-  for (hindex = 0; hindex < elen; hindex++) {
-    hnow = e[hindex];
-    Two_Sum(Q, hnow, Qnew, h[hindex]);
-    Q = Qnew;
-  }
-  h[hindex] = Q;
-  hlast = hindex;
-  for (findex = 1; findex < flen; findex++) {
-    Q = f[findex];
-    for (hindex = findex; hindex <= hlast; hindex++) {
-      hnow = h[hindex];
-      Two_Sum(Q, hnow, Qnew, h[hindex]);
-      Q = Qnew;
-    }
-    h[++hlast] = Q;
-  }
-  return hlast + 1;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  expansion_sum_zeroelim1()   Sum two expansions, eliminating zero         */
-/*                              components from the output expansion.        */
-/*                                                                           */
-/*  Sets h = e + f.  See the long version of my paper for details.           */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), maintains the nonadjacent property as well.  (That is,   */
-/*  if e has one of these properties, so will h.)  Does NOT maintain the     */
-/*  strongly nonoverlapping property.                                        */
-/*                                                                           */
-/*****************************************************************************/
-
-int expansion_sum_zeroelim1(int elen, REAL* e, int flen, REAL* f, REAL* h)
-/* e and h can be the same, but f and h cannot. */
-{
-  REAL Q;
-  INEXACT REAL Qnew;
-  int index, findex, hindex, hlast;
-  REAL hnow;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-
-  Q = f[0];
-  for (hindex = 0; hindex < elen; hindex++) {
-    hnow = e[hindex];
-    Two_Sum(Q, hnow, Qnew, h[hindex]);
-    Q = Qnew;
-  }
-  h[hindex] = Q;
-  hlast = hindex;
-  for (findex = 1; findex < flen; findex++) {
-    Q = f[findex];
-    for (hindex = findex; hindex <= hlast; hindex++) {
-      hnow = h[hindex];
-      Two_Sum(Q, hnow, Qnew, h[hindex]);
-      Q = Qnew;
-    }
-    h[++hlast] = Q;
-  }
-  hindex = -1;
-  for (index = 0; index <= hlast; index++) {
-    hnow = h[index];
-    if (hnow != 0.0) {
-      h[++hindex] = hnow;
-    }
-  }
-  if (hindex == -1) {
-    return 1;
-  } else {
-    return hindex + 1;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  expansion_sum_zeroelim2()   Sum two expansions, eliminating zero         */
-/*                              components from the output expansion.        */
-/*                                                                           */
-/*  Sets h = e + f.  See the long version of my paper for details.           */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), maintains the nonadjacent property as well.  (That is,   */
-/*  if e has one of these properties, so will h.)  Does NOT maintain the     */
-/*  strongly nonoverlapping property.                                        */
-/*                                                                           */
-/*****************************************************************************/
-
-int expansion_sum_zeroelim2(int elen, REAL* e, int flen, REAL* f, REAL* h)
-/* e and h can be the same, but f and h cannot. */
-{
-  REAL Q, hh;
-  INEXACT REAL Qnew;
-  int eindex, findex, hindex, hlast;
-  REAL enow;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-
-  hindex = 0;
-  Q = f[0];
-  for (eindex = 0; eindex < elen; eindex++) {
-    enow = e[eindex];
-    Two_Sum(Q, enow, Qnew, hh);
-    Q = Qnew;
-    if (hh != 0.0) {
-      h[hindex++] = hh;
-    }
-  }
-  h[hindex] = Q;
-  hlast = hindex;
-  for (findex = 1; findex < flen; findex++) {
-    hindex = 0;
-    Q = f[findex];
-    for (eindex = 0; eindex <= hlast; eindex++) {
-      enow = h[eindex];
-      Two_Sum(Q, enow, Qnew, hh);
-      Q = Qnew;
-      if (hh != 0) {
-        h[hindex++] = hh;
-      }
-    }
-    h[hindex] = Q;
-    hlast = hindex;
-  }
-  return hlast + 1;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  fast_expansion_sum()   Sum two expansions.                               */
-/*                                                                           */
-/*  Sets h = e + f.  See the long version of my paper for details.           */
-/*                                                                           */
-/*  If round-to-even is used (as with IEEE 754), maintains the strongly      */
-/*  nonoverlapping property.  (That is, if e is strongly nonoverlapping, h   */
-/*  will be also.)  Does NOT maintain the nonoverlapping or nonadjacent      */
-/*  properties.                                                              */
-/*                                                                           */
-/*****************************************************************************/
-
-int fast_expansion_sum(int elen, REAL* e, int flen, REAL* f, REAL* h)
-/* h cannot be e or f. */
-{
-  REAL Q;
-  INEXACT REAL Qnew;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  int eindex, findex, hindex;
-  REAL enow, fnow;
-
-  enow = e[0];
-  fnow = f[0];
-  eindex = findex = 0;
-  if ((fnow > enow) == (fnow > -enow)) {
-    Q = enow;
-    enow = e[++eindex];
-  } else {
-    Q = fnow;
-    fnow = f[++findex];
-  }
-  hindex = 0;
-  if ((eindex < elen) && (findex < flen)) {
-    if ((fnow > enow) == (fnow > -enow)) {
-      Fast_Two_Sum(enow, Q, Qnew, h[0]);
-      enow = e[++eindex];
-    } else {
-      Fast_Two_Sum(fnow, Q, Qnew, h[0]);
-      fnow = f[++findex];
-    }
-    Q = Qnew;
-    hindex = 1;
-    while ((eindex < elen) && (findex < flen)) {
-      if ((fnow > enow) == (fnow > -enow)) {
-        Two_Sum(Q, enow, Qnew, h[hindex]);
-        enow = e[++eindex];
-      } else {
-        Two_Sum(Q, fnow, Qnew, h[hindex]);
-        fnow = f[++findex];
-      }
-      Q = Qnew;
-      hindex++;
-    }
-  }
-  while (eindex < elen) {
-    Two_Sum(Q, enow, Qnew, h[hindex]);
-    enow = e[++eindex];
-    Q = Qnew;
-    hindex++;
-  }
-  while (findex < flen) {
-    Two_Sum(Q, fnow, Qnew, h[hindex]);
-    fnow = f[++findex];
-    Q = Qnew;
-    hindex++;
-  }
-  h[hindex] = Q;
-  return hindex + 1;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  fast_expansion_sum_zeroelim()   Sum two expansions, eliminating zero     */
-/*                                  components from the output expansion.    */
-/*                                                                           */
-/*  Sets h = e + f.  See the long version of my paper for details.           */
-/*                                                                           */
-/*  If round-to-even is used (as with IEEE 754), maintains the strongly      */
-/*  nonoverlapping property.  (That is, if e is strongly nonoverlapping, h   */
-/*  will be also.)  Does NOT maintain the nonoverlapping or nonadjacent      */
-/*  properties.                                                              */
-/*                                                                           */
-/*****************************************************************************/
-
-int fast_expansion_sum_zeroelim(int elen, REAL* e, int flen, REAL* f, REAL* h)
-/* h cannot be e or f. */
-{
-  REAL Q;
-  INEXACT REAL Qnew;
-  INEXACT REAL hh;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  int eindex, findex, hindex;
-  REAL enow, fnow;
-
-  enow = e[0];
-  fnow = f[0];
-  eindex = findex = 0;
-  if ((fnow > enow) == (fnow > -enow)) {
-    Q = enow;
-    enow = e[++eindex];
-  } else {
-    Q = fnow;
-    fnow = f[++findex];
-  }
-  hindex = 0;
-  if ((eindex < elen) && (findex < flen)) {
-    if ((fnow > enow) == (fnow > -enow)) {
-      Fast_Two_Sum(enow, Q, Qnew, hh);
-      enow = e[++eindex];
-    } else {
-      Fast_Two_Sum(fnow, Q, Qnew, hh);
-      fnow = f[++findex];
-    }
-    Q = Qnew;
-    if (hh != 0.0) {
-      h[hindex++] = hh;
-    }
-    while ((eindex < elen) && (findex < flen)) {
-      if ((fnow > enow) == (fnow > -enow)) {
-        Two_Sum(Q, enow, Qnew, hh);
-        enow = e[++eindex];
-      } else {
-        Two_Sum(Q, fnow, Qnew, hh);
-        fnow = f[++findex];
-      }
-      Q = Qnew;
-      if (hh != 0.0) {
-        h[hindex++] = hh;
-      }
-    }
-  }
-  while (eindex < elen) {
-    Two_Sum(Q, enow, Qnew, hh);
-    enow = e[++eindex];
-    Q = Qnew;
-    if (hh != 0.0) {
-      h[hindex++] = hh;
-    }
-  }
-  while (findex < flen) {
-    Two_Sum(Q, fnow, Qnew, hh);
-    fnow = f[++findex];
-    Q = Qnew;
-    if (hh != 0.0) {
-      h[hindex++] = hh;
-    }
-  }
-  if ((Q != 0.0) || (hindex == 0)) {
-    h[hindex++] = Q;
-  }
-  return hindex;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  linear_expansion_sum()   Sum two expansions.                             */
-/*                                                                           */
-/*  Sets h = e + f.  See either version of my paper for details.             */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  (That is, if e is                */
-/*  nonoverlapping, h will be also.)                                         */
-/*                                                                           */
-/*****************************************************************************/
-
-int linear_expansion_sum(int elen, REAL* e, int flen, REAL* f, REAL* h)
-/* h cannot be e or f. */
-{
-  REAL Q, q;
-  INEXACT REAL Qnew;
-  INEXACT REAL R;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  int eindex, findex, hindex;
-  REAL enow, fnow;
-  REAL g0;
-
-  enow = e[0];
-  fnow = f[0];
-  eindex = findex = 0;
-  if ((fnow > enow) == (fnow > -enow)) {
-    g0 = enow;
-    enow = e[++eindex];
-  } else {
-    g0 = fnow;
-    fnow = f[++findex];
-  }
-  if ((eindex < elen) && ((findex >= flen)
-                          || ((fnow > enow) == (fnow > -enow)))) {
-    Fast_Two_Sum(enow, g0, Qnew, q);
-    enow = e[++eindex];
-  } else {
-    Fast_Two_Sum(fnow, g0, Qnew, q);
-    fnow = f[++findex];
-  }
-  Q = Qnew;
-  for (hindex = 0; hindex < elen + flen - 2; hindex++) {
-    if ((eindex < elen) && ((findex >= flen)
-                            || ((fnow > enow) == (fnow > -enow)))) {
-      Fast_Two_Sum(enow, q, R, h[hindex]);
-      enow = e[++eindex];
-    } else {
-      Fast_Two_Sum(fnow, q, R, h[hindex]);
-      fnow = f[++findex];
-    }
-    Two_Sum(Q, R, Qnew, q);
-    Q = Qnew;
-  }
-  h[hindex] = q;
-  h[hindex + 1] = Q;
-  return hindex + 2;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  linear_expansion_sum_zeroelim()   Sum two expansions, eliminating zero   */
-/*                                    components from the output expansion.  */
-/*                                                                           */
-/*  Sets h = e + f.  See either version of my paper for details.             */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  (That is, if e is                */
-/*  nonoverlapping, h will be also.)                                         */
-/*                                                                           */
-/*****************************************************************************/
-
-int linear_expansion_sum_zeroelim(int elen, REAL* e, int flen, REAL* f, REAL* h)
-/* h cannot be e or f. */
-{
-  REAL Q, q, hh;
-  INEXACT REAL Qnew;
-  INEXACT REAL R;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  int eindex, findex, hindex;
-  int count;
-  REAL enow, fnow;
-  REAL g0;
-
-  enow = e[0];
-  fnow = f[0];
-  eindex = findex = 0;
-  hindex = 0;
-  if ((fnow > enow) == (fnow > -enow)) {
-    g0 = enow;
-    enow = e[++eindex];
-  } else {
-    g0 = fnow;
-    fnow = f[++findex];
-  }
-  if ((eindex < elen) && ((findex >= flen)
-                          || ((fnow > enow) == (fnow > -enow)))) {
-    Fast_Two_Sum(enow, g0, Qnew, q);
-    enow = e[++eindex];
-  } else {
-    Fast_Two_Sum(fnow, g0, Qnew, q);
-    fnow = f[++findex];
-  }
-  Q = Qnew;
-  for (count = 2; count < elen + flen; count++) {
-    if ((eindex < elen) && ((findex >= flen)
-                            || ((fnow > enow) == (fnow > -enow)))) {
-      Fast_Two_Sum(enow, q, R, hh);
-      enow = e[++eindex];
-    } else {
-      Fast_Two_Sum(fnow, q, R, hh);
-      fnow = f[++findex];
-    }
-    Two_Sum(Q, R, Qnew, q);
-    Q = Qnew;
-    if (hh != 0) {
-      h[hindex++] = hh;
-    }
-  }
-  if (q != 0) {
-    h[hindex++] = q;
-  }
-  if ((Q != 0.0) || (hindex == 0)) {
-    h[hindex++] = Q;
-  }
-  return hindex;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  scale_expansion()   Multiply an expansion by a scalar.                   */
-/*                                                                           */
-/*  Sets h = be.  See either version of my paper for details.                */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
-/*  properties as well.  (That is, if e has one of these properties, so      */
-/*  will h.)                                                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-int scale_expansion(int elen, REAL* e, REAL b, REAL* h)
-/* e and h cannot be the same. */
-{
-  INEXACT REAL Q;
-  INEXACT REAL sum;
-  INEXACT REAL product1;
-  REAL product0;
-  int eindex, hindex;
-  REAL enow;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  INEXACT REAL c;
-  INEXACT REAL abig;
-  REAL ahi, alo, bhi, blo;
-  REAL err1, err2, err3;
-
-  Split(b, bhi, blo);
-  Two_Product_Presplit(e[0], b, bhi, blo, Q, h[0]);
-  hindex = 1;
-  for (eindex = 1; eindex < elen; eindex++) {
-    enow = e[eindex];
-    Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
-    Two_Sum(Q, product0, sum, h[hindex]);
-    hindex++;
-    Two_Sum(product1, sum, Q, h[hindex]);
-    hindex++;
-  }
-  h[hindex] = Q;
-  return elen + elen;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  scale_expansion_zeroelim()   Multiply an expansion by a scalar,          */
-/*                               eliminating zero components from the        */
-/*                               output expansion.                           */
-/*                                                                           */
-/*  Sets h = be.  See either version of my paper for details.                */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
-/*  properties as well.  (That is, if e has one of these properties, so      */
-/*  will h.)                                                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-int scale_expansion_zeroelim(int elen, REAL* e, REAL b, REAL* h)
-/* e and h cannot be the same. */
-{
-  INEXACT REAL Q, sum;
-  REAL hh;
-  INEXACT REAL product1;
-  REAL product0;
-  int eindex, hindex;
-  REAL enow;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  INEXACT REAL c;
-  INEXACT REAL abig;
-  REAL ahi, alo, bhi, blo;
-  REAL err1, err2, err3;
-
-  Split(b, bhi, blo);
-  Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
-  hindex = 0;
-  if (hh != 0) {
-    h[hindex++] = hh;
-  }
-  for (eindex = 1; eindex < elen; eindex++) {
-    enow = e[eindex];
-    Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
-    Two_Sum(Q, product0, sum, hh);
-    if (hh != 0) {
-      h[hindex++] = hh;
-    }
-    Fast_Two_Sum(product1, sum, Q, hh);
-    if (hh != 0) {
-      h[hindex++] = hh;
-    }
-  }
-  if ((Q != 0.0) || (hindex == 0)) {
-    h[hindex++] = Q;
-  }
-  return hindex;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  compress()   Compress an expansion.                                      */
-/*                                                                           */
-/*  See the long version of my paper for details.                            */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), then any nonoverlapping expansion is converted to a      */
-/*  nonadjacent expansion.                                                   */
-/*                                                                           */
-/*****************************************************************************/
-
-int compress(int elen, REAL* e, REAL* h)         /* e and h may be the same. */
-{
-  REAL Q, q;
-  INEXACT REAL Qnew;
-  int eindex, hindex;
-  INEXACT REAL bvirt;
-  REAL enow, hnow;
-  int top, bottom;
-
-  bottom = elen - 1;
-  Q = e[bottom];
-  for (eindex = elen - 2; eindex >= 0; eindex--) {
-    enow = e[eindex];
-    Fast_Two_Sum(Q, enow, Qnew, q);
-    if (q != 0) {
-      h[bottom--] = Qnew;
-      Q = q;
-    } else {
-      Q = Qnew;
-    }
-  }
-  top = 0;
-  for (hindex = bottom + 1; hindex < elen; hindex++) {
-    hnow = h[hindex];
-    Fast_Two_Sum(hnow, Q, Qnew, q);
-    if (q != 0) {
-      h[top++] = q;
-    }
-    Q = Qnew;
-  }
-  h[top] = Q;
-  return top + 1;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  estimate()   Produce a one-word estimate of an expansion's value.        */
-/*                                                                           */
-/*  See either version of my paper for details.                              */
-/*                                                                           */
-/*****************************************************************************/
-
-REAL estimate(int elen, REAL* e)
-{
-  REAL Q;
-  int eindex;
-
-  Q = e[0];
-  for (eindex = 1; eindex < elen; eindex++) {
-    Q += e[eindex];
-  }
-  return Q;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-//  orient2d()       Adaptive exact 2D orientation test.  Robust.            //
-//                                                                           //
-//               Return a positive value if the points pa, pb, and pc occur  //
-//               in counterclockwise order; a negative value if they occur   //
-//               in clockwise order; and zero if they are collinear.  The    //
-//               result is also a rough approximation of twice the signed    //
-//               area of the triangle defined by the three points.           //
-//                                                                           //
-//  orient2d() use exact arithmetic to ensure a correct answer.  The result  //
-//  returned is the determinant of a matrix.  In orient2d() only, this       //
-//  determinant is computed adaptively, in the sense that exact arithmetic   //
-//  is used only to the degree it is needed to ensure that the returned      //
-//  value has the correct sign.  Hence, orient2d() is usually quite fast,    //
-//  but will run more slowly when the input points are collinear or nearly   //
-//  so.                                                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL orient2dadapt(REAL* pa, REAL* pb, REAL* pc, REAL detsum)
-{
-  INEXACT REAL acx, acy, bcx, bcy;
-  REAL acxtail, acytail, bcxtail, bcytail;
-  INEXACT REAL detleft, detright;
-  REAL detlefttail, detrighttail;
-  REAL det, errbound;
-  REAL B[4], C1[8], C2[12], D[16];
-  INEXACT REAL B3;
-  int C1length, C2length, Dlength;
-  REAL u[4];
-  INEXACT REAL u3;
-  INEXACT REAL s1, t1;
-  REAL s0, t0;
-
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  INEXACT REAL c;
-  INEXACT REAL abig;
-  REAL ahi, alo, bhi, blo;
-  REAL err1, err2, err3;
-  INEXACT REAL _i, _j;
-  REAL _0;
-
-  acx = (REAL) (pa[0] - pc[0]);
-  bcx = (REAL) (pb[0] - pc[0]);
-  acy = (REAL) (pa[1] - pc[1]);
-  bcy = (REAL) (pb[1] - pc[1]);
-
-  Two_Product(acx, bcy, detleft, detlefttail);
-  Two_Product(acy, bcx, detright, detrighttail);
-
-  Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
-               B3, B[2], B[1], B[0]);
-  B[3] = B3;
-
-  det = estimate(4, B);
-  errbound = ccwerrboundB * detsum;
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
-  Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
-  Two_Diff_Tail(pa[1], pc[1], acy, acytail);
-  Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
-
-  if ((acxtail == 0.0) && (acytail == 0.0)
-      && (bcxtail == 0.0) && (bcytail == 0.0)) {
-    return det;
-  }
-
-  errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
-  det += (acx * bcytail + bcy * acxtail)
-       - (acy * bcxtail + bcx * acytail);
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  Two_Product(acxtail, bcy, s1, s0);
-  Two_Product(acytail, bcx, t1, t0);
-  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
-  u[3] = u3;
-  C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
-
-  Two_Product(acx, bcytail, s1, s0);
-  Two_Product(acy, bcxtail, t1, t0);
-  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
-  u[3] = u3;
-  C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
-
-  Two_Product(acxtail, bcytail, s1, s0);
-  Two_Product(acytail, bcxtail, t1, t0);
-  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
-  u[3] = u3;
-  Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
-
-  return(D[Dlength - 1]);
-}
-
-REAL orient2d(REAL* pa, REAL* pb, REAL* pc)
-{
-  REAL detleft, detright, det;
-  REAL detsum, errbound;
-
-  detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
-  detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
-  det = detleft - detright;
-
-  if (detleft > 0.0) {
-    if (detright <= 0.0) {
-      return det;
-    } else {
-      detsum = detleft + detright;
-    }
-  } else if (detleft < 0.0) {
-    if (detright >= 0.0) {
-      return det;
-    } else {
-      detsum = -detleft - detright;
-    }
-  } else {
-    return det;
-  }
-
-  errbound = ccwerrboundA * detsum;
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  return orient2dadapt(pa, pb, pc, detsum);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-//  orient3d()       Adaptive exact 3D orientation test.  Robust.            //
-//                                                                           //
-//               Return a positive value if the point pd lies below the      //
-//               plane passing through pa, pb, and pc; "below" is defined so //
-//               that pa, pb, and pc appear in counterclockwise order when   //
-//               viewed from above the plane.  Returns a negative value if   //
-//               pd lies above the plane.  Returns zero if the points are    //
-//               coplanar.  The result is also a rough approximation of six  //
-//               times the signed volume of the tetrahedron defined by the   //
-//               four points.                                                //
-//                                                                           //
-//  orient3d() use exact arithmetic to ensure a correct answer.  The result  //
-//  returned is the determinant of a matrix.  In orient3d() only, this       //
-//  determinant is computed adaptively, in the sense that exact arithmetic   //
-//  is used only to the degree it is needed to ensure that the returned      //
-//  value has the correct sign.  Hence, orient3d() is usually quite fast,    //
-//  but will run more slowly when the input points are coplanar or nearly    //
-//  so.                                                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL orient3dadapt(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL permanent)
-{
-  INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz;
-  REAL det, errbound;
-
-  INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
-  REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
-  REAL bc[4], ca[4], ab[4];
-  INEXACT REAL bc3, ca3, ab3;
-  REAL adet[8], bdet[8], cdet[8];
-  int alen, blen, clen;
-  REAL abdet[16];
-  int ablen;
-  REAL *finnow, *finother, *finswap;
-  REAL fin1[192], fin2[192];
-  int finlength;
-
-  REAL adxtail, bdxtail, cdxtail;
-  REAL adytail, bdytail, cdytail;
-  REAL adztail, bdztail, cdztail;
-  INEXACT REAL at_blarge, at_clarge;
-  INEXACT REAL bt_clarge, bt_alarge;
-  INEXACT REAL ct_alarge, ct_blarge;
-  REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
-  int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
-  INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
-  INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
-  REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
-  REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
-  INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
-  INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
-  REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
-  REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
-  REAL bct[8], cat[8], abt[8];
-  int bctlen, catlen, abtlen;
-  INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
-  INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
-  REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
-  REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
-  REAL u[4], v[12], w[16];
-  INEXACT REAL u3;
-  int vlength, wlength;
-  REAL negate;
-
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  INEXACT REAL c;
-  INEXACT REAL abig;
-  REAL ahi, alo, bhi, blo;
-  REAL err1, err2, err3;
-  INEXACT REAL _i, _j, _k;
-  REAL _0;
-
-  adx = (REAL) (pa[0] - pd[0]);
-  bdx = (REAL) (pb[0] - pd[0]);
-  cdx = (REAL) (pc[0] - pd[0]);
-  ady = (REAL) (pa[1] - pd[1]);
-  bdy = (REAL) (pb[1] - pd[1]);
-  cdy = (REAL) (pc[1] - pd[1]);
-  adz = (REAL) (pa[2] - pd[2]);
-  bdz = (REAL) (pb[2] - pd[2]);
-  cdz = (REAL) (pc[2] - pd[2]);
-
-  Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
-  Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
-  Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
-  bc[3] = bc3;
-  alen = scale_expansion_zeroelim(4, bc, adz, adet);
-
-  Two_Product(cdx, ady, cdxady1, cdxady0);
-  Two_Product(adx, cdy, adxcdy1, adxcdy0);
-  Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
-  ca[3] = ca3;
-  blen = scale_expansion_zeroelim(4, ca, bdz, bdet);
-
-  Two_Product(adx, bdy, adxbdy1, adxbdy0);
-  Two_Product(bdx, ady, bdxady1, bdxady0);
-  Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
-  ab[3] = ab3;
-  clen = scale_expansion_zeroelim(4, ab, cdz, cdet);
-
-  ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
-  finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
-
-  det = estimate(finlength, fin1);
-  errbound = o3derrboundB * permanent;
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
-  Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
-  Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
-  Two_Diff_Tail(pa[1], pd[1], ady, adytail);
-  Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
-  Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
-  Two_Diff_Tail(pa[2], pd[2], adz, adztail);
-  Two_Diff_Tail(pb[2], pd[2], bdz, bdztail);
-  Two_Diff_Tail(pc[2], pd[2], cdz, cdztail);
-
-  if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
-      && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)
-      && (adztail == 0.0) && (bdztail == 0.0) && (cdztail == 0.0)) {
-    return det;
-  }
-
-  errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
-  det += (adz * ((bdx * cdytail + cdy * bdxtail)
-                 - (bdy * cdxtail + cdx * bdytail))
-          + adztail * (bdx * cdy - bdy * cdx))
-       + (bdz * ((cdx * adytail + ady * cdxtail)
-                 - (cdy * adxtail + adx * cdytail))
-          + bdztail * (cdx * ady - cdy * adx))
-       + (cdz * ((adx * bdytail + bdy * adxtail)
-                 - (ady * bdxtail + bdx * adytail))
-          + cdztail * (adx * bdy - ady * bdx));
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  finnow = fin1;
-  finother = fin2;
-
-  if (adxtail == 0.0) {
-    if (adytail == 0.0) {
-      at_b[0] = 0.0;
-      at_blen = 1;
-      at_c[0] = 0.0;
-      at_clen = 1;
-    } else {
-      negate = -adytail;
-      Two_Product(negate, bdx, at_blarge, at_b[0]);
-      at_b[1] = at_blarge;
-      at_blen = 2;
-      Two_Product(adytail, cdx, at_clarge, at_c[0]);
-      at_c[1] = at_clarge;
-      at_clen = 2;
-    }
-  } else {
-    if (adytail == 0.0) {
-      Two_Product(adxtail, bdy, at_blarge, at_b[0]);
-      at_b[1] = at_blarge;
-      at_blen = 2;
-      negate = -adxtail;
-      Two_Product(negate, cdy, at_clarge, at_c[0]);
-      at_c[1] = at_clarge;
-      at_clen = 2;
-    } else {
-      Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
-      Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
-      Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
-                   at_blarge, at_b[2], at_b[1], at_b[0]);
-      at_b[3] = at_blarge;
-      at_blen = 4;
-      Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
-      Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
-      Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
-                   at_clarge, at_c[2], at_c[1], at_c[0]);
-      at_c[3] = at_clarge;
-      at_clen = 4;
-    }
-  }
-  if (bdxtail == 0.0) {
-    if (bdytail == 0.0) {
-      bt_c[0] = 0.0;
-      bt_clen = 1;
-      bt_a[0] = 0.0;
-      bt_alen = 1;
-    } else {
-      negate = -bdytail;
-      Two_Product(negate, cdx, bt_clarge, bt_c[0]);
-      bt_c[1] = bt_clarge;
-      bt_clen = 2;
-      Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
-      bt_a[1] = bt_alarge;
-      bt_alen = 2;
-    }
-  } else {
-    if (bdytail == 0.0) {
-      Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
-      bt_c[1] = bt_clarge;
-      bt_clen = 2;
-      negate = -bdxtail;
-      Two_Product(negate, ady, bt_alarge, bt_a[0]);
-      bt_a[1] = bt_alarge;
-      bt_alen = 2;
-    } else {
-      Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
-      Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
-      Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
-                   bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
-      bt_c[3] = bt_clarge;
-      bt_clen = 4;
-      Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
-      Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
-      Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
-                  bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
-      bt_a[3] = bt_alarge;
-      bt_alen = 4;
-    }
-  }
-  if (cdxtail == 0.0) {
-    if (cdytail == 0.0) {
-      ct_a[0] = 0.0;
-      ct_alen = 1;
-      ct_b[0] = 0.0;
-      ct_blen = 1;
-    } else {
-      negate = -cdytail;
-      Two_Product(negate, adx, ct_alarge, ct_a[0]);
-      ct_a[1] = ct_alarge;
-      ct_alen = 2;
-      Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
-      ct_b[1] = ct_blarge;
-      ct_blen = 2;
-    }
-  } else {
-    if (cdytail == 0.0) {
-      Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
-      ct_a[1] = ct_alarge;
-      ct_alen = 2;
-      negate = -cdxtail;
-      Two_Product(negate, bdy, ct_blarge, ct_b[0]);
-      ct_b[1] = ct_blarge;
-      ct_blen = 2;
-    } else {
-      Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
-      Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
-      Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
-                   ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
-      ct_a[3] = ct_alarge;
-      ct_alen = 4;
-      Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
-      Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
-      Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
-                   ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
-      ct_b[3] = ct_blarge;
-      ct_blen = 4;
-    }
-  }
-
-  bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
-  wlength = scale_expansion_zeroelim(bctlen, bct, adz, w);
-  finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
-                                          finother);
-  finswap = finnow; finnow = finother; finother = finswap;
-
-  catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
-  wlength = scale_expansion_zeroelim(catlen, cat, bdz, w);
-  finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
-                                          finother);
-  finswap = finnow; finnow = finother; finother = finswap;
-
-  abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
-  wlength = scale_expansion_zeroelim(abtlen, abt, cdz, w);
-  finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
-                                          finother);
-  finswap = finnow; finnow = finother; finother = finswap;
-
-  if (adztail != 0.0) {
-    vlength = scale_expansion_zeroelim(4, bc, adztail, v);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
-                                            finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (bdztail != 0.0) {
-    vlength = scale_expansion_zeroelim(4, ca, bdztail, v);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
-                                            finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (cdztail != 0.0) {
-    vlength = scale_expansion_zeroelim(4, ab, cdztail, v);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
-                                            finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-
-  if (adxtail != 0.0) {
-    if (bdytail != 0.0) {
-      Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
-      Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdz, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                              finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (cdztail != 0.0) {
-        Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdztail, u3, u[2], u[1], u[0]);
-        u[3] = u3;
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                                finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-    }
-    if (cdytail != 0.0) {
-      negate = -adxtail;
-      Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
-      Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdz, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                              finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (bdztail != 0.0) {
-        Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdztail, u3, u[2], u[1], u[0]);
-        u[3] = u3;
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                                finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-    }
-  }
-  if (bdxtail != 0.0) {
-    if (cdytail != 0.0) {
-      Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
-      Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adz, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                              finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (adztail != 0.0) {
-        Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adztail, u3, u[2], u[1], u[0]);
-        u[3] = u3;
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                                finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-    }
-    if (adytail != 0.0) {
-      negate = -bdxtail;
-      Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
-      Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdz, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                              finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (cdztail != 0.0) {
-        Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdztail, u3, u[2], u[1], u[0]);
-        u[3] = u3;
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                                finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-    }
-  }
-  if (cdxtail != 0.0) {
-    if (adytail != 0.0) {
-      Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
-      Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdz, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                              finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (bdztail != 0.0) {
-        Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdztail, u3, u[2], u[1], u[0]);
-        u[3] = u3;
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                                finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-    }
-    if (bdytail != 0.0) {
-      negate = -cdxtail;
-      Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
-      Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adz, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                              finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (adztail != 0.0) {
-        Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adztail, u3, u[2], u[1], u[0]);
-        u[3] = u3;
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
-                                                finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-    }
-  }
-
-  if (adztail != 0.0) {
-    wlength = scale_expansion_zeroelim(bctlen, bct, adztail, w);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
-                                            finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (bdztail != 0.0) {
-    wlength = scale_expansion_zeroelim(catlen, cat, bdztail, w);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
-                                            finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (cdztail != 0.0) {
-    wlength = scale_expansion_zeroelim(abtlen, abt, cdztail, w);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
-                                            finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-
-  return finnow[finlength - 1];
-}
-
-REAL orient3d(REAL* pa, REAL* pb, REAL* pc, REAL* pd)
-{
-  REAL adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz;
-  REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
-  REAL det;
-  REAL permanent, errbound;
-
-  adx = pa[0] - pd[0];
-  bdx = pb[0] - pd[0];
-  cdx = pc[0] - pd[0];
-  ady = pa[1] - pd[1];
-  bdy = pb[1] - pd[1];
-  cdy = pc[1] - pd[1];
-  adz = pa[2] - pd[2];
-  bdz = pb[2] - pd[2];
-  cdz = pc[2] - pd[2];
-
-  bdxcdy = bdx * cdy;
-  cdxbdy = cdx * bdy;
-
-  cdxady = cdx * ady;
-  adxcdy = adx * cdy;
-
-  adxbdy = adx * bdy;
-  bdxady = bdx * ady;
-
-  det = adz * (bdxcdy - cdxbdy)
-      + bdz * (cdxady - adxcdy)
-      + cdz * (adxbdy - bdxady);
-
-  permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adz)
-            + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdz)
-            + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdz);
-  errbound = o3derrboundA * permanent;
-  if ((det > errbound) || (-det > errbound)) {
-    return det;
-  }
-
-  return orient3dadapt(pa, pb, pc, pd, permanent);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-//  incircle()       Adaptive exact 2D incircle test.  Robust.               //
-//                                                                           //
-//               Return a positive value if the point pd lies inside the     //
-//               circle passing through pa, pb, and pc; a negative value if  //
-//               it lies outside; and zero if the four points are cocircular.//
-//               The points pa, pb, and pc must be in counterclockwise       //
-//               order, or the sign of the result will be reversed.          //
-//                                                                           //
-//  incircle() use exact arithmetic to ensure a correct answer.  The result  //
-//  returned is the determinant of a matrix.  In incircle() only, this       //
-//  determinant is computed adaptively, in the sense that exact arithmetic   //
-//  is used only to the degree it is needed to ensure that the returned      //
-//  value has the correct sign.  Hence, incircle() is usually quite fast,    //
-//  but will run more slowly when the input points are cocircular or nearly  //
-//  so.                                                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL incircleadapt(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL permanent)
-{
-  INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
-  REAL det, errbound;
-
-  INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
-  REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
-  REAL bc[4], ca[4], ab[4];
-  INEXACT REAL bc3, ca3, ab3;
-  REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
-  int axbclen, axxbclen, aybclen, ayybclen, alen;
-  REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
-  int bxcalen, bxxcalen, bycalen, byycalen, blen;
-  REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
-  int cxablen, cxxablen, cyablen, cyyablen, clen;
-  REAL abdet[64];
-  int ablen;
-  REAL fin1[1152], fin2[1152];
-  REAL *finnow, *finother, *finswap;
-  int finlength;
-
-  REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
-  INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
-  REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
-  REAL aa[4], bb[4], cc[4];
-  INEXACT REAL aa3, bb3, cc3;
-  INEXACT REAL ti1, tj1;
-  REAL ti0, tj0;
-  REAL u[4], v[4];
-  INEXACT REAL u3, v3;
-  REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
-  REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
-  int temp8len, temp16alen, temp16blen, temp16clen;
-  int temp32alen, temp32blen, temp48len, temp64len;
-  REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
-  int axtbblen, axtcclen, aytbblen, aytcclen;
-  REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
-  int bxtaalen, bxtcclen, bytaalen, bytcclen;
-  REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
-  int cxtaalen, cxtbblen, cytaalen, cytbblen;
-  REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
-  int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
-  REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
-  int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
-  REAL axtbctt[8], aytbctt[8], bxtcatt[8];
-  REAL bytcatt[8], cxtabtt[8], cytabtt[8];
-  int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
-  REAL abt[8], bct[8], cat[8];
-  int abtlen, bctlen, catlen;
-  REAL abtt[4], bctt[4], catt[4];
-  int abttlen, bcttlen, cattlen;
-  INEXACT REAL abtt3, bctt3, catt3;
-  REAL negate;
-
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  INEXACT REAL c;
-  INEXACT REAL abig;
-  REAL ahi, alo, bhi, blo;
-  REAL err1, err2, err3;
-  INEXACT REAL _i, _j;
-  REAL _0;
-
-  adx = (REAL) (pa[0] - pd[0]);
-  bdx = (REAL) (pb[0] - pd[0]);
-  cdx = (REAL) (pc[0] - pd[0]);
-  ady = (REAL) (pa[1] - pd[1]);
-  bdy = (REAL) (pb[1] - pd[1]);
-  cdy = (REAL) (pc[1] - pd[1]);
-
-  Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
-  Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
-  Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
-  bc[3] = bc3;
-  axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
-  axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
-  aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
-  ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
-  alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
-
-  Two_Product(cdx, ady, cdxady1, cdxady0);
-  Two_Product(adx, cdy, adxcdy1, adxcdy0);
-  Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
-  ca[3] = ca3;
-  bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
-  bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
-  bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
-  byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
-  blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
-
-  Two_Product(adx, bdy, adxbdy1, adxbdy0);
-  Two_Product(bdx, ady, bdxady1, bdxady0);
-  Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
-  ab[3] = ab3;
-  cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
-  cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
-  cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
-  cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
-  clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
-
-  ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
-  finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
-
-  det = estimate(finlength, fin1);
-  errbound = iccerrboundB * permanent;
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
-  Two_Diff_Tail(pa[1], pd[1], ady, adytail);
-  Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
-  Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
-  Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
-  Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
-  if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
-      && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
-    return det;
-  }
-
-  errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
-  det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
-                                     - (bdy * cdxtail + cdx * bdytail))
-          + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
-       + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
-                                     - (cdy * adxtail + adx * cdytail))
-          + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
-       + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
-                                     - (ady * bdxtail + bdx * adytail))
-          + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  finnow = fin1;
-  finother = fin2;
-
-  if ((bdxtail != 0.0) || (bdytail != 0.0)
-      || (cdxtail != 0.0) || (cdytail != 0.0)) {
-    Square(adx, adxadx1, adxadx0);
-    Square(ady, adyady1, adyady0);
-    Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
-    aa[3] = aa3;
-  }
-  if ((cdxtail != 0.0) || (cdytail != 0.0)
-      || (adxtail != 0.0) || (adytail != 0.0)) {
-    Square(bdx, bdxbdx1, bdxbdx0);
-    Square(bdy, bdybdy1, bdybdy0);
-    Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
-    bb[3] = bb3;
-  }
-  if ((adxtail != 0.0) || (adytail != 0.0)
-      || (bdxtail != 0.0) || (bdytail != 0.0)) {
-    Square(cdx, cdxcdx1, cdxcdx0);
-    Square(cdy, cdycdy1, cdycdy0);
-    Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
-    cc[3] = cc3;
-  }
-
-  if (adxtail != 0.0) {
-    axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
-    temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
-                                          temp16a);
-
-    axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
-    temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
-
-    axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
-    temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (adytail != 0.0) {
-    aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
-    temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
-                                          temp16a);
-
-    aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
-    temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
-
-    aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
-    temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (bdxtail != 0.0) {
-    bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
-    temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
-                                          temp16a);
-
-    bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
-    temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
-
-    bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
-    temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (bdytail != 0.0) {
-    bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
-    temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
-                                          temp16a);
-
-    bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
-    temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
-
-    bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
-    temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (cdxtail != 0.0) {
-    cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
-    temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
-                                          temp16a);
-
-    cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
-    temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
-
-    cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
-    temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (cdytail != 0.0) {
-    cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
-    temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
-                                          temp16a);
-
-    cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
-    temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
-
-    cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
-    temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-
-  if ((adxtail != 0.0) || (adytail != 0.0)) {
-    if ((bdxtail != 0.0) || (bdytail != 0.0)
-        || (cdxtail != 0.0) || (cdytail != 0.0)) {
-      Two_Product(bdxtail, cdy, ti1, ti0);
-      Two_Product(bdx, cdytail, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      negate = -bdy;
-      Two_Product(cdxtail, negate, ti1, ti0);
-      negate = -bdytail;
-      Two_Product(cdx, negate, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
-      v[3] = v3;
-      bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
-
-      Two_Product(bdxtail, cdytail, ti1, ti0);
-      Two_Product(cdxtail, bdytail, tj1, tj0);
-      Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
-      bctt[3] = bctt3;
-      bcttlen = 4;
-    } else {
-      bct[0] = 0.0;
-      bctlen = 1;
-      bctt[0] = 0.0;
-      bcttlen = 1;
-    }
-
-    if (adxtail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
-      axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
-      temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (bdytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-      if (cdytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-
-      temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
-                                            temp32a);
-      axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
-      temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-    if (adytail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
-      aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
-      temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-
-
-      temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
-                                            temp32a);
-      aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
-      temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-  }
-  if ((bdxtail != 0.0) || (bdytail != 0.0)) {
-    if ((cdxtail != 0.0) || (cdytail != 0.0)
-        || (adxtail != 0.0) || (adytail != 0.0)) {
-      Two_Product(cdxtail, ady, ti1, ti0);
-      Two_Product(cdx, adytail, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      negate = -cdy;
-      Two_Product(adxtail, negate, ti1, ti0);
-      negate = -cdytail;
-      Two_Product(adx, negate, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
-      v[3] = v3;
-      catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
-
-      Two_Product(cdxtail, adytail, ti1, ti0);
-      Two_Product(adxtail, cdytail, tj1, tj0);
-      Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
-      catt[3] = catt3;
-      cattlen = 4;
-    } else {
-      cat[0] = 0.0;
-      catlen = 1;
-      catt[0] = 0.0;
-      cattlen = 1;
-    }
-
-    if (bdxtail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
-      bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
-      temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (cdytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-      if (adytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-
-      temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
-                                            temp32a);
-      bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
-      temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-    if (bdytail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
-      bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
-      temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-
-
-      temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
-                                            temp32a);
-      bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
-      temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-  }
-  if ((cdxtail != 0.0) || (cdytail != 0.0)) {
-    if ((adxtail != 0.0) || (adytail != 0.0)
-        || (bdxtail != 0.0) || (bdytail != 0.0)) {
-      Two_Product(adxtail, bdy, ti1, ti0);
-      Two_Product(adx, bdytail, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      negate = -ady;
-      Two_Product(bdxtail, negate, ti1, ti0);
-      negate = -adytail;
-      Two_Product(bdx, negate, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
-      v[3] = v3;
-      abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
-
-      Two_Product(adxtail, bdytail, ti1, ti0);
-      Two_Product(bdxtail, adytail, tj1, tj0);
-      Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
-      abtt[3] = abtt3;
-      abttlen = 4;
-    } else {
-      abt[0] = 0.0;
-      abtlen = 1;
-      abtt[0] = 0.0;
-      abttlen = 1;
-    }
-
-    if (cdxtail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
-      cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
-      temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (adytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-      if (bdytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-
-      temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
-                                            temp32a);
-      cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
-      temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-    if (cdytail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
-      cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
-      temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-
-
-      temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
-                                            temp32a);
-      cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
-      temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-  }
-
-  return finnow[finlength - 1];
-}
-
-REAL incircle(REAL* pa, REAL* pb, REAL* pc, REAL* pd)
-{
-  REAL adx, bdx, cdx, ady, bdy, cdy;
-  REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
-  REAL alift, blift, clift;
-  REAL det;
-  REAL permanent, errbound;
-
-  adx = pa[0] - pd[0];
-  bdx = pb[0] - pd[0];
-  cdx = pc[0] - pd[0];
-  ady = pa[1] - pd[1];
-  bdy = pb[1] - pd[1];
-  cdy = pc[1] - pd[1];
-
-  bdxcdy = bdx * cdy;
-  cdxbdy = cdx * bdy;
-  alift = adx * adx + ady * ady;
-
-  cdxady = cdx * ady;
-  adxcdy = adx * cdy;
-  blift = bdx * bdx + bdy * bdy;
-
-  adxbdy = adx * bdy;
-  bdxady = bdx * ady;
-  clift = cdx * cdx + cdy * cdy;
-
-  det = alift * (bdxcdy - cdxbdy)
-      + blift * (cdxady - adxcdy)
-      + clift * (adxbdy - bdxady);
-
-  permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
-            + (Absolute(cdxady) + Absolute(adxcdy)) * blift
-            + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
-  errbound = iccerrboundA * permanent;
-  if ((det > errbound) || (-det > errbound)) {
-    return det;
-  }
-
-  return incircleadapt(pa, pb, pc, pd, permanent);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-//  insphere()       Adaptive exact 3D insphere test.  Robust.               //
-//                                                                           //
-//               Return a positive value if the point pe lies inside the     //
-//               sphere passing through pa, pb, pc, and pd; a negative value //
-//               if it lies outside; and zero if the five points are         //
-//               cospherical.  The points pa, pb, pc, and pd must be ordered //
-//               so that they have a positive orientation (as defined by     //
-//               orient3d()), or the sign of the result will be reversed.    //
-//                                                                           //
-//  insphere() use exact arithmetic to ensure a correct answer.  The result  //
-//  returned is the determinant of a matrix.  In insphere() only, this       //
-//  determinant is computed adaptively, in the sense that exact arithmetic   //
-//  is used only to the degree it is needed to ensure that the returned      //
-//  value has the correct sign.  Hence, insphere() is usually quite fast,    //
-//  but will run more slowly when the input points are cospherical or nearly //
-//  so.                                                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL insphereexact(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe)
-{
-  INEXACT REAL axby1, bxcy1, cxdy1, dxey1, exay1;
-  INEXACT REAL bxay1, cxby1, dxcy1, exdy1, axey1;
-  INEXACT REAL axcy1, bxdy1, cxey1, dxay1, exby1;
-  INEXACT REAL cxay1, dxby1, excy1, axdy1, bxey1;
-  REAL axby0, bxcy0, cxdy0, dxey0, exay0;
-  REAL bxay0, cxby0, dxcy0, exdy0, axey0;
-  REAL axcy0, bxdy0, cxey0, dxay0, exby0;
-  REAL cxay0, dxby0, excy0, axdy0, bxey0;
-  REAL ab[4], bc[4], cd[4], de[4], ea[4];
-  REAL ac[4], bd[4], ce[4], da[4], eb[4];
-  REAL temp8a[8], temp8b[8], temp16[16];
-  int temp8alen, temp8blen, temp16len;
-  REAL abc[24], bcd[24], cde[24], dea[24], eab[24];
-  REAL abd[24], bce[24], cda[24], deb[24], eac[24];
-  int abclen, bcdlen, cdelen, dealen, eablen;
-  int abdlen, bcelen, cdalen, deblen, eaclen;
-  REAL temp48a[48], temp48b[48];
-  int temp48alen, temp48blen;
-  REAL abcd[96], bcde[96], cdea[96], deab[96], eabc[96];
-  int abcdlen, bcdelen, cdealen, deablen, eabclen;
-  REAL temp192[192];
-  REAL det384x[384], det384y[384], det384z[384];
-  int xlen, ylen, zlen;
-  REAL detxy[768];
-  int xylen;
-  REAL adet[1152], bdet[1152], cdet[1152], ddet[1152], edet[1152];
-  int alen, blen, clen, dlen, elen;
-  REAL abdet[2304], cddet[2304], cdedet[3456];
-  int ablen, cdlen;
-  REAL deter[5760];
-  int deterlen;
-  int i;
-
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  INEXACT REAL c;
-  INEXACT REAL abig;
-  REAL ahi, alo, bhi, blo;
-  REAL err1, err2, err3;
-  INEXACT REAL _i, _j;
-  REAL _0;
-
-  Two_Product(pa[0], pb[1], axby1, axby0);
-  Two_Product(pb[0], pa[1], bxay1, bxay0);
-  Two_Two_Diff(axby1, axby0, bxay1, bxay0, ab[3], ab[2], ab[1], ab[0]);
-
-  Two_Product(pb[0], pc[1], bxcy1, bxcy0);
-  Two_Product(pc[0], pb[1], cxby1, cxby0);
-  Two_Two_Diff(bxcy1, bxcy0, cxby1, cxby0, bc[3], bc[2], bc[1], bc[0]);
-
-  Two_Product(pc[0], pd[1], cxdy1, cxdy0);
-  Two_Product(pd[0], pc[1], dxcy1, dxcy0);
-  Two_Two_Diff(cxdy1, cxdy0, dxcy1, dxcy0, cd[3], cd[2], cd[1], cd[0]);
-
-  Two_Product(pd[0], pe[1], dxey1, dxey0);
-  Two_Product(pe[0], pd[1], exdy1, exdy0);
-  Two_Two_Diff(dxey1, dxey0, exdy1, exdy0, de[3], de[2], de[1], de[0]);
-
-  Two_Product(pe[0], pa[1], exay1, exay0);
-  Two_Product(pa[0], pe[1], axey1, axey0);
-  Two_Two_Diff(exay1, exay0, axey1, axey0, ea[3], ea[2], ea[1], ea[0]);
-
-  Two_Product(pa[0], pc[1], axcy1, axcy0);
-  Two_Product(pc[0], pa[1], cxay1, cxay0);
-  Two_Two_Diff(axcy1, axcy0, cxay1, cxay0, ac[3], ac[2], ac[1], ac[0]);
-
-  Two_Product(pb[0], pd[1], bxdy1, bxdy0);
-  Two_Product(pd[0], pb[1], dxby1, dxby0);
-  Two_Two_Diff(bxdy1, bxdy0, dxby1, dxby0, bd[3], bd[2], bd[1], bd[0]);
-
-  Two_Product(pc[0], pe[1], cxey1, cxey0);
-  Two_Product(pe[0], pc[1], excy1, excy0);
-  Two_Two_Diff(cxey1, cxey0, excy1, excy0, ce[3], ce[2], ce[1], ce[0]);
-
-  Two_Product(pd[0], pa[1], dxay1, dxay0);
-  Two_Product(pa[0], pd[1], axdy1, axdy0);
-  Two_Two_Diff(dxay1, dxay0, axdy1, axdy0, da[3], da[2], da[1], da[0]);
-
-  Two_Product(pe[0], pb[1], exby1, exby0);
-  Two_Product(pb[0], pe[1], bxey1, bxey0);
-  Two_Two_Diff(exby1, exby0, bxey1, bxey0, eb[3], eb[2], eb[1], eb[0]);
-
-  temp8alen = scale_expansion_zeroelim(4, bc, pa[2], temp8a);
-  temp8blen = scale_expansion_zeroelim(4, ac, -pb[2], temp8b);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
-                                          temp16);
-  temp8alen = scale_expansion_zeroelim(4, ab, pc[2], temp8a);
-  abclen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
-                                       abc);
-
-  temp8alen = scale_expansion_zeroelim(4, cd, pb[2], temp8a);
-  temp8blen = scale_expansion_zeroelim(4, bd, -pc[2], temp8b);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
-                                          temp16);
-  temp8alen = scale_expansion_zeroelim(4, bc, pd[2], temp8a);
-  bcdlen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
-                                       bcd);
-
-  temp8alen = scale_expansion_zeroelim(4, de, pc[2], temp8a);
-  temp8blen = scale_expansion_zeroelim(4, ce, -pd[2], temp8b);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
-                                          temp16);
-  temp8alen = scale_expansion_zeroelim(4, cd, pe[2], temp8a);
-  cdelen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
-                                       cde);
-
-  temp8alen = scale_expansion_zeroelim(4, ea, pd[2], temp8a);
-  temp8blen = scale_expansion_zeroelim(4, da, -pe[2], temp8b);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
-                                          temp16);
-  temp8alen = scale_expansion_zeroelim(4, de, pa[2], temp8a);
-  dealen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
-                                       dea);
-
-  temp8alen = scale_expansion_zeroelim(4, ab, pe[2], temp8a);
-  temp8blen = scale_expansion_zeroelim(4, eb, -pa[2], temp8b);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
-                                          temp16);
-  temp8alen = scale_expansion_zeroelim(4, ea, pb[2], temp8a);
-  eablen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
-                                       eab);
-
-  temp8alen = scale_expansion_zeroelim(4, bd, pa[2], temp8a);
-  temp8blen = scale_expansion_zeroelim(4, da, pb[2], temp8b);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
-                                          temp16);
-  temp8alen = scale_expansion_zeroelim(4, ab, pd[2], temp8a);
-  abdlen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
-                                       abd);
-
-  temp8alen = scale_expansion_zeroelim(4, ce, pb[2], temp8a);
-  temp8blen = scale_expansion_zeroelim(4, eb, pc[2], temp8b);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
-                                          temp16);
-  temp8alen = scale_expansion_zeroelim(4, bc, pe[2], temp8a);
-  bcelen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
-                                       bce);
-
-  temp8alen = scale_expansion_zeroelim(4, da, pc[2], temp8a);
-  temp8blen = scale_expansion_zeroelim(4, ac, pd[2], temp8b);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
-                                          temp16);
-  temp8alen = scale_expansion_zeroelim(4, cd, pa[2], temp8a);
-  cdalen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
-                                       cda);
-
-  temp8alen = scale_expansion_zeroelim(4, eb, pd[2], temp8a);
-  temp8blen = scale_expansion_zeroelim(4, bd, pe[2], temp8b);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
-                                          temp16);
-  temp8alen = scale_expansion_zeroelim(4, de, pb[2], temp8a);
-  deblen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
-                                       deb);
-
-  temp8alen = scale_expansion_zeroelim(4, ac, pe[2], temp8a);
-  temp8blen = scale_expansion_zeroelim(4, ce, pa[2], temp8b);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp8blen, temp8b,
-                                          temp16);
-  temp8alen = scale_expansion_zeroelim(4, ea, pc[2], temp8a);
-  eaclen = fast_expansion_sum_zeroelim(temp8alen, temp8a, temp16len, temp16,
-                                       eac);
-
-  temp48alen = fast_expansion_sum_zeroelim(cdelen, cde, bcelen, bce, temp48a);
-  temp48blen = fast_expansion_sum_zeroelim(deblen, deb, bcdlen, bcd, temp48b);
-  for (i = 0; i < temp48blen; i++) {
-    temp48b[i] = -temp48b[i];
-  }
-  bcdelen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
-                                        temp48blen, temp48b, bcde);
-  xlen = scale_expansion_zeroelim(bcdelen, bcde, pa[0], temp192);
-  xlen = scale_expansion_zeroelim(xlen, temp192, pa[0], det384x);
-  ylen = scale_expansion_zeroelim(bcdelen, bcde, pa[1], temp192);
-  ylen = scale_expansion_zeroelim(ylen, temp192, pa[1], det384y);
-  zlen = scale_expansion_zeroelim(bcdelen, bcde, pa[2], temp192);
-  zlen = scale_expansion_zeroelim(zlen, temp192, pa[2], det384z);
-  xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
-  alen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, adet);
-
-  temp48alen = fast_expansion_sum_zeroelim(dealen, dea, cdalen, cda, temp48a);
-  temp48blen = fast_expansion_sum_zeroelim(eaclen, eac, cdelen, cde, temp48b);
-  for (i = 0; i < temp48blen; i++) {
-    temp48b[i] = -temp48b[i];
-  }
-  cdealen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
-                                        temp48blen, temp48b, cdea);
-  xlen = scale_expansion_zeroelim(cdealen, cdea, pb[0], temp192);
-  xlen = scale_expansion_zeroelim(xlen, temp192, pb[0], det384x);
-  ylen = scale_expansion_zeroelim(cdealen, cdea, pb[1], temp192);
-  ylen = scale_expansion_zeroelim(ylen, temp192, pb[1], det384y);
-  zlen = scale_expansion_zeroelim(cdealen, cdea, pb[2], temp192);
-  zlen = scale_expansion_zeroelim(zlen, temp192, pb[2], det384z);
-  xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
-  blen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, bdet);
-
-  temp48alen = fast_expansion_sum_zeroelim(eablen, eab, deblen, deb, temp48a);
-  temp48blen = fast_expansion_sum_zeroelim(abdlen, abd, dealen, dea, temp48b);
-  for (i = 0; i < temp48blen; i++) {
-    temp48b[i] = -temp48b[i];
-  }
-  deablen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
-                                        temp48blen, temp48b, deab);
-  xlen = scale_expansion_zeroelim(deablen, deab, pc[0], temp192);
-  xlen = scale_expansion_zeroelim(xlen, temp192, pc[0], det384x);
-  ylen = scale_expansion_zeroelim(deablen, deab, pc[1], temp192);
-  ylen = scale_expansion_zeroelim(ylen, temp192, pc[1], det384y);
-  zlen = scale_expansion_zeroelim(deablen, deab, pc[2], temp192);
-  zlen = scale_expansion_zeroelim(zlen, temp192, pc[2], det384z);
-  xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
-  clen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, cdet);
-
-  temp48alen = fast_expansion_sum_zeroelim(abclen, abc, eaclen, eac, temp48a);
-  temp48blen = fast_expansion_sum_zeroelim(bcelen, bce, eablen, eab, temp48b);
-  for (i = 0; i < temp48blen; i++) {
-    temp48b[i] = -temp48b[i];
-  }
-  eabclen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
-                                        temp48blen, temp48b, eabc);
-  xlen = scale_expansion_zeroelim(eabclen, eabc, pd[0], temp192);
-  xlen = scale_expansion_zeroelim(xlen, temp192, pd[0], det384x);
-  ylen = scale_expansion_zeroelim(eabclen, eabc, pd[1], temp192);
-  ylen = scale_expansion_zeroelim(ylen, temp192, pd[1], det384y);
-  zlen = scale_expansion_zeroelim(eabclen, eabc, pd[2], temp192);
-  zlen = scale_expansion_zeroelim(zlen, temp192, pd[2], det384z);
-  xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
-  dlen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, ddet);
-
-  temp48alen = fast_expansion_sum_zeroelim(bcdlen, bcd, abdlen, abd, temp48a);
-  temp48blen = fast_expansion_sum_zeroelim(cdalen, cda, abclen, abc, temp48b);
-  for (i = 0; i < temp48blen; i++) {
-    temp48b[i] = -temp48b[i];
-  }
-  abcdlen = fast_expansion_sum_zeroelim(temp48alen, temp48a,
-                                        temp48blen, temp48b, abcd);
-  xlen = scale_expansion_zeroelim(abcdlen, abcd, pe[0], temp192);
-  xlen = scale_expansion_zeroelim(xlen, temp192, pe[0], det384x);
-  ylen = scale_expansion_zeroelim(abcdlen, abcd, pe[1], temp192);
-  ylen = scale_expansion_zeroelim(ylen, temp192, pe[1], det384y);
-  zlen = scale_expansion_zeroelim(abcdlen, abcd, pe[2], temp192);
-  zlen = scale_expansion_zeroelim(zlen, temp192, pe[2], det384z);
-  xylen = fast_expansion_sum_zeroelim(xlen, det384x, ylen, det384y, detxy);
-  elen = fast_expansion_sum_zeroelim(xylen, detxy, zlen, det384z, edet);
-
-  ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
-  cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet);
-  cdelen = fast_expansion_sum_zeroelim(cdlen, cddet, elen, edet, cdedet);
-  deterlen = fast_expansion_sum_zeroelim(ablen, abdet, cdelen, cdedet, deter);
-
-  return deter[deterlen - 1];
-}
-
-REAL insphereadapt(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe, REAL permanent)
-{
-  INEXACT REAL aex, bex, cex, dex, aey, bey, cey, dey, aez, bez, cez, dez;
-  REAL det, errbound;
-
-  INEXACT REAL aexbey1, bexaey1, bexcey1, cexbey1;
-  INEXACT REAL cexdey1, dexcey1, dexaey1, aexdey1;
-  INEXACT REAL aexcey1, cexaey1, bexdey1, dexbey1;
-  REAL aexbey0, bexaey0, bexcey0, cexbey0;
-  REAL cexdey0, dexcey0, dexaey0, aexdey0;
-  REAL aexcey0, cexaey0, bexdey0, dexbey0;
-  REAL ab[4], bc[4], cd[4], da[4], ac[4], bd[4];
-  INEXACT REAL ab3, bc3, cd3, da3, ac3, bd3;
-  REAL abeps, bceps, cdeps, daeps, aceps, bdeps;
-  REAL temp8a[8], temp8b[8], temp8c[8], temp16[16], temp24[24], temp48[48];
-  int temp8alen, temp8blen, temp8clen, temp16len, temp24len, temp48len;
-  REAL xdet[96], ydet[96], zdet[96], xydet[192];
-  int xlen, ylen, zlen, xylen;
-  REAL adet[288], bdet[288], cdet[288], ddet[288];
-  int alen, blen, clen, dlen;
-  REAL abdet[576], cddet[576];
-  int ablen, cdlen;
-  REAL fin1[1152];
-  int finlength;
-
-  REAL aextail, bextail, cextail, dextail;
-  REAL aeytail, beytail, ceytail, deytail;
-  REAL aeztail, beztail, ceztail, deztail;
-
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  INEXACT REAL c;
-  INEXACT REAL abig;
-  REAL ahi, alo, bhi, blo;
-  REAL err1, err2, err3;
-  INEXACT REAL _i, _j;
-  REAL _0;
-
-  aex = (REAL) (pa[0] - pe[0]);
-  bex = (REAL) (pb[0] - pe[0]);
-  cex = (REAL) (pc[0] - pe[0]);
-  dex = (REAL) (pd[0] - pe[0]);
-  aey = (REAL) (pa[1] - pe[1]);
-  bey = (REAL) (pb[1] - pe[1]);
-  cey = (REAL) (pc[1] - pe[1]);
-  dey = (REAL) (pd[1] - pe[1]);
-  aez = (REAL) (pa[2] - pe[2]);
-  bez = (REAL) (pb[2] - pe[2]);
-  cez = (REAL) (pc[2] - pe[2]);
-  dez = (REAL) (pd[2] - pe[2]);
-
-  Two_Product(aex, bey, aexbey1, aexbey0);
-  Two_Product(bex, aey, bexaey1, bexaey0);
-  Two_Two_Diff(aexbey1, aexbey0, bexaey1, bexaey0, ab3, ab[2], ab[1], ab[0]);
-  ab[3] = ab3;
-
-  Two_Product(bex, cey, bexcey1, bexcey0);
-  Two_Product(cex, bey, cexbey1, cexbey0);
-  Two_Two_Diff(bexcey1, bexcey0, cexbey1, cexbey0, bc3, bc[2], bc[1], bc[0]);
-  bc[3] = bc3;
-
-  Two_Product(cex, dey, cexdey1, cexdey0);
-  Two_Product(dex, cey, dexcey1, dexcey0);
-  Two_Two_Diff(cexdey1, cexdey0, dexcey1, dexcey0, cd3, cd[2], cd[1], cd[0]);
-  cd[3] = cd3;
-
-  Two_Product(dex, aey, dexaey1, dexaey0);
-  Two_Product(aex, dey, aexdey1, aexdey0);
-  Two_Two_Diff(dexaey1, dexaey0, aexdey1, aexdey0, da3, da[2], da[1], da[0]);
-  da[3] = da3;
-
-  Two_Product(aex, cey, aexcey1, aexcey0);
-  Two_Product(cex, aey, cexaey1, cexaey0);
-  Two_Two_Diff(aexcey1, aexcey0, cexaey1, cexaey0, ac3, ac[2], ac[1], ac[0]);
-  ac[3] = ac3;
-
-  Two_Product(bex, dey, bexdey1, bexdey0);
-  Two_Product(dex, bey, dexbey1, dexbey0);
-  Two_Two_Diff(bexdey1, bexdey0, dexbey1, dexbey0, bd3, bd[2], bd[1], bd[0]);
-  bd[3] = bd3;
-
-  temp8alen = scale_expansion_zeroelim(4, cd, bez, temp8a);
-  temp8blen = scale_expansion_zeroelim(4, bd, -cez, temp8b);
-  temp8clen = scale_expansion_zeroelim(4, bc, dez, temp8c);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
-                                          temp8blen, temp8b, temp16);
-  temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
-                                          temp16len, temp16, temp24);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, aex, temp48);
-  xlen = scale_expansion_zeroelim(temp48len, temp48, -aex, xdet);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, aey, temp48);
-  ylen = scale_expansion_zeroelim(temp48len, temp48, -aey, ydet);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, aez, temp48);
-  zlen = scale_expansion_zeroelim(temp48len, temp48, -aez, zdet);
-  xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
-  alen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, adet);
-
-  temp8alen = scale_expansion_zeroelim(4, da, cez, temp8a);
-  temp8blen = scale_expansion_zeroelim(4, ac, dez, temp8b);
-  temp8clen = scale_expansion_zeroelim(4, cd, aez, temp8c);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
-                                          temp8blen, temp8b, temp16);
-  temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
-                                          temp16len, temp16, temp24);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, bex, temp48);
-  xlen = scale_expansion_zeroelim(temp48len, temp48, bex, xdet);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, bey, temp48);
-  ylen = scale_expansion_zeroelim(temp48len, temp48, bey, ydet);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, bez, temp48);
-  zlen = scale_expansion_zeroelim(temp48len, temp48, bez, zdet);
-  xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
-  blen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, bdet);
-
-  temp8alen = scale_expansion_zeroelim(4, ab, dez, temp8a);
-  temp8blen = scale_expansion_zeroelim(4, bd, aez, temp8b);
-  temp8clen = scale_expansion_zeroelim(4, da, bez, temp8c);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
-                                          temp8blen, temp8b, temp16);
-  temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
-                                          temp16len, temp16, temp24);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, cex, temp48);
-  xlen = scale_expansion_zeroelim(temp48len, temp48, -cex, xdet);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, cey, temp48);
-  ylen = scale_expansion_zeroelim(temp48len, temp48, -cey, ydet);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, cez, temp48);
-  zlen = scale_expansion_zeroelim(temp48len, temp48, -cez, zdet);
-  xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
-  clen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, cdet);
-
-  temp8alen = scale_expansion_zeroelim(4, bc, aez, temp8a);
-  temp8blen = scale_expansion_zeroelim(4, ac, -bez, temp8b);
-  temp8clen = scale_expansion_zeroelim(4, ab, cez, temp8c);
-  temp16len = fast_expansion_sum_zeroelim(temp8alen, temp8a,
-                                          temp8blen, temp8b, temp16);
-  temp24len = fast_expansion_sum_zeroelim(temp8clen, temp8c,
-                                          temp16len, temp16, temp24);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, dex, temp48);
-  xlen = scale_expansion_zeroelim(temp48len, temp48, dex, xdet);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, dey, temp48);
-  ylen = scale_expansion_zeroelim(temp48len, temp48, dey, ydet);
-  temp48len = scale_expansion_zeroelim(temp24len, temp24, dez, temp48);
-  zlen = scale_expansion_zeroelim(temp48len, temp48, dez, zdet);
-  xylen = fast_expansion_sum_zeroelim(xlen, xdet, ylen, ydet, xydet);
-  dlen = fast_expansion_sum_zeroelim(xylen, xydet, zlen, zdet, ddet);
-
-  ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
-  cdlen = fast_expansion_sum_zeroelim(clen, cdet, dlen, ddet, cddet);
-  finlength = fast_expansion_sum_zeroelim(ablen, abdet, cdlen, cddet, fin1);
-
-  det = estimate(finlength, fin1);
-  errbound = isperrboundB * permanent;
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  Two_Diff_Tail(pa[0], pe[0], aex, aextail);
-  Two_Diff_Tail(pa[1], pe[1], aey, aeytail);
-  Two_Diff_Tail(pa[2], pe[2], aez, aeztail);
-  Two_Diff_Tail(pb[0], pe[0], bex, bextail);
-  Two_Diff_Tail(pb[1], pe[1], bey, beytail);
-  Two_Diff_Tail(pb[2], pe[2], bez, beztail);
-  Two_Diff_Tail(pc[0], pe[0], cex, cextail);
-  Two_Diff_Tail(pc[1], pe[1], cey, ceytail);
-  Two_Diff_Tail(pc[2], pe[2], cez, ceztail);
-  Two_Diff_Tail(pd[0], pe[0], dex, dextail);
-  Two_Diff_Tail(pd[1], pe[1], dey, deytail);
-  Two_Diff_Tail(pd[2], pe[2], dez, deztail);
-  if ((aextail == 0.0) && (aeytail == 0.0) && (aeztail == 0.0)
-      && (bextail == 0.0) && (beytail == 0.0) && (beztail == 0.0)
-      && (cextail == 0.0) && (ceytail == 0.0) && (ceztail == 0.0)
-      && (dextail == 0.0) && (deytail == 0.0) && (deztail == 0.0)) {
-    return det;
-  }
-
-  errbound = isperrboundC * permanent + resulterrbound * Absolute(det);
-  abeps = (aex * beytail + bey * aextail)
-        - (aey * bextail + bex * aeytail);
-  bceps = (bex * ceytail + cey * bextail)
-        - (bey * cextail + cex * beytail);
-  cdeps = (cex * deytail + dey * cextail)
-        - (cey * dextail + dex * ceytail);
-  daeps = (dex * aeytail + aey * dextail)
-        - (dey * aextail + aex * deytail);
-  aceps = (aex * ceytail + cey * aextail)
-        - (aey * cextail + cex * aeytail);
-  bdeps = (bex * deytail + dey * bextail)
-        - (bey * dextail + dex * beytail);
-  det += (((bex * bex + bey * bey + bez * bez)
-           * ((cez * daeps + dez * aceps + aez * cdeps)
-              + (ceztail * da3 + deztail * ac3 + aeztail * cd3))
-           + (dex * dex + dey * dey + dez * dez)
-           * ((aez * bceps - bez * aceps + cez * abeps)
-              + (aeztail * bc3 - beztail * ac3 + ceztail * ab3)))
-          - ((aex * aex + aey * aey + aez * aez)
-           * ((bez * cdeps - cez * bdeps + dez * bceps)
-              + (beztail * cd3 - ceztail * bd3 + deztail * bc3))
-           + (cex * cex + cey * cey + cez * cez)
-           * ((dez * abeps + aez * bdeps + bez * daeps)
-              + (deztail * ab3 + aeztail * bd3 + beztail * da3))))
-       + 2.0 * (((bex * bextail + bey * beytail + bez * beztail)
-                 * (cez * da3 + dez * ac3 + aez * cd3)
-                 + (dex * dextail + dey * deytail + dez * deztail)
-                 * (aez * bc3 - bez * ac3 + cez * ab3))
-                - ((aex * aextail + aey * aeytail + aez * aeztail)
-                 * (bez * cd3 - cez * bd3 + dez * bc3)
-                 + (cex * cextail + cey * ceytail + cez * ceztail)
-                 * (dez * ab3 + aez * bd3 + bez * da3)));
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  return insphereexact(pa, pb, pc, pd, pe);
-}
-
-REAL insphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe)
-{
-  REAL aex, bex, cex, dex;
-  REAL aey, bey, cey, dey;
-  REAL aez, bez, cez, dez;
-  REAL aexbey, bexaey, bexcey, cexbey, cexdey, dexcey, dexaey, aexdey;
-  REAL aexcey, cexaey, bexdey, dexbey;
-  REAL alift, blift, clift, dlift;
-  REAL ab, bc, cd, da, ac, bd;
-  REAL abc, bcd, cda, dab;
-  REAL aezplus, bezplus, cezplus, dezplus;
-  REAL aexbeyplus, bexaeyplus, bexceyplus, cexbeyplus;
-  REAL cexdeyplus, dexceyplus, dexaeyplus, aexdeyplus;
-  REAL aexceyplus, cexaeyplus, bexdeyplus, dexbeyplus;
-  REAL det;
-  REAL permanent, errbound;
-
-  aex = pa[0] - pe[0];
-  bex = pb[0] - pe[0];
-  cex = pc[0] - pe[0];
-  dex = pd[0] - pe[0];
-  aey = pa[1] - pe[1];
-  bey = pb[1] - pe[1];
-  cey = pc[1] - pe[1];
-  dey = pd[1] - pe[1];
-  aez = pa[2] - pe[2];
-  bez = pb[2] - pe[2];
-  cez = pc[2] - pe[2];
-  dez = pd[2] - pe[2];
-
-  aexbey = aex * bey;
-  bexaey = bex * aey;
-  ab = aexbey - bexaey;
-  bexcey = bex * cey;
-  cexbey = cex * bey;
-  bc = bexcey - cexbey;
-  cexdey = cex * dey;
-  dexcey = dex * cey;
-  cd = cexdey - dexcey;
-  dexaey = dex * aey;
-  aexdey = aex * dey;
-  da = dexaey - aexdey;
-
-  aexcey = aex * cey;
-  cexaey = cex * aey;
-  ac = aexcey - cexaey;
-  bexdey = bex * dey;
-  dexbey = dex * bey;
-  bd = bexdey - dexbey;
-
-  abc = aez * bc - bez * ac + cez * ab;
-  bcd = bez * cd - cez * bd + dez * bc;
-  cda = cez * da + dez * ac + aez * cd;
-  dab = dez * ab + aez * bd + bez * da;
-
-  alift = aex * aex + aey * aey + aez * aez;
-  blift = bex * bex + bey * bey + bez * bez;
-  clift = cex * cex + cey * cey + cez * cez;
-  dlift = dex * dex + dey * dey + dez * dez;
-
-  det = (dlift * abc - clift * dab) + (blift * cda - alift * bcd);
-
-  aezplus = Absolute(aez);
-  bezplus = Absolute(bez);
-  cezplus = Absolute(cez);
-  dezplus = Absolute(dez);
-  aexbeyplus = Absolute(aexbey);
-  bexaeyplus = Absolute(bexaey);
-  bexceyplus = Absolute(bexcey);
-  cexbeyplus = Absolute(cexbey);
-  cexdeyplus = Absolute(cexdey);
-  dexceyplus = Absolute(dexcey);
-  dexaeyplus = Absolute(dexaey);
-  aexdeyplus = Absolute(aexdey);
-  aexceyplus = Absolute(aexcey);
-  cexaeyplus = Absolute(cexaey);
-  bexdeyplus = Absolute(bexdey);
-  dexbeyplus = Absolute(dexbey);
-  permanent = ((cexdeyplus + dexceyplus) * bezplus
-               + (dexbeyplus + bexdeyplus) * cezplus
-               + (bexceyplus + cexbeyplus) * dezplus)
-            * alift
-            + ((dexaeyplus + aexdeyplus) * cezplus
-               + (aexceyplus + cexaeyplus) * dezplus
-               + (cexdeyplus + dexceyplus) * aezplus)
-            * blift
-            + ((aexbeyplus + bexaeyplus) * dezplus
-               + (bexdeyplus + dexbeyplus) * aezplus
-               + (dexaeyplus + aexdeyplus) * bezplus)
-            * clift
-            + ((bexceyplus + cexbeyplus) * aezplus
-               + (cexaeyplus + aexceyplus) * bezplus
-               + (aexbeyplus + bexaeyplus) * cezplus)
-            * dlift;
-  errbound = isperrboundA * permanent;
-  if ((det > errbound) || (-det > errbound)) {
-    return det;
-  }
-
-  return insphereadapt(pa, pb, pc, pd, pe, permanent);
-}
diff --git a/Tetgen/quality.cpp b/Tetgen/quality.cpp
deleted file mode 100644
index 879673f8d8..0000000000
--- a/Tetgen/quality.cpp
+++ /dev/null
@@ -1,1723 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// quality.cpp    Implement the Delaunay Mesh Refinement Algorithm of        //
-//                Shewchuk[2] to generate an almost good mesh.               //
-//                                                                           //
-// Tetgen Version 1.0 beta                                                   //
-// November, 2001                                                            //
-//                                                                           //
-// Si hang                                                                   //
-// Email: sihang@weboo.com                                                   //
-// http://www.weboo.com/sh/tetgen.htm                                        //
-//                                                                           //
-// You are free to use, copy and modify the sources under certain            //
-// circumstances, provided this copyright notice remains intact.             //
-// See the file LICENSE for details.                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Generating a mesh whose elements have small aspect ratio and their sizes  //
-// conform to a given control spacing function is one of the most important  //
-// steps in numerical simulations. The aspect ratio of an element is usually //
-// defined as the ratio of the radius of its circumsphere to the radius of   //
-// its inscribed sphere. An alternative but weaker quality measurement is    //
-// radius-edge ratio, which is the ratio of the circumradius to the shortest //
-// edge length of the tetrahedron.                                           //
-//                                                                           //
-// In two-dimensions, many methods guaranteed to generate well-shaped meshes,//
-// such as the two-dimensional Delaunay refinement method of J. Ruppert[1].  //
-// Surprisingly, in three-dimensions, generating well-shaped meshes is       //
-// considerablely more difficult, because it is difficult to identify and    //
-// remove some bad-shaped tetrahedra(like sliver) from the mesh. Even so,    //
-// generating a three-dimensional mesh with small radius-edge ratio is well  //
-// understood. Shewchuk[2] extend the Ruppert's method to three-dimensions   //
-// by proving that all tetrahedron will have radius-edge ratio no more than  //
-// 2.                                                                        //
-//                                                                           //
-// In this file, I implement Shewchuk's algorithm to generate an almost good //
-// tetrahedral mesh with good grading effect. But there is no guarantee that //
-// slivers can be eliminated.  It can be done by an additional mesh smooth-  //
-// ing and mesh improvement routines. This algorithm does not guarantee to   //
-// terminate when there exists small angles in the domain. It may cause      //
-// infinite loop in boundary protection step. For Tetgen can terminate in    //
-// all conditions, I modified the algorithm slightly on the split encroached //
-// subfaces rule. When a encroached subface is determined, it not always be  //
-// splited, only there is no small angle at this subface(that is, angle      //
-// between suface-to-subface and subface-to-subsegment is not a small angle  //
-// (<=45 degree)). (I'm looking for a pleasant way to fix this problem.)     //
-// Despite these unpleasant facts, the Delaunay refinement algorithm falls   //
-// into the class of algorithms that usually outperform their worst-case     //
-// bounds. One can apply a tighter bound (as low as 1.1)on radius-edge ratio //
-// than the theory suggests is possible, or even apply bounds on dihedral    //
-// angles, and still produce a small, nicely graded mesh.                    //
-//                                                                           //
-// Refernces:                                                                //
-//                                                                           //
-// [1] Jim Ruppert, A Delaunay Refinement Algorithm for Quality Two-         //
-//     Dimensional Mesh Generation, Journal of Algorithms 18(3):548-585,     //
-//     May 1995.                                                             //
-// [2] Jonathan Richard Shewchuk, Delaunay Refinement Mesh Generation.       //
-//     PhD thesis, School of Computer Science, Carnegie Mellon University,   //
-//     May 1997.                                                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-#include "tetlib.h"
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dumplist()    Debug functions. Write the items of list to a text file.    //
-//                                                                           //
-// type = 0 tetrahedron, type = 1 subface, type = 2 subsegments.             //
-// If sort > 0, sort list before output.                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::dumplist(char* dumpfile, list* checklist, int type, int sort)
-{
-  FILE *outfile;
-  triface *checktet;
-  face *checksh;
-  point3d torg, tdest, tapex, toppo;
-  int i;
-
-  outfile = fopen(dumpfile, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("Error:  Cannot create file %s.\n", dumpfile);
-    return;
-  }
-  if (!quiet) {
-    printf("Writing %s.\n", dumpfile);
-  }
-  if (verbose < 1) {
-    numbernodes(1);
-  }
-  if (sort > 0) {
-    checklist->sort();
-  }
-  fprintf(outfile, "# Dumping %d items.\n", checklist->len());
-  for (i = 0; i < checklist->len(); i++) {
-    if (type == 0) {
-      checktet = (triface*)(*checklist)[i];
-      fprintf(outfile, "%4d  x%lx ", i, (unsigned long)(checktet->tet));
-      if (isdead(checktet)) {
-        fprintf(outfile, "(dead)\n");
-      } else {
-        org (*checktet, torg);
-        dest(*checktet, tdest);
-        apex(*checktet, tapex);
-        oppo(*checktet, toppo);
-        fprintf(outfile, "(%d, %d, %d, %d)\n", pointmark(torg),
-                pointmark(tdest), pointmark(tapex), pointmark(toppo));
-      }
-    } else if (type == 1) {
-      checksh = (face*)(*checklist)[i];
-      fprintf(outfile, "%4d  x%lx ", i, (unsigned long)(checksh->sh));
-      if (isdead(checksh)) {
-        fprintf(outfile, "(dead)\n");
-      } else {
-        sorg (*checksh, torg);
-        sdest(*checksh, tdest);
-        sapex(*checksh, tapex);
-        fprintf(outfile, "(%d, %d, %d)\n",
-                pointmark(torg), pointmark(tdest), pointmark(tapex));
-      }
-    } else if (type == 2) {
-      checksh = (face*)(*checklist)[i];
-      fprintf(outfile, "%4d  x%lx ", i, (unsigned long)(checksh->sh));
-      if (isdead(checksh)) {
-        fprintf(outfile, "(dead)\n");
-      } else {
-        sorg (*checksh, torg);
-        sdest(*checksh, tdest);
-        fprintf(outfile, "(%d, %d)\n", pointmark(torg), pointmark(tdest));
-      }
-    }
-  }
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Mesh quality testing routines                                             //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checkquality()    To test edges of the face is encroached if they are     //
-//                   subsegments, otherwise to test if it is encroached if   //
-//                   it is a subface, last to test if the two tets abuting   //
-//                   this face are good quality.                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::checkquality(triface* testface)
-{
-  if (shsegflaws) {
-    face testseg;
-    int i;
-    for (i = 0; i < 3; i++) {
-      enextself(*testface);
-      tsspivot(testface, &testseg);
-      if (testseg.sh != dummysh) {
-        uncheckedshseglist->append(&testseg);
-      }
-    }
-  }
-  if (shflaws) {
-    face testsh;
-    tspivot(*testface, testsh);
-    if (testsh.sh != dummysh) {
-      uncheckedshlist->append(&testsh);
-    }
-  }
-  if (tetflaws) {
-    triface neighbortet;
-    uncheckedtetlist->append(testface);
-    sym(*testface, neighbortet);
-    if (neighbortet.tet != dummytet) {
-      uncheckedtetlist->append(&neighbortet);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checkedge4encroach()    Check a segment to see if it is encroached; add   //
-//                         it to the list if it is.                          //
-//                                                                           //
-// An encroached segment is an unflippable edge that has a point in its      //
-// diametral sphere (that is, it faces an angle greater than 90 degrees).    //
-// This definition is due to Ruppert[1]. While in three dimension, A         //
-// subsegment is encroached if a vertex other than its endpoints lies inside //
-// or on its diametral sphere (that is, it faces an angle greater than or    //
-// equal 90 degrees). This definition is due to Shewchuk[2]. This definition //
-// of encroachment is slightly stronger than Ruppert's, to ensure that all   //
-// unencroached subsegments are strongly Delaunay.                           //
-//                                                                           //
-// Returns a nonzero value if the edge is encroached.                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-// Check whether the apex('eapex') is inside the diametral sphere of the
-//   subsegment(from 'eorg' to 'edest'). Pythagoras' Theorem is used to
-//   check whether the angle at the vertex is greater than 90 degrees.
-
-inline bool isedgeencroached(point3d eapex, point3d eorg, point3d edest)
-{
-  return (eapex[0] * (eorg[0] + edest[0]) +
-          eapex[1] * (eorg[1] + edest[1]) +
-          eapex[2] * (eorg[2] + edest[2]) >=
-          eapex[0] * eapex[0] + eorg[0] * edest[0] +
-          eapex[1] * eapex[1] + eorg[1] * edest[1] +
-          eapex[2] * eapex[2] + eorg[2] * edest[2]);
-}
-
-int mesh3d::checkedge4encroach(face *testedge, point3d testpoint)
-{
-  badface3d *badedge;
-  triface neighbortet, spintet;
-  triface tmptet;
-  face tmpseg;
-  point3d eorg, edest, eapex;
-  point3d torg, tdest, tapex;
-  int encroachflag, smallangleflag;
-  int hitbdry;
-
-  encroachflag = 0;
-  eorg = sorg(*testedge);
-  edest = sdest(*testedge);
-
-  if (testpoint == (point3d) NULL) {
-    // Spin around subsegment 'testedge', find all faces which contained
-    //   it. For each face, check whether its apex is inside the diametral
-    //   sphere of the 'testedge'.
-    sstpivot(testedge, &neighbortet);
-    spintet = neighbortet;
-    tapex = apex(neighbortet);
-    hitbdry = 0;
-    while (true) {
-      if (fnextself(spintet)) {
-        eapex = apex(spintet);
-        if (eapex == tapex) {
-          break; // Rewind, can leave now.
-        }
-        if (isedgeencroached(eapex, eorg, edest)) {
-          encroachflag = 1;
-          break;
-        }
-      } else {
-        hitbdry ++;
-        if (hitbdry >= 2) {
-          break;
-        } else {
-          esym(neighbortet, spintet);
-        }
-      }
-    }
-    if (!encroachflag) {
-      eapex = apex(neighbortet);
-      if (isedgeencroached(eapex, eorg, edest)) {
-        encroachflag = 1;
-      }
-    }
-  } else {
-    // Check does 'testedge' be encroached by 'testpoint'.
-    if ((testpoint != eorg) && (testpoint != edest)) {
-      if (isedgeencroached(testpoint, eorg, edest)) {
-        encroachflag = 1;
-        sstpivot(testedge, &neighbortet);
-      }
-    }
-  }
-
-  if (encroachflag && (!sinfected(*testedge)) &&
-      (!nobisect || ((nobisect == 1) && !isridge(&neighbortet)))) {
-    // 'testedge' is being encroached. It will be splitted by inserting its
-    //   midpoint.
-    // If 'testedge' is belong to one or more triangular faces which its
-    //  (or their) three edges are all subsegments. Don't insert midpoint.
-    //  Because it will create small angles which can't be removed by edge
-    //  flips.
-    spintet = neighbortet;
-    tapex = apex(neighbortet);
-    hitbdry = smallangleflag = 0;
-    while (true) {
-      if (fnextself(spintet)) {
-        eapex = apex(spintet);
-        if (eapex == tapex) {
-          break; // Rewind, can leave now.
-        }
-        tmptet = spintet;
-        enextself(tmptet);
-        tsspivot(&tmptet, &tmpseg);
-        if (tmpseg.sh != dummysh) {
-          enextself(tmptet);
-          tsspivot(&tmptet, &tmpseg);
-          if (tmpseg.sh != dummysh) {
-            smallangleflag = 1;
-            break;
-          }
-        }
-      } else {
-        hitbdry ++;
-        if (hitbdry >= 2) {
-          break;
-        } else {
-          esym(neighbortet, spintet);
-        }
-      }
-    }
-    if (!smallangleflag) {
-      tmptet = neighbortet;
-      enextself(tmptet);
-      tsspivot(&tmptet, &tmpseg);
-      if (tmpseg.sh != dummysh) {
-        enextself(tmptet);
-        tsspivot(&tmptet, &tmpseg);
-        if (tmpseg.sh != dummysh) {
-          smallangleflag = 1;
-        }
-      }
-    }
-
-    if (!smallangleflag) {
-      if (verbose > 2) {
-        printf("    Queueing encroached segment from %d to %d.\n",
-               pointmark(eorg), pointmark(edest));
-      }
-      // Add the shell edge to the list of encroached segments.
-      badedge = (badface3d *) badsegments.alloc();
-      badedge->shface = *testedge;
-      badedge->faceorg = eorg;
-      badedge->facedest = edest;
-    } else {
-      if (!quiet && verbose) {
-        printf("Warning:  Not split encroached subsegment:\n");
-        printf("  from (%.12g, %.12g, %.12g)\n",eorg[0], eorg[1], eorg[2]);
-        printf("  to   (%.12g, %.12g, %.12g)\n", edest[0], edest[1], edest[2]);
-      }
-      // Set a flag in 'testedge' to avoid multiple tests later.
-      //   Here temporarily use the tenth pointer ('testedge->sh[10]'), infect
-      //   its shver field.
-      sinfect(*testedge);
-    }
-  }
-
-  // The return value indicate 'testedge' is being encroached.
-  return encroachflag;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checkface4encroach()    Check a subface to see if it is encroached; add   //
-//                         it to the list if it is.                          //
-//                                                                           //
-// An encroached subface is an unflippable face that has a point lies in or  //
-// on its equatorial sphere. This definition is due to Shewchuk[2].          //
-//                                                                           //
-// A priority queue used for keep Encroached faces. Why? The question 's     //
-// answer could be found at Shewchuk's paper[2]:                             //
-//   ...                                                                     //
-//   One further amendment to the algorithm is necessary to obtain the best  //
-// possible bound on the circumradius-to-shortest edge ratios of the tetrah- //
-// edra. When several encroached subfacets exist, they should not be split   //
-// in arbitrary order. If a vertex p encroaches upon a subfacet f of a facet //
-// F, but the projection of p to F dest not lie in f,  then splitting f is   //
-// not the best choice. One can show(Lemma 1) that there is some subfacet g  //
-// of F that is encroached upon by p and contain the projection point of p   //
-// to F. (The lemma assume that there are no encroached subsegments in the   //
-// mesh, as they have priority.) A better bound is achieved if the algorithm //
-// splits g first and delays the splitting of f indefinitely.                //
-//   ...                                                                     //
-//                                                                           //
-// Returns a nonzero value if the edge is encroached.                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::checkface4encroach(face* testface, point3d testpoint)
-{
-  triface testtet, tmptet, tmptmptet;
-  face testsh, neighborsh;
-  point3d forg, fdest, fapex, foppo;
-  enum locateresult loc;
-  REAL cent[3], proj[3];
-  REAL dx, dy, dz;
-  REAL radius2, dist2;
-  int encroachflag;
-
-  // If its a nonsolid face, need not check.
-  if (isnonsolid(*testface)) return 0;
-
-  // Find circumcenter of the face.
-  forg = sorg(*testface);
-  fdest = sdest(*testface);
-  fapex = sapex(*testface);
-  if ((testpoint != (point3d) NULL) &&
-      ((testpoint == forg) || (testpoint == fdest) || (testpoint == fapex))) {
-    return 0;
-  }
-  circumcenter(forg, fdest, fapex, cent);
-
-  // Get the square radius of equatorial sphere.
-  dx = forg[0] - cent[0];
-  dy = forg[1] - cent[1];
-  dz = forg[2] - cent[2];
-  radius2 = dx * dx + dy * dy + dz * dz;
-
-  encroachflag = 0;
-  if (testpoint == (point3d) NULL) {
-    // Check two opposite vertex to find encroaching point.
-    testsh = *testface;
-    stpivot(testsh, testtet);
-    if (testtet.tet != dummytet) {
-      foppo = oppo(testtet);
-      dx = foppo[0] - cent[0];
-      dy = foppo[1] - cent[1];
-      dz = foppo[2] - cent[2];
-      dist2 = dx * dx + dy * dy + dz * dz;
-      if (dist2 <= radius2) {
-        encroachflag = 1;
-      }
-    }
-    if (!encroachflag) {
-      sesymself(testsh);
-      stpivot(testsh, testtet);
-      if (testtet.tet != dummytet) {
-        foppo = oppo(testtet);
-        dx = foppo[0] - cent[0];
-        dy = foppo[1] - cent[1];
-        dz = foppo[2] - cent[2];
-        dist2 = dx * dx + dy * dy + dz * dz;
-        if (dist2 <= radius2) {
-          encroachflag = 1;
-        }
-      }
-    }
-  } else {
-    foppo = testpoint;
-    dx = foppo[0] - cent[0];
-    dy = foppo[1] - cent[1];
-    dz = foppo[2] - cent[2];
-    dist2 = dx * dx + dy * dy + dz * dz;
-    if (dist2 <= radius2) {
-      encroachflag = 1;
-      testsh = *testface;
-      stpivot(testsh, testtet);
-      if (testtet.tet == dummytet) {
-        sesymself(testsh);
-        stpivot(testsh, testtet);
-        assert(testtet.tet != dummytet);
-      }
-    }
-  }
-
-  if (encroachflag) {
-    // Before add it to bad face queue, we need check its project point
-    //   of this face to determine which queue(0 or 1) it should keep.
-    proj[0] = foppo[0];
-    proj[1] = foppo[1];
-    proj[2] = foppo[2];
-    projontoface(forg, fdest, fapex, proj);
-    loc = iscoplanarintri(proj, &testtet);
-    if (loc != OUTSIDE) {
-      enqueuebadface(testface, cent, 1);
-    } else {
-      enqueuebadface(testface, cent, 0);
-    }
-  }
-
-  return encroachflag;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// testtetrahedron()    Test a tetrahedron for quality measures.             //
-//                                                                           //
-// Tests a tetrahedron to see if it satisfies the minimum ratio condition    //
-// and the maximum volume condition. Tetrahedra that aren't upto spec are    //
-// added to the bad tetrahedron queue.                                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::testtetrahedron(triface* testtet)
-{
-  point3d torg, tdest, tapex, toppo;
-  REAL dxod, dyod, dzod, dxda, dyda, dzda, dxao, dyao, dzao;
-  REAL dxop, dyop, dzop, dxdp, dydp, dzdp, dxap, dyap, dzap;
-  REAL dxod2, dyod2, dzod2, dxda2, dyda2, dzda2, dxao2, dyao2, dzao2;
-  REAL dxop2, dyop2, dzop2, dxdp2, dydp2, dzdp2, dxap2, dyap2, dzap2;
-  REAL dxoc, dyoc, dzoc, dxoc2, dyoc2, dzoc2;
-  REAL edgelen[6], cent[3], smedgelen, radius, ratio2, volume;
-  int i;
-
-  torg = org(*testtet);
-  tdest = dest(*testtet);
-  tapex = apex(*testtet);
-  toppo = oppo(*testtet);
-
-  dxod = torg[0] - tdest[0];
-  dyod = torg[1] - tdest[1];
-  dzod = torg[2] - tdest[2];
-  dxda = tdest[0] - tapex[0];
-  dyda = tdest[1] - tapex[1];
-  dzda = tdest[2] - tapex[2];
-  dxao = tapex[0] - torg[0];
-  dyao = tapex[1] - torg[1];
-  dzao = tapex[2] - torg[2];
-
-  dxop = torg[0] - toppo[0];
-  dyop = torg[1] - toppo[1];
-  dzop = torg[2] - toppo[2];
-  dxdp = tdest[0] - toppo[0];
-  dydp = tdest[1] - toppo[1];
-  dzdp = tdest[2] - toppo[2];
-  dxap = tapex[0] - toppo[0];
-  dyap = tapex[1] - toppo[1];
-  dzap = tapex[2] - toppo[2];
-
-  dxod2 = dxod * dxod;
-  dyod2 = dyod * dyod;
-  dzod2 = dzod * dzod;
-  dxda2 = dxda * dxda;
-  dyda2 = dyda * dyda;
-  dzda2 = dzda * dzda;
-  dxao2 = dxao * dxao;
-  dyao2 = dyao * dyao;
-  dzao2 = dzao * dzao;
-
-  dxop2 = dxop * dxop;
-  dyop2 = dyop * dyop;
-  dzop2 = dzop * dzop;
-  dxdp2 = dxdp * dxdp;
-  dydp2 = dydp * dydp;
-  dzdp2 = dzdp * dzdp;
-  dxap2 = dxap * dxap;
-  dyap2 = dyap * dyap;
-  dzap2 = dzap * dzap;
-
-  // Find the lengths of the tetrahedron's siz edges.
-  edgelen[0] = dxod2 + dyod2 + dzod2;
-  edgelen[1] = dxda2 + dyda2 + dzda2;
-  edgelen[2] = dxao2 + dyao2 + dzao2;
-  edgelen[3] = dxop2 + dyop2 + dzop2;
-  edgelen[4] = dxdp2 + dydp2 + dzdp2;
-  edgelen[5] = dxap2 + dyap2 + dzap2;
-
-  smedgelen = edgelen[0];
-  for (i = 1; i < 6; i++) {
-    if (smedgelen > edgelen[i]) smedgelen = edgelen[i];
-  }
-  if (smedgelen <= usertolerance) {
-    printf("Precssion error in testtetrahedron(): \n");
-    printf("  The shortest edge length %.12g is smaller than tolerance.\n",
-           smedgelen);
-    printf("  This probably means that I am trying to refine mesh to a\n");
-    printf("    smaller size than can be accommodated by the finite \n");
-    printf("    precision of floating point arithmetic. \n");
-    precisionerror();
-  }
-
-  circumcenter(torg, tdest, tapex, toppo, cent);
-
-  dxoc = torg[0] - cent[0];
-  dyoc = torg[1] - cent[1];
-  dzoc = torg[2] - cent[2];
-  dxoc2 = dxoc * dxoc;
-  dyoc2 = dyoc * dyoc;
-  dzoc2 = dzoc * dzoc;
-
-  radius = dxoc2 + dyoc2 + dzoc2;
-  ratio2 = radius / smedgelen;
-
-  // Check whether the ratio is smaller than permitted.
-  if (ratio2 > goodratio) {
-    // It's a bad-shaped tet, before we decide to split it, we need check
-    //   if this bad-shaped tet is les on boundary with a small (dihedral)
-    //   angle. If so, we should not split it, or it maybe cause endless
-    //   loop until run out of your machine's precission.
-    // Not done yet.
-    // Add this tet to the list of bad tetrahedra.
-    enqueuebadtet(testtet, ratio2, torg, tdest, tapex, toppo, cent);
-    return;
-  }
-  if (varvolume || fixedvolume) {
-    // Check whether the volume is larger than permitted.
-    volume = tetvolume(torg, tdest, tapex, toppo);
-    if (volume < 0) volume = -volume;
-    if (fixedvolume && (volume > maxvolume)) {
-      // Add this tetrahedron to the list of bad tetrahedra.
-      enqueuebadtet(testtet, 0, torg, tdest, tapex, toppo, cent);
-    } else if (varvolume) {
-      // Nonpositive volume constraints are treated as unconstrained.
-      if ((volume > volumebound(testtet->tet)) &&
-          (volumebound(testtet->tet) > 0.0)) {
-        // Add this tetrahedron to the list of bad tetrahedron.
-        enqueuebadtet(testtet, 0, torg, tdest, tapex, toppo, cent);
-      }
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// enqueuebadface()    Add a bad subface to the end of a queue.              //
-//                                                                           //
-// The queue is actually a set of 2 queues.  'rank' should be 0 or 1.        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::enqueuebadface(face *insface, point3d inscent, int rank)
-{
-  badface3d *newface;
-
-  if (verbose > 2) {
-    printf("    Queueing bad face: (%d, %d, %d) rank %i.\n",
-           pointmark(sorg(*insface)), pointmark(sdest(*insface)),
-           pointmark(sapex(*insface)), rank);
-  }
-  // Allocate space for the bad face.
-  newface = (badface3d *) badfaces.alloc();
-  newface->shface = *insface;
-  if (inscent != NULL) {
-    // We need not re-calculate circumcenter when split face.
-    newface->badfacetet.tet = dummytet;
-    newface->cent[0] = inscent[0];
-    newface->cent[1] = inscent[1];
-    newface->cent[2] = inscent[2];
-  } else {
-    // We need re-calculate circumcenter when split face.
-    newface->badfacetet.tet = (tetrahedron *) NULL;
-  }
-  sapex(*insface, newface->faceapex);
-  sorg(*insface, newface->faceorg);
-  sdest(*insface, newface->facedest);
-  newface->nextface = (badface3d *) NULL;
-  // Add the face to the end of a queue.
-  *facequetail[rank] = newface;
-  // Maintain a pointer to the NULL pointer at the end of the queue.
-  facequetail[rank] = &newface->nextface;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dequeuebadface()    Remove a face from the front of the queue.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-badface3d* mesh3d::dequeuebadface()
-{
-  badface3d *result;
-  int queuenumber;
-
-  // Look for a nonempty queue.
-  for (queuenumber = 1; queuenumber >= 0; queuenumber--) {
-    result = facequefront[queuenumber];
-    if (result != (badface3d *) NULL) {
-      // Remove the face from the queue.
-      facequefront[queuenumber] = result->nextface;
-      // Maintain a pointer to the NULL pointer at the end of the queue.
-      if (facequefront[queuenumber] == (badface3d *) NULL) {
-        facequetail[queuenumber] = &facequefront[queuenumber];
-      }
-      return result;
-    }
-  }
-  return (badface3d *) NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// enqueuebadtet()    Add a bad tetrahedron to the end of a queue.           //
-//                                                                           //
-// The queue is actually a set of 64 queues.                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::enqueuebadtet(triface *instet, REAL ratio, point3d insorg,
-                           point3d insdest, point3d insapex, point3d insoppo,
-                           point3d inscent)
-{
-  badtet *newtet;
-  int queuenumber;
-
-  // Allocate space for the bad tetrahedron.
-  newtet = (badtet *) badtets.alloc();
-  newtet->btet = *instet;
-  newtet->key = ratio;
-  newtet->cent[0] = inscent[0];
-  newtet->cent[1] = inscent[1];
-  newtet->cent[2] = inscent[2];
-  newtet->tetorg = insorg;
-  newtet->tetdest = insdest;
-  newtet->tetapex = insapex;
-  newtet->tetoppo = insoppo;
-  newtet->nexttet = (badtet *) NULL;
-  // Determine the appropriate queue to put the bad tetrahedron into.
-  if (ratio > goodratio) { // square of 1.414
-    queuenumber = (int) ((ratio - goodratio) / 0.5);
-    if (queuenumber > 63) {
-      queuenumber = 63;
-    } else if (queuenumber < 0) {
-      // The integer overflow( caused by a very large ratio.)
-      queuenumber = 63;
-    }
-  } else {
-    // It's not a bad ratio; put the tetrahedron in the lowest-priority
-    //   queue.
-    queuenumber = 0;
-  }
-  // Add the tetrahedron to the end of a queue.
-  *tetquetail[queuenumber] = newtet;
-  // Maintain a pointer to the NULL pointer at the end of the queue.
-  tetquetail[queuenumber] = &newtet->nexttet;
-
-  if (verbose > 2) {
-    printf("    Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
-           pointmark(insorg), pointmark(insdest), pointmark(insapex),
-           pointmark(insoppo), sqrt(ratio), queuenumber);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dequeuebadtet()    Remove a tetrahedron from the front of the queue.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-badtet* mesh3d::dequeuebadtet()
-{
-  badtet *result;
-  int queuenumber;
-
-  // Look for a nonempty queue.
-  for (queuenumber = 63; queuenumber >= 0; queuenumber--) {
-    result = tetquefront[queuenumber];
-    if (result != (badtet *) NULL) {
-      // Remove the tetrahedron from the queue.
-      tetquefront[queuenumber] = result->nexttet;
-      // Maintain a pointer to the NULL pointer at the end of the queue.
-      if (tetquefront[queuenumber] == (badtet *) NULL) {
-        tetquetail[queuenumber] = &tetquefront[queuenumber];
-      }
-      return result;
-    }
-  }
-  return (badtet *) NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tallyencsegs()   Traverse the entire list of shell edges, check each edge //
-//                  to see if it is encroached.  If so, add it to the list.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::tallyencsegs()
-{
-  face edgeloop;
-
-  if (verbose) {
-    printf("  Making a list of encroached segments.\n");
-  }
-  subsegs.traversalinit();
-  edgeloop.shver = 0;
-  edgeloop.sh = shellfacetraverse(&subsegs);
-  while (edgeloop.sh != (shellface *) NULL) {
-    // If the segment is encroached, add it to the list.
-    checkedge4encroach(&edgeloop);
-    edgeloop.sh = shellfacetraverse(&subsegs);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tallyencfaces()     Traverse the entire list of shell faces, check each   //
-//                     face to see if it is encroached.  If so, add it to    //
-//                     the list.                                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::tallyencfaces()
-{
-  face faceloop;
-
-  if (verbose) {
-    printf("  Making a list of encroached subfaces.\n");
-  }
-  subfaces.traversalinit();
-  faceloop.shver = 0;
-  faceloop.sh = shellfacetraverse(&subfaces);
-  while (faceloop.sh != (shellface *) NULL) {
-    // If the subface is encroached, add it to the list.
-    checkface4encroach(&faceloop);
-    faceloop.sh = shellfacetraverse(&subfaces);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tallytets()     Traverse the entire list of tetrahedra, check each tet to //
-//                 see if it is bad quality.  If so, add it to the list.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::tallytets()
-{
-  triface tetloop;
-
-  if (verbose) {
-    printf("  Making a list of bad tetrahedra.\n");
-  }
-  tetrahedrons.traversalinit();
-  tetloop.loc = 0;
-  tetloop.ver = 0;
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    testtetrahedron(&tetloop);
-    tetloop.tet = tetrahedrontraverse();
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Mesh quality testing routines                                             //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Mesh quality maintenance routines                                         //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// repairencsegs()    Find and repair all the encroached segments.           //
-//                                                                           //
-// Encroached segments are repaired by splitting them by inserting a point   //
-// at or near their centers.                                                 //
-//                                                                           //
-// When a segment is split, the two resulting subsegments are always tested  //
-// to see if they are encroached upon, regardless of the value of 'flaws'.   //                                                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::repairencsegs()
-{
-  badface3d *encloop;
-  triface enctet;
-  triface *checktet, *skiptet;
-  face *checksh, *skipsh;
-  point3d eorg, edest;
-  point3d newpoint;
-  REAL segmentlength, nearestpoweroftwo;
-  REAL split;
-  int acuteorg, acutedest;
-  int flipcount;
-  int i;
-
-  while ((badsegments.items > 0) && (steinerleft != 0)) {
-    badsegments.traversalinit();
-    encloop = badsegmenttraverse();
-    while ((encloop != (badface3d *) NULL) && (steinerleft != 0)) {
-      // Check this edge is not splitted.
-      eorg = sorg(encloop->shface);
-      edest = sdest(encloop->shface);
-      if (((eorg != (point3d) NULL) && (edest != (point3d) NULL)) &&
-          ((eorg == encloop->faceorg) && (edest == encloop->facedest))) {
-        // To decide where to split a segment, we need to know if the
-        //   segment shares an endpoint with an adjacent segment.
-        //   The concern is that, if we simply split every encroached
-        //   segment in its center, two adjacent segments with a small
-        //   angle between them might lead to an infinite loop; each
-        //   point added to split one segment will encroach upon the
-        //   other segment, which must then be split with a point that
-        //   will encroach upon the first segment, and so on forever.
-        // To avoid this, imagine a set of concentric circles, whose
-        //   radii are powers of two, about each segment endpoint.
-        //   These concentric circles determine where the segment is
-        //   split.  (If both endpoints are shared with adjacent
-        //   segments, split the segment in the middle, and apply the
-        //   concentric shells for later splittings.)
-
-        // Is the origin shared with another segment?
-        acuteorg = isexistincidentseg(&(encloop->shface));
-        // Is the destination shared with another segment?
-        sesymself(encloop->shface);
-        acutedest = isexistincidentseg(&(encloop->shface));
-        sesymself(encloop->shface);
-
-        // Use the concentric circles if exactly one endpoint is shared
-        //   with another adjacent segment.
-        if (acuteorg ^ acutedest) {
-          segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0])
-                               + (edest[1] - eorg[1]) * (edest[1] - eorg[1])
-                               + (edest[2] - eorg[2]) * (edest[2] - eorg[2]));
-          // Find the power of two nearest the segment's length.
-          nearestpoweroftwo = 1.0;
-          while (segmentlength > SQUAREROOTTWO * nearestpoweroftwo) {
-            nearestpoweroftwo *= 2.0;
-          }
-          while (segmentlength < (0.5 * SQUAREROOTTWO) * nearestpoweroftwo) {
-            nearestpoweroftwo *= 0.5;
-          }
-          // Where do we split the segment?
-          split = 0.5 * nearestpoweroftwo / segmentlength;
-          if (acutedest) {
-            split = 1.0 - split;
-          }
-        } else {
-          // If we're not worried about adjacent segments, split
-          //   this segment in the middle.
-          split = 0.5;
-        }
-
-        // Create the new point.
-        newpoint = (point3d) points.alloc();
-        // Interpolate its coordinate and attributes.
-        for (i = 0; i < 3 + nextras; i++) {
-          newpoint[i] = (1.0 - split) * eorg[i] + split * edest[i];
-        }
-        // The new point must lies on subsegment.
-        setpointmark(newpoint, mark(encloop->shface));
-        if (verbose > 1) {
-          // Set pointmark of newpoint for Debuging outputs.
-          setpointmark(newpoint, points.items);
-        }
-        // Check whether the new point lies on an endpoint.
-        if ((compare2points(&newpoint, &eorg) == 0) ||
-            (compare2points(&newpoint, &edest) == 0)) {
-          printf("Error:  Ran out of precision at (%.12g, %.12g, %.12g).\n",
-                 newpoint[0], newpoint[1], newpoint[2]);
-          printf("  I attempted to split a segment to a smaller size than\n");
-          printf("    can be accommodated by the finite precision of floating\n");
-          printf("    point arithmetic.\n");
-          precisionerror();
-        }
-        if (verbose > 1) {
-          printf("  Insert circumcenter: (%.12g, %.12g, %.12g) %d\n",
-                 newpoint[0], newpoint[1], newpoint[2], pointmark(newpoint));
-          printf("    to split subsegment (%d, %d).\n",
-                 pointmark(eorg), pointmark(edest));
-        }
-        if (shsegflaws) {
-          uncheckedshseglist->clear();
-        }
-        if (shflaws) {
-          uncheckedshlist->clear();
-        }
-        if (tetflaws) {
-          uncheckedtetlist->clear();
-        }
-        // Find a tetra contain this subsegment.
-        sstpivot(&(encloop->shface), &enctet);
-        findversion(&enctet, &(encloop->shface));
-        // Insert the splitting point.  This should always succssed.
-        flipcount = insertonedge(newpoint, &enctet, &(encloop->shface));
-        if (verbose > 1) {
-          printf("  Successfully split subsegment with %d flips.\n", flipcount);
-        }
-        if (steinerleft > 0) {
-          steinerleft--;
-        }
-        // Check all encroached segments, subfaces and bad tetrahedra caused
-        //   by insert this point if there need.
-        if (shsegflaws && (uncheckedshseglist->len() > 0)) {
-          uncheckedshseglist->sort();
-          skipsh = checksh = (face*)(*uncheckedshseglist)[0];
-          if (!isdead(checksh)) {
-            checkedge4encroach(checksh);
-          }
-          for (i = 1; i < uncheckedshseglist->len(); i++) {
-            checksh = (face*)(*uncheckedshseglist)[i];
-            if (checksh->sh != skipsh->sh) {
-              if (!isdead(checksh)) {
-                checkedge4encroach(checksh);
-              }
-              skipsh = checksh;
-            }
-          }
-        }
-        if (shflaws && (uncheckedshlist->len() > 0)) {
-          uncheckedshlist->sort();
-          skipsh = checksh = (face*)(*uncheckedshlist)[0];
-          if (!isdead(checksh)) {
-            checkface4encroach(checksh);
-          }
-          for (i = 1; i < uncheckedshlist->len(); i++) {
-            checksh = (face*)(*uncheckedshlist)[i];
-            if (checksh->sh != skipsh->sh) {
-              if (!isdead(checksh)) {
-                checkface4encroach(checksh);
-              }
-              skipsh = checksh;
-            }
-          }
-        }
-        if (tetflaws && (uncheckedtetlist->len() > 0)) {
-          uncheckedtetlist->sort();
-          skiptet = checktet = (triface*)(*uncheckedtetlist)[0];
-          if (!isdead(checktet)) {
-            testtetrahedron(checktet);
-          }
-          for (i = 1; i < uncheckedtetlist->len(); i++) {
-            checktet = (triface*)(*uncheckedtetlist)[i];
-            if (checktet->tet != skiptet->tet) {
-              if (!isdead(checktet)) {
-                testtetrahedron(checktet);
-              }
-              skiptet = checktet;
-            }
-          }
-        }
-        // Check the two new subsegments to see if they're encroached.
-        checkedge4encroach(&(encloop->shface));
-        senextself(encloop->shface);
-        spivotself(encloop->shface);
-        encloop->shface.shver = 0;
-        checkedge4encroach(&(encloop->shface));
-      }
-      badsegmentdealloc(encloop);
-      encloop = badsegmenttraverse();
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// repairencfaces()    Find and repair all the encroached subfaces.          //
-//                                                                           //
-// Encroached subfaces are repaired by splitting them by inserting a point   //
-// at or near their circumcenters. However, if the new point would encroach  //
-// upon any any subsegment, it is not inserted; instead, all the subsegments //
-// it would encroach upon are split.                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::repairencfaces()
-{
-  list *neartetlist, *nearseglist;
-  badface3d* badface;
-  triface badfacetet;
-  triface testtet, neighbortet;
-  triface *checktet, *skiptet;
-  face testseg;
-  face *checksh, *skipsh;
-  point3d borg, bdest, bapex;
-  point3d newpoint;
-  enum locateresult intersect;
-  enum insertsiteresult success;
-  int encroachedseg;
-  int errorflag, flipcount;
-  int i, j;
-
-  neartetlist = nearseglist = NULL;
-
-  while (badfaces.items > 0) {
-    // Fix one encroached subfaces by inserting a point at its circumcenter.
-    badface = dequeuebadface();
-    assert(badface);
-    borg = sorg(badface->shface);
-    bdest = sdest(badface->shface);
-    bapex = sapex(badface->shface);
-    // Make sure that this subface is still the same subface when it was
-    //   tested and determined to be encroached. Subsequent transformations
-    //   may have made it a different subface.
-    if (((borg != (point3d) NULL) && (bdest != (point3d) NULL) &&
-         (bapex != (point3d) NULL)) && ((borg == badface->faceorg) &&
-         (bdest == badface->facedest) && (bapex == badface->faceapex))) {
-      errorflag = 0;
-      // Create a new point at the subface's circumcenter.
-      newpoint = (point3d) points.alloc();
-      // Check if we need calculate circumcenter.
-      if (badface->badfacetet.tet == (tetrahedron *) NULL) {
-        circumcenter(borg, bdest, bapex, badface->cent);
-      }
-      newpoint[0] = badface->cent[0];
-      newpoint[1] = badface->cent[1];
-      newpoint[2] = badface->cent[2];
-      if (issamepoint(newpoint, borg) || issamepoint(newpoint, bdest)
-          || issamepoint(newpoint, bapex)) {
-        if (!quiet) {
-          printf("Warning:  Newpoint (%.12g, %.12g, %.12g) falls on",
-                 newpoint[0], newpoint[1], newpoint[2]);
-          printf(" existing vertex.\n");
-        }
-        errorflag = 1;
-        pointdealloc(newpoint);
-      } else {
-        setpointmark(newpoint, mark(badface->shface));
-        if (verbose > 1) {
-          // Set pointmark of newpoint for Debuging outputs.
-          setpointmark(newpoint, points.items);
-        }
-        // Find a tetrahedron that contain this face.
-        stpivot(badface->shface, badfacetet);
-        if (badfacetet.tet == dummytet) {
-          sesymself(badface->shface);
-          stpivot(badface->shface, badfacetet);
-          assert(badfacetet.tet != dummytet);
-        }
-        // Find where the newpoint locates(ONFACE or ONEDGE), keep the
-        //   result in 'badfacetet'.
-        intersect = iscoplanarintri(newpoint, &badfacetet);
-        if (intersect == OUTSIDE) {
-          adjustedgering(badfacetet, CCW);
-          intersect = preciselocate(newpoint, &badfacetet);
-        }
-
-        if ((intersect == ONFACE) || (intersect == ONEDGE)) {
-          // If 'newpoint' is located ONFACE or ONEDGE, check if its
-          //   location encroaches on any nearby subsegments. It's a two
-          //   step process: First, gather all nearby subsegments; Second,
-          //   check each subsegment to discover its encroachness.
-          encroachedseg = 0;
-          assert(badfacetet.tet != dummytet);
-          if (!neartetlist) {
-            neartetlist = new list(sizeof(triface));
-            neartetlist->setcomp((compfunc) &compare2tets);
-            nearseglist = new list(sizeof(face));
-            nearseglist->setcomp((compfunc) &compare2shfaces);
-          } else {
-            neartetlist->clear();
-            nearseglist->clear();
-          }
-          // Step 1, gather all nearby subsegments, store them in list
-          //   'nearseglist'.
-          // To address this, Boywer-Watson's scheme (Cavity) is adopted.
-          //   All tetrahedra whose circumspheres contain 'newpoint' are
-          //   found. Check the edges for each tetrahedron, if there exist
-          //   a subsegment abutting this edge, add it to 'nearseglist'.
-          testtet = badfacetet;
-          // Check three edges of 'testtet''s current face.
-          for (i = 0; i < 3; i++) {
-            tsspivot(&testtet, &testseg);
-            if (testseg.sh != dummysh) {
-              nearseglist->append(&testseg);
-            }
-            enextself(testtet);
-          }
-          neartetlist->append(&testtet);
-          sym(testtet, neighbortet);
-          if (neighbortet.tet != dummytet) {
-            if (iinsphere(&neighbortet, newpoint) == 1) {
-              neartetlist->append(&neighbortet);
-            }
-          }
-          for (i = 0; i < neartetlist->len(); i++) {
-            // Get a tetra, which its circumsphere contain 'newpoint'.
-            testtet = *(triface *)(* neartetlist)[i];
-            adjustedgering(testtet, CCW);
-            // Check other three edges of this tetra. At the same time,
-            //   check other three neighbors of this tetra to see if their
-            //   circumsphere contain 'newpoint'.
-            for (j = 0; j < 3; j++) {
-              fnext(testtet, neighbortet);
-              enextself(neighbortet);
-              tsspivot(&neighbortet, &testseg);
-              if (testseg.sh != dummysh) {
-                if (nearseglist->hasitem(&testseg) == -1) {
-                  nearseglist->append(&testseg);
-                }
-              }
-              symself(neighbortet);
-              if (neighbortet.tet != dummytet) {
-                if (iinsphere(&neighbortet, newpoint) == 1) {
-                  if (neartetlist->hasitem(&neighbortet) == -1) {
-                    neartetlist->append(&neighbortet);
-                  }
-                }
-              }
-              enextself(testtet);
-            }
-          }
-          // Step 2, Check each segment to discover if they will be
-          //   encroached by 'newpoint'.
-          for (i = 0; i < nearseglist->len(); i++) {
-            testseg = *(face *)(* nearseglist)[i];
-            if (checkedge4encroach(&testseg, newpoint)) {
-              encroachedseg++;
-            }
-          }
-
-          if (encroachedseg == 0) {
-            if (verbose > 1) {
-              printf("  Insert circumcenter: (%.12g, %.12g, %.12g) %d\n",
-                     newpoint[0], newpoint[1], newpoint[2],
-                     pointmark(newpoint));
-              printf("    to split subface (%d, %d, %d).\n",
-                     pointmark(borg), pointmark(bdest), pointmark(bapex));
-            }
-            uncheckedshseglist->clear();
-            if (shflaws) {
-              uncheckedshlist->clear();
-            }
-            if (tetflaws) {
-              uncheckedtetlist->clear();
-            }
-            if (intersect == ONFACE) {
-              tspivot(badfacetet, badface->shface);
-              assert(badface->shface.sh != dummysh);
-              flipcount = insertonface(newpoint, &badfacetet,
-                                       &(badface->shface));
-            } else { // must intersect == ONEDGE
-              flipcount = insertonedge(newpoint, &badfacetet, (face*) NULL);
-            }
-            if (verbose > 1) {
-              printf("  Successfully split subface with %d flips.\n",
-                     flipcount);
-            }
-            success = SUCCESSFUL;
-          } else {
-            success = VIOLATINGEDGE;
-          }
-        } else if (intersect == OUTSIDE) {
-          success = FAILED;
-        } else if (intersect == ONVERTEX) {
-          success = DUPLICATE;
-        } else {  // intersect == INTETRAHEDRON
-          printf("Precision error in repairencface(): INTETRAHEDRON.\n");
-          printf("  Failed to locate a subface to contain newpoint.\n");
-          precisionerror();
-        }
-
-        if (success == SUCCESSFUL) {
-          if (steinerleft > 0) {
-            steinerleft--;
-          }
-          // We need check if new insert point cause other subfaces be
-          //   encroached and cause bad quality tetrahedra.
-          if (shflaws && (uncheckedshlist->len() > 0)) {
-            uncheckedshlist->sort();
-            skipsh = checksh = (face*)(*uncheckedshlist)[0];
-            if (!isdead(checksh)) {
-              checkface4encroach(checksh);
-            }
-            for (i = 1; i < uncheckedshlist->len(); i++) {
-              checksh = (face*)(*uncheckedshlist)[i];
-              if (checksh->sh != skipsh->sh) {
-                if (!isdead(checksh)) {
-                  checkface4encroach(checksh);
-                }
-                skipsh = checksh;
-              }
-            }
-          }
-          if (tetflaws && (uncheckedtetlist->len() > 0)) {
-            uncheckedtetlist->sort();
-            skiptet = checktet = (triface*)(*uncheckedtetlist)[0];
-            if (!isdead(checktet)) {
-              testtetrahedron(checktet);
-            }
-            for (i = 1; i < uncheckedtetlist->len(); i++) {
-              checktet = (triface*)(*uncheckedtetlist)[i];
-              if (checktet->tet != skiptet->tet) {
-                if (!isdead(checktet)) {
-                  testtetrahedron(checktet);
-                }
-                skiptet = checktet;
-              }
-            }
-          }
-        } else if (success == VIOLATINGEDGE) {
-          // Failed to insert the new point, but some segment was
-          //   marked as being encroached.
-          pointdealloc(newpoint);
-        } else if (success == VIOLATINGFACE) {
-          printf("Internalerror in splitface(): Unexpected condition");
-          printf(" success == VIOLATINGFACE.\n");
-          internalerror();
-        } else if (success == FAILED) {
-          if (!quiet && verbose) {
-            // Failed to insert the new point because it fails outside the
-            //   mesh. It's a except condition caused by the existing of
-            //   small angles in input model.
-            printf("Warning:  New point (%.12g, %.12g, %.12g) falls",
-                   newpoint[0], newpoint[1], newpoint[2]);
-            printf("  outside the mesh.\n");
-          }
-          pointdealloc(newpoint);
-        } else { // success == DUPLICATE
-          if (!quiet) {
-            // Failed to insert the new point because a vertex is already
-            //   there.
-            printf("Warning:  New point (%.12g, %.12g, %.12g) falls on",
-                   newpoint[0], newpoint[1], newpoint[2]);
-            printf(" existing vertex.\n");
-          }
-          pointdealloc(newpoint);
-          errorflag = 1;
-        }
-      }
-      if (errorflag) {
-        if (verbose) {
-          printf("  The new point is at the circumcenter of subface.\n");
-          printf("    (%.12g, %.12g, %.12g) (%.12g, %.12g, %.12g)",
-                 borg[0], borg[1], borg[2], bdest[0], bdest[1], bdest[2]);
-          printf(" (%.12g, %.12g, %.12g)\n", bapex[0], bapex[1], bapex[2]);
-        }
-        printf("  This probably means that I am trying to refine subfaces\n");
-        printf("    to a smaller size than can be accommodated by the finite\n");
-        printf("    precision of floating point arithmetic.\n");
-        precisionerror();
-      }
-    }
-    // Return the badface to the pool.
-    badfaces.dealloc((void *) badface);
-    // Fix any encroached segments that may have resulted.
-    if (badsegments.items > 0) {
-      repairencsegs();
-    }
-  }
-
-  if (neartetlist) {
-    delete neartetlist;
-    delete nearseglist;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// splittet()    Inserts a point at the circumsphere of a bad quality        //
-//               tetrahedron, thus eliminating the tetrahedron.              //
-//                                                                           //
-// If the new point would encroach upon any subsegment or subfacet, then it  //
-// is not inserted; instead, all the subsegments it would encroach upon are  //
-// split. If the bad quality tetrahedron is not eliminated as a result, then //
-// all the subfacets its circumcenter would encroach upon are split.         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::splittet(badtet* intet)
-{
-  triface searchtet;
-  triface testtet, neighbortet;
-  triface *checktet, *skiptet;
-  face testsh, testseg;
-  face *checksh, *skipsh;
-  point3d borg, bdest, bapex, boppo;
-  point3d newpoint;
-  enum locateresult intersect;
-  enum insertsiteresult success;
-  int encroachedseg, encroachedface;
-  int errorflag, flipcount;
-  int i, j;
-
-  borg = org(intet->btet);
-  bdest = dest(intet->btet);
-  bapex = apex(intet->btet);
-  boppo = oppo(intet->btet);
-  // Make sure that this tet is still the same tet it was when it was tested
-  //   and determined to be encroached. Subsequent transformations may have
-  //   made it a different tet.
-  if (((borg != (point3d) NULL) && (bdest != (point3d) NULL) &&
-       (bapex != (point3d) NULL) && (boppo != (point3d) NULL)) &&
-      ((borg == intet->tetorg) && (bdest == intet->tetdest) &&
-       (bapex == intet->tetapex) && (boppo == intet->tetoppo))) {
-    errorflag = 0;
-    // Create a new point at the tetrahedron's circumsphere.
-    newpoint = (point3d) points.alloc();
-    newpoint[0] = intet->cent[0];
-    newpoint[1] = intet->cent[1];
-    newpoint[2] = intet->cent[2];
-    if (issamepoint(newpoint, borg) || issamepoint(newpoint, bdest)
-        || issamepoint(newpoint, bapex) || issamepoint(newpoint, boppo)) {
-      if (!quiet) {
-        printf("Warning:  Newpoint (%.12g, %.12g, %.12g) falls on",
-               newpoint[0], newpoint[1], newpoint[2]);
-        printf(" existing vertex.\n");
-      }
-      pointdealloc(newpoint);
-      errorflag = 1;
-    } else {
-      // The new point must be in mesh, set a marker of zero.
-      setpointmark(newpoint, 0);
-      if (verbose > 1) {
-        // Set pointmark of newpoint for Debuging outputs.
-        setpointmark(newpoint, points.items);
-      }
-      // Ensure that the circumcenter must above 'intet->btet', so point
-      //   location will work.
-      searchtet = intet->btet;
-      searchtet.ver = 0;
-      for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
-        if (isaboveplane(&(searchtet), newpoint)) break;
-      }
-      assert(searchtet.loc < 4);
-      // Find where the newpoint locates, keep the result in 'searchtet'.
-      intersect = preciselocate(newpoint, &searchtet);
-
-      if ((intersect == INTETRAHEDRON) || (intersect == ONFACE)
-          || (intersect == ONEDGE)) {
-        // If 'newpoint' is located inside current mesh, insert the point
-        //   to split tetrahedron. Before insertion, check if its location
-        //   encroaches on any nearby subsegments or subfaces. Use Boywer-
-        //   Watson insertion scheme for encroach checking.
-        encroachedseg = encroachedface = 0;
-        cavetetlist->clear();
-        caveshlist->clear();
-        cavebdfacelist->clear();
-
-        // Collect all tetra to form the cavity. At the same time, collect
-        //   the boundary faces of this cavity and all encountered subfaces.
-        testtet = searchtet;
-        cavetetlist->append(&testtet);
-        tspivot(testtet, testsh);
-        if ((testsh.sh != dummysh) && !isnonsolid(testsh)) {
-          caveshlist->append(&testsh);
-          adjustedgering(testtet, CCW);
-          cavebdfacelist->append(&testtet);
-        } else {
-          sym(testtet, neighbortet);
-          assert(neighbortet.tet != dummytet);
-          if (iinsphere(&neighbortet, newpoint) == 1) {
-            cavetetlist->append(&neighbortet);
-          } else {
-            adjustedgering(testtet, CCW);
-            cavebdfacelist->append(&testtet);
-          }
-        }
-        for (i = 0; i < cavetetlist->len(); i++) {
-          // Get a tetra, which its circumsphere contain 'newpoint'.
-          testtet = *(triface *)(* cavetetlist)[i];
-          adjustedgering(testtet, CCW);
-          // Check other three neighbors of this tet.
-          for (j = 0; j < 3; j++) {
-            fnext(testtet, neighbortet);
-            tspivot(neighbortet, testsh);
-            if ((testsh.sh != dummysh) && !isnonsolid(testsh)) {
-              caveshlist->append(&testsh);
-              adjustedgering(neighbortet, CCW);
-              cavebdfacelist->append(&neighbortet);
-            } else {
-              symself(neighbortet);
-              assert(neighbortet.tet != dummytet);
-              if (iinsphere(&neighbortet, newpoint) == 1) {
-                if (cavetetlist->hasitem(&neighbortet) == -1) {
-                  cavetetlist->append(&neighbortet);
-                }
-              } else {
-                symself(neighbortet);
-                adjustedgering(neighbortet, CCW);
-                cavebdfacelist->append(&neighbortet);
-              }
-            }
-            enextself(testtet);
-          }
-        }
-        // Check for any encroached subsegments first.
-        for (i = 0; i < caveshlist->len(); i++) {
-          testsh = *(face *)(* caveshlist)[i];
-          for (j = 0; j < 3; j++) {
-            sspivot(testsh, testseg);
-            if (testseg.sh != dummysh) {
-              if (checkedge4encroach(&testseg, newpoint)) {
-                encroachedseg++;
-              }
-            }
-            senextself(testsh);
-          }
-        }
-        if (encroachedseg) {
-          success = VIOLATINGEDGE;
-        } else {
-          // If no subsegment be encroached, then check subfaces.
-          for (i = 0; i < caveshlist->len(); i++) {
-            testsh = *(face *)(* caveshlist)[i];
-            if (checkface4encroach(&testsh, newpoint)) {
-              encroachedface++;
-            }
-          }
-          if (encroachedface) {
-            success = VIOLATINGFACE;
-          }
-        }
-        if ((!encroachedseg) && (!encroachedface)) {
-          if (cavetetlist->hasitem(&(intet->btet)) != -1) {
-            if (verbose > 1) {
-              printf("  Insert circumcenter: (%.12g, %.12g, %.12g) %d\n",
-                     newpoint[0], newpoint[1], newpoint[2],
-                     pointmark(newpoint));
-              printf("    to split tetra (%d, %d, %d, %d).\n",
-                     pointmark(borg), pointmark(bdest), pointmark(bapex),
-                     pointmark(boppo));
-            }
-            uncheckedshseglist->clear();
-            uncheckedshlist->clear();
-            uncheckedtetlist->clear();
-            if (intersect == INTETRAHEDRON) {
-              flipcount = insertininterior(newpoint, &searchtet);
-            } else if (intersect == ONFACE) {
-              tspivot(searchtet, testsh);
-              if (testsh.sh != dummysh) {
-                // Note: 'testsh' must be an nonsolid subface.
-                assert(isnonsolid(testsh));
-                flipcount = insertonface(newpoint, &searchtet, &testsh);
-              } else {
-                flipcount = insertonface(newpoint, &searchtet, (face*) NULL);
-              }
-            } else { // must intersect == ONEDGE
-              // Note: 'newpoint' must locate on a interior edge.
-              flipcount = insertonedge(newpoint, &searchtet, (face*) NULL);
-            }
-            if (verbose > 1) {
-              printf("  Successfully split tetra with %d flips.\n", flipcount);
-            }
-            success = SUCCESSFUL;
-          } else {
-            // Do not insert 'newpoint', because it can't eliminate bad tet.
-            if (!quiet && verbose) {
-              printf("Warning:  A bad-quality tet survived.\n");
-            }
-            success = VIOLATINGEDGE;
-          }
-        }
-      } else if (intersect == ONVERTEX) {
-        success = DUPLICATE;
-      } else { // intersect == OUTSIDE
-        success = FAILED;
-      }
-
-      if (success == SUCCESSFUL) {
-        if (steinerleft > 0) {
-          steinerleft--;
-        }
-        // Check and queue the bad quality tetrahedra caused by inserting
-        //   'newpoint'.
-        if (uncheckedtetlist->len() > 0) {
-          uncheckedtetlist->sort();
-          skiptet = checktet = (triface*)(*uncheckedtetlist)[0];
-          if (!isdead(checktet)) {
-            testtetrahedron(checktet);
-          }
-          for (i = 1; i < uncheckedtetlist->len(); i++) {
-            checktet = (triface*)(*uncheckedtetlist)[i];
-            if (checktet->tet != skiptet->tet) {
-              if (!isdead(checktet)) {
-                testtetrahedron(checktet);
-              }
-              skiptet = checktet;
-            }
-          }
-        }
-      } else if ((success == VIOLATINGEDGE) || (success == VIOLATINGFACE)) {
-        // Failed to insert the new point, but some segment and subfaces
-        //   was marked as being encroached.
-        pointdealloc(newpoint);
-      } else if (success == FAILED) {
-        if (!quiet && verbose) {
-          // Failed to insert the new point because it fails outside the
-          //   mesh. It's an except condition caused by the existing of
-          //   small angles in input model.
-          printf("Warning:  New point (%.12g, %.12g, %.12g) falls outside",
-                 newpoint[0], newpoint[1], newpoint[2]);
-          printf(" the mesh.\n");
-        }
-        pointdealloc(newpoint);
-      } else { // success == DUPLICATE
-        if (!quiet) {
-          // Failed to insert the new point because a vertex is already there.
-          printf("Warning:  New point (%.12g, %.12g, %.12g) falls on",
-                 newpoint[0], newpoint[1], newpoint[2]);
-          printf(" existing vertex.\n");
-        }
-        pointdealloc(newpoint);
-        errorflag = 1;
-      }
-    }
-    if (errorflag) {
-      if (verbose) {
-        printf("  The new point is at the circumsphere of tetrahedron:\n");
-        printf("    (%.12g, %.12g, %.12g) (%.12g, %.12g, %.12g)\n",
-               borg[0], borg[1], borg[2], bdest[0], bdest[1], bdest[2]);
-        printf("    (%.12g, %.12g, %.12g) (%.12g, %.12g, %.12g)\n",
-               bapex[0], bapex[1], bapex[2], boppo[0], boppo[1], boppo[2]);
-      }
-      printf("  This probably means that I am trying to refine tetrahedra\n");
-      printf("    to a smaller size than can be accommodated by the finite\n");
-      printf("    precision of floating point arithmetic.\n");
-      precisionerror();
-    }
-  }
-  // Return the badtet to the pool.
-  badtets.dealloc((void *) intet);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// enforcequality()    Remove all the encroached edges and bad triangles     //
-//                     from the triangulation.                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::enforcequality()
-{
-  int i;
-
-  if (!quiet) {
-    printf("Adding Steiner points to enforce quality.\n");
-  }
-
-  // Initialize the pool of encroached segments.
-  badsegments.init(sizeof(badface3d), BADSHELLFACEPERBLOCK, POINTER, 0);
-  // Initialize the queue of subsegments which might be encroached.
-  uncheckedshseglist = new list(sizeof(face));
-  uncheckedshseglist->setcomp((compfunc) &compare2shfaces);
-  if (verbose) {
-    printf("  Looking for encroached segments.\n");
-  }
-  // Test all segments to see if they're encroached.
-  tallyencsegs();
-  // Note that steinerleft == -1 if an unlimited number
-  //   of Steiner points is allowed.
-  while ((badsegments.items > 0) && (steinerleft != 0)) {
-    if (verbose > 1) {
-      printf("  Splitting %d encroached segments.\n", badsegments.items);
-    }
-    // Fix the segments without noting newly encroached segments or
-    //   subfaces.
-    repairencsegs();
-    // Now, find all the segments that became encroached while adding
-    //   points to split encroached segments.
-    tallyencsegs();
-  }
-
-  // Initialize the pool of encroached subfaces.
-  badfaces.init(sizeof(badface3d), BADSHELLFACEPERBLOCK, POINTER, 0);
-  // Initialize the queue of subfaces which might be encroached.
-  uncheckedshlist = new list(sizeof(face));
-  uncheckedshlist->setcomp((compfunc) &compare2shfaces);
-  // Initialize the queues of bad subfaces.
-  for (i = 0; i < 2; i++) {
-    facequefront[i] = (badface3d *) NULL;
-    facequetail[i] = &facequefront[i];
-  }
-  if (verbose) {
-    printf("  Looking for encroached subfaces.\n");
-  }
-  // Test all subfaces to see if they're encroached.
-  tallyencfaces();
-  shsegflaws = 1;
-  // Note that steinerleft == -1 if an unlimited number
-  //   of Steiner points is allowed.
-  while ((badfaces.items > 0) && (steinerleft != 0)) {
-    if (verbose > 1) {
-      printf("  Splitting %d encroached subfaces.\n", badfaces.items);
-    }
-    // Fix the subfaces without noting newly encroached subfaces.
-    repairencfaces();
-    // Now, find all the subfaces that became encroached while adding
-    //   points to split encroached subfaces.
-    tallyencfaces();
-  }
-  // At this point, if we haven't run out of Steiner points, the
-  //   triangulation should be (conforming) Delaunay.
-
-  // Next, we worry about enforcing tetrahedra quality.
-  if ((minratio > 0.0) || varvolume || fixedvolume) {
-    // Initialize the pool of bad tetrahedra.
-    badtets.init(sizeof(badtet), BADTETPERBLOCK, POINTER, 0);
-    // Initialize the queue of tetrahedra which might have bad quality.
-    uncheckedtetlist = new list(sizeof(triface));
-    uncheckedtetlist->setcomp((compfunc) &compare2tets);
-    // Initialize lists for Boywer-Watson point insertion scheme.
-    cavetetlist = new list(sizeof(triface));
-    cavetetlist->setcomp((compfunc) &compare2tets);
-    caveshlist = new list(sizeof(face));
-    caveshlist->setcomp((compfunc) &compare2shfaces);
-    cavebdfacelist = new list(sizeof(triface));
-    cavebdfacelist->setcomp((compfunc) &compare2tets);
-    // Initialize the queues of bad tetrahedra.
-    for (i = 0; i < 64; i++) {
-      tetquefront[i] = (badtet *) NULL;
-      tetquetail[i] = &tetquefront[i];
-    }
-    // Test all tetrahedra to see if they're bad.
-    tallytets();
-    if (verbose) {
-      printf("  Splitting bad tetrahedra.\n");
-    }
-    shflaws = shsegflaws = tetflaws = 1;
-    while ((badtets.items > 0) && (steinerleft != 0)) {
-      // Fix one bad tetrahedron by inserting a point at its circumsphere.
-      splittet(dequeuebadtet());
-      // Fix any encroached segments and subfaces that may have resulted.
-      //   Record any new bad tetrahedra or encroached segments, subfaces
-      //   that result.
-      if (badsegments.items > 0) {
-        repairencsegs();
-      }
-      if (badfaces.items > 0) {
-        repairencfaces();
-      }
-    }
-    delete cavetetlist;
-    delete caveshlist;
-    delete cavebdfacelist;
-    delete uncheckedtetlist;
-  }
-  delete uncheckedshseglist;
-  delete uncheckedshlist;
-
-  // At this point, if we haven't run out of Steiner points, the
-  //   triangulation should be (conforming) Delaunay and have no
-  //   low-quality tetrahedra except slivers.
-
-  // Might we have run out of Steiner points too soon?
-  if (!quiet && ((badsegments.items > 0) || (badfaces.items > 0))
-      && (steinerleft == 0)) {
-    printf("\nWarning:  I ran out of Steiner points, but the mesh has\n");
-    printf("  %ld encroached segments and %ld encroached subfaces,\n",
-           badsegments.items, badfaces.items);
-    printf("  therefore might not be truly Delaunay.\n");
-    printf("  If the Delaunay property is important to you, try increasing\n");
-    printf("  the number of Steiner points (controlled by the -S switch)\n");
-    printf("  slightly and try again.\n\n");
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Mesh quality maintenance routines                                         //
-///////////////////////////////////////////////////////////////////////////////
diff --git a/Tetgen/tetlib.cpp b/Tetgen/tetlib.cpp
deleted file mode 100644
index 19e74aabde..0000000000
--- a/Tetgen/tetlib.cpp
+++ /dev/null
@@ -1,10847 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetlib.cpp    The implementation file for class mesh3d.  Include the mesh //
-//               data structure and the kernel member functions.             //
-//                                                                           //
-// Tetgen Version 1.0 beta                                                   //
-// November, 2001                                                            //
-//                                                                           //
-// Si hang                                                                   //
-// Email: sihang@weboo.com                                                   //
-// http://www.weboo.com/sh/tetgen.htm                                        //
-//                                                                           //
-// You are free to use, copy and modify the sources under certain            //
-// circumstances, provided this copyright notice remains intact.             //
-// See the file LICENSE for details.                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-#include "tetlib.h"
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Initialize all the lookup tables used by mesh manipulation primitives.    //                                             //
-//                                                                           //
-// The internal representation of the tetrahedron-based and triangle-edge    //
-// data structures takes advantage of the predefined numbering scheme for    //
-// vertices and faces of a tetrahedron, also takes advantage of that the     //
-// structure of two edge rings of each face is identical. Therefore, it can  //
-// be implemented by several global lookup tables as following.              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-// For enext() primitive, use 'ver' as index.
-int mesh3d::ve[6] = { 2, 5, 4, 1, 0, 3 };
-
-// For org(), dest() and apex() primitives, use 'ver' as index.
-int mesh3d::vo[6] = { 0, 1, 1, 2, 2, 0 };
-int mesh3d::vd[6] = { 1, 0, 2, 1, 0, 2 };
-int mesh3d::va[6] = { 2, 2, 0, 0, 1, 1 };
-
-// For org(), dest() and apex() primitives, use 'loc' as first index and
-//   'ver' as second index.
-int mesh3d::locver2org[4][6]  = { 0, 1, 1, 2, 2, 0,
-                                  0, 3, 3, 1, 1, 0,
-                                  1, 3, 3, 2, 2, 1,
-                                  2, 3, 3, 0, 0, 2 };
-int mesh3d::locver2dest[4][6] = { 1, 0, 2, 1, 0, 2,
-                                  3, 0, 1, 3, 0, 1,
-                                  3, 1, 2, 3, 1, 2,
-                                  3, 2, 0, 3, 2, 0 };
-int mesh3d::locver2apex[4][6] = { 2, 2, 0, 0, 1, 1,
-                                  1, 1, 0, 0, 3, 3,
-                                  2, 2, 1, 1, 3, 3,
-                                  0, 0, 2, 2, 3, 3 };
-
-// For oppo() primitives, use 'loc' as index.
-int mesh3d::loc2oppo[4] = { 3, 2, 0, 1 };
-
-// For fnext() primitives, use 'loc' as first index and 'ver' as second
-//   index, return a new 'loc' and new 'ver' in an int array.
-// Note: Only valid for face version = 0, 2, 4.
-int mesh3d::locver2nextf[4][6][2] =
-               { { {1, 5}, {-1, -1}, {2, 5}, {-1, -1}, {3, 5}, {-1, -1} },
-                 { {3, 3}, {-1, -1}, {2, 1}, {-1, -1}, {0, 1}, {-1, -1} },
-                 { {1, 3}, {-1, -1}, {3, 1}, {-1, -1}, {0, 3}, {-1, -1} },
-                 { {2, 3}, {-1, -1}, {1, 1}, {-1, -1}, {0, 5}, {-1, -1} } };
-
-int mesh3d::plus1mod3[3] = {1, 2, 0};
-int mesh3d::minus1mod3[3] = {2, 0, 1};
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Mesh data type linar-order functions used in list and link.  Refer to     //
-// file linklist.h for the description about linar-order functions.          //
-//                                                                           //
-// compare2points()    Compare two points by their x-coordinate, using the   //
-//                     y-coordinate as a secondary key, and the z-coordinate //
-//                     if their need.                                        //
-// compare2tets()      Compare two handles of tetrahedra by their addresses. //
-// compare2shfaces()   Compare two handles of subfaces/subsegments by their  //
-//                     addresses.                                            //
-//                                                                           //
-// Return 0 if they are same. Return 1 or -1 if they are not same.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int compare2points(point3d *point1, point3d *point2)
-{
-  if ((*point1)[0] < (*point2)[0]) {
-    return -1;
-  } else if ((*point1)[0] > (*point2)[0]) {
-    return +1;
-  } else {
-    if ((*point1)[1] < (*point2)[1]) {
-      return -1;
-    } else if ((*point1)[1] > (*point2)[1]) {
-      return +1;
-    } else {
-      if ((*point1)[2] < (*point2)[2]) {
-        return -1;
-      } else if ((*point1)[2] > (*point2)[2]) {
-        return +1;
-      } else {
-        return 0;
-      }
-    }
-  }
-}
-
-int compare2tets(triface* tface1, triface* tface2)
-{
-  if (tface1->tet == tface2->tet) {
-    return 0;                                   // These two tets are same.
-  } else if (tface1->tet < tface2->tet) {
-    return -1;
-  } else {
-    return 1;
-  }
-}
-
-int compare2shfaces(face* sface1, face* sface2)
-{
-  if (sface1->sh == sface2->sh) {
-    return 0;                      // These two subfaces/segments are same.
-  } else if (sface1->sh < sface2->sh) {
-    return -1;
-  } else {
-    return 1;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Advanced Mesh Manipulaton Primitives                                      //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getnextface()    Get next face of 'tface1' in the same face ring.         //
-//                                                                           //
-// The right-hand rule is used to determine where the next face is.          //
-//                                                                           //
-// The next face is returned in 'tface2' or 'tface1'(if tface2 == NULL).     //                                                                //
-// If next face exists, return true. Otherwise, (it's a outer boundary face),//
-// return false, and the return handle remain unchanged.                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool mesh3d::getnextface(triface* tface1, triface* tface2)
-{
-  // First we need decide where the next face in the face ring locate:
-  //   in this tet('tface1') or in it's neigbhour?  This can do quickly by
-  //   checking which edge ring of the 'tface1' version belong to.
-  if (EdgeRing(tface1->ver) == CW) {
-    // Indicate the next face is in the neigbhour tet.
-    if (!issymexist(tface1)) {
-      // Encounter Outer Space when spin face around edge. return.
-      return false;
-    }
-
-    point3d torg, tdest;
-
-    org(*tface1, torg);
-    dest(*tface1, tdest);
-    if (tface2) {
-      sym(*tface1, *tface2);
-      findversion(tface2, torg, tdest, 0); // 0 mean don't reverse direction.
-    } else {
-      symself(*tface1);
-      findversion(tface1, torg, tdest, 0);
-    }
-  } else {
-    // Indicate the next face is still in this tet('tface1').
-    if (tface2) {
-      *tface2 = *tface1;
-    }
-  }
-  // At here,  we know the next face must in retface.tet.
-  // assert(EdgeRing(tface2->ver) == CCW);
-  int tloc, tver;
-
-  if (tface2) {
-    tloc = tface2->loc; tver = tface2->ver;
-    tface2->loc = locver2nextf[tloc][tver][0];
-    tface2->ver = locver2nextf[tloc][tver][1];
-  } else {
-    tloc = tface1->loc; tver = tface1->ver;
-    tface1->loc = locver2nextf[tloc][tver][0];
-    tface1->ver = locver2nextf[tloc][tver][1];
-  }
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tsspivot()    Finds a subsegment abutting on this tetrahderon's edge.     //
-//                                                                           //
-// To find if there has a subsegment adjoining to this tetrahedron's edge,   //
-// first we need find a subface around this edge to see if there exist a     //
-// subsegment adjoining to it. Why? Because There are no pointers directly   //
-// connecting tetrahedron and adjoining subsegments. Connections between     //
-// tetrahedron and subsegments are entirely mediate througth subfaces.       //
-// Because a subsegment may be shared by any number of subfaces and          //
-// tetrahedra, each subsegment has a pointer to only one adjoining subfaces  //
-// (choose arbitrarly).                                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::tsspivot(triface* tface, face* tseg)
-{
-  triface spintet;
-  face tmpface;
-  point3d tapex;
-  int hitbdry;
-
-  spintet = *tface;
-  apex(*tface, tapex);
-  hitbdry = 0;
-  while (true) {
-    if (fnextself(spintet)) {
-      if (apex(spintet) == tapex) {
-        break; // Rewind, can leave now.
-      }
-      tspivot(spintet, tmpface);
-      if (tmpface.sh != dummysh) {
-        findversion(&tmpface, tface);
-        sspivot(tmpface, *tseg);
-        return;
-      }
-    } else {
-      hitbdry ++;
-      if(hitbdry >= 2) {
-        break;
-      } else {
-        esym(*tface, spintet);
-      }
-    }
-  }
-  // Check myself last.
-  tspivot(*tface, tmpface);
-  if (tmpface.sh != dummysh) {
-    findversion(&tmpface, tface);
-    sspivot(tmpface, *tseg);
-    return;
-  }
-  // Not find a subsegment.
-  tseg->sh = dummysh;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// sstpivot()    Finds a tetrahedron abutting a subsegment.                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::sstpivot(face* tseg, triface* tface)
-{
-  face parentface;
-
-  // Get the subface which contains the segment.
-  sdecode(tseg->sh[0], parentface);
-  assert(parentface.sh != dummysh);
-  // Get the tetrahera which the subface attches to.
-  stpivot(parentface, *tface);
-  if (tface->tet == dummytet) {
-    sesymself(parentface);
-    stpivot(parentface, *tface);
-    assert(tface->tet != dummytet);
-  }
-  findversion(tface, tseg, 0);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Advanced Mesh Manipulaton Primitives                                      //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Auxiliary Mesh Manipulaton Primitives                                     //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// findversion()    Find and set version to indicate the directed edge in    //
-//                  the input handle('tface' or 'sface'), which its origin   //
-//                  is 'dorg' and destination is 'ddest'.                    //
-//                                                                           //
-// If 'symflag' = 1, inverse the edge direction(esymself) before return.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::
-findversion(triface* tface, point3d dorg, point3d ddest, int symflag)
-{
-  point3d torg, tdest;
-
-  tface->ver = 0;
-  while (tface->ver < 6) {
-    org(*tface, torg);
-    dest(*tface, tdest);
-    if ((torg == dorg) && (tdest == ddest)) {
-      break;
-    } else if ((torg == ddest) && (tdest == dorg)) {
-      tface->ver++;
-      break;
-    }
-    tface->ver += 2;
-  }
-  assert(tface->ver < 6);
-  if (symflag) {
-    esymself(*tface);
-  }
-}
-
-void mesh3d::findversion(triface* tface, triface* dface, int symflag)
-{
-  findversion(tface, org(*dface), dest(*dface), symflag);
-}
-
-void mesh3d::findversion(triface* tface, face* sface, int symflag)
-{
-  findversion(tface, sorg(*sface), sdest(*sface), symflag);
-}
-
-void mesh3d::
-findversion(face* sface, point3d dorg, point3d ddest, int symflag)
-{
-  point3d shorg, shdest;
-
-  sface->shver = 0;
-  while (sface->shver < 6) {
-    sorg(*sface, shorg);
-    sdest(*sface, shdest);
-    if ((shorg == dorg) && (shdest == ddest)) {
-      break;
-    } else if ((shorg == ddest) && (shdest == dorg)) {
-      sface->shver++;
-      break;
-    }
-    sface->shver += 2;
-  }
-  assert(sface->shver < 6);
-  if (symflag) {
-    sesymself(*sface);
-  }
-}
-
-void mesh3d::findversion(face* sface, triface* dface, int symflag)
-{
-  findversion(sface, org(*dface), dest(*dface), symflag);
-}
-
-void mesh3d::findversion(face* sface, face* sface1, int symflag)
-{
-  findversion(sface, sorg(*sface1), sdest(*sface1), symflag);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// findorg()    Find and set the version to indicate the desired point.      //
-//                                                                           //
-// If 'dorg' is a one of vertices of 'tface', set the origin of 'tface' be   //
-// 'dorg' and return true, else return false.                                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool mesh3d::findorg(triface* tface, point3d dorg)
-{
-  if (org(*tface) == dorg) {
-    return true;
-  }
-  if (dest(*tface) == dorg) {
-    enextself(*tface);
-  } else {
-    if (apex(*tface) == dorg) {
-      enext2self(*tface);
-    } else {
-      if (oppo(*tface) == dorg) {
-        // Keep in the same tet after fnext().
-        adjustedgering(*tface, CCW);
-        fnextself(*tface);
-        enext2self(*tface);
-      } else {
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
-bool mesh3d::findorg(face* sface, point3d dorg)
-{
-  point3d pointptr;
-
-  sorg(*sface, pointptr);
-  if (pointptr == dorg) {
-    return true;
-  }
-  sdest(*sface, pointptr);
-  if (pointptr == dorg) {
-    senextself(*sface);
-  } else {
-    sapex(*sface, pointptr);
-    if (pointptr == dorg) {
-      senext2self(*sface);
-    } else {
-      return false;
-    }
-  }
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// isridge()    Returns true if the edge of tetrahedron(specified by loc and //
-//              ver) is a ridge in the mesh.                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool mesh3d::isridge(triface* tface)
-{
-  triface testtet;
-  point3d tapex;
-
-  // Spin current edge(loc and ver) to see if there will encounter
-  //   'Outer boundary' (dummytet).
-  if (!fnext(*tface, testtet)) {
-    return true;
-  }
-
-  apex(*tface, tapex);
-  do {
-    if(!fnextself(testtet)) {
-      return true;
-    }
-  } while (apex(testtet) != tapex);
-
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// isexistincidentseg()    Test if there exist any segment shares with input //
-//                         segment's origin. return true if there exists at  //
-//                         least one incident segment, otherwise return      //
-//                         false.                                            //
-//                                                                           //
-// This primitive is used to help decide where to split a segment.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool mesh3d::isexistincidentseg(face* tseg)
-{
-  triface neighbortet, spintet, testtet;
-  face testseg;
-  point3d tapex;
-  int findsegflag, reverseflag, hitbdry;
-
-  // Get a tet that contain this segment with the same origin and
-  //   destination of this segment.
-  sstpivot(tseg, &neighbortet);
-  // Spin around the tet, skip myself(tseg).
-  apex(neighbortet, tapex);
-  spintet = neighbortet;
-  hitbdry = reverseflag = findsegflag = 0;
-  while (true) {
-    if (fnextself(spintet)) {
-      if (apex(spintet) == tapex) {
-        break; // Rewind, can leave now.
-      }
-      // Get the correct edge. Note the 'reverseflag'.
-      if (!reverseflag) {
-        enext2(spintet, testtet);
-      } else {
-        enext(spintet, testtet);
-      }
-      tsspivot(&testtet, &testseg);
-      if (testseg.sh != dummysh) {
-        findsegflag = 1;
-        break;
-      }
-    } else {
-      hitbdry ++;
-      if(hitbdry >= 2) {
-        break;
-      } else {
-        reverseflag = 1;
-        esym(neighbortet, spintet);
-      }
-    }
-  }
-  if (!findsegflag) {
-    enext2(neighbortet, testtet);
-    tsspivot(&testtet, &testseg);
-    if (testseg.sh != dummysh) {
-      findsegflag = 1;
-    }
-  }
-  return findsegflag == 1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// issameface(), issameedge()    Compare the vertices of two faces/edges to  //
-//                               see if they are the same face/edge. The     //
-//                               inputs are handles of two tetrahedra.       //
-//                               Return 0 (same) or 1 (diffrent).            //
-//                                                                           //
-// These two primitives mainly used as list or link's linear order functions.//
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::issameface(triface* tface1, triface* tface2)
-{
-  point3d torg1, tdest1, tapex1;
-  point3d torg2, tdest2, tapex2;
-  int oldver, tmpver;
-
-  org(*tface1, torg1);
-  dest(*tface1, tdest1);
-  apex(*tface1, tapex1);
-
-  oldver = tface2->ver;
-  tmpver = 0;
-  while (tmpver < 6) {
-    tface2->ver = tmpver;
-    org(*tface2, torg2);
-    dest(*tface2, tdest2);
-    apex(*tface2, tapex2);
-    if (((torg1 == torg2) && (tdest1 == tdest2) && (tapex1 == tapex2))
-        || ((torg1 == tdest2) && (tdest1 == torg2) && (tapex1 == tapex2))) {
-      break;
-    }
-    tmpver += 2;
-  }
-
-  tface2->ver = oldver;
-  if (tmpver < 6) {
-    return 0;  // These two faces are same.
-  } else {
-    return 1;
-  }
-}
-
-int mesh3d::issameedge(triface* tface1, triface* tface2)
-{
-  point3d torg1, tdest1;
-  point3d torg2, tdest2;
-
-  org(*tface1, torg1);
-  dest(*tface1, tdest1);
-  org(*tface2, torg2);
-  dest(*tface2, tdest2);
-
-  if (((torg1 == torg2) && (tdest1 == tdest2))
-        || ((torg1 == tdest2) && (tdest1 == torg2))) {
-    return 0; // These two edges are same.
-  } else {
-    return 1;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dump()    For debuging, Print out the details of a tetrahedron/shellfacet //
-//           handle to standard output.                                      //
-//                                                                           //
-// It can be called directly from the debugger, and presents information     //
-// about a tetrahedron handle in digestible form. It's also used when the    //
-// highest level of verbosity (`-VVV') is specified.                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::dump(triface* tface)
-{
-  triface tmpface, prtface;
-  point3d tmppt;
-  face tmpsh;
-  int facecount;
-
-  printf("Tetra x%lx with loc(%i) and ver(%i):\n",
-         (unsigned long)(tface->tet), tface->loc, tface->ver);
-
-  tmpface = *tface;
-  facecount = 0;
-  while(facecount < 4) {
-    tmpface.loc = facecount;
-    sym(tmpface, prtface);
-    if(prtface.tet == dummytet) {
-      printf("      [%i] Outer space.\n", facecount);
-    } else {
-      printf("      [%i] x%lx  loc(%i).\n", facecount,
-             (unsigned long)(prtface.tet), prtface.loc);
-    }
-    facecount ++;
-  }
-
-  org(*tface, tmppt);
-  if(tmppt == (point3d) NULL) {
-    printf("      Org [%i] NULL\n", locver2org[tface->loc][tface->ver]);
-  } else {
-    printf("      Org [%i] x%lx (%.12g,%.12g,%.12g) %d\n",
-           locver2org[tface->loc][tface->ver], (unsigned long)(tmppt),
-           tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
-  }
-  dest(*tface, tmppt);
-  if(tmppt == (point3d) NULL) {
-    printf("      Dest[%i] NULL\n", locver2dest[tface->loc][tface->ver]);
-  } else {
-    printf("      Dest[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
-           locver2dest[tface->loc][tface->ver], (unsigned long)(tmppt),
-           tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
-  }
-  apex(*tface, tmppt);
-  if(tmppt == (point3d) NULL) {
-    printf("      Apex[%i] NULL\n", locver2apex[tface->loc][tface->ver]);
-  } else {
-    printf("      Apex[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
-           locver2apex[tface->loc][tface->ver], (unsigned long)(tmppt),
-           tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
-  }
-  oppo(*tface, tmppt);
-  if(tmppt == (point3d) NULL) {
-    printf("      Oppo[%i] NULL\n", loc2oppo[tface->loc]);
-  } else {
-    printf("      Oppo[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
-           loc2oppo[tface->loc], (unsigned long)(tmppt),
-           tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
-  }
-
-  if (useshelles) {
-    tmpface = *tface;
-    facecount = 0;
-    while(facecount < 4) {
-      tmpface.loc = facecount;
-      tspivot(tmpface, tmpsh);
-      if(tmpsh.sh != dummysh) {
-        printf("      [%i] x%lx  ver(%i).\n", facecount,
-               (unsigned long)(tmpsh.sh), tmpsh.shver);
-      }
-      facecount ++;
-    }
-  }
-}
-
-void mesh3d::dump(face* sface)
-{
-  face printsh;
-  triface printtet;
-  point3d tapex, printpoint;
-
-  sapex(*sface, tapex);
-  if (tapex != NULL) {
-    printf("subface x%lx with version %d and mark %d:\n",
-           (unsigned long)(sface->sh), sface->shver, mark(*sface));
-  } else {
-    printf("Subsegment x%lx with version %d and mark %d:\n",
-           (unsigned long)(sface->sh), sface->shver, mark(*sface));
-  }
-
-  if (tapex != NULL) {
-    // Current we don't use the first three pointers in subface,
-    //   so their values are always NULL. Skipped.
-    /*sdecode(sface->sh[0], printsh);
-    if (printsh.sh == dummysh) {
-      printf("      [0] = No shell\n");
-    } else {
-      printf("      [0] = x%lx  %d\n",
-             (unsigned long)(printsh.sh), printsh.shver);
-    }
-    sdecode(sface->sh[1], printsh);
-    if (printsh.sh == dummysh) {
-      printf("      [1] = No shell\n");
-    } else {
-      printf("      [1] = x%lx  %d\n",
-             (unsigned long)(printsh.sh), printsh.shver);
-    }
-    sdecode(sface->sh[2], printsh);
-    if (printsh.sh == dummysh) {
-      printf("      [2] = No shell\n");
-    } else {
-      printf("      [2] = x%lx  %d\n",
-             (unsigned long)(printsh.sh), printsh.shver);
-    }*/
-  } else {
-    sdecode(sface->sh[0], printsh);
-    if (printsh.sh == dummysh) {
-      printf("      [0] = No shell\n");
-    } else {
-      printf("      [0] = x%lx  %d\n",
-             (unsigned long)(printsh.sh), printsh.shver);
-    }
-    sdecode(sface->sh[1], printsh);
-    if (printsh.sh != dummysh) {
-      printf("      [1] = x%lx  %d\n",
-             (unsigned long)(printsh.sh), printsh.shver);
-    }
-    sdecode(sface->sh[2], printsh);
-    if (printsh.sh != dummysh) {
-      printf("      [2] = x%lx  %d\n",
-             (unsigned long)(printsh.sh), printsh.shver);
-    }
-  }
-
-  sorg(*sface, printpoint);
-  if (printpoint == (point3d) NULL)
-    printf("      Org [%d] = NULL\n", vo[sface->shver]);
-  else
-    printf("      Org [%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
-           vo[sface->shver], (unsigned long)(printpoint), printpoint[0],
-           printpoint[1], printpoint[2], pointmark(printpoint));
-  sdest(*sface, printpoint);
-  if (printpoint == (point3d) NULL)
-    printf("      Dest[%d] = NULL\n", vd[sface->shver]);
-  else
-    printf("      Dest[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
-            vd[sface->shver], (unsigned long)(printpoint), printpoint[0],
-            printpoint[1], printpoint[2], pointmark(printpoint));
-
-  if (tapex != NULL) {
-    sapex(*sface, printpoint);
-    if (printpoint == (point3d) NULL)
-      printf("      Apex[%d] = NULL\n", va[sface->shver]);
-    else
-      printf("      Apex[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
-             va[sface->shver], (unsigned long)(printpoint), printpoint[0],
-             printpoint[1], printpoint[2], pointmark(printpoint));
-
-    decode(sface->sh[6], printtet);
-    if (printtet.tet == dummytet) {
-      printf("      [6] = Outer space\n");
-    } else {
-      printf("      [6] = x%lx  %d\n",
-             (unsigned long)(printtet.tet), printtet.loc);
-    }
-    decode(sface->sh[7], printtet);
-    if (printtet.tet == dummytet) {
-      printf("      [7] = Outer space\n");
-    } else {
-      printf("      [7] = x%lx  %d\n",
-             (unsigned long)(printtet.tet), printtet.loc);
-    }
-
-    sdecode(sface->sh[8], printsh);
-    if (printsh.sh == dummysh) {
-      printf("      [8] = No subsegment\n");
-    } else {
-      printf("      [8] = x%lx  %d\n",
-             (unsigned long)(printsh.sh), printsh.shver);
-    }
-    sdecode(sface->sh[9], printsh);
-    if (printsh.sh == dummysh) {
-      printf("      [9] = No subsegment\n");
-    } else {
-      printf("      [9] = x%lx  %d\n",
-             (unsigned long)(printsh.sh), printsh.shver);
-    }
-    sdecode(sface->sh[10], printsh);
-    if (printsh.sh == dummysh) {
-      printf("      [10]= No subsegment\n");
-    } else {
-      printf("      [10]= x%lx  %d\n",
-             (unsigned long)(printsh.sh), printsh.shver);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Auxiliary Mesh Manipulaton Primitives                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Memory Management Routines                                                //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dummyinit()    Initialize the tetrahedron that fills "outer space" and    //
-//                the omnipresent subface.                                   //
-//                                                                           //
-// The tetrahedron that fills "outer space" called 'dummytet', is pointed to //
-// by every tetrahedron and subface on a boundary (be it outer or inner) of  //
-// the tetrahedralization. Also, 'dummytet' points to one of the tetrahedron //
-// on the convex hull(until the holes and concavities are carved), making it //
-// possible to find a starting tetrahedron for point location.               //
-//                                                                           //
-// The omnipresent subface,'dummysh', is pointed to by every tetrahedron or  //
-// subface that doesn't have a full complement of real subface to point to.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::dummyinit(int ttetwords, int tshwords)
-{
-  unsigned long alignptr;
-
-  // 'tetwords' and 'shwords' are used by the mesh manipulation primitives
-  //   to extract orientations of tetrahedra and subfaces from pointers.
-  tetwords = ttetwords;           // Initialize `tetwords' once and for all.
-  shwords = tshwords;              // Initialize `shwords' once and for all.
-
-  // Set up 'dummytet', the 'tetrahedron' that occupies "outer space".
-  dummytetbase = (tetrahedron *) new BYTE[tetwords * sizeof(tetrahedron)
-                                          + tetrahedrons.alignbytes];
-  // Align 'dummytet' on a 'tetrahedrons.alignbytes'-byte boundary.
-  alignptr = (unsigned long) dummytetbase;
-  dummytet = (tetrahedron *)
-    (alignptr + (unsigned long) tetrahedrons.alignbytes
-     - (alignptr % (unsigned long) tetrahedrons.alignbytes));
-  // Initialize the four adjoining tetrahedrons to be "outer space". These
-  //   will eventually be changed by various bonding operations, but their
-  //   values don't really matter, as long as they can legally be
-  //   dereferenced.
-  dummytet[0] = (tetrahedron) dummytet;
-  dummytet[1] = (tetrahedron) dummytet;
-  dummytet[2] = (tetrahedron) dummytet;
-  dummytet[3] = (tetrahedron) dummytet;
-  // Four NULL vertex points.
-  dummytet[4] = (tetrahedron) NULL;
-  dummytet[5] = (tetrahedron) NULL;
-  dummytet[6] = (tetrahedron) NULL;
-  dummytet[7] = (tetrahedron) NULL;
-
-  if (useshelles) {
-    // Set up 'dummysh', the omnipresent "subface" pointed to by any
-    //   tetrahedron side or subface end that isn't attached to a real
-    //   subface.
-    dummyshbase = (shellface *) new BYTE[shwords * sizeof(shellface)
-                                         + subfaces.alignbytes];
-    // Align 'dummysh' on a 'subfaces.alignbytes'-byte boundary.
-    alignptr = (unsigned long) dummyshbase;
-    dummysh = (shellface *)
-      (alignptr + (unsigned long) subfaces.alignbytes
-       - (alignptr % (unsigned long) subfaces.alignbytes));
-    // Initialize the three adjoining subfaces to be the omnipresent subface.
-    //   These will eventually be changed by various bonding operations, but
-    //   their values don't really matter, as long as they can legally be
-    //   dereferenced.
-    dummysh[0] = (shellface) dummysh;
-    dummysh[1] = (shellface) dummysh;
-    dummysh[2] = (shellface) dummysh;
-    // Three NULL vertex points.
-    dummysh[3] = (shellface) NULL;
-    dummysh[4] = (shellface) NULL;
-    dummysh[5] = (shellface) NULL;
-    // Initialize the two adjoining tetrahedra to be "outer space".
-    dummysh[6] = (shellface) dummytet;
-    dummysh[7] = (shellface) dummytet;
-    // Initialize the three adjoining subsegments to be "out boundary".
-    dummysh[8]  = (shellface) dummysh;
-    dummysh[9]  = (shellface) dummysh;
-    dummysh[10] = (shellface) dummysh;
-    // Set the boundary marker to zero.
-    * (int *) (dummysh + 11) = 0;
-    // Initialize the four adjoining subfaces of 'dummytet' to be the
-    //   omnipresent subface.
-    dummytet[8 ] = (tetrahedron) dummysh;
-    dummytet[9 ] = (tetrahedron) dummysh;
-    dummytet[10] = (tetrahedron) dummysh;
-    dummytet[11] = (tetrahedron) dummysh;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// initializepointpool()    Calculate the size of the point data structure   //
-//                          and initialize its memory pool.                  //
-//                                                                           //
-// This routine also computes the 'pointmarkindex' and `point2tetindex'      //
-// indices used to find values within each point.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::initializepointpool()
-{
-  int pointsize;
-
-  // The index within each point at which the boundary marker is found.
-  //   Ensure the point marker is aligned to a sizeof(int)-byte address.
-  pointmarkindex = ((3 + nextras) * sizeof(REAL) + sizeof(int) - 1)
-                 / sizeof(int);
-  pointsize = (pointmarkindex + 1) * sizeof(int);
-  if (poly || smesh) {
-    // The index within each point at which a tetrahedron pointer is found.
-    //   Ensure the pointer is aligned to a sizeof(tetrahedron)-byte address.
-    point2tetindex = (pointsize + sizeof(tetrahedron) - 1)
-                   / sizeof(tetrahedron);
-    pointsize = (point2tetindex + 1) * sizeof(tetrahedron);
-  }
-  // Initialize the pool of points.
-  points.init(pointsize, POINTPERBLOCK,
-    (sizeof(REAL) >= sizeof(tetrahedron)) ? FLOATINGPOINT : POINTER, 4);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// initializetetshpools()    Calculate the sizes of the tetrahedron and      //
-//                           subface data structures and initialize their    //
-//                           memory pools.                                   //
-//                                                                           //
-// This routine also computes the 'highorderindex', 'elemattribindex', and   //
-// 'volumeboundindex' indices used to find values within each tetrahedron.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::initializetetshpools()
-{
-  int tetsize;
-
-  // There are four pointers to other tetrahedra, four pointers to
-  //   corners, and possibly four pointers to subfaces.
-  highorderindex = 8 + (useshelles * 4);
-  // The number of bytes occupied by a tetrahedron.
-  tetsize = highorderindex * sizeof(tetrahedron);
-  // The index  within each tetrahedron at which its attributes are found,
-  //   where the index is measured in REALs.
-  elemattribindex = (tetsize + sizeof(REAL) - 1) / sizeof(REAL);
-  // The index within each tetrahedron at which the maximum volume
-  //   constraint is found, where the index is measured in REALs.  Note that
-  //   if the 'regionattrib' flag is set, an additional attribute will be
-  //   added.
-  volumeboundindex = elemattribindex + eextras + regionattrib;
-  // If tetrahedron attributes or a volume bound are needed, increase the
-  //   number of bytes occupied by a tetrahedron.
-  if (varvolume) {
-    tetsize = (volumeboundindex + 1) * sizeof(REAL);
-  } else if (eextras + regionattrib > 0) {
-    tetsize = volumeboundindex * sizeof(REAL);
-  }
-  // If a Voronoi diagram or tetrahedron neighbor graph is requested, make
-  //   sure there's room to store an integer index in each tetrahedron. This
-  //   integer index can occupy the same space as the subfaces or attributes
-  //   or volume constraint or extra nodes.
-  if ((voronoi || neighbors) &&
-      (tetsize < 8 * sizeof(tetrahedron) + sizeof(int))) {
-    tetsize = 8 * sizeof(tetrahedron) + sizeof(int);
-  }
-  // Having determined the memory size of a tetrahedron, initialize the pool.
-  tetrahedrons.init(tetsize, TETPERBLOCK, POINTER, 8);
-
-  if (useshelles) {
-    // Initialize the pool of subfaces. Note: Here we need eight-byte
-    //   aligned for each subface record (to keep six version).
-    subfaces.init(11 * sizeof(shellface) + sizeof(int), SUBFACEPERBLOCK,
-                  POINTER, 8);
-    // Initialize the pool of subsegments. The subsegment's record is same
-    //   with subface.
-    subsegs.init(11 * sizeof(shellface) + sizeof(int), SUBSEGPERBLOCK,
-                 POINTER, 8);
-    // Initialize the "outer space" tetrahedron and omnipresent subface.
-    dummyinit(tetrahedrons.itemwords, subfaces.itemwords);
-  } else {
-    // Initialize the "outer space" tetrahedron.
-    dummyinit(tetrahedrons.itemwords, 0);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetrahedrondealloc()    Deallocate space for a tetrahedron, marking it    //
-//                         dead.                                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
-{
-  // Set tetrahedron's vertices to NULL. This makes it possible to detect
-  //   dead tetrahedra when traversing the list of all tetrahedra.
-  dyingtetrahedron[4] = (tetrahedron) NULL;
-  dyingtetrahedron[5] = (tetrahedron) NULL;
-  dyingtetrahedron[6] = (tetrahedron) NULL;
-  dyingtetrahedron[7] = (tetrahedron) NULL;
-  tetrahedrons.dealloc((void *) dyingtetrahedron);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetrahedrontraverse()    Traverse the tetrahedra, skipping dead ones.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetrahedron* mesh3d::tetrahedrontraverse()
-{
-  tetrahedron *newtetrahedron;
-
-  do {
-    newtetrahedron = (tetrahedron *) tetrahedrons.traverse();
-    if (newtetrahedron == (tetrahedron *) NULL) {
-      return (tetrahedron *) NULL;
-    }
-  } while (newtetrahedron[4] == (tetrahedron) NULL);      // Skip dead ones.
-  return newtetrahedron;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// shellfacedealloc()    Deallocate space for a shellface, marking it dead.  //
-//                       Used both for dealloc a subface and subsegment.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::shellfacedealloc(memorypool *pool, shellface *dyingshellface)
-{
-  // Set shellface's vertices to NULL. This makes it possible to detect dead
-  //   shellfaces when traversing the list of all shellfaces.
-  dyingshellface[3] = (shellface) NULL;
-  dyingshellface[4] = (shellface) NULL;
-  dyingshellface[5] = (shellface) NULL;
-  pool->dealloc((void *) dyingshellface);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// shellfaceraverse()    Traverse the subfaces, skipping dead ones. Used for //
-//                       both subfaces and subsegments pool traverse.        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-shellface* mesh3d::shellfacetraverse(memorypool *pool)
-{
-  shellface *newshellface;
-
-  do {
-    newshellface = (shellface *) pool->traverse();
-    if (newshellface == (shellface *) NULL) {
-      return (shellface *) NULL;
-    }
-  } while (newshellface[3] == (shellface) NULL);        // Skip dead ones.
-  return newshellface;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// badsegmentdealloc()    Deallocate space for a bad segment, marking it     //
-//                        dead.                                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::badsegmentdealloc(badface3d *dyingshseg)
-{
-  // Set segment's faceorg to NULL. This makes it possible to detect dead
-  //   segments when traversing the list of all segments.
-  dyingshseg->faceorg = (point3d) NULL;
-  badsegments.dealloc((void *) dyingshseg);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// badsegmenttraverse()    Traverse the bad segments, skipping dead ones.    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-badface3d* mesh3d::badsegmenttraverse()
-{
-  badface3d *newsh;
-
-  do {
-    newsh = (badface3d *) badsegments.traverse();
-    if (newsh == (badface3d *) NULL) {
-      return (badface3d *) NULL;
-    }
-  } while (newsh->faceorg == (point3d) NULL);             // Skip dead ones.
-  return newsh;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// pointdealloc()    Deallocate space for a point, marking it dead.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::pointdealloc(point3d dyingpoint)
-{
-  // Mark the point as dead. This  makes it possible to detect dead points
-  //   when traversing the list of all points.
-  setpointmark(dyingpoint, DEADPOINT);
-  points.dealloc((void *) dyingpoint);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// pointtraverse()    Traverse the points, skipping dead ones.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-point3d mesh3d::pointtraverse()
-{
-  point3d newpoint;
-
-  do {
-    newpoint = (point3d) points.traverse();
-    if (newpoint == (point3d) NULL) {
-      return (point3d) NULL;
-    }
-  } while (pointmark(newpoint) == DEADPOINT);             // Skip dead ones.
-  return newpoint;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getpoint()    Get a specific point, by number, from the list.             //
-//                                                                           //
-// The first point is number 'firstnumber'.                                  //
-//                                                                           //
-// Note that this takes O(n) time ( with a small constant, if POINTPERBLOCK  //
-// is large ). I don't care to take the trouble to make it work in constant  //
-// time.                                                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-point3d mesh3d::getpoint(int number)
-{
-  void **getblock;
-  point3d foundpoint;
-  unsigned long alignptr;
-  int current;
-
-  getblock = points.firstblock;
-  current = firstnumber;
-  // Find the right block.
-  while (current + points.itemsperblock <= number) {
-    getblock = (void **) *getblock;
-    current += points.itemsperblock;
-  }
-  // Now find the right point.
-  alignptr = (unsigned long) (getblock + 1);
-  foundpoint = (point3d) (alignptr + (unsigned long) points.alignbytes
-                     - (alignptr % (unsigned long) points.alignbytes));
-  while (current < number) {
-    foundpoint += points.itemwords;
-    current++;
-  }
-  return foundpoint;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// maketetrahedron()    Create a new tetrahedron.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::maketetrahedron(triface *newtet)
-{
-  newtet->tet = (tetrahedron *) tetrahedrons.alloc();
-  // Initialize the four adjoining tetrahedra to be "outer space".
-  newtet->tet[0] = (tetrahedron) dummytet;
-  newtet->tet[1] = (tetrahedron) dummytet;
-  newtet->tet[2] = (tetrahedron) dummytet;
-  newtet->tet[3] = (tetrahedron) dummytet;
-  // Four NULL vertex points.
-  newtet->tet[4] = (tetrahedron) NULL;
-  newtet->tet[5] = (tetrahedron) NULL;
-  newtet->tet[6] = (tetrahedron) NULL;
-  newtet->tet[7] = (tetrahedron) NULL;
-  // Initialize the four adjoining subfaces to be the omnipresent subface.
-  if (useshelles) {
-    newtet->tet[8 ] = (tetrahedron) dummysh;
-    newtet->tet[9 ] = (tetrahedron) dummysh;
-    newtet->tet[10] = (tetrahedron) dummysh;
-    newtet->tet[11] = (tetrahedron) dummysh;
-  }
-  for (int i = 0; i < eextras; i++) {
-    setelemattribute(newtet->tet, i, 0.0);
-  }
-  if (varvolume) {
-    setvolumebound(newtet->tet, -1.0);
-  }
-  // Initialize the location and version to be Zero.
-  newtet->loc = 0;
-  newtet->ver = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// makeshellface()    Create a new shellface with version zero. Used both    //
-//                    for subfaces and seusegments.                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::makeshellface(memorypool *pool, face *newface)
-{
-  newface->sh = (shellface *) pool->alloc();
-  //Initialize the three adjoining subfaces to be the omnipresent subface.
-  newface->sh[0] = (shellface) dummysh;
-  newface->sh[1] = (shellface) dummysh;
-  newface->sh[2] = (shellface) dummysh;
-  // Three NULL vertex points.
-  newface->sh[3] = (shellface) NULL;
-  newface->sh[4] = (shellface) NULL;
-  newface->sh[5] = (shellface) NULL;
-  // Initialize the two adjoining tetrahedra to be "outer space".
-  newface->sh[6] = (shellface) dummytet;
-  newface->sh[7] = (shellface) dummytet;
-  // Initialize the three adjoining subsegments to be the omnipresent
-  //   subsegments.
-  newface->sh [8] = (shellface) dummysh;
-  newface->sh [9] = (shellface) dummysh;
-  newface->sh[10] = (shellface) dummysh;
-  // Set the boundary marker to zero.
-  * (int *) (newface->sh + 11) = 0;
-  // Initialize the version to be Zero.
-  newface->shver = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Memory Management Routines                                                //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Geometric Primitives                                                      //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-inline bool mesh3d::iszero(const REAL value)
-{
-  if (noroundoff) {
-    return value == 0.0;
-  } else {
-    return fabs(value) <= usertolerance;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// iorient3d()    3D Orientation test.                                       //
-//                                                                           //
-// Return +1 if the point pd lies "below" the plane passing through pa, pb,  //
-// and pc;  Return -1 if pd lies "above" the plane.  Return 0 if the points  //
-// are coplanar.                                                             //
-//                                                                           //
-// "below" and "above" is defined use Right-Hand Rule, so that pa, pb, and   //
-// pc appear in counterclockwise order when making a fist, the thumb points  //
-// to the "above" direction of the plane.                                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::iorient3d(point3d pa, point3d pb, point3d pc, point3d pd)
-{
-  orient3dcount++;
-
-  if (!noexact) {
-    // Using adaptive precision arithmetic and tolerance.
-    REAL sign = orient3d(pa, pb, pc, pd);
-    if (iszero(sign)) sign = 0.0;
-    if (sign > 0) return (1);
-    else if (sign < 0) return (-1);
-    else return (0);
-  } else {
-    // Using as nearly exact arithmetic as required.
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-#define MINMAX4(da, db, dc, dd, dMin, dMax) { \
-      REAL dMax1, dMax2, dMin1, dMin2; \
-      if (da > db) {dMax1 = da; dMin1 = db;} \
-      else         {dMax1 = db; dMin1 = da;} \
-      if (dc > dd) {dMax2 = dc; dMin2 = dd;} \
-      else         {dMax2 = dd; dMin2 = dc;} \
-      if (dMax1 > dMax2) dMax = dMax1; \
-      else               dMax = dMax2; \
-      if (dMin1 < dMin2) dMin = dMin1; \
-      else               dMin = dMin2; \
-    }
-    REAL dXa = pa[0], dYa = pa[1], dZa = pa[2];
-    REAL dXb = pb[0], dYb = pb[1], dZb = pb[2];
-    REAL dXc = pc[0], dYc = pc[1], dZc = pc[2];
-    REAL dXd = pd[0], dYd = pd[1], dZd = pd[2];
-
-    REAL dMaxX, dMinX, dMaxY, dMinY, dMaxZ, dMinZ;
-
-    REAL dDX2 = dXb - dXa;
-    REAL dDX3 = dXc - dXa;
-    REAL dDX4 = dXd - dXa;
-    MINMAX4(dXa, dXb, dXc, dXd, dMinX, dMaxX);
-
-    REAL dDY2 = dYb - dYa;
-    REAL dDY3 = dYc - dYa;
-    REAL dDY4 = dYd - dYa;
-    MINMAX4(dYa, dYb, dYc, dYd, dMinY, dMaxY);
-
-    REAL dDZ2 = dZb - dZa;
-    REAL dDZ3 = dZc - dZa;
-    REAL dDZ4 = dZd - dZa;
-    MINMAX4(dZa, dZb, dZc, dZd, dMinZ, dMaxZ);
-    REAL dMax = MAX( MAX(dMaxX-dMinX, dMaxY-dMinY), dMaxZ-dMinZ);
-
-    // dDet is proportional to the cell volume
-    REAL dDet = (dDX2*(dDY3*dDZ4 - dDY4*dDZ3)
-                 + dDX3*(dDY4*dDZ2 - dDY2*dDZ4)
-                 + dDX4*(dDY2*dDZ3 - dDY3*dDZ2));
-
-    // Compute an upper bound on the error bound.
-    REAL dError = usertolerance * dMax*dMax*dMax;
-
-    // Note: This is an left-hand direction, we need translate
-    //   it to right-hand direction we used.
-    if (dDet > dError)
-      return (-1);  // return (1);
-    else if (dDet < -dError)
-      return (1);   // return (-1);
-    return(0);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// iinsphere()    Insphere test.                                             //
-//                                                                           //
-// Determines whether point 'pe' is inside or outside the circumsphere of    //
-// the tetrahedron formed by point pa, pb, pc, pd.                           //
-//                                                                           //
-// Return a positive value if the point 'pe' lies inside the sphere passing  //
-// through pa, pb, pc, and pd; a negative value if it lies outside; and zero //
-// if the five points are cospherical. The points pa, pb, pc, and pd must be //
-// ordered so that they have a positive orientation (as defined by orient3d),//
-// or the sign of the result will be reversed.                               //
-//                                                                           //
-// Note: We can skip to test pa, pb, pc, and pd 's orientation, because we   //
-// always known the orientation of pa, pb, pc and pd in advance.             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::iinsphere(point3d pa, point3d pb, point3d pc, point3d pd,
-                      point3d pe)
-{
-#ifdef SELF_CHECK
-  assert(iorient3d(pa, pb, pc, pd) > 0);
-#endif // defined SELF_CHECK
-
-  inspherecount++;
-
-  if (!noexact) {
-    // Using adaptive precision arithmetic and tolerance.
-    REAL sign = insphere(pa, pb, pc, pd, pe);
-    if (iszero(sign)) sign = 0.0;
-    if (sign > 0.) return (1);
-    else if (sign < 0.) return (-1);
-    else return (0);
-  } else {
-    // Using as nearly exact arithmetic as required.
-#define dDet4By4(Mat4)                                    \
-    (  Mat4[0][0] * (  Mat4[1][1]*Mat4[2][2]*Mat4[3][3]   \
-                     + Mat4[1][2]*Mat4[2][3]*Mat4[3][1]   \
-                     + Mat4[1][3]*Mat4[2][1]*Mat4[3][2]   \
-                     - Mat4[3][1]*Mat4[2][2]*Mat4[1][3]   \
-                     - Mat4[3][2]*Mat4[2][3]*Mat4[1][1]   \
-                     - Mat4[3][3]*Mat4[2][1]*Mat4[1][2] ) \
-     - Mat4[0][1] * (  Mat4[1][0]*Mat4[2][2]*Mat4[3][3]   \
-                     + Mat4[1][2]*Mat4[2][3]*Mat4[3][0]   \
-                     + Mat4[1][3]*Mat4[2][0]*Mat4[3][2]   \
-                     - Mat4[3][0]*Mat4[2][2]*Mat4[1][3]   \
-                     - Mat4[3][2]*Mat4[2][3]*Mat4[1][0]   \
-                     - Mat4[3][3]*Mat4[2][0]*Mat4[1][2] ) \
-     + Mat4[0][2] * (  Mat4[1][0]*Mat4[2][1]*Mat4[3][3]   \
-                     + Mat4[1][1]*Mat4[2][3]*Mat4[3][0]   \
-                     + Mat4[1][3]*Mat4[2][0]*Mat4[3][1]   \
-                     - Mat4[3][0]*Mat4[2][1]*Mat4[1][3]   \
-                     - Mat4[3][1]*Mat4[2][3]*Mat4[1][0]   \
-                     - Mat4[3][3]*Mat4[2][0]*Mat4[1][1] ) \
-     - Mat4[0][3] * (  Mat4[1][0]*Mat4[2][1]*Mat4[3][2]   \
-                     + Mat4[1][1]*Mat4[2][2]*Mat4[3][0]   \
-                     + Mat4[1][2]*Mat4[2][0]*Mat4[3][1]   \
-                     - Mat4[3][0]*Mat4[2][1]*Mat4[1][2]   \
-                     - Mat4[3][1]*Mat4[2][2]*Mat4[1][0]   \
-                     - Mat4[3][2]*Mat4[2][0]*Mat4[1][1] ) \
-    )
-    REAL dXa = pa[0], dYa = pa[1], dZa = pa[2];
-    REAL dXb = pb[0], dYb = pb[1], dZb = pb[2];
-    REAL dXc = pc[0], dYc = pc[1], dZc = pc[2];
-    REAL dXd = pd[0], dYd = pd[1], dZd = pd[2];
-    REAL dXe = pe[0], dYe = pe[1], dZe = pe[2];
-
-    REAL a2dInSphMat[4][4], dWa;
-    dWa = dXa*dXa + dYa*dYa + dZa*dZa;
-
-    a2dInSphMat[0][0] = dXb - dXa;
-    a2dInSphMat[0][1] = dYb - dYa;
-    a2dInSphMat[0][2] = dZb - dZa;
-    a2dInSphMat[0][3] = dXb*dXb + dYb*dYb + dZb*dZb - dWa;
-
-    a2dInSphMat[1][0] = dXc - dXa;
-    a2dInSphMat[1][1] = dYc - dYa;
-    a2dInSphMat[1][2] = dZc - dZa;
-    a2dInSphMat[1][3] = dXc*dXc + dYc*dYc + dZc*dZc - dWa;
-
-    a2dInSphMat[2][0] = dXd - dXa;
-    a2dInSphMat[2][1] = dYd - dYa;
-    a2dInSphMat[2][2] = dZd - dZa;
-    a2dInSphMat[2][3] = dXd*dXd + dYd*dYd + dZd*dZd - dWa;
-
-    a2dInSphMat[3][0] = dXe - dXa;
-    a2dInSphMat[3][1] = dYe - dYa;
-    a2dInSphMat[3][2] = dZe - dZa;
-    a2dInSphMat[3][3] = dXe*dXe + dYe*dYe + dZe*dZe - dWa;
-
-    // Set up a scale that is the average of the distance from A to each
-    // of the other verts.  Use some trickery to take advantage of
-    // already knowing what the differences in coordinates are.
-    REAL dAveLen = 0.25 * (Mag3D(a2dInSphMat[0])
-                           + Mag3D(a2dInSphMat[1])
-                           + Mag3D(a2dInSphMat[2])
-                           + Mag3D(a2dInSphMat[3]));
-    REAL dScale = pow(dAveLen, 5);
-    // REAL dDet = dDet4By4(a2dInSphMat) / dScale *
-    //             iorient3d(pa, pb, pc, pd);
-    REAL dDet = dDet4By4(a2dInSphMat) / dScale;
-    if (dDet >  userubtolerance) {
-      return (1); // return (-1);
-    } else if (dDet < -userubtolerance) {
-      return (-1); // return ( 1);
-    } else {
-      return (0);
-    }
-  }
-}
-
-int mesh3d::iinsphere(triface* tface, point3d testpoint)
-{
-  point3d torg, tdest, tapex, toppo;
-
-  org(*tface, torg);
-  dest(*tface, tdest);
-  apex(*tface, tapex);
-  oppo(*tface, toppo);
-  // We need form a positive orientation of this points before test.
-  if (EdgeRing(tface->ver) == CCW) {
-    return iinsphere(tdest, torg, tapex, toppo, testpoint);
-  } else {
-    return iinsphere(torg, tdest, tapex, toppo, testpoint);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Some convient functions for Geometric Primitives.                         //
-//                                                                           //
-// isbelowplane     Return ture iff point is 'below' the plane.              //
-// isaboveplane     Return true iff point is 'above' the plane.              //
-// iscoplane        Return true iff points are coplane.                      //
-// iscoline         Return true iff three points are colinear.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool mesh3d::isbelowplane(triface* tface, point3d testpoint)
-{
-  point3d torg, tdest, tapex;
-
-  org(*tface, torg);
-  dest(*tface, tdest);
-  apex(*tface, tapex);
-  return iorient3d(torg, tdest, tapex, testpoint) > 0;
-}
-
-bool mesh3d::isaboveplane(triface* tface, point3d testpoint)
-{
-  point3d torg, tdest, tapex;
-
-  org(*tface, torg);
-  dest(*tface, tdest);
-  apex(*tface, tapex);
-  return iorient3d(torg, tdest, tapex, testpoint) < 0;
-}
-
-bool mesh3d::iscoplane(triface* tface, point3d testpoint)
-{
-  point3d torg, tdest, tapex;
-
-  org(*tface, torg);
-  dest(*tface, tdest);
-  apex(*tface, tapex);
-  return iorient3d(torg, tdest, tapex, testpoint) == 0;
-}
-
-bool mesh3d::isbelowplane(point3d pa, point3d pb, point3d pc, point3d pd)
-{
-  return iorient3d(pa, pb, pc, pd) > 0;
-}
-
-bool mesh3d::isaboveplane(point3d pa, point3d pb, point3d pc, point3d pd)
-{
-  return iorient3d(pa, pb, pc, pd) < 0;
-}
-
-bool mesh3d::iscoplane(point3d pa, point3d pb, point3d pc, point3d pd)
-{
-  return iorient3d(pa, pb, pc, pd) == 0;
-}
-
-bool mesh3d::iscoline(point3d pa, point3d pb, point3d pc)
-{
-  REAL v0[3], v1[3], v2[3];
-
-  Sub3D(pa, pc, v0);
-  Sub3D(pb, pc, v1);
-  Cross3D(v0, v1, v2);
-  return (iszero(v2[0])) && (iszero(v2[1])) && (iszero(v2[2]));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Geometric Primitives                                                      //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Geometric Functions                                                       //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// projontoface()    Get the orthogonal projection of point 'p' onto the     //
-//                   plane passing through points a, b and c. Return by 'p'. //
-//                                                                           //
-// Given a facet F(contains point a, b and c) and a point p, the orthogonal  //
-// projection p' of p onto F is the point that is coplanar with points a, b  //
-// and c, and satisfies the requirement that the line pp' is orthogonal to F.//
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::projontoface(point3d a, point3d b, point3d c, point3d p)
-{
-  REAL ba[3], ca[3], pa[3], n[3];
-  REAL dist;
-
-  // Get unit normal of face abc.
-  Sub3D(b, a, ba);
-  Sub3D(c, a, ca);
-  Cross3D(ba, ca, n);
-  Normalize3D(n);
-
-  Sub3D(p, a, pa);
-  dist = Dot3D(pa, n);
-
-  p[0] -= dist * n[0];
-  p[1] -= dist * n[1];
-  p[2] -= dist * n[2];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// circumcenter()    Get the equatorial shpere center of a triangular face   //
-//                   defines by vertices a, b and c. Return by 'res'.        //
-//                                                                           //
-// Equatorial shpere of a triangular face is the smallest sphere that passes //
-// through the three vertices of the face.                                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::circumcenter(point3d a, point3d b, point3d c, point3d res)
-{
-  REAL adRow1[3], adRow2[3], adRow3[3];
-  REAL dRHS1, dRHS2, dRHS3;
-  REAL dTemp;
-
-  Sub3D(a, b, adRow1);
-  Sub3D(a, c, adRow2);
-  Cross3D(adRow1, adRow2, adRow3);
-
-#ifdef SELF_CHECK
-  if (noexact) {
-    noexact = 0;
-    // Check three dividers to catch precission problems before going on.
-    REAL adOrg[3] = {0, 0, 0};
-    if (iorient3d(adRow1, adRow2, adRow3, adOrg) == 0) {
-      printf("Precssion error in circumcenter():\n");
-      printf("  Try to find circumcenter from three almost colinear points:\n");
-      printf("    point 1: (%.12g, %.12g, %.12g).\n", a[0], a[1], a[2]);
-      printf("    point 2: (%.12g, %.12g, %.12g).\n", b[0], b[1], b[2]);
-      printf("    point 3: (%.12g, %.12g, %.12g).\n", c[0], c[1], c[2]);
-      printf("  This probably means I am trying to refine mesh by splitting\n");
-      printf("    a nearly degenerate subface(which created by the approximate\n");
-      printf("    finite precision of floating point arithmetic).\n");
-      noexact = 1;
-      precisionerror();
-    }
-    noexact = 1;
-  }
-#endif // defined SELF_CHECK
-
-  dRHS1 = 0.5 * (Dot3D(a, a) - Dot3D(b, b));
-  dRHS2 = 0.5 * (Dot3D(a, a) - Dot3D(c, c));
-  dRHS3 = Dot3D(a, adRow3);
-
-  // Gussian elimination. Solve 3 by 3 linear system.
-
-  // Pivot first column
-  if (fabs(adRow1[0]) >= fabs(adRow2[0]) &&
-      fabs(adRow1[0]) >= fabs(adRow3[0])) {
-    ;
-  } else if (fabs(adRow2[0]) >= fabs(adRow3[0])) {
-    dTemp = dRHS1;
-    dRHS1 = dRHS2;
-    dRHS2 = dTemp;
-    Swap3D(adRow1, adRow2);
-  } else {
-    dTemp = dRHS1;
-    dRHS1 = dRHS3;
-    dRHS3 = dTemp;
-    Swap3D(adRow1, adRow3);
-  }
-
-  // Eliminate first column
-  dRHS2 -= dRHS1 * adRow2[0]/adRow1[0];
-  dRHS3 -= dRHS1 * adRow3[0]/adRow1[0];
-  adRow2[1] = adRow2[1] - adRow1[1] * (adRow2[0]/adRow1[0]);
-  adRow2[2] = adRow2[2] - adRow1[2] * (adRow2[0]/adRow1[0]);
-  adRow3[1] = adRow3[1] - adRow1[1] * (adRow3[0]/adRow1[0]);
-  adRow3[2] = adRow3[2] - adRow1[2] * (adRow3[0]/adRow1[0]);
-
-  // Pivot second column
-  if (fabs(adRow2[1]) >= fabs(adRow3[1])) {
-    ;
-  } else {
-    dTemp = dRHS2;
-    dRHS2 = dRHS3;
-    dRHS3 = dTemp;
-    Swap3D(adRow2, adRow3);
-  }
-
-  // Eliminate second column
-  dRHS3 -= dRHS2 * adRow3[1]/adRow2[1];
-  adRow3[2] = adRow3[2] - adRow2[2] * (adRow3[1]/adRow2[1]);
-
-  // Solve for dRHS3 and back-substitute
-  res[2] = dRHS3 /= adRow3[2];
-  dRHS2 -= adRow2[2] * dRHS3;
-  dRHS1 -= adRow1[2] * dRHS3;
-
-  // Solve for dRHS2 and back-substitute
-  res[1] = dRHS2 /= adRow2[1];
-  dRHS1 -= adRow1[1] * dRHS2;
-
-  // Solve for dRHS1
-  res[0] = dRHS1 /= adRow1[0];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// circumcenter()    Get the circumcenter of four points a, b, c and d.      //
-//                   Return by 'res'.                                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::circumcenter(point3d a, point3d b, point3d c, point3d d,
-                          point3d res)
-{
-  REAL adRow1[3], adRow2[3], adRow3[3];
-  REAL dRHS1, dRHS2, dRHS3;
-  REAL dTemp;
-
-  Sub3D(a, b, adRow1);
-  Sub3D(a, c, adRow2);
-  Sub3D(a, d, adRow3);
-
-#ifdef SELF_CHECK
-  if (noexact) {
-    noexact = 0;
-    if (iorient3d(a, b, c, d) == 0) {
-      printf("Precssion error in circumcenter():\n");
-      printf("  Try to find circumcenter from four almost coplanar points:\n");
-      printf("    point 1: (%.12g, %.12g, %.12g).\n", a[0], a[1], a[2]);
-      printf("    point 2: (%.12g, %.12g, %.12g).\n", b[0], b[1], b[2]);
-      printf("    point 3: (%.12g, %.12g, %.12g).\n", c[0], c[1], c[2]);
-      printf("    point 4: (%.12g, %.12g, %.12g).\n", d[0], d[1], d[2]);
-      printf("  This probably means I am trying to refine mesh by splitting\n");
-      printf("    a nearly degenerate tetrahedron(which created by the \n");
-      printf("    approximate finite precision of floating point arithmetic).\n");
-      noexact = 1;
-      precisionerror();
-    }
-    noexact = 1;
-  }
-#endif // defined SELF_CHECK
-
-  dRHS1 = 0.5 * (Dot3D(a, a) - Dot3D(b, b));
-  dRHS2 = 0.5 * (Dot3D(a, a) - Dot3D(c, c));
-  dRHS3 = 0.5 * (Dot3D(a, a) - Dot3D(d, d));
-
-  // Gussian elimination. Solve 3 by 3 linear system.
-
-  // Pivot first column
-  if (fabs(adRow1[0]) >= fabs(adRow2[0]) &&
-      fabs(adRow1[0]) >= fabs(adRow3[0])) {
-    ;
-  } else if (fabs(adRow2[0]) >= fabs(adRow3[0])) {
-    dTemp = dRHS1;
-    dRHS1 = dRHS2;
-    dRHS2 = dTemp;
-    Swap3D(adRow1, adRow2);
-  } else {
-    dTemp = dRHS1;
-    dRHS1 = dRHS3;
-    dRHS3 = dTemp;
-    Swap3D(adRow1, adRow3);
-  }
-
-  // Eliminate first column
-  dRHS2 -= dRHS1 * adRow2[0]/adRow1[0];
-  dRHS3 -= dRHS1 * adRow3[0]/adRow1[0];
-  adRow2[1] = adRow2[1] - adRow1[1] * (adRow2[0]/adRow1[0]);
-  adRow2[2] = adRow2[2] - adRow1[2] * (adRow2[0]/adRow1[0]);
-  adRow3[1] = adRow3[1] - adRow1[1] * (adRow3[0]/adRow1[0]);
-  adRow3[2] = adRow3[2] - adRow1[2] * (adRow3[0]/adRow1[0]);
-
-  // Pivot second column
-  if (fabs(adRow2[1]) >= fabs(adRow3[1])) {
-    ;
-  } else {
-    dTemp = dRHS2;
-    dRHS2 = dRHS3;
-    dRHS3 = dTemp;
-    Swap3D(adRow2, adRow3);
-  }
-
-  // Eliminate second column
-  dRHS3 -= dRHS2 * adRow3[1]/adRow2[1];
-  adRow3[2] = adRow3[2] - adRow2[2] * (adRow3[1]/adRow2[1]);
-
-  // Solve for dRHS3 and back-substitute
-  res[2] = dRHS3 /= adRow3[2];
-  dRHS2 -= adRow2[2] * dRHS3;
-  dRHS1 -= adRow1[2] * dRHS3;
-
-  // Solve for dRHS2 and back-substitute
-  res[1] = dRHS2 /= adRow2[1];
-  dRHS1 -= adRow1[1] * dRHS2;
-
-  // Solve for dRHS1
-  res[0] = dRHS1 /= adRow1[0];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetvolume()    Get the volume of tetrahedron formed by vertices a, b, c   //
-//                and d.                                                     //
-//                                                                           //
-// Note: The return value may be negative. True volume is fabs(retval).      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL mesh3d::tetvolume(point3d a, point3d b, point3d c, point3d d)
-{
-  REAL adVec1[3], adVec2[3], adVec3[3];
-  REAL adCross[3];
-
-  Sub3D(b, a, adVec1);
-  Sub3D(c, a, adVec2);
-  Sub3D(d, a, adVec3);
-
-  Cross3D(adVec2, adVec3, adCross);
-  return Dot3D(adCross, adVec1) / 6.;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// facedihedral()    Get the diahedral angle of two faces, given by their    //
-//                   vertices.                                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL mesh3d::facedihedral(point3d forg1, point3d fdest1, point3d fapex1,
-                          point3d forg2, point3d fdest2, point3d fapex2)
-{
-  REAL adNorm0[3], adNorm1[3];
-  REAL dScale, dDot;
-
-  Normal3D(forg1, fdest1, fapex1, adNorm0);
-  Normalize3D(adNorm0);
-  Normal3D(forg2, fdest2, fapex2, adNorm1);
-  Normalize3D(adNorm1);
-
-  dScale = 180. / acos(-1.);
-  dDot = -Dot3D(adNorm0, adNorm1);
-  if (dDot > 1.) dDot = 1.;
-  else if (dDot < -1.) dDot = -1.;
-  return acos(dDot) * dScale;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetalldihedral()    Get all(six) dihedral angles in tetrahedron form by   //
-//                     vertices a, b, c and d. Return by array adDihed[6].   //
-//                                                                           //
-// The order in which the dihedrals are assigned matters for computation of  //
-// solid angles. The way they're currently set up, combining them as (0,1,2),//
-// (0,3,4), (1,3,5), (2,4,5) gives (in order) solid angles at vertices a, b, //
-// c and d.                                                                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::tetalldihedral(point3d a, point3d b, point3d c, point3d d,
-                            REAL adDihed[6])
-{
-  REAL adNorm0[3], adNorm1[3], adNorm2[3], adNorm3[3];
-  REAL dScale, dDot;
-
-  Normal3D(c, b, d, adNorm0);
-  Normalize3D(adNorm0);
-  Normal3D(a, c, d, adNorm1);
-  Normalize3D(adNorm1);
-  Normal3D(b, a, d, adNorm2);
-  Normalize3D(adNorm2);
-  Normal3D(a, b, c, adNorm3);
-  Normalize3D(adNorm3);
-
-  dScale = 180. / acos(-1.);
-  dDot = -Dot3D(adNorm0, adNorm1);
-  if (dDot > 1.) dDot = 1.;
-  else if (dDot < -1.) dDot = -1.;
-  adDihed[5] = acos(dDot) * dScale; // Edge CD
-
-  dDot = -Dot3D(adNorm0, adNorm2);
-  if (dDot > 1.) dDot = 1.;
-  else if (dDot < -1.) dDot = -1.;
-  adDihed[4] = acos(dDot) * dScale; // Edge BD
-
-  dDot = -Dot3D(adNorm0, adNorm3);
-  if (dDot > 1.) dDot = 1.;
-  else if (dDot < -1.) dDot = -1.;
-  adDihed[3] = acos(dDot) * dScale; // Edge BC
-
-  dDot = -Dot3D(adNorm1, adNorm2);
-  if (dDot > 1.) dDot = 1.;
-  else if (dDot < -1.) dDot = -1.;
-  adDihed[2] = acos(dDot) * dScale; // Edge AD
-
-  dDot = -Dot3D(adNorm1, adNorm3);
-  if (dDot > 1.) dDot = 1.;
-  else if (dDot < -1.) dDot = -1.;
-  adDihed[1] = acos(dDot) * dScale; // Edge AC
-
-  dDot = -Dot3D(adNorm2, adNorm3);
-  if (dDot > 1.) dDot = 1.;
-  else if (dDot < -1.) dDot = -1.;
-  adDihed[0] = acos(dDot) * dScale; // Edge AB
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Geometric Functions                                                       //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Point Location Routines                                                   //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-//   A crucial step in implementing many mesh generation algorithms is the   //
-// point location problem. For example, in incremental insertion algorithms, //
-// for each vertex to be inserted, we need to find the tetrahedron in which  //
-// this vertex lies, so that it may be inserted.  In many circumstances, the //
-// dominant cost is the time required for point location.                    //
-//                                                                           //
-//   Fortunately the point location problem is well studied in computational //
-// geometry literature and and several theoretically optimal algorithms have //
-// been proposed, such as the "Bucketing" algorithm of Asano et al.[1], the  //
-// "Alternating Digital Tree(ADT)" algorithm of Bonet and Peraire[2] and the //
-// Fast Randomized Point Location algorithm of Mucke, Isaac and Zhu[3], etc. //
-// Where [3] is more suitable and faster algorithm for our 3D Delaunay mesh  //
-// generator.                                                                //
-//                                                                           //
-//   Our mesh data structure is very suitable for implementing the algorithm //
-// in [3], and with using the Adaptive Exact Geometric Predicates package of //
-// Shewchuk to improve the robustness of implementation(use -X swith).       //
-//                                                                           //
-// Please see tetlib.h and predicate.h to learn more about the mesh data     //
-// structure and exact floating-point arithmetic.                            //
-//                                                                           //
-// Refernces:                                                                //
-//                                                                           //
-// [1] T. Asano, M. Edahiro, H. Imai, M. Iri, and K. Murota. Practical use   //
-//     of bucketing techniques in computational geometry. In G. T. Toussaint,//
-//     editor, Computational Geometry, pages 153-195. North-Holland,         //
-//     Amsterdam, Netherlands, 1985.                                         //
-// [2] J. Bonet and J. Peraire. An alternating digital tree (ADT) algorithm  //
-//     for 3D geometric searching and intersection problems. International   //
-//     Journal for Numerical Methods in Engineering, 31:1-17, 1991.          //
-// [3] Ernst P. Mucke, Isaac Saias, and Binhai Zhu, Fast Randomized Point    //
-//     Location Without Preprocessing in Two- and Three-dimensional Delaunay //
-//     Triangulations, Proceedings of the Twelfth Annual Symposium on        //
-//     Computational Geometry, ACM, May 1996.                                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// randomnation()    Generate a random number between 0 and 'choices' - 1.   //
-//                                                                           //
-// This is a simple linear congruential random number generator. Hence,it is //
-// a bad random number generator, but good enough for most randomized geome- //
-// tric algorithms.                                                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-unsigned long mesh3d::randomnation(unsigned int choices)
-{
-  randomseed = (randomseed * 1366l + 150889l) % 714025l;
-  return randomseed / (714025l / choices + 1);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// makepointmap()    Construct a mapping from points to tetrahedra to        //
-//                   improve the speed of point location for subsegment and  //
-//                   subfacet insertion.                                     //
-//                                                                           //
-// Traverses all the tetrahedra, and provides each corner of each            //
-// tetrahedron with a pointer to that tetrahedera. Of course, pointers will  //
-// be overwritten by other pointers because (almost) each point is a corner  //
-// of several tetrahedra, but in the end every point will point to some      //
-// tetrahedron that contains it.                                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::makepointmap()
-{
-  triface tetloop;
-  point3d pointptr;
-
-  if (verbose) {
-    printf("  Constructing mapping from points to tetrahedra.\n");
-  }
-  tetrahedrons.traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    // Check all four points of the tetrahedron.
-    org(tetloop, pointptr);
-    setpoint2tet(pointptr, encode(tetloop));
-    dest(tetloop, pointptr);
-    setpoint2tet(pointptr, encode(tetloop));
-    apex(tetloop, pointptr);
-    setpoint2tet(pointptr, encode(tetloop));
-    oppo(tetloop, pointptr);
-    setpoint2tet(pointptr, encode(tetloop));
-    // Get another tet.
-    tetloop.tet = tetrahedrontraverse();
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// isintet()    Determine whether a vertex lies inside, on or outside a      //
-//              tetrahedron.                                                 //
-//                                                                           //
-// For 'testpoint' to be inside the tetrahedron formed by pa, pb, pc and pd, //
-// the orientation has to be right with respect to every face of tetrahedron.//
-//                                                                           //
-// Return OUTSIDE if the point lies outside the tet; Return ONVERTEX if it   //
-// coincides with a vertex in the tet;  Return ONEDGE if it lies on an edge; //
-// Return ONFACE if it lies on a face; and Return INTETRAHEDRON if it lies   //
-// strictly inside.                                                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum mesh3d::locateresult
-mesh3d::isintet(point3d pa, point3d pb, point3d pc, point3d pd,
-                point3d testpoint)
-{
-  int isign, icheck, iretval;
-
-  // Get orientation of pa, pb, pc and pd.
-  isign = iorient3d(pa, pb, pc, pd);
-  assert(isign != 0);
-
-  iretval = 0;
-  icheck = iorient3d(pb, pd, pc, testpoint) * isign;
-  if (icheck == -1) return OUTSIDE;
-  iretval += icheck;
-
-  icheck = iorient3d(pc, pd, pa, testpoint) * isign;
-  if (icheck == -1) return OUTSIDE;
-  iretval += icheck;
-
-  icheck = iorient3d(pa, pd, pb, testpoint) * isign;
-  if (icheck == -1) return OUTSIDE;
-  iretval += icheck;
-
-  icheck = iorient3d(pa, pb, pc, testpoint) * isign;
-  if (icheck == -1) return OUTSIDE;
-  iretval += icheck;
-
-  if (iretval == 1) {
-    return ONVERTEX;
-  } else if (iretval == 2) {
-    return ONEDGE;
-  } else if (iretval == 3) {
-    return ONFACE;
-  } else {
-    return INTETRAHEDRON;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// distance()    Returns the minimum "distance" of triface to point p.       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-static REAL square (REAL x)
-{
-  return (x * x);
-}
-
-REAL mesh3d::distance(triface* tface, point3d p)
-{
-#define Min(X,Y)  (((X) < (Y)) ? (X) : (Y))
-  REAL d, da, db, dc;
-  point3d tp;
-
-  org(*tface, tp);
-  da = square(p[0] - tp[0]) + square(p[1] - tp[1]) + square(p[2] - tp[2]);
-  dest(*tface, tp);
-  db = square(p[0] - tp[0]) + square(p[1] - tp[1]) + square(p[2] - tp[2]);
-  apex(*tface, tp);
-  dc = square(p[0] - tp[0]) + square(p[1] - tp[1]) + square(p[2] - tp[2]);
-  d = Min (da, db);
-  return (Min (d, dc));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// iscoplanarintri()    Determine whether a vertex lies inside, on or        //
-//                      outside a triangle in 3D. It assume the vert and the //
-//                      triangle are coplanar. Approximate test. Nonrobust.  //
-//                                                                           //
-// Return OUTSIDE if the vertex lies outside the triangle.                   //
-//                                                                           //
-// Returns ONVERTEX if the point lies on an existing vertex.  'searchtet' is //
-// a handle whose origin is the existing vertex.                             //
-//                                                                           //
-// Returns ONEDGE if the point lies on a mesh edge.  'searchtet' is a handle //
-// whose face version is the edge on which the point lies.                   //
-//                                                                           //
-// Returns ONFACE if the point lies strictly within a facet.  1searchtet' is //
-// a handle whose location is the face on which the point lies.              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum mesh3d::locateresult
-mesh3d::iscoplanarintri(point3d searchpoint, triface* searchtet)
-{
-  point3d torg, tdest, tapex;
-  const REAL dTol = 5.e-9;
-  const REAL dFloor = 1.e-6;
-  REAL dSum, dDiff;                // Tempory variables used in fuzzycomp().
-  int iCompRes;
-
-#define fuzzycomp(dA, dB, iRes)                                            \
-  dSum  = fabs(dA) + fabs(dB);                                             \
-  dDiff = dA - dB;                                                         \
-  dSum = (dSum > dFloor) ? dSum : dFloor;                                  \
-  if (dDiff > dTol * dSum) iRes = 1;                                       \
-  else if (dDiff < - dTol * dSum) iRes = -1;                               \
-  else iRes = 0;
-
-#define orient2dfast(pa, pb, pc)                                           \
-  ((pa[0] - pc[0]) * (pb[1] - pc[1]) - (pa[1] - pc[1]) * (pb[0] - pc[0]))
-
-// #define iszero3(v) (iszero(v[0]) && iszero(v[1]) && iszero(v[2]))
-#define iszero3(v) \
-  (sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]) <= userubtolerance)
-
-  org(*searchtet, torg); //  torg = searchtet->org();
-  // First find out the on vertex case, this must do first.
-  fuzzycomp(searchpoint[0], torg[0], iCompRes);
-  if (iCompRes == 0) {
-    fuzzycomp(searchpoint[1], torg[1], iCompRes);
-    if (iCompRes == 0) {
-      fuzzycomp(searchpoint[2], torg[2], iCompRes);
-      if (iCompRes == 0) {
-        return ONVERTEX;
-      }
-    }
-  }
-
-  dest(*searchtet, tdest); // tdest = searchtet->dest();
-  fuzzycomp(searchpoint[0], tdest[0], iCompRes);
-  if (iCompRes == 0) {
-    fuzzycomp(searchpoint[1], tdest[1], iCompRes);
-    if (iCompRes == 0) {
-      fuzzycomp(searchpoint[2], tdest[2], iCompRes);
-      if (iCompRes == 0) {
-        enextself(*searchtet);
-        return ONVERTEX;
-      }
-    }
-  }
-
-  apex(*searchtet, tapex); // tapex = searchtet->apex();
-  fuzzycomp(searchpoint[0], tapex[0], iCompRes);
-  if (iCompRes == 0) {
-    fuzzycomp(searchpoint[1], tapex[1], iCompRes);
-    if (iCompRes == 0) {
-      fuzzycomp(searchpoint[2], tapex[2], iCompRes);
-      if (iCompRes == 0) {
-        enext2self(*searchtet);
-        return ONVERTEX;
-      }
-    }
-  }
-
-  // Next find out the on edge case.
-  REAL v0[3], v1[3], v2[3];
-  int iCompRes1, iCompRes2;
-
-  Sub3D(torg, searchpoint, v0);
-  Sub3D(tdest, searchpoint, v1);
-  Cross3D(v0, v1, v2);
-  if (iszero3(v2)) {
-    fuzzycomp(torg[0], searchpoint[0], iCompRes1);
-    fuzzycomp(searchpoint[0], tdest[0], iCompRes2);
-    if ((iCompRes1 != 1) == (iCompRes2 != 1)) {
-      fuzzycomp(torg[1], searchpoint[1], iCompRes1);
-      fuzzycomp(searchpoint[1], tdest[1], iCompRes2);
-      if ((iCompRes1 != 1) == (iCompRes2 != 1)) {
-        fuzzycomp(torg[2], searchpoint[2], iCompRes1);
-        fuzzycomp(searchpoint[2], tdest[2], iCompRes2);
-        if ((iCompRes1 != 1) == (iCompRes2 != 1)) {
-          return ONEDGE;
-        }
-      }
-    }
-  }
-  Sub3D(tapex, searchpoint, v0);
-  Cross3D(v0, v1, v2);
-  if (iszero3(v2)) {
-    fuzzycomp(tdest[0], searchpoint[0], iCompRes1);
-    fuzzycomp(searchpoint[0], tapex[0], iCompRes2);
-    if ((iCompRes1 != 1) == (iCompRes2 != 1)) {
-      fuzzycomp(tdest[1], searchpoint[1], iCompRes1);
-      fuzzycomp(searchpoint[1], tapex[1], iCompRes2);
-      if ((iCompRes1 != 1) == (iCompRes2 != 1)) {
-        fuzzycomp(tdest[2], searchpoint[2], iCompRes1);
-        fuzzycomp(searchpoint[2], tapex[2], iCompRes2);
-        if ((iCompRes1 != 1) == (iCompRes2 != 1)) {
-          enextself(*searchtet);
-          return ONEDGE;
-        }
-      }
-    }
-  }
-  Sub3D(torg, searchpoint, v1);
-  Cross3D(v0, v1, v2);
-  if (iszero3(v2)) {
-    fuzzycomp(tapex[0], searchpoint[0], iCompRes1);
-    fuzzycomp(searchpoint[0], torg[0], iCompRes2);
-    if ((iCompRes1 != 1) == (iCompRes2 != 1)) {
-      fuzzycomp(tapex[1], searchpoint[1], iCompRes1);
-      fuzzycomp(searchpoint[1], torg[1], iCompRes2);
-      if ((iCompRes1 != 1) == (iCompRes2 != 1)) {
-        fuzzycomp(tapex[2], searchpoint[2], iCompRes1);
-        fuzzycomp(searchpoint[2], torg[2], iCompRes2);
-        if ((iCompRes1 != 1) == (iCompRes2 != 1)) {
-          enext2self(*searchtet);
-          return ONEDGE;
-        }
-      }
-    }
-  }
-
-  // Finally, to find if this point lies on face.
-  REAL adNorm[3], adBasisX[3], adBasisY[3];
-  REAL VProjA[2], VProjB[2], VProjC[2], VProj[2];
-  REAL sign0, sign1, sign2;
-
-  // Find a normal and two vectors in the plane.
-  Sub3D(tdest, torg, v0);
-  Sub3D(tapex, torg, v1);
-  Cross3D(v0, v1, adNorm);
-  Normalize3D(adNorm);
-  Assign3D(v0, adBasisX);
-  Normalize3D(adBasisX);
-  Cross3D(adNorm, adBasisX, adBasisY);
-
-  // Project onto a plane (adBasisX, adBasisY).
-  VProjA[0] = Dot3D(torg, adBasisX);
-  VProjA[1] = Dot3D(torg, adBasisY);
-  VProjB[0] = Dot3D(tdest, adBasisX);
-  VProjB[1] = Dot3D(tdest, adBasisY);
-  VProjC[0] = Dot3D(tapex, adBasisX);
-  VProjC[1] = Dot3D(tapex, adBasisY);
-  VProj [0] = Dot3D(searchpoint, adBasisX);
-  VProj [1] = Dot3D(searchpoint, adBasisY);
-
-  sign0 = orient2dfast(VProjA, VProjB, VProj);
-  sign1 = orient2dfast(VProjB, VProjC, VProj);
-  sign2 = orient2dfast(VProjC, VProjA, VProj);
-
-  if (((sign0 > 0.) == (sign1 > 0.)) && ((sign1 > 0.) == (sign2 > 0.))) {
-    return ONFACE;
-  } else {
-    return OUTSIDE;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// preciselocate()    Find a tetrahedron, a face or an edge containing a     //
-//                    given point.                                           //
-//                                                                           //
-// Begins its search from 'searchtet'. It is important that 'searchtet' be a //
-// handle with the property that 'searchpoint' is strictly lies 'above' of   //
-// the facet denoted by 'searchtet', or is colplanar with that facet and     //
-// does not intersect that facet. (In particular, 'searchpoint' should not   //
-// be the vertex of that facet.)                                             //
-//                                                                           //
-// Returns ONVERTEX if the point lies on an existing vertex.  'searchtet' is //
-// a handle whose origin is the existing vertex.                             //
-//                                                                           //
-// Returns ONEDGE if the point lies on a mesh edge.  'searchtet' is a handle //
-// whose face version is the edge on which the point lies.                   //
-//                                                                           //
-// Returns ONFACE if the point lies strictly within a facet.  'searchtet' is //
-// a handle whose location is the face on which the point lies.              //
-//                                                                           //
-// Returns INTETRAHEDRON if the point lies strictly within a tetrahededron.  //
-// 'searchtet' is a handle on the tetrahedron that contains the point.       //
-//                                                                           //
-// Returns OUTSIDE if the point lies outside the mesh. 'searchtet' is a      //
-// handle whose location is the face the point is to 'above' of. This might  //
-// occur when the circumcenter of a tetrahedron falls just slightly outside  //
-// the mesh due to floating-point roundoff error.  It also occurs when       //
-// seeking a hole or region point that a foolish user has placed outside the //
-// mesh.                                                                     //
-//                                                                           //
-// WARNING: This routine is designed for convex triangulations, and will not //
-// generally work after the holes and concavities have been carved. However, //
-// it can still be used to find the circumcenter of a triangle, a tetrahedron//
-// as long as the search is begun from the tetrahedron in question.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum mesh3d::locateresult
-mesh3d::preciselocate(point3d searchpoint, triface* searchtet)
-{
-  triface checkface, backtracetet;
-  point3d torg, tdest, toppo;
-  enum locateresult retval;
-  int ahead, turns;
-
-  assert(searchtet->tet != dummytet);
-  if (verbose > 2) {
-    printf("    Searching for point %d.\n", pointmark(searchpoint));
-  }
-
-  while (true) {
-    // Check if we walk off the boundary of the triangulation.
-    if (searchtet->tet == dummytet) {
-      *searchtet = backtracetet;
-      if (verbose > 2) {
-        printf("    End Searching: Outside current mesh.\n");
-      }
-      return OUTSIDE;
-    }
-    if (verbose > 2) {
-      printf("    From face (%d, %d, %d, %d)\n",
-             pointmark(org(*searchtet)), pointmark(dest(*searchtet)),
-             pointmark(apex(*searchtet)), pointmark(oppo(*searchtet)));
-    }
-    searchtet->ver = 0;
-    // 'toppo' is the shared vertex at all orientation tests.
-    oppo(*searchtet, toppo);
-    // Check three side faces of 'searchtet' in order.
-    //   To see if we need walk through this face.
-    for (turns = 0; turns < 3; turns++) {
-      fnext(*searchtet, checkface);
-      org(checkface, torg);
-      dest(checkface, tdest);
-      ahead = iorient3d(torg, tdest, toppo, searchpoint);
-      if (ahead == 0) {
-        // Check if `searchpoint' is locate on face, on edge or on vertex.
-        retval = iscoplanarintri(searchpoint, &checkface);
-        if (retval != OUTSIDE) {
-          *searchtet = checkface;
-          if (verbose > 2) {
-            printf("    End Searching: ");
-            if (retval == ONVERTEX) {
-              printf("On Vertex.");
-            } else if (retval == ONEDGE) {
-              printf("On Edge.");
-            } else if (retval == ONFACE) {
-              printf("On Face.");
-            }
-            printf("\n");
-          }
-          return retval;
-        }
-      } else if (ahead < 0) {
-        // We need walk through this face and continue to search.
-        backtracetet = checkface;
-        sym(checkface, *searchtet);
-        break;
-      }
-      enextself(*searchtet);
-    }
-    if (turns >= 3) {
-      // Found! Inside tetrahedron.
-      if (verbose > 2) {
-        printf("    End Searching: Inside tetraheda.\n");
-      }
-      return INTETRAHEDRON;
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// locate()    Find a tetrahedron, a face or an edge containing a given      //
-//             point.                                                        //
-//                                                                           //
-// Searching begins from one of:  the input 'searchtet', a recently encount- //
-// ered tetrahedron 'recenttet',  or from a tetrahedra chosen from a random  //
-// sample.  The choice is made by determining which tetrahedron's vertexs is //
-// closest to the point we are searcing for. Normally, 'searchtet' should be //
-// a handle on the convex hull of the tetrahedrization.                      //
-//                                                                           //
-// On completion, 'searchtet' is a tetrahedron that contains 'searchpoint'.  //
-//                                                                           //
-// Returns ONVERTEX if the point lies on an existing vertex.  'searchtet' is //
-// a handle whose origin is the existing vertex.                             //
-//                                                                           //
-// Returns ONEDGE if the point lies on a mesh edge.  'searchtet' is a handle //
-// whose face version is the edge on which the point lies.                   //
-//                                                                           //
-// Returns ONFACE if the point lies strictly within a facet.  1searchtet' is //
-// a handle whose location is the face on which the point lies.              //
-//                                                                           //
-// Returns INTETRAHEDRON if the point lies strictly within a tetrahededron.  //
-// 'searchtet' is a handle on the tetrahedron that contains the point.       //
-//                                                                           //
-// Returns OUTSIDE if the point lies outside the mesh. 'searchtet' is a      //
-// handle whose location is the face the point is to 'above' of. This might  //
-// occur when the circumcenter of a tetrahedron falls just slightly outside  //
-// the mesh due to floating-point roundoff error.  It also occurs when       //
-// seeking a hole or region point that a foolish user has placed outside the //
-// mesh.                                                                     //
-//                                                                           //
-// WARNING: This routine is designed for convex triangulations, and will not //
-// not generally work after the holes and concavities have been carved.      //
-//                                                                           //
-// Details on the random sampling method can be found in [3].                //
-//                                                                           //
-// The simple method to implement this algorithm use  tet-tri data structure //
-// is listed here: ( Suppose T is the current tetrahedrization, and p is the //
-// point we are searching.)                                                  //
-//                                                                           //
-//   (1). Choose a random facet a (a belong to T), such that p belong to a+. //
-//   (2). If T union a = NULL, then p lies outside the current triangulation,//
-//        and a is visible from p. Otherwise,  there is a unique tetrahedron //
-//        t(t include a+, t belong to T), If p belong to t, then p is locat- //
-//        ed inside(the tetrahedron t(a+) of)T. In both cases we are done.If //
-//        p not belong to t(a+), then there exists some facet b of the tetr- //
-//        ahedron t(a+), with the same orientation of a, and p belong to b+. //
-//        Repeat step (2) with a = b.                                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum mesh3d::locateresult
-mesh3d::locate(point3d searchpoint, triface *searchtet)
-{
-  triface checkface;
-  tetrahedron *firsttet, *tetptr;
-  point3d torg, tdest, tapex;
-  void **sampleblock;
-  long sampleblocks, samplesperblock, samplenum;
-  long tetblocks, i, j;
-  unsigned long alignptr;
-  REAL searchdist, dist;
-  int ahead;
-
-  // Record the distance from the suggested starting tetrahedron to the
-  //   point we seek.
-  if(searchtet->tet == dummytet) {
-    // This is an 'Outer Space' handle, get a hull tetrahedron.
-    searchtet->loc = 0;
-    symself(*searchtet);
-  }
-  searchdist = distance(searchtet, searchpoint);
-
-  // Select "good" candidate using k random samples, taking the closest one.
-  //   (The trick here is that we use just normal FP distance() function.)
-
-  // If a recently encountered tetrahedron has been recorded and has not
-  //   been deallocated, test it as a good starting point.
-  if (!isdead(&recenttet)) {
-    // adjustedgering(recenttet, CCW);
-    dist = distance(&recenttet, searchpoint);
-    if (dist < searchdist) {
-      *searchtet = recenttet;
-      searchdist = dist;
-    }
-  }
-
-  // The number of random samples taken is proportional to the cube root of
-  //   the number of tetrahedra in the mesh. The next bit of code assumes
-  //   that the number of tetrahedra increases monotonically.
-  while (SAMPLEFACTOR * samples * samples * samples < tetrahedrons.items) {
-    samples++;
-  }
-  // Find how much blocks in current tet pool.
-  tetblocks = (tetrahedrons.maxitems + TETPERBLOCK - 1) / TETPERBLOCK;
-  // Find the average samles per block. Each block at least have 1 sample.
-  samplesperblock = 1 + (samples / tetblocks);
-  sampleblocks = samples / samplesperblock;
-  sampleblock = tetrahedrons.firstblock;
-  for (i = 0; i < sampleblocks; i++) {
-    alignptr = (unsigned long) (sampleblock + 1);
-    firsttet = (tetrahedron *)
-               (alignptr + (unsigned long) tetrahedrons.alignbytes
-               - (alignptr % (unsigned long) tetrahedrons.alignbytes));
-    for (j = 0; j < samplesperblock; j++) {
-      if (i == tetblocks - 1) {
-        // This is the last block.
-        samplenum = randomnation((int)
-                      (tetrahedrons.maxitems - (i * TETPERBLOCK)));
-      } else {
-        samplenum = randomnation(TETPERBLOCK);
-      }
-      tetptr = (tetrahedron *)
-               (firsttet + (samplenum * tetrahedrons.itemwords));
-      if (tetptr[4] != (tetrahedron) NULL) {
-        checkface.tet = tetptr;
-        dist = distance(&checkface, searchpoint);
-        if (dist < searchdist) {
-          *searchtet = checkface;
-          searchdist = dist;
-        }
-      }
-    }
-    sampleblock = (void **) *sampleblock;
-  }
-  if (verbose > 2) {
-    printf("    Randomly sampling %d times.\n", sampleblocks * samplesperblock);
-  }
-
-  // Orient 'searchtet' to fit the preconditions of calling preciselocate().
-  adjustedgering(*searchtet, CCW);
-  org(*searchtet, torg);
-  dest(*searchtet, tdest);
-  apex(*searchtet, tapex);
-  ahead = iorient3d(torg, tdest, tapex, searchpoint);
-  if (ahead > 0) {
-    // 'searchpoint' is below the face, get the other side of the face.
-    // Note: Must check first if searchtet is located on 'Outer Boundary'.
-    if(!issymexist(searchtet)) {
-      return OUTSIDE;
-    }
-    symself(*searchtet);
-  } else if (ahead == 0) {
-    // Check if `searchpoint' is locate on face, on edge or on vertex.
-    enum locateresult retval = iscoplanarintri(searchpoint, searchtet);
-    if (retval != OUTSIDE) {
-      if (verbose > 2) {
-        printf("    End Searching: ");
-        if (retval == ONVERTEX) {
-          printf("On Vertex.");
-        } else if (retval == ONEDGE) {
-          printf("On Edge.");
-        } else if (retval == ONFACE) {
-          printf("On Face.");
-        }
-        printf("\n");
-      }
-      return retval;
-    }
-  }
-  return preciselocate(searchpoint, searchtet);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Point Location Routines                                                   //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Mesh Transformation Routines                                              //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Three-dimensional flip operators and algorithm.                           //
-//                                                                           //
-//   The "local transformation" (LTRANS for short) procedure for three-      //
-// dimensional triangulations is analogous to the edge flipping procedure    //
-// used first by Lawson[1] to construct two-dimensional triangulations. The  //
-// LTRANS methods was instroduced (first) by Barry Joe[2]. He proved that    //
-// the LTRANS can be used to construct a Delaunay triangulation when apply   //
-// in an appropriate order to a special triangulation with his incermental   //
-// flip algorithm[2].                                                        //
-//                                                                           //
-//   The LTRANS procedure is based on the possible configurations of five    //
-// distinct non-coplanar three-dimensional points, a, b, c, d, e. See Barry  //
-// Joe 's paper[2] fig 1 and fig 2. There show five possible configurations  //
-// of the five points, named configuration 1 ,..., configuration 5. Let T be //
-// a triangulation of the five points. the LTRANS procedure is that if the   //
-// five points are in congiguration 1 or 3, then replace the triangulation   //
-// T by other possible triangulation of the five points.The LTRANS procedure //
-// can be consider to be a face swap. Joe also show that the LOTRANS applied //
-// to the T are of the one of four types, called type 1 to 4(2-3 swap, 3-2   //
-// swap, 2-2 swap, 4-4 swap, See paper[2] fig 3).                            //
-//                                                                           //
-//   Let T(i, 0) be the preliminary triangulation of the first i vertices    //
-// obtained by joining the ith vertex to the visible bondary faces of T(i-1, //
-// D). For k >= 1, let T(i, k) be the triangualtion obtained by applying the //
-// LOTRANS procedure to a non-locally-optimal transformable(paper[1], defin- //
-// ition 1 and 2) interior face of T(i, k-1). The following therom is proved //
-// by Barry Joe(paper[2], Therom 3):                                         //
-//   If T(i-1, D) is a Delaunay triangulation, then there exists a finite    //
-//   m(m >= 0) such that T(i, m) = T(i, D) is a Delaunay triangulation.      //
-//                                                                           //
-//   Another useful notion in programming is face type, which described in   //
-// [3]. Let abc be an interior face in a triangulation T of a point set V.   //
-// Then abc is incident on two tetrahedron abcd and abce. We assign a face   //
-// type to abc of the form 'Trs' and 'Nrs' where 'T' stands for transform-   //
-// able and 'N' stands for nontransformable, and the possible types are:     //
-// T23, T32, T22, T44, N44, N40, N30, N20. Except for the case r=s=4, 'r' is //
-// number of tetrahedroa in the triangulation of a, b, c, d, e containing    //
-// abcd and abce, and either 's' is zero if the configuration has only one   //
-// possible triangulation or 's' is the number of tetrahedron in the other   //
-// triangulation of a, b, c, d, e. the T44 and N44 types involv a sixth ver- //
-// tex and a pair of simultaneous local transformations(involve 4 tetrahedron//
-// before and after) as explained in paper[3].                               //
-//                                                                           //
-// Refernces:                                                                //
-//                                                                           //
-// [1] Lawson, C.L. (1977), Software for C1 surface interpolation, in J.R.   //
-//     Rice, ed,. Mathematic Software III, Acadmeic Press, New York, 161-194.//
-// [2] Barry Joe. Construction of three-dimensional Delaunay triangulations  //
-//     using local transformations. Computer Aided Geometric Design, 8(1991),//
-//     pp. 123-142.                                                          //
-// [3] Barry Joe. Construction of Three-Dimensional Improved-Quality Triang- //
-//     ulati on Using Local Transformations".  SIAM Journal on Scientific    //
-//     Computing, 16(6):1292�C1307, November 1995.                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// categorizeface()    Decide which type of triangular face this is, anyway. //
-//                                                                           //
-// The input is a handle of triangular face of a tetrahedron. Return an      //
-// enumerate type of facecategory. Normally, the input handle will not be    //
-// changed. If return 'eT32' and 'eN32',  function will reset the face       //
-// version to the edge which is tansformable('eT32') or non-transformable    //
-// ('eN32'). If return 'eT22', 'eT44', or 'eN44', function will reset the    //
-// input face version to be the diagonal edge.                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum mesh3d::facecategory mesh3d::categorizeface(triface& horiz)
-{
-  triface symhoriz, abdcasing, bcdcasing, cadcasing;
-  triface bad, abe, symbad, symabe;
-  face tmpsh0, tmpsh1, tmpseg;
-  point3d pa, pb, pc, pd, pe;
-  point3d abdoppo, bcdoppo, cadoppo;
-  int sharecount;
-
-  sym(horiz, symhoriz);
-  if (symhoriz.tet == dummytet) {
-    return LOCKED;  // Can't swap a boundary face.
-  }
-  if (checksegments) {
-    tspivot(horiz, tmpsh0);
-    if (tmpsh0.sh != dummysh) {
-      if (!isnonsolid(tmpsh0)) {
-        return LOCKED;   // Can't swap a subface.
-      }
-    }
-  }
-  // Now we assume 'horiz' is tet<a, b, c, d>,
-  adjustedgering(horiz, CCW);
-  // Set 'symhoriz' be tet<b, a, c, e>.
-  findversion(&symhoriz, &horiz);
-
-  org(horiz, pa);
-  dest(horiz, pb);
-  apex(horiz, pc);
-  oppo(horiz, pd);
-  oppo(symhoriz, pe);
-
-  // Find the number of tetrahedra that be a neighbor of both of the
-  //   first two.
-  sharecount = 2;
-  abdoppo = bcdoppo = cadoppo = (point3d) NULL;
-
-  // Set 'abdcasing', 'bcdcasing', 'cadcasing'.
-  fnext(horiz, abdcasing);  // at edge<a, b>.
-  if (issymexist(&abdcasing)) {
-    symself(abdcasing);
-    oppo(abdcasing, abdoppo);
-    if (abdoppo == pe) sharecount++;
-  }
-  enextself(horiz);
-  fnext(horiz, bcdcasing);  // at edge<b, c>.
-  if (issymexist(&bcdcasing)) {
-    symself(bcdcasing);
-    oppo(bcdcasing, bcdoppo);
-    if (bcdoppo == pe) sharecount++;
-  }
-  enextself(horiz);
-  fnext(horiz, cadcasing);  // at edge<c, a>
-  if (issymexist(&cadcasing)) {
-    symself(cadcasing);
-    oppo(cadcasing, cadoppo);
-    if (cadoppo == pe) sharecount++;
-  }
-  enextself(horiz);  // Rewind.
-
-  if (sharecount == 4) { // Four tet case.
-    return N40;
-  }
-
-  if (sharecount == 3) { // Three tet case.
-    if (abdoppo == pe) {
-      // Check if edge<a, b> cross face<c, d, e>.
-      if (!isbelowplane(pc, pd, pe, pa))
-        return N30; // Either eN30 or eOther.
-      if (!isaboveplane(pc, pd, pe, pb))
-        return N30; // Either eN30 or eOther.
-      // return eT32;  // Return edge<a, b>.
-    } else if (bcdoppo == pe) {
-      // Check if edge<b, c> cross the face<a, d, e>.
-      if (!isbelowplane(pa, pd, pe, pb))
-        return N30; // Either eN30 or eOther.
-      if (!isaboveplane(pa, pd, pe, pc))
-        return N30; // Either eN30 or eOther.
-      enextself(horiz);
-      // return eT32;  // Return edge<b, c>.
-    } else {
-      assert(cadoppo == pe);
-      // Check if edge<c, a> cross the face<b, d, e>.
-      if (!isbelowplane(pb, pd, pe, pc))
-        return N30; // Either eN30 or eOther.
-      if (!isaboveplane(pb, pd, pe, pa))
-        return N30; // Either eN30 or eOther.
-      enext2self(horiz);
-      // return T32;  // Return edge<c, a>.
-    }
-    if (checksegments) {
-      tsspivot(&horiz, &tmpseg);
-      if (tmpseg.sh != dummysh) {
-        // Unfortunately, it's a subsegment, not swappable.
-        return LOCKED;
-      }
-    }
-    return T32;
-  } // End of three tet case.
-
-  // Only leave two tets case: 'horiz' and 'symhoriz'.
-  assert(sharecount == 2);
-  // These returns take out all cases which allow the saving of an
-  //   orientation primitive evaluation.  This is very useful, as
-  //   this is a critical code path.
-  // Check if e above face<b, c, d>.
-  int iOrientA = iorient3d(pb, pc, pd, pe);
-  if (iOrientA == -1) {
-    enextself(horiz);
-    return N32;  // Return edge<b, c>.
-  }
-  // Check if e above face<c, a, d>.
-  int iOrientB = iorient3d(pc, pa, pd, pe);
-  if (iOrientB == -1) {
-    enext2self(horiz);
-    return N32;  // Return edge<c, a>.
-  }
-  if (iOrientA + iOrientB == 0) return N20;
-  // Check if e above face<a, b, d>.
-  int iOrientC = iorient3d(pa, pb, pd, pe);
-  if (iOrientC == -1) {
-    return N32;  // Return edge<a, b>.
-  }
-
-  switch (iOrientA + iOrientB + iOrientC) {
-    case 0:
-      // Impossible, but included for completeness.
-    case 1:
-      // Two orientations are zero (three points co-linear). Hopelessly
-      //   unswappable.  Bail out.
-	    return N20;
-    case 2:
-      // Four points are coplanar; (T22, T44, N44) One orientation must
-      //   be 0; verts are re-labeled to make it iOrientC. This implies
-      //   that edge<a, b> is the coplanar edge.
-      assert(!(iOrientA && iOrientB && iOrientC));
-      if (iOrientA == 0) {
-        // edge<b, c> is the diagonal.
-        enextself(horiz);
-        enext2self(symhoriz);
-        org(horiz, pa);
-        dest(horiz, pb);
-        apex(horiz, pc);
-      } else if (iOrientB == 0) {
-        // edge<c, a> is the diagonal.
-        enext2self(horiz);
-        enextself(symhoriz);
-        org(horiz, pa);
-        dest(horiz, pb);
-        apex(horiz, pc);
-      }
-      // Now we can sure edge<a, b> is the diagonal. Verify that the
-      //   re-labeling was done correctly.
-	    // assert(iorient3d(pa, pb, pd, pe) == 0);
-      if (checksegments) {
-        tsspivot(&horiz, &tmpseg);
-        if (tmpseg.sh != dummysh) {
-          // Unfortunately, it's a subsegment, not swappable.
-          return LOCKED;
-        }
-      }
-
-      // The configuration of these two tets is classified based on the
-      //   properties of the coplanar faces:
-      // 1 If both are BFaces with the same boundary condition, swappable
-      //   two tets to two.
-      // 2 If both are BFaces with different bdry cond, not swappable.
-      // 3 If one is a BFace and the other not, not swappable.
-      // 4 If neither is a BFace, both opposite cells are tets, and the
-      //   tets have the same fourth vert, swappable four to four.
-      // 5 If neither is a BFace, both opposite cells are tets, and the
-      //   tets do not have the same fourth vert, not swappable, although
-      //   some non-local transformations might make it so.
-      // 6 If neither is a BFace and one or both opposite cells is not a
-      //   tet, not swappable.
-      fnext(horiz, bad);
-      fnext(symhoriz, abe);
-      sym(bad, symbad);
-      sym(abe, symabe);
-
-      if ((symbad.tet == dummytet) && (symabe.tet == dummytet)) {
-        // Both faces are on the boundary.
-        if (checksegments) {
-          tspivot(bad, tmpsh0);
-          tspivot(abe, tmpsh1);
-          if ((tmpsh0.sh == dummysh) && (tmpsh1.sh == dummysh)) {
-            return T22;       // case 1.
-          } else if ((tmpsh0.sh != dummysh) && (tmpsh1.sh != dummysh)) {
-            if (mark(tmpsh0) == mark(tmpsh1)) {
-              return T22;     // case 1.
-            } else {
-              return LOCKED;  // case 2.
-            }
-          } else {
-            if (tmpsh0.sh != dummysh) {
-              if (isnonsolid(tmpsh0)) {
-                return T22;   // case 1.
-              }
-            } else { // tmpsh1.sh != dummysh
-              if (isnonsolid(tmpsh1)) {
-                return T22;   // case 1.
-              }
-            }
-            return LOCKED;    // case 2.
-          }
-        } else {
-          return T22;         // case 1.
-        }
-      } else if ((symbad.tet != dummytet) && (symabe.tet != dummytet)) {
-        // Both faces are inner facets.
-        point3d badoppo, abeoppo;
-        oppo(symbad, badoppo);
-        oppo(symabe, abeoppo);
-        if (badoppo == abeoppo) {
-          if (checksegments) {
-            tspivot(bad, tmpsh0);
-            tspivot(abe, tmpsh1);
-            if ((tmpsh0.sh == dummysh) && (tmpsh1.sh == dummysh)) {
-              return T44;     // case 1.
-            } else if ((tmpsh0.sh != dummysh) && (tmpsh1.sh != dummysh)) {
-              if (mark(tmpsh0) == mark(tmpsh1)) {
-                return T44;   // case 1.
-              } else {
-                return LOCKED; // case 2.
-              }
-            } else {
-              if (tmpsh0.sh == dummysh) {
-                if (isnonsolid(tmpsh1)) {
-                  return T44; // case 1.
-                }
-              } else {
-                if (isnonsolid(tmpsh0)) {
-                  return T44; // case 1.
-                }
-              }
-              return LOCKED;   // case 2.
-            }
-          } else {
-            return T44;       // case 4.
-          }
-        } else {
-          return N44;         // case 5.
-        }
-      } else {
-        // Exactly one face on the boundary or internal faces with cells
-        //   other than tets
-	      return LOCKED;         // cases 3, 6.
-      }
-    case 3:
-      // Configuration is convex and therefore swappable two tets to three.
-	    return T23;
-    default:
-	    // No other cases should be possible
-	    assert(0);
-      return LOCKED;
-  } // End of switch.
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// querydoswap()    Determines whether swapping is needed for current seting //
-//                  swaptype.                                                //
-//                                                                           //
-// There are many measures can be used, like Delaunay criterion, local max-  //
-// min solid angle criterion and max-min dihedral angle, etc. Current only   //
-// use the Delaunay criterion.                                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool mesh3d::querydoswap(triface& queryface)
-{
-  triface symface;
-  point3d symoppo;
-
-  sym(queryface, symface);
-  assert(symface.tet != dummytet);
-  oppo(symface, symoppo);
-  int sign = iinsphere(&queryface, symoppo);
-  if (sign > 0) {
-    return (true);
-  } else if (sign < 0) {
-    return (false);
-  } else {
-    cospherecount ++;
-    return (false);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// preservesubsegments()    Preserve subsegments that abutting a flipping    //
-//                          subface(must be nonsolid).                       //
-//                                                                           //
-// This routine used in all local transformation routines to prevent missing //
-// subsegments when flip away a nonsolid subface. The inputs are a handle    //
-// of flipping face 'abc'(must be a nonsolid subface) and a handle of tetra  //
-// that abutting this face 'abcd'. This routine will check each side of face //
-// 'abc', to see if their exist a subsegment abutting at this side. If find, //
-// still need determine whether there exist another subfaces hold this       //
-// subsegment. If no such subface be found. We must insert a subface for     //
-// holding this subsegment, otherwise, this subsegment will missing after do //
-// flip. At each case, the face 'abc' will dealloc at end. Before 'abc' is   //
-// deallocated, we must dissolve it from its two adjacent tets, otherwise,   //
-// one of tet may still think it is connecting a subface.                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::preservesubsegments(face& abc, triface& abcd)
-{
-  triface tmpabcd, spintet;
-  face checkseg, checksh;
-  point3d tapex;
-  int edgecount, successbonded, hitbdry;
-
-  tmpabcd = abcd;
-  adjustedgering(tmpabcd, CCW);              // For fnext() should be exist.
-  findversion(&abc, &tmpabcd, false);    // For keep same enext() direction.
-
-  edgecount = 0;
-  while (edgecount < 3) {
-    sspivot(abc, checkseg);
-    if (checkseg.sh != dummysh) {
-      // Find a subsegment adjoining at a nonsolid subface('abc').
-      spivot(checkseg, checksh);
-      if (checksh.sh != abc.sh) {
-        // There must exist another subface that hold this segment. We can
-        //   safely deallocte this subface.
-      } else {
-        // We must find another subface to hold this segment, if no such
-        //   subface be found. Then we should insert a nonsolid subface.
-        spintet = tmpabcd;
-        apex(tmpabcd, tapex);
-        successbonded = hitbdry = 0;
-        while (true) {
-          if (fnextself(spintet)) {
-            if (apex(spintet) == tapex) {
-              break; // Rewind, can leave now.
-            }
-            tspivot(spintet, checksh);
-            if (checksh.sh != dummysh) {
-              findversion(&checksh, &spintet);
-              ssbond(checksh, checkseg);
-              successbonded = 1;
-              break;
-            }
-          } else {
-            hitbdry ++;
-            if(hitbdry >= 2) {
-              break;
-            } else {
-              esym(tmpabcd, spintet);
-            }
-          }
-        }
-        if (!successbonded) {
-          // Badly, We must insert a subface for holding this subsegment;
-          //   otherwise, this subsegment will missing after do flip.
-          triface tmptet;
-          fnext(tmpabcd, tmptet);
-          insertsubface(&tmptet, NONSOLIDFLAG, 1);
-          face newsh;
-          tspivot(tmptet, newsh);
-          findversion(&newsh, &tmptet);
-          ssbond(newsh, checkseg);
-        }
-      }
-    }
-    senextself(abc);
-    enextself(tmpabcd);
-    edgecount ++;
-  }
-
-  // Before dealloc subface, must dissolve it from its two side.
-  tsdissolve(abcd);
-  sym(abcd, tmpabcd);
-  if (tmpabcd.tet != dummytet) {
-    tsdissolve(tmpabcd);
-  }
-  // This subface can be dealloced now.
-  shellfacedealloc(&subfaces, abc.sh);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flip23()    Swap two tets for three.                                      //
-//                                                                           //
-// See Barry Joe's paper [2] as listed at above. See figure 1 in this paper. //
-// We change configuration 1A to 1B. The input 'flipface' is face<abc>.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::flip23(triface& flipface)
-{
-  triface abcd, bace;                                  // Old configuration.
-  triface oldabd, oldbcd, oldcad;
-  triface abdcasing, bcdcasing, cadcasing;
-  face abdsh, bcdsh, cadsh;
-  triface oldbae, oldcbe, oldace;
-  triface baecasing, cbecasing, acecasing;
-  face baesh, cbesh, acesh;
-  face abcsh;                                           // Flipping subface.
-  triface edab, edbc, edca;                            // New configuration.
-  point3d pa, pb, pc, pd, pe;
-  REAL attrib, volume;
-  int flipcount, i;
-
-  flip_t23s++;
-
-  if (verbose > 2) {
-    printf("    Do T23 on face (%d, %d, %d, %d).\n",
-           pointmark(org(flipface)), pointmark(dest(flipface)),
-           pointmark(apex(flipface)), pointmark(oppo(flipface)));
-  }
-
-  abcd = flipface;
-  abcd.ver = 0;  // adjust at edge<ab>.
-  sym(abcd, bace);
-  findversion(&bace, &abcd); // adjust at edge<ba>.
-  // Keep all old faces and their casings before doflip.
-  oldabd = oldbcd = oldcad = abcd;
-  fnextself(oldabd);
-  enextfnextself(oldbcd);
-  enext2fnextself(oldcad);
-  oldbae = oldcbe = oldace = bace;
-  fnextself(oldbae);
-  enext2fnextself(oldcbe);
-  enextfnextself(oldace);
-  sym(oldabd, abdcasing);
-  sym(oldbcd, bcdcasing);
-  sym(oldcad, cadcasing);
-  sym(oldbae, baecasing);
-  sym(oldcbe, cbecasing);
-  sym(oldace, acecasing);
-  if (checksegments) {
-    // Check the flip face<a, b, c> 's three edges to see if there exist
-    //   subsegment. This step must do first.
-    tspivot(abcd, abcsh);
-    if (abcsh.sh != dummysh) {
-      assert(isnonsolid(abcsh));
-      preservesubsegments(abcsh, abcd);
-    }
-    // Now, we can find all subfaces abutting faces in old configuration.
-    tspivot(oldabd, abdsh);
-    tspivot(oldbcd, bcdsh);
-    tspivot(oldcad, cadsh);
-    tspivot(oldbae, baesh);
-    tspivot(oldcbe, cbesh);
-    tspivot(oldace, acesh);
-  }
-  org (abcd, pa);
-  dest(abcd, pb);
-  apex(abcd, pc);
-  oppo(abcd, pd);
-  oppo(bace, pe);
-
-  // Set new configuration.
-  edab.tet = abcd.tet;
-  // default: 'edab' loc = 0, ver = 0.
-  setorg (edab, pe);
-  setdest(edab, pd);
-  setapex(edab, pa);
-  setoppo(edab, pb);
-
-  edbc.tet = bace.tet;
-  // defult: 'edbc' loc = 0, ver = 0.
-  setorg (edbc, pe);
-  setdest(edbc, pd);
-  setapex(edbc, pb);
-  setoppo(edbc, pc);
-
-  maketetrahedron(&edca);
-  // default: 'edca' loc = 0, ver = 0.
-  setorg (edca, pe);
-  setdest(edca, pd);
-  setapex(edca, pc);
-  setoppo(edca, pa);
-
-  // Set the element attributes of the new tetrahedron('edca').
-  for (i = 0; i < eextras; i++) {
-    attrib = elemattribute(abcd.tet, i);
-    setelemattribute(edca.tet, i, attrib);
-  }
-  // Set the volume constraint of the new tetrahedron('edca').
-  if (varvolume) {
-    volume = volumebound(abcd.tet);
-    setvolumebound(edca.tet, volume);
-  }
-
-  // There may be shell facets that need to be bonded to new configuarton.
-  if (checksegments) {
-    // Clear old flags in 'edab'('abcd') and 'edbc'('bace').
-    for (i = 0; i < 4; i ++) {
-      edab.loc = i;
-      tsdissolve(edab);
-      edbc.loc = i;
-      tsdissolve(edbc);
-    }
-    if (abdsh.sh != dummysh) {
-      edab.loc = 2; // face<a, b, d>.
-      tsbond(edab, abdsh);
-    }
-    if (baesh.sh != dummysh) {
-      edab.loc = 3; // face<b, a, e>.
-      tsbond(edab, baesh);
-    }
-    if (bcdsh.sh != dummysh) {
-      edbc.loc = 2; // face<b, c, d>.
-      tsbond(edbc, bcdsh);
-    }
-    if (cbesh.sh != dummysh) {
-      edbc.loc = 3; // face<c, b, e>.
-      tsbond(edbc, cbesh);
-    }
-    if (cadsh.sh != dummysh) {
-      edca.loc = 2; // face<c, a, d>.
-      tsbond(edca, cadsh);
-    }
-    if (acesh.sh != dummysh) {
-      edca.loc = 3; // face<a, c, e>.
-      tsbond(edca, acesh);
-    }
-  }
-
-  // Clear old bonds in 'edab'('abcd') and 'edbc'('bace').
-  for (i = 0; i < 4; i ++) {
-    edab.loc = i;
-    dissolve(edab);
-    edbc.loc = i;
-    dissolve(edbc);
-  }
-  // Bond the three tetrahedra.
-  edab.loc = 0;
-  edca.loc = 1;
-  bond(edab, edca);
-  edab.loc = 1;
-  edbc.loc = 0;
-  bond(edab, edbc);
-  edbc.loc = 1;
-  edca.loc = 0;
-  bond(edbc, edca);
-  // Bond each casing faces.
-  edab.loc = 2;
-  bond(edab, abdcasing);
-  edab.loc = 3;
-  bond(edab, baecasing);
-  edbc.loc = 2;
-  bond(edbc, bcdcasing);
-  edbc.loc = 3;
-  bond(edbc, cbecasing);
-  edca.loc = 2;
-  bond(edca, cadcasing);
-  edca.loc = 3;
-  bond(edca, acecasing);
-
-  edab.loc = 0;
-  edbc.loc = 0;
-  edca.loc = 0;
-#ifdef SELF_CHECK
-  if (!isaboveplane(&edab, pb)) {
-    printf("Internal error in flip23():\n");
-    printf("  Clockwise tetrahedron after flip (edab).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&edbc, pc)) {
-    printf("Internal error in flip23():\n");
-    printf("  Clockwise tetrahedron after flip (edbc).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&edca, pa)) {
-    printf("Internal error in flip23():\n");
-    printf("  Clockwise tetrahedron after flip (edca).\n");
-    internalerror();
-  }
-#endif // defined SELF_CHECK
-  if (verbose > 2) {
-    printf("    Updating edab ");
-    dump(&edab);
-    printf("    Updating edbc ");
-    dump(&edbc);
-    printf("    Creating edca ");
-    dump(&edca);
-  }
-
-  if(usefliplist) {
-    flipcount = 0;
-    edab.loc = 2; // face<a, b, d>.
-    enqueuefliplist(edab);
-    edab.loc = 3; // face<b, a, e>.
-    enqueuefliplist(edab);
-    edbc.loc = 2; // face<b, c, d>.
-    enqueuefliplist(edbc);
-    edbc.loc = 3; // face<c, b, e>.
-    enqueuefliplist(edbc);
-    edca.loc = 2; // face<c, a, d>.
-    enqueuefliplist(edca);
-    edca.loc = 3; // face<a, c, e>.
-    enqueuefliplist(edca);
-  } else {
-    flipcount = 1;
-    edab.loc = 2; // face<a, b, d>.
-    flipcount += flip(edab);
-    edab.loc = 3; // face<b, a, e>.
-    flipcount += flip(edab);
-    edbc.loc = 2; // face<b, c, d>.
-    flipcount += flip(edbc);
-    edbc.loc = 3; // face<c, b, e>.
-    flipcount += flip(edbc);
-    edca.loc = 2; // face<c, a, d>.
-    flipcount += flip(edca);
-    edca.loc = 3; // face<a, c, e>.
-    flipcount += flip(edca);
-  }
-
-  return flipcount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flip32()    Swap three tets for two.                                      //
-//                                                                           //
-// See Barry Joe's paper [2] as listed at above. See figure 1 in this paper. //
-// We change configuration 1B to 1A. The input 'flipface' is edge<de>.       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::flip32(triface& flipface)
-{
-  triface edab, edbc, edca;                            // Old configuration.
-  triface oldabd, oldbcd, oldcad;
-  triface abdcasing, bcdcasing, cadcasing;
-  face abdsh, bcdsh, cadsh;
-  triface oldbae, oldcbe, oldace;
-  triface baecasing, cbecasing, acecasing;
-  face baesh, cbesh, acesh;
-  triface abcd, bace;                                  // New configuration.
-  point3d pa, pb, pc, pd, pe;
-  int flipcount, i;
-
-  flip_t32s++;
-
-  if (verbose > 2) {
-    printf("    Do T32 on face (%d, %d, %d, %d).\n",
-           pointmark(org(flipface)), pointmark(dest(flipface)),
-           pointmark(apex(flipface)), pointmark(oppo(flipface)));
-  }
-
-  // 'flipface' must be tet<e, d, a, b> or tet<d, e, a, -b>.
-  edab = flipface;
-  // Adjust face version first, so 'edab' be tet<e, d, a, b>.
-  adjustedgering(edab, CCW);
-  // Set 'edbc' and 'edca'.
-  fnext(edab, edbc);
-  symself(edbc);
-  findversion(&edbc, &edab, 0);
-  fnext(edbc, edca);
-  symself(edca);
-  findversion(&edca, &edab, 0);
-  // Keep all old faces and their casings before doflip.
-  oldabd = oldbae = edab;
-  enextfnextself(oldabd);
-  enext2fnextself(oldbae);
-  oldbcd = oldcbe = edbc;
-  enextfnextself(oldbcd);
-  enext2fnextself(oldcbe);
-  oldcad = oldace = edca;
-  enextfnextself(oldcad);
-  enext2fnextself(oldace);
-  sym(oldabd, abdcasing);
-  sym(oldbcd, bcdcasing);
-  sym(oldcad, cadcasing);
-  sym(oldbae, baecasing);
-  sym(oldcbe, cbecasing);
-  sym(oldace, acecasing);
-  if (checksegments) {
-    // Check faces around flip edge<e, d> to see if there exist subsegment
-    //   attaching it. This step must do first. The three face are ed(abc).
-    face tmpface;
-    tspivot(edab, tmpface);
-    if (tmpface.sh != dummysh) {
-      assert(isnonsolid(tmpface));
-      preservesubsegments(tmpface, edab);
-    }
-    tspivot(edbc, tmpface);
-    if (tmpface.sh != dummysh) {
-      assert(isnonsolid(tmpface));
-      preservesubsegments(tmpface, edbc);
-    }
-    tspivot(edca, tmpface);
-    if (tmpface.sh != dummysh) {
-      assert(isnonsolid(tmpface));
-      preservesubsegments(tmpface, edca);
-    }
-    // Find all subfaces abutting faces in old configuration.
-    tspivot(oldabd, abdsh);
-    tspivot(oldbcd, bcdsh);
-    tspivot(oldcad, cadsh);
-    tspivot(oldbae, baesh);
-    tspivot(oldcbe, cbesh);
-    tspivot(oldace, acesh);
-  }
-  apex(edab, pa);
-  oppo(edab, pb);
-  oppo(edbc, pc);
-  dest(edab, pd);
-  org (edab, pe);
-
-  // Set new configuration.
-  abcd.tet = edab.tet;
-  // default: 'abcd' loc = 0, ver = 0.
-  setorg (abcd, pa);
-  setdest(abcd, pb);
-  setapex(abcd, pc);
-  setoppo(abcd, pd);
-
-  bace.tet = edbc.tet;
-  // default: 'bace' loc = 0, ver = 0.
-  setorg (bace, pb);
-  setdest(bace, pa);
-  setapex(bace, pc);
-  setoppo(bace, pe);
-
-  // In flip32 case, we needn't reset element attributes and volume
-  //   constraint, because no new tetrahedron be created.
-
-  // There may be shell facets that need to be bonded to the new
-  //   configuration.
-  if (checksegments) {
-    // Clear old flags in 'abcd'('edab') and 'bace'('edbc').
-    for (i = 0; i < 4; i ++) {
-      abcd.loc = i;
-      tsdissolve(abcd);
-      bace.loc = i;
-      tsdissolve(bace);
-    }
-    if (abdsh.sh != dummysh) {
-      abcd.loc = 1; // face<a, b, d>.
-      tsbond(abcd, abdsh);
-    }
-    if (baesh.sh != dummysh) {
-      bace.loc = 1; // face<b, a, e>.
-      tsbond(bace, baesh);
-    }
-    if (bcdsh.sh != dummysh) {
-      abcd.loc = 2; // face<b, c, d>.
-      tsbond(abcd, bcdsh);
-    }
-    if (cbesh.sh != dummysh) {
-      bace.loc = 3; // face<c, b, e>.
-      tsbond(bace, cbesh);
-    }
-    if (cadsh.sh != dummysh) {
-      abcd.loc = 3; // face<c, a, d>.
-      tsbond(abcd, cadsh);
-    }
-    if (acesh.sh != dummysh) {
-      bace.loc = 2; // face<a, c, e>.
-      tsbond(bace, acesh);
-    }
-  }
-
-  for (i = 0; i < 4; i ++) {
-    abcd.loc = i;
-    dissolve(abcd);
-    bace.loc = i;
-    dissolve(bace);
-  }
-  // Bond the new configuration.
-  abcd.loc = 0;
-  bace.loc = 0;
-  bond(abcd, bace);
-  // Bond each casing faces.
-  abcd.loc = 1;
-  bond(abcd, abdcasing);
-  abcd.loc = 2;
-  bond(abcd, bcdcasing);
-  abcd.loc = 3;
-  bond(abcd, cadcasing);
-  bace.loc = 1;
-  bond(bace, baecasing);
-  bace.loc = 3;
-  bond(bace, cbecasing);
-  bace.loc = 2;
-  bond(bace, acecasing);
-
-  abcd.loc = 0;
-  bace.loc = 0;
-#ifdef SELF_CHECK
-  if (!isaboveplane(&abcd, pd)) {
-    printf("Internal error in flip32():\n");
-    printf("  Clockwise tetrahedron after flip (abcd).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&bace, pe)) {
-    printf("Internal error in flip32():\n");
-    printf("  Clockwise tetrahedron after flip (bace).\n");
-    internalerror();
-  }
-#endif // defined SELF_CHECK
-  if (verbose > 2) {
-    printf("    Updating abcd ");
-    dump(&abcd);
-    printf("    Updating bace ");
-    dump(&bace);
-    printf("    Deleting edca ");
-    dump(&edca);
-  }
-  // Dealloc 'edca'.
-  tetrahedrondealloc(edca.tet);
-
-  if (usefliplist) {
-    flipcount = 0;
-    abcd.loc = 1; // face<a, b, d>.
-    enqueuefliplist(abcd);
-    bace.loc = 1; // face<b, a, e>.
-    enqueuefliplist(bace);
-    abcd.loc = 2; // face<b, c, d>.
-    enqueuefliplist(abcd);
-    bace.loc = 3; // face<c, b, e>.
-    enqueuefliplist(bace);
-    abcd.loc = 3; // face<c, a, d>.
-    enqueuefliplist(abcd);
-    bace.loc = 2; // face<a, c, e>.
-    enqueuefliplist(bace);
-  } else {
-    flipcount = 1;
-    abcd.loc = 1; // face<a, b, d>.
-    flipcount += flip(abcd);
-    bace.loc = 1; // face<b, a, e>.
-    flipcount += flip(bace);
-    abcd.loc = 2; // face<b, c, d>.
-    flipcount += flip(abcd);
-    bace.loc = 3; // face<c, b, e>.
-    flipcount += flip(bace);
-    abcd.loc = 3; // face<c, a, d>.
-    flipcount += flip(abcd);
-    bace.loc = 2; // face<a, c, e>.
-    flipcount += flip(bace);
-  }
-
-  return flipcount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flip22()    Swap two tets for two, in the case where two faces are        //
-//             coplanar.                                                     //
-//                                                                           //
-// See Barry Joe's paper [2] as listed at above. See figure 1 in this paper. //
-// We change configuration 3A to 3B. The input 'flipface' lock at edge<ab>.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::flip22(triface& flipface)
-{
-  triface abcd, bace;                                  // Old configuration.
-  triface oldbcd, oldcad, oldcbe, oldace;
-  triface bcdcasing, cadcasing, cbecasing, acecasing;
-  face bcdsh, cadsh, cbesh, acesh;
-  triface oldabd, oldbae;                                 // Flipping faces.
-  face abdsh, baesh, abcsh;                            // Flipping subfaces.
-  face abdrightseg, abdleftseg;
-  face baerightseg, baeleftseg;
-  triface ceda, cdeb;                                  // New configuration.
-  face debsh, edash;
-  triface ghosttet;
-  point3d pa, pb, pc, pd, pe;
-  int flipcount, i;
-
-  flip_t22s++;
-
-  if (verbose > 2) {
-    printf("    Do T22 on face (%d, %d, %d, %d).\n",
-           pointmark(org(flipface)), pointmark(dest(flipface)),
-           pointmark(apex(flipface)), pointmark(oppo(flipface)));
-  }
-
-  // Set a 'ghosttet' handle the Outer space.
-  ghosttet.tet = dummytet;
-
-  abcd = flipface;
-  adjustedgering(abcd, CCW);
-  sym(abcd, bace);
-  findversion(&bace, &abcd);
-  oldbcd = oldcad = abcd;
-  enextfnextself(oldbcd);
-  enext2fnextself(oldcad);
-  oldcbe = oldace = bace;
-  enext2fnextself(oldcbe);
-  enextfnextself(oldace);
-  sym(oldbcd, bcdcasing);
-  sym(oldcad, cadcasing);
-  sym(oldcbe, cbecasing);
-  sym(oldace, acecasing);
-  if (checksegments) {
-    // Check the flip face<a, b, c> 's three edges to see if there exist
-    //   subsegment. This step must do first.
-    tspivot(abcd, abcsh);
-    if (abcsh.sh != dummysh) {
-      assert(isnonsolid(abcsh));
-      preservesubsegments(abcsh, abcd);
-    }
-    // Now, we can find all subfaces abutting faces in old configuration.
-    tspivot(oldbcd, bcdsh);
-    tspivot(oldcad, cadsh);
-    tspivot(oldcbe, cbesh);
-    tspivot(oldace, acesh);
-    // Keep flip edge<ab> and its two(coplanar) flip faces.
-    fnext(abcd, oldabd);
-    fnext(bace, oldbae);
-    tspivot(oldabd, abdsh);
-    tspivot(oldbae, baesh);
-    if ((abdsh.sh != dummysh) || (baesh.sh != dummysh)) {
-      // Check if there missing a half subface.
-      if (abdsh.sh == dummysh) {
-        assert(baesh.sh != dummysh);
-        insertsubface(&oldabd, NONSOLIDFLAG, 1);
-        tspivot(oldabd, abdsh);
-      } else if (baesh.sh == dummysh) {
-        assert(abdsh.sh != dummysh);
-        insertsubface(&oldbae, NONSOLIDFLAG, 1);
-        tspivot(oldbae, baesh);
-      }
-      // Save segments which adhering to 'abdsh'.
-      findversion(&abdsh, &abcd, 0);  // lock at edge<ab>.
-      senextself(abdsh);              // arrive  edge<bd>.
-      sspivot(abdsh, abdrightseg);
-      senextself(abdsh);              // arrive  edge<da>
-      sspivot(abdsh, abdleftseg);
-      // Save segments which adhering to 'baesh'.
-      findversion(&baesh, &bace, 0);  // lock at edge<ba>.
-      senextself(baesh);              // arrive  edge<ae>.
-      sspivot(baesh, baerightseg);
-      senextself(baesh);              // arrive  edge<eb>.
-      sspivot(baesh, baeleftseg);
-    }
-  }
-  org (abcd, pa);
-  dest(abcd, pb);
-  apex(abcd, pc);
-  oppo(abcd, pd);
-  oppo(bace, pe);
-
-  // Set new configuration.
-  ceda.tet = abcd.tet;
-  // default: 'ceda' loc = 0, ver = 0.
-  setorg (ceda, pc);
-  setdest(ceda, pe);
-  setapex(ceda, pd);
-  setoppo(ceda, pa);
-
-  cdeb.tet = bace.tet;
-  // default: 'cdeb' loc = 0, ver = 0.
-  setorg (cdeb, pc);
-  setdest(cdeb, pd);
-  setapex(cdeb, pe);
-  setoppo(cdeb, pb);
-
-  // In flip22 case, we needn't reset element attributes and volume
-  //   constraint, because no new tetrahedron be created.
-
-  // There may be shell facets that need to be bonded to the new
-  //   configuration.
-  if (checksegments) {
-    // Clear old flags in 'ceda'('abcd') and 'cdeb'('bace').
-    for (i = 0; i < 4; i ++) {
-      ceda.loc = i;
-      tsdissolve(ceda);
-      cdeb.loc = i;
-      tsdissolve(cdeb);
-    }
-    if (bcdsh.sh != dummysh) {
-      cdeb.loc = 1; // face<b, c, d>.
-      tsbond(cdeb, bcdsh);
-    }
-    if (cbesh.sh != dummysh) {
-      cdeb.loc = 3; // face<c, b, e>.
-      tsbond(cdeb, cbesh);
-    }
-    if (cadsh.sh != dummysh) {
-      ceda.loc = 3; // face<c, a, d>.
-      tsbond(ceda, cadsh);
-    }
-    if (acesh.sh != dummysh) {
-      ceda.loc = 1; // face<a, c, e>.
-      tsbond(ceda, acesh);
-    }
-    if (abdsh.sh != dummysh) {
-      debsh.sh = abdsh.sh;
-      // default: 'debsh' ver = 0.
-      setsorg (debsh, pd);
-      setsdest(debsh, pe);
-      setsapex(debsh, pb);
-
-      edash.sh = baesh.sh;
-      // default: 'edash' ver = 0.
-      setsorg (edash, pe);
-      setsdest(edash, pd);
-      setsapex(edash, pa);
-
-      ssdissolve(debsh);
-      ssdissolve(edash);
-      senextself(debsh);
-      ssbond(debsh, baeleftseg);
-      senextself(debsh);
-      ssbond(debsh, abdrightseg);
-      senextself(edash);
-      ssbond(edash, abdleftseg);
-      senextself(edash);
-      ssbond(edash, baerightseg);
-
-      // Bond with cdeb(loc = 2).
-      cdeb.loc = 2;
-      tsbond(cdeb, debsh);
-      // Bond other side of cdeb('Outer space').
-      sesymself(debsh);
-      tsbond(ghosttet, debsh);
-      // Bond with ceda.
-      ceda.loc = 2;
-      tsbond(ceda, edash);
-      // Bond other side of ceda('Outer space').
-      sesymself(edash);
-      tsbond(ghosttet, edash);
-    }
-  }
-
-  // Clear old flags in 'ceda'('abcd') and 'cdeb'('bace').
-  for (i = 0; i < 4; i ++) {
-    ceda.loc = i;
-    dissolve(ceda);
-    cdeb.loc = i;
-    dissolve(cdeb);
-  }
-  // Bond the new configuration.
-  ceda.loc = 0;
-  cdeb.loc = 0;
-  bond(ceda, cdeb);
-  // Bond each casing facets.
-  cdeb.loc = 1;
-  bond(cdeb, bcdcasing);
-  ceda.loc = 3;
-  bond(ceda, cadcasing);
-  cdeb.loc = 3;
-  bond(cdeb, cbecasing);
-  ceda.loc = 1;
-  bond(ceda, acecasing);
-  // Bond 'Outer space', diffrent in flip44.
-  cdeb.loc = 2;
-  bond(cdeb, ghosttet);
-  ceda.loc = 2;
-  bond(ceda, ghosttet);
-
-  ceda.loc = 0;
-  cdeb.loc = 0;
-#ifdef SELF_CHECK
-  if (!isaboveplane(&ceda, pa)) {
-    printf("Internal error in flip22():\n");
-    printf("  Clockwise tetrahedron after flip (ceda).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&cdeb, pb)) {
-    printf("Internal error in flip22():\n");
-    printf("  Clockwise tetrahedron after flip (cdeb).\n");
-    internalerror();
-  }
-#endif // defined SELF_CHECK
-  if (verbose > 2) {
-    printf("    Updating ceda ");
-    dump(&ceda);
-    printf("    Updating cdeb ");
-    dump(&cdeb);
-  }
-
-  if (usefliplist) {
-    flipcount = 0;
-    ceda.loc = 3; // face<c, a, d>.
-    enqueuefliplist(ceda);
-    ceda.loc = 1; // face<a, c, e>.
-    enqueuefliplist(ceda);
-    cdeb.loc = 1; // face<b, c, d>.
-    enqueuefliplist(cdeb);
-    cdeb.loc = 3; // face<c, b, e>.
-    enqueuefliplist(cdeb);
-  } else {
-    flipcount = 1;
-    ceda.loc = 3; // face<c, a, d>.
-    flipcount += flip(ceda);
-    ceda.loc = 1; // face<a, c, e>.
-    flipcount += flip(ceda);
-    cdeb.loc = 1; // face<b, c, d>.
-    flipcount += flip(cdeb);
-    cdeb.loc = 3; // face<c, b, e>.
-    flipcount += flip(cdeb);
-  }
-
-  return flipcount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flip44()    Swap four tets for four, in the case where two faces are      //
-//             coplanar.                                                     //
-//                                                                           //
-// See Barry Joe's paper [2] as listed at above. See figure 1 in this paper. //
-// We change configuration 3A to 3B. The input 'flipface' lock at edge<ab>.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::flip44(triface& flipface)
-{
-  triface abcd, bace, bafd, abfe;                      // Old configuration.
-  triface oldbcd, oldcad, oldcbe, oldace;
-  triface oldfbd, oldafd, oldbfe, oldfae;
-  triface bcdcasing, cadcasing, cbecasing, acecasing;
-  triface fbdcasing, afdcasing, bfecasing, faecasing;
-  face bcdsh, cadsh, cbesh, acesh;
-  face fbdsh, afdsh, bfesh, faesh;
-  triface oldabd, oldbae;                                 // Flipping faces.
-  face abdsh, baesh, abcsh, abfsh;                     // Flipping subfaces.
-  face abdrightseg, abdleftseg;
-  face baerightseg, baeleftseg;
-  triface ceda, cdeb, fdea, fedb;                      // New configuration.
-  face debsh, edash;
-  point3d pa, pb, pc, pd, pe, pf;
-  int flipcount, i;
-
-  flip_t44s++;
-
-  if (verbose > 2) {
-    printf("    Do T44 on face (%d, %d, %d, %d).\n",
-           pointmark(org(flipface)), pointmark(dest(flipface)),
-           pointmark(apex(flipface)), pointmark(oppo(flipface)));
-  }
-
-  abcd = flipface;
-  adjustedgering(abcd, CCW);
-  sym(abcd, bace);
-  findversion(&bace, &abcd);
-
-  // Find the other side two tets of 'abcd' and 'bace'.
-  bafd = abcd;
-  fnextself(bafd);
-  fnextself(bafd);
-  esymself(bafd);
-  abfe = bace;
-  fnextself(abfe);
-  fnextself(abfe);
-  esymself(abfe);
-
-  oldbcd = oldcad = abcd;
-  enextfnextself(oldbcd);
-  enext2fnextself(oldcad);
-  oldcbe = oldace = bace;
-  enext2fnextself(oldcbe);
-  enextfnextself(oldace);
-
-  oldfbd = oldafd = bafd;
-  enext2fnextself(oldfbd);
-  enextfnextself(oldafd);
-  oldbfe = oldfae = abfe;
-  enextfnextself(oldbfe);
-  enext2fnextself(oldfae);
-
-  sym(oldbcd, bcdcasing);
-  sym(oldcad, cadcasing);
-  sym(oldcbe, cbecasing);
-  sym(oldace, acecasing);
-
-  sym(oldfbd, fbdcasing);
-  sym(oldafd, afdcasing);
-  sym(oldbfe, bfecasing);
-  sym(oldfae, faecasing);
-
-  if (checksegments) {
-    // Check the flip face<a, b, c> 's three edges to see if there exist
-    //   subsegment. This step must do first.
-    tspivot(abcd, abcsh);
-    if (abcsh.sh != dummysh) {
-      assert(isnonsolid(abcsh));
-      preservesubsegments(abcsh, abcd);
-    }
-    // Now, we can find all subfaces abutting faces in old configuration.
-    tspivot(oldbcd, bcdsh);
-    tspivot(oldcad, cadsh);
-    tspivot(oldcbe, cbesh);
-    tspivot(oldace, acesh);
-
-    // Check the flip face<a, b, f> 's three edges to see if there exist
-    //   subsegment. This step must do first.
-    tspivot(bafd, abfsh);
-    if (abfsh.sh != dummysh) {
-      assert(isnonsolid(abfsh));
-      preservesubsegments(abfsh, bafd);
-    }
-    // Now, we can find all subfaces abutting faces in old configuration.
-    tspivot(oldfbd, fbdsh);
-    tspivot(oldafd, afdsh);
-    tspivot(oldbfe, bfesh);
-    tspivot(oldfae, faesh);
-
-    // Keep flip edge and (coplanar) flip faces. This codes are diffrent
-    //   with flip22. 'abdsh' and 'baesh' may be 'dummysh'.
-    fnext(abcd, oldabd);
-    fnext(bace, oldbae);
-    tspivot(oldabd, abdsh);
-    tspivot(oldbae, baesh);
-    if ((abdsh.sh != dummysh) || (baesh.sh != dummysh)) {
-      // Check if there missing a half subface.
-      if (abdsh.sh == dummysh) {
-        assert(baesh.sh != dummysh);
-        insertsubface(&oldabd, NONSOLIDFLAG, 1);
-        tspivot(oldabd, abdsh);
-      } else if (baesh.sh == dummysh) {
-        assert(abdsh.sh != dummysh);
-        insertsubface(&oldbae, NONSOLIDFLAG, 1);
-        tspivot(oldbae, baesh);
-      }
-      // Save segments which adhering to 'abdsh'.
-      findversion(&abdsh, &abcd, 0);  // lock at edge<ab>.
-      senextself(abdsh);
-      sspivot(abdsh, abdrightseg);
-      senextself(abdsh);
-      sspivot(abdsh, abdleftseg);
-      // Save segments which adhering to 'baesh'.
-      findversion(&baesh, &bace, 0);  // lock at edge<ba>.
-      senextself(baesh);
-      sspivot(baesh, baerightseg);
-      senextself(baesh);
-      sspivot(baesh, baeleftseg);
-    }
-  }
-  org (abcd, pa);
-  dest(abcd, pb);
-  apex(abcd, pc);
-  oppo(abcd, pd);
-  oppo(bace, pe);
-  apex(bafd, pf);
-
-  // Set new configuration.
-  ceda.tet = abcd.tet;
-  // default: 'ceda' loc = 0, ver = 0.
-  setorg (ceda, pc);
-  setdest(ceda, pe);
-  setapex(ceda, pd);
-  setoppo(ceda, pa);
-
-  cdeb.tet = bace.tet;
-  // default: 'cdeb' loc = 0, ver = 0.
-  setorg (cdeb, pc);
-  setdest(cdeb, pd);
-  setapex(cdeb, pe);
-  setoppo(cdeb, pb);
-
-  fdea.tet = bafd.tet;
-  // default: 'fdea' loc = 0, ver = 0.
-  setorg (fdea, pf);
-  setdest(fdea, pd);
-  setapex(fdea, pe);
-  setoppo(fdea, pa);
-
-  fedb.tet = abfe.tet;
-  // default: 'fedb' loc = 0, ver = 0.
-  setorg (fedb, pf);
-  setdest(fedb, pe);
-  setapex(fedb, pd);
-  setoppo(fedb, pb);
-
-  // In flip44 case, we needn't reset element attributes and volume
-  //   constraint, because no new tetrahedron be created.
-
-  // There may be shell facets that need to be bonded to the new
-  //   configuration.
-  if (checksegments) {
-    // Clear old flags in 'ceda'('abcd') and 'cdeb'('bace').
-    for (i = 0; i < 4; i ++) {
-      ceda.loc = i;
-      tsdissolve(ceda);
-      cdeb.loc = i;
-      tsdissolve(cdeb);
-    }
-    if (bcdsh.sh != dummysh) {
-      cdeb.loc = 1; // face<b, c, d>.
-      tsbond(cdeb, bcdsh);
-    }
-    if (cbesh.sh != dummysh) {
-      cdeb.loc = 3; // face<c, b, e>.
-      tsbond(cdeb, cbesh);
-    }
-    if (cadsh.sh != dummysh) {
-      ceda.loc = 3; // face<c, a, d>.
-      tsbond(ceda, cadsh);
-    }
-    if (acesh.sh != dummysh) {
-      ceda.loc = 1; // face<a, c, e>.
-      tsbond(ceda, acesh);
-    }
-
-    // Clear old flags in 'fdea'('bafd') and 'fedb'('abfe').
-    for (i = 0; i < 4; i ++) {
-      fdea.loc = i;
-      tsdissolve(fdea);
-      fedb.loc = i;
-      tsdissolve(fedb);
-    }
-    if (fbdsh.sh != dummysh) {
-      fedb.loc = 3; // face<f, b, d>.
-      tsbond(fedb, fbdsh);
-    }
-    if (bfesh.sh != dummysh) {
-      fedb.loc = 1; // face<b, f, e>.
-      tsbond(fedb, bfesh);
-    }
-    if (afdsh.sh != dummysh) {
-      fdea.loc = 1; // face<a, f, d>.
-      tsbond(fdea, afdsh);
-    }
-    if (faesh.sh != dummysh) {
-      fdea.loc = 3; // face<f, a, e>.
-      tsbond(fdea, faesh);
-    }
-    if (abdsh.sh != dummysh) {
-      debsh.sh = abdsh.sh;
-      // default: 'debsh' ver = 0.
-      setsorg (debsh, pd);
-      setsdest(debsh, pe);
-      setsapex(debsh, pb);
-
-      edash.sh = baesh.sh;
-      // default: 'edash' ver = 0.
-      setsorg (edash, pe);
-      setsdest(edash, pd);
-      setsapex(edash, pa);
-
-      ssdissolve(debsh);
-      ssdissolve(edash);
-      senextself(debsh);
-      ssbond(debsh, baeleftseg);
-      senextself(debsh);
-      ssbond(debsh, abdrightseg);
-      senextself(edash);
-      ssbond(edash, abdleftseg);
-      senextself(edash);
-      ssbond(edash, baerightseg);
-
-      // Sandwich between 2 tets.
-      cdeb.loc = 2;
-      tsbond(cdeb, debsh);
-      sesymself(debsh);   // Don't forget to change edgering.
-      fedb.loc = 2;
-      tsbond(fedb, debsh);
-      // Sandwich between 2 tets.
-      ceda.loc = 2;
-      tsbond(ceda, edash);
-      sesymself(edash);  // Don't forget to change edgering.
-      fdea.loc = 2;
-      tsbond(fdea, edash); 
-    }
-  }
-
-  for (i = 0; i < 4; i ++) {
-    ceda.loc = i;
-    dissolve(ceda);
-    cdeb.loc = i;
-    dissolve(cdeb);
-  }
-  // Bond the new configuration.
-  ceda.loc = 0;
-  cdeb.loc = 0;
-  bond(ceda, cdeb);
-  // Bond each casing facets.
-  cdeb.loc = 1;
-  bond(cdeb, bcdcasing);
-  ceda.loc = 3;
-  bond(ceda, cadcasing);
-  cdeb.loc = 3;
-  bond(cdeb, cbecasing);
-  ceda.loc = 1;
-  bond(ceda, acecasing);
-
-  for (i = 0; i < 4; i ++) {
-    fdea.loc = i;
-    dissolve(fdea);
-    fedb.loc = i;
-    dissolve(fedb);
-  }
-  // Bond the two new tetrahedron at other side.
-  fdea.loc = 0;
-  fedb.loc = 0;
-  bond(fdea, fedb);
-  // Bond each casing facets.
-  fedb.loc = 3;
-  bond(fedb, fbdcasing);
-  fdea.loc = 1;
-  bond(fdea, afdcasing);
-  fedb.loc = 1;
-  bond(fedb, bfecasing);
-  fdea.loc = 3;
-  bond(fdea, faecasing);
-
-  // Bond two side tets.
-  ceda.loc = 2;
-  fdea.loc = 2;
-  bond(ceda, fdea);
-  cdeb.loc = 2;
-  fedb.loc = 2;
-  bond(cdeb, fedb);
-
-  ceda.loc = 0;
-  cdeb.loc = 0;
-  fdea.loc = 0;
-  fedb.loc = 0;
-#ifdef SELF_CHECK
-  if (!isaboveplane(&ceda, pa)) {
-    printf("Internal error in flip44():\n");
-    printf("  Clockwise tetrahedron after flip (ceda).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&cdeb, pb)) {
-    printf("Internal error in flip44():\n");
-    printf("  Clockwise tetrahedron after flip (cdeb).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&fdea, pa)) {
-    printf("Internal error in flip44():\n");
-    printf("  Clockwise tetrahedron after flip (fdea).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&fedb, pb)) {
-    printf("Internal error in flip44():\n");
-    printf("  Clockwise tetrahedron after flip (fedb).\n");
-    internalerror();
-  }
-#endif // defined SELF_CHECK
-  if (verbose > 2) {
-    printf("    Updating ceda ");
-    dump(&ceda);
-    printf("    Updating cdeb ");
-    dump(&cdeb);
-    printf("    Updating fdea ");
-    dump(&fdea);
-    printf("    Updating fedb ");
-    dump(&fedb);
-  }
-
-  if (usefliplist) {
-    flipcount = 0;
-    ceda.loc = 3; // face<c, a, d>.
-    enqueuefliplist(ceda);
-    ceda.loc = 1; // face<a, c, e>.
-    enqueuefliplist(ceda);
-    cdeb.loc = 1; // face<b, c, d>.
-    enqueuefliplist(cdeb);
-    cdeb.loc = 3; // face<c, b, e>.
-    enqueuefliplist(cdeb);
-    fdea.loc = 1; // face<a, f, d>.
-    enqueuefliplist(fdea);
-    fdea.loc = 3; // face<f, a, e>.
-    enqueuefliplist(fdea);
-    fedb.loc = 3; // face<f, b, d>.
-    enqueuefliplist(fedb);
-    fedb.loc = 1; // face<b, f, e>.
-    enqueuefliplist(fedb);
-  } else {
-    flipcount = 1;
-    ceda.loc = 3; // face<c, a, d>.
-    flipcount += flip(ceda);
-    ceda.loc = 1; // face<a, c, e>.
-    flipcount += flip(ceda);
-    cdeb.loc = 1; // face<b, c, d>.
-    flipcount += flip(cdeb);
-    cdeb.loc = 3; // face<c, b, e>.
-    flipcount += flip(cdeb);
-    fdea.loc = 1; // face<a, f, d>.
-    flipcount += flip(fdea);
-    fdea.loc = 3; // face<f, a, e>.
-    flipcount += flip(fdea);
-    fedb.loc = 3; // face<f, b, d>.
-    flipcount += flip(fedb);
-    fedb.loc = 1; // face<b, f, e>.
-    flipcount += flip(fedb);
-  }
-
-  return flipcount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flip()    Swap away face if this is legal and improves the mesh quality   //
-//           measure.                                                        //
-//                                                                           //
-// Swapping typically propagates through the mesh, and the return value is   //
-// the total number of swaps done during this invocation.                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::flip(triface& flipface)
-{
-  // If the face has been removed, don't bother
-  if (isdead(&flipface)) return (0);
-
-  enum facecategory fc = categorizeface(flipface);
-  // Determine the preferable configuration and swap if necessary.
-  switch (fc) {
-    // These cases are handled by edge swapping.
-    case N44:
-    case N32:
-      // if (edgeswapallow) {
-        // if (querydoswap(flipface)) {
-        //  return edgeswap(flipface, 0);
-        // }
-      // }
-      break;
-    // These cases are definitely unswappable
-    case N40:
-    case N30:
-    case N20:
-    case LOCKED:
-      break;
-    case T44:
-      if (querydoswap(flipface)) {
-        return flip44(flipface);
-      }
-      break;
-    case T22:
-      if (querydoswap(flipface)) {
-        return flip22(flipface);
-      }
-      break;
-    case T23:
-      if (querydoswap(flipface)) {
-        return flip23(flipface);
-      }
-      break;
-    case T32:
-      if (querydoswap(flipface)) {
-        return flip32(flipface);
-      }
-      break;
-    // Catch-all for bad cases
-    default:
-      // Shouldn't be here: face wasn't categorized.
-      break;
-  }
-  checkquality(&flipface);
-  return 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// enqueuefliplist()    Add a face which may be non-Delaunay to 'fliplist',  //
-//                      so we can batch process all (to be flipped) faces    //
-//                      together rather than flip a face at one time.        //
-//                                                                           //
-// This routine couple with dequeuefliplist() and dofliplist() are used for  //
-// the implementation of Randomized Incremental Delaunay Algorithm.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::enqueuefliplist(triface& flipface)
-{
-  badface3d queface;
-
-  queface.badfacetet = flipface;
-  org (flipface, queface.faceorg);
-  dest(flipface, queface.facedest);
-  apex(flipface, queface.faceapex); 
-  if (verbose > 2) {
-    printf("    Queueing flip face: (%d, %d, %d).\n",
-           pointmark(queface.faceorg), pointmark(queface.facedest),
-           pointmark(queface.faceapex));
-  }
-  fliplist->push(&queface);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dequeuefliplist()    Get a exist face from 'fliplist', check its Delaunay //
-//                      -hood and perform corresponding flip operator if it  //
-//                      is a non-Delaunay face.                              //
-//                                                                           //
-// This routine couple with enqueuefliplist() and dofliplist() are used for  //
-// the implementation of Randomized Incremental Delaunay Algorithm.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool mesh3d::dequeuefliplist(triface& flipface)
-{
-  badface3d queface;
-  point3d forg, fdest, fapex;
-
-  while (fliplist->get(&queface)) {
-    if (!isdead(&(queface.badfacetet))) {
-      org (queface.badfacetet, forg);
-      dest(queface.badfacetet, fdest);
-      apex(queface.badfacetet, fapex);
-      if ((forg == queface.faceorg)
-          && (fdest == queface.facedest)
-          && (fapex == queface.faceapex)) {
-        flipface = queface.badfacetet;
-        if (verbose > 2) {
-          printf("    Getting  flip face: (%d, %d, %d).\n",
-                 pointmark(queface.faceorg), pointmark(queface.facedest),
-                 pointmark(queface.faceapex));
-        }
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Mesh Transformation Routines                                              //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Insert/Delete point routines                                              //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertsite()    Insert a vertex into Delaunay tetrahedrization, perform-  //
-//                 ing flips as necessary to maintain the Delaunay property. //
-//                                                                           //
-//   The point 'insertpoint' is located.  If 'searchtet.tet' is not NULL,    //
-// the search for the containing tetrahedron begins from 'searchtet'. If     //
-// 'searchtet.tet' is NULL, a full point location procedure is called. If    //
-// 'inseertpoint' is found inside a tetrahedron, the tetrahedra is split     //
-// into four by call routine insertininterior(); if 'insertpoint' lies on    //
-// an edge, the edge is split in two, thereby splitting the adjacent         //
-// tetrahedra. It will be done by call routine insertonedge();  if           //
-// 'insertpoint' lies on an face, the face is split into three, thereby      //
-// splitting the adjacent tetrahedra.  It will be done by call routine       //
-// insertonface().  Face or edge flips are used to restore the Delaunay      //
-// property.  If 'insertpoint' lies on an existing vertex, no action is      //
-// taken, and value DUPLICATEPOINT is returned. On return, 'searchtet' is    //
-// set to a handle contain the existing vertex.                              //
-//                                                                           //
-//   Normally, the parameter 'splitface' and 'splitedge' are set to NULL,    //
-// implying that no subface and subsegment should be split. In this case, if //
-// 'insertpoint' is found to lie on a subface or a subsegment, no action is  //
-// taken, and the value VIOLATINGFACE or VIOLATINGEDGE is returned. On       //
-// return, 'searchtet' is set to a handle whose primary face or edge is the  //
-// violated subface or subsegment.                                           //
-//                                                                           //
-//   If the calling routine wishes to split a subface or subsegment by       //
-// inserting a point in it, the parameter 'splitface' or 'splitedge' should  //
-// be that subface or subsegment. In this case, 'searchtet' MUST be the      //
-// tetrahedron handle reached by pivoting from that subface or subsegment;   //
-// no point location is done.                                                //
-//                                                                           //
-//   If a point being inserted,  the return value will be SUCCESSFUL. If a   //
-// point is found to locate outside the mesh and can't be inserted, the      //
-// return value will be FAILED otherwise. In either case, 'searchtet' is set //
-// to a handle whose contains the newly inserted vertex.                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum mesh3d::insertsiteresult
-mesh3d::insertsite(point3d insertpoint, triface* searchtet, face* splitface,
-                   face* splitedge)
-{
-  triface horiz;
-  face brokenshell;
-  badface3d *encroached;
-  enum locateresult intersect;
-  int flipcount;
-
-  if (verbose > 1) {
-    printf("  Insert point to mesh: (%.12g, %.12g, %.12g) %d.\n",
-           insertpoint[0], insertpoint[1], insertpoint[2],
-           pointmark(insertpoint));
-  }
-
-  if ((splitface == NULL) && (splitedge == NULL)) {
-    // Find the location of the point to be inserted. Check if a good
-    //   starting tetrahedron has already been provided by the caller.
-    if (isdead(searchtet)) {
-      // Find a boundary tetrahedron.
-      horiz.tet = dummytet;
-      horiz.loc = 0;
-      symself(horiz);
-      // Search for a tetrahedron containing 'insertpoint'.
-      intersect = locate(insertpoint, &horiz);
-    } else {
-      // Start searching from the tetrahedron provided by the caller.
-      horiz = *searchtet;
-      intersect = preciselocate(insertpoint, &horiz);
-    }
-  } else {
-    // The calling routine provides the edge or face in which the point
-    //   is inserted.
-    horiz = *searchtet;
-    if ((splitface != NULL) && (splitedge == NULL))  {
-      intersect = ONFACE;
-    } else if ((splitface == NULL) && (splitedge != NULL)) {
-      intersect = ONEDGE;
-    } else {
-      printf("Internal error in insertsite():");
-      printf("  splitface and splitedge couldn't use together.\n");
-      internalerror();
-    }
-  }
-
-  // Keep search stat.
-  *searchtet = horiz;
-  recenttet = horiz;
-
-  switch (intersect) {
-    case ONVERTEX:
-      // There's already a vertex there. Return in 'searchtet' a tetrahedron
-      //   whose origin is the existing vertex.
-      if (verbose > 1) {
-        printf("  Not insert for duplicating point.\n");
-      }
-      return DUPLICATE;
-
-    case ONEDGE:
-      // The vertex falls on an edge or boundary.
-      if (checksegments && (splitedge == NULL)) {
-        // Check whether the vertex falls on a shell edge.
-        tsspivot(&horiz, &brokenshell);
-        if (brokenshell.sh != dummysh) {
-          // The vertex falls on a shell edge.
-          if (shsegflaws) {
-            if (nobisect == 0) {
-              // Add the shell edge to the list of encroached segments.
-              encroached = (badface3d*) badsegments.alloc();
-              encroached->shface = brokenshell;
-              sorg (brokenshell, encroached->faceorg);
-              sdest(brokenshell, encroached->facedest);
-            } else if ((nobisect == 1) && (intersect == ONEDGE)) {
-              // This segment may be split only if it is an internal
-              //   boundary.
-              if (!isridge(&horiz)) {
-                // Add the shell edge to the list of encroached segments.
-                encroached = (badface3d*) badsegments.alloc();
-                encroached->shface = brokenshell;
-                sorg (brokenshell, encroached->faceorg);
-                sdest(brokenshell, encroached->facedest);
-              }
-            }
-          }
-          // Return a handle whose primary edge contains the point, which
-          //   has not been inserted.
-          if (verbose > 1) {
-            printf("  Not insert for landing right on other subsegment.\n");
-          }
-          return VIOLATINGEDGE;
-        }
-      }
-      flipcount = insertonedge(insertpoint, searchtet, splitedge);
-      if (verbose > 1) {
-        printf("  Successfully insert on edge with %d flips.\n", flipcount);
-      }
-      return SUCCESSFUL;
-
-    case ONFACE:
-      // The vertex falls on a facet or boundary.
-      if (checksegments && (splitface == NULL)) {
-        // Check whether the vertex falls on a shell facet.
-        tspivot(horiz, brokenshell);
-        if (brokenshell.sh != dummysh) {
-          // The vertex falls on a shell facet.
-          if (shflaws) {
-            if (nobisect == 0) {
-              // Add the shell facet to the list of encroached subfaces.
-              enqueuebadface(&brokenshell, (point3d)NULL, 1);
-            } else if ((nobisect == 1) && (intersect == ONEDGE)) {
-              // This subface may be split only if it is an internal
-              //   boundary.
-              if (issymexist(&horiz)) {
-                // Add the shell facet to the list of encroached subface.
-                enqueuebadface(&brokenshell, (point3d)NULL, 1);
-              }
-            }
-          }
-          // Return a handle whose primary face contains the point,
-          //   which has not been inserted.
-          if (verbose > 1) {
-            printf("  Not insert for landing right on other subface.\n");
-          }
-          return VIOLATINGFACE;
-        }
-      }
-      flipcount = insertonface(insertpoint, searchtet, splitface);
-      if (verbose > 1) {
-        printf("  Successfully insert on face with %d flips.\n", flipcount);
-      }
-      return SUCCESSFUL;
-
-    case INTETRAHEDRON:
-      // This vertex falls inside a tetrahedron.
-      flipcount = insertininterior(insertpoint, searchtet);
-      if (verbose > 1) {
-        printf("  Successfully insert in tetrahedron with %d flips.\n",
-               flipcount);
-      }
-      return SUCCESSFUL;
-
-    case OUTSIDE:
-      if (verbose > 1) {
-        printf("  Not insert for locating outside the mesh.\n");
-      }
-      return FAILED;
-  } // End of switch(intersect)
-
-  // Should never have a chance to reach here.
-  return FAILED;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertininterior()     Insert the point in a  tetrahedron,   splitting it //
-//                        into four.  Face or edge flips are used to restore //
-//                        the Delaunay property.                             //
-//                                                                           //
-// 'insertpoint'(v) lies above wrt 'horiz'(abcd).                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::insertininterior(point3d insertpoint, triface* horiz)
-{
-  triface oldabd, oldbcd, oldcad;                      // Old configuration.
-  triface abdcasing, bcdcasing, cadcasing;
-  face abdsh, bcdsh, cadsh;
-  triface abcv, badv, cbdv, acdv;                      // New configuration.
-  point3d pa, pb, pc, pd;
-  REAL attrib, volume;
-  int flipcount, i;
-
-  abcv = *horiz;
-  abcv.ver = 0;
-  // Set the vertices of changed and new tetrahedron.
-  org (abcv, pa);
-  dest(abcv, pb);
-  apex(abcv, pc);
-  oppo(abcv, pd);
-
-  oldabd = oldbcd = oldcad = abcv;
-  fnextself(oldabd);
-  enextfnextself(oldbcd);
-  enext2fnextself(oldcad);
-  sym(oldabd, abdcasing);
-  sym(oldbcd, bcdcasing);
-  sym(oldcad, cadcasing);
-  maketetrahedron(&badv);
-  maketetrahedron(&cbdv);
-  maketetrahedron(&acdv);
-
-  // Set 'badv' vertexs.
-  setorg (badv, pb);
-  setdest(badv, pa);
-  setapex(badv, pd);
-  setoppo(badv, insertpoint);
-  // Set 'cbdv' vertexs.
-  setorg (cbdv, pc);
-  setdest(cbdv, pb);
-  setapex(cbdv, pd);
-  setoppo(cbdv, insertpoint);
-  // Set 'acdv' vertexs.
-  setorg (acdv, pa);
-  setdest(acdv, pc);
-  setapex(acdv, pd);
-  setoppo(acdv, insertpoint);
-  // Set 'abcv' vertexs
-  setoppo(abcv, insertpoint);
-
-  // Set the element attributes of the new tetrahedron.
-  for (i = 0; i < eextras; i++) {
-    attrib = elemattribute(abcv.tet, i);
-    setelemattribute(badv.tet, i, attrib);
-    setelemattribute(cbdv.tet, i, attrib);
-    setelemattribute(acdv.tet, i, attrib);
-  }
-  // Set the volume constraint of the new tetrahedron.
-  if (varvolume) {
-    volume = volumebound(abcv.tet);
-    setvolumebound(badv.tet, volume);
-    setvolumebound(cbdv.tet, volume);
-    setvolumebound(acdv.tet, volume);
-  }
-
-  // There may be shell facets that need to be bonded to
-  //   the new tetrahedron.
-  if (checksegments) {
-    tspivot(oldabd, abdsh);
-    if (abdsh.sh != dummysh) {
-      tsdissolve(oldabd);
-      tsbond(badv, abdsh);
-    }
-    tspivot(oldbcd, bcdsh);
-    if (bcdsh.sh != dummysh) {
-      tsdissolve(oldbcd);
-      tsbond(cbdv, bcdsh);
-    }
-    tspivot(oldcad, cadsh);
-    if (cadsh.sh != dummysh) {
-      tsdissolve(oldcad);
-      tsbond(acdv, cadsh);
-    }
-  }
-
-  // Bond the new triangles to the surrounding tetrahedron.
-  bond(badv, abdcasing);
-  bond(cbdv, bcdcasing);
-  bond(acdv, cadcasing);
-
-  badv.loc = 3; // face<d, v, b>.
-  cbdv.loc = 2;
-  bond(badv, cbdv);
-  cbdv.loc = 3; // face<d, v, c>.
-  acdv.loc = 2;
-  bond(cbdv, acdv);
-  acdv.loc = 3; // face<d, v, a>.
-  badv.loc = 2;
-  bond(acdv, badv);
-  badv.loc = 1; // face<b, v, a>.
-  bond(badv, oldabd);
-  cbdv.loc = 1; // face<c, v, b>.
-  bond(cbdv, oldbcd);
-  acdv.loc = 1; // face<a, v, c>.
-  bond(acdv, oldcad);
-
-  badv.loc = 0;
-  cbdv.loc = 0;
-  acdv.loc = 0;
-#ifdef SELF_CHECK
-  if (!isaboveplane(&abcv, insertpoint)) {
-    printf("Internal error in insertininterior():\n");
-    printf("  Clockwise tetrahedron prior to point insertion(abcv).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&badv, insertpoint)) {
-    printf("Internal error in insertininterior():\n");
-    printf("  Clockwise tetrahedron after point insertion (badv).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&cbdv, insertpoint)) {
-    printf("Internal error in insertininterior():\n");
-    printf("  Clockwise tetrahedron after point insertion (cbdv).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&acdv, insertpoint)) {
-    printf("Internal error in insertininterior():\n");
-    printf("  Clockwise tetrahedron after point insertion (acdv).\n");
-    internalerror();
-  }
-#endif // defined SELF_CHECK
-  if (verbose > 2) {
-    printf("    Updating abcv ");
-    dump(&abcv);
-    printf("    Creating badv ");
-    dump(&badv);
-    printf("    Creating cbdv ");
-    dump(&cbdv);
-    printf("    Creating acdv ");
-    dump(&acdv);
-  }
-
-  flipcount = 0;
-
-  if (usefliplist) {
-    enqueuefliplist(abcv);
-    enqueuefliplist(badv);
-    enqueuefliplist(cbdv);
-    enqueuefliplist(acdv);
-  } else {
-    flipcount += flip(abcv);
-    flipcount += flip(badv);
-    flipcount += flip(cbdv);
-    flipcount += flip(acdv);
-  }
-
-  if (isdead(horiz)) {
-    // We need return a live tet.
-    if (!isdead(&badv)) {
-      *horiz = badv;
-    } else if (!isdead(&cbdv)) {
-      *horiz = cbdv;
-    } else {
-      // assert(!acdv.isdead());
-      if (!isdead(&acdv)) {
-        *horiz = acdv;
-      } else {
-        if (verbose) {
-          printf("Warnning in insertininterior():\n");
-          printf("  After %d flips, we can't return a live tet.\n", flipcount);
-        }
-      }
-    }
-  }
-
-  return flipcount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertonface()    Insert a point on a face of tetrahedron, splitting one  //
-//                   tetrahedron into three (if the face lies on outer       //
-//                   boundary), or two tetrahedras into six.  Face or edge   //
-//                   flips are used to restore the Delaunay property.        //
-//                                                                           //
-// 'horiz.location()' indicates the face where 'insertpoint' lies on. If the //
-// 'splitface' != NULL, this mean insert a point on boundary face.   'horiz' //
-// should be a handle of this boundary face adjoining to.                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::insertonface(point3d insertpoint, triface* horiz, face* splitface)
-{
-  triface oldbcd, oldcad, oldace, oldcbe;              // Old configuration.
-  triface bcdcasing, cadcasing, acecasing, cbecasing;
-  face bcdsh, cadsh, acesh, cbesh;
-  triface badv, cbdv, acdv, abev, bcev, caev;          // New configuration.
-  point3d pa, pb, pc, pd, pe;
-  REAL attrib, volume;
-  bool mirrorflag;
-  int flipcount, i;
-
-  badv = *horiz;
-  badv.ver = 0;
-  // Now assume 'badv' is tet<a, b, c, d>.
-  org (badv, pa);
-  dest(badv, pb);
-  apex(badv, pc);
-  oppo(badv, pd);
-  // Is there a second tetrahderon?
-  mirrorflag = issymexist(&badv);
-  if (mirrorflag) {
-    // This is a interior face.
-    sym(badv, abev);
-    findversion(&abev, &badv);
-    // Now 'abev' is tet <b, a, c, e>.
-    oppo(abev, pe);
-  }
-
-  oldbcd = oldcad = badv;
-  enextfnextself(oldbcd);
-  enext2fnextself(oldcad);
-  fnextself(badv);
-  esymself(badv);  // Now 'badv' is tet<b, a, d, c>.
-  sym(oldbcd, bcdcasing);
-  sym(oldcad, cadcasing);
-  maketetrahedron(&cbdv);
-  maketetrahedron(&acdv);
-  // Is there a second tetrahderon?
-  if (mirrorflag) {
-    // This is a interior face.
-    oldace = oldcbe = abev;
-    enextfnextself(oldace);
-    enext2fnextself(oldcbe);
-    fnextself(abev);
-    esymself(abev);  // Now abev is tet<a, b, e, c>.
-    sym(oldace, acecasing);
-    sym(oldcbe, cbecasing);
-    maketetrahedron(&caev);
-    maketetrahedron(&bcev);
-  } else {
-    // Splitting the boundary face increases the number of boundary faces.
-    hullsize += 2;
-  }
-
-  // Set the vertices of changed and new tetrahedron.
-  // Set 'cbdv'.
-  setorg (cbdv, pc);
-  setdest(cbdv, pb);
-  setapex(cbdv, pd);
-  setoppo(cbdv, insertpoint);
-  // Set 'acdv'.
-  setorg (acdv, pa);
-  setdest(acdv, pc);
-  setapex(acdv, pd);
-  setoppo(acdv, insertpoint);
-  // Set 'badv'.
-  setoppo(badv, insertpoint);
-
-  // Set the element attributes of new tetrahedron.
-  for (i = 0; i < eextras; i++) {
-    attrib = elemattribute(badv.tet, i);
-    setelemattribute(cbdv.tet, i, attrib);
-    setelemattribute(acdv.tet, i, attrib);
-  }
-  if (varvolume) {
-    // Set the area constraint of new tetrahedron.
-    volume = volumebound(badv.tet);
-    setvolumebound(cbdv.tet, volume);
-    setvolumebound(acdv.tet, volume);
-  }
-
-  if (mirrorflag) {
-    // Set 'caev'.
-    setorg (caev, pc);
-    setdest(caev, pa);
-    setapex(caev, pe);
-    setoppo(caev, insertpoint);
-    // Set 'bcev'.
-    setorg(bcev, pb);
-    setdest(bcev, pc);
-    setapex(bcev, pe);
-    setoppo(bcev, insertpoint);
-    // Set 'abev'.
-    setoppo(abev, insertpoint);
-
-    // Set the element attributes of new tetrahedron.
-    for (i = 0; i < eextras; i++) {
-      attrib = elemattribute(abev.tet, i);
-      setelemattribute(bcev.tet, i, attrib);
-      setelemattribute(caev.tet, i, attrib);
-    }
-    if (varvolume) {
-      // Set the area constraint of new tetrahedron.
-      volume = volumebound(abev.tet);
-      setvolumebound(bcev.tet, volume);
-      setvolumebound(caev.tet, volume);
-    }
-  }
-
-  // There may be shell facets that need to be bonded to the
-  //   new tetrahedron.
-  if (checksegments) {
-    tspivot(oldbcd, bcdsh);
-    if (bcdsh.sh != dummysh) {
-      tsdissolve(oldbcd);
-      tsbond(cbdv, bcdsh);
-    }
-    tspivot(oldcad, cadsh);
-    if (cadsh.sh != dummysh) {
-      tsdissolve(oldcad);
-      tsbond(acdv, cadsh);
-    }
-    if (mirrorflag) {
-      tspivot(oldace, acesh);
-      if (acesh.sh != dummysh) {
-        tsdissolve(oldace);
-        tsbond(caev, acesh);
-      }
-      tspivot(oldcbe, cbesh);
-      if (cbesh.sh != dummysh) {
-        tsdissolve(oldcbe);
-        tsbond(bcev, cbesh);
-      }
-    }
-  }
-
-  // Bond the new tetrahedron to the surrounding tetrahedron.
-  bond(cbdv, bcdcasing);  // Default 'cbdv' loc = 0.
-  bond(acdv, cadcasing);  // Default 'acdv' loc = 0.
-  cbdv.loc = 2;
-  bond(cbdv, oldbcd);
-  cbdv.loc = 3;
-  acdv.loc = 2;
-  bond(cbdv, acdv);
-  acdv.loc = 3;
-  bond(acdv, oldcad);
-
-  if (mirrorflag) {
-    bond(caev, acecasing);  // Default 'bcev' loc = 0.
-    bond(bcev, cbecasing);  // Default 'caev' loc = 0.
-    caev.loc = 2;
-    bond(caev, oldace);
-    caev.loc = 3;
-    bcev.loc = 2;
-    bond(caev, bcev);
-    bcev.loc = 3;
-    bond(bcev, oldcbe);
-
-    // Bond two new coplanar facets.
-    cbdv.loc = 1;
-    bcev.loc = 1;
-    bond(cbdv, bcev);
-    acdv.loc = 1;
-    caev.loc = 1;
-    bond(acdv, caev);
-  }
-
-  cbdv.loc = 0;
-  acdv.loc = 0;
-  if (mirrorflag) {
-    bcev.loc = 0;
-    caev.loc = 0;
-  }
-
-  if (splitface != (face *) NULL) {
-    // We need insert two new subface into current mesh.
-    triface righttet, lefttet;
-    face oldrightshface, oldleftshface;
-    face rightshseg, leftshseg;
-    face newrightshface, newleftshface;
-
-    // Init 'splitface' be face<a, b, c>
-    findversion(splitface, pa, pb, 0);
-    senext(*splitface, oldrightshface);  // face<b, c, a>
-    senext2(*splitface, oldleftshface);  // face<c, a, b>
-
-    // Set 'splitface' be face<a, b, v>
-    setsapex(*splitface, insertpoint);
-    // Insert two new shell facets at cbdv(right), and acdv(left).
-    //   Set 'righttet' be tet<c, b, v, -d>.
-    fnext(cbdv, righttet);
-    //   Insert a new subface abutting 'righttet'.
-    insertsubface(&righttet, mark(*splitface), 0);
-    //   Set 'lefttet' tet<a, c, v, -d>.
-    fnext(acdv, lefttet);
-    //   Insert a new subface abutting 'leftete'.
-    insertsubface(&lefttet, mark(*splitface), 0);
-
-    // Set 'newrightshface' be face<b, c, v>
-    tspivot(righttet, newrightshface);
-    findversion(&newrightshface, pb, pc, 0);
-    // Set 'newleftshface' be face<c, a, v>
-    tspivot(lefttet, newleftshface);
-    findversion(&newleftshface, pc, pa, 0);
-
-    // Bond subsegments to two new shell facets if there have one. Do not
-    //   forget to dissolve orgin bond first.
-    sspivot(oldrightshface, rightshseg);
-    if (rightshseg.sh != dummysh) {
-      ssdissolve(oldrightshface);
-      ssbond(newrightshface, rightshseg);
-    }
-    sspivot(oldleftshface, leftshseg);
-    if (leftshseg.sh != dummysh) {
-      ssdissolve(oldleftshface);
-      ssbond(newleftshface, leftshseg);
-    }
-
-    if (shflaws) {
-      // Now, the original 'splitface' was splitted to 'splitface',
-      //   'newrightshface' and 'newleftshface'.
-      // In quality mesh generation step, we need check if these three
-      //   subfaces being encroached. (Because they are Delaunay faces
-      //   and needn't do flip).
-      uncheckedshlist->append(splitface);
-      uncheckedshlist->append(&newrightshface);
-      uncheckedshlist->append(&newleftshface);
-    }
-  } // if (splitface != (face *) NULL)
-
-#ifdef SELF_CHECK
-  if (!isaboveplane(&badv, insertpoint)) {
-    printf("Internal error in insertonface():\n");
-    printf("  Clockwise tetra prior to face point insertion (badv).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&cbdv, insertpoint)) {
-    printf("Internal error in insertonface():\n");
-    printf("  Clockwise tetra after face point insertion (cbdv).\n");
-    internalerror();
-  }
-  if (!isaboveplane(&acdv, insertpoint)) {
-    printf("Internal error in insertonface():\n");
-    printf("  Clockwise tetra after face point insertion (acdv).\n");
-    internalerror();
-  }
-  if (mirrorflag) {
-    if (!isaboveplane(&abev, insertpoint)) {
-      printf("Internal error in insertonface():\n");
-      printf("  Clockwise tetra prior to face point insertion (abev).\n");
-      internalerror();
-    }
-    if (!isaboveplane(&bcev, insertpoint)) {
-      printf("Internal error in insertonface():\n");
-      printf("  Clockwise tetra after face point insertion (bcev).\n");
-      internalerror();
-    }
-    if (!isaboveplane(&caev, insertpoint)) {
-      printf("Internal error in insertonface():\n");
-      printf("  Clockwise tetra after face point insertion (caev).\n");
-      internalerror();
-    }
-  }
-#endif // defined SELF_CHECK
-  if (verbose > 2) {
-    printf("    Updating badv ");
-    dump(&badv);
-    printf("    Creating cbdv ");
-    dump(&cbdv);
-    printf("    Creating acdv ");
-    dump(&acdv);
-    if (mirrorflag) {
-      printf("    Updating abev ");
-      dump(&abev);
-      printf("    Creating bcev ");
-      dump(&bcev);
-      printf("    Creating caev ");
-      dump(&caev);
-    }
-  }
-
-  flipcount = 0;
-
-  if (usefliplist) {
-    enqueuefliplist(badv);
-    enqueuefliplist(cbdv);
-    enqueuefliplist(acdv);
-    if (mirrorflag) {
-      enqueuefliplist(abev);
-      enqueuefliplist(bcev);
-      enqueuefliplist(caev);
-    }
-  } else {
-    flipcount += flip(badv);
-    flipcount += flip(cbdv);
-    flipcount += flip(acdv);
-    if (mirrorflag) {
-      flipcount += flip(abev);
-      flipcount += flip(bcev);
-      flipcount += flip(caev);
-    }
-  }
-
-  if (isdead(horiz)) {
-    // We need return a live tet.
-    if (splitface != (face*) NULL) {
-      stpivot(*splitface, *horiz);
-      if (horiz->tet == dummytet) {
-        assert(mirrorflag == 0);
-        sesymself(*splitface);
-        stpivot(*splitface, *horiz);
-      }
-    } else if (!isdead(&cbdv)) {
-      *horiz = cbdv;
-    } else if (!isdead(&acdv)) {
-      *horiz = acdv;
-    } else {
-      assert(mirrorflag);
-      if (!isdead(&abev)) {
-        *horiz = abev;
-      } else if (!isdead(&bcev)) {
-        *horiz = bcev;
-      } else {
-        // assert(!caev.isdead());
-        if (!isdead(&caev)) {
-          *horiz = caev;
-        } else {
-          if (verbose) {
-            printf("Warnning in insertonface(): \n");
-            printf("  After %d flips, we can't return a live tet.\n",
-                   flipcount);
-          }
-        }
-      }
-    }
-  }
-
-  return flipcount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertonedge()    Insert a point on an edge, splitting all tetrahedra     //
-//                   which around this edge into two.  Face or edge flips    //
-//                   are used to restore the Delaunay property.              //
-//                                                                           //
-// 'horiz.org()' and 'horiz.dest()'  indicates the edge where 'insertpoint'  //
-// lies on. If the 'splitedge' != NULL, this mean insert a point on boundary //
-// edge. 'horiz' should be a handle of this boundary edge adjoining to.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::insertonedge(point3d insertpoint, triface* horiz, face* splitedge)
-{
-  triface bdrytet, spintet, tmptet;
-  triface *bots, *oldtops, *topcasings, *newtops;
-  face topshell;
-  triface tmpbond0, tmpbond1;
-  point3d pa, pb, nj, nj_1;
-  point3d tapex;
-  int wrapfacecount, wrapcount, hitbdry;
-  int flipcount, i, k;
-
-  // Adjust 'horiz''s face version. Let it belong to EdgeRing = 0.
-  adjustedgering(*horiz, CCW);
-  // Now, we can sure 'horiz' be tet<b, a, n1, n2>.
-
-  // First find how much tetrahedron wrap around edge<ba>. As a side effect,
-  //   we will find if edge<ba> lies on boundary, if so we keep the handle
-  //   of first encountered boundary tetrahedron in 'bdrytet'.
-  spintet = *horiz;
-  apex(*horiz, tapex);
-  wrapfacecount = 1;
-  hitbdry = 0;
-  while (true) {
-    if (fnextself(spintet)) {
-      if (apex(spintet) == tapex) {
-        break;
-      }
-      wrapfacecount ++;
-    } else {
-      hitbdry ++;
-      if (hitbdry >= 2) {
-        break;
-      } else {
-        esym(spintet, bdrytet);
-        esym(*horiz, spintet);
-      }
-    }
-  }
-
-  // Determine how much wrap tetrahedra from 'wrapfacecount'.
-  if (hitbdry == 0) {
-    wrapcount = wrapfacecount;
-  } else {
-    wrapcount = wrapfacecount - 1;
-    // Splitting the boundary face increases the number of boundary faces.
-    hullsize += 2;
-  }
-  assert(wrapcount >= 1);
-
-  // Current state:
-  //   Let i = wrapfacecount be the total found faces. Let the wrap faces'
-  //     apex sequence be: n[1], n[2], ..., n[i].
-  //   IF hitbdry = 0, THEN edge<ba> is inner edge. 'horiz' will be tet
-  //     <b, a, n[1], n[2]>; ELSE the edge <ba> is on boundary. 'bdrytet'
-  //     will be tet<a, b, n[j], n[j-1]>; (where 2 <= j <= i).
-  //   Note: the 'horiz' and 'bdrytet' has inversed fnext direction.
-  //
-  // For using the same process to cope with the diffrence between 'horiz'
-  //   and 'bdrytet', we adjust 'horiz' be tet<a, b, n[2], n[1]>. So they
-  //   have the same fnext direction.
-  if (hitbdry == 0) {
-    fnext(*horiz, spintet);
-    esymself(spintet);
-  } else {
-    spintet = bdrytet;
-  }
-
-  // Make lists of dividing(bot, oldtop) tetrahedra, Create new(newtop)
-  //   tetrahedra for each original tetrahedron.
-  bots = new triface[wrapcount];
-  oldtops = new triface[wrapcount];
-  topcasings = new triface[wrapcount];
-  newtops = new triface[wrapcount];
-
-  // Walk around the edge, gathering tetrahedra and setting up new tetra-
-  //   hedra. If 'hitbdry' != 0, start from 'bdrytet', otherwise, start
-  //   from 'horiz'. For convinence, we inverse the number sequence of the
-  //   apex of each wrapfaces in Owen's paper, and let the vertex sequence
-  //   be : 1, 2, ..., j-1, j. (where j = wrapcount.)
-  for (i = 0; i < wrapcount; i ++) {
-    fnextself(spintet);
-    // Set 'tmptet' be tet<b, a, n[j], n[j-1]>.
-    esym(spintet, tmptet);
-    // Set 'bots[i]' be tet<n[j], a, n[j-1], b>.
-    enextself(tmptet);
-    fnext(tmptet, bots[i]);
-    esymself(bots[i]);
-    // Set 'oldtops[i]' be tet<n[j], b, n[j-1], -a>.
-    enextself(tmptet);
-    fnext(tmptet, oldtops[i]);
-    // Set 'topcasing'.
-    sym(oldtops[i], topcasings[i]);
-    maketetrahedron(&(newtops[i]));
-  }
-
-  org (spintet, pa);
-  dest(spintet, pb);
-  // Set the vertices of changed and new tetrahedra.
-  for (i = 0; i < wrapcount; i ++) {
-    // 'bots[i]' is tet<n[j], a, n[j-1], b>.
-    org (bots[i], nj); //
-    apex(bots[i], nj_1);
-    // Set 'newtops[i]' be tet<b, n[j], n[j-1], v>.
-    setorg(newtops[i], pb);
-    setdest(newtops[i], nj);
-    setapex(newtops[i], nj_1);
-    setoppo(newtops[i], insertpoint);
-    // Set 'bots' be tet<n[j], a, n[j-1], v>.
-    setoppo(bots[i], insertpoint);
-    // Set the element attributes of a new tetrahedron.
-    for (k = 0; k < eextras; k++) {
-      setelemattribute(newtops[i].tet, k,
-                       elemattribute(bots[i].tet, k));
-    }
-    if (varvolume) {
-      // Set the area constraint of a new tetrahedron.
-      setvolumebound(newtops[i].tet, volumebound(bots[i].tet));
-    }
-  }
-
-  // There may be shell facets that need to be bonded to each new
-  //   tetrahedron's topcasing side.
-  if (checksegments) {
-    // Check topcasing shell at each newtops side.
-    for (i = 0; i < wrapcount; i ++) {
-      tspivot(oldtops[i], topshell);
-      if (topshell.sh != dummysh) {
-        tsdissolve(oldtops[i]);
-        tsbond(newtops[i], topshell);
-      }
-    }
-  }
-
-  // Bond newtops to topcasings and bots.
-  for (i = 0; i < wrapcount; i ++) {
-    // default: 'newtops[i]' loc = 0.
-    bond(newtops[i], topcasings[i]);
-    newtops[i].loc = 2;
-    bond(newtops[i], oldtops[i]);
-  }
-  // Bond between each newtops. Becareful the boundary case.
-  tmpbond0 = newtops[0];
-  for (i = 1; i <= wrapcount; i ++) {
-    if(i == wrapcount) {
-      if(hitbdry == 0) {
-        tmpbond1 = newtops[0];
-      } else {
-        break; // Insert on boundary edge case.
-      }
-    } else {
-      tmpbond1 = newtops[i];
-    }
-    tmpbond0.loc = 1;
-    tmpbond1.loc = 3;
-    bond(tmpbond0, tmpbond1);
-    tmpbond0 = tmpbond1;
-  }
-
-  for (i = 0; i < wrapcount; i ++) {
-    newtops[i].loc = 0;
-  }
-
-  // There may be shell facets that need to be bonded to each new
-  //   tetrahedron's sandwich side.
-  if (checksegments || (splitedge != (face*) NULL)) {
-    triface tmpbot, tmpnewtop;
-    face botsandwichsh, modibotleftsh, modibotrightsh;
-    face botleftshseg, botrightshseg;
-    face newtopsandwichsh;
-
-    for (i = 0; i < wrapcount; i ++) {
-      // Set 'tmpbot' be tet<a, n[j], v, n[j-1]>.
-      fnext(bots[i], tmpbot);
-      esymself(tmpbot);
-      tspivot(tmpbot, botsandwichsh);
-      if (botsandwichsh.sh != dummysh) {
-        findversion(&botsandwichsh, &tmpbot);
-        // Set 'botsandwichsh' be face<n[j], a, v>
-        setsapex(botsandwichsh, insertpoint);
-        // Set 'modibotleftsh' be face<v, n[j], a>
-        senext2(botsandwichsh, modibotleftsh);
-        // Set 'tmpnewtop' be tet<n[j], b, v, n[j-1]>.
-        fnext(newtops[i], tmpnewtop);
-        esymself(tmpnewtop);
-        // Insert a new shell facet at 'tmpnewtop'.
-        insertsubface(&tmpnewtop, mark(botsandwichsh), 0);
-        // Set 'newtopsandwichsh' be face<b, n[j], v>.
-        tspivot(tmpnewtop, newtopsandwichsh);
-        findversion(&newtopsandwichsh, &tmpnewtop);
-        // Check subsegment that need bond to 'botleftshseg'.
-        sspivot(modibotleftsh, botleftshseg);
-        if (botleftshseg.sh != dummysh) {
-          ssdissolve(modibotleftsh);
-          ssbond(newtopsandwichsh, botleftshseg);
-        }
-        // Here we can skip checking the right side's segment, because
-        //   if there exist a segment, it will be split later.
-        if (shflaws) {
-          // Now, the original 'botsandwichsh' was splitted to
-          //   'botsandwichsh' and 'newtopsandwichsh'.
-          // In quality mesh generation step, we need check if these two
-          //   subfaces being encroached. (Because they are Delaunay faces
-          //   and needn't do flip).
-          uncheckedshlist->append(&botsandwichsh);
-          uncheckedshlist->append(&newtopsandwichsh);
-        }
-      }
-    }
-    if (hitbdry != 0) {
-      // Additional shell facet at bots[0] other side need split.
-      // We recall: 'bots[0]' is tet<n[j], a, n[j-1], v>.
-      //         'newtops[0]' is tet<b, n[j], n[j-1], v>.
-      // Set 'tmpbot' be tet<n[j-1], pa, v, n[j]>.
-      tmpbot = bots[0];
-      enextfnextself(tmpbot);
-      esymself(tmpbot);
-      tspivot(tmpbot, botsandwichsh);
-      if (botsandwichsh.sh != dummysh) {
-        // Set 'botsandwichsh' be face<a, n[j-1], v>.
-        findversion(&botsandwichsh, &tmpbot);
-        setsapex(botsandwichsh, insertpoint);
-        // Set 'modibotrightsh' be face<n[j-1], v, a>.
-        senext(botsandwichsh, modibotrightsh);
-        // Set 'tmpnewtop' be tet<b, n[j-1], v, n[j]>.
-        tmpnewtop = newtops[0];
-        enext2fnextself(tmpnewtop);
-        esymself(tmpnewtop);
-        // Insert a new shell facet at 'tmpnewtop'.
-        insertsubface(&tmpnewtop, mark(botsandwichsh), 0);
-        // Set 'newtopsandwichsh' be face<n[j-1], b, v>.
-        tspivot(tmpnewtop, newtopsandwichsh);
-        findversion(&newtopsandwichsh, &tmpnewtop);
-        // Check subsegment that need bond to 'botrightshseg'.
-        sspivot(modibotrightsh, botrightshseg);
-        if (botrightshseg.sh != dummysh) {
-          ssdissolve(modibotrightsh);
-          ssbond(newtopsandwichsh, botrightshseg);
-        }
-        // Here we can skip checking the left side's segment, because
-        //   if there exist a segment, it will be split later.
-        if (shflaws) {
-          uncheckedshlist->append(&botsandwichsh);
-          uncheckedshlist->append(&newtopsandwichsh);
-        }
-      }
-    }
-
-    if (splitedge != (face*) NULL) {
-      face newseg;
-      face tmpbond0;
-      // We need insert a new subsegments into current mesh.
-      // Set 'splitedge' be edge<ab>.
-      findversion(splitedge, pa, pb, 0);
-      // Set 'splitedge' be edge<av>.
-      setsdest(*splitedge, insertpoint);
-      // Insert a new subsegment <vb> at 'tmpnewtop'.
-      fnext(newtops[0], tmpnewtop);
-      enext2self(tmpnewtop);
-      insertsubsegment(&tmpnewtop, mark(*splitedge));
-      tsspivot(&tmpnewtop, &newseg);
-      findversion(&newseg, insertpoint, pb, 0);
-      // Bond these two edges. So it can be quickly found each other after
-      //   splitting this subsegment.
-      senext(*splitedge, tmpbond0);
-      senext2self(newseg);
-      sbond(tmpbond0, newseg);
-    }
-  }
-
-#ifdef SELF_CHECK
-  for (i = 0; i < wrapcount; i ++) {
-    if (!isaboveplane(&(bots[i]), insertpoint)) {
-      printf("Internal error in insertonedge():\n");
-      printf("  Clockwise tetra prior to point insertion (bots[%i]).\n", i);
-      internalerror();
-    }
-    if (!isaboveplane(&(newtops[i]), insertpoint)) {
-      printf("Internal error in insertonedge():\n");
-      printf("  Clockwise tetra after point insertion (bots[%i]).\n", i);
-      internalerror();
-    }
-  }
-#endif // defined SELF_CHECK
-  if (verbose > 2) {
-    for (i = 0; i < wrapcount; i ++) {
-      printf("    Updating bots[%i] ", i);
-      dump(&(bots[i]));
-      printf("    Creating newtops[%i] ", i);
-      dump(&(newtops[i]));
-    }
-  }
-
-  flipcount = 0;
-
-  if (usefliplist) {
-    for (i = 0; i < wrapcount; i ++) {
-      enqueuefliplist(bots[i]);
-      enqueuefliplist(newtops[i]);
-    }
-  } else {
-    for (i = 0; i < wrapcount; i ++) {
-      flipcount += flip(bots[i]);
-      flipcount += flip(newtops[i]);
-    }
-  }
-
-  if (isdead(horiz)) {
-    // We need return a live tet.
-    if (splitedge != (face*) NULL) {
-      sstpivot(splitedge, horiz); // *horiz = splitedge->sstpivot();
-    } else {
-      for (i = 0; i < wrapcount; i ++) {
-        if (!isdead(&(bots[i]))) {
-          *horiz = bots[i];
-          break;
-        }
-        if (!isdead(&(newtops[i]))) {
-          *horiz = newtops[i];
-          break;
-        }
-      }
-      // assert(i < wrapcount);
-      if (!(i < wrapcount)) {
-        if (verbose) {
-          printf("Warnning in insertonedge(): \n");
-          printf("  After %d flips, we can't return a live tet.\n", flipcount);
-        }
-      }
-    }
-  }
-
-  delete [] bots;
-  delete [] oldtops;
-  delete [] topcasings;
-  delete [] newtops;
-
-  return flipcount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertsubface()    Create a new shell facet and insert it between two     //
-//                    tetrahedra.                                            //
-//                                                                           //
-// The new shell facet is created at the face described by the handle 'tet'. //
-// Its vertices are properly initialized. The marker 'shellemark' is applied //
-// to the shell facet and, if appropriate, its vertices.                     //
-//                                                                           //
-// The 'autobondsegs' flag is used to indicate whether we need do a segment  //
-// searching for the newly inserted subface. Generally, in mesh refinement   //
-// stage, we always need searching segments for newly inserted subface, so   //
-// the (triface).tsspivot() primitive will work correctly and efficiently.   //
-// But when do a local transformation on a face or edge, the segments around //
-// the subface always can be found before do flipping. So there need not do  //
-// segments searching (set autobondsegs = 0).                                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::insertsubface(triface* tet, int shellemark, int autobondsegs)
-{
-  triface abcd, bace;
-  face newshell, bseg;
-  point3d pa, pb, pc;
-  int i;
-
-  abcd = *tet;
-  adjustedgering(abcd, CCW);
-  // Mark points if possible.
-  org (abcd, pa);
-  dest(abcd, pb);
-  apex(abcd, pc);
-  if (shellemark != NONSOLIDFLAG) {
-    if (pointmark(pa) == 0) {
-      setpointmark(pa, shellemark);
-    }
-    if (pointmark(pb) == 0) {
-      setpointmark(pb, shellemark);
-    }
-    if (pointmark(pc) == 0) {
-      setpointmark(pc, shellemark);
-    }
-  }
-
-  // Check if there's already exist a shell facet here.
-  tspivot(abcd, newshell);
-  if (newshell.sh == dummysh) {
-    // Make new shell facet and initialize its vertices.
-    makeshellface(&subfaces, &newshell);
-    setsorg (newshell, pb);
-    setsdest(newshell, pa);
-    setsapex(newshell, pc);
-    // Bond new shell facet to the two tetrahedra it is sandwiched
-    //   between.  Note that the facing tetrahedron 'oppotet' might be
-    //   equal to 'dummytet' (outer space), but the new shell facet is
-    //   bonded to it all the same.
-    tsbond(abcd, newshell);
-    sym(abcd, bace);
-    sesymself(newshell);
-    tsbond(bace, newshell);
-    if (autobondsegs) {
-      // Check if there exist subsegments at three edge of this new
-      //   subface. If so, set corresponding pointers in 'newshell' to
-      //   link these subsegments.
-      // Now 'abcd' and 'newshell' both locked at edge 'ab'.
-      for (i = 0; i < 3; i ++) {
-        enextself(abcd);
-        senextself(newshell);
-        tsspivot(&abcd, &bseg); // bseg = abcd.sspivot();
-        if (bseg.sh != dummysh) {
-          ssbond(newshell, bseg);
-        }
-      }
-    }
-    setmark(newshell, shellemark);
-    if (verbose > 2) {
-      printf("    Inserting new: ");
-      dump(&newshell);
-    }
-  } else {
-    // The exist shellface may be nonsolid(<0) or not have a marker(0), now
-    //   we can make it solid or set new shell's mark.
-    if (shellemark != NONSOLIDFLAG) {
-      if (isnonsolid(newshell) || (mark(newshell) == 0)) {
-        setmark(newshell, shellemark);
-      }
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertsubsegment()    Create a new subsegment and connect it to surround- //
-//                       ing subface.                                        //
-//                                                                           //
-// The new subsegment is created at the face described by the handle 'tet'.  //
-// Its vertices are properly initialized. The marker 'shellemark' is applied //
-// to the shell facet and, if appropriate, its vertices.                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::insertsubsegment(triface* tet, int shellemark)
-{
-  triface abcd, spintet;
-  face newseg, parentshell;
-  point3d pa, pb;
-  point3d tapex;
-  int hitbdry, subfacecount;
-
-  abcd = *tet;
-  adjustedgering(abcd, CCW);
-  org(abcd, pa);
-  dest(abcd, pb);
-  // Mark points if possible.
-  if (shellemark != NONSOLIDFLAG) {
-    if (pointmark(pa) == 0) {
-      setpointmark(pa, shellemark);
-    }
-    if (pointmark(pb) == 0) {
-      setpointmark(pb, shellemark);
-    }
-  }
-  // Check if there's already exist a subsegment at this face's side.
-  tsspivot(&abcd, &newseg); // newseg = abcd.sspivot();
-  if (newseg.sh == dummysh) {
-    // Make new subsegment and initialize its vertices.
-    makeshellface(&subsegs, &newseg);
-    setsorg(newseg, pb);
-    setsdest(newseg, pa);
-    setmark(newseg, shellemark);
-    // To insert this subsegment, spin around this edge, to find all surro-
-    //   unding subface and set connection between them. If there isn't
-    //   exist such subface, we need create a nonsolid subface, and insert
-    //   it to mesh for insert this subsegment.
-    spintet = abcd;
-    apex(abcd, tapex);
-    subfacecount = 0;
-    hitbdry = 0;
-    tspivot(spintet, parentshell);
-    if (parentshell.sh != dummysh) {
-      findversion(&parentshell, &spintet);
-      ssbond(parentshell, newseg);
-      subfacecount++;
-    }
-    while (true) {
-      if (fnextself(spintet)) {
-        if (apex(spintet) == tapex) {
-          break;  // Rewind, can leave now.
-        }
-        tspivot(spintet, parentshell);
-        if (parentshell.sh != dummysh) {
-          findversion(&parentshell, &spintet);
-          ssbond(parentshell, newseg);
-          subfacecount++;
-        }
-      } else {
-        hitbdry ++;
-        if(hitbdry >= 2) {
-          break;
-        } else {
-          esym(abcd, spintet);
-        }
-      }
-    }
-    if (subfacecount == 0) {
-      // Insert a new shell facet for holding the new subsegment.
-      if (verbose > 2) {
-        printf("    Inserting a nonsolid subface for holding subsegment.\n");
-      }
-      insertsubface(&abcd, NONSOLIDFLAG, 1);
-      tspivot(abcd, parentshell);
-      findversion(&parentshell, &abcd);
-      ssbond(parentshell, newseg);
-    }
-    if (verbose > 2) {
-      printf("    Inserting new: ");
-      dump(&newseg);
-    }
-  } else {
-    if (mark(newseg) == 0) {
-      setmark(newseg, shellemark);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// deletesite()    Delete a vertex from a Delaunay triangulation, ensuring   //
-//                 that the triangulation remains Delaunay.                  //
-//                                                                           //
-// The origin of `deltet' is deleted. Only interior points that do not lie   //
-// on segments (shell edges) or boundaries may be deleted.                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::deletesite(triface *deltet)
-{
-  list *incitetlist, *incishlist;
-  list *equatorpointlist, *equatoredgelist;
-  list *northpointlist, *sourthpointlist;
-  list *equatorcasinglist;
-  list *northcasinglist, *sourthcasinglist;
-  list *northbacktracelist, *sourthbacktracelist;
-  triface *giftfaces;
-  triface *incitet, testtet, neighbortet;
-  face *incish,  testsh, testseg;
-  point3d *giftpoints;
-  point3d delorg, deldest, delapex;
-  point3d torg, tdest, tapex;
-  point3d tnorth;
-  triangulateio in, out;
-  REAL norm[3], xaxi[3], yaxi[3];
-  REAL v0[3], v1[3], dsin;
-  REAL *northattribs, *sourthattribs;
-  REAL northvolume, sourthvolume;
-  int *equatoredge, shellmark, add2north;
-  int bdrycount, bdry2count;
-  int orgori, destori, apexori;
-  int numberofgiftfaces, numberofgiftpoints;
-  int success;
-  int i, j, index;
-
-  testtet = *deltet;
-  delorg = org(testtet);
-  adjustedgering(testtet, CCW);
-  findorg(&testtet, delorg);
-
-  if (verbose > 1) {
-    printf("  Delete point from mesh: (%.12g, %.12g, %.12g) %d\n",
-           delorg[0], delorg[1], delorg[2], pointmark(delorg));
-  }
-
-  // Get all tetrahedra and subfaces which incidents to the delete point.
-  incitetlist = new list(sizeof(triface));
-  incishlist = new list(sizeof(face));
-  incitetlist->setcomp((compfunc) &compare2tets);
-  incishlist->setcomp((compfunc) &compare2shfaces);
-  bdrycount = bdry2count = 0;
-
-  if (verbose > 2) {
-    printf("    Queuing incident tet (%d, %d, %d, %d).\n",
-           pointmark(org(testtet)), pointmark(dest(testtet)),
-           pointmark(apex(testtet)), pointmark(oppo(testtet)));
-  }
-  incitetlist->append(&testtet);
-  symself(testtet);
-  if (testtet.tet != dummytet) {
-    adjustedgering(testtet, CCW);
-    findorg(&testtet, delorg);
-    if (verbose > 2) {
-      printf("    Queuing incident tet (%d, %d, %d, %d).\n",
-             pointmark(org(testtet)), pointmark(dest(testtet)),
-             pointmark(apex(testtet)), pointmark(oppo(testtet)));
-    }
-    incitetlist->append(&testtet);
-    tspivot(testtet, testsh);
-    if (testsh.sh != dummysh) {
-      if (!isnonsolid(testsh)) {
-        bdry2count++;
-        findorg(&testsh, delorg);
-        if (verbose > 2) {
-           printf("    Queuing incident face (%d, %d, %d) (inner).\n",
-                  pointmark(sorg(testsh)), pointmark(sdest(testsh)),
-                  pointmark(sapex(testsh)));
-        }
-        incishlist->append(&testsh);
-      }
-    }
-  } else {
-    tspivot(*deltet, testsh);
-    assert(testsh.sh != dummysh);
-    assert(!isnonsolid(testsh));
-    bdrycount++;
-    findorg(&testsh, delorg);
-    if (verbose > 2) {
-      printf("    Queuing incident boundary face (%d, %d, %d).\n",
-             pointmark(sorg(testsh)), pointmark(sdest(testsh)),
-             pointmark(sapex(testsh)));
-    }
-    incishlist->append(&testsh);
-  }
-  // Keep adding tets and subfaces incident on delpoint until they're
-  //   all there.
-  for (i = 0; i < incitetlist->len(); i++) {
-    incitet = (triface *)(* incitetlist)[i];
-    for (j = 0; j < 2; j++) {
-      testtet = *incitet;
-      if (j == 1) {
-        enext2self(testtet);
-      }
-      fnextself(testtet);
-      if (issymexist(&testtet)) {
-        symself(testtet);
-        if (incitetlist->hasitem(&testtet) == -1) {
-          // This tet need add to queue.
-          adjustedgering(testtet, CCW);
-          findorg(&testtet, delorg);
-          if (verbose > 2) {
-            printf("    Queuing incident tet (%d, %d, %d, %d).\n",
-                   pointmark(org(testtet)), pointmark(dest(testtet)),
-                   pointmark(apex(testtet)), pointmark(oppo(testtet)));
-          }
-          incitetlist->append(&testtet);
-          tspivot(testtet, testsh);
-          if (testsh.sh != dummysh) {
-            if (!isnonsolid(testsh)) {
-              bdry2count++;
-              findorg(&testsh, delorg);
-              if (verbose > 2) {
-                printf("    Queuing incident face (%d, %d, %d) (inner).\n",
-                       pointmark(sorg(testsh)), pointmark(sdest(testsh)),
-                       pointmark(sapex(testsh)));
-              }
-              incishlist->append(&testsh);
-            }
-          }
-        } else {
-          // This tet has been added to queue, we still need check if there
-          //   exist inner shell face at two side of this tet.
-          tspivot(testtet, testsh);
-          if (testsh.sh != dummysh) {
-            if (!isnonsolid(testsh)) {
-              if (incishlist->hasitem(&testsh) == -1) {
-                bdry2count++;
-                findorg(&testsh, delorg);
-                if (verbose > 2) {
-                  printf("    Queuing incident face (%d, %d, %d) (inner).\n",
-                         pointmark(sorg(testsh)), pointmark(sdest(testsh)),
-                         pointmark(sapex(testsh)));
-                }
-                incishlist->append(&testsh);
-              }
-            }
-          }
-        }
-      } else {
-        tspivot(testtet, testsh);
-        assert(testsh.sh != dummysh);
-        assert(!isnonsolid(testsh));
-        bdrycount++;
-        findorg(&testsh, delorg);
-        if (verbose > 2) {
-          printf("    Queuing incident boundary face (%d, %d, %d).\n",
-                 pointmark(sorg(testsh)), pointmark(sdest(testsh)),
-                 pointmark(sapex(testsh)));
-        }
-        incishlist->append(&testsh);
-      }
-    }
-  }
-
-  if (((bdry2count > 0) && (bdrycount > 0)) ||
-      ((bdry2count == 1) || (bdrycount == 1))) {
-    if (!quiet) {
-      printf("Warnning: ");
-      if ((bdry2count > 0) && (bdrycount > 0)) {
-        printf("Try to delete a point which seems locating on the");
-        printf(" intersection of two incident facets.\n");
-      } else {
-        printf("Try to delete a point which is an apex on boundary.\n");
-      }
-    }
-    delete incitetlist;
-    delete incishlist;
-    return 0;
-  }
-
-  if ((bdry2count > 0) || (bdrycount > 0)) {
-    if (verbose > 2) {
-      printf("    Generating a triangulation for coplanar subfaces.\n");
-    }
-    equatorpointlist = new list("point");
-    equatoredgelist = new list(sizeof(int) * 2);
-
-    testsh = *(face *)(* incishlist)[0];
-    assert(delorg == sorg(testsh));
-    deldest = sdest(testsh);
-    delapex = sapex(testsh);
-    equatorpointlist->append(&deldest);
-    equatorpointlist->append(&delapex);
-    equatoredge = (int*) equatoredgelist->alloc();
-    equatoredge[0] = 0;
-    equatoredge[1] = 1;
-    for (i = 1; i < incishlist->len(); i++) {
-      incish = (face *)(* incishlist)[i];
-      assert(delorg == sorg(*incish));
-      tdest = sdest(*incish);
-      tapex = sapex(*incish);
-#ifdef SELF_CHECK
-      if ((!iscoplane(delorg, deldest, delapex, tdest)) ||
-          (!iscoplane(delorg, deldest, delapex, tapex))) {
-        printf("Internal Error in deletesite(): Try to delete a point");
-        printf(" which is an apex on the boundary.\n");
-        internalerror();
-      }
-#endif // defined SELF_CHECK
-      equatoredge = (int*) equatoredgelist->alloc();
-      equatoredge[0] = equatorpointlist->hasitem(&tdest);
-      if (equatoredge[0] == -1) {
-        equatorpointlist->append(&tdest);
-        equatoredge[0] = equatorpointlist->len() - 1;
-      }
-      equatoredge[1] = equatorpointlist->hasitem(&tapex);
-      if (equatoredge[1] == -1) {
-        equatorpointlist->append(&tapex);
-        equatoredge[1] = equatorpointlist->len() - 1;
-      }
-    }
-    assert(equatorpointlist->len() > 0);
-    assert(equatoredgelist->len() > 0);
-    if (verbose > 2) {
-      printf("    There are %d points and %d segments at equator.\n",
-             equatorpointlist->len(), equatoredgelist->len());
-    }
-
-    triangulateioinit(&in);
-    triangulateioinit(&out);
-    in.numberofpoints = equatorpointlist->len();
-    in.pointlist = new REAL[in.numberofpoints * 2];
-    in.numberofsegments = equatoredgelist->len();
-    in.segmentlist = new int[in.numberofsegments * 2];
-    index = 0;
-    for (i = 0; i < in.numberofsegments; i ++) {
-      equatoredge = (int*) (*equatoredgelist)[i];
-      in.segmentlist[index++] = equatoredge[0];
-      in.segmentlist[index++] = equatoredge[1];
-    }
-    // Determine normal, verify closed polygon.
-    tdest = *(point3d*)(*equatorpointlist)[in.segmentlist[0]];
-    tapex = *(point3d*)(*equatorpointlist)[in.segmentlist[1]];
-    Sub3D(tapex, tdest, v0);
-    Normalize3D(v0);
-    index = 2;
-    dsin = 0;
-    for (i = 1; iszero(dsin); i++) {
-      tdest = *(point3d*)(*equatorpointlist)[in.segmentlist[index++]];
-      tapex = *(point3d*)(*equatorpointlist)[in.segmentlist[index++]];
-      Sub3D(tapex, tdest, v1);
-      Normalize3D(v1);
-      Cross3D(v0, v1, norm);
-      dsin = Mag3D(norm);
-      if (!iszero(dsin)) Scale3D(norm, 1./dsin);
-      if (i >= in.numberofsegments) {
-        printf("Internal Error in deletesite(): Can't find a normal.\n");
-        internalerror();
-      }
-    }
-    // Project onto a plane
-    Assign3D(v1, xaxi);
-    Cross3D(norm, xaxi, yaxi);
-    index = 0;
-    for (i = 0; i < in.numberofpoints; i ++) {
-      tdest = *(point*)(*equatorpointlist)[i];
-      in.pointlist[index++] = Dot3D(tdest, xaxi);
-      in.pointlist[index++] = Dot3D(tdest, yaxi);
-    }
-    // Now create the 2D mesh.
-    surfmesh->triangulate(&in, &out, NULL);
-    if (surfmesh->triangles.items <= 0) {
-      printf("Internal Error in deletesite(): Can't form a surface");
-      printf(" triangulation.\n");
-      internalerror();
-    }
-    if (verbose > 2) {
-      printf("    Triangulation result: %d triangles.\n",
-             surfmesh->triangles.items);
-    }
-    surfmesh->trianglerestart();
-  }
-
-  if (verbose > 2) {
-    printf("    Identify the casing faces at north");
-  }
-  northpointlist = new list("point");
-  northcasinglist = new list(sizeof(triface));
-  if (bdry2count > 0) {
-    if (verbose > 2) {
-      printf(" and sourth.\n");
-    }
-    sourthpointlist = new list("point");
-    sourthcasinglist = new list(sizeof(triface));
-    for (i = 0; i < incitetlist->len(); i++) {
-      testtet = *(triface *)(* incitetlist)[i];
-      enextfnextself(testtet);
-      tspivot(testtet, testsh);
-      torg = org(testtet);
-      tdest = dest(testtet);
-      tapex = apex(testtet);
-      orgori = iorient3d(delorg, deldest, delapex, torg);
-      destori = iorient3d(delorg, deldest, delapex, tdest);
-      apexori = iorient3d(delorg, deldest, delapex, tapex);
-      add2north = 1;
-      if (orgori != 0) {
-        if (orgori < 0) {
-          if (northpointlist->hasitem(&torg) == -1) {
-            northpointlist->append(&torg);
-          }
-        } else {
-          if (sourthpointlist->hasitem(&torg) == -1) {
-            sourthpointlist->append(&torg);
-          }
-          add2north = 0;
-        }
-      }
-      if (destori != 0) {
-        if (destori < 0) {
-          if (northpointlist->hasitem(&tdest) == -1) {
-            northpointlist->append(&tdest);
-          }
-        } else {
-          if (sourthpointlist->hasitem(&tdest) == -1) {
-            sourthpointlist->append(&tdest);
-          }
-          add2north = 0;
-        }
-      }
-      if (apexori != 0) {
-        if (apexori < 0) {
-          if (northpointlist->hasitem(&tapex) == -1) {
-            northpointlist->append(&tapex);
-          }
-        } else {
-          if (sourthpointlist->hasitem(&tapex) == -1) {
-            sourthpointlist->append(&tapex);
-          }
-          add2north = 0;
-        }
-      }
-      symself(testtet);
-      if (testtet.tet == dummytet) {
-        assert (testsh.sh != dummysh);
-        maketetrahedron(&testtet);
-        setorg(testtet, torg);
-        setdest(testtet, tdest);
-        setapex(testtet, tapex);
-        sesymself(testsh);
-        tsbond(testtet, testsh);
-        if (verbose > 2) {
-          printf("    Creating a fake tet for holding face(%d, %d, %d).\n",
-                 pointmark(torg), pointmark(tdest), pointmark(tapex));
-        }
-      }
-      adjustedgering(testtet, CCW);
-      if (add2north) {
-        if (verbose > 2) {
-          printf("    Queuing northcasing face (%d, %d, %d).\n",
-                 pointmark(org(testtet)), pointmark(dest(testtet)),
-                 pointmark(apex(testtet)));
-        }
-        northcasinglist->append(&testtet);
-      } else {
-        if (verbose > 2) {
-          printf("    Queuing sourthcasing face (%d, %d, %d).\n",
-                 pointmark(org(testtet)), pointmark(dest(testtet)),
-                 pointmark(apex(testtet)));
-        }
-        sourthcasinglist->append(&testtet);
-      }
-    }
-    assert(sourthcasinglist->len() > 0);
-    if (verbose > 2) {
-      printf("    There are %d points at sourth.\n", sourthpointlist->len());
-    }
-  } else {
-    if (verbose > 2) {
-      printf(".\n");
-    }
-    for (i = 0; i < incitetlist->len(); i++) {
-      testtet = *(triface *)(* incitetlist)[i];
-      enextfnextself(testtet);
-      tspivot(testtet, testsh);
-      torg = org(testtet);
-      tdest = dest(testtet);
-      tapex = apex(testtet);
-      if (bdrycount > 0) {
-        if (equatorpointlist->hasitem(&torg) == -1) {
-          if (northpointlist->hasitem(&torg) == -1) {
-            northpointlist->append(&torg);
-          }
-        }
-        if (equatorpointlist->hasitem(&tdest) == -1) {
-          if (northpointlist->hasitem(&tdest) == -1) {
-            northpointlist->append(&tdest);
-          }
-        }
-        if (equatorpointlist->hasitem(&tapex) == -1) {
-          if (northpointlist->hasitem(&tapex) == -1) {
-            northpointlist->append(&tapex);
-          }
-        }
-      } else {
-        if (northpointlist->hasitem(&torg) == -1) {
-          northpointlist->append(&torg);
-        }
-        if (northpointlist->hasitem(&tdest) == -1) {
-          northpointlist->append(&tdest);
-        }
-        if (northpointlist->hasitem(&tapex) == -1) {
-          northpointlist->append(&tapex);
-        }
-      }
-      symself(testtet);
-      if (testtet.tet == dummytet) {
-        assert (testsh.sh != dummysh);
-        maketetrahedron(&testtet);
-        setorg(testtet, torg);
-        setdest(testtet, tdest);
-        setapex(testtet, tapex);
-        sesymself(testsh);
-        tsbond(testtet, testsh);
-        if (verbose > 2) {
-          printf("    Creating a fake tet for holding face(%d, %d, %d).\n",
-                 pointmark(torg), pointmark(tdest), pointmark(tapex));
-        }
-      }
-      adjustedgering(testtet, CCW);
-      if (verbose > 2) {
-        printf("    Queuing northcasing face (%d, %d, %d).\n",
-               pointmark(org(testtet)), pointmark(dest(testtet)),
-               pointmark(apex(testtet)));
-      }
-      northcasinglist->append(&testtet);
-    }
-  }
-  assert(northcasinglist->len() > 0);
-  if (verbose > 2) {
-    printf("    There are %d points at north.\n", northpointlist->len());
-  }
-
-  if (verbose > 2) {
-    printf("    Protecting subsegments process.\n");
-  }
-  for (i = 0; i < northcasinglist->len(); i++) {
-    testtet = *(triface*)(*northcasinglist)[i];
-    tspivot(testtet, testsh);
-    if (testsh.sh == dummysh) {
-      for (j = 0; j < 3; j++) {
-        tsspivot(&testtet, &testseg);
-        if (testseg.sh != dummysh) {
-          if (verbose > 2) {
-            printf("    Segment (%d, %d) needs protect.\n",
-                   pointmark(sorg(testseg)), pointmark(sdest(testseg)));
-          }
-          insertsubface(&testtet, NONSOLIDFLAG, 1);
-          break;
-        }
-        enextself(testtet);
-      }
-    } else {
-      // Bond all segments to this subface to ensure
-      //   the subsegment-subface bond.
-      for (j = 0; j < 3; j++) {
-        sspivot(testsh, testseg);
-        if (testseg.sh != dummysh) {
-          ssbond(testsh, testseg);
-        }
-        senextself(testsh);
-      }
-    }
-  }
-  if (bdry2count > 0) {
-    for (i = 0; i < sourthcasinglist->len(); i++) {
-      testtet = *(triface*)(*sourthcasinglist)[i];
-      tspivot(testtet, testsh);
-      if (testsh.sh == dummysh) {
-        for (j = 0; j < 3; j++) {
-          tsspivot(&testtet, &testseg);
-          if (testseg.sh != dummysh) {
-            if (verbose > 2) {
-              printf("    Segment (%d, %d) needs protect.\n",
-                     pointmark(sorg(testseg)), pointmark(sdest(testseg)));
-            }
-            insertsubface(&testtet, NONSOLIDFLAG, 1);
-            break;
-          }
-          enextself(testtet);
-        }
-      } else {
-        // Bond all segments of to this subface to ensure
-        //   the subsegment-subface bond.
-        for (j = 0; j < 3; j++) {
-          sspivot(testsh, testseg);
-          if (testseg.sh != dummysh) {
-            ssbond(testsh, testseg);
-          }
-          senextself(testsh);
-        }
-      }
-    }
-  }
-
-  // Keep shellmark for subfaces.
-  if ((bdrycount > 0) || (bdry2count > 0)) {
-    incish = (face*)(*incishlist)[0];
-    shellmark = mark(*incish);
-#ifdef SELF_CHECK
-    for (i = 1; i < incishlist->len(); i++) {
-      incish = (face*)(*incishlist)[i];
-      if (shellmark != mark(*incish)) {
-        printf("Internal error in deletesite(): \n");
-        printf("  Try to delete a point which seems on a subsegment.\n");
-        internalerror();
-      }
-    }
-#endif // defined SELF_CHECK
-  }
-
-  // Keep attribs and varvolume for new tets.
-  if (eextras || varvolume) {
-    if (eextras > 0) {
-      northattribs = new REAL[eextras];
-      if (bdry2count > 0) {
-        sourthattribs = new REAL[eextras];
-      }
-    }
-    if (bdry2count > 0) {
-      // Find a incident tet which belong to sourth side.
-      incish = (face*)(*incishlist)[0];
-      // This is sourth side. (Above we use the first shell face as horiz).
-      stpivot(*incish, testtet);
-#ifdef SELF_CHECK
-      assert(isbelowplane(delorg, deldest, delapex, oppo(testtet)));
-#endif // defined SELF_CHECK
-      for (i = 0; i < eextras; i++) {
-        sourthattribs[i] = elemattribute(testtet.tet, i);
-      }
-      if (varvolume) {
-        sourthvolume = volumebound(testtet.tet);
-      }
-      // Set north side.
-      symself(testtet);
-      assert(testtet.tet != dummytet);
-      for (i = 0; i < eextras; i++) {
-        northattribs[i] = elemattribute(testtet.tet, i);
-      }
-      if (varvolume) {
-        northvolume = volumebound(testtet.tet);
-      }
-    } else {
-      incitet = (triface*)(*incitetlist)[0];
-      // There only north side.
-      for (i = 0; i < eextras; i++) {
-        northattribs[i] = elemattribute(incitet->tet, i);
-      }
-      if (varvolume) {
-        northvolume = volumebound(incitet->tet);
-      }
-    }
-  } else {
-    northattribs = sourthattribs = NULL;
-    northvolume = sourthvolume = 0;
-  }
-
-  if ((bdrycount > 0) || (bdry2count > 0)) {
-    if (verbose > 2) {
-      printf("    Creating casing faces for holding subfaces on equator.\n");
-    }
-    equatorcasinglist = new list(sizeof(triface));
-    tnorth = *(point3d*)(*northpointlist)[0];
-    for (i = 0; i < out.numberoftriangles; i++) {
-      index = i * 3;
-      orgori = out.trianglelist[index++];
-      destori = out.trianglelist[index++];
-      apexori = out.trianglelist[index++];
-      torg = *(point3d*)(*equatorpointlist)[orgori];
-      tdest = *(point3d*)(*equatorpointlist)[destori];
-      tapex = *(point3d*)(*equatorpointlist)[apexori];
-      maketetrahedron(&testtet);
-      makeshellface(&subfaces, &testsh);
-      setmark(testsh, shellmark);
-      add2north = iorient3d(torg, tdest, tapex, tnorth);
-      assert(add2north != 0);
-      if (add2north < 0) {
-        setorg(testtet, tdest);
-        setdest(testtet, torg);
-        setsorg(testsh, torg);
-        setsdest(testsh, tdest);
-      } else {
-        setorg(testtet, torg);
-        setdest(testtet, tdest);
-        setsorg(testsh, tdest);
-        setsdest(testsh, torg);
-      }
-      setapex(testtet, tapex);
-      setsapex(testsh, tapex);
-      tsbond(testtet, testsh);
-      if (verbose > 2) {
-        printf("    Creating and queuing equator casing face (%d, %d, %d).\n",
-               pointmark(org(testtet)), pointmark(dest(testtet)),
-               pointmark(apex(testtet)));
-        printf("    Creating and bonding equator subface (%d, %d, %d).\n",
-               pointmark(sorg(testsh)), pointmark(sdest(testsh)),
-               pointmark(sapex(testsh)));
-      }
-      equatorcasinglist->append(&testtet);
-    }
-    assert(equatorcasinglist->len() > 0);
-  }
-
-  if ((bdrycount > 0) || (bdry2count > 0)) {
-    numberofgiftfaces = equatorcasinglist->len() + northcasinglist->len();
-    numberofgiftpoints = equatorpointlist->len() + northpointlist->len();
-  } else {
-    numberofgiftfaces = northcasinglist->len();
-    numberofgiftpoints = northpointlist->len();
-  }
-  giftfaces = new triface[numberofgiftfaces];
-  giftpoints = new point3d[numberofgiftpoints];
-  // Create a backtrace list to keep all new tets be created during
-  //   gift-wrapping stage, so we can delete them if gift-wrapping failed.
-  northbacktracelist = new list(sizeof(triface));
-
-  if ((bdrycount > 0) || (bdry2count > 0)) {
-    //   Generate giftfaces.
-    for (i = 0; i < equatorcasinglist->len(); i++) {
-      giftfaces[i] = *(triface*)(*equatorcasinglist)[i];
-    }
-    for (j = i; j < numberofgiftfaces; j++) {
-      giftfaces[j] = *(triface*)(*northcasinglist)[j - i];
-    }
-    //   Generate giftpoints.
-    for (i = 0; i < equatorpointlist->len(); i++) {
-      giftpoints[i] = *(point3d*)(*equatorpointlist)[i];
-    }
-    for (j = i; j < numberofgiftpoints; j++) {
-      giftpoints[j] = *(point3d*)(*northpointlist)[j - i];
-    }
-  } else {
-    //   Generate giftfaces.
-    for (i = 0; i < numberofgiftfaces; i++) {
-      giftfaces[i] = *(triface*)(*northcasinglist)[i];
-    }
-    //   Generate giftpoints.
-    for (i = 0; i < numberofgiftpoints; i++) {
-      giftpoints[i] = *(point3d*)(*northpointlist)[i];
-    }
-  }
-
-  success = giftwrapping(numberofgiftfaces, giftfaces, numberofgiftpoints,
-                         giftpoints, northattribs, northvolume,
-                         northbacktracelist);
-
-  if ((bdry2count > 0) && success) {
-    if (verbose > 2) {
-      printf("    Removing and replacing fake tets at equator with real tets.\n");
-    }
-    for (i = 0; i < equatorcasinglist->len(); i++) {
-      incitet = (triface*)(*equatorcasinglist)[i];
-      assert(oppo(*incitet) == (point3d) NULL);
-      sym(*incitet, testtet);
-      tspivot(*incitet, testsh);
-      dissolve(testtet);
-      stdissolve(testsh);
-      // Remove fake tet.
-      tetrahedrondealloc(incitet->tet);
-      // Replace fake tet with a real tet.
-      adjustedgering(testtet, CCW);
-      *incitet = testtet;
-      if (verbose > 2) {
-        printf("    Changing (%d, %d, %d).\n", pointmark(org(testtet)),
-               pointmark(dest(testtet)), pointmark(apex(testtet)));
-      }
-    }
-    delete [] giftfaces;
-    delete [] giftpoints;
-
-    numberofgiftfaces = equatorcasinglist->len() + sourthcasinglist->len();
-    numberofgiftpoints = equatorpointlist->len() + sourthpointlist->len();
-    giftfaces = new triface[numberofgiftfaces];
-    giftpoints = new point3d[numberofgiftpoints];
-    // Create a backtrace list to keep all new tets be created during
-    //   gift-wrapping stage, so we can delete them if gift-wrapping failed.
-    sourthbacktracelist = new list(sizeof(triface));
-
-    //   Generate giftfaces.
-    for (i = 0; i < equatorcasinglist->len(); i++) {
-      giftfaces[i] = *(triface*)(*equatorcasinglist)[i];
-    }
-    for (j = i; j < numberofgiftfaces; j++) {
-      giftfaces[j] = *(triface*)(*sourthcasinglist)[j - i];
-    }
-    //   Generate giftpoints.
-    for (i = 0; i < equatorpointlist->len(); i++) {
-      giftpoints[i] = *(point3d*)(*equatorpointlist)[i];
-    }
-    for (j = i; j < numberofgiftpoints; j++) {
-      giftpoints[j] = *(point3d*)(*sourthpointlist)[j - i];
-    }
-
-    success = giftwrapping(numberofgiftfaces, giftfaces, numberofgiftpoints,
-                           giftpoints, sourthattribs, sourthvolume,
-                           sourthbacktracelist);
-    if (!success) {
-      if (verbose > 2) {
-        printf("    Badly, gift-wrapping failed, clear all new tets that");
-        printf(" created at sourthcasing.\n");
-      }
-      // Removing new subfaces at equators first. Because after new tets
-      //   being removed, subfaces will no holder.
-      for (i = 0; i < equatorcasinglist->len(); i++) {
-        testtet = *(triface*)(*equatorcasinglist)[i];
-        tspivot(testtet, testsh);
-        assert(testsh.sh != dummysh);
-        shellfacedealloc(&subfaces, testsh.sh);
-      }
-      // Clear equatorcasinglist to avoid deallocate subfaces twice.
-      equatorcasinglist->clear();
-      // Dealloc all new tets in which created during gift-wrapping.
-      for (i = 0; i < sourthbacktracelist->len(); i++) {
-        incitet = (triface*)(*sourthbacktracelist)[i];
-        if (verbose > 2) {
-          printf("    Deleting new tet (%d, %d, %d, %d).\n",
-                 pointmark(org(*incitet)), pointmark(dest(*incitet)),
-                 pointmark(apex(*incitet)), pointmark(oppo(*incitet)));
-        }
-        tetrahedrondealloc(incitet->tet);
-      }
-    }
-  }
-
-  if (!success) {
-    if (verbose > 2) {
-      printf("    Badly, gift-wrapping failed, clear all new tets that");
-      printf(" created during gift-wrapping.\n");
-    }
-    if ((bdrycount > 0) || (bdry2count > 0)) {
-      // Removing new subfaces at equators.
-      for (i = 0; i < equatorcasinglist->len(); i++) {
-        testtet = *(triface*)(*equatorcasinglist)[i];
-        tspivot(testtet, testsh);
-        assert(testsh.sh != dummysh);
-        shellfacedealloc(&subfaces, testsh.sh);
-        // It's a equator casing fake tet, delete it.
-        tetrahedrondealloc(testtet.tet);
-      }
-      equatorcasinglist->clear();
-    }
-    for (i = 0; i < northbacktracelist->len(); i++) {
-      incitet = (triface*)(*northbacktracelist)[i];
-      if (verbose > 2) {
-        printf("    Deleting new tet (%d, %d, %d, %d).\n",
-               pointmark(org(*incitet)), pointmark(dest(*incitet)),
-               pointmark(apex(*incitet)), pointmark(oppo(*incitet)));
-      }
-      tetrahedrondealloc(incitet->tet);
-    }
-  }
-
-  if (success) {
-    if (verbose > 2) {
-      printf("    Deleting all incident tets and incident faces.\n");
-    }
-    for (i = 0; i < incitetlist->len(); i++) {
-      incitet = (triface*)(*incitetlist)[i];
-      if (verbose > 2) {
-        printf("    Deleting tet (%d, %d, %d, %d).\n",
-               pointmark(org(*incitet)), pointmark(dest(*incitet)),
-               pointmark(apex(*incitet)), pointmark(oppo(*incitet)));
-      }
-      tspivot(*incitet, testsh);
-      if (testsh.sh != dummysh) {
-        if (verbose > 2) {
-          printf("    Deleting subface (%d, %d, %d).\n",
-                 pointmark(sorg(testsh)), pointmark(sdest(testsh)),
-                 pointmark(sapex(testsh)));
-        }
-        sym(*incitet, neighbortet);
-        tsdissolve(neighbortet);
-        shellfacedealloc(&subfaces, testsh.sh);
-      }
-      fnext(*incitet, testtet);
-      tspivot(testtet, testsh);
-      if (testsh.sh != dummysh) {
-        if (verbose > 2) {
-          printf("    Deleting subface (%d, %d, %d).\n",
-                 pointmark(sorg(testsh)), pointmark(sdest(testsh)),
-                 pointmark(sapex(testsh)));
-        }
-        sym(testtet, neighbortet);
-        tsdissolve(neighbortet);
-        shellfacedealloc(&subfaces, testsh.sh);
-      }
-      enext2(*incitet, testtet);
-      fnextself(testtet);
-      tspivot(testtet, testsh);
-      if (testsh.sh != dummysh) {
-        if (verbose > 2) {
-          printf("    Deleting subface (%d, %d, %d).\n",
-                 pointmark(sorg(testsh)), pointmark(sdest(testsh)),
-                 pointmark(sapex(testsh)));
-        }
-        sym(testtet, neighbortet);
-        tsdissolve(neighbortet);
-        shellfacedealloc(&subfaces, testsh.sh);
-      }
-      tetrahedrondealloc(incitet->tet);
-    }
-
-    // Now we can delete the point.
-    pointdealloc(delorg);
-    if (bdrycount > 0) {
-      // Deleting the boundary point decreases the number of boundary faces.
-      hullsize -= 2;
-    }
-  } else {
-    // Gift-wrapping failed, we need restore original configuration.
-    //   This time, all tets in 'incitetlist' are still keep the pointers
-    //   to its casing face, use this pointers to restore original config-
-    //   uration.
-    if (verbose > 2) {
-      printf("    Fail to delete point, restoring original configuration.\n");
-    }
-    for (i = 0; i < incitetlist->len(); i++) {
-      incitet = (triface*)(*incitetlist)[i];
-      enextfnextself(*incitet);
-      // Get and bond its casing face if its not a 'dummytet'.
-      sym(*incitet, testtet);
-      if (testtet.tet != dummytet) {
-        bond(*incitet, testtet);
-      }
-      // Get and bond the subface if its not a 'dummysh'.
-      tspivot(*incitet, testsh);
-      if (testsh.sh != dummysh) {
-        tsbond(*incitet, testsh);;
-      }
-    }
-  }
-
-  // Whatever success or not success, we must do the following step.
-  if (verbose > 2) {
-    printf("    Removing and replacing fake tets in north with dummytet.\n");
-  }
-  for (i = 0; i < northcasinglist->len(); i++) {
-    testtet = *(triface*)(*northcasinglist)[i];
-    if (oppo(testtet) == (point3d) NULL) {
-      if (verbose > 2) {
-        printf("    Changing (%d, %d, %d).\n", pointmark(org(testtet)),
-               pointmark(dest(testtet)), pointmark(apex(testtet)));
-      }
-      if (success) {
-        // Here do dissolve only success == 1.
-        sym(testtet, neighbortet);
-        dissolve(neighbortet);
-      }
-      tspivot(testtet, testsh);
-      if (testsh.sh != dummysh) {
-        stdissolve(testsh);
-      }
-      tetrahedrondealloc(testtet.tet);
-      testtet = neighbortet;
-      if (shflaws && success) {
-        uncheckedshlist->append(&testsh);
-      }
-    }
-    // Ensure adjoining tets quality at casing face.
-    if (tetflaws && success) {
-      uncheckedtetlist->append(&testtet);
-      sym(testtet, neighbortet);
-      if (neighbortet.tet != dummytet) {
-        uncheckedtetlist->append(&neighbortet);
-      }
-    }
-  }
-
-  if (bdry2count > 0) {
-    if (verbose > 2) {
-      printf("    Removing and replacing fake tets in sourth with dummytet.\n");
-    }
-    for (i = 0; i < sourthcasinglist->len(); i++) {
-      testtet = *(triface*)(*sourthcasinglist)[i];
-      if (oppo(testtet) == (point3d) NULL) {
-        // This is a fake tet, delete it and set it be 'dummytet'.
-        if (verbose > 2) {
-          printf("    Changing (%d, %d, %d).\n",
-                 pointmark(org(testtet)), pointmark(dest(testtet)),
-                 pointmark(apex(testtet)));
-        }
-        if (success) {
-          // Here do dissolve only success == 1.
-          sym(testtet, neighbortet);
-          dissolve(neighbortet);
-        }
-        tspivot(testtet, testsh);
-        if (testsh.sh != dummysh) {
-          stdissolve(testsh);
-        }
-        tetrahedrondealloc(testtet.tet);
-        testtet = neighbortet;
-        if (shflaws && success) {
-          uncheckedshlist->append(&testsh);
-        }
-      }
-      // Ensure adjoining tets quality at casing face.
-      if (tetflaws && success) {
-        uncheckedtetlist->append(&testtet);
-        sym(testtet, neighbortet);
-        if (neighbortet.tet != dummytet) {
-          uncheckedtetlist->append(&neighbortet);
-        }
-      }
-    }
-  }
-
-  if ((bdrycount > 0) || (bdry2count > 0)) {
-    if (verbose > 2) {
-      printf("    Bonding subsegments to equator subfaces.\n");
-    }
-    for (i = 0; i < equatorcasinglist->len(); i++) {
-      testtet = *(triface*)(*equatorcasinglist)[i];
-      tspivot(testtet, testsh);
-      // For keep the same enext() direction.
-      findversion(&testsh, org(testtet), dest(testtet), 0);
-      for (j = 0; j < 3; j++) {
-        tsspivot(&testtet, &testseg);
-        if (testseg.sh != dummysh) {
-          ssbond(testsh, testseg);
-        }
-        enextself(testtet);
-        senextself(testsh);
-      }
-      // Check quality if need.
-      if (shflaws && success) {
-        uncheckedshlist->append(&testsh);
-      }
-      if (bdry2count == 0) {
-        // Remove and replacing fake tet at equator with 'dummytet'.
-        sym(testtet, neighbortet);
-        dissolve(neighbortet);
-        tspivot(testtet, testsh);
-        if (testsh.sh != dummysh) {
-          stdissolve(testsh);
-        }
-        tetrahedrondealloc(testtet.tet);
-        testtet = neighbortet;
-      }
-      if (tetflaws && success) {
-        uncheckedtetlist->append(&testtet);
-        if (bdry2count > 0) {
-          symself(testtet);
-          uncheckedtetlist->append(&testtet);
-        }
-      }
-    }
-  }
-
-  if (!success && docheck) {
-    checkmesh();
-    checkshells();
-  }
-
-  delete [] giftfaces;
-  delete [] giftpoints;
-  delete incitetlist;
-  delete incishlist;
-  delete northpointlist;
-  delete northcasinglist;
-  delete northbacktracelist;
-  if ((bdrycount > 0) || (bdry2count > 0)) {
-    delete equatorpointlist;
-    delete equatoredgelist;
-    delete equatorcasinglist;
-    if (bdry2count > 0) {
-      delete sourthpointlist;
-      delete sourthcasinglist;
-      delete sourthbacktracelist;
-    }
-  }
-  if (eextras) {
-    delete [] northattribs;
-    if (bdry2count > 0) {
-      delete [] sourthattribs;
-    }
-  }
-  return success;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Insert/Delete point routines                                              //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Giftwrapping Algorithm Implementation                                     //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Using gift-wrapping algorithm to construct a constrained Delaunay         //
-// triangulation for input triangular faces bounded polyhedras.              //
-//                                                                           //
-//   Gift-wrapping (also called pivoting or incremental search) algorithm    //
-// can be used to solve Convex Hull(CH) problem, construct Delaunay Triangu- //
-// lation(DT) and Constrained Delaunay Triangulation(CDT) in d-dimension.    //
-//                                                                           //
-//   To construct three-dimensional CDT, gift-wrapping begins by finding a   //
-// single constrained Delaunay tetrahedron, upon which the remaining         //
-// Delaunay tetrahedras crystallize one by one. Say that a constraining      //
-// triangluar face of a Delaunay tetrahedron is UNFINISHED if the algorithm  //
-// has not yet identified the other Delaunay tetrahedron that shares the     //
-// face. To finish a face is to find the other tetrahedron, one must test    //
-// the visibility of each vertex from that face, If the face lies in the     //
-// boundary of the input, the face becomes finished when the algorithm       //
-// recognizes that there is no other adjoining tetrahedron.                  //
-//                                                                           //
-//   Generally, the running time for constructing a CDT using gift-wrapping  //
-// is O(nv*nf*ns), where nv is the number of input vertexs, nf is the number //
-// of constraining triangluar face and ns is the number of final tetrahedra. //
-// There have many variant implementations of this algorithm to improve the  //
-// poor time complexity of general gift-wrapping. Although in practice, gift //
-// -wrapping is not very suitable for constructing CDT. But if the vertexs'  //
-// and constraining faces number are tipically small, the performance of the //
-// algorithm used is not critical, our improved implementation of gift-      //
-// wrapping will suffice.                                                    //
-//                                                                           //
-//   The main idea in achieving an optimal result of gift-wrapping algorithm //
-// is that of eliminating redundant computations. Observe for each           //
-// UNFINISHED face, we must find a best visible vertex that can form a       //
-// constrained Delaunay tetrahedron with this face. For each visible vertex,  //
-// we need check all other constraining faces to see if they are obstructed  //
-// the visibility of vertex from the face. If we have known some of these    //
-// constraining faces can not obstructed the visibility of vertex in advance,//
-// we could have same time not to compute them.                              //
-//                                                                           //
-//   For this purpose, I use a Weighted-Vertex approach, which is widely     //
-// used in variety of graph algorithms, to help us determine whether a face  //
-// can be safely skipped. At first each vertex's weight is the number of     //
-// edges connected at this vertex. So all vertex's weight must great or      //
-// equal than 3. During the procedure of gift-wrapping, the weight of vertex //
-// will decrease 1 when an UNFINISHED face(contains this vertex) becaomes    //
-// finished, and increase 1 when a new UNFINISHED face(contains this vertex) //
-// be generated. Then, if a face contains a vertex with Zero-weight, it      //
-// means the face has already been finished, so it has no chance to obstruct //
-// other vertex(Remember the meaning of CDT), we can saftly skip this face   //
-// in later computing. The weight of vertex also can help us in chossing a   //
-// best face to start and chossing a best vertex when there exist more than  //
-// one visible vertexs. Please see the functions getgiftface() and           //
-// getgiftpoint() for a detail description.                                  //
-//                                                                           //
-//   At last, there need do a lot of triangle-triangle intersection tests in //
-// finding a best vertex to finish a face. I use the codes of Tomas Moller   //
-// directly to do the tests, see below.                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Triangle/triangle intersection test routine, by Tomas Moller.             //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Triangle/triangle intersection test routine,                              //
-// by Tomas Moller, 1997.                                                    //
-// See article "A Fast Triangle-Triangle Intersection Test",                 //
-// Journal of Graphics Tools, 2(2), 1997                                     //
-//                                                                           //
-// int tri_tri_intersect(REAL V0[3], REAL V1[3], REAL V2[3],                 //
-//                       REAL U0[3], REAL U1[3], REAL U2[3])                 //
-//                                                                           //
-// parameters: vertices of triangle 1: V0,V1,V2                              //
-//             vertices of triangle 2: U0,U1,U2                              //
-// result    : returns 1 if the triangles intersect, otherwise 0             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// fuzzycomp_interval()    Compare two floating-point values dx and dy.      //
-//                                                                           //
-// Return +1 if dx > dy; Return -1 if dx < dy; Return  0 if dx == dy.        //
-//                                                                           //
-// Si hang added this function for compare intervals. July, 2001.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int fuzzycomp_interval(REAL dA, REAL dB)
-{
-  REAL dSum, dDiff;
-  REAL dTol = 5.e-9;
-  REAL dFloor = 1.e-6;
-
-  dSum  = fabs(dA) + fabs(dB);
-  dDiff = dA - dB;
-  dSum = (dSum > dFloor) ? dSum : dFloor;
-  if (dDiff > dTol * dSum) return 1;
-  else if (dDiff < - dTol * dSum) return -1;
-  else return 0;
-}
-
-// if USE_EPSILON_TEST is true then we do a check:
-//   if |dv|<EPSILON then dv=0.0;
-// else no check is done (which is less robust)
-
-#define USE_EPSILON_TEST TRUE
-#define EPSILON 1e-7
-
-// some macros
-#define CROSS(dest,v1,v2)                                                  \
-  dest[0]=v1[1]*v2[2]-v1[2]*v2[1];                                         \
-  dest[1]=v1[2]*v2[0]-v1[0]*v2[2];                                         \
-  dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
-
-#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
-
-#define SUB(dest,v1,v2)                                                    \
-  dest[0]=v1[0]-v2[0];                                                     \
-  dest[1]=v1[1]-v2[1];                                                     \
-  dest[2]=v1[2]-v2[2];
-
-// sort so that a<=b
-#define SORT(a,b)                                                          \
-  if(a>b) {                                                                \
-    REAL c;                                                                \
-    c=a; a=b; b=c;                                                         \
-  }
-
-#define ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1)                          \
-  isect0=VV0+(VV1-VV0)*D0/(D0-D1);                                         \
-  isect1=VV0+(VV2-VV0)*D0/(D0-D2);
-
-#define COMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,isect0,isect1)    \
-  if(D0D1>0.0f)                                                            \
-  {                                                                        \
-    /* here we know that D0D2<=0.0 */                                      \
-/* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
-    ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1);                             \
-  }                                                                        \
-  else if(D0D2>0.0f)                                                       \
-  {                                                                        \
-    /* here we know that d0d1<=0.0 */                                      \
-    ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1);                             \
-  }                                                                        \
-  else if(D1*D2>0.0f || D0!=0.0f)                                          \
-  {                                                                        \
-    /* here we know that d0d1<=0.0 or that D0!=0.0 */                      \
-    ISECT(VV0,VV1,VV2,D0,D1,D2,isect0,isect1);                             \
-  }                                                                        \
-  else if(D1!=0.0f)                                                        \
-  {                                                                        \
-    ISECT(VV1,VV0,VV2,D1,D0,D2,isect0,isect1);                             \
-  }                                                                        \
-  else if(D2!=0.0f)                                                        \
-  {                                                                        \
-    ISECT(VV2,VV0,VV1,D2,D0,D1,isect0,isect1);                             \
-  }                                                                        \
-  else                                                                     \
-  {                                                                        \
-    /* triangles are coplanar */                                           \
-    return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2);                         \
-  }
-
-// this edge to edge test is based on Franlin Antonio's gem:
-//   "Faster Line Segment Intersection", in Graphics Gems III,
-//   pp. 199-202
-#define EDGE_EDGE_TEST(V0,U0,U1)                                           \
-  Bx=U0[i0]-U1[i0];                                                        \
-  By=U0[i1]-U1[i1];                                                        \
-  Cx=V0[i0]-U0[i0];                                                        \
-  Cy=V0[i1]-U0[i1];                                                        \
-  f=Ay*Bx-Ax*By;                                                           \
-  d=By*Cx-Bx*Cy;                                                           \
-  if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f))                       \
-  {                                                                        \
-    e=Ax*Cy-Ay*Cx;                                                         \
-    if(f>0)                                                                \
-    {                                                                      \
-      if(e>=0 && e<=f) return 1;                                           \
-    }                                                                      \
-    else                                                                   \
-    {                                                                      \
-      if(e<=0 && e>=f) return 1;                                           \
-    }                                                                      \
-  }
-
-#define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2)                             \
-{                                                                          \
-  REAL Ax,Ay,Bx,By,Cx,Cy,e,d,f;                                            \
-  Ax=V1[i0]-V0[i0];                                                        \
-  Ay=V1[i1]-V0[i1];                                                        \
-  /* test edge U0,U1 against V0,V1 */                                      \
-  EDGE_EDGE_TEST(V0,U0,U1);                                                \
-  /* test edge U1,U2 against V0,V1 */                                      \
-  EDGE_EDGE_TEST(V0,U1,U2);                                                \
-  /* test edge U2,U1 against V0,V1 */                                      \
-  EDGE_EDGE_TEST(V0,U2,U0);                                                \
-}
-
-#define POINT_IN_TRI(V0,U0,U1,U2)                                          \
-{                                                                          \
-  REAL a,b,c,d0,d1,d2;                                                     \
-  /* is T1 completly inside T2? */                                         \
-  /* check if V0 is inside tri(U0,U1,U2) */                                \
-  a=U1[i1]-U0[i1];                                                         \
-  b=-(U1[i0]-U0[i0]);                                                      \
-  c=-a*U0[i0]-b*U0[i1];                                                    \
-  d0=a*V0[i0]+b*V0[i1]+c;                                                  \
-                                                                           \
-  a=U2[i1]-U1[i1];                                                         \
-  b=-(U2[i0]-U1[i0]);                                                      \
-  c=-a*U1[i0]-b*U1[i1];                                                    \
-  d1=a*V0[i0]+b*V0[i1]+c;                                                  \
-                                                                           \
-  a=U0[i1]-U2[i1];                                                         \
-  b=-(U0[i0]-U2[i0]);                                                      \
-  c=-a*U2[i0]-b*U2[i1];                                                    \
-  d2=a*V0[i0]+b*V0[i1]+c;                                                  \
-  if(d0*d1>0.0)                                                            \
-  {                                                                        \
-    if(d0*d2>0.0) return 1;                                                \
-  }                                                                        \
-}
-
-int coplanar_tri_tri(const REAL N[3],
-                     const REAL V0[3],const REAL V1[3],const REAL V2[3],
-                     const REAL U0[3],const REAL U1[3],const REAL U2[3])
-{
-   REAL A[3];
-   short i0,i1;
-   // first project onto an axis-aligned plane, that maximizes the area
-   //   of the triangles, compute indices: i0,i1.
-   A[0]=fabs(N[0]);
-   A[1]=fabs(N[1]);
-   A[2]=fabs(N[2]);
-   if(A[0]>A[1])
-   {
-      if(A[0]>A[2])
-      {
-          i0=1;      // A[0] is greatest
-          i1=2;
-      }
-      else
-      {
-          i0=0;      // A[2] is greatest
-          i1=1;
-      }
-   }
-   else   // A[0]<=A[1]
-   {
-      if(A[2]>A[1])
-      {
-          i0=0;      // A[2] is greatest
-          i1=1;
-      }
-      else
-      {
-          i0=0;      // A[1] is greatest
-          i1=2;
-      }
-    }
-
-    // test all edges of triangle 1 against the edges of triangle 2
-    EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2);
-    EDGE_AGAINST_TRI_EDGES(V1,V2,U0,U1,U2);
-    EDGE_AGAINST_TRI_EDGES(V2,V0,U0,U1,U2);
-
-    // finally, test if tri1 is totally contained in tri2 or vice versa
-    POINT_IN_TRI(V0,U0,U1,U2);
-    POINT_IN_TRI(U0,V0,V1,V2);
-
-    return 0;
-}
-
-
-int tri_tri_intersect(const REAL V0[3], const REAL V1[3], const REAL V2[3],
-                      const REAL U0[3], const REAL U1[3], const REAL U2[3])
-{
-  REAL E1[3],E2[3];
-  REAL N1[3],N2[3],d1,d2;
-  REAL du0,du1,du2,dv0,dv1,dv2;
-  REAL D[3];
-  REAL isect1[2], isect2[2];
-  REAL du0du1,du0du2,dv0dv1,dv0dv2;
-  short index;
-  REAL vp0,vp1,vp2;
-  REAL up0,up1,up2;
-  REAL b,c,max;
-
-  // compute plane equation of triangle(V0,V1,V2)
-  SUB(E1,V1,V0);
-  SUB(E2,V2,V0);
-  CROSS(N1,E1,E2);
-  d1=-DOT(N1,V0);
-  // plane equation 1: N1.X+d1=0
-
-  // put U0,U1,U2 into plane equation 1 to compute signed distances to
-  //   the plane
-  du0=DOT(N1,U0)+d1;
-  du1=DOT(N1,U1)+d1;
-  du2=DOT(N1,U2)+d1;
-
-  // coplanarity robustness check
-#if USE_EPSILON_TEST==TRUE
-  if(fabs(du0)<EPSILON) du0=0.0;
-  if(fabs(du1)<EPSILON) du1=0.0;
-  if(fabs(du2)<EPSILON) du2=0.0;
-#endif
-  du0du1=du0*du1;
-  du0du2=du0*du2;
-
-  if(du0du1>0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ?
-    return 0;                    // no intersection occurs
-
-  // compute plane of triangle (U0,U1,U2)
-  SUB(E1,U1,U0);
-  SUB(E2,U2,U0);
-  CROSS(N2,E1,E2);
-  d2=-DOT(N2,U0);
-  // plane equation 2: N2.X+d2=0
-
-  // put V0,V1,V2 into plane equation 2
-  dv0=DOT(N2,V0)+d2;
-  dv1=DOT(N2,V1)+d2;
-  dv2=DOT(N2,V2)+d2;
-
-#if USE_EPSILON_TEST==TRUE
-  if(fabs(dv0)<EPSILON) dv0=0.0;
-  if(fabs(dv1)<EPSILON) dv1=0.0;
-  if(fabs(dv2)<EPSILON) dv2=0.0;
-#endif
-
-  dv0dv1=dv0*dv1;
-  dv0dv2=dv0*dv2;
-
-  if(dv0dv1>0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ?
-    return 0;                    // no intersection occurs
-
-  // compute direction of intersection line
-  CROSS(D,N1,N2);
-
-  // compute and index to the largest component of D
-  max=fabs(D[0]);
-  index=0;
-  b=fabs(D[1]);
-  c=fabs(D[2]);
-  if(b>max) max=b,index=1;
-  if(c>max) max=c,index=2;
-
-  // this is the simplified projection onto L
-  vp0=V0[index];
-  vp1=V1[index];
-  vp2=V2[index];
-
-  up0=U0[index];
-  up1=U1[index];
-  up2=U2[index];
-
-  // compute interval for triangle 1
-  COMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,isect1[0],isect1[1]);
-
-  // compute interval for triangle 2
-  COMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,isect2[0],isect2[1]);
-
-  SORT(isect1[0],isect1[1]);
-  SORT(isect2[0],isect2[1]);
-
-  // Origin code,
-  // if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0;
-  // New code, changed by Si hang
-  if ((fuzzycomp_interval(isect1[1], isect2[0]) == -1) ||
-      (fuzzycomp_interval(isect2[1], isect1[0]) == -1)) return 0;
-  return 1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Triangle/triangle intersection test routine, by Tomas Moller.             //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// struct giftface                                                           //
-//                                                                           //
-// A struct used to store a face for giftwrapping algorithm to construct     //
-// constrained Delaunay tetrahedralization. Where 'casing' is a handle of    //
-// unfinished face, and 'iorg', 'idest' and 'iapex' are vertex index in      //
-// pointweightlist. Use these values to get weights value for each vertices  //
-// of this giftface.                                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-typedef struct giftfacetype {
-  triface casing;
-  int iorg, idest, iapex;
-} giftface;
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dumpgifts()    Debug routine. Write current gift faces and gift points    //
-//                infomation to file.                                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::dumpgifts(char *gfile, list *giftfacelist, int numberofgiftpoints,
-                       point3d *giftpoints, int *pointweightlist)
-{
-  FILE *outfile;
-  giftface *gfaceptr;
-  int i;
-
-  outfile = fopen(gfile, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("  Error:  Cannot create file %s.\n", gfile);
-    return;
-  }
-  if (!quiet) {
-    printf("Writing %s.\n", gfile);
-  }
-  if (verbose < 1) {
-    numbernodes(1);
-  }
-  fprintf(outfile, "# Dumpping %d giftfaces.\n", giftfacelist->len());
-  for (i = 0; i < giftfacelist->len(); i++) {
-    gfaceptr = (giftface*)(*giftfacelist)[i];
-    fprintf(outfile, "%4d %4d %4d %4d  index %3d %3d %3d.\n", i,
-            pointmark(org(gfaceptr->casing)),
-            pointmark(dest(gfaceptr->casing)),
-            pointmark(apex(gfaceptr->casing)),
-            gfaceptr->iorg, gfaceptr->idest, gfaceptr->iapex);
-  }
-  fprintf(outfile, "# Dumpping %d giftpoints.\n", numberofgiftpoints);
-  for (i = 0; i < numberofgiftpoints; i++) {
-    fprintf(outfile, "%4d %4d %10.8g %10.8g %10.8g weight %4d.\n", i,
-            pointmark(giftpoints[i]), giftpoints[i][0], giftpoints[i][1],
-            giftpoints[i][2], pointweightlist[i]);
-  }
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// is_face_tet_inter_0()     Check if input face is intersecting with input  //
-//                           tetrahedron(given by its four vertexs). There   //
-//                           no shared points between face and tetrahedron.  //
-//                                                                           //
-// Take each faces of tetrahedron and do triangle-triangle intersection test //
-// with the input face. They are intersected if one of face pairs are inter- //
-// secting. If all face pairs are not intersecting, we still need to check   //
-// if the face is fully in the tetrahedron.                                  //
-//                                                                           //
-// Return 1 if they are intersecting each other. Otherwise, return zero.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::is_face_tet_inter_0(triface *checkface, point3d torg, point3d tdest,
-                                point3d tapex, point3d toppo)
-{
-  point3d forg, fdest, fapex;
-  int intersect;
-  int i;
-
-  org (*checkface, forg);
-  dest(*checkface, fdest);
-  apex(*checkface, fapex);
-
-  intersect = 0;
-  for (i = 0; i < 4; i++) {
-    if (i == 0) {
-      // 'checkface' must not intersect with base face. Remember, they are
-      //    both the input constraining faces.
-      // intersect = tri_tri_intersect(forg, fdest, fapex, torg, tdest, tapex);
-    } else if (i == 1) {
-      intersect = tri_tri_intersect(forg, fdest, fapex, torg, tdest, toppo);
-    } else if (i == 2) {
-      intersect = tri_tri_intersect(forg, fdest, fapex, tdest, tapex, toppo);
-    } else if (i == 3) {
-      intersect = tri_tri_intersect(forg, fdest, fapex, tapex, torg, toppo);
-    }
-    if (intersect) {
-      return 1;
-    }
-  }
-  // Check the face is located in the tetrahedron. That is to check each
-  //   vertex of face is located in tetrahedron. Because no face pair is
-  //   intersecting(above step guarantee this) and not exists share point.
-  //   We only need check one vertex, choose aribitarily.
-  enum locateresult loc = isintet(torg, tdest, tapex, toppo, forg);
-  // There only two cases (in or out) can be happened.
-  if ((intersect != OUTSIDE) && (intersect != INTETRAHEDRON)) {
-    printf("Internal error in is_face_tet_inter_0(): \n");
-    printf("  Invalid isintet() return value: %i. \n", intersect);
-    printf("  (0 = coplanar, 1 = on vertex, 2 = on edge, 3 = on face.)\n");
-    internalerror();
-  }
-  intersect = (loc == OUTSIDE) ? 0 : 1;
-  return intersect;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// is_face_tet_inter_1()     Check if input face is intersecting with input  //
-//                           tetrahedron(given by its four vertexs). There 1 //
-//                           share points between face and tetrahedron.      //
-//                                                                           //
-// Here we can reuse is_face_tet_inter_0(). But before use it we must detach //
-// the share point between face and tetrahedron.                             //
-//                                                                           //
-// Return 1 if they are intersecting each other. Otherwise, return zero.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::is_face_tet_inter_1(triface *checkface, point3d torg, point3d tdest,
-                                point3d tapex, point3d toppo)
-{
-  point3d forg, fdest, fapex;
-  REAL tmpforg[3], center[3];
-  int oldversion, intersect;
-  int i;
-
-  // We will change the checkface's version. So we must restore it after
-  //   checking, otherwise, the index fields in each giftface will invalid.
-  oldversion = checkface->ver;
-  // First set the share vertex be origin of checkface.
-  for (i = 0; i < 3; i++) {
-    org(*checkface, forg);
-    if ((forg == torg) || (forg == tdest) ||
-        (forg == tapex) || (forg == toppo)) {
-      dest(*checkface, fdest);
-      apex(*checkface, fapex);
-      break;
-    }
-    enextself(*checkface);
-  }
-  assert(i < 3);
-
-  center[0] = 0.5 * (fdest[0] + fapex[0]);
-  center[1] = 0.5 * (fdest[1] + fapex[1]);
-  center[2] = 0.5 * (fdest[2] + fapex[2]);
-
-  tmpforg[0] = 0.5 * (forg[0] + center[0]);
-  tmpforg[1] = 0.5 * (forg[1] + center[1]);
-  tmpforg[2] = 0.5 * (forg[2] + center[2]);
-
-  setorg(*checkface, tmpforg);
-  intersect = is_face_tet_inter_0(checkface, torg, tdest, tapex, toppo);
-  setorg(*checkface, forg);
-  checkface->ver = oldversion;
-
-  return intersect;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// is_face_tet_inter_2()     Check if input face is intersecting with input  //
-//                           tetrahedron(given by its four vertexs). There 2 //
-//                           share points between face and tetrahedron.      //
-//                                                                           //
-// The algorithm:                                                            //
-//                                                                           //
-// Set the face be f, two share point be org, dest. The other point in face  //
-//   be apex, The other two points in tetrahedron be v0, v1.                 //
-// Take f as reference plane. Check spatial relation between f and v0, v1.   //
-// IF (v0 and v1 are locating at the same side to f) THEN                    //
-//   return No intersecyion;                                                 //
-// ELSE IF (v0 and v1 are locating at diffrent side to f) THEN               //
-//   Take a face f' in tetrahedron which contain v0 but not contain v1 as    //
-//     reference plane. Check spatial relation between f' and apex, v1.      //
-//   IF (apex and v1 are loacting at the same side of f') THEN               //
-//     return Intersection;                                                  //
-//   ELSE                                                                    //
-//     return No intersection;                                               //
-//   END                                                                     //
-// ELSE IF (v0 or v1 is coplanar with f) THEN                                //
-//   IF (v0 is coplanar with f) THEN                                         //
-//     Take apex face f' in tetrahedron which contain v1 but not conatin v0  //
-//       as reference plane. Check spatial relation between f' and apex, v0. //
-//     IF (apex and v0 are loacting at the same side of f') THEN             //
-//       return Intersection;                                                //
-//     ELSE                                                                  //
-//       return No intersection;                                             //
-//     END                                                                   //
-//   ELSE                                                                    //
-//     (v1 is coplanar with f)                                               //
-//     Take apex face f' in tetrahedron which contain v0 but not conatin v1  //
-//       as reference plane. Check spatial relation between f' and apex, v1. //
-//     IF (apex and v1 are loacting at the same side of f') THEN             //
-//       return Intersection;                                                //
-//     ELSE                                                                  //
-//       return No intersection;                                             //
-//     END                                                                   //
-//   END                                                                     //
-// ELSE                                                                      //
-//   (both v0 and v1 are coplanar with f)                                    //
-//   Impossible case. Throw;                                                 //
-// END                                                                       //
-//                                                                           //
-// Return 1 if they are intersecting each other. Otherwise, return zero.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::is_face_tet_inter_2(triface *checkface, point3d torg, point3d tdest,
-                                point3d tapex, point3d toppo)
-{
-  point3d forg, fdest, fapex, v0, v1;
-  int iori1, iori2, iori3, iori4;
-  int oldversion, intersect;
-  int i;
-
-  // We will change the checkface's version. So we must restore it after
-  //   checking, otherwise, the index fields in each giftface will invalid.
-  oldversion = checkface->ver;
-  // Get forg, fdest, fapex.
-  for (i = 0; i < 3; i++) {
-    org(*checkface, forg);
-    dest(*checkface, fdest);
-    if (((forg == torg) || (forg == tdest) ||
-         (forg == tapex) || (forg == toppo)) &&
-        ((fdest == torg) || (fdest == tdest) ||
-         (fdest == tapex) || (fdest == toppo))) {
-      apex(*checkface, fapex);
-      break;
-    }
-    enextself(*checkface);
-  }
-  assert(i < 3);
-
-  // Get v0, v1.
-  if ((torg == forg) || (torg == fdest)) {
-    if ((tdest == forg) || (tdest == fdest)) {
-      v0 = tapex; v1 = toppo;
-    } else if ((tapex == forg) || (tapex == fdest)) {
-      v0 = tdest; v1 = toppo;
-    } else {
-      assert((toppo == forg) || (toppo == fdest));
-      v0 = tdest; v1 = tapex;
-    }
-  } else {
-    v0 = torg;
-    if ((tdest == forg) || (tdest == fdest)) {
-      if ((tapex == forg) || (tapex == fdest)) {
-        v1 = toppo;
-      } else {
-        assert((toppo == forg) || (toppo == fdest));
-        v1 = tapex;
-      }
-    } else {
-      assert((tapex == forg) || (tapex == fdest));
-      assert((toppo == forg) || (toppo == fdest));
-      v1 = tdest;
-    }
-  }
-  assert((v0 != forg) && (v0 != fdest));
-  assert((v1 != forg) && (v1 != fdest));
-
-  iori1 = iorient3d(forg, fdest, fapex, v0);
-  iori2 = iorient3d(forg, fdest, fapex, v1);
-  if (iori1 * iori2 != 0) {
-    // No coplanar case.
-    if (iori1 == iori2) {
-      intersect = 0;  // No intersection.
-    } else {
-      iori3 = iorient3d(forg, fdest, v0, fapex);
-      iori4 = iorient3d(forg, fdest, v0, v1);
-      assert(iori3 * iori4 != 0);
-      if (iori3 != iori4) {
-        intersect = 0;  // No intersection.
-      } else {
-        intersect = 1;  // Intersection.
-      }
-    }
-  } else {
-    // v0, or v1 is coplanar with face.
-    if (iori1 == 0) {
-      assert(iori2 != 0);
-      // v0 is coplanar with face, choose v1.
-      iori3 = iorient3d(forg, fdest, v1, v0);
-      iori4 = iorient3d(forg, fdest, v1, fapex);
-    } else {
-      assert(iori1 != 0);
-      // v1 is coplanar with face, choose v0.
-      iori3 = iorient3d(forg, fdest, v0, v1);
-      iori4 = iorient3d(forg, fdest, v0, fapex);
-    }
-    assert(iori3 * iori4 != 0);
-    if (iori3 != iori4) {
-      intersect = 0;  // No intersection.
-    } else {
-      intersect = 1;  // Intersection.
-    }
-  }
-
-  checkface->ver = oldversion;
-  return intersect;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getgiftface()    Search for a face that most suitable for finishing.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::getgiftface(list *giftfacelist, int numberofgiftpoints,
-                        int *pointweightlist, list *smallweightlist)
-{
-  giftface *gfaceptr;
-  int smallestweight, smallestindex;
-  int gpointindex, giftfaceweight;
-  int i, j, index;
-
-  // First find the smallest weight and index in giftpoint array.
-  smallestweight = 1000;
-  smallestindex = -1;
-  for (i = 0; i < numberofgiftpoints; i++) {
-    // We only need consider the unfinished giftpoint.
-    if (pointweightlist[i] == 0) continue;
-    if (pointweightlist[i] < smallestweight) {
-      smallestweight = pointweightlist[i];
-      smallestindex = i;
-    }
-  }
-  assert(smallestindex != -1);
-
-  if (smallestweight == 3) {
-    for (i = 0; i < giftfacelist->len(); i++) {
-      gfaceptr = (giftface*) (*giftfacelist)[i];
-      if ((pointweightlist[gfaceptr->iorg] == 3)
-          || (pointweightlist[gfaceptr->idest] == 3)
-          || (pointweightlist[gfaceptr->iapex] == 3)) {
-        break;
-      }
-    }
-    assert(i < giftfacelist->len());
-    return i;
-  } else {
-    // For there might exist more than one points have the same smallest
-    //   weight, I use a list to keep all these points.
-    smallweightlist = new list("int");
-    smallweightlist->append(&smallestindex);
-    for (i = smallestindex + 1; i < numberofgiftpoints; i++) {
-      if (pointweightlist[i] == smallestweight) {
-        smallweightlist->append(&i);
-      }
-    }
-    // Find the most suit giftface. Get each point index from
-    //   'smallweightlist', then find in giftface array. If a giftface
-    //   contain this point, then sum its weight of three point. Get a
-    //   giftface which have the smallest sum of weight.
-    smallestweight = 1000;
-    smallestindex = -1;
-    for (i = 0; i < smallweightlist->len(); i++) {
-      gpointindex = *(int*)(*smallweightlist)[i];
-      for (j = 0; j < giftfacelist->len(); j++) {
-        gfaceptr = (giftface*) (*giftfacelist)[j];
-        if ((gfaceptr->iorg == gpointindex) ||
-            (gfaceptr->idest == gpointindex) ||
-            (gfaceptr->iapex == gpointindex)) {
-          giftfaceweight = pointweightlist[gfaceptr->iorg]
-                         + pointweightlist[gfaceptr->idest]
-                         + pointweightlist[gfaceptr->iapex];
-          if (smallestweight > giftfaceweight) {
-            smallestweight = giftfaceweight;
-            smallestindex = j;
-          }
-        }
-      }
-    }
-    assert(smallestindex != -1);
-    return smallestindex;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getgiftpoint()    Search for a point that finished input face.            //
-//                                                                           //
-// To get a visible giftpoint for input giftface, we need:                   //
-//   (1) First find all points which visible from input face.                //
-//   (2) Choose a best (gift)point among these points.                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::getgiftpoint(triface *gface, list *giftfacelist,
-                         int numberofgiftpoints, point3d *giftpoints,
-                         int *pointweightlist, list *candpointindexlist,
-                         list *bestpointindexlist)
-{
-  giftface *gfaceptr;
-  point3d forg, fdest, fapex;
-  point3d testpoint1, testpoint2;
-  int intersect, sharecount;
-  int inspheretest, findflag;
-  int gpointindex1, gpointindex2;
-  int largerweight;
-  int i, j, index;
-
-  // Get the vertexs of input (gift)face.
-  dest(*gface, forg);
-  org(*gface, fdest);
-  apex(*gface, fapex);
-  if (verbose > 2) {
-    printf("    Finding a point for finishing face (%d, %d, %d).\n",
-           pointmark(forg), pointmark(fdest), pointmark(fapex));
-  }
-
-  candpointindexlist->clear();
-
-  // Step (1):
-  for (i = 0; i < numberofgiftpoints; i++) {
-    if (pointweightlist[i] == 0) {
-      // All faces which contain this point were finished.
-      continue;
-    }
-    testpoint1 = giftpoints[i];
-    if ((testpoint1 == forg) || (testpoint1 == fdest) ||
-        (testpoint1 == fapex)) {
-      continue; // Skip the vertex of face.
-    }
-    if (!isaboveplane(forg, fdest, fapex, testpoint1)) {
-      // This point is below or coplanar or coincident with this face.
-      continue;
-    }
-    if (verbose > 2) {
-      printf("    Checking point %d.\n", pointmark(testpoint1));
-    }
-    // Now, we found that this point is vivible form face, we still need
-    //   to check if there exist any constraining face that will cause
-    //   this point unvisible form face.
-    intersect = 0;
-    for (j = 0; j < giftfacelist->len(); j++) {
-      gfaceptr = (giftface*) (*giftfacelist)[j];
-      if ((pointweightlist[gfaceptr->iorg] == 0) ||
-          (pointweightlist[gfaceptr->idest] == 0) ||
-          (pointweightlist[gfaceptr->iapex] == 0)) {
-        // This face contain a zero-weight point, skip it.
-        continue;
-      }
-      if (verbose > 2) {
-        printf("    Checking face (%d, %d, %d).\n",
-               pointmark(org(gfaceptr->casing)),
-               pointmark(dest(gfaceptr->casing)),
-               pointmark(apex(gfaceptr->casing)));
-      }
-      // Check if this face's vertexs are share with the new tet.
-      sharecount = 0;
-      if (isfacehaspoint(&gfaceptr->casing, forg)) sharecount++;
-      if (isfacehaspoint(&gfaceptr->casing, fdest)) sharecount++;
-      if (isfacehaspoint(&gfaceptr->casing, fapex)) sharecount++;
-      if (isfacehaspoint(&gfaceptr->casing, testpoint1)) sharecount++;
-      // assert(sharecount < 4);
-      if (sharecount == 0) {
-        intersect = is_face_tet_inter_0(&gfaceptr->casing, forg, fdest, fapex,
-                                        testpoint1);
-      } else if (sharecount == 1) {
-        intersect = is_face_tet_inter_1(&gfaceptr->casing, forg, fdest, fapex,
-                                        testpoint1);
-      } else if (sharecount == 2) {
-        intersect = is_face_tet_inter_2(&gfaceptr->casing, forg, fdest, fapex,
-                                        testpoint1);
-      } else { // if (sharecount == 3)
-        intersect = 0;
-      }
-      if (intersect) {
-        // If exist intersection face. break find face loop.
-        if (verbose > 2) {
-          printf("    Skipped.\n");
-        }
-        break;
-      }
-    }
-    if (!intersect) {
-      if (verbose > 2) {
-        printf("    Visible from face.\n");
-      }
-      candpointindexlist->append(&i);
-    }
-  }
-  if (candpointindexlist->len() == 0) {
-    return -1; // Cannot find a point that can finish input face.
-  }
-
-  // Setp (2):
-  if (verbose > 2) {
-    printf("    Find %d candidating points.\n", candpointindexlist->len());
-  }
-
-  // Find a best point index from 'candpointindexlist'. A best point
-  //   should be satisfied following rules:
-  //   (1) It must satisfy the empty circumsphere criteria with the input
-  //       face. If there exist more than one such point, choose the point
-  //       which has the largest weight.
-  //   (2) The degenerate case is there exist cosphere points. If so, we
-  //       should choose a point which has the largest weight (This will
-  //       helpfully avoid form a tetrahedron that cause later giftwrapping
-  //       failed).
-  //   (3) If no satisfied point be found. This mean we can't form a constr-
-  //       ained Delaunay tetrahedralization from this faces and points(In
-  //       my case, it should not happen.) For complete the job, we choose
-  //       the point which has the maximized minimum-dihedral angle (not
-  //       done yet).
-
-  bestpointindexlist->clear();
-
-  for (i = 0; i < candpointindexlist->len(); i++) {
-    findflag = 1;
-    gpointindex1 = *(int*)(*candpointindexlist)[i];
-    testpoint1 = giftpoints[gpointindex1];
-    for (j = 0; j < candpointindexlist->len(); j++) {
-      if (j == i) continue; // Skip the same point.
-      gpointindex2 = *(int*)(*candpointindexlist)[j];
-      testpoint2 = giftpoints[gpointindex2];
-      inspheretest = iinsphere(fdest, forg, fapex, testpoint1, testpoint2);
-      if (inspheretest > 0) {
-        findflag = 0;
-        break;
-      } else if (inspheretest == 0) {
-        if (pointweightlist[gpointindex1] < pointweightlist[gpointindex2]) {
-          findflag = 0;
-          break;
-        }
-      }
-    }
-    if (findflag) {
-      bestpointindexlist->append(&gpointindex1);
-    }
-  }
-
-  if (verbose > 2) {
-    printf("    Find %d best points.\n", bestpointindexlist->len());
-  }
-  if (bestpointindexlist->len() == 1) {
-    gpointindex1 = *(int*)(*bestpointindexlist)[0];
-  } else if (bestpointindexlist->len() > 1) {
-    for (i = 0; i < bestpointindexlist->len(); i++) {
-      gpointindex2 = *(int*)(*bestpointindexlist)[i];
-      if (verbose > 2) {
-        printf("     Checking point %d, weight = %d.\n",
-               pointmark(giftpoints[gpointindex2]),
-               pointweightlist[gpointindex2]);
-      }
-      if (i == 0) {
-        largerweight = pointweightlist[gpointindex2];
-        gpointindex1 = gpointindex2;
-      } else {
-        if (largerweight < pointweightlist[gpointindex2]) {
-          largerweight = pointweightlist[gpointindex2];
-          gpointindex1 = gpointindex2;
-        }
-      }
-    }
-  } else {
-    // No constrained Delaunay tetrahedralization can be formed.
-    printf("Internal error in getgiftpoint(): \n");
-    printf("  Cannot find a best point from %i points",
-           candpointindexlist->len());
-    internalerror();
-  }
-
-  return gpointindex1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// giftwrapping()    Generate a constrained Delaunay tetrahedralization from //
-//                   input faces and points use Giftwrapping algorithm.      //
-//                                                                           //
-// The Giftwrapping algorithm:                                               //
-//   The gift-wrapping algorithm maintains a dictionary of unfinished faces, //
-// which initially contains the d+1 faces of the first Delaunay d-simplex.   //
-// Repeat the following step: remove an arbitrary unfinished face f from the //
-// dictionary and search for a vertex that finishes f. This vertex must be   //
-// above f, and have the property that the new d-simplex that results has an //
-// empty circumsphere. Na��vely, this search takes O(n) time. If no vertex   //
-// is above f, then f lies on the boundary of the convex hull. Otherwise, s  //
-// becomes part of the growing triangulation. Check each (d-1)-face of s,    //
-// except f against the dictionary. If a face is already present in the dic- //
-// tionary, then the face is now finished, so remove it from the dictionary. //
-// Otherwise, the face is new, so insert it into the dictionary.             //
-//                                                                           //
-// 'backtracelist' is a list to keep all new tets be created during gift-    //
-// wrapping stage, so we can delete them if gift-wrapping failed.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::giftwrapping(int numberofgiftfaces, triface *giftfaces,
-                         int numberofgiftpoints, point3d *giftpoints,
-                         REAL *tetattribs, REAL volumevar, list *backtracelist)
-{
-  list *giftfacelist;
-  list *smallweightlist;
-  list *candpointindexlist, *bestpointindexlist;
-  giftface gface, *gfaceptr;
-  triface newtetra, checkface;
-  face checksh;
-  point3d gpoint, checkorg, checkdest;
-  int *pointweightlist;
-  int gfaceindex, gpointindex;
-  int success, facefinished;
-  int i, j;
-
-  if (verbose > 1) {
-    printf("  Gift-wrapping begin with %d faces, %d points.\n",
-           numberofgiftfaces, numberofgiftpoints);
-  }
-  giftfacelist = new list(sizeof(giftface));
-  pointweightlist = new int[numberofgiftpoints];
-  // Init giftfacelist. At init all giftfaces are unfinished.
-  for (i = 0; i < numberofgiftfaces; i++) {
-    gfaceptr = (giftface*) giftfacelist->alloc();
-    gfaceptr->casing = giftfaces[i];
-    gfaceptr->iorg = gfaceptr->idest = gfaceptr->iapex = 0;
-  }
-  // Generate weights for every giftpoint. At the same time, store all
-  //   vertexs's index in giftpoints array of each giftface. This will
-  //   avoid to search index every time when a giftface is finfished.
-  for (i = 0; i < numberofgiftpoints; i++) {
-    pointweightlist[i] = 0;
-    for (j = 0; j < giftfacelist->len(); j++) {
-      gfaceptr = (giftface*) (*giftfacelist)[j];
-      if (org(gfaceptr->casing) == giftpoints[i]) {
-        pointweightlist[i]++;
-        gfaceptr->iorg = i;
-      } else if (dest(gfaceptr->casing) == giftpoints[i]) {
-        pointweightlist[i]++;
-        gfaceptr->idest = i;
-      } else if (apex(gfaceptr->casing) == giftpoints[i]) {
-        pointweightlist[i]++;
-        gfaceptr->iapex = i;
-      }
-    }
-    assert(pointweightlist[i] > 0);
-  }
-  if (verbose > 3) {
-    dumpgifts("gifts.txt", giftfacelist, numberofgiftpoints,
-              giftpoints, pointweightlist);
-  }
-
-  success = 1;
-  // For there might exist more than one points have the same smallest
-  //   weight, I use a list to keep all these points.
-  smallweightlist = new list("int");
-  // A list to keep all indexs of points which visible from the input
-  //   giftface(*gface) in giftpoints array.
-  candpointindexlist = new list("int");
-  // A list to keep the best point(s) for finishing a giftface.
-  bestpointindexlist = new list("int");
-  // These three lists are created here to avoid create and delete every
-  //   time when finishing each giftface.
-
-  // Do giftwrapping from 'giftfacelist' and 'giftpoints'.
-  while (giftfacelist->len()) {
-    // Get a most suit giftface to start.
-    gfaceindex = getgiftface(giftfacelist, numberofgiftpoints, pointweightlist,
-                             smallweightlist);
-    gface = *(giftface*)(*giftfacelist)[gfaceindex];
-    if (verbose > 2) {
-      printf("    Choosing face (%d, %d, %d).\n", pointmark(org(gface.casing)),
-             pointmark(dest(gface.casing)), pointmark(apex(gface.casing)));
-    }
-    // Decrease corresponding point's weight.
-    pointweightlist[gface.iorg]--;
-    pointweightlist[gface.idest]--;
-    pointweightlist[gface.iapex]--;
-    // Remove this giftface from unfinished list.
-    giftfacelist->del(gfaceindex);
-    // Get a giftpoint that can be formed a constrained Delaunay tetrahedron
-    //   with this giftface.
-    gpointindex = getgiftpoint(&gface.casing, giftfacelist, numberofgiftpoints,
-                               giftpoints, pointweightlist, candpointindexlist,
-                               bestpointindexlist);
-    if (gpointindex == -1) {
-      success = 0;
-      break; // Giftwrapping failed.
-    }
-    gpoint = giftpoints[gpointindex];
-    if (verbose > 2) {
-      printf("    Choosing point %d.\n", pointmark(gpoint));
-    }
-    // Form a new tetrahedron from gface.casing and gpoint.
-    maketetrahedron(&newtetra);
-    backtracelist->append(&newtetra);
-    setorg (newtetra, dest(gface.casing));
-    setdest(newtetra, org(gface.casing));
-    setapex(newtetra, apex(gface.casing));
-    setoppo(newtetra, gpoint);
-    // Bond the new tetra with gift face.
-    bond(gface.casing, newtetra);
-    tspivot(gface.casing, checksh);
-    if (checksh.sh != dummysh) {
-      sesymself(checksh);
-      tsbond(newtetra, checksh);
-    }
-    if (tetattribs != NULL) {
-      // Set the element attributes of the new tetrahedron.
-      for (i = 0; i < eextras; i++) {
-        setelemattribute(newtetra.tet, i, tetattribs[i]);
-      }
-    }
-    if (varvolume) {
-      // Set the area constraint of a new tetrahedron.
-      setvolumebound(newtetra.tet, volumevar);
-    }
-    // Check three new faces of newtetra to see if they are finished by
-    //   other gift faces. If find such gift face, its being finished,
-    //   remove it from giftfaces(set face finished flag be 1). If not
-    //   find such gift face, add this face to giftfaces.
-    adjustedgering(newtetra, CCW);
-    for (i = 0; i < 3; i++) {
-      fnext(newtetra, checkface);
-      checkorg = org(checkface);
-      checkdest = dest(checkface);
-      // Find in giftfacelist to see if any face be finished. If a face
-      //   has both three points(checkorg, checkdest and gpoint). It must
-      //   be finished.
-      facefinished = 0;
-      for (j = 0; j < giftfacelist->len(); j++) {
-        gfaceptr = (giftface*)(*giftfacelist)[j];
-        if (isfacehaspoint(&(gfaceptr->casing), checkorg) &&
-            isfacehaspoint(&(gfaceptr->casing), checkdest) &&
-            isfacehaspoint(&(gfaceptr->casing), gpoint)) {
-          // Find such face, now it is finished.
-          if (verbose > 2) {
-            printf("    Finishing face (%d, %d, %d).\n",
-                   pointmark(org(gfaceptr->casing)),
-                   pointmark(dest(gfaceptr->casing)),
-                   pointmark(apex(gfaceptr->casing)));
-          }
-          //   Decrease corresponding point's weight.
-          pointweightlist[gfaceptr->iorg]--;
-          pointweightlist[gfaceptr->idest]--;
-          pointweightlist[gfaceptr->iapex]--;
-          //   Bond these two tets.
-          bond(gfaceptr->casing, checkface);
-          tspivot(gfaceptr->casing, checksh);
-          if (checksh.sh != dummysh) {
-            sesymself(checksh);
-            tsbond(checkface, checksh);
-          }
-          // Remove this giftface from unfinished list.
-          giftfacelist->del(j);
-          facefinished = 1;
-          break;
-        }
-      }
-      if (!facefinished) {
-        // This is an unfinished face, add it to giftfacelist.
-        gfaceptr = (giftface*) giftfacelist->alloc();
-        adjustedgering(checkface, CCW);
-        gfaceptr->casing = checkface;
-        if (verbose > 2) {
-          printf("    Adding an unfinished face (%d, %d, %d).\n",
-                 pointmark(org(gfaceptr->casing)),
-                 pointmark(dest(gfaceptr->casing)),
-                 pointmark(apex(gfaceptr->casing)));
-        }
-        // Decide the index of point from gface. Note: here gface's enext()
-        //   sequence is: (idest, iorg)->(iorg, iapex)->(iapex, idest) that
-        //   corresponding to checkface's enext() sequence. But after do
-        //   checkface.adjustedgering(0) it becomes inversed in each term:
-        //   that is: (iorg, idest)->(iapex, iorg)->(idest, iapex).
-        if (i == 0) {
-          gfaceptr->iorg = gface.iorg;
-          gfaceptr->idest = gface.idest;
-        } else if (i == 1) {
-          gfaceptr->iorg = gface.iapex;
-          gfaceptr->idest = gface.iorg;
-        } else { // i == 2
-          gfaceptr->iorg = gface.idest;
-          gfaceptr->idest = gface.iapex;
-        }
-        gfaceptr->iapex = gpointindex;
-        // Increase each vertex's weight.
-        pointweightlist[gfaceptr->iorg]++;
-        pointweightlist[gfaceptr->idest]++;
-        pointweightlist[gfaceptr->iapex]++;
-      }
-      enextself(newtetra);
-    }
-    if (verbose > 2) {
-      printf("    Create new: ");
-      dump(&newtetra);
-    }
-  }
-
-  if (verbose > 1) {
-    printf("  Gift-wrapping end: %s.\n", success ? "Success" : "Failed");
-  }
-  delete [] pointweightlist;
-  delete giftfacelist;
-  delete smallweightlist;
-  delete bestpointindexlist;
-  delete candpointindexlist;
-  return success;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Giftwrapping Algorithm Implementation                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// Randomized Incremental Flip Delaunay Tetrahedrization                     //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-//   Incremental insertion algorithm is the simplest and the most commonly   //
-// used algorithm for constructing Delaunay triangulations. It extends in    //
-// a straightforward way to three (or more) dimensions. In three-dimension   //
-// there have several algorithms based on the incermental scheme, such as    //
-// the algorithms proposed by Boywer/Watson[1], Joe[2] and Edelsbrunner and  //
-// Shah[3], etc.                                                             //
-//                                                                           //
-//   Joe[2] provided an Incremental Flip algorithm to construct Delaunay     //
-// tetrahedralization with time complexity of O(n ^ 2) in the worst case, n  //
-// is the size of input point set. Edelsbrunner and Shah[3] extended Joe's   //
-// algorithm to a Randomized Incremental Flip algorithm with time complexity //
-// of O(n ^ (d+1)/2) in the worst case and O(n log n + n ^ ceiling(d/2)) in  //
-// the expected case.  Empirical results with an existing implementation     //
-// (Detri[4]) shows the Edelsbrunner and Shah[3]'s algorithm behaved well    //
-// for both randomly and regular distributed point sets.                     //
-//                                                                           //
-//   Tetgen uses the Randomized Incremental Flip algorithm of Edelsbrunner   //
-// and Shah[3] to construct Delaunay tetrahedralizations of 3D point sets.   //
-// The implementation is robust and fast. It used the fast randomized point  //
-// location algorithm of Mucke, Issac and Zhu's to perform point location.   //
-// and optionally used the adaptive exact geometric predicates package of    //
-// Shewchuk to perform exact orientation and insphere tests, Mucke's share-  //
-// ware Detri[4] also implemented the same algorithm, but lack of speed. My  //
-// implementation of this algorithm is faster than Detri[4].                 //
-//                                                                           //
-// Please see predicate.cpp, ptloc.cpp and flips.cpp for more infomation.    //
-//                                                                           //
-// Refernces:                                                                //
-//                                                                           //
-// [1] Adrian Bowyer. Computing Dirichlet Tessellations. Computer Journal    //
-//     24(2):162-166, 1981.  David F. Watson. Computing the three-dimens-    //
-//     ional Delaunay Tessellation with Application to Voronoi Polytopes.    //
-//     Computer Journal 24(2):167-172, 1981.                                 //
-// [2] Barry Joe. Construction of Three-Dimensional Triangulations using     //
-//     Local Transformations. Computer Aided Geometric Design 8:123-142,     //
-//     1991.                                                                 //
-// [3] Herbert Edelsbrunner and Nimish Shah. Incremental topological         //
-//     flipping works for regular triangulations. Algorithmica, 15:223-241,  //
-//     1996.                                                                 //
-// [4] Detri, The Code Constructs the 3D Delaunay Triangulation of a Given   //
-//     Point Set Using a Variant of the Randomized Incremental-Flip          //
-//     Algorithm,                                                            //
-//     http://www.geom.umn.edu/software/cglist/GeomDir/Detri_2.6.a.tar.gz    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// construct_initial_tetra()    Create an initial triangulation by building  //
-//                              tetrahedron <a, b, c, o>; where the four     //
-//                              points are not coplanar, and no three points //
-//                              are colinear.                                //
-//                                                                           //
-// To construct the first tetrahedron, we should detect and avoid degenerate //
-// cases. They are two duplicated points, three colinear points and four     //
-// coplanar points. At two duplicated points case, we just ignored one of    //
-// them; at colinear and coplanar points cases, we must skip current point   //
-// and get next point, keep testing until a good point be found, all skipped //
-// points will consider later, store them in 'skippointlist'.                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::construct_initial_tetra(queue* skippointlist)
-{
-  triface newtet, ghosttet;
-  point3d pointloop;
-  point3d pa, pb, pc, pd;
-  int pointnumber;
-  int i, j;
-
-  if (verbose > 1) {
-    printf("  Construct an initial tetrahedron.\n");
-  }
-  // Set a 'ghosttet' handle the Outer space.
-  ghosttet.tet = dummytet;
-  pointnumber = points.items;
-  points.traversalinit();
-  pa = pointtraverse();
-  i = 0;
-  while (i < pointnumber) {
-    pointloop = pointtraverse();
-    i++;
-    if(compare2points(&pa, &pointloop) == 0) {
-      if (!quiet) {
-        printf("Warning:  A duplicate point at (%.12g, %.12g, %.12g)",
-               pointloop[0], pointloop[1], pointloop[2]);
-        printf(" appeared and was ignored.\n");
-      }
-      // This will cause change from input points set.
-      // pointdealloc(pointloop);
-      continue;
-    }
-    break;
-  }
-  if (i >= pointnumber) {
-    printf("\nAll points are duplicate, no tetrahedralization be");
-    printf(" constructed.\n");
-    exit(1);
-  }
-  pb = pointloop;
-  while (i < pointnumber) {
-    pointloop = pointtraverse();
-    i++;
-    if (iscoline(pa, pb, pointloop)) {
-      if (verbose > 2) {
-        printf("    A colinear point at (%.12g, %.12g, %.12g) %d",
-          pointloop[0], pointloop[1], pointloop[2]);
-        printf(" appeared and queued to process later.\n");
-      }
-      skippointlist->push(&pointloop);
-      continue;
-    }
-    break;
-  }
-  if (i >= pointnumber) {
-    printf("\nAll points are colinear, no tetrahedralization be");
-    printf(" constructed.\n");
-    exit(1);
-  }
-  pc = pointloop;
-  while (i < pointnumber) {
-    pointloop = pointtraverse();
-    i++;
-    if (iscoplane(pa, pb, pc, pointloop)) {
-      if (verbose > 2) {
-        printf("    A coplanar point at (%.12g, %.12g, %.12g)",
-          pointloop[0], pointloop[1], pointloop[2]);
-        printf(" appeared and queued to process later.\n");
-      }
-      skippointlist->push(&pointloop);
-      continue;
-    }
-    break;
-  }
-  if (i >= pointnumber) {
-    printf("All points are coplanar, no tetrahedrization be constructed.\n");
-    exit(1);
-  }
-  pd = pointloop;
-
-  if (!isaboveplane(pa, pb, pc, pd)) {
-    pointloop = pa; pa = pb; pb = pointloop;
-  }
-  maketetrahedron(&newtet);
-  setorg(newtet, pa);
-  setdest(newtet, pb);
-  setapex(newtet, pc);
-  setoppo(newtet, pd);
-  bond(newtet, ghosttet);
-  if (verbose > 2) {
-    printf("    Creating tetra ");
-    dump(&newtet);
-  }
-  // At init, all faces of this tet are hull faces.
-  hullsize = 4;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// collect_visibles()    Collects all CH facets visible from insertpoint and //
-//                       stores them in fliplist. At the same time,construct //
-//                       tetrahedra from insertpoint to all visible facets.  //
-//                                                                           //
-// The 'insertpoint' locate outside CH. And 'horiz' is a init hull facet ha- //
-// ndle that visible from 'insertpoint'. ( We assume that an oracle provided //
-// the initial facet which is on CH )   'fliplist' is a queue for return all //
-// visible facets from 'insertpoint', which will check doflip later.         //
-//                                                                           //
-// 'ghosttet' is a handle that hold the 'Outer Space' of current mesh. Use   //
-// this handle to bond new generated tetrahedron on current boundary, so     //
-// later point location routines will work correctlly.                       //
-//                                                                           //
-// 'unfinfacelist' is a link to keep all unfinished faces for 'insertpoint'. //
-// It is created in routine rand_incr_flip_delaunay() to avoid create it and //
-// delete it every time when call this routine. At the beginning and end of  //
-// this routine, 'unfinfacelist' should be empty.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::collect_visibles(point3d insertpoint, triface *horiz,
-                              triface *ghosttet, link *unfinfacelist)
-{
-  triface newtet, otherface, horizface;
-  point3d torg, tdest, tapex;
-  int findex;
-
-  if (verbose > 1) {
-    printf("  Collect visible facets for inserting point: \n");
-  }
-
-  enqueuefliplist(*horiz);
-  adjustedgering(*horiz, CCW);
-  org (*horiz, torg);
-  dest(*horiz, tdest);
-  apex(*horiz, tapex);
-  // Mount the initial tetrahedron to mesh.  That is a tetrahedron consists
-  //   of facet horiz and insertpoint.
-  maketetrahedron(&newtet); // default newtet.ver = 0.
-  setorg (newtet, tdest);
-  setdest(newtet, torg);
-  setapex(newtet, tapex);
-  setoppo(newtet, insertpoint);
-  // Make the connection of two tets.
-  bond(newtet, *horiz);
-  // Add the new tetrahedron's three faces to unfinished faces list.
-  //   Keep 'insertpoint' be apex of each faces.
-  fnext(newtet, otherface);
-  unfinfacelist->add(&otherface);
-  enextfnext(newtet, otherface);
-  unfinfacelist->add(&otherface);
-  enext2fnext(newtet, otherface);
-  bond(otherface, *ghosttet);
-  unfinfacelist->add(&otherface);
-  if (verbose > 2) {
-    printf("    Creating newtet ");
-    dump(&newtet);
-  }
-  // Hull face number decreased caused by face bond() operation.
-  hullsize --;
-
-  // Loop untill unfinfacelist is empty.
-  while (unfinfacelist->len() > 0) {
-    horizface = * (triface *) unfinfacelist->getnitem(1);
-    unfinfacelist->del(1);  // Remove it.
-    otherface = horizface;
-    adjustedgering(otherface, CCW);
-    // Spin otherface around the edge of otherface. Stop when encounter
-    //   Outer space.
-    while (fnextself(otherface)) ;
-    adjustedgering(horizface, CW);
-    apex(otherface, tapex);
-    if (isaboveplane(&horizface, tapex)) {
-      // otherface is visible form insertpoint.
-      enqueuefliplist(otherface);
-      org (otherface, torg);
-      dest(otherface, tdest);
-      // Mount a tetrahedron to mesh.  This tetrahedron is consists of
-      //   otherface's vertexs and insertpoint.
-      maketetrahedron(&newtet);          // default newtet.ver = 0.
-      setorg (newtet, torg);
-      setdest(newtet, tdest);
-      setapex(newtet, tapex);
-      setoppo(newtet, insertpoint);
-      // Make the connection of three tets.  Note:  The other two faces of
-      //   new tet default bond to 'dummytet',  here need check if they are
-      //   finished.
-      bond(newtet, otherface);
-      // Hull face number decrease caused by bond().
-      hullsize --;
-      fnext(newtet, otherface);
-      bond(otherface, horizface);
-      // Check other two face if they already exist in list Unfinshed.If so
-      //   They are finished now and can be removed from list, then bond.
-      enextfnext(newtet, otherface);
-      findex = unfinfacelist->hasitem(&otherface);
-      if ((findex > 0) && (findex <= unfinfacelist->len())) {
-        horizface = * (triface *) unfinfacelist->getnitem(findex);
-        unfinfacelist->del(findex);  // Remove it.
-        bond(otherface, horizface);
-      } else {
-        bond(otherface, *ghosttet);
-        unfinfacelist->add(&otherface);
-      }
-      enext2fnext(newtet, otherface);
-      findex = unfinfacelist->hasitem(&otherface);
-      if ((findex > 0) && (findex <= unfinfacelist->len())) {
-        horizface = * (triface *) unfinfacelist->getnitem(findex);
-        unfinfacelist->del(findex);  // Remove it.
-        bond(otherface, horizface);
-      } else {
-        bond(otherface, *ghosttet);
-        unfinfacelist->add(&otherface);
-      }
-      if (verbose > 2) {
-        printf("    Createing newtet ");
-        dump(&newtet);
-      }
-    } else {
-      // This is a hull face.
-      hullsize ++;
-    }
-  } // End of while.
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dofliplist()    Flips non-Delaunay triangular facets in given 'fliplist'  //
-//                 until all triangular facets are locally Delaunay.         //
-//                                                                           //
-// ASSUMPTION: Current tetrahedrization is non-Delaunay after inserting      //
-// point v, AND: all possibly non-Delaunay link-facets after are on 'flip-   //
-// list. Upon success (which should always happen, by now) dofliplist()      //
-// returns the number of necessary flips. As a side effect,'fliplist' will   //
-// be cleared, and current tetrahedrization updated accordingly.             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int mesh3d::dofliplist()
-{
-  triface flipface;
-  enum facecategory fc;
-  int flipcount;
-
-  flipcount = flip_t23s + flip_t32s + flip_t22s + flip_t44s;
-  // Start flip.
-  if (verbose > 1) {
-    printf("  Start do flip list: %d faces in list.", fliplist->len());
-    if (verbose > 1) printf("\n");
-  }
-  while (dequeuefliplist(flipface)) {
-    fc = categorizeface(flipface);
-    // Determine the preferable configuration and swap if necessary.
-    switch (fc) {
-      // These cases are handled by edge swapping.
-      case N44:
-      case N32:
-        break;
-      // These cases are definitely unswappable
-      case N40:
-      case N30:
-      case N20:
-      case LOCKED:
-        break;
-      case T44:
-        if (querydoswap(flipface)) {
-          flip44(flipface);
-        }
-        break;
-      case T22:
-        if (querydoswap(flipface)) {
-          flip22(flipface);
-        }
-        break;
-      case T23:
-        if (querydoswap(flipface)) {
-          flip23(flipface);
-        }
-        break;
-      case T32:
-        if (querydoswap(flipface)) {
-          flip32(flipface);
-        }
-        break;
-      // Catch-all for bad cases
-      default:
-        break;
-    }
-  }
-  flipcount = flip_t23s + flip_t32s + flip_t22s + flip_t44s - flipcount;
-  if (verbose > 1) {
-    printf("  Total %d flips.\n", flipcount);
-  }
-  return flipcount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// rand_incr_flip_delaunay()   Construction delaunay tetrahedrization for a  //
-//                             given three-dimensional point set use Random- //
-//                             ize Incremental Flip algorithm.               //
-//                                                                           //
-// The basic idea of the incremental flip algorithm is the folloeing. S be a //
-// set of points in IR{3}, Let 4 <= i <= n and assume that the Delaunay tri- //
-// angulation of the first i-1 points in S is already constructed; call it   //
-// D(i-1). Add the i-th point pi (belong to S) to the triangulation,and res- //
-// tore Delaunayhood by flipping; this result in D(i). Repeat this procedure //
-// until i = n. If implemented correctly, this strategy always leads to the  //
-// Ddelaunay triangulation of S.                                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-long mesh3d::rand_incr_flip_delaunay()
-{
-  queue *skippointlist;
-  link *unfinfacelist;
-  triface starttet, ghosttet;
-  point3d pointloop;
-  enum insertsiteresult insres;
-  long max_flips, flipcount;
-  int max_flips_overflow;
-
-  // max_flips is the upper bound on total number of flips.
-  //   see Herbert's Triangulation notes, p95.
-  max_flips = points.items * (points.items + 3) + 1;
-  if (max_flips <= 0) {
-    // The long number Overflow!
-    max_flips_overflow = 1;
-  } else {
-    max_flips_overflow = 0;
-  }
-
-  usefliplist = 1;
-  if (fliplist) {
-    fliplist->clear();
-  } else {
-    fliplist = new queue(sizeof(badface3d));
-  }
-
-  // Set a queue for keeping all skipped points in routine
-  //   construct_initial_tetra();
-  skippointlist = new queue("point");
-
-  // Set a 'ghosttet' handle the Outer space.
-  //   This variable only used in routine collect_visible().
-  ghosttet.tet = dummytet;
-  // Setup a list for keeping all unfinished faces.
-  //   This list only used in routine collect_visible(). It is created here
-  //   to avoid create it and delete it every time when call this routine.
-  unfinfacelist = new link(sizeof(triface));
-  // Set user-defined compare function for comparing faces.
-  unfinfacelist->setcomp((compfunc) &issameface);
-
-  flip_t23s = flip_t32s = flip_t22s = flip_t44s = 0;
-  cospherecount = 0;
-
-  // Build a initial tetrahedron.
-  construct_initial_tetra(skippointlist);
-
-  // Delaunay tetrahedrization construction.
-  //   Continue get points after above routine, need not do traverseinit().
-  pointloop = pointtraverse();
-  while (pointloop != (point3d) NULL) {
-    starttet.tet = (tetrahedron *) NULL;
-    insres = insertsite(pointloop, &starttet, NULL, NULL);
-    if (insres == FAILED) {
-      // Point is outside current mesh.
-      collect_visibles(pointloop, &starttet, &ghosttet, unfinfacelist);
-      assert(unfinfacelist->len() == 0);
-    } else if (insres == DUPLICATE) {
-      if (!quiet) {
-        printf("Warning:  A duplicate point at (%.12g, %.12g, %.12g)",
-               pointloop[0], pointloop[1], pointloop[2]);
-        printf(" appeared and was ignored.\n");
-      }
-    }
-    if (!fliplist->empty()) {
-      flipcount = dofliplist();
-      if (!max_flips_overflow) {
-        max_flips -= flipcount;
-      }
-    }
-    pointloop = pointtraverse();
-  }
-  if (!max_flips_overflow && (max_flips <= 0)) {
-    printf("Error: Randomize Incremental Flip algorithm crashed!\n");
-    internalerror();
-  }
-
-  if (skippointlist->len() > 0) {
-    while (skippointlist->get(&pointloop)) {
-      starttet.tet = (tetrahedron *) NULL;
-      insres = insertsite(pointloop, &starttet, NULL, NULL);
-      if (insres == FAILED) {
-        // Point is outside current mesh.
-        collect_visibles(pointloop, &starttet, &ghosttet, unfinfacelist);
-        assert(unfinfacelist->len() == 0);
-      } else if (insres == DUPLICATE) {
-        if (!quiet) {
-          printf("Warning:  A duplicate point at (%.12g, %.12g, %.12g)",
-                 pointloop[0], pointloop[1], pointloop[2]);
-          printf(" appeared and was ignored.\n");
-        }
-      }
-      if (!fliplist->empty()) {
-        flipcount = dofliplist();
-        if (!max_flips_overflow) {
-          max_flips -= flipcount;
-        }
-      }
-    }
-    if (!max_flips_overflow && (max_flips <= 0)) {
-      printf("Error: Randomize Incremental Flip algorithm crashed!\n");
-      internalerror();
-    }
-  }
-
-  if (verbose) {
-    printf("  Total flips: %d  Where T23: %d  T32: %d  T22: %d  T44: %d\n",
-           flip_t23s + flip_t32s + flip_t22s + flip_t44s,
-           flip_t23s, flip_t32s, flip_t22s, flip_t44s);
-    printf("  Cosphere count: %d\n", cospherecount);
-  }
-  assert(fliplist->empty());
-  usefliplist = 0;
-  delete skippointlist;
-  delete unfinfacelist;
-  return hullsize;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// delaunay()   Form a Delaunay triangulation.                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-long mesh3d::delaunay()
-{
-  eextras = 0;
-  initializetetshpools();
-
-  if (!quiet) {
-    if (noexact) {
-      printf("Using approximate floating-point arthmetic ");
-    } else {
-      printf("Using adaptive exact floating-point arthmetic ");
-    }
-    if (noroundoff) {
-      printf("without tolerance.\n");
-    } else {
-      printf("with tolerance %g.\n", usertolerance);
-    }
-    printf("Constructing Delaunay triangulation ");
-    printf("by Randomized Incremental-Flip algorithm.\n");
-  }
-
-  return rand_incr_flip_delaunay();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// Randomized Incremental Flip Delaunay Tetrahedrization                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// File I/O Routines                                                         //
-// BEGIN                                                                     //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// readline()    Read a nonempty line from a file.                           //
-//                                                                           //
-// A line is considered "nonempty" if it contains something that looks like  //
-// a number.                                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-char* mesh3d::readline(char *string, FILE *infile, char *infilename)
-{
-  char *result;
-
-  // Search for something that looks like a number.
-  do {
-    result = fgets(string, INPUTLINESIZE, infile);
-    if (result == (char *) NULL) {
-      printf("File I/O Error:  Unexpected end of file in %s.\n", infilename);
-      exit(1);
-    }
-    // Skip anything that doesn't look like a number, a comment,
-    //   or the end of a line.
-    while ((*result != '\0') && (*result != '#')
-           && (*result != '.') && (*result != '+') && (*result != '-')
-           && ((*result < '0') || (*result > '9'))) {
-      result++;
-    }
-  // If it's a comment or end of line, read another line and try again.
-  } while ((*result == '#') || (*result == '\0'));
-  return result;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// findfield()    Find the next field of a string.                           //
-//                                                                           //
-// Jumps past the current field by searching for whitespace, then jumps past //
-// the whitespace to find the next field.                                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-char* mesh3d::findfield(char *string)
-{
-  char *result;
-
-  result = string;
-  // Skip the current field.  Stop upon reaching whitespace.
-  while ((*result != '\0') && (*result != '#')
-         && (*result != ' ') && (*result != '\t')) {
-    result++;
-  }
-  // Now skip the whitespace and anything else that doesn't look like a
-  //   number, a comment, or the end of a line.
-  while ((*result != '\0') && (*result != '#')
-         && (*result != '.') && (*result != '+') && (*result != '-')
-         && ((*result < '0') || (*result > '9'))) {
-    result++;
-  }
-  // Check for a comment (prefixed with `#').
-  if (*result == '#') {
-    *result = '\0';
-  }
-  return result;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// readnodes()    Read the points from a file, which may be a .node or .poly //
-//                file.                                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::readnodes(FILE **polyfile)
-{
-  FILE *infile;
-  point3d pointloop;
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-  char *infilename;
-  REAL x, y, z;
-  int firstnode;
-  int nodemarkers;
-  int currentmarker;
-  int i, j;
-
-  if (poly || smesh) {
-    // Read the points from a .poly or .smesh file.
-    if (poly) {
-      if (!quiet) {
-        printf("Opening %s.\n", inpolyfilename);
-      }
-      *polyfile = fopen(inpolyfilename, "r");
-      if (*polyfile == (FILE *) NULL) {
-        printf("File I/O Error:  Cannot access file %s.\n", inpolyfilename);
-        exit(1);
-      }
-      stringptr = readline(inputline, *polyfile, inpolyfilename);
-    } else {
-      if (!quiet) {
-        printf("Opening %s.\n", insmeshfilename);
-      }
-      *polyfile = fopen(insmeshfilename, "r");
-      if (*polyfile == (FILE *) NULL) {
-        printf("File I/O Error:  Cannot access file %s.\n", insmeshfilename);
-        exit(1);
-      }
-      stringptr = readline(inputline, *polyfile, insmeshfilename);
-    }
-    // Read number of points, number of dimensions, number of point
-    //   attributes, and number of boundary markers.
-    inpoints = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      mesh_dim = 3;
-    } else {
-      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      nextras = 0;
-    } else {
-      nextras = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      nodemarkers = 0;
-    } else {
-      nodemarkers = (int) strtol (stringptr, &stringptr, 0);
-    }
-    if (inpoints > 0) {
-      readnodefile = 0;
-      infilename = inpolyfilename;
-      infile = *polyfile;
-    } else {
-      // If the .poly file claims there are zero points, that means that
-      //   the points should be read from a separate .node file.
-      readnodefile = 1;
-      infilename = innodefilename;
-    }
-  } else {
-    readnodefile = 1;
-    infilename = innodefilename;
-    *polyfile = (FILE *) NULL;
-  }
-
-  if (readnodefile) {
-    // Read the points from a .node file.
-    if (!quiet) {
-      printf("Opening %s.\n", innodefilename);
-    }
-    infile = fopen(innodefilename, "r");
-    if (infile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
-      exit(1);
-    }
-    // Read number of points, number of dimensions, number of point
-    //   attributes, and number of boundary markers.
-    stringptr = readline(inputline, infile, innodefilename);
-    inpoints = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      mesh_dim = 3;
-    } else {
-      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      nextras = 0;
-    } else {
-      nextras = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      nodemarkers = 0;
-    } else {
-      nodemarkers = (int) strtol (stringptr, &stringptr, 0);
-    }
-  }
-
-  if (inpoints < 4) {
-    printf("Error:  Input must have at least four input points.\n");
-    exit(1);
-  }
-  if (mesh_dim != 3) {
-    printf("Error:  This program only works with three-dimensional meshes.\n");
-    exit(1);
-  }
-
-  initializepointpool();
-
-  // Read the points.
-  for (i = 0; i < inpoints; i++) {
-    pointloop = (point3d) points.alloc();
-    stringptr = readline(inputline, infile, infilename);
-    if (i == 0) {
-      firstnode = (int) strtol (stringptr, &stringptr, 0);
-      if ((firstnode == 0) || (firstnode == 1)) {
-        firstnumber = firstnode;
-      }
-    }
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      printf("File I/O Error:  Point %d has no x coordinate.\n",
-             firstnumber + i);
-      exit(1);
-    }
-    x = (REAL) strtod(stringptr, &stringptr);
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      printf("File I/O Error:  Point %d has no y coordinate.\n",
-             firstnumber + i);
-      exit(1);
-    }
-    y = (REAL) strtod(stringptr, &stringptr);
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      printf("File I/O Error:  Point %d has no z coordinate.\n",
-             firstnumber + i);
-      exit(1);
-    }
-    z = (REAL) strtod(stringptr, &stringptr);
-    pointloop[0] = x;
-    pointloop[1] = y;
-    pointloop[2] = z;
-    // Read the point attributes.
-    for (j = 3; j < 3 + nextras; j++) {
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        pointloop[j] = 0.0;
-      } else {
-        pointloop[j] = (REAL) strtod(stringptr, &stringptr);
-      }
-    }
-    if (nodemarkers) {
-      // Read a point marker.
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        setpointmark(pointloop, 0);
-      } else {
-        currentmarker = (int) strtol (stringptr, &stringptr, 0);
-        setpointmark(pointloop, currentmarker);
-      }
-    } else {
-      // If no markers are specified in the file, they default to zero.
-      setpointmark(pointloop, 0);
-    }
-    // Determine the smallest and largest x and y coordinates.
-    if (i == 0) {
-      xmin = xmax = x;
-      ymin = ymax = y;
-      zmin = zmax = z;
-    } else {
-      xmin = (x < xmin) ? x : xmin;
-      xmax = (x > xmax) ? x : xmax;
-      ymin = (y < ymin) ? y : ymin;
-      ymax = (y > ymax) ? y : ymax;
-      zmin = (z < ymin) ? z : zmin;
-      zmax = (z > zmax) ? z : zmax;
-    }
-  }
-  if (readnodefile) {
-    fclose(infile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// readholes()   Read the holes, and possibly regional attributes and volume //
-//               constraints, from a .poly file.                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::readholes(FILE *polyfile, REAL **hlist, int *holes, REAL **rlist,
-                       int *regions)
-{
-  REAL *holelist;
-  REAL *regionlist;
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-  int index;
-  int i;
-
-  // Read the holes.
-  if (poly || smesh) {
-    stringptr = readline(inputline, polyfile, inpolyfilename);
-    *holes = (int) strtol (stringptr, &stringptr, 0);
-  } else {
-    // There need not hole section in smesh file format.
-    *holes = 0;
-  }
-  if (*holes > 0) {
-    holelist = (REAL *) new REAL[3 * *holes];
-    *hlist = holelist;
-    for (i = 0; i < 3 * *holes; i += 3) {
-      stringptr = readline(inputline, polyfile, inpolyfilename);
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        printf("File I/O Error:  Hole %d has no x coordinate.\n",
-               firstnumber + (i / 3));
-        exit(1);
-      } else {
-        holelist[i] = (REAL) strtod(stringptr, &stringptr);
-      }
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        printf("File I/O Error:  Hole %d has no y coordinate.\n",
-               firstnumber + (i / 3));
-        exit(1);
-      } else {
-        holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
-      }
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        printf("File I/O Error:  Hole %d has no z coordinate.\n",
-               firstnumber + (i / 3));
-        exit(1);
-      } else {
-        holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
-      }
-    }
-  } else {
-    *hlist = (REAL *) NULL;
-  }
-
-  if ((regionattrib || varvolume) && !refine) {
-    // Read the volume constraints.
-    stringptr = readline(inputline, polyfile, inpolyfilename);
-    *regions = (int) strtol (stringptr, &stringptr, 0);
-    if (*regions > 0) {
-      regionlist = (REAL *) new REAL[5 * *regions];
-      *rlist = regionlist;
-      index = 0;
-      for (i = 0; i < *regions; i++) {
-        stringptr = readline(inputline, polyfile, inpolyfilename);
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          printf("File I/O Error:  Region %d has no x coordinate.\n",
-                 firstnumber + i);
-          exit(1);
-        } else {
-          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          printf("File I/O Error:  Region %d has no y coordinate.\n",
-                 firstnumber + i);
-          exit(1);
-        } else {
-          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          printf("File I/O Error:  Region %d has no z coordinate.\n",
-                 firstnumber + i);
-          exit(1);
-        } else {
-          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          printf("File I/O Error:  Region %d has no region attribute or",
-                 firstnumber + i);
-          printf(" volume constraint.\n");
-          exit(1);
-        } else {
-          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          regionlist[index] = regionlist[index - 1];
-        } else {
-          regionlist[index] = (REAL) strtod(stringptr, &stringptr);
-        }
-        index++;
-      }
-    }
-  } else {
-    // Set `*regions' to zero to avoid an accidental free() later.
-    *regions = 0;
-    *rlist = (REAL *) NULL;
-  }
-
-  fclose(polyfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outnodes()    Number the points and write them to a .node file.           //
-//                                                                           //
-// To save memory, the point numbers are written over the shell markers      //
-// after the points are written to a file.                                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::outnodes()
-{
-  FILE *outfile;
-  point3d pointloop;
-  int pointnumber;
-  int i;
-
-  if (!quiet) {
-    printf("Writing %s.\n", outnodefilename);
-  }
-  outfile = fopen(outnodefilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", outnodefilename);
-    exit(1);
-  }
-  // Number of points, number of dimensions, number of point attributes,
-  //   and number of boundary markers (zero or one).
-  fprintf(outfile, "%ld  %d  %d  %d\n", points.items, mesh_dim, nextras,
-          1 - nobound);
-
-  points.traversalinit();
-  pointloop = pointtraverse();
-  pointnumber = firstnumber;
-  while (pointloop != (point3d) NULL) {
-    // Point number, x, y and z coordinates.
-    fprintf(outfile, "%4d    %.17g  %.17g  %.17g", pointnumber, pointloop[0],
-            pointloop[1], pointloop[2]);
-    for (i = 0; i < nextras; i++) {
-      // Write an attribute.
-      fprintf(outfile, "  %.17g", pointloop[i + 3]);
-    }
-    if (nobound) {
-      fprintf(outfile, "\n");
-    } else {
-      // Write the boundary marker.
-      fprintf(outfile, "    %d\n", pointmark(pointloop));
-    }
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-
-  fprintf(outfile, "# Generated by %s\n", commandline);
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// numbernodes()    Number the points.                                       //
-//                                                                           //
-// Each point is assigned a marker equal to its number.                      //
-//                                                                           //
-// Used when outnodes() is not called because no .node file is written.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::numbernodes(int myfirstnumber)
-{
-  point3d pointloop;
-  int pointnumber;
-
-  points.traversalinit();
-  pointloop = pointtraverse();
-  if (!myfirstnumber) {
-    pointnumber = firstnumber;
-  } else {
-    pointnumber = myfirstnumber;
-  }
-  while (pointloop != (point3d) NULL) {
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outelems()     Write the tetrahedra to an .ele file.                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::outelems()
-{
-  FILE *outfile;
-  tetrahedron* tptr;
-  point3d p1, p2, p3, p4;
-  int elementnumber;
-  int i;
-
-  if (!quiet) {
-    printf("Writing %s.\n", outelefilename);
-  }
-  outfile = fopen(outelefilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", outelefilename);
-    exit(1);
-  }
-  // Number of tetras, points per tetra, attributes per tetra.
-  fprintf(outfile, "%ld  %d  %d\n", tetrahedrons.items, 4, eextras);
-
-  tetrahedrons.traversalinit();
-  tptr = tetrahedrontraverse();
-  elementnumber = firstnumber;
-  while (tptr != (tetrahedron *) NULL) {
-    p1 = (point3d) tptr[4];
-    p2 = (point3d) tptr[5];
-    p3 = (point3d) tptr[6];
-    p4 = (point3d) tptr[7];
-    // Triangle number, indices for three points.
-    fprintf(outfile, "%5d   %5d %5d %5d %5d", elementnumber,
-            pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
-    for (i = 0; i < eextras; i++) {
-      fprintf(outfile, "    %.17g", elemattribute(tptr, i));
-    }
-    fprintf(outfile, "\n");
-    tptr = tetrahedrontraverse();
-    elementnumber++;
-  }
-
-  fprintf(outfile, "# Generated by %s\n", commandline);
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outelems2gid()    Generate mesh files for viewing by Gid.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::outelems2gid()
-{
-  FILE *outfile;
-  char gidfilename[FILENAMESIZE];
-  tetrahedron* tetptr;
-  point3d pointloop, p1, p2, p3, p4;;
-  int pointnumber, elementnumber;
-  int i;
-
-  strcpy(gidfilename, outelefilename);
-  strcat(gidfilename, ".gid");
-
-  if (!quiet) {
-    printf("Writing %s.\n", gidfilename);
-  }
-  outfile = fopen(gidfilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", gidfilename);
-    return;
-  }
-
-  fprintf(outfile, "mesh dimension = 3 elemtype tetrahedron nnode = 4\n");
-  fprintf(outfile, "coordinates\n");
-
-  points.traversalinit();
-  pointloop = pointtraverse();
-  pointnumber = 1;  // Gid mesh reader must need first number be '1'.
-  while (pointloop != (point3d) NULL) {
-    // Point number, x , y and z coordinates.
-    fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber, pointloop[0],
-            pointloop[1], pointloop[2]);
-    for (i = 0; i < nextras; i++) {
-      // Write an attribute.
-      fprintf(outfile, " %.17g", pointloop[i + 3]);
-    }
-    if (nobound) {
-      fprintf(outfile, "\n");
-    } else {
-      // Write the boundary marker.
-      fprintf(outfile, "    %d\n", pointmark(pointloop));
-    }
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-
-  fprintf(outfile, "end coordinates\n");
-  fprintf(outfile, "elements\n");
-
-  tetrahedrons.traversalinit();
-  tetptr = tetrahedrontraverse();
-  elementnumber = 1;
-  while (tetptr != (tetrahedron *) NULL) {
-    p1 = (point3d) tetptr[4];
-    p2 = (point3d) tetptr[5];
-    p3 = (point3d) tetptr[6];
-    p4 = (point3d) tetptr[7];
-    // tetrahedron number, indices for four points.
-    fprintf(outfile, "%5d  %5d %5d %5d %5d", elementnumber,
-            pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
-
-    for (i = 0; i < eextras; i++) {
-      fprintf(outfile, "  %.17g", elemattribute(tetptr, i));
-    }
-    fprintf(outfile, "\n");
-
-    tetptr = tetrahedrontraverse();
-    elementnumber++;
-  }
-
-  fprintf(outfile, "end elements\n");
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outelems2fa()    Generate mesh files for viewing by FA.                   //
-//                                                                           //
-// There need three files: .prj, .cor and .elm for FA.                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::outelems2fa()
-{
-  FILE *outfile;
-  char fafilename[FILENAMESIZE];
-  tetrahedron* tetptr;
-  point3d pointloop, p1, p2, p3, p4;;
-  int pointnumber, elementnumber;
-  int i;
-
-  strcpy(fafilename, outelefilename);
-  strcat(fafilename, ".prj");
-
-  if (!quiet) {
-    printf("Writing %s.\n", fafilename);
-  }
-  outfile = fopen(fafilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", fafilename);
-    return;
-  }
-  fprintf(outfile, "%s\n", outelefilename);
-  fprintf(outfile, "0\n0\n0\n");
-  fclose(outfile);
-
-  strcpy(fafilename, outelefilename);
-  strcat(fafilename, ".cor");
-
-  if (!quiet) {
-    printf("Writing %s.\n", fafilename);
-  }
-  outfile = fopen(fafilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", fafilename);
-    return;
-  }
-  fprintf(outfile, "%d    3\n", points.items);
-
-  points.traversalinit();
-  pointloop = pointtraverse();
-  pointnumber = 1;  // FA mesh reader must need first number be '1'.
-  while (pointloop != (point3d) NULL) {
-    // Point number, x , y and z coordinates.
-    fprintf(outfile, "%.17g %.17g %.17g\n", pointloop[0],
-            pointloop[1], pointloop[2]);
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-  fclose(outfile);
-
-  strcpy(fafilename, outelefilename);
-  strcat(fafilename, ".elm");
-
-  if (!quiet) {
-    printf("Writing %s.\n", fafilename);
-  }
-  outfile = fopen(fafilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", fafilename);
-    return;
-  }
-  fprintf(outfile, "%d    5\n", tetrahedrons.items);
-
-  tetrahedrons.traversalinit();
-  tetptr = tetrahedrontraverse();
-  elementnumber = 1;
-  while (tetptr != (tetrahedron *) NULL) {
-    p1 = (point3d) tetptr[4];
-    p2 = (point3d) tetptr[5];
-    p3 = (point3d) tetptr[6];
-    p4 = (point3d) tetptr[7];
-    // tetrahedron number, indices for four points.
-    fprintf(outfile, "%5d %5d %5d %5d",
-            pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
-    if (eextras > 0) {
-      fprintf(outfile, "  %.17g", elemattribute(tetptr, 0) + 1);
-    } else {
-      fprintf(outfile, "  1");
-    }
-    fprintf(outfile, "\n");
-
-    tetptr = tetrahedrontraverse();
-    elementnumber++;
-  }
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outfaces()    Write the faces to a .face file.                            //
-//                                                                           //
-// Also use this routine to output hull faces(when hull = 1).                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::outfaces(int hull)
-{
-  FILE *outfile;
-  triface tface, tsymface;
-  face checkmark;
-  point3d torg, tdest, tapex;
-  int facenumber;
-
-  if (!quiet) {
-    printf("Writing %s.\n", facefilename);
-  }
-  outfile = fopen(facefilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", facefilename);
-    exit(1);
-  }
-  // Number of faces, number of boundary markers (zero or one).
-  if (hull) {
-    fprintf(outfile, "%ld  %d\n", hullsize, 1 - nobound);
-  } else {
-    fprintf(outfile, "%ld  %d\n", faces, 1 - nobound);
-  }
-
-  tetrahedrons.traversalinit();
-  tface.tet = tetrahedrontraverse();
-  facenumber = firstnumber;
-  // To loop over the set of faces, loop over all tetrahedrons, and look at
-  //   the four faces of each tetrahedron. If there isn't another
-  //   tetrahedron adjacent to the face, operate on the face.  If there is
-  //   another adjacent tetrahedron, operate on the face only if the current
-  //   tetrahedron has a smaller pointer than its neighbor.  This way, each
-  //   face is considered only once.
-  // If the 'hull' flag is set, only operate on faces which neighbour is
-  //   'dummytet'. This will only output hull faces.
-  while (tface.tet != (tetrahedron *) NULL) {
-    for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
-      sym(tface, tsymface);
-      if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
-        org (tface, torg);
-        dest(tface, tdest);
-        apex(tface, tapex);
-        if (hull) {
-          if (tsymface.tet == dummytet) {
-            // Only output hull faces.
-            fprintf(outfile, "%5d   %4d  %4d  %4d\n", facenumber,
-                    pointmark(torg), pointmark(tdest), pointmark(tapex));
-            facenumber++;
-          }
-        } else {
-          if (nobound) {
-            // Face number, indices of three vertexs.
-            fprintf(outfile, "%5d   %4d  %4d  %4d\n", facenumber,
-                    pointmark(torg), pointmark(tdest), pointmark(tapex));
-          } else {
-            // Face number, indices of three vertexs, and a boundary marker.
-            //   If there's no shell face, the boundary marker is zero.
-            if (useshelles) {
-              tspivot(tface, checkmark);
-              if ((checkmark.sh == dummysh) || isnonsolid(checkmark)) {
-                fprintf(outfile, "%5d   %4d  %4d  %4d  %4d\n", facenumber,
-                        pointmark(torg), pointmark(tdest), pointmark(tapex), 0);
-              } else {
-                fprintf(outfile, "%5d   %4d  %4d  %4d  %4d\n", facenumber,
-                        pointmark(torg), pointmark(tdest), pointmark(tapex),
-                        mark(checkmark));
-              }
-            } else {
-              fprintf(outfile, "%5d   %4d  %4d  %4d  %4d\n", facenumber,
-                      pointmark(torg), pointmark(tdest), pointmark(tapex),
-                      tsymface.tet == dummytet);
-            }
-          }
-          facenumber++;
-        }
-      }
-    }
-    tface.tet = tetrahedrontraverse();
-  }
-
-  fprintf(outfile, "# Generated by %s\n", commandline);
-  fclose(outfile);
-}
-
-void mesh3d::outfaces2gid(int hull)
-{
-  FILE *outfile;
-  char gidfilename[FILENAMESIZE];
-  triface tface, tsymface;
-  face checkmark;
-  point3d pointloop, torg, tdest, tapex;
-  int pointnumber, facenumber, i;
-
-  strcpy(gidfilename, facefilename);
-  strcat(gidfilename, ".gid");
-
-  if (!quiet) {
-    printf("Writing %s.\n", gidfilename);
-  }
-  outfile = fopen(gidfilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", gidfilename);
-    return;
-  }
-
-  fprintf(outfile, "mesh dimension = 3 elemtype triangle nnode = 3\n");
-  fprintf(outfile, "coordinates\n");
-
-  points.traversalinit();
-  pointloop = pointtraverse();
-  pointnumber = 1;  // Gid mesh reader must need first number be '1'.
-  while (pointloop != (point3d) NULL) {
-    // Point number, x , y and z coordinates.
-    fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber, pointloop[0],
-            pointloop[1], pointloop[2]);
-    for (i = 0; i < nextras; i++) {
-      // Write an attribute.
-      fprintf(outfile, " %.17g", pointloop[i + 3]);
-    }
-    if (nobound) {
-      fprintf(outfile, "\n");
-    } else {
-      // Write the boundary marker.
-      fprintf(outfile, "    %d\n", pointmark(pointloop));
-    }
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-
-  fprintf(outfile, "end coordinates\n");
-  fprintf(outfile, "elements\n");
-
-  tetrahedrons.traversalinit();
-  tface.tet = tetrahedrontraverse();
-  facenumber = 1;
-  // To loop over the set of faces, loop over all tetrahedra, and look at
-  //   the four faces of each tetrahedron. If there isn't another tetrahedron
-  //   adjacent to the face, operate on the face.  If there is another adj-
-  //   acent tetrahedron, operate on the face only if the current tetrahedron
-  //   has a smaller pointer than its neighbor.  This way, each face is
-  //   considered only once.
-  // If the 'hull' flag is set, only operate on faces which neighbour is
-  //   'dummytet'. This will only output hull faces.
-  while (tface.tet != (tetrahedron *) NULL) {
-    for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
-      sym(tface, tsymface);
-      if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
-        org (tface, torg);
-        dest(tface, tdest);
-        apex(tface, tapex);
-        if (hull) {
-          if (tsymface.tet == dummytet) {
-            // Only output hull faces.
-            fprintf(outfile, "%5d   %d  %d  %d\n", facenumber,
-                    pointmark(torg), pointmark(tdest), pointmark(tapex));
-            facenumber++;
-          }
-        } else {
-          if (nobound) {
-            // Face number, indices of three vertexs.
-            fprintf(outfile, "%5d   %d  %d  %d\n", facenumber,
-                    pointmark(torg), pointmark(tdest), pointmark(tapex));
-          } else {
-            // Face number, indices of three vertexs, and a boundary marker.
-            //   If there's no shell face, the boundary marker is zero.
-            if (useshelles) {
-              tspivot(tface, checkmark);
-              if (checkmark.sh == dummysh) {
-                fprintf(outfile, "%5d   %d  %d  %d  %d\n", facenumber,
-                        pointmark(torg), pointmark(tdest), pointmark(tapex), 0);
-              } else {
-                fprintf(outfile, "%5d   %d  %d  %d  %d\n", facenumber,
-                        pointmark(torg), pointmark(tdest), pointmark(tapex),
-                        mark(checkmark));
-              }
-            } else {
-              fprintf(outfile, "%5d   %d  %d  %d  %d\n", facenumber,
-                      pointmark(torg), pointmark(tdest), pointmark(tapex),
-                      tsymface.tet == dummytet);
-            }
-          }
-          facenumber++;
-        }
-      }
-    }
-    tface.tet = tetrahedrontraverse();
-  }
-
-  fprintf(outfile, "end elements\n");
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outedges()    Write the edges (segments) to a .edge file.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::outedges()
-{
-  FILE *outfile;
-  face segloop;
-  point3d torg, tdest;
-  int edgenumber;
-
-  if (!quiet) {
-    printf("Writing %s.\n", edgefilename);
-  }
-  outfile = fopen(edgefilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
-    exit(1);
-  }
-  // Number of edges.
-  fprintf(outfile, "%ld\n", subsegs.items);
-
-  subsegs.traversalinit();
-  segloop.sh = shellfacetraverse(&subsegs);
-  edgenumber = firstnumber;
-  while (segloop.sh != (shellface*) NULL) {
-    torg = sorg(segloop);
-    tdest = sdest(segloop);
-    fprintf(outfile, "%5d   %4d  %4d\n", edgenumber,
-            pointmark(torg), pointmark(tdest));
-    edgenumber++;
-    segloop.sh = shellfacetraverse(&subsegs);
-  }
-
-  fprintf(outfile, "# Generated by %s\n", commandline);
-  fclose(outfile);
-}
-
-void mesh3d::outedges2gid()
-{
-  FILE *outfile;
-  char gidfilename[FILENAMESIZE];
-  face segloop;
-  point3d pointloop, torg, tdest;
-  int pointnumber, edgenumber, i;
-
-  strcpy(gidfilename, edgefilename);
-  strcat(gidfilename, ".gid");
-
-  if (!quiet) {
-    printf("Writing %s.\n", gidfilename);
-  }
-  outfile = fopen(gidfilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", gidfilename);
-    return;
-  }
-
-  fprintf(outfile, "MESH    dimension 3 ElemType Linear  Nnode 2\n");
-  fprintf(outfile, "Coordinates\n");
-
-  points.traversalinit();
-  pointloop = pointtraverse();
-  pointnumber = 1;  // Gid mesh reader must need first number be '1'.
-  while (pointloop != (point3d) NULL) {
-    // Point number, x , y and z coordinates.
-    fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber, pointloop[0],
-            pointloop[1], pointloop[2]);
-    for (i = 0; i < nextras; i++) {
-      // Write an attribute.
-      fprintf(outfile, " %.17g", pointloop[i + 3]);
-    }
-    if (nobound) {
-      fprintf(outfile, "\n");
-    } else {
-      // Write the boundary marker.
-      fprintf(outfile, "    %d\n", pointmark(pointloop));
-    }
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-
-  fprintf(outfile, "end coordinates\n");
-  fprintf(outfile, "Elements\n");
-
-  subsegs.traversalinit();
-  segloop.sh = shellfacetraverse(&subsegs);
-  edgenumber = firstnumber;
-  while (segloop.sh != (shellface*) NULL) {
-    torg = sorg(segloop);
-    tdest = sdest(segloop);
-    fprintf(outfile, "%5d   %4d  %4d\n", edgenumber,
-            pointmark(torg), pointmark(tdest));
-    edgenumber++;
-    segloop.sh = shellfacetraverse(&subsegs);
-  }
-
-  fprintf(outfile, "end elements\n");
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outneighbors()    Write neighbor elems to file *.neigh                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::outneighbors()
-{
-  FILE *outfile;
-  tetrahedron *tptr;
-  triface tetloop, tetsym;
-  int elementnumber;
-  int neighbor1, neighbor2, neighbor3, neighbor4;
-
-  if (!quiet) {
-    printf("Writing %s.\n", neighborfilename);
-  }
-  outfile = fopen(neighborfilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", neighborfilename);
-    exit(1);
-  }
-  // Number of tetrahedra, four faces per tetrahedron.
-  fprintf(outfile, "%ld  %d\n", tetrahedrons.items, 4);
-
-  tetrahedrons.traversalinit();
-  tptr = tetrahedrontraverse();
-  elementnumber = firstnumber;
-  while (tptr != (tetrahedron *) NULL) {
-    * (int *) (tptr + 8) = elementnumber;
-    tptr = tetrahedrontraverse();
-    elementnumber++;
-  }
-  * (int *) (dummytet + 8) = -1;
-
-  tetrahedrons.traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  elementnumber = firstnumber;
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    tetloop.loc = 0;
-    sym(tetloop, tetsym);
-    neighbor1 = * (int *) (tetsym.tet + 8);
-    tetloop.loc = 1;
-    sym(tetloop, tetsym);
-    neighbor2 = * (int *) (tetsym.tet + 8);
-    tetloop.loc = 2;
-    sym(tetloop, tetsym);
-    neighbor3 = * (int *) (tetsym.tet + 8);
-    tetloop.loc = 3;
-    sym(tetloop, tetsym);
-    neighbor4 = * (int *) (tetsym.tet + 8);
-    // Tetrahedra number, neighboring tetrahedron numbers.
-    fprintf(outfile, "%4d    %4d  %4d  %4d  %4d\n", elementnumber,
-            neighbor1, neighbor2, neighbor3, neighbor4);
-    tptr = tetrahedrontraverse();
-    elementnumber++;
-  }
-
-  fprintf(outfile, "# Generated by %s\n", commandline);
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-//  outoff()    Write the triangulation to an .off file.                     //
-//                                                                           //
-//  OFF stands for the Object File Format, a format used by the Geometry     //
-//  Center's Geomview package.                                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::outoff()
-{
-  FILE *outfile;
-  triface tface, tsymface;
-  point3d pointloop;
-  point3d torg, tdest, tapex;
-
-  if (!quiet) {
-    printf("Writing %s.\n", offfilename);
-  }
-  outfile = fopen(offfilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", offfilename);
-    exit(1);
-  }
-  // Number of points, faces, and edges(not used, here show hullsize).
-  fprintf(outfile, "OFF\n%ld  %ld  %ld\n", points.items, faces, hullsize);
-
-  // Write the points.
-  points.traversalinit();
-  pointloop = pointtraverse();
-  while (pointloop != (point3d) NULL) {
-    fprintf(outfile, " %.17g  %.17g  %.17g\n", pointloop[0],
-            pointloop[1], pointloop[2]);
-    pointloop = pointtraverse();
-  }
-
-  tetrahedrons.traversalinit();
-  tface.tet = tetrahedrontraverse();
-  // To loop over the set of faces, loop over all tetrahedra, and look at
-  //   the four faces of each tetrahedron. If there isn't another tetrahedron
-  //   adjacent to the face, operate on the face.  If there is another adj-
-  //   acent tetrahedron, operate on the face only if the current tetrahedron
-  //   has a smaller pointer than its neighbor.  This way, each face is
-  //   considered only once.
-  // If the 'hull' flag is set, only operate on faces which neighbour is
-  //   'dummytet'. This will only output hull faces.
-  while (tface.tet != (tetrahedron *) NULL) {
-    for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
-      sym(tface, tsymface);
-      if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
-        org (tface, torg);
-        dest(tface, tdest);
-        apex(tface, tapex);
-        // Face number, indices of three vertexs.
-        fprintf(outfile, "3   %4d  %4d  %4d\n", pointmark(torg) - 1,
-                pointmark(tdest) - 1, pointmark(tapex) - 1);
-      }
-    }
-    tface.tet = tetrahedrontraverse();
-  }
-
-  fprintf(outfile, "# Generated by %s\n", commandline);
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dumpallbadelems()    Output all bad elements.                             //
-//                                                                           //
-// Bad elements include Sliver, Cap, Wedge, Spindle, Needle.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::dumpallbadelems(char* badelemfilename)
-{
-  FILE *outfile;
-  tetrahedron* tetptr;
-  point3d pointloop, p1, p2, p3, p4;
-  REAL alldihed[6], allsolid[4];
-  REAL smallsolid, largesolid;
-  REAL smalldihed, largedihed;
-  REAL smallestdiangle, biggestdiangle;
-  int pointnumber, elementnumber;
-  int smalldihedcount, largedihedcount;
-  int smallsolidcount, largesolidcount;
-  int elemtype;
-  int i;
-
-  if (!quiet) {
-    printf("Writing %s.\n", badelemfilename);
-  }
-  outfile = fopen(badelemfilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", badelemfilename);
-    return;
-  }
-  smallsolid = 3.;
-  largesolid = 300.;
-  smalldihed = 20.;
-  largedihed = 160.;
-
-  fprintf(outfile, "mesh dimension = 3 elemtype tetrahedron nnode = 4\n");
-  fprintf(outfile, "coordinates\n");
-
-  points.traversalinit();
-  pointloop = pointtraverse();
-  pointnumber = 1;  // Gid mesh reader must need first number be '1'.
-  while (pointloop != (point3d) NULL) {
-    // Point number, x , y and z coordinates.
-    fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber, pointloop[0],
-            pointloop[1], pointloop[2]);
-    for (i = 0; i < nextras; i++) {
-      // Write an attribute.
-      fprintf(outfile, " %.17g", pointloop[i + 3]);
-    }
-    if (nobound) {
-      fprintf(outfile, "\n");
-    } else {
-      // Write the boundary marker.
-      fprintf(outfile, "    %d\n", pointmark(pointloop));
-    }
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-
-  fprintf(outfile, "end coordinates\n");
-  fprintf(outfile, "elements\n");
-
-  tetrahedrons.traversalinit();
-  tetptr = tetrahedrontraverse();
-  elementnumber = 1;
-  while (tetptr != (tetrahedron *) NULL) {
-    p1 = (point3d) tetptr[4];
-    p2 = (point3d) tetptr[5];
-    p3 = (point3d) tetptr[6];
-    p4 = (point3d) tetptr[7];
-
-    tetalldihedral(p1, p2, p3, p4, alldihed);
-    smalldihedcount = largedihedcount = 0;
-    smallestdiangle = 180;
-    biggestdiangle = 0;
-    for (i = 0; i < 6; i++) {
-      if (alldihed[i] < smallestdiangle) {
-        smallestdiangle = alldihed[i];
-      } else if (alldihed[i] > biggestdiangle) {
-        biggestdiangle = alldihed[i];
-      }
-      if (alldihed[i] < smalldihed) {
-        smalldihedcount++;
-      } else if (alldihed[i] > largedihed) {
-        largedihedcount++;
-      }
-    }
-    allsolid[0] = alldihed[0] + alldihed[1] + alldihed[2] - 180;
-    allsolid[1] = alldihed[0] + alldihed[3] + alldihed[4] - 180;
-    allsolid[2] = alldihed[1] + alldihed[3] + alldihed[5] - 180;
-    allsolid[3] = alldihed[2] + alldihed[4] + alldihed[5] - 180;
-    smallsolidcount = largesolidcount = 0;
-    for (i = 0; i < 4; i++) {
-      if (allsolid[i] < smallsolid) {
-        smallsolidcount++;
-      } else if (allsolid[i] > largesolid) {
-        largesolidcount++;
-      }
-    }
-    if (largesolidcount >= 1) {
-      elemtype = 1; // capcount++;
-    } else if ((largedihedcount > 0) && (smalldihedcount > 0)) {
-      elemtype = 2; // slivercount++;
-    } else if (largedihedcount > 0) {
-      elemtype = 3; // spindlecount++;
-    } else if (smalldihedcount > 0) {
-      elemtype = 4; // wedgecount++;
-    } else if (smallsolidcount > 0) {
-      elemtype = 5; // needlecount++;
-    } else {
-      elemtype = 0; // roundcount++;
-    }
-
-    if (elemtype) {
-      // tetrahedron number, indices for four points.
-      fprintf(outfile, "%5d  %5d %5d %5d %5d  %10.6g %10.6g", elementnumber,
-              pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4),
-              smallestdiangle, biggestdiangle);
-      if (elemtype == 1) {
-        fprintf(outfile, "      Cap");
-      } else if (elemtype == 2) {
-        fprintf(outfile, "      Sliver");
-      } else if (elemtype == 3) {
-        fprintf(outfile, "      Spindle");
-      } else if (elemtype == 4) {
-        fprintf(outfile, "      Wedge");
-      } else if (elemtype == 5) {
-        fprintf(outfile, "      Needle");
-      }
-      fprintf(outfile, "\n");
-    }
-
-    tetptr = tetrahedrontraverse();
-    elementnumber++;
-  }
-
-  fprintf(outfile, "end elements\n");
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// END                                                                       //
-// File I/O Routines                                                         //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// internalerror()    Ask the user to send me the defective product.  Exit.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::internalerror()
-{
-  printf("  Please report this bug to sihang@weboo.com. Include the\n");
-  printf("    message above, your input data set, and the exact command\n");
-  printf("    line you used to run this program, thank you.\n");
-  exit(1);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// precisionerror()    Print an error message for precision problems.        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::precisionerror()
-{
-  if (noexact) {
-    printf("  This problem maybe caused by the approximate floating-point\n");
-    printf("    arthmetic. Try use -X switch in commandline and try again.\n");
-  } else {
-    printf("  Try increasing the volume criterion and/or increasing the\n");
-    printf("    minimum allowable radius-edge ratio so that tiny tetrahedra\n");
-    printf("    are not created.\n");
-  }
-#ifdef SINGLE
-  printf("  Alternatively, try recompiling me with double precision\n");
-  printf("    arithmetic (by removing \"#define SINGLE\" from the\n");
-  printf("    source file or \"-DSINGLE\" from the makefile).\n");
-#endif // SINGLE
-  exit(1);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// recovererror()      Print an error message for recover problems.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::recovererror()
-{
-  printf("  You met a recover problem in your model. Please check your\n");
-  printf("    input PLC facet data, make sure that all coplanar segments,\n");
-  printf("    polygons and isolated points are list in this facet.\n");
-  printf("  If there still has problem, please report this bug to \n");
-  printf("    sihang@weboo.com. Include the message above, your input data\n");
-  printf("    set, and the exact command line you used to run this program,\n");
-  printf("    thank you.\n");
-  exit(1);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checkmesh()    Test the mesh for topological consistency.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::checkmesh()
-{
-  triface tetraloop;
-  triface oppotet, oppooppotet;
-  point3d tetorg, tetdest, tetapex, tetoppo;
-  point3d oppoorg, oppodest, oppoapex;
-  int horrors;
-  int saveexact;
-
-  // Temporarily turn on exact arithmetic if it's off.
-  saveexact = noexact;
-  noexact = 0;
-  if (!quiet) {
-    printf("  Checking consistency of mesh...\n");
-  }
-  if (verbose < 1) {
-    numbernodes(1);
-  }
-  horrors = 0;
-  // Run through the list of tetrahedra, checking each one.
-  tetrahedrons.traversalinit();
-  tetraloop.tet = tetrahedrontraverse();
-  while (tetraloop.tet != (tetrahedron *) NULL) {
-    // Check all four faces of the tetrahedron.
-    for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
-      org (tetraloop, tetorg);
-      dest(tetraloop, tetdest);
-      apex(tetraloop, tetapex);
-      oppo(tetraloop, tetoppo);
-      if (tetraloop.loc == 0) {             // Only test for inversion once.
-        if (orient3d(tetorg, tetdest, tetapex, tetoppo) >= 0.0) {
-          printf("  !! !! Inverted ");
-          dump(&tetraloop);
-          horrors++;
-        }
-      }
-      // Find the neighboring tetrahedron on this face.
-      sym(tetraloop, oppotet);
-      if (oppotet.tet != dummytet) {
-        // Check that the tetrahedron's neighbor knows it's a neighbor.
-        sym(oppotet, oppooppotet);
-        if ((tetraloop.tet != oppooppotet.tet)
-            || (tetraloop.loc != oppooppotet.loc)) {
-          printf("  !! !! Asymmetric tetra-tetra bond:\n");
-          if (tetraloop.tet == oppooppotet.tet) {
-            printf("   (Right tetrahedron, wrong orientation)\n");
-          }
-          printf("    First ");
-          dump(&tetraloop);
-          printf("    Second (nonreciprocating) ");
-          dump(&oppotet);
-          horrors++;
-        }
-        // Check that both tetrahedra agree on the identities
-        //   of their shared vertices.
-        if (findorg(&oppotet, tetorg)) {
-          dest(oppotet, oppodest);
-          apex(oppotet, oppoapex);
-        } else {
-          oppodest = (point3d) NULL;
-        }
-        if ((tetdest != oppoapex) || (tetapex != oppodest)) {
-          printf("  !! !! Mismatched face coordinates between two tetras:\n");
-          printf("    First mismatched ");
-          dump(&tetraloop);
-          printf("    Second mismatched ");
-          dump(&oppotet);
-          horrors++;
-        }
-      }
-    }
-    tetraloop.tet = tetrahedrontraverse();
-  }
-  if (horrors == 0) {
-    if (!quiet) {
-      printf("  In my studied opinion, the mesh appears to be consistent.\n");
-    }
-  } else if (horrors == 1) {
-    printf("  !! !! !! !! Precisely one festering wound discovered.\n");
-  } else {
-    printf("  !! !! !! !! %d abominations witnessed.\n", horrors);
-  }
-  // Restore the status of exact arithmetic.
-  noexact = saveexact;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checkdelaunay()    Ensure that the mesh is (constrained or conforming)    //
-//                    Delaunay.                                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::checkdelaunay()
-{
-  triface tetraloop;
-  triface oppotet;
-  face opposhelle;
-  point3d tetorg, tetdest, tetapex, tetoppo;
-  point3d oppooppo;
-  int shouldbedelaunay;
-  int horrors;
-  int saveexact;
-
-  // Temporarily turn on exact arithmetic if it's off.
-  saveexact = noexact;
-  noexact = 0;
-  if (!quiet) {
-    printf("  Checking Delaunay property of mesh...\n");
-  }
-  if (verbose < 1) {
-    numbernodes(1);
-  }
-  horrors = 0;
-  // Run through the list of triangles, checking each one.
-  tetrahedrons.traversalinit();
-  tetraloop.tet = tetrahedrontraverse();
-  while (tetraloop.tet != (tetrahedron *) NULL) {
-    // Check all three edges of the triangle.
-    for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
-      org(tetraloop, tetorg);
-      dest(tetraloop, tetdest);
-      apex(tetraloop, tetapex);
-      oppo(tetraloop, tetoppo);
-      sym(tetraloop, oppotet);
-      oppo(oppotet, oppooppo);
-      // Only test that the face is locally Delaunay if there is an
-      //   adjoining tetrahedron whose pointer is larger (to ensure that
-      //   each pair isn't tested twice).
-      shouldbedelaunay = (oppotet.tet != dummytet)
-                          && (tetoppo != (point3d) NULL)
-                          && (oppooppo != (point3d) NULL)
-                          && (tetraloop.tet < oppotet.tet);
-      if (checksegments && shouldbedelaunay) {
-        // If a shell edge separates the triangles, then the edge is
-        //   constrained, so no local Delaunay test should be done.
-        tspivot(tetraloop, opposhelle);
-        if (opposhelle.sh != dummysh){
-          if (!isnonsolid(opposhelle)) {
-            shouldbedelaunay = 0;
-          }
-        }
-      }
-      if (shouldbedelaunay) {
-        if (iinsphere(tetdest, tetorg, tetapex, tetoppo, oppooppo) > 0) {
-          printf("  !! !! Non-Delaunay pair of triangles:\n");
-          printf("    First non-Delaunay ");
-          dump(&tetraloop);
-          printf("    Second non-Delaunay ");
-          dump(&oppotet);
-          horrors++;
-        }
-      }
-    }
-    tetraloop.tet = tetrahedrontraverse();
-  }
-  if (horrors == 0) {
-    if (!quiet) {
-      printf(
-  "  By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
-    }
-  } else if (horrors == 1) {
-    printf(
-         "  !! !! !! !! Precisely one terrifying transgression identified.\n");
-  } else {
-    printf("  !! !! !! !! %d obscenities viewed with horror.\n", horrors);
-  }
-  // Restore the status of exact arithmetic.
-  noexact = saveexact;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checkshells()       Test the shells of mesh for topological consistency.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::checkshells()
-{
-  triface oppotet, oppooppotet;
-  triface testtet, spintet;
-  face shloop, testsh;
-  face segloop, testseg;
-  point3d tapex, spapex;
-  int hitbdry, edgecount;
-  int horrors;
-
-  if (!quiet) {
-    printf("  Checking subfaces-tetrahedra connection...\n");
-  }
-  if (verbose < 1) {
-    numbernodes(1);
-  }
-  horrors = 0;
-  subfaces.traversalinit();
-  shloop.sh = shellfacetraverse(&subfaces);
-  while (shloop.sh != (shellface *) NULL) {
-    shloop.shver = 0;
-    stpivot(shloop, oppotet);
-    if (oppotet.tet != dummytet) {
-      tspivot(oppotet, testsh);
-      if (testsh.sh != shloop.sh) {
-        printf("  !! !! Wrong tetra-subface connection.\n");
-        printf("    Tetra: ");
-        dump(&oppotet);
-        printf("    Subface: ");
-        dump(&shloop);
-        horrors++;
-      }
-    }
-    sesymself(shloop);
-    stpivot(shloop, oppooppotet);
-    if (oppooppotet.tet != dummytet) {
-      tspivot(oppooppotet, testsh);
-      if (testsh.sh != shloop.sh) {
-        printf("  !! !! Wrong tetra-subface connection.\n");
-        printf("    Tetra: ");
-        dump(&oppooppotet);
-        printf("    Subface: ");
-        dump(&shloop);
-        horrors++;
-      }
-      if (oppotet.tet != dummytet) {
-        sym(oppotet, testtet);
-        if (testtet.tet != oppooppotet.tet) {
-          printf("  !! !! Wrong tetra-subface-tetra connection.\n");
-          printf("    Tetra 1: ");
-          dump(&oppotet);
-          printf("    Subface: ");
-          dump(&shloop);
-          printf("    Tetra 2: ");
-          dump(&oppooppotet);
-          horrors++;
-        }
-      }
-    }
-    shloop.sh = shellfacetraverse(&subfaces);
-  }
-  if (horrors == 0) {
-    if (!quiet) {
-      printf("  Subfaces-tetrahedra connected correctly.\n");
-    }
-  } else if (horrors == 1) {
-    printf(
-    "  !! !! !! !! Precisely one terrifying subface-tetrahedron identified.\n");
-  } else {
-    printf("  !! !! !! !! %d subface-tetrahedron viewed with horror.\n",
-           horrors);
-    return;
-  }
-
-  if (!quiet) {
-    printf("  Checking Subfaces-subsegments connection...\n");
-  }
-  horrors = 0;
-  horrors = 0;
-  subfaces.traversalinit();
-  shloop.sh = shellfacetraverse(&subfaces);
-  while (shloop.sh != (shellface *) NULL) {
-    shloop.shver = 0;
-    for (edgecount = 0; edgecount < 3; edgecount++) {
-      senextself(shloop);
-      sspivot(shloop, testseg);
-      if (testseg.sh != dummysh) {
-        if (!((sorg(shloop) == sorg(testseg))
-              && (sdest(shloop) == sdest(testseg)))
-            && !((sorg(shloop) == sdest(testseg))
-                 && (sdest(shloop) == sorg(testseg)))) {
-          printf("  !! !! Wrong subface-subsegment connection.\n");
-          printf("    Subface: ");
-          dump(&shloop);
-          printf("    Subsegment: ");
-          dump(&testseg);
-          horrors++;
-        }
-      }
-    }
-    shloop.sh = shellfacetraverse(&subfaces);
-  }
-  if (horrors == 0) {
-    if (!quiet) {
-      printf("  Subfaces-subsegments connected correctly.\n");
-    }
-  } else if (horrors == 1) {
-    printf(
-    "  !! !! !! !! Precisely one terrifying subface-subsegments identified.\n");
-  } else {
-    printf("  !! !! !! !! %d subface-subsegments viewed with horror.\n",
-           horrors);
-    return;
-  }
-
-  if (!quiet) {
-    printf("  Checking Subsegments connection...\n");
-  }
-  horrors = 0;
-  subsegs.traversalinit();
-  segloop.sh = shellfacetraverse(&subsegs);
-  while (segloop.sh != (shellface *) NULL) {
-    segloop.shver = 0;
-    sapex(segloop, spapex);
-    if (spapex != (point3d) NULL) {
-      printf("  !! !! Detect a subface in subsegs pool(apex() != NULL).\n");
-      printf("    Wrong : ");
-      dump(&segloop);
-      horrors++;
-      segloop.sh = shellfacetraverse(&subsegs);
-      continue;
-    }
-    spivot(segloop, testsh);
-    if (testsh.sh == dummysh) {
-      printf("  !! !! A subsegment missing its parent subface.\n ");
-      printf("    Wrong : ");
-      dump(&segloop);
-      horrors++;
-      segloop.sh = shellfacetraverse(&subsegs);
-      continue;
-    }
-    sspivot(testsh, testseg);
-    if (testseg.sh != segloop.sh) {
-      printf("  !! !! Wrong subface-subsegment connection.\n ");
-      printf("    Wrong : ");
-      dump(&testsh);
-      printf("    Wrong : ");
-      dump(&segloop);
-      horrors++;
-      segloop.sh = shellfacetraverse(&subsegs);
-      continue;
-    }
-    stpivot(testsh, testtet);
-    if (testtet.tet == dummytet) {
-      sesymself(testsh);
-      stpivot(testsh, testtet);
-      if (testtet.tet == dummytet) {
-        printf("  !! !! Parent subface not bonded to a valid tetrahedron.\n ");
-        printf("    Wrong : ");
-        dump(&testsh);
-        horrors++;
-        segloop.sh = shellfacetraverse(&subsegs);
-        continue;
-      }
-    }
-    findversion(&testtet, &testseg);
-    spintet = testtet;
-    apex(testtet, tapex);
-    hitbdry = 0;
-    while (true) {
-      if (fnextself(spintet)) {
-        apex(spintet, spapex);
-        if (spapex == tapex) {
-          break; // Rewind, can leave now.
-        }
-        tspivot(spintet, testsh);
-        if (testsh.sh != dummysh) {
-          findversion(&testsh, &spintet);
-          sspivot(testsh, testseg);
-          if (testseg.sh == dummysh) {
-            printf("  !! !! Subface miss bond a subsegment.\n");
-            printf("    Miss bond : ");
-            dump(&testsh);
-            printf("    Miss : ");
-            dump(&segloop);
-            horrors++;
-          } else if (testseg.sh != segloop.sh) {
-            printf("  !! !! Wrong subface-subsegment bond.\n");
-            printf("    Wrong : ");
-            dump(&testsh);
-            printf("    Wrong : ");
-            dump(&segloop);
-            horrors++;
-          }
-        }
-      } else {
-        hitbdry ++;
-        if(hitbdry >= 2) {
-          break;
-        } else {
-          esym(testtet, spintet);
-        }
-      }
-    }
-    segloop.sh = shellfacetraverse(&subsegs);
-  }
-  if (horrors == 0) {
-    if (!quiet) {
-      printf("  Subsegments connected correctly.\n");
-    }
-  } else if (horrors == 1) {
-    printf(
-    "  !! !! !! !! Precisely one terrifying subsegment identified.\n");
-  } else {
-    printf("  !! !! !! !! %d subsegments viewed with horror.\n", horrors);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// quality_statistics()    Print statistics about the quality of the mesh.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::quality_statistics()
-{
-  triface tetloop;
-  point3d p[4];
-  REAL ratiotable[16];
-  REAL dx[6], dy[6], dz[6];
-  REAL edgelength[6];
-  REAL alldihed[6], allsolid[4];
-  REAL tetvol;
-  REAL tetlongest2;
-  REAL shortest, longest;
-  REAL smallestvolume, biggestvolume;
-  REAL tetminaltitude2;
-  REAL minaltitude;
-  REAL tetaspect2;
-  REAL worstaspect;
-  REAL smallestdiangle, biggestdiangle;
-  REAL smallsolid, largesolid;
-  REAL smalldihed, largedihed;
-  unsigned long roundcount, slivercount, capcount;
-  unsigned long needlecount, wedgecount, spindlecount;
-  int dihedangletable[18];
-  int aspecttable[16];
-  int aspectindex;
-  int tendegree;
-  int smallsolidcount, largesolidcount;
-  int smalldihedcount, largedihedcount;
-  int i, ii, j, k;
-
-  printf("Mesh quality statistics:\n\n");
-
-  ratiotable[0]  =      1.5;      ratiotable[1]  =     2.0;
-  ratiotable[2]  =      2.5;      ratiotable[3]  =     3.0;
-  ratiotable[4]  =      4.0;      ratiotable[5]  =     6.0;
-  ratiotable[6]  =     10.0;      ratiotable[7]  =    15.0;
-  ratiotable[8]  =     25.0;      ratiotable[9]  =    50.0;
-  ratiotable[10] =    100.0;      ratiotable[11] =   300.0;
-  ratiotable[12] =   1000.0;      ratiotable[13] = 10000.0;
-  ratiotable[14] = 100000.0;      ratiotable[15] =     0.0;
-  for (i = 0; i < 16; i++) {
-    aspecttable[i] = 0;
-  }
-  for (i = 0; i < 18; i++) {
-    dihedangletable[i] = 0;
-  }
-
-  worstaspect = 0.0;
-  minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
-  minaltitude = minaltitude * minaltitude;
-  shortest = minaltitude;
-  longest = 0.0;
-  smallestvolume = minaltitude;
-  biggestvolume = 0.0;
-  worstaspect = 0.0;
-  smallestdiangle = 180.0;
-  biggestdiangle = 0.0;
-  smallsolid = 3.;
-  largesolid = 300.;
-  smalldihed = 18.;
-  largedihed = 162.;
-  roundcount = slivercount = 0l;
-  capcount = spindlecount = wedgecount = needlecount = 0;
-
-  tetrahedrons.traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    org (tetloop, p[0]);
-    dest(tetloop, p[1]);
-    apex(tetloop, p[2]);
-    oppo(tetloop, p[3]);
-    tetlongest2 = 0.0;
-
-    for (i = 0; i < 3; i++) {
-      j = plus1mod3[i];
-      k = minus1mod3[i];
-      dx[i] = p[j][0] - p[k][0];
-      dy[i] = p[j][1] - p[k][1];
-      dz[i] = p[j][2] - p[k][2];
-      edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i] + dz[i] * dz[i];
-      if (edgelength[i] > tetlongest2) {
-        tetlongest2 = edgelength[i];
-      }
-      if (edgelength[i] > longest) {
-        longest = edgelength[i];
-      }
-      if (edgelength[i] < shortest) {
-        shortest = edgelength[i];
-      }
-    }
-
-    for (i = 3; i < 6; i++) {
-      j = i - 3;
-      k = 3;
-      dx[i] = p[j][0] - p[k][0];
-      dy[i] = p[j][1] - p[k][1];
-      dz[i] = p[j][2] - p[k][2];
-      edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i] + dz[i] * dz[i];
-      if (edgelength[i] > tetlongest2) {
-        tetlongest2 = edgelength[i];
-      }
-      if (edgelength[i] > longest) {
-        longest = edgelength[i];
-      }
-      if (edgelength[i] < shortest) {
-        shortest = edgelength[i];
-      }
-    }
-
-    tetvol = tetvolume(p[0], p[1], p[2], p[3]);
-    if (tetvol < 0) tetvol = -tetvol;
-    if (tetvol < smallestvolume) {
-      smallestvolume = tetvol;
-    }
-    if (tetvol > biggestvolume) {
-      biggestvolume = tetvol;
-    }
-
-    tetalldihedral(p[0], p[1], p[2], p[3], alldihed);
-    smalldihedcount = largedihedcount = 0;
-    for (i = 0; i < 6; i++) {
-      if (alldihed[i] < smallestdiangle) {
-        smallestdiangle = alldihed[i];
-      } else if (alldihed[i] > biggestdiangle) {
-        biggestdiangle = alldihed[i];
-      }
-      if (alldihed[i] < smalldihed) {
-        smalldihedcount++;
-      } else if (alldihed[i] > largedihed) {
-        largedihedcount++;
-      }
-      tendegree = (int) (alldihed[i] / 10.);
-      dihedangletable[tendegree]++;
-    }
-    allsolid[0] = alldihed[0] + alldihed[1] + alldihed[2] - 180;
-    allsolid[1] = alldihed[0] + alldihed[3] + alldihed[4] - 180;
-    allsolid[2] = alldihed[1] + alldihed[3] + alldihed[5] - 180;
-    allsolid[3] = alldihed[2] + alldihed[4] + alldihed[5] - 180;
-    smallsolidcount = largesolidcount = 0;
-    for (i = 0; i < 4; i++) {
-      if (allsolid[i] < smallsolid) {
-        smallsolidcount++;
-      } else if (allsolid[i] > largesolid) {
-        largesolidcount++;
-      }
-    }
-    if (largesolidcount >= 1) {
-      capcount++;
-    } else if ((largedihedcount > 0) && (smalldihedcount > 0)) {
-      slivercount++;
-    } else if (largedihedcount > 0) {
-      spindlecount++;
-    } else if (smalldihedcount > 0) {
-      wedgecount++;
-    } else if (smallsolidcount > 0) {
-      needlecount++;
-    } else {
-      roundcount++;
-    }
-
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  shortest = sqrt(shortest);
-  longest = sqrt(longest);
-  minaltitude = sqrt(minaltitude);
-  worstaspect = sqrt(worstaspect);
-
-  printf("  Smallest volume: %16.5g   |  Largest volume: %16.5g\n",
-         smallestvolume, biggestvolume);
-  printf("  Shortest edge:   %16.5g   |  Longest edge:   %16.5g\n",
-         shortest, longest);
-  printf("\n");
-  printf("  Smallest dihedral: %14.5g   |  Largest dihedral: %14.5g\n\n",
-         smallestdiangle, biggestdiangle);
-  printf("  Dihedral Angle histogram:\n");
-  for (i = 0; i < 9; i++) {
-    printf("      %3d - %3d degrees:  %8d    |    %3d - %3d degrees:  %8d\n",
-           i * 10, i * 10 + 10, dihedangletable[i],
-           i * 10 + 90, i * 10 + 100, dihedangletable[i + 9]);
-  }
-  printf("\n");
-
-  printf("  Shape histogram:\n\n");
-  printf("    Sliver:  %d\n", slivercount);
-  printf("    Needle:  %d\n", needlecount);
-  printf("    Spindle: %d\n", spindlecount);
-  printf("    Wedge:   %d\n", wedgecount);
-  printf("    Cap:     %d\n\n", capcount);
-  printf("  There are %d bad elements among %d elements.\n",
-         slivercount + needlecount + spindlecount + wedgecount + capcount,
-         tetrahedrons.items);
-
-  printf("\n");
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// statistics()    Print all sorts of cool facts.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::statistics()
-{
-  printf("\nStatistics:\n\n");
-  printf("  Input points: %d\n", inpoints);
-  if (refine) {
-    printf("  Input tetrahedra: %d\n", inelements);
-  }
-  if (poly) {
-    printf("  Input facets: %d\n", infacets);
-    if (!refine) {
-      printf("  Input holes: %d\n", holes);
-    }
-  }
-
-  printf("\n  Mesh points: %ld\n", points.items);
-  printf("  Mesh tetrahedra: %ld\n", tetrahedrons.items);
-  printf("  Mesh faces: %ld\n", faces);
-  if (poly || refine) {
-    printf("  Mesh boundary faces: %ld\n", hullsize);
-    printf("  Mesh subfaces: %ld (include nonsolids)\n", subfaces.items);
-    printf("  Mesh subsegments: %ld\n\n", subsegs.items);
-  } else {
-    printf("  Mesh convex hull faces: %ld\n\n", hullsize);
-  }
-  if (verbose) {
-    if (quality) {
-      quality_statistics();
-    }
-    printf("Memory allocation statistics:\n\n");
-    printf("  Maximum number of points: %ld\n", points.maxitems);
-    printf("  Maximum number of tetrahedra: %ld\n", tetrahedrons.maxitems);
-    if (subfaces.maxitems > 0) {
-      printf("  Maximum number of subfaces: %ld\n", subfaces.maxitems);
-    }
-    if (subsegs.maxitems > 0) {
-      printf("  Maximum number of segments: %ld\n", subsegs.maxitems);
-    }
-    if (viri.maxitems > 0) {
-      printf("  Maximum number of viri: %ld\n", viri.maxitems);
-    }
-    if (badfaces.maxitems > 0) {
-      printf("  Maximum number of encroached subfaces: %ld\n",
-             badfaces.maxitems);
-    }
-    if (badsegments.maxitems > 0) {
-      printf("  Maximum number of encroached segments: %ld\n",
-             badsegments.maxitems);
-    }
-    if (badtets.maxitems > 0) {
-      printf("  Maximum number of bad tetrahedra: %ld\n", badtets.maxitems);
-    }
-    printf("  Approximate heap memory use (bytes): %ld\n\n",
-           points.maxitems * points.itembytes
-           + tetrahedrons.maxitems * tetrahedrons.itembytes
-           + subfaces.maxitems * subfaces.itembytes
-           + subsegs.maxitems * subsegs.itembytes
-           + viri.maxitems * viri.itembytes
-           + badfaces.maxitems * badfaces.itembytes
-           + badsegments.maxitems * badsegments.itembytes
-           + badtets.maxitems * badtets.itembytes);
-
-    printf("Algorithmic statistics:\n\n");
-    printf("  Number of insphere tests: %ld\n", inspherecount);
-    printf("  Number of orientation tests: %ld\n", orient3dcount);
-    if (segmentintersectioncount > 0) {
-      printf("  Number of segment intersections: %ld\n",
-             segmentintersectioncount);
-    }
-    printf("\n");
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// syntax()    Print list of command line switches.                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::syntax()
-{
-  printf("tetgen [-pq__a__AnfcgBPNEIOXzS__T__CQVh] input_file\n");
-  printf("    -p  Triangulates a Piecewise Linear Complex (.poly file).\n");
-  printf("    -q  Quality mesh generation. Use Shewchuk's Delaunay Refinement\n");
-  printf("        Algorithm. A minimum radius-edge ratio may be specified.\n");
-  printf("    -a  Applies a maximum tetrahedron volume constraint.\n");
-  printf("    -A  Applies attributes to identify elements in certain regions.\n");
-  printf("    -f  Generates a list of tetrahedron faces.\n");
-  printf("    -e  Generates a list of edges (segments).\n");
-  printf("    -c  Generates a list of convex hull faces.\n");
-  printf("    -n  Generates a list of tetrahedron neighbors.\n");
-  printf("    -g  Generates file for viewing mesh by Geomview(*.off) or Gid.\n");
-  printf("    -B  Suppresses output of boundary information.\n");
-  printf("    -P  Suppresses output of .poly file.\n");
-  printf("    -N  Suppresses output of .node file.\n");
-  printf("    -E  Suppresses output of .ele file.\n");
-  printf("    -I  Suppresses mesh iteration numbers.\n");
-  printf("    -O  Ignores holes in .poly file.\n");
-  printf("    -X  Use exact arithmetic to perform geometric predicates.\n");
-  printf("    -z  Numbers all items starting from zero (rather than one).\n");
-  printf("    -S  Specifies maximum number of added Steiner points.\n");
-  printf("    -T  Specifies the tolerance for round-to-zero.\n");
-  printf("    -C  Check consistency of final mesh.\n");
-  printf("    -Q  Quiet:  No terminal output except errors.\n");
-  printf("    -V  Verbose:  Detailed information on what I'm doing.\n");
-  printf("    -h  Help:  Detailed instructions for Tetgen.\n");
-  exit(0);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// meshinit()     Initialize some variables.                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::meshinit()
-{
-  recenttet.tet = (tetrahedron*) NULL;     // No tetra has been visited yet.
-  samples = 1;            // Point location should take at least one sample.
-  checksegments = 0;      // There are no segments in the triangulation yet.
-  randomseed = 1;
-  usefliplist = 0;
-  shflaws = shsegflaws = tetflaws = 0;
-  fliplist = NULL;
-  dummytetbase = dummyshbase = NULL;
-  surfmesh = NULL;
-
-  // Init statistic variables.
-  flip_t23s = flip_t32s = flip_t22s = flip_t44s = 0;
-  cospherecount = segmentintersectioncount = 0l;
-  inspherecount = orient3dcount = 0l;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// meshdeinit()     Free all remaining allocated memory.                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::meshdeinit()
-{
-  tetrahedrons.deinit();
-  if (dummytetbase) {
-    delete [] dummytetbase;
-  }
-  if (useshelles) {
-    subfaces.deinit();
-    subsegs.deinit();
-    if (dummyshbase) {
-      delete [] dummyshbase;
-    }
-  }
-  points.deinit();
-  if (poly && faces) {
-    badsegments.deinit();
-  }
-  if (quality) {
-    badfaces.deinit();
-    if ((minratio > 0.0) || varvolume || fixedvolume) {
-      badtets.deinit();
-    }
-  }
-  if (fliplist) {
-    delete fliplist;
-  }
-  if (surfmesh) {
-    delete surfmesh;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// parsecommandline()    Read the command line, identify switches, and set   //
-//                       up options and file names.                          //
-//                                                                           //
-// The effects of this routine are felt entirely through global variables.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::parsecommandline(int argc, char **argv)
-{
-  int startindex;
-  int increment;
-  int meshnumber;
-  int i, j, k;
-  char workstring[FILENAMESIZE];
-
-  poly = smesh = 0;
-  refine = quality = varvolume = fixedvolume = regionattrib = convex = 0;
-  firstnumber = 1;
-  facesout = edgesout = voronoi = neighbors = geomview = 0;
-  nobound = nopolywritten = nonodewritten = noelewritten = noiterationnum = 0;
-  noholes = nobisect = 0;
-  noexact = 1;   // default vaule, not use exact arithmetic.
-  splitseg = 1;  // default value in 3D case.
-  docheck = 0;
-  steiner = -1;
-  minratio = 2.0;  // Default radius-edge ratio.
-  maxvolume = -1.0;
-  noroundoff = 0;
-  usertolerance = 1e-12;    // default tolerance.
-  userubtolerance = 1e-10;
-  badelemreport = 0;
-  quiet = verbose = 0;
-  innodefilename[0] = '\0';
-  commandline[0] = '\0';
-
-  startindex = 1;
-  strcpy(commandline, argv[0]);
-  strcat(commandline, " ");
-  for (i = startindex; i < argc; i++) {
-    if (argv[i][0] == '-') {
-      for (j = startindex; argv[i][j] != '\0'; j++) {
-        if (argv[i][j] == 'p') {
-          poly = 1;
-        }
-        if (argv[i][j] == 'r') {
-          refine = 1;
-        }
-        if (argv[i][j] == 'q') {
-          quality = 1;
-          if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-              (argv[i][j + 1] == '.')) {
-            k = 0;
-            while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-                   (argv[i][j + 1] == '.')) {
-              j++;
-              workstring[k] = argv[i][j];
-              k++;
-            }
-            workstring[k] = '\0';
-            minratio = (REAL) strtod(workstring, (char **) NULL);
-            if (minratio <= 0.0) {
-              printf("Command line Error:  After -q switch, the minimum");
-              printf(" radius-edge ratio must greater than Zero.\n");
-              exit(1);
-            }
-          } else {
-            minratio = 2; // Default radius-edge ratio.
-          }
-        }
-        if (argv[i][j] == 'a') {
-          quality = 1;
-          if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-              (argv[i][j + 1] == '.')) {
-            fixedvolume = 1;
-            k = 0;
-            while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-                   (argv[i][j + 1] == '.')) {
-              j++;
-              workstring[k] = argv[i][j];
-              k++;
-            }
-            workstring[k] = '\0';
-            maxvolume = (REAL) strtod(workstring, (char **) NULL);
-            if (maxvolume <= 0.0) {
-              printf("Command line Error:  After -a switch, the maximum");
-              printf(" volume constraints must greater than Zero.\n");
-              exit(1);
-            }
-          } else {
-            varvolume = 1;
-          }
-        }
-        if (argv[i][j] == 'A') {
-          regionattrib = 1;
-        }
-        if (argv[i][j] == 'c') {
-          convex = 1;
-        }
-        if (argv[i][j] == 's') {
-          splitseg = 0;
-        }
-        if (argv[i][j] == 'z') {
-          firstnumber = 0;
-        }
-        if (argv[i][j] == 'f') {
-          facesout = 1;
-        }
-        if (argv[i][j] == 'e') {
-          edgesout = 1;
-        }
-        if (argv[i][j] == 'v') {
-          voronoi = 1;
-        }
-        if (argv[i][j] == 'n') {
-          neighbors = 1;
-        }
-        if (argv[i][j] == 'g') {
-          geomview = 1;
-        }
-        if (argv[i][j] == 'B') {
-          nobound = 1;
-        }
-        if (argv[i][j] == 'P') {
-          nopolywritten = 1;
-        }
-        if (argv[i][j] == 'N') {
-          nonodewritten = 1;
-        }
-        if (argv[i][j] == 'E') {
-          noelewritten = 1;
-        }
-        if (argv[i][j] == 'I') {
-          noiterationnum = 1;
-        }
-        if (argv[i][j] == 'O') {
-          noholes = 1;
-        }
-        if (argv[i][j] == 'X') {
-          noexact = 0; // Use exact arithmetic.
-        }
-        if (argv[i][j] == 'Y') {
-          nobisect++;
-        }
-        if (argv[i][j] == 'S') {
-          steiner = 0;
-          while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
-            j++;
-            steiner = steiner * 10 + (int) (argv[i][j] - '0');
-          }
-        }
-        if (argv[i][j] == 'T') {
-          if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-              (argv[i][j + 1] == '.')) {
-            k = 0;
-            while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-                   (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
-                   (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
-              j++;
-              workstring[k] = argv[i][j];
-              k++;
-            }
-            workstring[k] = '\0';
-            usertolerance = (REAL) strtod(workstring, (char **) NULL);
-            if (usertolerance <= 0.0) {
-              printf("Command line Error:  After -T switch, tolerance");
-              printf(" must greater than Zero.\n");
-              exit(1);
-            }
-            userubtolerance = usertolerance * 1e+2;
-          }
-        }
-        if (argv[i][j] == 'F') {
-          noroundoff = 1;
-        }
-        if (argv[i][j] == 'b') {
-          badelemreport = 1;
-        }
-        if (argv[i][j] == 'C') {
-          docheck = 1;
-        }
-        if (argv[i][j] == 'Q') {
-          quiet = 1;
-        }
-        if (argv[i][j] == 'V') {
-          verbose++;
-        }
-        if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
-            (argv[i][j] == '?')) {
-          syntax();
-        }
-      }
-    } else {
-      strncpy(innodefilename, argv[i], FILENAMESIZE - 1);
-      innodefilename[FILENAMESIZE - 1] = '\0';
-    }
-    strcat(commandline, argv[i]);
-    strcat(commandline, " ");
-  }
-  commandline[FILENAMESIZE - 1] = '\0';
-  if (innodefilename[0] == '\0') {
-    syntax();
-  }
-  if (!strcmp(&innodefilename[strlen(innodefilename) - 5], ".node")) {
-    innodefilename[strlen(innodefilename) - 5] = '\0';
-  }
-  if (!strcmp(&innodefilename[strlen(innodefilename) - 5], ".poly")) {
-    innodefilename[strlen(innodefilename) - 5] = '\0';
-    poly = 1;
-    smesh = 0;
-  }
-  if (!strcmp(&innodefilename[strlen(innodefilename) - 6], ".smesh")) {
-    innodefilename[strlen(innodefilename) - 6] = '\0';
-    smesh = 1;
-    poly = 0;
-  }
-  if (!strcmp(&innodefilename[strlen(innodefilename) - 4], ".ele")) {
-    innodefilename[strlen(innodefilename) - 4] = '\0';
-    refine = 1;
-  }
-  if (!strcmp(&innodefilename[strlen(innodefilename) - 7], ".volume")) {
-    innodefilename[strlen(innodefilename) - 5] = '\0';
-    refine = 1;
-    quality = 1;
-    varvolume = 1;
-  }
-  steinerleft = steiner;
-  useshelles = poly || smesh || refine || quality || convex;
-  goodratio = minratio;
-  goodratio *= goodratio;
-  if (refine && noiterationnum) {
-    printf("Command line Error:  You cannot use the -I switch when");
-    printf(" refining a triangulation.\n");
-    exit(1);
-  }
-  // Be careful not to allocate space for element volume constraints that
-  //   will never be assigned any value (other than the default -1.0).
-  if (!refine && !poly && !smesh) {
-    varvolume = 0;
-  }
-  // Be careful not to add an extra attribute to each element unless the
-  //   input supports it (PLC in, but not refining a preexisting mesh).
-  if (refine || (!poly && !smesh)) {
-    regionattrib = 0;
-  }
-
-  strcpy(inpolyfilename, innodefilename);
-  strcpy(insmeshfilename, innodefilename);
-  strcpy(inelefilename, innodefilename);
-  strcpy(volumefilename, innodefilename);
-  increment = 0;
-  strcpy(workstring, innodefilename);
-  j = 1;
-  while (workstring[j] != '\0') {
-    if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
-      increment = j + 1;
-    }
-    j++;
-  }
-  meshnumber = 0;
-  if (increment > 0) {
-    j = increment;
-    do {
-      if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
-        meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
-      } else {
-        increment = 0;
-      }
-      j++;
-    } while (workstring[j] != '\0');
-  }
-  if (noiterationnum) {
-    strcpy(outnodefilename, innodefilename);
-    strcpy(outelefilename, innodefilename);
-    strcpy(facefilename, innodefilename);
-    strcpy(edgefilename, innodefilename);
-    strcpy(neighborfilename, innodefilename);
-    strcpy(offfilename, innodefilename);
-    strcat(outnodefilename, ".node");
-    strcat(outelefilename, ".ele");
-    strcat(facefilename, ".face");
-    strcat(edgefilename, ".edge");
-    strcat(neighborfilename, ".neigh");
-    strcat(offfilename, ".off");
-  } else if (increment == 0) {
-    strcpy(outnodefilename, innodefilename);
-    strcpy(outpolyfilename, innodefilename);
-    strcpy(outelefilename, innodefilename);
-    strcpy(facefilename, innodefilename);
-    strcpy(edgefilename, innodefilename);
-    strcpy(neighborfilename, innodefilename);
-    strcpy(offfilename, innodefilename);
-    strcat(outnodefilename, ".1.node");
-    strcat(outpolyfilename, ".1.poly");
-    strcat(outelefilename, ".1.ele");
-    strcat(facefilename, ".1.face");
-    strcat(edgefilename, ".1.edge");
-    strcat(neighborfilename, ".1.neigh");
-    strcat(offfilename, ".1.off");
-  } else {
-    workstring[increment] = '%';
-    workstring[increment + 1] = 'd';
-    workstring[increment + 2] = '\0';
-    sprintf(outnodefilename, workstring, meshnumber + 1);
-    strcpy(outpolyfilename, outnodefilename);
-    strcpy(outelefilename, outnodefilename);
-    strcpy(facefilename, outnodefilename);
-    strcpy(edgefilename, outnodefilename);
-    strcpy(neighborfilename, outnodefilename);
-    strcpy(offfilename, outnodefilename);
-    strcat(outnodefilename, ".node");
-    strcat(outpolyfilename, ".poly");
-    strcat(outelefilename, ".ele");
-    strcat(facefilename, ".face");
-    strcat(edgefilename, ".edge");
-    strcat(neighborfilename, ".neigh");
-    strcat(offfilename, ".off");
-  }
-  strcat(innodefilename, ".node");
-  strcat(inpolyfilename, ".poly");
-  strcat(insmeshfilename, ".smesh");
-  strcat(inelefilename, ".ele");
-  strcat(volumefilename, ".volume");
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// triangulate()   Gosh, do everything.                                      //
-//                                                                           //
-// The sequence is roughly as follows.  Many of these steps can be skipped,  //
-// depending on the command line switches.                                   //
-//                                                                           //
-// - Initialize constants and parse the command line.                        //
-// - Read the points from a file and either                                  //
-//   - triangulate them                                                      //
-// - Insert the PLC segments and subfaces (-p).                              //
-// - Read the holes (-p), regional attributes (-pA), and regional area       //
-//     constraints (-pa).  Carve the holes and concavities, and spread the   //
-//     regional attributes and area constraints.                             //
-// - Enforce the constraints on minimum angle (-q) and maximum area (-a).    //
-//     Also enforce the conforming Delaunay property (-q and -a).            //
-// - Compute the number of edges in the resulting mesh.                      //
-// - Write the output files and print the statistics.                        //
-// - Check the consistency and Delaunay property of the mesh (-C).           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void mesh3d::triangulate(int argc, char **argv)
-{
-  REAL *holearray;                                        // Array of holes.
-  REAL *regionarray;   // Array of regional attributes and area constraints.
-  FILE *polyfile;
-  // Variables for timing the performance of Tetrahedra.
-#ifndef NO_TIMER
-  // The types are defined in sys/time.h.
-  struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
-  struct timezone tz;
-#else  // NO_TIMER
-  // The types are defined in time.h.
-  clock_t tv0, tv1, tv2, tv3, tv4, tv5, tv6;
-#endif // NO_TIMER
-
-#ifndef NO_TIMER
-  gettimeofday(&tv0, &tz);
-#else  // NO_TIMER
-  tv0 = clock();
-#endif // NO_TIMER
-
-  exactinit();                     // Initialize exact arithmetic constants.
-  parsecommandline(argc, argv);
-  readnodes(&polyfile);
-
-  if (verbose > 1) {
-    // Number the points first when "-VV" or "-VVV" switch be set, so that
-    //   the debug functions can output point indices for you.
-    numbernodes(1);
-  }
-
-  if (!quiet) {
-#ifndef NO_TIMER
-    gettimeofday(&tv1, &tz);
-#else  // NO_TIMER
-    tv1 = clock();
-#endif // NO_TIMER
-  }
-
-  if (refine) {
-    // Read and reconstruct a mesh.
-    printf("Sorry, the -r switch has not been implemented now.\n");
-    exit(1);
-  } else {
-    hullsize = delaunay();                        // Triangulate the points.
-  }
-
-  if (!quiet) {
-    if (refine) {
-      printf("Mesh reconstruction");
-    } else {
-      printf("Delaunay");
-    }
-#ifndef NO_TIMER
-    gettimeofday(&tv2, &tz);
-    printf(" milliseconds:  %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec)
-           + (tv2.tv_usec - tv1.tv_usec) / 1000l);
-#else  // NO_TIMER
-    tv2 = clock();
-    printf(" milliseconds:  %g\n", 1000l * (tv2 - tv1) / (REAL) CLK_TCK);
-#endif // NO_TIMER
-  }
-
-  if (useshelles) {
-    checksegments = 1;                  // Segments will be introduced next.
-    if (!refine) {
-      // Insert PLC segments/facets and/or convex hull segments/facets.
-      infacets = formskeleton(polyfile);
-      if (docheck) {
-        checkshells();
-      }
-    }
-  }
-
-  if (!quiet) {
-#ifndef NO_TIMER
-    gettimeofday(&tv3, &tz);
-    if (useshelles && !refine) {
-      printf("Segment and facet milliseconds:  %ld\n",
-             1000l * (tv3.tv_sec - tv2.tv_sec)
-             + (tv3.tv_usec - tv2.tv_usec) / 1000l);
-    }
-#else  // NO_TIMER
-    tv3 = clock();
-    if (useshelles && !refine) {
-      printf("Segment and facet milliseconds:  %g\n",
-             1000l * (tv3 - tv2) / (REAL) CLK_TCK);
-    }
-#endif // NO_TIMER
-  }
-
-  if (poly || smesh) {
-    readholes(polyfile, &holearray, &holes, &regionarray, &regions);
-    if (!refine) {
-      // Carve out holes and concavities.
-      carveholes(holearray, holes, regionarray, regions);
-    }
-  } else {
-    // Without a PLC, there can be no holes or regional attributes
-    //   or area constraints.  The following are set to zero to avoid
-    //   an accidental free later.
-    holes = 0;
-    regions = 0;
-  }
-
-  if (!quiet) {
-#ifndef NO_TIMER
-    gettimeofday(&tv4, &tz);
-    if (poly && !refine) {
-      printf("Hole milliseconds:  %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec)
-             + (tv4.tv_usec - tv3.tv_usec) / 1000l);
-    }
-#else  // NO_TIMER
-    tv4 = clock();
-    if (poly && !refine) {
-      printf("Hole milliseconds:  %g\n", 1000l * (tv4 - tv3) / (REAL) CLK_TCK);
-    }
-#endif // NO_TIMER
-  }
-
-  if (quality) {
-    enforcequality();                 // Enforce angle and area constraints.
-  }
-
-  if (!quiet) {
-#ifndef NO_TIMER
-    gettimeofday(&tv5, &tz);
-    if (quality) {
-      printf("Quality milliseconds:  %ld\n",
-             1000l * (tv5.tv_sec - tv4.tv_sec)
-             + (tv5.tv_usec - tv4.tv_usec) / 1000l);
-    }
-#else  // NO_TIMER
-    tv5 = clock();
-    if (quality) {
-      printf("Quality milliseconds:  %g\n",
-             1000l * (tv5 - tv4) / (REAL) CLK_TCK);
-    }
-#endif // NO_TIMER
-  }
-
-  // Compute the number of edges.
-  faces = (4l * tetrahedrons.items + hullsize) / 2l;
-
-  if (!quiet) {
-    printf("\n");
-  }
-
-  // If not using iteration numbers, don't write a .node file if one was
-  //   read, because the original one would be overwritten!
-  if (nonodewritten || (noiterationnum && readnodefile)) {
-    if (!quiet) {
-      printf("NOT writing a .node file.\n");
-    }
-    numbernodes();                 // We must remember to number the points.
-  } else {
-    outnodes();                                   // Numbers the points too.
-  }
-
-  if (noelewritten) {
-    if (!quiet) {
-      printf("NOT writing an .ele file.\n");
-    }
-  } else {
-    outelems();
-  }
-
-  if (regions > 0) {
-    delete [] regionarray;
-  }
-  if (holes > 0) {
-    delete [] holearray;
-  }
-  if (geomview) {
-    outelems2gid();   // for gid mesh reader.
-    outfaces2gid(1);  // only output hull faces.
-    outoff();         // off file of geomview.
-    // outelems2fa();    // Fa files.
-  }
-  if (facesout || convex) {
-    outfaces(convex);
-  }
-  if (edgesout) {
-    outedges();
-  }
-  if (neighbors) {
-    outneighbors();
-  }
-  if (badelemreport) {
-    dumpallbadelems("badelems.gid");
-  }
-
-  if (!quiet) {
-#ifndef NO_TIMER
-    gettimeofday(&tv6, &tz);
-    printf("\nOutput milliseconds:  %ld\n",
-           1000l * (tv6.tv_sec - tv5.tv_sec)
-           + (tv6.tv_usec - tv5.tv_usec) / 1000l);
-    printf("Total running milliseconds:  %ld\n",
-           1000l * (tv6.tv_sec - tv0.tv_sec)
-           + (tv6.tv_usec - tv0.tv_usec) / 1000l);
-#else  // NO_TIMER
-    tv6 = clock();
-    printf("\nOutput milliseconds:  %g\n",
-           1000l * (tv6 - tv5) / (REAL) CLK_TCK);
-    printf("Total running milliseconds:  %g\n",
-           1000l * (tv6 - tv0) / (REAL) CLK_TCK);
-#endif // NO_TIMER
-    statistics();
-  }
-
-  // If the "-C" swith be set.
-  if (docheck) {
-    checkmesh();
-    if (checksegments) {
-      checkshells();
-    }
-    checkdelaunay();
-  }
-}
diff --git a/Tetgen/tetlib.h b/Tetgen/tetlib.h
deleted file mode 100644
index 3c860cb03e..0000000000
--- a/Tetgen/tetlib.h
+++ /dev/null
@@ -1,1301 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetlib.h    Head file for the mesh data structures and mesh3d class       //
-//             declaration.                                                  //
-//                                                                           //
-// Tetgen Version 1.0 beta                                                   //
-// Oct. 2001                                                                 //
-//                                                                           //
-// Si hang                                                                   //
-// Email: sihang@weboo.com                                                   //
-// http://www.weboo.com/sh/tetgen.htm                                        //
-//                                                                           //
-// You are free to use, copy and modify the sources under certain            //
-// circumstances, provided this copyright notice remains intact.             //
-// See the file LICENSE for details.                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-//   Tetgen is based on the Delaunay method and incorporates face-swapping   //
-// techniques. It generates meshes composed of tetrahedral elements. Tetgen  //
-// generates exact Delaunay tetrahedralization for three-dimensional point   //
-// sets, generates boundary constrained Delaunay tetrahedralization and      //
-// quality (conforming) Delaunay tetrahedralizations for three-dimensional   //
-// Piecewise Linear Complex(PLC).                                            //
-//                                                                           //
-//   The Tetgen mesh generator is based on:                                  //
-//                                                                           //
-// [*] Integrating two relative mesh data structures: The tetrahedron-based  //
-//     mesh data structure and triangle-edge mesh data structure.            //
-//                                                                           //
-// [*] Using the randomized incremental flip algorithm to construct Delaunay //
-//     tetrahedralization for 3D point sets.                                 //
-//                                                                           //
-// [*] Using simple face/edge swapping method and local re-meshing method to //
-//     construct boundary-constrained Delaunay tetrahedralization.           //
-//                                                                           //
-// [*] Using the Delaunay refinement algorithm and the radius-edge ratio     //
-//     quality measure to incrementally insert (steiner) points into the     //
-//     mesh to eliminate bad quality tetrahedra and generate an almost good  //
-//     mesh with good grading.                                               //
-//                                                                           //
-// [*] Other algorithms involve fast randomized point location algorithm to  //
-//     perform fast point location and using gift-wrapping algorithm to      //
-//     construct a constrained Delaunay triangulation for triangular faces   //
-//     bounded polyhedras.                                                   //
-//                                                                           //
-// [*] Embedding the 2D mesh generator Triangle to generate planar surface   //
-//     mesh, Optionally using the adaptive exact arithmetic package to       //
-//     improve the robustness of the implementation.                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef tetlibH
-#define tetlibH
-
-#include "defines.h"
-#include "linklist.h"
-#include "trilib.h"
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Mesh data structures                                                      //
-//                                                                           //
-//   The efficiency of a tetrahedral mesh generator is rests on its          //
-// algorithms and data structures. It was important to begin with a robust   //
-// data structure that was flexible and encompassing enough to serve as the  //
-// basis for a wide variety of applications. In Tetgen, the data structure   //
-// was so designed make it suitable for both Delaunay and Advancing-Front    //
-// methods.                                                                  //
-//                                                                           //
-//   Tetgen integrates two relative mesh data structures: The tetrahedron-   //
-// based data structure of Shewchuk[1] and the triangle-edge data structure  //
-// of Mucke[2]. Where the tetrahedron-based data structure is convenient for //
-// storing tetrahedral mesh and is deeply discussed in [1]. The triangle-    //
-// edge data structure is convenient for face classification and mesh        //
-// manipulation, it was mainly described in [2].                             //
-//                                                                           //
-//   Please refer to Dobkin and Laszlo[3], Guibas and Stolfi[4], and Owen[5] //
-// for more general discussions about mesh data structures.                  //
-//                                                                           //
-// Refernces:                                                                //
-//                                                                           //
-// [1] Jonathan Richard Shewchuk, Delaunay Refinement Mesh Generation. Ph.D. //
-//     thesis, School of Computer Science, Carnegie Mellon University, Pitt- //
-//     sburgh, Pennsylvania. May 1997. Available as Technical Rreport CMU-CS //
-//     -97-137.                                                              //
-// [2] Ernst P. Mucke, Shapes and Implementations in Three-Dimensional Geom- //
-//     etry. Ph.D. thesis, Technical Report UIUCDCS-R-93-1836. Department of //
-//     Computer Science, University of Illinois at Urbana-Champaign, Urbana, //
-//     Illinois, 1993.                                                       //
-// [3] David P. Dobkin and Michael J. Laszlo. Primitives for the Manipulati- //
-//     on of Three-Dimensional Subdivisions. Algorithmica 4:3-32, 1989.      //
-// [4] Leonidas J. Guibas and Jorge Stolfi, Primitives for the Manipulation  //
-//     of General Subdivisions and the Computation of Voronoi Diagrams, ACM  //
-//     Transactions on Graphics 4(2):74-123, April 1985.                     //
-// [5] Steven J. Owen, Non-Simplicial Unstructured Mesh Generation, Ph.D.    //
-//     Dissertation, Carnegie Mellon University, 1999.                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Basic data structure: tetrahedron                                         //
-//                                                                           //
-//   Each tetrahedron contain four pointers to its vertices, and four        //
-// pointers to the adjoining tetrahedra. Plus four pointers to subfaces      //
-// (define below, these pointers are usually 'dummysh'). It may or may not   //
-// also contain user-defined attributes and/or a floating-point volume       //
-// constraint.                                                               //
-//   Because the size and structure of a 'tetrahedron' is not decided until  //
-// runtime,  It is not simply defined to be a structure or a class.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-typedef REAL **tetrahedron;
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Basic data structure: shellface                                           //
-//                                                                           //
-//   The shell (triangular) face data structure. Both subface and subsegment //
-// are represented by shellface(see[1]).                                     //
-//   Each subface contains three pointers to its vertices, three pointers to //
-// adjoining subfaces, and two pointers to adjoining tetrahedron,  plus one  //
-// boundary marker.  Three pointer to adjoining subfaces are only used for   //
-// coplanar neighbours in a common facet, or used for applications of gener- //
-// ating surface meshes. Each subface also has three pointers to adjoining   //
-// subsegments. To save space, there are no pointers directly connecting     //
-// tetrahedra and adjoining subsegments;  connections between tetrahedra and //
-// subsegments are entirely mediated through subfaces.                       //
-//   Because a subsegment may be shared by any number of subfaces and        //
-// tetrahedra, each subsegment has a pointer to only one adjoining subface //
-// (chosen arbitrarily);  the others must be found through the connectivity  //
-// of the mesh.                                                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-typedef REAL **shellface;
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Basic data structure: point3d                                             //
-//                                                                           //
-//   The point data structure.  Each point is actually an array of REALs.    //
-// The number of REALs is unknown until runtime. An integer boundary marker, //
-// and sometimes a pointer to a tetrahedron, is appended after the REALs.    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-typedef REAL *point3d;
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Handle                                                                    //
-//                                                                           //
-//   The oriented triangular face 'triface' and oriented shell face 'face'   //
-// data structures defined below do not themselves store any part of the     //
-// mesh. The mesh itself is made of 'tetrahedron's, 'shellface's, and        //
-// 'point3d's.                                                               //
-//                                                                           //
-//   Oriented triangular faces and oriented shell faces will usually be      //
-// referred to as "handles".  A handle is essentially a pointer into the     //
-// mesh; it allows you to "hold" one particular part of the mesh.  Handles   //
-// are used to specify the regions in which one is traversing and modifying  //
-// the mesh.                                                                 //
-//                                                                           //
-//    A 'triface' is a handle that holds a tetrahedron. It holds a specific  //
-// side of the tetrahedron. An 'face' is a handle that holds a shell face.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// The handle data structure: triface                                        //
-//                                                                           //
-//   triface is an oriented triangluar face of tetrahedron in 3D. The        //
-// orientation is determined by face vertices. A triface includes a pointer  //
-// to a tetrahedron, a face location and a face version. where face location //
-// is an integer number varies from 0 to 3. It was used to indicate a face   //
-// of tetrahedron. Face version is an integer number varies from 0 to 5. It  //
-// was used to represent an oriented edge of face.                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-class triface {
-
-  public:
-
-    tetrahedron* tet;
-    int loc;                                           // Range from 0 to 3.
-    int ver;                                           // Range from 0 to 5.
-
-    // Constructors;
-    triface() : tet(0), loc(0), ver(0) {}
-    triface(const triface& tface) {
-      tet = tface.tet; loc = tface.loc; ver = tface.ver;
-    }
-
-    // Operators;
-    triface& operator=(const triface& tface) {
-      tet = tface.tet; loc = tface.loc; ver = tface.ver;
-      return *this;
-    }
-    bool operator==(triface& tface) {
-      return (tet == tface.tet) && (loc == tface.loc) && (ver == tface.ver);
-    }
-    bool operator!=(triface& tface) {
-      return (tet != tface.tet) || (loc != tface.loc) || (ver != tface.ver);
-    }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// The handle data structure: face                                           //
-//                                                                           //
-//   face is an oriented subface in 3D. The orientation is determined by its //
-// vertices. A face includes a pointer to a shell face, and a face version.  //
-// where face version is an integer number varies from 0 to 5. It was used   //
-// to represent an oriented edge of face.                                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-class face {
-
-  public:
-
-    shellface *sh;
-    int shver;                                        // Ranges from 0 to 5.
-
-    // Constructors;
-    face() : sh(0), shver(0) {}
-    face(const face& sface) {
-      sh = sface.sh; shver = sface.shver;
-    }
-
-    // Operators;
-    face& operator=(const face& sface) {
-      sh = sface.sh; shver = sface.shver;
-      return *this;
-    }
-    bool operator==(face& sface) {
-      return (sh == sface.sh) && (shver == sface.shver);
-    }
-    bool operator!=(face& sface) {
-      return (sh != sface.sh) || (shver != sface.shver);
-    }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Mesh data type linar-order functions used in list and link data types.    //
-// See linklist.h for detail description about linar-order functions.        //
-//                                                                           //
-// compare2points()    Compare two point3ds by their x-coordinate, using the //
-//                     y-coordinate as a secondary key, and the z-coordinate //
-//                     if their need.                                        //
-// compare2tets()      Compare two handles of tetrahedra by thire address.   //
-// compare2shfaces()   Compare two handles of subfaces/subsegments by thire  //
-//                     address.                                              //
-//                                                                           //
-// Return 0 if they are the same. Return 1 or -1 if they are not the same.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int compare2points(point3d*, point3d*);
-int compare2tets(triface*, triface*);
-int compare2shfaces(face*, face*);
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// struct badface3d                                                          //
-//                                                                           //
-//   A queue used to store bad triangular faces.  Each face's vertices are   //
-// stored so that one can check whether a face is still the same.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-typedef struct badface3dtype {
-  triface badfacetet;                    // A tetrahedron hold the bad face.
-  face shface;                                                // A bad face.
-  REAL cent[3];                           // The circumcenters' coordinates.
-  point3d faceorg, facedest, faceapex;                // The three vertices.
-  struct badface3dtype *nextface;               // Pointer to next bad face.
-} badface3d;
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// struct badtet                                                             //
-//                                                                           //
-//   A queue used to store bad tetrahedra. Each tetrahedron's vertices are   //
-// stored so that one can check whether a tetrahedron is still the same.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-typedef struct badtettype {
-  triface btet;                                                // A bad tet.
-  REAL key;                                          // radius-edge ratio^2.
-  REAL cent[3];                           // The circumcenters' coordinates.
-  point3d tetorg, tetdest, tetapex, tetoppo;           // The four vertices.
-  struct badtettype *nexttet;                    // Pointer to next bad tet.
-} badtet;
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// class mesh3d    The quality Tetrahedral mesh Generator and Delaunay       //
-//                 triangulator implementation class.                        //
-//                                                                           //
-//   Tetgen is based on the Delaunay method and incorporates face-swapping   //
-// techniques. It generates meshed composed of tetrahedral elements. Tetgen  //
-// generates exact Delaunay tetrahedralization for three-dimensional point   //
-// sets, generates boundary constrained Delaunay tetrahedralization and      //
-// quality (conforming) Delaunay tetrahedralizations for three-dimensional   //
-// Piecewise Linear Complex(PLC).                                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-class mesh3d {
-
-  public:
-
-    // Labels that signify the result of point location.  The result of a
-    //   search indicates that the point falls in the interior of a tetra-
-    //   hedra, on a face, on an edge, on a vertex, or outside the mesh.
-    enum locateresult {INTETRAHEDRON, ONFACE, ONEDGE, ONVERTEX, OUTSIDE};
-
-    // Labels that signify the result of site insertion.  The result indica-
-    //   tes that the point was inserted with complete success, was inserted
-    //   but encroaches on a segment or a subface, was not inserted because
-    //   it lies on a segment or a subface, or was not inserted because
-    //   another point occupies the same location.
-    enum insertsiteresult {SUCCESSFUL, FAILED, VIOLATINGEDGE, VIOLATINGFACE,
-                           DUPLICATE};
-
-    // Labels that signify the result of direction finding.  The result
-    //   indicates that a segment connecting the two query points falls
-    //   within the tetrahedron's face, along the left edge of the face
-    //   along the right edge of the face, along the top edge of the face
-    //   or cross the opposite face of the query point.
-    enum finddirectionresult {LEFTCOLLINEAR, RIGHTCOLLINEAR, TOPCOLLINEAR,
-                              WITHIN, ACROSS};
-
-    // Labels that signify the result of subface matching.  The result of a
-    //   match indicates that the match face is existing in mesh, one edge
-    //   of the match face is missing, or two edge of the match face is mis-
-    //   sing.
-    enum matchfaceresult {FACEMATCHING, EDGEMISSING, APEXMISSING};
-
-    // Labels that signify the result of tetrahedral face category. The
-    //   result of face category are used for purposes of face and edge
-    //   swapping. 'T' indicates that the face is transformable, 'N'
-    //   indicates non-transformable. For 'T' faces, the digits are the
-    //   number of tets before and after the transformation.  For 'N' faces,
-    //   the digits are the number of tets that would be present for a
-    //   transformable case; a zero as the second digit indicates that the
-    //   case is irrevocably unswappable.
-    enum facecategory {T23, T32, T22, T44, N32, N44, N40, N30, N20, LOCKED};
-
-    // Labels that signify two edge ring of a triangle, one(CCW) traversing
-    //   edges in counterclockwise direction and one(CW) travesing edges in
-    //   clockwise direction.
-    enum {CCW = 0, CW = 1};
-
-  public:
-
-    // Variables used to allocate and access memory.
-    memorypool tetrahedrons;
-    memorypool subfaces;
-    memorypool subsegs;
-    memorypool points;
-    memorypool viri;
-    memorypool badsegments;
-    memorypool badfaces;
-    memorypool badtets;
-
-    // Variables for global used.
-    REAL xmin, xmax, ymin, ymax, zmin, zmax;
-    int inpoints, inelements, infacets, holes, regions;
-    int mesh_dim, nextras, eextras;
-    long faces, hullsize;
-    int tetwords, shwords;
-    int pointmarkindex, point2tetindex;
-    int highorderindex, elemattribindex, volumeboundindex;
-    int checksegments;
-    int readnodefile;
-    long samples;
-    unsigned long randomseed;
-
-    // Vraiables for switches.
-    int poly, smesh;
-    int refine, quality, varvolume, fixedvolume, regionattrib, convex;
-    int firstnumber;
-    int facesout, edgesout, voronoi, neighbors, geomview;
-    int nopolywritten, nonodewritten, noelewritten, noiterationnum;
-    int nobound, noholes, nobisect, noexact, noroundoff;
-    int splitseg, steiner, steinerleft;
-    int docheck;
-    int quiet, verbose;
-    int useshelles, usefliplist;
-    int shflaws, shsegflaws, tetflaws;
-    int badelemreport;
-    REAL minratio, goodratio;
-    REAL maxvolume;
-    REAL usertolerance, userubtolerance;
-
-    // A queue used to keep all uncategorized tetrahedra's face, which
-    //   maybe non local optimal.
-    queue *fliplist;
-
-    // Pointer to the two-dimensional mesh generator. Used in surface
-    //   recover process.
-    mesh2d *surfmesh;
-
-    // Pointer to a recently visited tetrahedron. Improves point location
-    //   if proximate points are inserted sequentially.
-    triface recenttet;
-
-    // Pointer to the 'tetrahedron' that occupies all of "outer space".
-    tetrahedron *dummytet;
-    tetrahedron *dummytetbase; // Keep base address so we can free it later.
-
-    // Pointer to the omnipresent shell face.  Referenced by any tetrahedron,
-    //   or subface that isn't really connected to a shell face at that
-    //   location.
-    shellface *dummysh;
-    shellface *dummyshbase;  // Keep base address so we can free() it later.
-
-    // Variables used to quality mesh generation.
-    badface3d *facequefront[2];
-    badface3d **facequetail[2];
-    badtet *tetquefront[64];
-    badtet **tetquetail[64];
-    list *uncheckedshseglist;
-    list *uncheckedshlist;
-    list *uncheckedtetlist;
-    // Three lists used for Boywer-Watson point insertion scheme.
-    list *cavetetlist;
-    list *caveshlist;
-    list *cavebdfacelist;
-
-    long inspherecount;               // Number of insphere tests performed.
-    long orient3dcount;               // Number of orient3d tests performed.
-    long cospherecount;                        // Number of cosphere tested.
-    long segmentintersectioncount; // Number segment intersection performed.
-    // Number of flips performed.
-    long flip_t23s, flip_t32s, flip_t22s, flip_t44s;
-
-    // Vraiables for filenames.
-    char innodefilename[FILENAMESIZE];
-    char inelefilename[FILENAMESIZE];
-    char inpolyfilename[FILENAMESIZE];
-    char insmeshfilename[FILENAMESIZE];
-    char volumefilename[FILENAMESIZE];
-    char outnodefilename[FILENAMESIZE];
-    char outelefilename[FILENAMESIZE];
-    char outpolyfilename[FILENAMESIZE];
-    char facefilename[FILENAMESIZE];
-    char edgefilename[FILENAMESIZE];
-    char neighborfilename[FILENAMESIZE];
-    char offfilename[FILENAMESIZE];
-    char commandline[FILENAMESIZE];
-
-  public:
-
-    ////////////////////////////////////////////////////////////////////////
-    //                                                                    //
-    // Mesh manipulation primitives.                                      //
-    //                                                                    //
-    //   Each tetrahedron contains four pointers to other tetrahedra,     //
-    // with face locations. Each pointer  points not to the first pointer //
-    // of a tetrahedron, but to one of the first four pointers of a       //
-    // tetrahedron. It is necessary to extract both the tetrahedron       //
-    // itself and the face location. To save memory,  We keep both pieces //
-    // (a tet pointer, a face loction) of information in one pointer, and //
-    // do not allocate space for face version.  To make this possible,  I //
-    // assume that all tetrahedra are aligned to eight-byte boundaries.   //
-    // The three least significant bits (two for face locations, one for  //
-    // viral infection) are masked out to produce the real pointer. The   //
-    // 'decode' primitive below decodes a pointer, extracting a face      //
-    // location, and a pointer to the a tetrahedron. The 'encode'         //
-    // primitive compresses a pointer to a tetrahedron and a face         //
-    // location into a single pointer.                                    //
-    //                                                                    //
-    ////////////////////////////////////////////////////////////////////////
-
-    // Fast lookup tables for mesh manipulation primitives. These tables are
-    //   just like global variables that used by all objects of the class.
-
-    // For enext() primitive, use 'ver' as index.
-    static int ve[6];
-
-    // For org(), dest() and apex() primitives, use 'ver' as index.
-    static int vo[6], vd[6], va[6];
-
-    // For org(), dest() and apex() primitives, use 'loc' as first index
-    //   and 'ver' as second index.
-    static int locver2org[4][6];
-    static int locver2dest[4][6];
-    static int locver2apex[4][6];
-    // For oppo() primitives, use 'loc' as index.
-    static int loc2oppo[4];
-
-    // For fnext() primitives, use 'loc' as first index and 'ver' as second
-    //   index, return a new 'loc' and new 'ver' in an int array.
-    // Note: Only valid for face version = 0, 2, 4.
-    static int locver2nextf[4][6][2];
-
-    static int plus1mod3[3];
-    static int minus1mod3[3];
-
-    // Some macros for convenience
-    #define Div2  >> 1
-    #define Mod2  & 01
-    // NOTE: These bit operators should only be used in macros below.
-
-    // Get orient(Range from 0 to 2) from face version(Range from 0 to 5).
-    #define Orient(V)   ((V) Div2)
-
-    // Determine edge ring(0 or 1) from face version(Range from 0 to 5).
-    #define EdgeRing(V) ((V) Mod2)
-
-    ////////////////////////////////////////////////////////////////////////
-    // Primitives for tetrahedron                                         //
-    ////////////////////////////////////////////////////////////////////////
-
-    // decode() converts a pointer to a triface.  The location is
-    //   extracted from the two least significant bits of the pointer.
-    static void decode(tetrahedron ptr, triface& tface) {
-      tface.loc = (int) ((unsigned long) (ptr) & (unsigned long) 3l);
-      tface.tet = (tetrahedron *)
-                  ((unsigned long) (ptr) & ~(unsigned long) 7l);
-    }
-
-    // encode() compresses a triface into a single pointer.  It relies on
-    //   the assumption that all tetrahedra are aligned to four-byte
-    //   boundaries, so the two least significant bits of (triface).tet are
-    //   zero.
-    static tetrahedron encode(triface& tface) {
-      return (tetrahedron)
-             ((unsigned long) tface.tet | (unsigned long) tface.loc);
-    }
-
-    // sym() finds the abutting tetrahedron on the same face.
-    static void sym(triface& tface1, triface& tface2) {
-      tetrahedron ptr = tface1.tet[tface1.loc];
-      decode(ptr, tface2);
-    }
-
-    static void symself(triface& tface) {
-      tetrahedron ptr = tface.tet[tface.loc];
-      decode(ptr, tface);
-    }
-
-    // The bond() and dissolve() primitives are just like the splice()
-    //   primitive of Mucke[2]'s.
-
-    // Bond two tetrahedra together at their faces.
-    static void bond(triface& tface1, triface& tface2) {
-      tface1.tet[tface1.loc] = encode(tface2);
-      tface2.tet[tface2.loc] = encode(tface1);
-    }
-
-    // Dissolve a bond (from one side).  Note that the other tetrahedron
-    //   will still think it's connected to this tetrahedron.  Usually,
-    //   however, the other tetrahedron is being deleted entirely, or bonded
-    //   to another tetrahedron, so it doesn't matter.
-    // Note: 'dummytet' isn't a static member variable of class, that's
-    //   the reason why dissolve() can not be declared with 'static'.
-    void dissolve(triface& tface) {
-      tface.tet[tface.loc] = (tetrahedron) dummytet;
-    }
-
-    // These primitives determine or set the origin, destination, apex or
-    //   opposition of a tetrahedron with respect to 'loc' and 'ver'.
-
-    static void org(triface& tface, point3d& pointptr) {
-      pointptr = (point3d) tface.tet[locver2org[tface.loc][tface.ver] + 4];
-    }
-
-    static point3d org(triface& tface) {
-      return (point3d) tface.tet[locver2org[tface.loc][tface.ver] + 4];
-    }
-
-    static void dest(triface& tface, point3d& pointptr) {
-      pointptr = (point3d) tface.tet[locver2dest[tface.loc][tface.ver] + 4];
-    }
-
-    static point3d dest(triface& tface) {
-      return (point3d) tface.tet[locver2dest[tface.loc][tface.ver] + 4];
-    }
-
-    static void apex(triface& tface, point3d& pointptr) {
-      pointptr = (point3d) tface.tet[locver2apex[tface.loc][tface.ver] + 4];
-    }
-
-    static point3d apex(triface& tface) {
-      return (point3d) tface.tet[locver2apex[tface.loc][tface.ver] + 4];
-    }
-
-    static void oppo(triface& tface, point3d& pointptr) {
-      pointptr = (point3d) tface.tet[loc2oppo[tface.loc] + 4];
-    }
-
-    static point3d oppo(triface& tface) {
-      return (point3d) tface.tet[loc2oppo[tface.loc] + 4];
-    }
-
-    static void setorg(triface& tface, point3d pointptr) {
-      tface.tet[locver2org[tface.loc][tface.ver] + 4] = (tetrahedron) pointptr;
-    }
-
-    static void setdest(triface& tface, point3d pointptr) {
-      tface.tet[locver2dest[tface.loc][tface.ver] + 4] = (tetrahedron) pointptr;
-    }
-
-    static void setapex(triface& tface, point3d pointptr) {
-      tface.tet[locver2apex[tface.loc][tface.ver] + 4] = (tetrahedron) pointptr;
-    }
-
-    static void setoppo(triface& tface, point3d pointptr) {
-      tface.tet[loc2oppo[tface.loc] + 4] = (tetrahedron) pointptr;
-    }
-
-    static void setvertices2null(triface& tface) {
-      tface.tet[4] = (tetrahedron) NULL;
-      tface.tet[5] = (tetrahedron) NULL;
-      tface.tet[6] = (tetrahedron) NULL;
-      tface.tet[7] = (tetrahedron) NULL;
-    }
-
-    // These primitives were drived from Mucke[2]'s triangle-based data
-    //   structure to change face-edge relation in a tetrahedron (esym,
-    //   enext and enext2) or between two tetrahedra (fnext).
-
-    // If e0 = e(i, j), e1 = e(j, i), that is e0 and e1 are the two
-    //   direction of the same undirected edge of a triangular face.
-    //   e0.sym() = e1 and vice versa.
-    static void esym(triface& tface1, triface& tface2) {
-      tface2.tet = tface1.tet;
-      tface2.loc = tface1.loc;
-      tface2.ver = tface1.ver + (EdgeRing(tface1.ver) ? -1 : 1);
-    }
-
-    static void esymself(triface& tface) {
-      tface.ver += (EdgeRing(tface.ver) ? -1 : 1);
-    }
-
-    // If e0 and e1 are both in the same edge ring of a triangular face,
-    //   e1 = e0.enext(). Then e1 is the successor of e0.
-    static void enext(triface& tface1, triface& tface2) {
-      tface2.tet = tface1.tet;
-      tface2.loc = tface1.loc;
-      tface2.ver = ve[tface1.ver];
-    }
-
-    static void enextself(triface& tface) {
-      tface.ver = ve[tface.ver];
-    }
-
-    // enext2() is equal to e2 = e0.enext().enext()
-    static void enext2(triface& tface1, triface& tface2) {
-      tface2.tet = tface1.tet;
-      tface2.loc = tface1.loc;
-      tface2.ver = ve[ve[tface1.ver]];
-    }
-
-    static void enext2self(triface& tface) {
-      tface.ver = ve[ve[tface.ver]];
-    }
-
-    // If f0 and f1 are both in the same triangle ring of a triangular face,
-    //   f1 = f0.fnext(), Then f1 is the successor of f0. Return true if f1
-    //   exist. Return false if f1 not exist(f0 is a boundary face).
-    #define fnext(triface1, triface2)                                      \
-      getnextface(&(triface1), &(triface2))
-
-    #define fnextself(triface)                                             \
-      getnextface(&(triface), NULL)
-
-    // enextfnext() and enext2fnext() are combination primitives of enext()
-    //   and fnext().
-    #define enextfnext(triface1, triface2)                                 \
-      enext(triface1, triface2);                                           \
-      fnextself(triface2)
-
-    #define enextfnextself(triface)                                        \
-      enextself(triface);                                                  \
-      fnextself(triface)
-
-    #define enext2fnext(triface1, triface2)                                \
-      enext2(triface1, triface2);                                          \
-      fnextself(triface2)
-
-    #define enext2fnextself(triface)                                       \
-      enext2self(triface);                                                 \
-      fnextself(triface)
-
-    // Primitives to infect or cure a tetrahedron with the virus. These rely
-    //   on the assumption that all tetrahedron are aligned to eight-byte
-    //   boundaries.
-    static void infect(triface& tface) {
-      tface.tet[0] = (tetrahedron)
-                    ((unsigned long) tface.tet[0] | (unsigned long) 4l);
-    }
-
-    static void uninfect(triface& tface) {
-      tface.tet[0] = (tetrahedron)
-                  ((unsigned long) tface.tet[0] & ~ (unsigned long) 4l);
-    }
-
-    // Test a tetrahedron for viral infection.
-    static bool infected(triface& tface) {
-      return (((unsigned long) tface.tet[0] & (unsigned long) 4l) != 0);
-    }
-
-    // Check or set a tetrahedron's attributes.
-    REAL elemattribute(tetrahedron* ptr, int attnum) {
-      return ((REAL *) (ptr))[elemattribindex + attnum];
-    }
-
-    void setelemattribute(tetrahedron* ptr, int attnum, REAL value) {
-      ((REAL *) (ptr))[elemattribindex + attnum] = value;
-    }
-
-    // Check or set a tetrahedron's maximum volume bound.
-    REAL volumebound(tetrahedron* ptr) {
-      return ((REAL *) (ptr))[volumeboundindex];
-    }
-
-    void setvolumebound(tetrahedron* ptr, REAL value) {
-      ((REAL *) (ptr))[volumeboundindex] = value;
-    }
-
-    ////////////////////////////////////////////////////////////////////////
-    // Primitives for shellface                                           //
-    ////////////////////////////////////////////////////////////////////////
-
-    // sdecode() converts a pointer to an oriented shell face.  The face
-    //   version is extracted from the least three significant bit of the
-    //   pointer.  The three least significant bits are masked out to
-    //   produce the real pointer.
-    static void sdecode(shellface sptr, face& sface) {
-      sface.shver = (int) ((unsigned long) (sptr) & (unsigned long) 7l);
-      sface.sh = (shellface *)
-             ((unsigned long) (sptr) & ~ (unsigned long) 7l);
-    }
-
-    // sencode() compresses an oriented shell face into a single pointer.
-    //   It relies on the assumption that all shell faces are aligned to
-    //   eight-byte boundaries, so the least three significant bit of
-    //   (face).sh is zero.
-    static shellface sencode(face& sface) {
-      return (shellface)
-             ((unsigned long) sface.sh | (unsigned long) sface.shver);
-    }
-
-    // spivot() finds the other shell face (from the same face) that shares
-    //   the same edge.
-    static void spivot(face& sface1, face& sface2) {
-      shellface sptr = sface1.sh[Orient(sface1.shver)];
-      sdecode(sptr, sface2);
-    }
-
-    static void spivotself(face& sface) {
-      shellface sptr = sface.sh[Orient(sface.shver)];
-      sdecode(sptr, sface);
-    }
-
-    // Bond two shell faces together.
-    static void sbond(face& sface1, face& sface2) {
-      sface1.sh[Orient(sface1.shver)] = sencode(sface2);
-      sface2.sh[Orient(sface2.shver)] = sencode(sface1);
-    }
-
-    // Dissolve a shell face bond (from one side).  Note that the other
-    //   shell face will still think it's connected to this shell face.
-    // Note: 'dummysh' isn't a static member variable of class, that's
-    //   the reason why sdissolve() can not be declared with 'static'.
-    void sdissolve(face& sface) {
-      sface.sh[Orient(sface.shver)] = (shellface) dummysh;
-    }
-
-    // These primitives determine or set the origin, destination, or apex
-    //   of a shell face with respect to current face version.
-
-    static void sorg(face& sface, point3d& pointptr) {
-      pointptr = (point3d) sface.sh[3 + vo[sface.shver]];
-    }
-
-    static point3d sorg(face& sface) {
-      return (point3d) sface.sh[3 + vo[sface.shver]];
-    }
-
-    static void sdest(face& sface, point3d& pointptr) {
-      pointptr = (point3d) sface.sh[3 + vd[sface.shver]];
-    }
-
-    static point3d sdest(face& sface) {
-      return (point3d) sface.sh[3 + vd[sface.shver]];
-    }
-
-    static void sapex(face& sface, point3d& pointptr) {
-      pointptr = (point3d) sface.sh[3 + va[sface.shver]];
-    }
-
-    static point3d sapex(face& sface) {
-      return (point3d) sface.sh[3 + va[sface.shver]];
-    }
-
-    static void setsorg(face& sface, point3d pointptr) {
-      sface.sh[3 + vo[sface.shver]] = (shellface) pointptr;
-    }
-
-    static void setsdest(face& sface, point3d pointptr) {
-      sface.sh[3 + vd[sface.shver]] = (shellface) pointptr;
-    }
-
-    static void setsapex(face& sface, point3d pointptr) {
-      sface.sh[3 + va[sface.shver]] = (shellface) pointptr;
-    }
-
-    // These primitives were drived from Mucke[2]'s triangle-based data
-    //   structure to change face-edge relation in a tetrahedron (sesym,
-    //   senext and senext2).
-
-    static void sesym(face& sface1, face& sface2) {
-      sface2.sh = sface1.sh;
-      sface2.shver = sface1.shver + (EdgeRing(sface1.shver) ? -1 : 1);
-    }
-
-    static void sesymself(face& sface) {
-      sface.shver += (EdgeRing(sface.shver) ? -1 : 1);
-    }
-
-    static void senext(face& sface1, face& sface2) {
-      sface2.sh = sface1.sh;
-      sface2.shver = ve[sface1.shver];
-    }
-
-    static void senextself(face& sface) { sface.shver = ve[sface.shver]; }
-
-    static void senext2(face& sface1, face& sface2) {
-      sface2.sh = sface1.sh;
-      sface2.shver = ve[ve[sface1.shver]];
-    }
-
-    static void senext2self(face& sface) {
-      sface.shver = ve[ve[sface.shver]];
-    }
-
-    // These primitives read or set a shell marker.  Shell markers are used
-    //   to hold user boundary information.
-
-    static int mark(face& sface) { return (* (int *) (sface.sh + 11)); }
-
-    static void setmark(face& sface, int value) {
-      * (int *) (sface.sh + 11) = value;
-    }
-
-    // Primitives to infect or cure a shell face with the virus. These rely
-    //   on the assumption that all shell face are aligned to eight-byte
-    //   boundaries.
-    static void sinfect(face& sface) {
-      sface.sh[10] = (shellface)
-                     ((unsigned long) sface.sh[10] | (unsigned long) 4l);
-    }
-
-    static void suninfect(face& sface) {
-      sface.sh[10] = (shellface)
-                     ((unsigned long) sface.sh[10] & ~ (unsigned long) 4l);
-    }
-
-    // Test a shell face for viral infection.
-    static bool sinfected(face& sface) {
-      return (((unsigned long) sface.sh[10] & (unsigned long) 4l) != 0);
-    }
-
-    ////////////////////////////////////////////////////////////////////////
-    // Primitives for interacting tetrahedra and subfaces                 //
-    ////////////////////////////////////////////////////////////////////////
-
-    // tspivot() finds a subface abutting on this tetrahdera.
-    static void tspivot(triface& tface, face& sface) {
-      shellface sptr = (shellface) tface.tet[8 + tface.loc];
-      sdecode(sptr, sface);
-    }
-
-    // stpivot() finds a tetrahedron abutting a subface.
-    static void stpivot(face& sface, triface& tface) {
-      tetrahedron ptr = (tetrahedron) sface.sh[6 + EdgeRing(sface.shver)];
-      decode(ptr, tface);
-    }
-
-    // tsbond() bond a tetrahedron to a subface.
-    static void tsbond(triface& tface, face& sface) {
-      tface.tet[8 + tface.loc] = (tetrahedron) sencode(sface);
-      sface.sh[6 + EdgeRing(sface.shver)] = (shellface) encode(tface);
-    }
-
-    // tsdissolve() dissolve a bond (from the tetrahedron side).
-    void tsdissolve(triface& tface) {
-      tface.tet[8 + tface.loc] = (tetrahedron) dummysh;
-    }
-
-    // stdissolve() dissolve a bond (from the subface side).
-    void stdissolve(face& sface) {
-      sface.sh[6 + EdgeRing(sface.shver)] = (shellface) dummytet;
-    }
-
-    ////////////////////////////////////////////////////////////////////////
-    // Primitives for interacting subfaces and subsegments                //
-    ////////////////////////////////////////////////////////////////////////
-
-    // sspivot() finds a subsegment abutting a subface.
-    static void sspivot(face& sface, face& edge) {
-      shellface sptr = (shellface) sface.sh[8 + Orient(sface.shver)];
-      sdecode(sptr, edge);
-    }
-
-    // ssbond() bond a subface to a subsegment.
-    static void ssbond(face& sface, face& edge) {
-      sface.sh[8 + Orient(sface.shver)] = sencode(edge);
-      edge.sh[0] = sencode(sface);
-    }
-
-    // ssdisolve() dissolve a bond (from the subface side)
-    void ssdissolve(face& sface) {
-      sface.sh[8 + Orient(sface.shver)] = (shellface) dummysh;
-    }
-
-    ////////////////////////////////////////////////////////////////////////
-    // Primitives for point3d                                             //
-    ////////////////////////////////////////////////////////////////////////
-
-    int pointmark(point3d pt) { return ((int *) (pt))[pointmarkindex]; }
-
-    void setpointmark(point3d pt, int value) {
-      ((int *) (pt))[pointmarkindex] = value;
-    }
-
-    tetrahedron point2tet(point3d pt) {
-      return ((tetrahedron *) (pt))[point2tetindex];
-    }
-
-    void setpoint2tet(point3d pt, tetrahedron value) {
-      ((tetrahedron *) (pt))[point2tetindex] = value;
-    }
-
-    ////////////////////////////////////////////////////////////////////////
-    // Advanced primitives                                                //
-    ////////////////////////////////////////////////////////////////////////
-
-    // Implement the fnext(), fnextself() primitives of tetrahedron.
-    bool getnextface(triface*, triface*);
-
-    // Finds a subsegment abutting on this tetrahdera.
-    void tsspivot(triface*, face*);
-
-    // Finds a tetrahedron abutting a subsegment.
-    void sstpivot(face*, triface*);
-
-    ////////////////////////////////////////////////////////////////////////
-    // Useful auxiliary primitives                                        //
-    ////////////////////////////////////////////////////////////////////////
-
-    // Find and set version to indicate the directed edge.
-    static void findversion(triface*, point3d, point3d, int symflag = 1);
-    static void findversion(triface*, triface*, int symflag = 1);
-    static void findversion(triface*, face*, int symflag = 1);
-    static void findversion(face*, point3d, point3d, int symflag = 1);
-    static void findversion(face*, triface*, int symflag = 1);
-    static void findversion(face*, face*, int symflag = 1);
-
-    // Find and set the version to indicate the desired point.
-    bool findorg(triface*, point3d);
-    bool findorg(face*, point3d);
-
-    // Adjusts edge version(ver) to corresponding edge ring if necessary.
-    //   Here direction is only valid for 0(CCW) or 1(CW).
-    static void adjustedgering(triface& tface, int direction) {
-      if (EdgeRing(tface.ver) != direction) {
-        esymself(tface);
-      }
-    }
-
-    // Returns true if adjoining tetrahedron exist.
-    // Note: 'dummytet' is not a static member variable.
-    bool issymexist(triface* tface) {
-      tetrahedron *ptr = (tetrahedron *)
-        ((unsigned long)(tface->tet[tface->loc]) & ~(unsigned long)3l);
-      return ptr != dummytet;
-    }
-
-    // Returns true if this tetrahedron is dealloced.
-    static bool isdead(triface* tface) {
-      if (tface->tet == (tetrahedron*) NULL) {
-        return true;
-      } else {
-        return tface->tet[4] == (tetrahedron) NULL;
-      }
-    }
-
-    // Returns true if this shellface is dealloced.
-    static bool isdead(face* sface) {
-      if (sface->sh == (shellface*) NULL) {
-        return true;
-      } else {
-        return sface->sh[3] == (shellface) NULL;
-      }
-    }
-
-    // Test if the subface is a non-solid subface. Every non-solid subface
-    //   is marked with a special flag NONSOLIDFLAG.
-    static bool isnonsolid(face& sface) {
-      return mark(sface) == NONSOLIDFLAG;
-    }
-
-    // Return true if the point is one of vertices of input triangular face.
-    static bool isfacehaspoint(triface* tface, point3d testpoint) {
-      return  ((org(*tface) == testpoint)
-               || (dest(*tface) == testpoint)
-               || (apex(*tface) == testpoint));
-    }
-
-    // Compare the coordinates of two points to see if they are coincident.
-    //   Return true if they are coincident, otherwise return false;
-    bool issamepoint(point3d p1, point3d p2) {
-      return (fabs(p1[0] - p2[0]) <= usertolerance)
-              && (fabs(p1[1] - p2[1]) <= usertolerance)
-              && (fabs(p1[2] - p2[2]) <= usertolerance);
-    }
-
-    // Returns true if the edge of tetrahedron(specified by loc and ver)
-    //   is a ridge in the mesh.
-    bool isridge(triface*);
-
-    // Test if there exist any segment shars with input segment's origin.
-    //   Return true if exist such segment, otherwise return false.
-    bool isexistincidentseg(face*);
-
-    // Compare the vertices of two faces/edges to see if they are the same
-    //   face/edge. The inputs are handles of two tetrahedra. Only return
-    //   0 (same) or 1 (diffrent). The two primitives mainly used as list
-    //   or link's linear order functions.
-    static int issameface(triface*, triface*);
-    static int issameedge(triface*, triface*);
-
-    // For debuging, print out the details of a tetrahedron/shellfacet
-    //   handle to standard output.
-    void dump(triface*);
-    void dump(face*);
-
-    ////////////////////////////////////////////////////////////////////////
-    // End of mesh manipulation primitives                                //
-    ////////////////////////////////////////////////////////////////////////
-
-    ////////////////////////////////////////////////////////////////////////
-    // Commonly used vector operations                                    //
-    ////////////////////////////////////////////////////////////////////////
-
-    // Assign3D(), Return: vres = va.
-    static void Assign3D(REAL* va, REAL* vres) {
-      vres[0] = va[0]; vres[1] = va[1]; vres[2] = va[2];
-    }
-
-    // Sub3D(), Return: vres = va - vb.
-    static void Sub3D(REAL* va, REAL* vb, REAL* vres) {
-      vres[0] = va[0] - vb[0];
-      vres[1] = va[1] - vb[1];
-      vres[2] = va[2] - vb[2];
-    }
-
-    // Scale3D(), Return: vres = vres * scale.
-    static void Scale3D(REAL* vres, REAL scale) {
-      vres[0] *= scale; vres[1] *= scale; vres[2] *= scale;
-    }
-
-    // Dot3D(), Return: va dot vb.
-    static REAL Dot3D(REAL* va, REAL* vb) {
-      return (va[0] * vb[0] + va[1] * vb[1] + va[2] * vb[2]);
-    }
-
-    // Cross3D(), Return: vres = va cross vb.
-    static void Cross3D(REAL* va, REAL* vb, REAL* vres) {
-      vres[0] = va[1] * vb[2] - va[2] * vb[1];
-      vres[1] = va[2] * vb[0] - va[0] * vb[2];
-      vres[2] = va[0] * vb[1] - va[1] * vb[0];
-    }
-
-    // Mag3D(), Return: Mod of va.
-    static REAL Mag3D(REAL* va) {
-      return sqrt(va[0] * va[0] + va[1] * va[1] + va[2] * va[2]);
-    }
-
-    // Dist3D(), Return the Euler distance of va and vb.
-    static REAL Dist3D(REAL* va, REAL* vb) {
-      return sqrt((va[0] - vb[0]) * (va[0] - vb[0])
-                  + (va[1] - vb[1]) * (va[1] - vb[1])
-                  + (va[2] - vb[2]) * (va[2] - vb[2]));
-    }
-
-    // Normal3D(), Compute the vector normal for a set of three points.
-    static void Normal3D(REAL* va, REAL* vb, REAL* vc, REAL* vnormal) {
-      REAL tempb[3], tempc[3];
-      Sub3D(vb, va, tempb);
-      Sub3D(vc, va, tempc);
-      Cross3D(tempb, tempc, vnormal);
-    }
-
-    // Normalize3D(), Return: Unit vector of va.
-    static void Normalize3D(REAL* va) {
-      REAL invmag = 1. / Mag3D(va);
-      Scale3D(va, invmag);
-    }
-
-    static void Swap3D(REAL* va, REAL* vb) {
-      REAL temp;
-      temp = vb[0]; vb[0] = va[0]; va[0] = temp;
-      temp = vb[1]; vb[1] = va[1]; va[1] = temp;
-      temp = vb[2]; vb[2] = va[2]; va[2] = temp;
-    }
-
-    ////////////////////////////////////////////////////////////////////////
-    // End of commonly used vector operations                             //
-    ////////////////////////////////////////////////////////////////////////
-
-    // Memory management routines
-    void dummyinit(int, int);
-    void initializepointpool();
-    void initializetetshpools();
-    void tetrahedrondealloc(tetrahedron*);
-    tetrahedron *tetrahedrontraverse();
-    void shellfacedealloc(memorypool*, shellface*);
-    shellface *shellfacetraverse(memorypool*);
-    void badsegmentdealloc(badface3d*);
-    badface3d *badsegmenttraverse();
-    void pointdealloc(point3d);
-    point3d pointtraverse();
-    point3d getpoint(int number);
-    // tetrahedron, subface and subsegment construct routines
-    void maketetrahedron(triface*);
-    void makeshellface(memorypool*, face*);
-
-    // Geometric primitives.
-    inline bool iszero(const REAL);
-    int iorient3d(point3d, point3d, point3d, point3d);
-    int iinsphere(point3d, point3d, point3d, point3d, point3d);
-    int iinsphere(triface*, point3d);
-    bool isbelowplane(point3d, point3d, point3d, point3d);
-    bool isbelowplane(triface*, point3d);
-    bool isaboveplane(point3d, point3d, point3d, point3d);
-    bool isaboveplane(triface*, point3d);
-    bool iscoplane(point3d, point3d, point3d, point3d);
-    bool iscoplane(triface*, point3d);
-    bool iscoline(point3d, point3d, point3d);
-
-    // Geometric functions.
-    void projontoface(point3d, point3d, point3d, point3d);
-    void circumcenter(point3d, point3d, point3d, point3d);
-    void circumcenter(point3d, point3d, point3d, point3d, point3d);
-    REAL tetvolume(point3d, point3d, point3d, point3d);
-    REAL facedihedral(point3d, point3d, point3d, point3d, point3d, point3d);
-    void tetalldihedral(point3d, point3d, point3d, point3d, REAL[6]);
-
-    // Point location routines.
-    // (Fast Randomized Point Location Algorithm of Mucke, Issac and Zhu.)
-    unsigned long randomnation(unsigned int);
-    void makepointmap();
-    REAL distance(triface*, point3d);
-    enum locateresult isintet(point3d, point3d, point3d, point3d, point3d);
-    enum locateresult iscoplanarintri(point3d, triface*);
-    enum locateresult preciselocate(point3d, triface*);
-    enum locateresult locate(point3d, triface*);
-
-    // Mesh transformation routines.
-    enum facecategory categorizeface(triface&);
-    bool querydoswap(triface&);
-    // bool querydoswap(triface&, enum facecategory);
-    void preservesubsegments(face&, triface&);
-    void enqueuefliplist(triface&);
-    bool dequeuefliplist(triface&);
-    int flip23(triface&);
-    int flip32(triface&);
-    int flip22(triface&);
-    int flip44(triface&);
-    int flip(triface&);
-
-    // Insert/Delete point routines.
-    enum insertsiteresult insertsite(point3d, triface*, face*, face*);
-    int insertonedge(point3d, triface*, face*);
-    int insertonface(point3d, triface*, face*);
-    int insertininterior(point3d, triface*);
-    void insertsubface(triface*, int, int);
-    void insertsubsegment(triface*, int);
-    int deletesite(triface*);
-
-    // Giftwrapping Algorithm
-    int is_face_tet_inter_0(triface*, point3d, point3d, point3d, point3d);
-    int is_face_tet_inter_1(triface*, point3d, point3d, point3d, point3d);
-    int is_face_tet_inter_2(triface*, point3d, point3d, point3d, point3d);
-    int getgiftface(list*, int, int*, list*);
-    int getgiftpoint(triface*, list*, int, point3d*, int*, list*, list*);
-    int giftwrapping(int, triface*, int, point3d*, REAL*, REAL, list*);
-
-    // Delaunay tetrahedrization construct routines.
-    // (Randomized Incremental Flip Algorithm.)
-    void construct_initial_tetra(queue*);
-    void collect_visibles(point3d, triface*, triface*, link*);
-    int dofliplist();
-    long rand_incr_flip_delaunay();
-    long delaunay();
-
-    // Segment/facet (boundary) constrained routines.
-    enum finddirectionresult finddirection(triface*, point3d);
-    void segmentintersection(triface*, face*, point3d);
-    int scoutsegment(triface*, point3d, int);
-    void conformingedge(point3d, point3d, int);
-    void insertsegment(point3d, point3d, int);
-    void getsteinersinseg(point3d, point3d, list*);
-    int getdiagonalapexindex(struct triangulateio*, int, int);
-    int getneighbourtriedge(struct triangulateio*, int, int, int*, int*);
-    int swapdiagonal(struct triangulateio*, int, int, int);
-    enum matchfaceresult matchface(point3d, point3d, point3d, triface*, int);
-    int insertfieldpoint(int, triface*, int, point3d*, list*);
-    int recoverface(list*, triangulateio*, int, int);
-    void insertfacet(list*, list*, int, int);
-    int formskeleton(FILE*);
-
-    // Carving out holes and concavities routines.
-    void infecthull();
-    void plague();
-    void regionplague(REAL, REAL);
-    void carveholes(REAL*, int, REAL*, int);
-
-    // Mesh quality testing routines.
-    void checkquality(triface*);
-    int checkedge4encroach(face*, point3d testpoint = NULL);
-    int checkface4encroach(face*, point3d testpoint = NULL);
-    void testtetrahedron(triface*);
-    void enqueuebadface(face*, point3d, int);
-    badface3d *dequeuebadface();
-    void enqueuebadtet(triface*, REAL, point3d, point3d, point3d, point3d,
-                       point3d);
-    badtet *dequeuebadtet();
-    // Mesh quality maintenance routines.
-    void tallyencsegs();
-    void tallyencfaces();
-    void tallytets();
-    void repairencsegs();
-    void repairencfaces();
-    void splittet(badtet*);
-    void enforcequality();
-
-    // File I/O routines.
-    char *readline(char*, FILE*, char*);
-    char *findfield(char*);
-    void readnodes(FILE**);
-    void readholes(FILE*, REAL**, int*, REAL**, int*);
-    void numbernodes(int myfirstnumber = 0);
-    void outnodes();
-    void outelems();
-    void outfaces(int hull = 0);
-    void outedges();
-    void outneighbors();
-    void outoff();
-    void outelems2gid();
-    void outfaces2gid(int hull = 0);
-    void outedges2gid();
-    void outelems2fa();
-
-    // Debug routines.
-    void dumpgifts(char*, list*, int, point3d*, int*);
-    void dumplist(char*, list*, int, int);
-    void dumpallbadelems(char*);
-
-    void internalerror();
-    void precisionerror();
-    void recovererror();
-
-    void checkmesh();
-    void checkdelaunay();
-    void checkshells();
-    void statistics();
-    void quality_statistics();
-    void syntax();
-
-    void meshinit();
-    void meshdeinit();
-    void parsecommandline(int, char**);
-
-  public:
-
-    mesh3d() { meshinit(); }
-    ~mesh3d() { meshdeinit(); }
-
-    // General mesh construction.
-    void triangulate(int, char**);
-};
-
-#endif // #ifndef tetlibH
diff --git a/Tetgen/tetmain.cpp b/Tetgen/tetmain.cpp
deleted file mode 100644
index ded9d1649a..0000000000
--- a/Tetgen/tetmain.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-
-#include "tetlib.h"
-
-int main(int argc, char* argv[])
-{
-  mesh3d mymesh;
-
-  mymesh.triangulate(argc, argv);
-
-  return 0;
-}
diff --git a/Tetgen/trilib.cpp b/Tetgen/trilib.cpp
deleted file mode 100644
index b4cab2f132..0000000000
--- a/Tetgen/trilib.cpp
+++ /dev/null
@@ -1,5602 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// trilib.cpp    Implementation file for two-dimensional mesh generator.     //
-//                                                                           //
-// Tetgen Version 1.0 beta                                                   //
-// July, 2001                                                                //
-//                                                                           //
-// Si hang                                                                   //
-// Email: sihang@weboo.com                                                   //
-// http://www.weboo.com/sh/tetgen.htm                                        //
-//                                                                           //
-// You are free to use, copy and modify the sources under certain            //
-// circumstances, provided this copyright notice remains intact.             //
-// See the file LICENSE for details.                                         //
-//                                                                           //
-// This file with it's couple file trilib.h are modified version of the      //
-// triangle program of Jonathan Richard Shewchuk, which is public available  //
-// from the following Web page with its license(see trilib.h):               //
-//                                                                           //
-//              http://www.cs.cmu.edu/~quake/triangle.html                   //
-//                                                                           //
-// Please see trilib.h for description of how to use this modified codes     //
-// of triangle.                                                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-/*****************************************************************************/
-/*                                                                           */
-/*  Traingle program license:                                                */
-/*                                                                           */
-/*  Triangle                                                                 */
-/*  A Two-Dimensional Quality Mesh Generator                                 */
-/*  and Delaunay Triangulator.                                               */
-/*  Version 1.3                                                              */
-/*                                                                           */
-/*  Copyright 1996                                                           */
-/*  Jonathan Richard Shewchuk                                                */
-/*  School of Computer Science                                               */
-/*  Carnegie Mellon University                                               */
-/*  5000 Forbes Avenue                                                       */
-/*  Pittsburgh, Pennsylvania  15213-3891                                     */
-/*  jrs@cs.cmu.edu                                                           */
-/*                                                                           */
-/*  This program may be freely redistributed under the condition that the    */
-/*    copyright notices (including this entire header and the copyright      */
-/*    notice printed when the `-h' switch is selected) are not removed, and  */
-/*    no compensation is received.  Private, research, and institutional     */
-/*    use is free.  You may distribute modified versions of this code UNDER  */
-/*    THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE   */
-/*    SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE   */
-/*    AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR    */
-/*    NOTICE IS GIVEN OF THE MODIFICATIONS.  Distribution of this code as    */
-/*    part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT  */
-/*    WITH THE AUTHOR.  (If you are not directly supplying this code to a    */
-/*    customer, and you are instead telling them how they can obtain it for  */
-/*    free, then you are not required to make any arrangement with me.)      */
-/*                                                                           */
-/*  Disclaimer:  Neither I nor Carnegie Mellon warrant this code in any way  */
-/*    whatsoever.  This code is provided "as-is".  Use at your own risk.     */
-/*                                                                           */
-/*****************************************************************************/
-
-#include "trilib.h"
-
-/********* struct triangulateio routines begin here                  *********/
-/**                                                                         **/
-/**                                                                         **/
-
-void triangulateioinit(struct triangulateio* io)
-{
-  io->pointlist = NULL;
-  io->pointattributelist = NULL;
-  io->pointmarkerlist = NULL;
-  io->numberofpoints = 0;
-  io->numberofpointattributes = 0;
-
-  io->trianglelist = NULL;
-  io->triangleattributelist = NULL;
-  io->trianglearealist = NULL;
-  io->neighborlist = NULL;
-  io->numberoftriangles = 0;
-  io->numberofcorners = 0;
-  io->numberoftriangleattributes = 0;
-
-  io->segmentlist = NULL;
-  io->segmentmarkerlist = NULL;
-  io->numberofsegments = 0;
-
-  io->holelist = NULL;
-  io->numberofholes = 0;
-
-  io->regionlist = NULL;
-  io->numberofregions = 0;
-
-  io->edgelist = NULL;
-  io->edgemarkerlist = NULL;
-  io->normlist = NULL;
-  io->numberofedges = 0;
-}
-
-void triangulateiodeinit(struct triangulateio* io)
-{
-  if (io->numberofpoints && io->pointlist) {
-    delete [] io->pointlist;
-    io->pointlist = NULL;
-    io->numberofpoints = 0;
-  }
-  if (io->numberofpointattributes && io->pointattributelist) {
-    delete [] io->pointattributelist;
-    io->pointattributelist = NULL;
-    io->numberofpointattributes = 0;
-  }
-  if (io->pointmarkerlist) {
-    delete [] io->pointmarkerlist;
-    io->pointmarkerlist = NULL;
-  }
-
-  if (io->numberoftriangles && io->trianglelist) {
-    delete [] io->trianglelist;
-    io->trianglelist = NULL;
-    io->numberoftriangles = 0;
-    io->numberofcorners = 0;
-  }
-  if (io->numberoftriangleattributes && io->triangleattributelist) {
-    delete [] io->triangleattributelist;
-    io->triangleattributelist = NULL;
-    io->numberoftriangleattributes = 0;
-  }
-  if (io->trianglearealist) {
-    delete [] io->trianglearealist;
-    io->trianglearealist = NULL;
-  }
-  if (io->neighborlist) {
-    delete [] io->neighborlist;
-    io->neighborlist = NULL;
-  }
-
-  if (io->numberofsegments && io->segmentlist) {
-    delete [] io->segmentlist;
-    io->segmentlist = NULL;
-    io->numberofsegments = 0;
-  }
-  if (io->segmentmarkerlist) {
-    delete [] io->segmentmarkerlist;
-    io->segmentmarkerlist = NULL;
-  }
-
-  if (io->numberofholes && io->holelist) {
-    delete [] io->holelist;
-    io->holelist = NULL;
-    io->numberofholes = 0;
-  }
-
-  if (io->numberofregions && io->regionlist) {
-    delete [] io->regionlist;
-    io->regionlist = NULL;
-    io->numberofregions = 0;
-  }
-
-  if (io->numberofedges && io->edgelist) {
-    delete [] io->edgelist;
-    io->edgelist = NULL;
-    io->numberofedges = 0;
-  }
-  if (io->edgemarkerlist) {
-    delete [] io->edgemarkerlist;
-    io->edgemarkerlist = NULL;
-  }
-  if (io->normlist) {
-    delete [] io->normlist;
-    io->normlist = NULL;
-  }
-}
-
-void triangulateioreport(struct triangulateio *io, int markers,
-  int reporttriangles, int reportneighbors, int reportsegments,
-  int reportedges, int reportnorms)
-{
-  int i, j;
-
-  if (io->numberofpoints && io->pointlist)  {
-    for (i = 0; i < io->numberofpoints; i++) {
-      printf("Point %4d:", i + 1);
-      for (j = 0; j < 2; j++) {
-        printf("  %.6g", io->pointlist[i * 2 + j]);
-      }
-      if (io->numberofpointattributes > 0) {
-        printf("   attributes");
-      }
-      for (j = 0; j < io->numberofpointattributes; j++) {
-        printf("  %.6g",
-               io->pointattributelist[i * io->numberofpointattributes + j]);
-      }
-      if (markers) {
-        printf("   marker %d\n", io->pointmarkerlist[i]);
-      } else {
-        printf("\n");
-      }
-    }
-    printf("\n");
-  }
-
-  if (reporttriangles || reportneighbors) {
-    for (i = 0; i < io->numberoftriangles; i++) {
-      if (reporttriangles) {
-        printf("Triangle %4d points:", i + 1);
-        for (j = 0; j < io->numberofcorners; j++) {
-          printf("  %4d", io->trianglelist[i * io->numberofcorners + j] + 1);
-        }
-        if (io->numberoftriangleattributes > 0) {
-          printf("   attributes");
-        }
-        for (j = 0; j < io->numberoftriangleattributes; j++) {
-          printf("  %.6g", io->triangleattributelist[i *
-                                         io->numberoftriangleattributes + j]);
-        }
-        printf("\n");
-      }
-      if (reportneighbors) {
-        printf("Triangle %4d neighbors:", i + 1);
-        for (j = 0; j < 3; j++) {
-          if (io->neighborlist[i * 3 + j] < 0) {
-            printf("  %4d", io->neighborlist[i * 3 + j]);
-          } else {
-            printf("  %4d", io->neighborlist[i * 3 + j] + 1);
-          }
-        }
-        printf("\n");
-      }
-    }
-    printf("\n");
-  }
-
-  if (reportsegments) {
-    for (i = 0; i < io->numberofsegments; i++) {
-      printf("Segment %4d points:", i + 1);
-      for (j = 0; j < 2; j++) {
-        printf("  %4d", io->segmentlist[i * 2 + j] + 1);
-      }
-      if (markers) {
-        printf("   marker %d\n", io->segmentmarkerlist[i]);
-      } else {
-        printf("\n");
-      }
-    }
-    printf("\n");
-  }
-
-  if (reportedges) {
-    for (i = 0; i < io->numberofedges; i++) {
-      printf("Edge %4d points:", i + 1);
-      for (j = 0; j < 2; j++) {
-        printf("  %4d", io->edgelist[i * 2 + j] + 1);
-      }
-      if (reportnorms && (io->edgelist[i * 2 + 1] == -1)) {
-        for (j = 0; j < 2; j++) {
-          printf("  %.6g", io->normlist[i * 2 + j]);
-        }
-      }
-      if (markers) {
-        printf("   marker %d\n", io->edgemarkerlist[i]);
-      } else {
-        printf("\n");
-      }
-    }
-    printf("\n");
-  }
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* struct triangulateio routines end here                    *********/
-
-/********* Mesh manipulation primitives begin here                   *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/* Fast lookup arrays to speed some of the mesh manipulation primitives.     */
-
-int mesh2d::plus1mod3[3] = {1, 2, 0};
-int mesh2d::minus1mod3[3] = {2, 0, 1};
-
-/********* Primitives for triangles                                  *********/
-/*                                                                           */
-/*                                                                           */
-
-/* decode() converts a pointer to an oriented triangle.  The orientation is  */
-/*   extracted from the two least significant bits of the pointer.           */
-
-#define decode(ptr, triedge)                                                  \
-  (triedge).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l);      \
-  (triedge).tri = (triangle *)                                                \
-                  ((unsigned long) (ptr) ^ (unsigned long) (triedge).orient)
-
-/* encode() compresses an oriented triangle into a single pointer.  It       */
-/*   relies on the assumption that all triangles are aligned to four-byte    */
-/*   boundaries, so the two least significant bits of (triedge).tri are zero.*/
-
-#define encode(triedge)                                                       \
-  (triangle) ((unsigned long) (triedge).tri | (unsigned long) (triedge).orient)
-
-/* The following edge manipulation primitives are all described by Guibas    */
-/*   and Stolfi.  However, they use an edge-based data structure, whereas I  */
-/*   am using a triangle-based data structure.                               */
-
-/* sym() finds the abutting triangle, on the same edge.  Note that the       */
-/*   edge direction is necessarily reversed, because triangle/edge handles   */
-/*   are always directed counterclockwise around the triangle.               */
-
-#define sym(triedge1, triedge2)                                               \
-  ptr = (triedge1).tri[(triedge1).orient];                                    \
-  decode(ptr, triedge2);
-
-#define symself(triedge)                                                      \
-  ptr = (triedge).tri[(triedge).orient];                                      \
-  decode(ptr, triedge);
-
-/* lnext() finds the next edge (counterclockwise) of a triangle.             */
-
-#define lnext(triedge1, triedge2)                                             \
-  (triedge2).tri = (triedge1).tri;                                            \
-  (triedge2).orient = plus1mod3[(triedge1).orient]
-
-#define lnextself(triedge)                                                    \
-  (triedge).orient = plus1mod3[(triedge).orient]
-
-/* lprev() finds the previous edge (clockwise) of a triangle.                */
-
-#define lprev(triedge1, triedge2)                                             \
-  (triedge2).tri = (triedge1).tri;                                            \
-  (triedge2).orient = minus1mod3[(triedge1).orient]
-
-#define lprevself(triedge)                                                    \
-  (triedge).orient = minus1mod3[(triedge).orient]
-
-/* onext() spins counterclockwise around a point; that is, it finds the next */
-/*   edge with the same origin in the counterclockwise direction.  This edge */
-/*   will be part of a different triangle.                                   */
-
-#define onext(triedge1, triedge2)                                             \
-  lprev(triedge1, triedge2);                                                  \
-  symself(triedge2);
-
-#define onextself(triedge)                                                    \
-  lprevself(triedge);                                                         \
-  symself(triedge);
-
-/* oprev() spins clockwise around a point; that is, it finds the next edge   */
-/*   with the same origin in the clockwise direction.  This edge will be     */
-/*   part of a different triangle.                                           */
-
-#define oprev(triedge1, triedge2)                                             \
-  sym(triedge1, triedge2);                                                    \
-  lnextself(triedge2);
-
-#define oprevself(triedge)                                                    \
-  symself(triedge);                                                           \
-  lnextself(triedge);
-
-/* dnext() spins counterclockwise around a point; that is, it finds the next */
-/*   edge with the same destination in the counterclockwise direction.  This */
-/*   edge will be part of a different triangle.                              */
-
-#define dnext(triedge1, triedge2)                                             \
-  sym(triedge1, triedge2);                                                    \
-  lprevself(triedge2);
-
-#define dnextself(triedge)                                                    \
-  symself(triedge);                                                           \
-  lprevself(triedge);
-
-/* dprev() spins clockwise around a point; that is, it finds the next edge   */
-/*   with the same destination in the clockwise direction.  This edge will   */
-/*   be part of a different triangle.                                        */
-
-#define dprev(triedge1, triedge2)                                             \
-  lnext(triedge1, triedge2);                                                  \
-  symself(triedge2);
-
-#define dprevself(triedge)                                                    \
-  lnextself(triedge);                                                         \
-  symself(triedge);
-
-/* rnext() moves one edge counterclockwise about the adjacent triangle.      */
-/*   (It's best understood by reading Guibas and Stolfi.  It involves        */
-/*   changing triangles twice.)                                              */
-
-#define rnext(triedge1, triedge2)                                             \
-  sym(triedge1, triedge2);                                                    \
-  lnextself(triedge2);                                                        \
-  symself(triedge2);
-
-#define rnextself(triedge)                                                    \
-  symself(triedge);                                                           \
-  lnextself(triedge);                                                         \
-  symself(triedge);
-
-/* rnext() moves one edge clockwise about the adjacent triangle.             */
-/*   (It's best understood by reading Guibas and Stolfi.  It involves        */
-/*   changing triangles twice.)                                              */
-
-#define rprev(triedge1, triedge2)                                             \
-  sym(triedge1, triedge2);                                                    \
-  lprevself(triedge2);                                                        \
-  symself(triedge2);
-
-#define rprevself(triedge)                                                    \
-  symself(triedge);                                                           \
-  lprevself(triedge);                                                         \
-  symself(triedge);
-
-/* These primitives determine or set the origin, destination, or apex of a   */
-/* triangle.                                                                 */
-
-#define org(triedge, pointptr)                                                \
-  pointptr = (point) (triedge).tri[plus1mod3[(triedge).orient] + 3]
-
-#define dest(triedge, pointptr)                                               \
-  pointptr = (point) (triedge).tri[minus1mod3[(triedge).orient] + 3]
-
-#define apex(triedge, pointptr)                                               \
-  pointptr = (point) (triedge).tri[(triedge).orient + 3]
-
-#define setorg(triedge, pointptr)                                             \
-  (triedge).tri[plus1mod3[(triedge).orient] + 3] = (triangle) pointptr
-
-#define setdest(triedge, pointptr)                                            \
-  (triedge).tri[minus1mod3[(triedge).orient] + 3] = (triangle) pointptr
-
-#define setapex(triedge, pointptr)                                            \
-  (triedge).tri[(triedge).orient + 3] = (triangle) pointptr
-
-#define setvertices2null(triedge)                                             \
-  (triedge).tri[3] = (triangle) NULL;                                         \
-  (triedge).tri[4] = (triangle) NULL;                                         \
-  (triedge).tri[5] = (triangle) NULL;
-
-/* Bond two triangles together.                                              */
-
-#define bond(triedge1, triedge2)                                              \
-  (triedge1).tri[(triedge1).orient] = encode(triedge2);                       \
-  (triedge2).tri[(triedge2).orient] = encode(triedge1)
-
-/* Dissolve a bond (from one side).  Note that the other triangle will still */
-/*   think it's connected to this triangle.  Usually, however, the other     */
-/*   triangle is being deleted entirely, or bonded to another triangle, so   */
-/*   it doesn't matter.                                                      */
-
-#define dissolve(triedge)                                                     \
-  (triedge).tri[(triedge).orient] = (triangle) dummytri
-
-/* Copy a triangle/edge handle.                                              */
-
-#define triedgecopy(triedge1, triedge2)                                       \
-  (triedge2).tri = (triedge1).tri;                                            \
-  (triedge2).orient = (triedge1).orient
-
-/* Test for equality of triangle/edge handles.                               */
-
-#define triedgeequal(triedge1, triedge2)                                      \
-  (((triedge1).tri == (triedge2).tri) &&                                      \
-   ((triedge1).orient == (triedge2).orient))
-
-/* Primitives to infect or cure a triangle with the virus.  These rely on    */
-/*   the assumption that all shell edges are aligned to four-byte boundaries.*/
-
-#define infect(triedge)                                                       \
-  (triedge).tri[6] = (triangle)                                               \
-                     ((unsigned long) (triedge).tri[6] | (unsigned long) 2l)
-
-#define uninfect(triedge)                                                     \
-  (triedge).tri[6] = (triangle)                                               \
-                     ((unsigned long) (triedge).tri[6] & ~ (unsigned long) 2l)
-
-/* Test a triangle for viral infection.                                      */
-
-#define infected(triedge)                                                     \
-  (((unsigned long) (triedge).tri[6] & (unsigned long) 2l) != 0)
-
-/* Check or set a triangle's attributes.                                     */
-
-#define elemattribute(triedge, attnum)                                        \
-  ((REAL *) (triedge).tri)[elemattribindex + (attnum)]
-
-#define setelemattribute(triedge, attnum, value)                              \
-  ((REAL *) (triedge).tri)[elemattribindex + (attnum)] = value
-
-/* Check or set a triangle's maximum area bound.                             */
-
-#define areabound(triedge)  ((REAL *) (triedge).tri)[areaboundindex]
-
-#define setareabound(triedge, value)                                          \
-  ((REAL *) (triedge).tri)[areaboundindex] = value
-
-/********* Primitives for shell edges                                *********/
-/*                                                                           */
-/*                                                                           */
-
-/* sdecode() converts a pointer to an oriented shell edge.  The orientation  */
-/*   is extracted from the least significant bit of the pointer.  The two    */
-/*   least significant bits (one for orientation, one for viral infection)   */
-/*   are masked out to produce the real pointer.                             */
-
-#define sdecode(sptr, edge)                                                   \
-  (edge).shorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l);      \
-  (edge).sh = (shelle *)                                                      \
-              ((unsigned long) (sptr) & ~ (unsigned long) 3l)
-
-/* sencode() compresses an oriented shell edge into a single pointer.  It    */
-/*   relies on the assumption that all shell edges are aligned to two-byte   */
-/*   boundaries, so the least significant bit of (edge).sh is zero.          */
-
-#define sencode(edge)                                                         \
-  (shelle) ((unsigned long) (edge).sh | (unsigned long) (edge).shorient)
-
-/* ssym() toggles the orientation of a shell edge.                           */
-
-#define ssym(edge1, edge2)                                                    \
-  (edge2).sh = (edge1).sh;                                                    \
-  (edge2).shorient = 1 - (edge1).shorient
-
-#define ssymself(edge)                                                        \
-  (edge).shorient = 1 - (edge).shorient
-
-/* spivot() finds the other shell edge (from the same segment) that shares   */
-/*   the same origin.                                                        */
-
-#define spivot(edge1, edge2)                                                  \
-  sptr = (edge1).sh[(edge1).shorient];                                        \
-  sdecode(sptr, edge2)
-
-#define spivotself(edge)                                                      \
-  sptr = (edge).sh[(edge).shorient];                                          \
-  sdecode(sptr, edge)
-
-/* snext() finds the next shell edge (from the same segment) in sequence;    */
-/*   one whose origin is the input shell edge's destination.                 */
-
-#define snext(edge1, edge2)                                                   \
-  sptr = (edge1).sh[1 - (edge1).shorient];                                    \
-  sdecode(sptr, edge2)
-
-#define snextself(edge)                                                       \
-  sptr = (edge).sh[1 - (edge).shorient];                                      \
-  sdecode(sptr, edge)
-
-/* These primitives determine or set the origin or destination of a shell    */
-/*   edge.                                                                   */
-
-#define sorg(edge, pointptr)                                                  \
-  pointptr = (point) (edge).sh[2 + (edge).shorient]
-
-#define sdest(edge, pointptr)                                                 \
-  pointptr = (point) (edge).sh[3 - (edge).shorient]
-
-#define setsorg(edge, pointptr)                                               \
-  (edge).sh[2 + (edge).shorient] = (shelle) pointptr
-
-#define setsdest(edge, pointptr)                                              \
-  (edge).sh[3 - (edge).shorient] = (shelle) pointptr
-
-/* These primitives read or set a shell marker.  Shell markers are used to   */
-/*   hold user boundary information.                                         */
-
-#define mark(edge)  (* (int *) ((edge).sh + 6))
-
-#define setmark(edge, value)                                                  \
-  * (int *) ((edge).sh + 6) = value
-
-/* Bond two shell edges together.                                            */
-
-#define sbond(edge1, edge2)                                                   \
-  (edge1).sh[(edge1).shorient] = sencode(edge2);                              \
-  (edge2).sh[(edge2).shorient] = sencode(edge1)
-
-/* Dissolve a shell edge bond (from one side).  Note that the other shell    */
-/*   edge will still think it's connected to this shell edge.                */
-
-#define sdissolve(edge)                                                       \
-  (edge).sh[(edge).shorient] = (shelle) dummysh
-
-/* Copy a shell edge.                                                        */
-
-#define shellecopy(edge1, edge2)                                              \
-  (edge2).sh = (edge1).sh;                                                    \
-  (edge2).shorient = (edge1).shorient
-
-/* Test for equality of shell edges.                                         */
-
-#define shelleequal(edge1, edge2)                                             \
-  (((edge1).sh == (edge2).sh) &&                                              \
-   ((edge1).shorient == (edge2).shorient))
-
-/********* Primitives for interacting triangles and shell edges      *********/
-/*                                                                           */
-/*                                                                           */
-
-/* tspivot() finds a shell edge abutting a triangle.                         */
-
-#define tspivot(triedge, edge)                                                \
-  sptr = (shelle) (triedge).tri[6 + (triedge).orient];                        \
-  sdecode(sptr, edge)
-
-/* stpivot() finds a triangle abutting a shell edge.  It requires that the   */
-/*   variable `ptr' of type `triangle' be defined.                           */
-
-#define stpivot(edge, triedge)                                                \
-  ptr = (triangle) (edge).sh[4 + (edge).shorient];                            \
-  decode(ptr, triedge)
-
-/* Bond a triangle to a shell edge.                                          */
-
-#define tsbond(triedge, edge)                                                 \
-  (triedge).tri[6 + (triedge).orient] = (triangle) sencode(edge);             \
-  (edge).sh[4 + (edge).shorient] = (shelle) encode(triedge)
-
-/* Dissolve a bond (from the triangle side).                                 */
-
-#define tsdissolve(triedge)                                                   \
-  (triedge).tri[6 + (triedge).orient] = (triangle) dummysh
-
-/* Dissolve a bond (from the shell edge side).                               */
-
-#define stdissolve(edge)                                                      \
-  (edge).sh[4 + (edge).shorient] = (shelle) dummytri
-
-/********* Primitives for points                                     *********/
-/*                                                                           */
-/*                                                                           */
-
-#define pointmark(pt)  ((int *) (pt))[pointmarkindex]
-
-#define setpointmark(pt, value)                                               \
-  ((int *) (pt))[pointmarkindex] = value
-
-#define point2tri(pt)  ((triangle *) (pt))[point2triindex]
-
-#define setpoint2tri(pt, value)                                               \
-  ((triangle *) (pt))[point2triindex] = value
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Mesh manipulation primitives end here                     *********/
-
-/********* User interaction routines begin here                      *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  syntax()   Print list of command line switches.                          */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::syntax()
-{
-  printf("triangle [-paAcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
-  exit(0);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  info()   Print out complete instructions.                                */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::info()
-{
-  printf("Triangle\n");
-  printf(
-"A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
-  printf("Version 1.3\n\n");
-  printf(
-"Copyright 1996 Jonathan Richard Shewchuk  (bugs/comments to jrs@cs.cmu.edu)\n"
-);
-  printf("School of Computer Science / Carnegie Mellon University\n");
-  printf("5000 Forbes Avenue / Pittsburgh, Pennsylvania  15213-3891\n");
-  printf(
-"Created as part of the Archimedes project (tools for parallel FEM).\n");
-  printf(
-"Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
-  printf("There is no warranty whatsoever.  Use at your own risk.\n");
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  internalerror()   Ask the user to send me the defective product.  Exit.  */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::internalerror()
-{
-  printf("  Please report this bug to sihang@weboo.com\n");
-  printf("  Include the message above, your input data set, and the exact\n");
-  printf("    command line you used to run Triangle.\n");
-  exit(1);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  parsecommandline()   Read the command line, identify switches, and set   */
-/*                       up options and file names.                          */
-/*                                                                           */
-/*  The effects of this routine are felt entirely through global variables.  */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::parsecommandline(int argc, char **argv, int libflag)
-{
-  int startindex;
-  char startchar;
-  int increment;
-  int meshnumber;
-  int i, j, k;
-  char workstring[FILENAMESIZE];
-
-  poly = refine = quality = vararea = fixedarea = regionattrib = convex = 0;
-  firstnumber = 1;
-  edgesout = voronoi = neighbors = geomview = 0;
-  nobound = nopolywritten = nonodewritten = noelewritten = noiterationnum = 0;
-  noholes = noexact = 0;
-  incremental = sweepline = 0;
-  dwyer = 1;
-  splitseg = 0;
-  docheck = 0;
-  nobisect = 0;
-  steiner = -1;
-  order = 1;
-  minangle = 0.0;
-  maxarea = -1.0;
-  quiet = verbose = 0;
-
-  if (libflag) {
-    startindex = 0;
-  } else {
-    startindex = 1;
-  }
-
-  for (i = startindex; i < argc; i++) {
-    if (libflag) {
-      startchar = '-';
-    } else {
-      startchar = argv[i][0];
-    }
-    if (startchar == '-') {
-      for (j = startindex; argv[i][j] != '\0'; j++) {
-        if (argv[i][j] == 'p') {
-          poly = 1;
-        }
-        if (argv[i][j] == 'r') {
-          refine = 1;
-	      }
-        if (argv[i][j] == 'q') {
-          quality = 1;
-          if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-              (argv[i][j + 1] == '.')) {
-            k = 0;
-            while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-                   (argv[i][j + 1] == '.')) {
-              j++;
-              workstring[k] = argv[i][j];
-              k++;
-            }
-            workstring[k] = '\0';
-            minangle = (REAL) strtod(workstring, (char **) NULL);
-          } else {
-            minangle = 20.0;
-          }
-        }
-        if (argv[i][j] == 'a') {
-          quality = 1;
-          if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-              (argv[i][j + 1] == '.')) {
-            fixedarea = 1;
-            k = 0;
-            while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-                   (argv[i][j + 1] == '.')) {
-              j++;
-              workstring[k] = argv[i][j];
-              k++;
-            }
-            workstring[k] = '\0';
-            maxarea = (REAL) strtod(workstring, (char **) NULL);
-            if (maxarea <= 0.0) {
-              printf("Error:  Maximum area must be greater than zero.\n");
-              exit(1);
-            }
-          } else {
-            vararea = 1;
-          }
-        }
-        if (argv[i][j] == 'A') {
-          regionattrib = 1;
-        }
-        if (argv[i][j] == 'c') {
-          convex = 1;
-        }
-        if (argv[i][j] == 'z') {
-          firstnumber = 0;
-        }
-        if (argv[i][j] == 'e') {
-          edgesout = 1;
-        }
-        if (argv[i][j] == 'v') {
-          voronoi = 1;
-        }
-        if (argv[i][j] == 'n') {
-          neighbors = 1;
-        }
-        if (argv[i][j] == 'g') {
-          geomview = 1;
-        }
-        if (argv[i][j] == 'B') {
-          nobound = 1;
-        }
-        if (argv[i][j] == 'P') {
-          nopolywritten = 1;
-        }
-        if (argv[i][j] == 'N') {
-          nonodewritten = 1;
-        }
-        if (argv[i][j] == 'E') {
-          noelewritten = 1;
-        }
-        if (argv[i][j] == 'I') {
-          noiterationnum = 1;
-        }
-        if (argv[i][j] == 'O') {
-          noholes = 1;
-        }
-        if (argv[i][j] == 'X') {
-          noexact = 1;
-        }
-        if (argv[i][j] == 'o') {
-          if (argv[i][j + 1] == '2') {
-            j++;
-            order = 2;
-          }
-        }
-        if (argv[i][j] == 'Y') {
-          nobisect++;
-        }
-        if (argv[i][j] == 'S') {
-          steiner = 0;
-          while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
-            j++;
-            steiner = steiner * 10 + (int) (argv[i][j] - '0');
-          }
-        }
-        if (argv[i][j] == 'i') {
-          incremental = 1;
-        }
-        if (argv[i][j] == 'F') {
-          sweepline = 1;
-        }
-        if (argv[i][j] == 'l') {
-          dwyer = 0;
-        }
-        if (argv[i][j] == 's') {
-          splitseg = 1;
-        }
-        if (argv[i][j] == 'C') {
-          docheck = 1;
-        }
-        if (argv[i][j] == 'Q') {
-          quiet = 1;
-        }
-        if (argv[i][j] == 'V') {
-          verbose++;
-        }
-        if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
-            (argv[i][j] == '?')) {
-          info();
-        }
-      }
-    }
-  }
-
-  steinerleft = steiner;
-  useshelles = poly || refine || quality || convex;
-  // Be careful not to add an extra attribute to each element unless the
-  //   input supports it (PSLG in, but not refining a preexisting mesh).
-  if (refine || !poly) {
-    regionattrib = 0;
-  }
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* User interaction routines begin here                      *********/
-
-/********* Debugging routines begin here                             *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  printtriangle()   Print out the details of a triangle/edge handle.       */
-/*                                                                           */
-/*  I originally wrote this procedure to simplify debugging; it can be       */
-/*  called directly from the debugger, and presents information about a      */
-/*  triangle/edge handle in digestible form.  It's also used when the        */
-/*  highest level of verbosity (`-VVV') is specified.                        */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::printtriangle(struct triedge *t)
-{
-  struct triedge printtri;
-  struct edge printsh;
-  point printpoint;
-
-  printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
-         t->orient);
-  decode(t->tri[0], printtri);
-  if (printtri.tri == dummytri) {
-    printf("    [0] = Outer space\n");
-  } else {
-    printf("    [0] = x%lx  %d\n", (unsigned long) printtri.tri,
-           printtri.orient);
-  }
-  decode(t->tri[1], printtri);
-  if (printtri.tri == dummytri) {
-    printf("    [1] = Outer space\n");
-  } else {
-    printf("    [1] = x%lx  %d\n", (unsigned long) printtri.tri,
-           printtri.orient);
-  }
-  decode(t->tri[2], printtri);
-  if (printtri.tri == dummytri) {
-    printf("    [2] = Outer space\n");
-  } else {
-    printf("    [2] = x%lx  %d\n", (unsigned long) printtri.tri,
-           printtri.orient);
-  }
-  org(*t, printpoint);
-  if (printpoint == (point) NULL)
-    printf("    Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
-  else
-    printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
-           (t->orient + 1) % 3 + 3, (unsigned long) printpoint,
-           printpoint[0], printpoint[1]);
-  dest(*t, printpoint);
-  if (printpoint == (point) NULL)
-    printf("    Dest  [%d] = NULL\n", (t->orient + 2) % 3 + 3);
-  else
-    printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
-           (t->orient + 2) % 3 + 3, (unsigned long) printpoint,
-           printpoint[0], printpoint[1]);
-  apex(*t, printpoint);
-  if (printpoint == (point) NULL)
-    printf("    Apex  [%d] = NULL\n", t->orient + 3);
-  else
-    printf("    Apex  [%d] = x%lx  (%.12g, %.12g)\n",
-           t->orient + 3, (unsigned long) printpoint,
-           printpoint[0], printpoint[1]);
-  if (useshelles) {
-    sdecode(t->tri[6], printsh);
-    if (printsh.sh != dummysh) {
-      printf("    [6] = x%lx  %d\n", (unsigned long) printsh.sh,
-             printsh.shorient);
-    }
-    sdecode(t->tri[7], printsh);
-    if (printsh.sh != dummysh) {
-      printf("    [7] = x%lx  %d\n", (unsigned long) printsh.sh,
-             printsh.shorient);
-    }
-    sdecode(t->tri[8], printsh);
-    if (printsh.sh != dummysh) {
-      printf("    [8] = x%lx  %d\n", (unsigned long) printsh.sh,
-             printsh.shorient);
-    }
-  }
-  if (vararea) {
-    printf("    Area constraint:  %.4g\n", areabound(*t));
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  printshelle()   Print out the details of a shell edge handle.            */
-/*                                                                           */
-/*  I originally wrote this procedure to simplify debugging; it can be       */
-/*  called directly from the debugger, and presents information about a      */
-/*  shell edge handle in digestible form.  It's also used when the highest   */
-/*  level of verbosity (`-VVV') is specified.                                */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::printshelle(struct edge *s)
-{
-  struct edge printsh;
-  struct triedge printtri;
-  point printpoint;
-
-  printf("shell edge x%lx with orientation %d and mark %d:\n",
-         (unsigned long) s->sh, s->shorient, mark(*s));
-  sdecode(s->sh[0], printsh);
-  if (printsh.sh == dummysh) {
-    printf("    [0] = No shell\n");
-  } else {
-    printf("    [0] = x%lx  %d\n", (unsigned long) printsh.sh,
-           printsh.shorient);
-  }
-  sdecode(s->sh[1], printsh);
-  if (printsh.sh == dummysh) {
-    printf("    [1] = No shell\n");
-  } else {
-    printf("    [1] = x%lx  %d\n", (unsigned long) printsh.sh,
-           printsh.shorient);
-  }
-  sorg(*s, printpoint);
-  if (printpoint == (point) NULL)
-    printf("    Origin[%d] = NULL\n", 2 + s->shorient);
-  else
-    printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
-           2 + s->shorient, (unsigned long) printpoint,
-           printpoint[0], printpoint[1]);
-  sdest(*s, printpoint);
-  if (printpoint == (point) NULL)
-    printf("    Dest  [%d] = NULL\n", 3 - s->shorient);
-  else
-    printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
-           3 - s->shorient, (unsigned long) printpoint,
-           printpoint[0], printpoint[1]);
-  decode(s->sh[4], printtri);
-  if (printtri.tri == dummytri) {
-    printf("    [4] = Outer space\n");
-  } else {
-    printf("    [4] = x%lx  %d\n", (unsigned long) printtri.tri,
-           printtri.orient);
-  }
-  decode(s->sh[5], printtri);
-  if (printtri.tri == dummytri) {
-    printf("    [5] = Outer space\n");
-  } else {
-    printf("    [5] = x%lx  %d\n", (unsigned long) printtri.tri,
-           printtri.orient);
-  }
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Debugging routines end here                               *********/
-
-/********* Memory management routines begin here                     *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  dummyinit()   Initialize the triangle that fills "outer space" and the   */
-/*                omnipresent shell edge.                                    */
-/*                                                                           */
-/*  The triangle that fills "outer space", called `dummytri', is pointed to  */
-/*  by every triangle and shell edge on a boundary (be it outer or inner) of */
-/*  the triangulation.  Also, `dummytri' points to one of the triangles on   */
-/*  the convex hull (until the holes and concavities are carved), making it  */
-/*  possible to find a starting triangle for point location.                 */
-/*                                                                           */
-/*  The omnipresent shell edge, `dummysh', is pointed to by every triangle   */
-/*  or shell edge that doesn't have a full complement of real shell edges    */
-/*  to point to.                                                             */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::dummyinit(int trianglewords, int shellewords)
-{
-  unsigned long alignptr;
-
-  /* `triwords' and `shwords' are used by the mesh manipulation primitives */
-  /*   to extract orientations of triangles and shell edges from pointers. */
-  triwords = trianglewords;       /* Initialize `triwords' once and for all. */
-  shwords = shellewords;           /* Initialize `shwords' once and for all. */
-
-  /* Set up `dummytri', the `triangle' that occupies "outer space". */
-  dummytribase = (triangle *) new BYTE[triwords * sizeof(triangle)
-                                       + triangles.alignbytes];
-  if (dummytribase == (triangle *) NULL) {
-    printf("Error:  Out of memory.\n");
-    exit(1);
-  }
-  /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
-  alignptr = (unsigned long) dummytribase;
-  dummytri = (triangle *)
-    (alignptr + (unsigned long) triangles.alignbytes
-     - (alignptr % (unsigned long) triangles.alignbytes));
-  /* Initialize the three adjoining triangles to be "outer space".  These  */
-  /*   will eventually be changed by various bonding operations, but their */
-  /*   values don't really matter, as long as they can legally be          */
-  /*   dereferenced.                                                       */
-  dummytri[0] = (triangle) dummytri;
-  dummytri[1] = (triangle) dummytri;
-  dummytri[2] = (triangle) dummytri;
-  /* Three NULL vertex points. */
-  dummytri[3] = (triangle) NULL;
-  dummytri[4] = (triangle) NULL;
-  dummytri[5] = (triangle) NULL;
-
-  if (useshelles) {
-    /* Set up `dummysh', the omnipresent "shell edge" pointed to by any      */
-    /*   triangle side or shell edge end that isn't attached to a real shell */
-    /*   edge.                                                               */
-    dummyshbase = (shelle *) new BYTE[shwords * sizeof(shelle)
-                                      + shelles.alignbytes];
-    if (dummyshbase == (shelle *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-    /* Align `dummysh' on a `shelles.alignbytes'-byte boundary. */
-    alignptr = (unsigned long) dummyshbase;
-    dummysh = (shelle *)
-      (alignptr + (unsigned long) shelles.alignbytes
-       - (alignptr % (unsigned long) shelles.alignbytes));
-    /* Initialize the two adjoining shell edges to be the omnipresent shell */
-    /*   edge.  These will eventually be changed by various bonding         */
-    /*   operations, but their values don't really matter, as long as they  */
-    /*   can legally be dereferenced.                                       */
-    dummysh[0] = (shelle) dummysh;
-    dummysh[1] = (shelle) dummysh;
-    /* Two NULL vertex points. */
-    dummysh[2] = (shelle) NULL;
-    dummysh[3] = (shelle) NULL;
-    /* Initialize the two adjoining triangles to be "outer space". */
-    dummysh[4] = (shelle) dummytri;
-    dummysh[5] = (shelle) dummytri;
-    /* Set the boundary marker to zero. */
-    * (int *) (dummysh + 6) = 0;
-
-    /* Initialize the three adjoining shell edges of `dummytri' to be */
-    /*   the omnipresent shell edge.                                  */
-    dummytri[6] = (triangle) dummysh;
-    dummytri[7] = (triangle) dummysh;
-    dummytri[8] = (triangle) dummysh;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  initializepointpool()   Calculate the size of the point data structure   */
-/*                          and initialize its memory pool.                  */
-/*                                                                           */
-/*  This routine also computes the `pointmarkindex' and `point2triindex'     */
-/*  indices used to find values within each point.                           */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::initializepointpool()
-{
-  int pointsize;
-
-  /* The index within each point at which the boundary marker is found.  */
-  /*   Ensure the point marker is aligned to a sizeof(int)-byte address. */
-  pointmarkindex = ((mesh_dim + nextras) * sizeof(REAL) + sizeof(int) - 1)
-                 / sizeof(int);
-  pointsize = (pointmarkindex + 1) * sizeof(int);
-  if (poly) {
-    /* The index within each point at which a triangle pointer is found.   */
-    /*   Ensure the pointer is aligned to a sizeof(triangle)-byte address. */
-    point2triindex = (pointsize + sizeof(triangle) - 1) / sizeof(triangle);
-    pointsize = (point2triindex + 1) * sizeof(triangle);
-  }
-  /* Initialize the pool of points. */
-  points.init(pointsize, POINTPERBLOCK,
-           (sizeof(REAL) >= sizeof(triangle)) ? FLOATINGPOINT : POINTER, 0);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  initializetrisegpools()   Calculate the sizes of the triangle and shell  */
-/*                            edge data structures and initialize their      */
-/*                            memory pools.                                  */
-/*                                                                           */
-/*  This routine also computes the `highorderindex', `elemattribindex', and  */
-/*  `areaboundindex' indices used to find values within each triangle.       */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::initializetrisegpools()
-{
-  int trisize;
-
-  /* The index within each triangle at which the extra nodes (above three)  */
-  /*   associated with high order elements are found.  There are three      */
-  /*   pointers to other triangles, three pointers to corners, and possibly */
-  /*   three pointers to shell edges before the extra nodes.                */
-  highorderindex = 6 + (useshelles * 3);
-  /* The number of bytes occupied by a triangle. */
-  trisize = ((order + 1) * (order + 2) / 2 + (highorderindex - 3)) *
-            sizeof(triangle);
-  /* The index within each triangle at which its attributes are found, */
-  /*   where the index is measured in REALs.                           */
-  elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
-  /* The index within each triangle at which the maximum area constraint  */
-  /*   is found, where the index is measured in REALs.  Note that if the  */
-  /*   `regionattrib' flag is set, an additional attribute will be added. */
-  areaboundindex = elemattribindex + eextras + regionattrib;
-  /* If triangle attributes or an area bound are needed, increase the number */
-  /*   of bytes occupied by a triangle.                                      */
-  if (vararea) {
-    trisize = (areaboundindex + 1) * sizeof(REAL);
-  } else if (eextras + regionattrib > 0) {
-    trisize = areaboundindex * sizeof(REAL);
-  }
-  /* If a Voronoi diagram or triangle neighbor graph is requested, make    */
-  /*   sure there's room to store an integer index in each triangle.  This */
-  /*   integer index can occupy the same space as the shell edges or       */
-  /*   attributes or area constraint or extra nodes.                       */
-  if ((voronoi || neighbors) &&
-      (trisize < 6 * sizeof(triangle) + sizeof(int))) {
-    trisize = 6 * sizeof(triangle) + sizeof(int);
-  }
-  /* Having determined the memory size of a triangle, initialize the pool. */
-  triangles.init(trisize, TRIPERBLOCK, POINTER, 4);
-
-  if (useshelles) {
-    /* Initialize the pool of shell edges. */
-    shelles.init(6 * sizeof(triangle) + sizeof(int), SHELLEPERBLOCK,
-                 POINTER, 4);
-
-    /* Initialize the "outer space" triangle and omnipresent shell edge. */
-    dummyinit(triangles.itemwords, shelles.itemwords);
-  } else {
-    /* Initialize the "outer space" triangle. */
-    dummyinit(triangles.itemwords, 0);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  triangledealloc()   Deallocate space for a triangle, marking it dead.    */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::triangledealloc(triangle *dyingtriangle)
-{
-  /* Set triangle's vertices to NULL.  This makes it possible to        */
-  /*   detect dead triangles when traversing the list of all triangles. */
-  dyingtriangle[3] = (triangle) NULL;
-  dyingtriangle[4] = (triangle) NULL;
-  dyingtriangle[5] = (triangle) NULL;
-  triangles.dealloc(dyingtriangle);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  triangletraverse()   Traverse the triangles, skipping dead ones.         */
-/*                                                                           */
-/*****************************************************************************/
-
-triangle* mesh2d::triangletraverse()
-{
-  triangle *newtriangle;
-
-  do {
-    newtriangle = (triangle *) triangles.traverse();
-    if (newtriangle == (triangle *) NULL) {
-      return (triangle *) NULL;
-    }
-  } while (newtriangle[3] == (triangle) NULL);            /* Skip dead ones. */
-  return newtriangle;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  shelledealloc()   Deallocate space for a shell edge, marking it dead.    */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::shelledealloc(shelle *dyingshelle)
-{
-  /* Set shell edge's vertices to NULL.  This makes it possible to */
-  /*   detect dead shells when traversing the list of all shells.  */
-  dyingshelle[2] = (shelle) NULL;
-  dyingshelle[3] = (shelle) NULL;
-  shelles.dealloc(dyingshelle);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  shelletraverse()   Traverse the shell edges, skipping dead ones.         */
-/*                                                                           */
-/*****************************************************************************/
-
-shelle* mesh2d::shelletraverse()
-{
-  shelle *newshelle;
-
-  do {
-    newshelle = (shelle *) shelles.traverse();
-    if (newshelle == (shelle *) NULL) {
-      return (shelle *) NULL;
-    }
-  } while (newshelle[2] == (shelle) NULL);                /* Skip dead ones. */
-  return newshelle;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  pointdealloc()   Deallocate space for a point, marking it dead.          */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::pointdealloc(point dyingpoint)
-{
-  /* Mark the point as dead.  This makes it possible to detect dead points */
-  /*   when traversing the list of all points.                             */
-  setpointmark(dyingpoint, DEADPOINT);
-  points.dealloc(dyingpoint);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  pointtraverse()   Traverse the points, skipping dead ones.               */
-/*                                                                           */
-/*****************************************************************************/
-
-point mesh2d::pointtraverse()
-{
-  point newpoint;
-
-  do {
-    newpoint = (point) points.traverse();
-    if (newpoint == (point) NULL) {
-      return (point) NULL;
-    }
-  } while (pointmark(newpoint) == DEADPOINT);             /* Skip dead ones. */
-  return newpoint;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  getpoint()   Get a specific point, by number, from the list.             */
-/*                                                                           */
-/*  The first point is number 'firstnumber'.                                 */
-/*                                                                           */
-/*  Note that this takes O(n) time (with a small constant, if POINTPERBLOCK  */
-/*  is large).  I don't care to take the trouble to make it work in constant */
-/*  time.                                                                    */
-/*                                                                           */
-/*****************************************************************************/
-
-point mesh2d::getpoint(int number)
-{
-  void **getblock;
-  point foundpoint;
-  unsigned long alignptr;
-  int current;
-
-  getblock = points.firstblock;
-  current = firstnumber;
-  /* Find the right block. */
-  while (current + points.itemsperblock <= number) {
-    getblock = (void **) *getblock;
-    current += points.itemsperblock;
-  }
-  /* Now find the right point. */
-  alignptr = (unsigned long) (getblock + 1);
-  foundpoint = (point) (alignptr + (unsigned long) points.alignbytes
-                        - (alignptr % (unsigned long) points.alignbytes));
-  while (current < number) {
-    foundpoint += points.itemwords;
-    current++;
-  }
-  return foundpoint;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  triangledeinit()   Free all remaining allocated memory.                  */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::triangledeinit()
-{
-  triangles.deinit();
-  if (dummytribase) delete [] dummytribase;
-  if (useshelles) {
-    shelles.deinit();
-    if (dummyshbase) delete [] dummyshbase;
-  }
-  points.deinit();
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Memory management routines end here                       *********/
-
-/********* Constructors begin here                                   *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  maketriangle()   Create a new triangle with orientation zero.            */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::maketriangle(struct triedge *newtriedge)
-{
-  int i;
-
-  newtriedge->tri = (triangle *) triangles.alloc();
-  /* Initialize the three adjoining triangles to be "outer space". */
-  newtriedge->tri[0] = (triangle) dummytri;
-  newtriedge->tri[1] = (triangle) dummytri;
-  newtriedge->tri[2] = (triangle) dummytri;
-  /* Three NULL vertex points. */
-  newtriedge->tri[3] = (triangle) NULL;
-  newtriedge->tri[4] = (triangle) NULL;
-  newtriedge->tri[5] = (triangle) NULL;
-  /* Initialize the three adjoining shell edges to be the omnipresent */
-  /*   shell edge.                                                    */
-  if (useshelles) {
-    newtriedge->tri[6] = (triangle) dummysh;
-    newtriedge->tri[7] = (triangle) dummysh;
-    newtriedge->tri[8] = (triangle) dummysh;
-  }
-  for (i = 0; i < eextras; i++) {
-    setelemattribute(*newtriedge, i, 0.0);
-  }
-  if (vararea) {
-    setareabound(*newtriedge, -1.0);
-  }
-
-  newtriedge->orient = 0;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  makeshelle()   Create a new shell edge with orientation zero.            */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::makeshelle(struct edge *newedge)
-{
-  newedge->sh = (shelle *) shelles.alloc();
-  /* Initialize the two adjoining shell edges to be the omnipresent */
-  /*   shell edge.                                                  */
-  newedge->sh[0] = (shelle) dummysh;
-  newedge->sh[1] = (shelle) dummysh;
-  /* Two NULL vertex points. */
-  newedge->sh[2] = (shelle) NULL;
-  newedge->sh[3] = (shelle) NULL;
-  /* Initialize the two adjoining triangles to be "outer space". */
-  newedge->sh[4] = (shelle) dummytri;
-  newedge->sh[5] = (shelle) dummytri;
-  /* Set the boundary marker to zero. */
-  setmark(*newedge, 0);
-
-  newedge->shorient = 0;
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Constructors end here                                     *********/
-
-/********* Determinant evaluation routines begin here                *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/* This routines were move to "predicate.cpp" file                           */
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Determinant evaluation routines end here                  *********/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  triangleinit()   Initialize some variables.                              */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::triangleinit()
-{
-  points.maxitems = triangles.maxitems = shelles.maxitems = viri.maxitems = 0l;
-  points.itembytes = triangles.itembytes = shelles.itembytes =
-    viri.itembytes = 0;
-  recenttri.tri = (triangle *) NULL;    /* No triangle has been visited yet. */
-  samples = 1;            /* Point location should take at least one sample. */
-  checksegments = 0;      /* There are no segments in the triangulation yet. */
-  circumcentercount = 0;
-  randomseed = 1;
-  incirclecount = counterclockcount = 0;
-  dummytribase = NULL;
-  dummyshbase = NULL;
-  restartsymbol = 0;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/* trianglerestart()    Clear all remaining allocated memory, not free them. */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::trianglerestart()
-{
-  triangles.restart();
-  if (useshelles) {
-    shelles.restart();
-  }
-  points.restart();
-
-  recenttri.tri = (triangle *) NULL;    // No triangle has been visited yet.
-  samples = 1;            // Point location should take at least one sample.
-  checksegments = 0;      // There are no segments in the triangulation yet.
-  randomseed = 1;
-  circumcentercount = 0;
-  restartsymbol = 1;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  counterclockwise()   Return a positive value if the points pa, pb, and   */
-/*                       pc occur in counterclockwise order; a negative      */
-/*                       value if they occur in clockwise order; and zero    */
-/*                       if they are collinear.  The result is also a rough  */
-/*                       approximation of twice the signed area of the       */
-/*                       triangle defined by the three points.               */
-/*                                                                           */
-/*  Uses exact arithmetic if necessary to ensure a correct answer.  The      */
-/*  result returned is the determinant of a matrix.  This determinant is     */
-/*  computed adaptively, in the sense that exact arithmetic is used only to  */
-/*  the degree it is needed to ensure that the returned value has the        */
-/*  correct sign.  Hence, this function is usually quite fast, but will run  */
-/*  more slowly when the input points are collinear or nearly so.            */
-/*                                                                           */
-/*  See my Robust Predicates paper for details.                              */
-/*                                                                           */
-/*****************************************************************************/
-
-#define dDIST2D(a, b) sqrt((a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]))
-
-REAL mesh2d::counterclockwise(point pa, point pb, point pc)
-{
-  counterclockcount++;
-  if (noexact) {
-    REAL xa = pa[0], ya = pa[1];
-    REAL xb = pb[0], yb = pb[1];
-    REAL xc = pc[0], yc = pc[1];
-
-    // Currently no exact arithmetic
-    REAL dDet = ((xb - xa) * (yc - ya) - (xc - xa) * (yb - ya));
-    // Scale the determinant by the mean of the magnitudes of vectors:
-    REAL dScale = (dDIST2D (pa, pb)
-                   + dDIST2D (pb, pc)
-		               + dDIST2D (pc, pa)) / 3;
-    REAL dScaleDet = dDet / (dScale * dScale);
-    if (fabs(dScaleDet) <= 1.e-10) {
-      dDet = 0.;
-    }
-    return dDet;
-  } else {
-    REAL dDet = orient2d(pa, pb, pc);
-    return dDet;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  incircle()   Return a positive value if the point pd lies inside the     */
-/*               circle passing through pa, pb, and pc; a negative value if  */
-/*               it lies outside; and zero if the four points are cocircular.*/
-/*               The points pa, pb, and pc must be in counterclockwise       */
-/*               order, or the sign of the result will be reversed.          */
-/*                                                                           */
-/*  Uses exact arithmetic if necessary to ensure a correct answer.  The      */
-/*  result returned is the determinant of a matrix.  This determinant is     */
-/*  computed adaptively, in the sense that exact arithmetic is used only to  */
-/*  the degree it is needed to ensure that the returned value has the        */
-/*  correct sign.  Hence, this function is usually quite fast, but will run  */
-/*  more slowly when the input points are cocircular or nearly so.           */
-/*                                                                           */
-/*  See my Robust Predicates paper for details.                              */
-/*                                                                           */
-/*****************************************************************************/
-
-REAL mesh2d::iincircle(point pa, point pb, point pc, point pd)
-{
-  incirclecount++;
-  return incircle(pa, pb, pc, pd);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  randomnation()   Generate a random number between 0 and `choices' - 1.   */
-/*                                                                           */
-/*  This is a simple linear congruential random number generator.  Hence, it */
-/*  is a bad random number generator, but good enough for most randomized    */
-/*  geometric algorithms.                                                    */
-/*                                                                           */
-/*****************************************************************************/
-
-unsigned long mesh2d::randomnation(unsigned int choices)
-{
-  randomseed = (randomseed * 1366l + 150889l) % 714025l;
-  return randomseed / (714025l / choices + 1);
-}
-
-/********* Point location routines begin here                        *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  makepointmap()   Construct a mapping from points to triangles to improve  */
-/*                  the speed of point location for segment insertion.       */
-/*                                                                           */
-/*  Traverses all the triangles, and provides each corner of each triangle   */
-/*  with a pointer to that triangle.  Of course, pointers will be            */
-/*  overwritten by other pointers because (almost) each point is a corner    */
-/*  of several triangles, but in the end every point will point to some      */
-/*  triangle that contains it.                                               */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::makepointmap()
-{
-  struct triedge triangleloop;
-  point triorg;
-
-  if (verbose) {
-    printf("    Constructing mapping from points to triangles.\n");
-  }
-  triangles.traversalinit();
-  triangleloop.tri = triangletraverse();
-  while (triangleloop.tri != (triangle *) NULL) {
-    /* Check all three points of the triangle. */
-    for (triangleloop.orient = 0; triangleloop.orient < 3;
-         triangleloop.orient++) {
-      org(triangleloop, triorg);
-      setpoint2tri(triorg, encode(triangleloop));
-    }
-    triangleloop.tri = triangletraverse();
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  preciselocate()   Find a triangle or edge containing a given point.      */
-/*                                                                           */
-/*  Begins its search from `searchtri'.  It is important that `searchtri'    */
-/*  be a handle with the property that `searchpoint' is strictly to the left */
-/*  of the edge denoted by `searchtri', or is collinear with that edge and   */
-/*  does not intersect that edge.  (In particular, `searchpoint' should not  */
-/*  be the origin or destination of that edge.)                              */
-/*                                                                           */
-/*  These conditions are imposed because preciselocate() is normally used in */
-/*  one of two situations:                                                   */
-/*                                                                           */
-/*  (1)  To try to find the location to insert a new point.  Normally, we    */
-/*       know an edge that the point is strictly to the left of.  In the     */
-/*       incremental Delaunay algorithm, that edge is a bounding box edge.   */
-/*       In Ruppert's Delaunay refinement algorithm for quality meshing,     */
-/*       that edge is the shortest edge of the triangle whose circumcenter   */
-/*       is being inserted.                                                  */
-/*                                                                           */
-/*  (2)  To try to find an existing point.  In this case, any edge on the    */
-/*       convex hull is a good starting edge.  The possibility that the      */
-/*       vertex one seeks is an endpoint of the starting edge must be        */
-/*       screened out before preciselocate() is called.                      */
-/*                                                                           */
-/*  On completion, `searchtri' is a triangle that contains `searchpoint'.    */
-/*                                                                           */
-/*  This implementation differs from that given by Guibas and Stolfi.  It    */
-/*  walks from triangle to triangle, crossing an edge only if `searchpoint'  */
-/*  is on the other side of the line containing that edge.  After entering   */
-/*  a triangle, there are two edges by which one can leave that triangle.    */
-/*  If both edges are valid (`searchpoint' is on the other side of both      */
-/*  edges), one of the two is chosen by drawing a line perpendicular to      */
-/*  the entry edge (whose endpoints are `forg' and `fdest') passing through  */
-/*  `fapex'.  Depending on which side of this perpendicular `searchpoint'    */
-/*  falls on, an exit edge is chosen.                                        */
-/*                                                                           */
-/*  This implementation is empirically faster than the Guibas and Stolfi     */
-/*  point location routine (which I originally used), which tends to spiral  */
-/*  in toward its target.                                                    */
-/*                                                                           */
-/*  Returns ONVERTEX if the point lies on an existing vertex.  `searchtri'   */
-/*  is a handle whose origin is the existing vertex.                         */
-/*                                                                           */
-/*  Returns ONEDGE if the point lies on a mesh edge.  `searchtri' is a       */
-/*  handle whose primary edge is the edge on which the point lies.           */
-/*                                                                           */
-/*  Returns INTRIANGLE if the point lies strictly within a triangle.         */
-/*  `searchtri' is a handle on the triangle that contains the point.         */
-/*                                                                           */
-/*  Returns OUTSIDE if the point lies outside the mesh.  `searchtri' is a    */
-/*  handle whose primary edge the point is to the right of.  This might      */
-/*  occur when the circumcenter of a triangle falls just slightly outside    */
-/*  the mesh due to floating-point roundoff error.  It also occurs when      */
-/*  seeking a hole or region point that a foolish user has placed outside    */
-/*  the mesh.                                                                */
-/*                                                                           */
-/*  WARNING:  This routine is designed for convex triangulations, and will   */
-/*  not generally work after the holes and concavities have been carved.     */
-/*  However, it can still be used to find the circumcenter of a triangle, as */
-/*  long as the search is begun from the triangle in question.               */
-/*                                                                           */
-/*****************************************************************************/
-
-enum mesh2d::locateresult
-mesh2d::preciselocate(point searchpoint, struct triedge *searchtri)
-{
-  struct triedge backtracktri;
-  point forg, fdest, fapex;
-  point swappoint;
-  REAL orgorient, destorient;
-  int moveleft;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (verbose > 2) {
-    printf("  Searching for point (%.12g, %.12g).\n",
-           searchpoint[0], searchpoint[1]);
-  }
-  /* Where are we? */
-  org(*searchtri, forg);
-  dest(*searchtri, fdest);
-  apex(*searchtri, fapex);
-  while (1) {
-    if (verbose > 2) {
-      printf("    At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
-             forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
-    }
-    /* Check whether the apex is the point we seek. */
-    if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
-      lprevself(*searchtri);
-      return ONVERTEX;
-    }
-    /* Does the point lie on the other side of the line defined by the */
-    /*   triangle edge opposite the triangle's destination?            */
-    destorient = counterclockwise(forg, fapex, searchpoint);
-    /* Does the point lie on the other side of the line defined by the */
-    /*   triangle edge opposite the triangle's origin?                 */
-    orgorient = counterclockwise(fapex, fdest, searchpoint);
-    if (destorient > 0.0) {
-      if (orgorient > 0.0) {
-        /* Move left if the inner product of (fapex - searchpoint) and  */
-        /*   (fdest - forg) is positive.  This is equivalent to drawing */
-        /*   a line perpendicular to the line (forg, fdest) passing     */
-        /*   through `fapex', and determining which side of this line   */
-        /*   `searchpoint' falls on.                                    */
-        moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
-                   (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
-      } else {
-        moveleft = 1;
-      }
-    } else {
-      if (orgorient > 0.0) {
-        moveleft = 0;
-      } else {
-        /* The point we seek must be on the boundary of or inside this */
-        /*   triangle.                                                 */
-        if (destorient == 0.0) {
-          lprevself(*searchtri);
-          return ONEDGE;
-        }
-        if (orgorient == 0.0) {
-          lnextself(*searchtri);
-          return ONEDGE;
-        }
-        return INTRIANGLE;
-      }
-    }
-
-    /* Move to another triangle.  Leave a trace `backtracktri' in case */
-    /*   floating-point roundoff or some such bogey causes us to walk  */
-    /*   off a boundary of the triangulation.  We can just bounce off  */
-    /*   the boundary as if it were an elastic band.                   */
-    if (moveleft) {
-      lprev(*searchtri, backtracktri);
-      fdest = fapex;
-    } else {
-      lnext(*searchtri, backtracktri);
-      forg = fapex;
-    }
-    sym(backtracktri, *searchtri);
-
-    /* Check for walking off the edge. */
-    if (searchtri->tri == dummytri) {
-      /* Turn around. */
-      triedgecopy(backtracktri, *searchtri);
-      swappoint = forg;
-      forg = fdest;
-      fdest = swappoint;
-      apex(*searchtri, fapex);
-      /* Check if the point really is beyond the triangulation boundary. */
-      destorient = counterclockwise(forg, fapex, searchpoint);
-      orgorient = counterclockwise(fapex, fdest, searchpoint);
-      if ((orgorient < 0.0) && (destorient < 0.0)) {
-        return OUTSIDE;
-      }
-    } else {
-      apex(*searchtri, fapex);
-    }
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  locate()   Find a triangle or edge containing a given point.             */
-/*                                                                           */
-/*  Searching begins from one of:  the input `searchtri', a recently         */
-/*  encountered triangle `recenttri', or from a triangle chosen from a       */
-/*  random sample.  The choice is made by determining which triangle's       */
-/*  origin is closest to the point we are searcing for.  Normally,           */
-/*  `searchtri' should be a handle on the convex hull of the triangulation.  */
-/*                                                                           */
-/*  Details on the random sampling method can be found in the Mucke, Saias,  */
-/*  and Zhu paper cited in the header of this code.                          */
-/*                                                                           */
-/*  On completion, `searchtri' is a triangle that contains `searchpoint'.    */
-/*                                                                           */
-/*  Returns ONVERTEX if the point lies on an existing vertex.  `searchtri'   */
-/*  is a handle whose origin is the existing vertex.                         */
-/*                                                                           */
-/*  Returns ONEDGE if the point lies on a mesh edge.  `searchtri' is a       */
-/*  handle whose primary edge is the edge on which the point lies.           */
-/*                                                                           */
-/*  Returns INTRIANGLE if the point lies strictly within a triangle.         */
-/*  `searchtri' is a handle on the triangle that contains the point.         */
-/*                                                                           */
-/*  Returns OUTSIDE if the point lies outside the mesh.  `searchtri' is a    */
-/*  handle whose primary edge the point is to the right of.  This might      */
-/*  occur when the circumcenter of a triangle falls just slightly outside    */
-/*  the mesh due to floating-point roundoff error.  It also occurs when      */
-/*  seeking a hole or region point that a foolish user has placed outside    */
-/*  the mesh.                                                                */
-/*                                                                           */
-/*  WARNING:  This routine is designed for convex triangulations, and will   */
-/*  not generally work after the holes and concavities have been carved.     */
-/*                                                                           */
-/*****************************************************************************/
-
-enum mesh2d::locateresult
-mesh2d::locate(point searchpoint, struct triedge *searchtri)
-{
-  void **sampleblock;
-  triangle *firsttri;
-  struct triedge sampletri;
-  point torg, tdest;
-  unsigned long alignptr;
-  REAL searchdist, dist;
-  REAL ahead;
-  long sampleblocks, samplesperblock, samplenum;
-  long triblocks;
-  long i, j;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (verbose > 2) {
-    printf("  Randomly sampling for a triangle near point (%.12g, %.12g).\n",
-           searchpoint[0], searchpoint[1]);
-  }
-  /* Record the distance from the suggested starting triangle to the */
-  /*   point we seek.                                                */
-  org(*searchtri, torg);
-  searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
-             + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
-  if (verbose > 2) {
-    printf("    Boundary triangle has origin (%.12g, %.12g).\n",
-           torg[0], torg[1]);
-  }
-
-  /* If a recently encountered triangle has been recorded and has not been */
-  /*   deallocated, test it as a good starting point.                      */
-  if (recenttri.tri != (triangle *) NULL) {
-    if (recenttri.tri[3] != (triangle) NULL) {
-      org(recenttri, torg);
-      if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
-        triedgecopy(recenttri, *searchtri);
-        return ONVERTEX;
-      }
-      dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
-           + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
-      if (dist < searchdist) {
-        triedgecopy(recenttri, *searchtri);
-        searchdist = dist;
-        if (verbose > 2) {
-          printf("    Choosing recent triangle with origin (%.12g, %.12g).\n",
-                 torg[0], torg[1]);
-        }
-      }
-    }
-  }
-
-  /* The number of random samples taken is proportional to the cube root of */
-  /*   the number of triangles in the mesh.  The next bit of code assumes   */
-  /*   that the number of triangles increases monotonically.                */
-  while (SAMPLEFACTOR * samples * samples * samples < triangles.items) {
-    samples++;
-  }
-  triblocks = (triangles.maxitems + TRIPERBLOCK - 1) / TRIPERBLOCK;
-  samplesperblock = 1 + (samples / triblocks);
-  sampleblocks = samples / samplesperblock;
-  sampleblock = triangles.firstblock;
-  sampletri.orient = 0;
-  for (i = 0; i < sampleblocks; i++) {
-    alignptr = (unsigned long) (sampleblock + 1);
-    firsttri = (triangle *) (alignptr + (unsigned long) triangles.alignbytes
-                          - (alignptr % (unsigned long) triangles.alignbytes));
-    for (j = 0; j < samplesperblock; j++) {
-      if (i == triblocks - 1) {
-        samplenum = randomnation((int)
-                                 (triangles.maxitems - (i * TRIPERBLOCK)));
-      } else {
-        samplenum = randomnation(TRIPERBLOCK);
-      }
-      sampletri.tri = (triangle *)
-                      (firsttri + (samplenum * triangles.itemwords));
-      if (sampletri.tri[3] != (triangle) NULL) {
-        org(sampletri, torg);
-        dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
-             + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
-        if (dist < searchdist) {
-          triedgecopy(sampletri, *searchtri);
-          searchdist = dist;
-          if (verbose > 2) {
-            printf("    Choosing triangle with origin (%.12g, %.12g).\n",
-                   torg[0], torg[1]);
-          }
-        }
-      }
-    }
-    sampleblock = (void **) *sampleblock;
-  }
-  /* Where are we? */
-  org(*searchtri, torg);
-  dest(*searchtri, tdest);
-  /* Check the starting triangle's vertices. */
-  if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
-    return ONVERTEX;
-  }
-  if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
-    lnextself(*searchtri);
-    return ONVERTEX;
-  }
-  /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */
-  ahead = counterclockwise(torg, tdest, searchpoint);
-  if (ahead < 0.0) {
-    /* Turn around so that `searchpoint' is to the left of the */
-    /*   edge specified by `searchtri'.                        */
-    symself(*searchtri);
-  } else if (ahead == 0.0) {
-    /* Check if `searchpoint' is between `torg' and `tdest'. */
-    if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0]))
-        && ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
-      return ONEDGE;
-    }
-  }
-  return preciselocate(searchpoint, searchtri);
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Point location routines end here                          *********/
-
-/********* Mesh transformation routines begin here                   *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  insertshelle()   Create a new shell edge and insert it between two       */
-/*                   triangles.                                              */
-/*                                                                           */
-/*  The new shell edge is inserted at the edge described by the handle       */
-/*  `tri'.  Its vertices are properly initialized.  The marker `shellemark'  */
-/*  is applied to the shell edge and, if appropriate, its vertices.          */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::insertshelle(struct triedge *tri, int shellemark)
-{
-  struct triedge oppotri;
-  struct edge newshelle;
-  point triorg, tridest;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  /* Mark points if possible. */
-  org(*tri, triorg);
-  dest(*tri, tridest);
-  if (pointmark(triorg) == 0) {
-    setpointmark(triorg, shellemark);
-  }
-  if (pointmark(tridest) == 0) {
-    setpointmark(tridest, shellemark);
-  }
-  /* Check if there's already a shell edge here. */
-  tspivot(*tri, newshelle);
-  if (newshelle.sh == dummysh) {
-    /* Make new shell edge and initialize its vertices. */
-    makeshelle(&newshelle);
-    setsorg(newshelle, tridest);
-    setsdest(newshelle, triorg);
-    /* Bond new shell edge to the two triangles it is sandwiched between. */
-    /*   Note that the facing triangle `oppotri' might be equal to        */
-    /*   `dummytri' (outer space), but the new shell edge is bonded to it */
-    /*   all the same.                                                    */
-    tsbond(*tri, newshelle);
-    sym(*tri, oppotri);
-    ssymself(newshelle);
-    tsbond(oppotri, newshelle);
-    setmark(newshelle, shellemark);
-    if (verbose > 2) {
-      printf("  Inserting new ");
-      printshelle(&newshelle);
-    }
-  } else {
-    if (mark(newshelle) == 0) {
-      setmark(newshelle, shellemark);
-    }
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  Terminology                                                              */
-/*                                                                           */
-/*  A "local transformation" replaces a small set of triangles with another  */
-/*  set of triangles.  This may or may not involve inserting or deleting a   */
-/*  point.                                                                   */
-/*                                                                           */
-/*  The term "casing" is used to describe the set of triangles that are      */
-/*  attached to the triangles being transformed, but are not transformed     */
-/*  themselves.  Think of the casing as a fixed hollow structure inside      */
-/*  which all the action happens.  A "casing" is only defined relative to    */
-/*  a single transformation; each occurrence of a transformation will        */
-/*  involve a different casing.                                              */
-/*                                                                           */
-/*  A "shell" is similar to a "casing".  The term "shell" describes the set  */
-/*  of shell edges (if any) that are attached to the triangles being         */
-/*  transformed.  However, I sometimes use "shell" to refer to a single      */
-/*  shell edge, so don't get confused.                                       */
-/*                                                                           */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  flip()   Transform two triangles to two different triangles by flipping  */
-/*           an edge within a quadrilateral.                                 */
-/*                                                                           */
-/*  Imagine the original triangles, abc and bad, oriented so that the        */
-/*  shared edge ab lies in a horizontal plane, with the point b on the left  */
-/*  and the point a on the right.  The point c lies below the edge, and the  */
-/*  point d lies above the edge.  The `flipedge' handle holds the edge ab    */
-/*  of triangle abc, and is directed left, from vertex a to vertex b.        */
-/*                                                                           */
-/*  The triangles abc and bad are deleted and replaced by the triangles cdb  */
-/*  and dca.  The triangles that represent abc and bad are NOT deallocated;  */
-/*  they are reused for dca and cdb, respectively.  Hence, any handles that  */
-/*  may have held the original triangles are still valid, although not       */
-/*  directed as they were before.                                            */
-/*                                                                           */
-/*  Upon completion of this routine, the `flipedge' handle holds the edge    */
-/*  dc of triangle dca, and is directed down, from vertex d to vertex c.     */
-/*  (Hence, the two triangles have rotated counterclockwise.)                */
-/*                                                                           */
-/*  WARNING:  This transformation is geometrically valid only if the         */
-/*  quadrilateral adbc is convex.  Furthermore, this transformation is       */
-/*  valid only if there is not a shell edge between the triangles abc and    */
-/*  bad.  This routine does not check either of these preconditions, and     */
-/*  it is the responsibility of the calling routine to ensure that they are  */
-/*  met.  If they are not, the streets shall be filled with wailing and      */
-/*  gnashing of teeth.                                                       */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::flip(struct triedge *flipedge)
-{
-  struct triedge botleft, botright;
-  struct triedge topleft, topright;
-  struct triedge top;
-  struct triedge botlcasing, botrcasing;
-  struct triedge toplcasing, toprcasing;
-  struct edge botlshelle, botrshelle;
-  struct edge toplshelle, toprshelle;
-  point leftpoint, rightpoint, botpoint;
-  point farpoint;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  /* Identify the vertices of the quadrilateral. */
-  org(*flipedge, rightpoint);
-  dest(*flipedge, leftpoint);
-  apex(*flipedge, botpoint);
-  sym(*flipedge, top);
-#ifdef SELF_CHECK
-  if (top.tri == dummytri) {
-    printf("Internal error in flip():  Attempt to flip on boundary.\n");
-    lnextself(*flipedge);
-    return;
-  }
-  if (checksegments) {
-    tspivot(*flipedge, toplshelle);
-    if (toplshelle.sh != dummysh) {
-      printf("Internal error in flip():  Attempt to flip a segment.\n");
-      lnextself(*flipedge);
-      return;
-    }
-  }
-#endif /* SELF_CHECK */
-  apex(top, farpoint);
-
-  /* Identify the casing of the quadrilateral. */
-  lprev(top, topleft);
-  sym(topleft, toplcasing);
-  lnext(top, topright);
-  sym(topright, toprcasing);
-  lnext(*flipedge, botleft);
-  sym(botleft, botlcasing);
-  lprev(*flipedge, botright);
-  sym(botright, botrcasing);
-  /* Rotate the quadrilateral one-quarter turn counterclockwise. */
-  bond(topleft, botlcasing);
-  bond(botleft, botrcasing);
-  bond(botright, toprcasing);
-  bond(topright, toplcasing);
-
-  if (checksegments) {
-    /* Check for shell edges and rebond them to the quadrilateral. */
-    tspivot(topleft, toplshelle);
-    tspivot(botleft, botlshelle);
-    tspivot(botright, botrshelle);
-    tspivot(topright, toprshelle);
-    if (toplshelle.sh == dummysh) {
-      tsdissolve(topright);
-    } else {
-      tsbond(topright, toplshelle);
-    }
-    if (botlshelle.sh == dummysh) {
-      tsdissolve(topleft);
-    } else {
-      tsbond(topleft, botlshelle);
-    }
-    if (botrshelle.sh == dummysh) {
-      tsdissolve(botleft);
-    } else {
-      tsbond(botleft, botrshelle);
-    }
-    if (toprshelle.sh == dummysh) {
-      tsdissolve(botright);
-    } else {
-      tsbond(botright, toprshelle);
-    }
-  }
-
-  /* New point assignments for the rotated quadrilateral. */
-  setorg(*flipedge, farpoint);
-  setdest(*flipedge, botpoint);
-  setapex(*flipedge, rightpoint);
-  setorg(top, botpoint);
-  setdest(top, farpoint);
-  setapex(top, leftpoint);
-  if (verbose > 2) {
-    printf("  Edge flip results in left ");
-    lnextself(topleft);
-    printtriangle(&topleft);
-    printf("  and right ");
-    printtriangle(flipedge);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  insertsite()   Insert a vertex into a Delaunay triangulation,            */
-/*                 performing flips as necessary to maintain the Delaunay    */
-/*                 property.                                                 */
-/*                                                                           */
-/*  The point `insertpoint' is located.  If `searchtri.tri' is not NULL,     */
-/*  the search for the containing triangle begins from `searchtri'.  If      */
-/*  `searchtri.tri' is NULL, a full point location procedure is called.      */
-/*  If `insertpoint' is found inside a triangle, the triangle is split into  */
-/*  three; if `insertpoint' lies on an edge, the edge is split in two,       */
-/*  thereby splitting the two adjacent triangles into four.  Edge flips are  */
-/*  used to restore the Delaunay property.  If `insertpoint' lies on an      */
-/*  existing vertex, no action is taken, and the value DUPLICATEPOINT is     */
-/*  returned.  On return, `searchtri' is set to a handle whose origin is the */
-/*  existing vertex.                                                         */
-/*                                                                           */
-/*  Normally, the parameter `splitedge' is set to NULL, implying that no     */
-/*  segment should be split.  In this case, if `insertpoint' is found to     */
-/*  lie on a segment, no action is taken, and the value VIOLATINGPOINT is    */
-/*  returned.  On return, `searchtri' is set to a handle whose primary edge  */
-/*  is the violated segment.                                                 */
-/*                                                                           */
-/*  If the calling routine wishes to split a segment by inserting a point in */
-/*  it, the parameter `splitedge' should be that segment.  In this case,     */
-/*  `searchtri' MUST be the triangle handle reached by pivoting from that    */
-/*  segment; no point location is done.                                      */
-/*                                                                           */
-/*  `segmentflaws' and `triflaws' are flags that indicate whether or not     */
-/*  there should be checks for the creation of encroached segments or bad    */
-/*  quality faces.  If a newly inserted point encroaches upon segments,      */
-/*  these segments are added to the list of segments to be split if          */
-/*  `segmentflaws' is set.  If bad triangles are created, these are added    */
-/*  to the queue if `triflaws' is set.                                       */
-/*                                                                           */
-/*  If a duplicate point or violated segment does not prevent the point      */
-/*  from being inserted, the return value will be ENCROACHINGPOINT if the    */
-/*  point encroaches upon a segment (and checking is enabled), or            */
-/*  SUCCESSFULPOINT otherwise.  In either case, `searchtri' is set to a      */
-/*  handle whose origin is the newly inserted vertex.                        */
-/*                                                                           */
-/*  insertsite() does not use flip() for reasons of speed; some              */
-/*  information can be reused from edge flip to edge flip, like the          */
-/*  locations of shell edges.                                                */
-/*                                                                           */
-/*****************************************************************************/
-
-enum mesh2d::insertsiteresult
-mesh2d::insertsite(point insertpoint, struct triedge *searchtri,
-                   struct edge *splitedge, int segmentflaws, int triflaws)
-{
-  struct triedge horiz;
-  struct triedge top;
-  struct triedge botleft, botright;
-  struct triedge topleft, topright;
-  struct triedge newbotleft, newbotright;
-  struct triedge newtopright;
-  struct triedge botlcasing, botrcasing;
-  struct triedge toplcasing, toprcasing;
-  struct triedge testtri;
-  struct edge botlshelle, botrshelle;
-  struct edge toplshelle, toprshelle;
-  struct edge brokenshelle;
-  struct edge checkshelle;
-  struct edge rightedge;
-  struct edge newedge;
-  struct edge *encroached;
-  point first;
-  point leftpoint, rightpoint, botpoint, toppoint, farpoint;
-  REAL attrib;
-  REAL area;
-  enum insertsiteresult success;
-  enum locateresult intersect;
-  int doflip;
-  int mirrorflag;
-  int i;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;         /* Temporary variable used by spivot() and tspivot(). */
-
-  if (verbose > 1) {
-    printf("  Inserting (%.12g, %.12g).\n", insertpoint[0], insertpoint[1]);
-  }
-  if (splitedge == (struct edge *) NULL) {
-    /* Find the location of the point to be inserted.  Check if a good */
-    /*   starting triangle has already been provided by the caller.    */
-    if (searchtri->tri == (triangle *) NULL) {
-      /* Find a boundary triangle. */
-      horiz.tri = dummytri;
-      horiz.orient = 0;
-      symself(horiz);
-      /* Search for a triangle containing `insertpoint'. */
-      intersect = locate(insertpoint, &horiz);
-    } else {
-      /* Start searching from the triangle provided by the caller. */
-      triedgecopy(*searchtri, horiz);
-      intersect = preciselocate(insertpoint, &horiz);
-    }
-  } else {
-    /* The calling routine provides the edge in which the point is inserted. */
-    triedgecopy(*searchtri, horiz);
-    intersect = ONEDGE;
-  }
-  if (intersect == ONVERTEX) {
-    /* There's already a vertex there.  Return in `searchtri' a triangle */
-    /*   whose origin is the existing vertex.                            */
-    triedgecopy(horiz, *searchtri);
-    triedgecopy(horiz, recenttri);
-    return DUPLICATEPOINT;
-  }
-  if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
-    /* The vertex falls on an edge or boundary. */
-    if (checksegments && (splitedge == (struct edge *) NULL)) {
-      /* Check whether the vertex falls on a shell edge. */
-      tspivot(horiz, brokenshelle);
-      if (brokenshelle.sh != dummysh) {
-        /* The vertex falls on a shell edge. */
-        /* Return a handle whose primary edge contains the point, */
-        /*   which has not been inserted.                         */
-        triedgecopy(horiz, *searchtri);
-        triedgecopy(horiz, recenttri);
-        return VIOLATINGPOINT;
-      }
-    }
-    /* Insert the point on an edge, dividing one triangle into two (if */
-    /*   the edge lies on a boundary) or two triangles into four.      */
-    lprev(horiz, botright);
-    sym(botright, botrcasing);
-    sym(horiz, topright);
-    /* Is there a second triangle?  (Or does this edge lie on a boundary?) */
-    mirrorflag = topright.tri != dummytri;
-    if (mirrorflag) {
-      lnextself(topright);
-      sym(topright, toprcasing);
-      maketriangle(&newtopright);
-    } else {
-      /* Splitting the boundary edge increases the number of boundary edges. */
-      hullsize++;
-    }
-    maketriangle(&newbotright);
-
-    /* Set the vertices of changed and new triangles. */
-    org(horiz, rightpoint);
-    dest(horiz, leftpoint);
-    apex(horiz, botpoint);
-    setorg(newbotright, botpoint);
-    setdest(newbotright, rightpoint);
-    setapex(newbotright, insertpoint);
-    setorg(horiz, insertpoint);
-    for (i = 0; i < eextras; i++) {
-      /* Set the element attributes of a new triangle. */
-      setelemattribute(newbotright, i, elemattribute(botright, i));
-    }
-    if (vararea) {
-      /* Set the area constraint of a new triangle. */
-      setareabound(newbotright, areabound(botright));
-    }
-    if (mirrorflag) {
-      dest(topright, toppoint);
-      setorg(newtopright, rightpoint);
-      setdest(newtopright, toppoint);
-      setapex(newtopright, insertpoint);
-      setorg(topright, insertpoint);
-      for (i = 0; i < eextras; i++) {
-        /* Set the element attributes of another new triangle. */
-        setelemattribute(newtopright, i, elemattribute(topright, i));
-      }
-      if (vararea) {
-        /* Set the area constraint of another new triangle. */
-        setareabound(newtopright, areabound(topright));
-      }
-    }
-
-    /* There may be shell edges that need to be bonded */
-    /*   to the new triangle(s).                       */
-    if (checksegments) {
-      tspivot(botright, botrshelle);
-      if (botrshelle.sh != dummysh) {
-        tsdissolve(botright);
-        tsbond(newbotright, botrshelle);
-      }
-      if (mirrorflag) {
-        tspivot(topright, toprshelle);
-        if (toprshelle.sh != dummysh) {
-          tsdissolve(topright);
-          tsbond(newtopright, toprshelle);
-        }
-      }
-    }
-
-    /* Bond the new triangle(s) to the surrounding triangles. */
-    bond(newbotright, botrcasing);
-    lprevself(newbotright);
-    bond(newbotright, botright);
-    lprevself(newbotright);
-    if (mirrorflag) {
-      bond(newtopright, toprcasing);
-      lnextself(newtopright);
-      bond(newtopright, topright);
-      lnextself(newtopright);
-      bond(newtopright, newbotright);
-    }
-
-    if (splitedge != (struct edge *) NULL) {
-      /* Split the shell edge into two. */
-      setsdest(*splitedge, insertpoint);
-      ssymself(*splitedge);
-      spivot(*splitedge, rightedge);
-      insertshelle(&newbotright, mark(*splitedge));
-      tspivot(newbotright, newedge);
-      sbond(*splitedge, newedge);
-      ssymself(newedge);
-      sbond(newedge, rightedge);
-      ssymself(*splitedge);
-    }
-
-#ifdef SELF_CHECK
-    if (counterclockwise(rightpoint, leftpoint, botpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle prior to edge point insertion (bottom).\n");
-    }
-    if (mirrorflag) {
-      if (counterclockwise(leftpoint, rightpoint, toppoint) < 0.0) {
-        printf("Internal error in insertsite():\n");
-        printf("  Clockwise triangle prior to edge point insertion (top).\n");
-      }
-      if (counterclockwise(rightpoint, toppoint, insertpoint) < 0.0) {
-        printf("Internal error in insertsite():\n");
-        printf("  Clockwise triangle after edge point insertion (top right).\n"
-               );
-      }
-      if (counterclockwise(toppoint, leftpoint, insertpoint) < 0.0) {
-        printf("Internal error in insertsite():\n");
-        printf("  Clockwise triangle after edge point insertion (top left).\n"
-               );
-      }
-    }
-    if (counterclockwise(leftpoint, botpoint, insertpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle after edge point insertion (bottom left).\n"
-             );
-    }
-    if (counterclockwise(botpoint, rightpoint, insertpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf(
-        "  Clockwise triangle after edge point insertion (bottom right).\n");
-    }
-#endif /* SELF_CHECK */
-    if (verbose > 2) {
-      printf("  Updating bottom left ");
-      printtriangle(&botright);
-      if (mirrorflag) {
-        printf("  Updating top left ");
-        printtriangle(&topright);
-        printf("  Creating top right ");
-        printtriangle(&newtopright);
-      }
-      printf("  Creating bottom right ");
-      printtriangle(&newbotright);
-    }
-
-    /* Position `horiz' on the first edge to check for */
-    /*   the Delaunay property.                        */
-    lnextself(horiz);
-  } else {
-    /* Insert the point in a triangle, splitting it into three. */
-    lnext(horiz, botleft);
-    lprev(horiz, botright);
-    sym(botleft, botlcasing);
-    sym(botright, botrcasing);
-    maketriangle(&newbotleft);
-    maketriangle(&newbotright);
-
-    /* Set the vertices of changed and new triangles. */
-    org(horiz, rightpoint);
-    dest(horiz, leftpoint);
-    apex(horiz, botpoint);
-    setorg(newbotleft, leftpoint);
-    setdest(newbotleft, botpoint);
-    setapex(newbotleft, insertpoint);
-    setorg(newbotright, botpoint);
-    setdest(newbotright, rightpoint);
-    setapex(newbotright, insertpoint);
-    setapex(horiz, insertpoint);
-    for (i = 0; i < eextras; i++) {
-      /* Set the element attributes of the new triangles. */
-      attrib = elemattribute(horiz, i);
-      setelemattribute(newbotleft, i, attrib);
-      setelemattribute(newbotright, i, attrib);
-    }
-    if (vararea) {
-      /* Set the area constraint of the new triangles. */
-      area = areabound(horiz);
-      setareabound(newbotleft, area);
-      setareabound(newbotright, area);
-    }
-
-    /* There may be shell edges that need to be bonded */
-    /*   to the new triangles.                         */
-    if (checksegments) {
-      tspivot(botleft, botlshelle);
-      if (botlshelle.sh != dummysh) {
-        tsdissolve(botleft);
-        tsbond(newbotleft, botlshelle);
-      }
-      tspivot(botright, botrshelle);
-      if (botrshelle.sh != dummysh) {
-        tsdissolve(botright);
-        tsbond(newbotright, botrshelle);
-      }
-    }
-
-    /* Bond the new triangles to the surrounding triangles. */
-    bond(newbotleft, botlcasing);
-    bond(newbotright, botrcasing);
-    lnextself(newbotleft);
-    lprevself(newbotright);
-    bond(newbotleft, newbotright);
-    lnextself(newbotleft);
-    bond(botleft, newbotleft);
-    lprevself(newbotright);
-    bond(botright, newbotright);
-
-#ifdef SELF_CHECK
-    if (counterclockwise(rightpoint, leftpoint, botpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle prior to point insertion.\n");
-    }
-    if (counterclockwise(rightpoint, leftpoint, insertpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle after point insertion (top).\n");
-    }
-    if (counterclockwise(leftpoint, botpoint, insertpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle after point insertion (left).\n");
-    }
-    if (counterclockwise(botpoint, rightpoint, insertpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle after point insertion (right).\n");
-    }
-#endif /* SELF_CHECK */
-    if (verbose > 2) {
-      printf("  Updating top ");
-      printtriangle(&horiz);
-      printf("  Creating left ");
-      printtriangle(&newbotleft);
-      printf("  Creating right ");
-      printtriangle(&newbotright);
-    }
-  }
-
-  /* The insertion is successful by default, unless an encroached */
-  /*   edge is found.                                             */
-  success = SUCCESSFULPOINT;
-  /* Circle around the newly inserted vertex, checking each edge opposite */
-  /*   it for the Delaunay property.  Non-Delaunay edges are flipped.     */
-  /*   `horiz' is always the edge being checked.  `first' marks where to  */
-  /*   stop circling.                                                     */
-  org(horiz, first);
-  rightpoint = first;
-  dest(horiz, leftpoint);
-  /* Circle until finished. */
-  while (1) {
-    /* By default, the edge will be flipped. */
-    doflip = 1;
-    if (checksegments) {
-      /* Check for a segment, which cannot be flipped. */
-      tspivot(horiz, checkshelle);
-      if (checkshelle.sh != dummysh) {
-        /* The edge is a segment and cannot be flipped. */
-        doflip = 0;
-      }
-    }
-    if (doflip) {
-      /* Check if the edge is a boundary edge. */
-      sym(horiz, top);
-      if (top.tri == dummytri) {
-        /* The edge is a boundary edge and cannot be flipped. */
-        doflip = 0;
-      } else {
-        /* Find the point on the other side of the edge. */
-        apex(top, farpoint);
-        /* In the incremental Delaunay triangulation algorithm, any of    */
-        /*   `leftpoint', `rightpoint', and `farpoint' could be vertices  */
-        /*   of the triangular bounding box.  These vertices must be      */
-        /*   treated as if they are infinitely distant, even though their */
-        /*   "coordinates" are not.                                       */
-        if ((leftpoint == infpoint1) || (leftpoint == infpoint2)
-                   || (leftpoint == infpoint3)) {
-          /* `leftpoint' is infinitely distant.  Check the convexity of */
-          /*   the boundary of the triangulation.  'farpoint' might be  */
-          /*   infinite as well, but trust me, this same condition      */
-          /*   should be applied.                                       */
-          doflip = counterclockwise(insertpoint, rightpoint, farpoint) > 0.0;
-        } else if ((rightpoint == infpoint1) || (rightpoint == infpoint2)
-                   || (rightpoint == infpoint3)) {
-          /* `rightpoint' is infinitely distant.  Check the convexity of */
-          /*   the boundary of the triangulation.  'farpoint' might be  */
-          /*   infinite as well, but trust me, this same condition      */
-          /*   should be applied.                                       */
-          doflip = counterclockwise(farpoint, leftpoint, insertpoint) > 0.0;
-        } else if ((farpoint == infpoint1) || (farpoint == infpoint2)
-            || (farpoint == infpoint3)) {
-          /* `farpoint' is infinitely distant and cannot be inside */
-          /*   the circumcircle of the triangle `horiz'.           */
-          doflip = 0;
-        } else {
-          /* Test whether the edge is locally Delaunay. */
-          doflip = iincircle(leftpoint, insertpoint, rightpoint, farpoint)
-                   > 0.0;
-        }
-        if (doflip) {
-          /* We made it!  Flip the edge `horiz' by rotating its containing */
-          /*   quadrilateral (the two triangles adjacent to `horiz').      */
-          /* Identify the casing of the quadrilateral. */
-          lprev(top, topleft);
-          sym(topleft, toplcasing);
-          lnext(top, topright);
-          sym(topright, toprcasing);
-          lnext(horiz, botleft);
-          sym(botleft, botlcasing);
-          lprev(horiz, botright);
-          sym(botright, botrcasing);
-          /* Rotate the quadrilateral one-quarter turn counterclockwise. */
-          bond(topleft, botlcasing);
-          bond(botleft, botrcasing);
-          bond(botright, toprcasing);
-          bond(topright, toplcasing);
-          if (checksegments) {
-            /* Check for shell edges and rebond them to the quadrilateral. */
-            tspivot(topleft, toplshelle);
-            tspivot(botleft, botlshelle);
-            tspivot(botright, botrshelle);
-            tspivot(topright, toprshelle);
-            if (toplshelle.sh == dummysh) {
-              tsdissolve(topright);
-            } else {
-              tsbond(topright, toplshelle);
-            }
-            if (botlshelle.sh == dummysh) {
-              tsdissolve(topleft);
-            } else {
-              tsbond(topleft, botlshelle);
-            }
-            if (botrshelle.sh == dummysh) {
-              tsdissolve(botleft);
-            } else {
-              tsbond(botleft, botrshelle);
-            }
-            if (toprshelle.sh == dummysh) {
-              tsdissolve(botright);
-            } else {
-              tsbond(botright, toprshelle);
-            }
-          }
-          /* New point assignments for the rotated quadrilateral. */
-          setorg(horiz, farpoint);
-          setdest(horiz, insertpoint);
-          setapex(horiz, rightpoint);
-          setorg(top, insertpoint);
-          setdest(top, farpoint);
-          setapex(top, leftpoint);
-          for (i = 0; i < eextras; i++) {
-            /* Take the average of the two triangles' attributes. */
-            attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i));
-            setelemattribute(top, i, attrib);
-            setelemattribute(horiz, i, attrib);
-          }
-          if (vararea) {
-            if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
-              area = -1.0;
-            } else {
-              /* Take the average of the two triangles' area constraints.    */
-              /*   This prevents small area constraints from migrating a     */
-              /*   long, long way from their original location due to flips. */
-              area = 0.5 * (areabound(top) + areabound(horiz));
-            }
-            setareabound(top, area);
-            setareabound(horiz, area);
-          }
-#ifdef SELF_CHECK
-          if (insertpoint != (point) NULL) {
-            if (counterclockwise(leftpoint, insertpoint, rightpoint) < 0.0) {
-              printf("Internal error in insertsite():\n");
-              printf("  Clockwise triangle prior to edge flip (bottom).\n");
-            }
-            /* The following test has been removed because constrainededge() */
-            /*   sometimes generates inverted triangles that insertsite()    */
-            /*   removes.                                                    */
-/*
-            if (counterclockwise(rightpoint, farpoint, leftpoint) < 0.0) {
-              printf("Internal error in insertsite():\n");
-              printf("  Clockwise triangle prior to edge flip (top).\n");
-            }
-*/
-            if (counterclockwise(farpoint, leftpoint, insertpoint) < 0.0) {
-              printf("Internal error in insertsite():\n");
-              printf("  Clockwise triangle after edge flip (left).\n");
-            }
-            if (counterclockwise(insertpoint, rightpoint, farpoint) < 0.0) {
-              printf("Internal error in insertsite():\n");
-              printf("  Clockwise triangle after edge flip (right).\n");
-            }
-          }
-#endif /* SELF_CHECK */
-          if (verbose > 2) {
-            printf("  Edge flip results in left ");
-            lnextself(topleft);
-            printtriangle(&topleft);
-            printf("  and right ");
-            printtriangle(&horiz);
-          }
-          /* On the next iterations, consider the two edges that were  */
-          /*   exposed (this is, are now visible to the newly inserted */
-          /*   point) by the edge flip.                                */
-          lprevself(horiz);
-          leftpoint = farpoint;
-        }
-      }
-    }
-    if (!doflip) {
-      /* The handle `horiz' is accepted as locally Delaunay. */
-      /* Look for the next edge around the newly inserted point. */
-      lnextself(horiz);
-      sym(horiz, testtri);
-      /* Check for finishing a complete revolution about the new point, or */
-      /*   falling off the edge of the triangulation.  The latter will     */
-      /*   happen when a point is inserted at a boundary.                  */
-      if ((leftpoint == first) || (testtri.tri == dummytri)) {
-        /* We're done.  Return a triangle whose origin is the new point. */
-        lnext(horiz, *searchtri);
-        lnext(horiz, recenttri);
-        return success;
-      }
-      /* Finish finding the next edge around the newly inserted point. */
-      lnext(testtri, horiz);
-      rightpoint = leftpoint;
-      dest(horiz, leftpoint);
-    }
-  }
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Mesh transformation routines end here                     *********/
-
-/********* Divide-and-conquer Delaunay triangulation begins here     *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  The divide-and-conquer bounding box                                      */
-/*                                                                           */
-/*  I originally implemented the divide-and-conquer and incremental Delaunay */
-/*  triangulations using the edge-based data structure presented by Guibas   */
-/*  and Stolfi.  Switching to a triangle-based data structure doubled the    */
-/*  speed.  However, I had to think of a few extra tricks to maintain the    */
-/*  elegance of the original algorithms.                                     */
-/*                                                                           */
-/*  The "bounding box" used by my variant of the divide-and-conquer          */
-/*  algorithm uses one triangle for each edge of the convex hull of the      */
-/*  triangulation.  These bounding triangles all share a common apical       */
-/*  vertex, which is represented by NULL and which represents nothing.       */
-/*  The bounding triangles are linked in a circular fan about this NULL      */
-/*  vertex, and the edges on the convex hull of the triangulation appear     */
-/*  opposite the NULL vertex.  You might find it easiest to imagine that     */
-/*  the NULL vertex is a point in 3D space behind the center of the          */
-/*  triangulation, and that the bounding triangles form a sort of cone.      */
-/*                                                                           */
-/*  This bounding box makes it easy to represent degenerate cases.  For      */
-/*  instance, the triangulation of two vertices is a single edge.  This edge */
-/*  is represented by two bounding box triangles, one on each "side" of the  */
-/*  edge.  These triangles are also linked together in a fan about the NULL  */
-/*  vertex.                                                                  */
-/*                                                                           */
-/*  The bounding box also makes it easy to traverse the convex hull, as the  */
-/*  divide-and-conquer algorithm needs to do.                                */
-/*                                                                           */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  pointsort()   Sort an array of points by x-coordinate, using the         */
-/*                y-coordinate as a secondary key.                           */
-/*                                                                           */
-/*  Uses quicksort.  Randomized O(n log n) time.  No, I did not make any of  */
-/*  the usual quicksort mistakes.                                            */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::pointsort(point *sortarray, int arraysize)
-{
-  int left, right;
-  int pivot;
-  REAL pivotx, pivoty;
-  point temp;
-
-  if (arraysize == 2) {
-    /* Recursive base case. */
-    if ((sortarray[0][0] > sortarray[1][0]) ||
-        ((sortarray[0][0] == sortarray[1][0]) &&
-         (sortarray[0][1] > sortarray[1][1]))) {
-      temp = sortarray[1];
-      sortarray[1] = sortarray[0];
-      sortarray[0] = temp;
-    }
-    return;
-  }
-  /* Choose a random pivot to split the array. */
-  pivot = (int) randomnation(arraysize);
-  pivotx = sortarray[pivot][0];
-  pivoty = sortarray[pivot][1];
-  /* Split the array. */
-  left = -1;
-  right = arraysize;
-  while (left < right) {
-    /* Search for a point whose x-coordinate is too large for the left. */
-    do {
-      left++;
-    } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
-                                 ((sortarray[left][0] == pivotx) &&
-                                  (sortarray[left][1] < pivoty))));
-    /* Search for a point whose x-coordinate is too small for the right. */
-    do {
-      right--;
-    } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
-                                 ((sortarray[right][0] == pivotx) &&
-                                  (sortarray[right][1] > pivoty))));
-    if (left < right) {
-      /* Swap the left and right points. */
-      temp = sortarray[left];
-      sortarray[left] = sortarray[right];
-      sortarray[right] = temp;
-    }
-  }
-  if (left > 1) {
-    /* Recursively sort the left subset. */
-    pointsort(sortarray, left);
-  }
-  if (right < arraysize - 2) {
-    /* Recursively sort the right subset. */
-    pointsort(&sortarray[right + 1], arraysize - right - 1);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  pointmedian()   An order statistic algorithm, almost.  Shuffles an array */
-/*                  of points so that the first `median' points occur        */
-/*                  lexicographically before the remaining points.           */
-/*                                                                           */
-/*  Uses the x-coordinate as the primary key if axis == 0; the y-coordinate  */
-/*  if axis == 1.  Very similar to the pointsort() procedure, but runs in    */
-/*  randomized linear time.                                                  */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::pointmedian(point *sortarray, int arraysize, int median, int axis)
-{
-  int left, right;
-  int pivot;
-  REAL pivot1, pivot2;
-  point temp;
-
-  if (arraysize == 2) {
-    /* Recursive base case. */
-    if ((sortarray[0][axis] > sortarray[1][axis]) ||
-        ((sortarray[0][axis] == sortarray[1][axis]) &&
-         (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
-      temp = sortarray[1];
-      sortarray[1] = sortarray[0];
-      sortarray[0] = temp;
-    }
-    return;
-  }
-  /* Choose a random pivot to split the array. */
-  pivot = (int) randomnation(arraysize);
-  pivot1 = sortarray[pivot][axis];
-  pivot2 = sortarray[pivot][1 - axis];
-  /* Split the array. */
-  left = -1;
-  right = arraysize;
-  while (left < right) {
-    /* Search for a point whose x-coordinate is too large for the left. */
-    do {
-      left++;
-    } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
-                                 ((sortarray[left][axis] == pivot1) &&
-                                  (sortarray[left][1 - axis] < pivot2))));
-    /* Search for a point whose x-coordinate is too small for the right. */
-    do {
-      right--;
-    } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
-                                 ((sortarray[right][axis] == pivot1) &&
-                                  (sortarray[right][1 - axis] > pivot2))));
-    if (left < right) {
-      /* Swap the left and right points. */
-      temp = sortarray[left];
-      sortarray[left] = sortarray[right];
-      sortarray[right] = temp;
-    }
-  }
-  /* Unlike in pointsort(), at most one of the following */
-  /*   conditionals is true.                             */
-  if (left > median) {
-    /* Recursively shuffle the left subset. */
-    pointmedian(sortarray, left, median, axis);
-  }
-  if (right < median - 1) {
-    /* Recursively shuffle the right subset. */
-    pointmedian(&sortarray[right + 1], arraysize - right - 1,
-                median - right - 1, axis);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  alternateaxes()   Sorts the points as appropriate for the divide-and-    */
-/*                    conquer algorithm with alternating cuts.               */
-/*                                                                           */
-/*  Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1.   */
-/*  For the base case, subsets containing only two or three points are       */
-/*  always sorted by x-coordinate.                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::alternateaxes(point *sortarray, int arraysize, int axis)
-{
-  int divider;
-
-  divider = arraysize >> 1;
-  if (arraysize <= 3) {
-    /* Recursive base case:  subsets of two or three points will be      */
-    /*   handled specially, and should always be sorted by x-coordinate. */
-    axis = 0;
-  }
-  /* Partition with a horizontal or vertical cut. */
-  pointmedian(sortarray, arraysize, divider, axis);
-  /* Recursively partition the subsets with a cross cut. */
-  if (arraysize - divider >= 2) {
-    if (divider >= 2) {
-      alternateaxes(sortarray, divider, 1 - axis);
-    }
-    alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  mergehulls()   Merge two adjacent Delaunay triangulations into a         */
-/*                 single Delaunay triangulation.                            */
-/*                                                                           */
-/*  This is similar to the algorithm given by Guibas and Stolfi, but uses    */
-/*  a triangle-based, rather than edge-based, data structure.                */
-/*                                                                           */
-/*  The algorithm walks up the gap between the two triangulations, knitting  */
-/*  them together.  As they are merged, some of their bounding triangles     */
-/*  are converted into real triangles of the triangulation.  The procedure   */
-/*  pulls each hull's bounding triangles apart, then knits them together     */
-/*  like the teeth of two gears.  The Delaunay property determines, at each  */
-/*  step, whether the next "tooth" is a bounding triangle of the left hull   */
-/*  or the right.  When a bounding triangle becomes real, its apex is        */
-/*  changed from NULL to a real point.                                       */
-/*                                                                           */
-/*  Only two new triangles need to be allocated.  These become new bounding  */
-/*  triangles at the top and bottom of the seam.  They are used to connect   */
-/*  the remaining bounding triangles (those that have not been converted     */
-/*  into real triangles) into a single fan.                                  */
-/*                                                                           */
-/*  On entry, `farleft' and `innerleft' are bounding triangles of the left   */
-/*  triangulation.  The origin of `farleft' is the leftmost vertex, and      */
-/*  the destination of `innerleft' is the rightmost vertex of the            */
-/*  triangulation.  Similarly, `innerright' and `farright' are bounding      */
-/*  triangles of the right triangulation.  The origin of `innerright' and    */
-/*  destination of `farright' are the leftmost and rightmost vertices.       */
-/*                                                                           */
-/*  On completion, the origin of `farleft' is the leftmost vertex of the     */
-/*  merged triangulation, and the destination of `farright' is the rightmost */
-/*  vertex.                                                                  */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::mergehulls(struct triedge *farleft, struct triedge *innerleft,
-                        struct triedge *innerright, struct triedge *farright,
-                        int axis)
-{
-  struct triedge leftcand, rightcand;
-  struct triedge baseedge;
-  struct triedge nextedge;
-  struct triedge sidecasing, topcasing, outercasing;
-  struct triedge checkedge;
-  point innerleftdest;
-  point innerrightorg;
-  point innerleftapex, innerrightapex;
-  point farleftpt, farrightpt;
-  point farleftapex, farrightapex;
-  point lowerleft, lowerright;
-  point upperleft, upperright;
-  point nextapex;
-  point checkvertex;
-  int changemade;
-  int badedge;
-  int leftfinished, rightfinished;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  dest(*innerleft, innerleftdest);
-  apex(*innerleft, innerleftapex);
-  org(*innerright, innerrightorg);
-  apex(*innerright, innerrightapex);
-  /* Special treatment for horizontal cuts. */
-  if (dwyer && (axis == 1)) {
-    org(*farleft, farleftpt);
-    apex(*farleft, farleftapex);
-    dest(*farright, farrightpt);
-    apex(*farright, farrightapex);
-    /* The pointers to the extremal points are shifted to point to the */
-    /*   topmost and bottommost point of each hull, rather than the    */
-    /*   leftmost and rightmost points.                                */
-    while (farleftapex[1] < farleftpt[1]) {
-      lnextself(*farleft);
-      symself(*farleft);
-      farleftpt = farleftapex;
-      apex(*farleft, farleftapex);
-    }
-    sym(*innerleft, checkedge);
-    apex(checkedge, checkvertex);
-    while (checkvertex[1] > innerleftdest[1]) {
-      lnext(checkedge, *innerleft);
-      innerleftapex = innerleftdest;
-      innerleftdest = checkvertex;
-      sym(*innerleft, checkedge);
-      apex(checkedge, checkvertex);
-    }
-    while (innerrightapex[1] < innerrightorg[1]) {
-      lnextself(*innerright);
-      symself(*innerright);
-      innerrightorg = innerrightapex;
-      apex(*innerright, innerrightapex);
-    }
-    sym(*farright, checkedge);
-    apex(checkedge, checkvertex);
-    while (checkvertex[1] > farrightpt[1]) {
-      lnext(checkedge, *farright);
-      farrightapex = farrightpt;
-      farrightpt = checkvertex;
-      sym(*farright, checkedge);
-      apex(checkedge, checkvertex);
-    }
-  }
-  /* Find a line tangent to and below both hulls. */
-  do {
-    changemade = 0;
-    /* Make innerleftdest the "bottommost" point of the left hull. */
-    if (counterclockwise(innerleftdest, innerleftapex, innerrightorg) > 0.0) {
-      lprevself(*innerleft);
-      symself(*innerleft);
-      innerleftdest = innerleftapex;
-      apex(*innerleft, innerleftapex);
-      changemade = 1;
-    }
-    /* Make innerrightorg the "bottommost" point of the right hull. */
-    if (counterclockwise(innerrightapex, innerrightorg, innerleftdest) > 0.0) {
-      lnextself(*innerright);
-      symself(*innerright);
-      innerrightorg = innerrightapex;
-      apex(*innerright, innerrightapex);
-      changemade = 1;
-    }
-  } while (changemade);
-  /* Find the two candidates to be the next "gear tooth". */
-  sym(*innerleft, leftcand);
-  sym(*innerright, rightcand);
-  /* Create the bottom new bounding triangle. */
-  maketriangle(&baseedge);
-  /* Connect it to the bounding boxes of the left and right triangulations. */
-  bond(baseedge, *innerleft);
-  lnextself(baseedge);
-  bond(baseedge, *innerright);
-  lnextself(baseedge);
-  setorg(baseedge, innerrightorg);
-  setdest(baseedge, innerleftdest);
-  /* Apex is intentionally left NULL. */
-  if (verbose > 2) {
-    printf("  Creating base bounding ");
-    printtriangle(&baseedge);
-  }
-  /* Fix the extreme triangles if necessary. */
-  org(*farleft, farleftpt);
-  if (innerleftdest == farleftpt) {
-    lnext(baseedge, *farleft);
-  }
-  dest(*farright, farrightpt);
-  if (innerrightorg == farrightpt) {
-    lprev(baseedge, *farright);
-  }
-  /* The vertices of the current knitting edge. */
-  lowerleft = innerleftdest;
-  lowerright = innerrightorg;
-  /* The candidate vertices for knitting. */
-  apex(leftcand, upperleft);
-  apex(rightcand, upperright);
-  /* Walk up the gap between the two triangulations, knitting them together. */
-  while (1) {
-    /* Have we reached the top?  (This isn't quite the right question,       */
-    /*   because even though the left triangulation might seem finished now, */
-    /*   moving up on the right triangulation might reveal a new point of    */
-    /*   the left triangulation.  And vice-versa.)                           */
-    leftfinished = counterclockwise(upperleft, lowerleft, lowerright) <= 0.0;
-    rightfinished = counterclockwise(upperright, lowerleft, lowerright) <= 0.0;
-    if (leftfinished && rightfinished) {
-      /* Create the top new bounding triangle. */
-      maketriangle(&nextedge);
-      setorg(nextedge, lowerleft);
-      setdest(nextedge, lowerright);
-      /* Apex is intentionally left NULL. */
-      /* Connect it to the bounding boxes of the two triangulations. */
-      bond(nextedge, baseedge);
-      lnextself(nextedge);
-      bond(nextedge, rightcand);
-      lnextself(nextedge);
-      bond(nextedge, leftcand);
-      if (verbose > 2) {
-        printf("  Creating top bounding ");
-        printtriangle(&baseedge);
-      }
-      /* Special treatment for horizontal cuts. */
-      if (dwyer && (axis == 1)) {
-        org(*farleft, farleftpt);
-        apex(*farleft, farleftapex);
-        dest(*farright, farrightpt);
-        apex(*farright, farrightapex);
-        sym(*farleft, checkedge);
-        apex(checkedge, checkvertex);
-        /* The pointers to the extremal points are restored to the leftmost */
-        /*   and rightmost points (rather than topmost and bottommost).     */
-        while (checkvertex[0] < farleftpt[0]) {
-          lprev(checkedge, *farleft);
-          farleftapex = farleftpt;
-          farleftpt = checkvertex;
-          sym(*farleft, checkedge);
-          apex(checkedge, checkvertex);
-        }
-        while (farrightapex[0] > farrightpt[0]) {
-          lprevself(*farright);
-          symself(*farright);
-          farrightpt = farrightapex;
-          apex(*farright, farrightapex);
-        }
-      }
-      return;
-    }
-    /* Consider eliminating edges from the left triangulation. */
-    if (!leftfinished) {
-      /* What vertex would be exposed if an edge were deleted? */
-      lprev(leftcand, nextedge);
-      symself(nextedge);
-      apex(nextedge, nextapex);
-      /* If nextapex is NULL, then no vertex would be exposed; the */
-      /*   triangulation would have been eaten right through.      */
-      if (nextapex != (point) NULL) {
-        /* Check whether the edge is Delaunay. */
-        badedge = iincircle(lowerleft, lowerright, upperleft, nextapex) > 0.0;
-        while (badedge) {
-          /* Eliminate the edge with an edge flip.  As a result, the    */
-          /*   left triangulation will have one more boundary triangle. */
-          lnextself(nextedge);
-          sym(nextedge, topcasing);
-          lnextself(nextedge);
-          sym(nextedge, sidecasing);
-          bond(nextedge, topcasing);
-          bond(leftcand, sidecasing);
-          lnextself(leftcand);
-          sym(leftcand, outercasing);
-          lprevself(nextedge);
-          bond(nextedge, outercasing);
-          /* Correct the vertices to reflect the edge flip. */
-          setorg(leftcand, lowerleft);
-          setdest(leftcand, NULL);
-          setapex(leftcand, nextapex);
-          setorg(nextedge, NULL);
-          setdest(nextedge, upperleft);
-          setapex(nextedge, nextapex);
-          /* Consider the newly exposed vertex. */
-          upperleft = nextapex;
-          /* What vertex would be exposed if another edge were deleted? */
-          triedgecopy(sidecasing, nextedge);
-          apex(nextedge, nextapex);
-          if (nextapex != (point) NULL) {
-            /* Check whether the edge is Delaunay. */
-            badedge = iincircle(lowerleft, lowerright, upperleft, nextapex)
-                      > 0.0;
-          } else {
-            /* Avoid eating right through the triangulation. */
-            badedge = 0;
-          }
-        }
-      }
-    }
-    /* Consider eliminating edges from the right triangulation. */
-    if (!rightfinished) {
-      /* What vertex would be exposed if an edge were deleted? */
-      lnext(rightcand, nextedge);
-      symself(nextedge);
-      apex(nextedge, nextapex);
-      /* If nextapex is NULL, then no vertex would be exposed; the */
-      /*   triangulation would have been eaten right through.      */
-      if (nextapex != (point) NULL) {
-        /* Check whether the edge is Delaunay. */
-        badedge = iincircle(lowerleft, lowerright, upperright, nextapex) > 0.0;
-        while (badedge) {
-          /* Eliminate the edge with an edge flip.  As a result, the     */
-          /*   right triangulation will have one more boundary triangle. */
-          lprevself(nextedge);
-          sym(nextedge, topcasing);
-          lprevself(nextedge);
-          sym(nextedge, sidecasing);
-          bond(nextedge, topcasing);
-          bond(rightcand, sidecasing);
-          lprevself(rightcand);
-          sym(rightcand, outercasing);
-          lnextself(nextedge);
-          bond(nextedge, outercasing);
-          /* Correct the vertices to reflect the edge flip. */
-          setorg(rightcand, NULL);
-          setdest(rightcand, lowerright);
-          setapex(rightcand, nextapex);
-          setorg(nextedge, upperright);
-          setdest(nextedge, NULL);
-          setapex(nextedge, nextapex);
-          /* Consider the newly exposed vertex. */
-          upperright = nextapex;
-          /* What vertex would be exposed if another edge were deleted? */
-          triedgecopy(sidecasing, nextedge);
-          apex(nextedge, nextapex);
-          if (nextapex != (point) NULL) {
-            /* Check whether the edge is Delaunay. */
-            badedge = iincircle(lowerleft, lowerright, upperright, nextapex)
-                      > 0.0;
-          } else {
-            /* Avoid eating right through the triangulation. */
-            badedge = 0;
-          }
-        }
-      }
-    }
-    if (leftfinished || (!rightfinished &&
-           (iincircle(upperleft, lowerleft, lowerright, upperright) > 0.0))) {
-      /* Knit the triangulations, adding an edge from `lowerleft' */
-      /*   to `upperright'.                                       */
-      bond(baseedge, rightcand);
-      lprev(rightcand, baseedge);
-      setdest(baseedge, lowerleft);
-      lowerright = upperright;
-      sym(baseedge, rightcand);
-      apex(rightcand, upperright);
-    } else {
-      /* Knit the triangulations, adding an edge from `upperleft' */
-      /*   to `lowerright'.                                       */
-      bond(baseedge, leftcand);
-      lnext(leftcand, baseedge);
-      setorg(baseedge, lowerright);
-      lowerleft = upperleft;
-      sym(baseedge, leftcand);
-      apex(leftcand, upperleft);
-    }
-    if (verbose > 2) {
-      printf("  Connecting ");
-      printtriangle(&baseedge);
-    }
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  divconqrecurse()   Recursively form a Delaunay triangulation by the      */
-/*                     divide-and-conquer method.                            */
-/*                                                                           */
-/*  Recursively breaks down the problem into smaller pieces, which are       */
-/*  knitted together by mergehulls().  The base cases (problems of two or    */
-/*  three points) are handled specially here.                                */
-/*                                                                           */
-/*  On completion, `farleft' and `farright' are bounding triangles such that */
-/*  the origin of `farleft' is the leftmost vertex (breaking ties by         */
-/*  choosing the highest leftmost vertex), and the destination of            */
-/*  `farright' is the rightmost vertex (breaking ties by choosing the        */
-/*  lowest rightmost vertex).                                                */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::divconqrecurse(point *sortarray, int vertices, int axis,
-                            struct triedge *farleft, struct triedge *farright)
-{
-  struct triedge midtri, tri1, tri2, tri3;
-  struct triedge innerleft, innerright;
-  REAL area;
-  int divider;
-
-  if (verbose > 2) {
-    printf("  Triangulating %d points.\n", vertices);
-  }
-  if (vertices == 2) {
-    /* The triangulation of two vertices is an edge.  An edge is */
-    /*   represented by two bounding triangles.                  */
-    maketriangle(farleft);
-    setorg(*farleft, sortarray[0]);
-    setdest(*farleft, sortarray[1]);
-    /* The apex is intentionally left NULL. */
-    maketriangle(farright);
-    setorg(*farright, sortarray[1]);
-    setdest(*farright, sortarray[0]);
-    /* The apex is intentionally left NULL. */
-    bond(*farleft, *farright);
-    lprevself(*farleft);
-    lnextself(*farright);
-    bond(*farleft, *farright);
-    lprevself(*farleft);
-    lnextself(*farright);
-    bond(*farleft, *farright);
-    if (verbose > 2) {
-      printf("  Creating ");
-      printtriangle(farleft);
-      printf("  Creating ");
-      printtriangle(farright);
-    }
-    /* Ensure that the origin of `farleft' is sortarray[0]. */
-    lprev(*farright, *farleft);
-    return;
-  } else if (vertices == 3) {
-    /* The triangulation of three vertices is either a triangle (with */
-    /*   three bounding triangles) or two edges (with four bounding   */
-    /*   triangles).  In either case, four triangles are created.     */
-    maketriangle(&midtri);
-    maketriangle(&tri1);
-    maketriangle(&tri2);
-    maketriangle(&tri3);
-    area = counterclockwise(sortarray[0], sortarray[1], sortarray[2]);
-    if (area == 0.0) {
-      /* Three collinear points; the triangulation is two edges. */
-      setorg(midtri, sortarray[0]);
-      setdest(midtri, sortarray[1]);
-      setorg(tri1, sortarray[1]);
-      setdest(tri1, sortarray[0]);
-      setorg(tri2, sortarray[2]);
-      setdest(tri2, sortarray[1]);
-      setorg(tri3, sortarray[1]);
-      setdest(tri3, sortarray[2]);
-      /* All apices are intentionally left NULL. */
-      bond(midtri, tri1);
-      bond(tri2, tri3);
-      lnextself(midtri);
-      lprevself(tri1);
-      lnextself(tri2);
-      lprevself(tri3);
-      bond(midtri, tri3);
-      bond(tri1, tri2);
-      lnextself(midtri);
-      lprevself(tri1);
-      lnextself(tri2);
-      lprevself(tri3);
-      bond(midtri, tri1);
-      bond(tri2, tri3);
-      /* Ensure that the origin of `farleft' is sortarray[0]. */
-      triedgecopy(tri1, *farleft);
-      /* Ensure that the destination of `farright' is sortarray[2]. */
-      triedgecopy(tri2, *farright);
-    } else {
-      /* The three points are not collinear; the triangulation is one */
-      /*   triangle, namely `midtri'.                                 */
-      setorg(midtri, sortarray[0]);
-      setdest(tri1, sortarray[0]);
-      setorg(tri3, sortarray[0]);
-      /* Apices of tri1, tri2, and tri3 are left NULL. */
-      if (area > 0.0) {
-        /* The vertices are in counterclockwise order. */
-        setdest(midtri, sortarray[1]);
-        setorg(tri1, sortarray[1]);
-        setdest(tri2, sortarray[1]);
-        setapex(midtri, sortarray[2]);
-        setorg(tri2, sortarray[2]);
-        setdest(tri3, sortarray[2]);
-      } else {
-        /* The vertices are in clockwise order. */
-        setdest(midtri, sortarray[2]);
-        setorg(tri1, sortarray[2]);
-        setdest(tri2, sortarray[2]);
-        setapex(midtri, sortarray[1]);
-        setorg(tri2, sortarray[1]);
-        setdest(tri3, sortarray[1]);
-      }
-      /* The topology does not depend on how the vertices are ordered. */
-      bond(midtri, tri1);
-      lnextself(midtri);
-      bond(midtri, tri2);
-      lnextself(midtri);
-      bond(midtri, tri3);
-      lprevself(tri1);
-      lnextself(tri2);
-      bond(tri1, tri2);
-      lprevself(tri1);
-      lprevself(tri3);
-      bond(tri1, tri3);
-      lnextself(tri2);
-      lprevself(tri3);
-      bond(tri2, tri3);
-      /* Ensure that the origin of `farleft' is sortarray[0]. */
-      triedgecopy(tri1, *farleft);
-      /* Ensure that the destination of `farright' is sortarray[2]. */
-      if (area > 0.0) {
-        triedgecopy(tri2, *farright);
-      } else {
-        lnext(*farleft, *farright);
-      }
-    }
-    if (verbose > 2) {
-      printf("  Creating ");
-      printtriangle(&midtri);
-      printf("  Creating ");
-      printtriangle(&tri1);
-      printf("  Creating ");
-      printtriangle(&tri2);
-      printf("  Creating ");
-      printtriangle(&tri3);
-    }
-    return;
-  } else {
-    /* Split the vertices in half. */
-    divider = vertices >> 1;
-    /* Recursively triangulate each half. */
-    divconqrecurse(sortarray, divider, 1 - axis, farleft, &innerleft);
-    divconqrecurse(&sortarray[divider], vertices - divider, 1 - axis,
-                   &innerright, farright);
-    if (verbose > 1) {
-      printf("  Joining triangulations with %d and %d vertices.\n", divider,
-             vertices - divider);
-    }
-    /* Merge the two triangulations into one. */
-    mergehulls(farleft, &innerleft, &innerright, farright, axis);
-  }
-}
-
-long mesh2d::removeghosts(struct triedge *startghost)
-{
-  struct triedge searchedge;
-  struct triedge dissolveedge;
-  struct triedge deadtri;
-  point markorg;
-  long hullsize;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (verbose) {
-    printf("  Removing ghost triangles.\n");
-  }
-  /* Find an edge on the convex hull to start point location from. */
-  lprev(*startghost, searchedge);
-  symself(searchedge);
-  dummytri[0] = encode(searchedge);
-  /* Remove the bounding box and count the convex hull edges. */
-  triedgecopy(*startghost, dissolveedge);
-  hullsize = 0;
-  do {
-    hullsize++;
-    lnext(dissolveedge, deadtri);
-    lprevself(dissolveedge);
-    symself(dissolveedge);
-    /* If no PSLG is involved, set the boundary markers of all the points */
-    /*   on the convex hull.  If a PSLG is used, this step is done later. */
-    if (!poly) {
-      /* Watch out for the case where all the input points are collinear. */
-      if (dissolveedge.tri != dummytri) {
-        org(dissolveedge, markorg);
-        if (pointmark(markorg) == 0) {
-          setpointmark(markorg, 1);
-        }
-      }
-    }
-    /* Remove a bounding triangle from a convex hull triangle. */
-    dissolve(dissolveedge);
-    /* Find the next bounding triangle. */
-    sym(deadtri, dissolveedge);
-    /* Delete the bounding triangle. */
-    triangledealloc(deadtri.tri);
-  } while (!triedgeequal(dissolveedge, *startghost));
-  return hullsize;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  divconqdelaunay()   Form a Delaunay triangulation by the divide-and-     */
-/*                      conquer method.                                      */
-/*                                                                           */
-/*  Sorts the points, calls a recursive procedure to triangulate them, and   */
-/*  removes the bounding box, setting boundary markers as appropriate.       */
-/*                                                                           */
-/*****************************************************************************/
-
-long mesh2d::divconqdelaunay()
-{
-  point *sortarray;
-  struct triedge hullleft, hullright;
-  int divider;
-  int i, j;
-
-  /* Allocate an array of pointers to points for sorting. */
-  sortarray = (point *) new point[inpoints];
-  if (sortarray == (point *) NULL) {
-    printf("Error:  Out of memory.\n");
-    exit(1);
-  }
-  points.traversalinit();
-  for (i = 0; i < inpoints; i++) {
-    sortarray[i] = pointtraverse();
-  }
-  if (verbose) {
-    printf("  Sorting points.\n");
-  }
-  /* Sort the points. */
-  pointsort(sortarray, inpoints);
-  /* Discard duplicate points, which can really mess up the algorithm. */
-  i = 0;
-  for (j = 1; j < inpoints; j++) {
-    if ((sortarray[i][0] == sortarray[j][0])
-        && (sortarray[i][1] == sortarray[j][1])) {
-      if (!quiet) {
-        printf(
-"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
-               sortarray[j][0], sortarray[j][1]);
-      }
-/*  Commented out - would eliminate point from output .node file, but causes
-    a failure if some segment has this point as an endpoint.
-      setpointmark(sortarray[j], DEADPOINT);
-*/
-    } else {
-      i++;
-      sortarray[i] = sortarray[j];
-    }
-  }
-  i++;
-  if (dwyer) {
-    /* Re-sort the array of points to accommodate alternating cuts. */
-    divider = i >> 1;
-    if (i - divider >= 2) {
-      if (divider >= 2) {
-        alternateaxes(sortarray, divider, 1);
-      }
-      alternateaxes(&sortarray[divider], i - divider, 1);
-    }
-  }
-  if (verbose) {
-    printf("  Forming triangulation.\n");
-  }
-  /* Form the Delaunay triangulation. */
-  divconqrecurse(sortarray, i, 0, &hullleft, &hullright);
-  delete [] sortarray;
-
-  return removeghosts(&hullleft);
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Divide-and-conquer Delaunay triangulation ends here       *********/
-
-/********* General mesh construction routines begin here             *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  delaunay()   Form a Delaunay triangulation.                              */
-/*                                                                           */
-/*****************************************************************************/
-
-long mesh2d::delaunay()
-{
-  eextras = 0;
-  if (!restartsymbol) {
-    initializetrisegpools();
-  }
-  if (!quiet) {
-    printf("Constructing Delaunay triangulation ");
-    if (incremental) {
-      printf("by incremental method.\n");
-    } else if (sweepline) {
-      printf("by sweepline method.\n");
-    } else {
-      printf("by divide-and-conquer method.\n");
-    }
-  }
-  if (incremental) {
-    // return incrementaldelaunay();
-    printf("Sorry, the incremental delaunay algorithm have not");
-    printf(" been transformed.\n");
-    exit(1);
-  } else if (sweepline) {
-    // return sweeplinedelaunay();
-    printf("Sorry, the sweepline delaunay algorithm have not");
-    printf(" been transformed.\n");
-    exit(1);
-  } else {
-    return divconqdelaunay();
-  }
-  return 0;
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* General mesh construction routines end here               *********/
-
-/********* Segment (shell edge) insertion begins here                *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  finddirection()   Find the first triangle on the path from one point     */
-/*                    to another.                                            */
-/*                                                                           */
-/*  Finds the triangle that intersects a line segment drawn from the         */
-/*  origin of `searchtri' to the point `endpoint', and returns the result    */
-/*  in `searchtri'.  The origin of `searchtri' does not change, even though  */
-/*  the triangle returned may differ from the one passed in.  This routine   */
-/*  is used to find the direction to move in to get from one point to        */
-/*  another.                                                                 */
-/*                                                                           */
-/*  The return value notes whether the destination or apex of the found      */
-/*  triangle is collinear with the two points in question.                   */
-/*                                                                           */
-/*****************************************************************************/
-
-enum mesh2d::finddirectionresult
-mesh2d::finddirection(struct triedge *searchtri, point endpoint)
-{
-  struct triedge checktri;
-  point startpoint;
-  point leftpoint, rightpoint;
-  REAL leftccw, rightccw;
-  int leftflag, rightflag;
-  triangle ptr;           /* Temporary variable used by onext() and oprev(). */
-
-  org(*searchtri, startpoint);
-  dest(*searchtri, rightpoint);
-  apex(*searchtri, leftpoint);
-  /* Is `endpoint' to the left? */
-  leftccw = counterclockwise(endpoint, startpoint, leftpoint);
-  leftflag = leftccw > 0.0;
-  /* Is `endpoint' to the right? */
-  rightccw = counterclockwise(startpoint, endpoint, rightpoint);
-  rightflag = rightccw > 0.0;
-  if (leftflag && rightflag) {
-    /* `searchtri' faces directly away from `endpoint'.  We could go */
-    /*   left or right.  Ask whether it's a triangle or a boundary   */
-    /*   on the left.                                                */
-    onext(*searchtri, checktri);
-    if (checktri.tri == dummytri) {
-      leftflag = 0;
-    } else {
-      rightflag = 0;
-    }
-  }
-  while (leftflag) {
-    /* Turn left until satisfied. */
-    onextself(*searchtri);
-    if (searchtri->tri == dummytri) {
-      printf("Internal error in finddirection():  Unable to find a\n");
-      printf("  triangle leading from (%.12g, %.12g) to", startpoint[0],
-             startpoint[1]);
-      printf("  (%.12g, %.12g).\n", endpoint[0], endpoint[1]);
-      internalerror();
-    }
-    apex(*searchtri, leftpoint);
-    rightccw = leftccw;
-    leftccw = counterclockwise(endpoint, startpoint, leftpoint);
-    leftflag = leftccw > 0.0;
-  }
-  while (rightflag) {
-    /* Turn right until satisfied. */
-    oprevself(*searchtri);
-    if (searchtri->tri == dummytri) {
-      printf("Internal error in finddirection():  Unable to find a\n");
-      printf("  triangle leading from (%.12g, %.12g) to", startpoint[0],
-             startpoint[1]);
-      printf("  (%.12g, %.12g).\n", endpoint[0], endpoint[1]);
-      internalerror();
-    }
-    dest(*searchtri, rightpoint);
-    leftccw = rightccw;
-    rightccw = counterclockwise(startpoint, endpoint, rightpoint);
-    rightflag = rightccw > 0.0;
-  }
-  if (leftccw == 0.0) {
-    return LEFTCOLLINEAR;
-  } else if (rightccw == 0.0) {
-    return RIGHTCOLLINEAR;
-  } else {
-    return WITHIN;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  segmentintersection()   Find the intersection of an existing segment     */
-/*                          and a segment that is being inserted.  Insert    */
-/*                          a point at the intersection, splitting an        */
-/*                          existing shell edge.                             */
-/*                                                                           */
-/*  The segment being inserted connects the apex of splittri to endpoint2.   */
-/*  splitshelle is the shell edge being split, and MUST be opposite          */
-/*  splittri.  Hence, the edge being split connects the origin and           */
-/*  destination of splittri.                                                 */
-/*                                                                           */
-/*  On completion, splittri is a handle having the newly inserted            */
-/*  intersection point as its origin, and endpoint1 as its destination.      */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::
-segmentintersection(struct triedge *splittri, struct edge *splitshelle,
-                    point endpoint2)
-{
-  point endpoint1;
-  point torg, tdest;
-  point leftpoint, rightpoint;
-  point newpoint;
-  enum insertsiteresult success;
-  enum finddirectionresult collinear;
-  REAL ex, ey;
-  REAL tx, ty;
-  REAL etx, ety;
-  REAL split, denom;
-  int i;
-  triangle ptr;                       /* Temporary variable used by onext(). */
-
-  /* Find the other three segment endpoints. */
-  apex(*splittri, endpoint1);
-  org(*splittri, torg);
-  dest(*splittri, tdest);
-  /* Segment intersection formulae; see the Antonio reference. */
-  tx = tdest[0] - torg[0];
-  ty = tdest[1] - torg[1];
-  ex = endpoint2[0] - endpoint1[0];
-  ey = endpoint2[1] - endpoint1[1];
-  etx = torg[0] - endpoint2[0];
-  ety = torg[1] - endpoint2[1];
-  denom = ty * ex - tx * ey;
-  if (denom == 0.0) {
-    printf("Internal error in segmentintersection():");
-    printf("  Attempt to find intersection of parallel segments.\n");
-    internalerror();
-  }
-  split = (ey * etx - ex * ety) / denom;
-  /* Create the new point. */
-  newpoint = (point) points.alloc();
-  /* Interpolate its coordinate and attributes. */
-  for (i = 0; i < 2 + nextras; i++) {
-    newpoint[i] = torg[i] + split * (tdest[i] - torg[i]);
-  }
-  setpointmark(newpoint, mark(*splitshelle));
-  if (verbose > 1) {
-    printf(
-    "  Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
-           torg[0], torg[1], tdest[0], tdest[1], newpoint[0], newpoint[1]);
-  }
-  /* Insert the intersection point.  This should always succeed. */
-  success = insertsite(newpoint, splittri, splitshelle, 0, 0);
-  if (success != SUCCESSFULPOINT) {
-    printf("Internal error in segmentintersection():\n");
-    printf("  Failure to split a segment.\n");
-    internalerror();
-  }
-  if (steinerleft > 0) {
-    steinerleft--;
-  }
-  /* Inserting the point may have caused edge flips.  We wish to rediscover */
-  /*   the edge connecting endpoint1 to the new intersection point.         */
-  collinear = finddirection(splittri, endpoint1);
-  dest(*splittri, rightpoint);
-  apex(*splittri, leftpoint);
-  if ((leftpoint[0] == endpoint1[0]) && (leftpoint[1] == endpoint1[1])) {
-    onextself(*splittri);
-  } else if ((rightpoint[0] != endpoint1[0]) ||
-             (rightpoint[1] != endpoint1[1])) {
-    printf("Internal error in segmentintersection():\n");
-    printf("  Topological inconsistency after splitting a segment.\n");
-    internalerror();
-  }
-  /* `splittri' should have destination endpoint1. */
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  scoutsegment()   Scout the first triangle on the path from one endpoint  */
-/*                   to another, and check for completion (reaching the      */
-/*                   second endpoint), a collinear point, and the            */
-/*                   intersection of two segments.                           */
-/*                                                                           */
-/*  Returns one if the entire segment is successfully inserted, and zero if  */
-/*  the job must be finished by conformingedge() or constrainededge().       */
-/*                                                                           */
-/*  If the first triangle on the path has the second endpoint as its         */
-/*  destination or apex, a shell edge is inserted and the job is done.       */
-/*                                                                           */
-/*  If the first triangle on the path has a destination or apex that lies on */
-/*  the segment, a shell edge is inserted connecting the first endpoint to   */
-/*  the collinear point, and the search is continued from the collinear      */
-/*  point.                                                                   */
-/*                                                                           */
-/*  If the first triangle on the path has a shell edge opposite its origin,  */
-/*  then there is a segment that intersects the segment being inserted.      */
-/*  Their intersection point is inserted, splitting the shell edge.          */
-/*                                                                           */
-/*  Otherwise, return zero.                                                  */
-/*                                                                           */
-/*****************************************************************************/
-
-int mesh2d::
-scoutsegment(struct triedge *searchtri, point endpoint2, int newmark)
-{
-  struct triedge crosstri;
-  struct edge crossedge;
-  point leftpoint, rightpoint;
-  point endpoint1;
-  enum finddirectionresult collinear;
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  collinear = finddirection(searchtri, endpoint2);
-  dest(*searchtri, rightpoint);
-  apex(*searchtri, leftpoint);
-  if (((leftpoint[0] == endpoint2[0]) && (leftpoint[1] == endpoint2[1])) ||
-      ((rightpoint[0] == endpoint2[0]) && (rightpoint[1] == endpoint2[1]))) {
-    /* The segment is already an edge in the mesh. */
-    if ((leftpoint[0] == endpoint2[0]) && (leftpoint[1] == endpoint2[1])) {
-      lprevself(*searchtri);
-    }
-    /* Insert a shell edge, if there isn't already one there. */
-    insertshelle(searchtri, newmark);
-    return 1;
-  } else if (collinear == LEFTCOLLINEAR) {
-    /* We've collided with a point between the segment's endpoints. */
-    /* Make the collinear point be the triangle's origin. */
-    lprevself(*searchtri);
-    insertshelle(searchtri, newmark);
-    /* Insert the remainder of the segment. */
-    return scoutsegment(searchtri, endpoint2, newmark);
-  } else if (collinear == RIGHTCOLLINEAR) {
-    /* We've collided with a point between the segment's endpoints. */
-    insertshelle(searchtri, newmark);
-    /* Make the collinear point be the triangle's origin. */
-    lnextself(*searchtri);
-    /* Insert the remainder of the segment. */
-    return scoutsegment(searchtri, endpoint2, newmark);
-  } else {
-    lnext(*searchtri, crosstri);
-    tspivot(crosstri, crossedge);
-    /* Check for a crossing segment. */
-    if (crossedge.sh == dummysh) {
-      return 0;
-    } else {
-      org(*searchtri, endpoint1);
-      /* Insert a point at the intersection. */
-      segmentintersection(&crosstri, &crossedge, endpoint2);
-      triedgecopy(crosstri, *searchtri);
-      insertshelle(searchtri, newmark);
-      /* Insert the remainder of the segment. */
-      return scoutsegment(searchtri, endpoint2, newmark);
-    }
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  conformingedge()   Force a segment into a conforming Delaunay            */
-/*                     triangulation by inserting a point at its midpoint,   */
-/*                     and recursively forcing in the two half-segments if   */
-/*                     necessary.                                            */
-/*                                                                           */
-/*  Generates a sequence of edges connecting `endpoint1' to `endpoint2'.     */
-/*  `newmark' is the boundary marker of the segment, assigned to each new    */
-/*  splitting point and shell edge.                                          */
-/*                                                                           */
-/*  Note that conformingedge() does not always maintain the conforming       */
-/*  Delaunay property.  Once inserted, segments are locked into place;       */
-/*  points inserted later (to force other segments in) may render these      */
-/*  fixed segments non-Delaunay.  The conforming Delaunay property will be   */
-/*  restored by enforcequality() by splitting encroached segments.           */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::conformingedge(point endpoint1, point endpoint2, int newmark)
-{
-  struct triedge searchtri1, searchtri2;
-  struct edge brokenshelle;
-  point newpoint;
-  point midpoint1, midpoint2;
-  enum insertsiteresult success;
-  int result1, result2;
-  int i;
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  if (verbose > 2) {
-    printf("Forcing segment into triangulation by recursive splitting:\n");
-    printf("  (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
-           endpoint2[0], endpoint2[1]);
-  }
-  /* Create a new point to insert in the middle of the segment. */
-  newpoint = (point) points.alloc();
-  /* Interpolate coordinates and attributes. */
-  for (i = 0; i < 2 + nextras; i++) {
-    newpoint[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
-  }
-  setpointmark(newpoint, newmark);
-  /* Find a boundary triangle to search from. */
-  searchtri1.tri = (triangle *) NULL;
-  /* Attempt to insert the new point. */
-  success = insertsite(newpoint, &searchtri1, (struct edge *) NULL, 0, 0);
-  if (success == DUPLICATEPOINT) {
-    if (verbose > 2) {
-      printf("  Segment intersects existing point (%.12g, %.12g).\n",
-             newpoint[0], newpoint[1]);
-    }
-    /* Use the point that's already there. */
-    pointdealloc(newpoint);
-    org(searchtri1, newpoint);
-  } else {
-    if (success == VIOLATINGPOINT) {
-      if (verbose > 2) {
-        printf("  Two segments intersect at (%.12g, %.12g).\n",
-               newpoint[0], newpoint[1]);
-      }
-      /* By fluke, we've landed right on another segment.  Split it. */
-      tspivot(searchtri1, brokenshelle);
-      success = insertsite(newpoint, &searchtri1, &brokenshelle, 0, 0);
-      if (success != SUCCESSFULPOINT) {
-        printf("Internal error in conformingedge():\n");
-        printf("  Failure to split a segment.\n");
-        internalerror();
-      }
-    }
-    /* The point has been inserted successfully. */
-    if (steinerleft > 0) {
-      steinerleft--;
-    }
-  }
-  triedgecopy(searchtri1, searchtri2);
-  result1 = scoutsegment(&searchtri1, endpoint1, newmark);
-  result2 = scoutsegment(&searchtri2, endpoint2, newmark);
-  if (!result1) {
-    /* The origin of searchtri1 may have changed if a collision with an */
-    /*   intervening vertex on the segment occurred.                    */
-    org(searchtri1, midpoint1);
-    conformingedge(midpoint1, endpoint1, newmark);
-  }
-  if (!result2) {
-    /* The origin of searchtri2 may have changed if a collision with an */
-    /*   intervening vertex on the segment occurred.                    */
-    org(searchtri2, midpoint2);
-    conformingedge(midpoint2, endpoint2, newmark);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  delaunayfixup()   Enforce the Delaunay condition at an edge, fanning out */
-/*                    recursively from an existing point.  Pay special       */
-/*                    attention to stacking inverted triangles.              */
-/*                                                                           */
-/*  This is a support routine for inserting segments into a constrained      */
-/*  Delaunay triangulation.                                                  */
-/*                                                                           */
-/*  The origin of fixuptri is treated as if it has just been inserted, and   */
-/*  the local Delaunay condition needs to be enforced.  It is only enforced  */
-/*  in one sector, however, that being the angular range defined by          */
-/*  fixuptri.                                                                */
-/*                                                                           */
-/*  This routine also needs to make decisions regarding the "stacking" of    */
-/*  triangles.  (Read the description of constrainededge() below before      */
-/*  reading on here, so you understand the algorithm.)  If the position of   */
-/*  the new point (the origin of fixuptri) indicates that the vertex before  */
-/*  it on the polygon is a reflex vertex, then "stack" the triangle by       */
-/*  doing nothing.  (fixuptri is an inverted triangle, which is how stacked  */
-/*  triangles are identified.)                                               */
-/*                                                                           */
-/*  Otherwise, check whether the vertex before that was a reflex vertex.     */
-/*  If so, perform an edge flip, thereby eliminating an inverted triangle    */
-/*  (popping it off the stack).  The edge flip may result in the creation    */
-/*  of a new inverted triangle, depending on whether or not the new vertex   */
-/*  is visible to the vertex three edges behind on the polygon.              */
-/*                                                                           */
-/*  If neither of the two vertices behind the new vertex are reflex          */
-/*  vertices, fixuptri and fartri, the triangle opposite it, are not         */
-/*  inverted; hence, ensure that the edge between them is locally Delaunay.  */
-/*                                                                           */
-/*  `leftside' indicates whether or not fixuptri is to the left of the       */
-/*  segment being inserted.  (Imagine that the segment is pointing up from   */
-/*  endpoint1 to endpoint2.)                                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::delaunayfixup(struct triedge *fixuptri, int leftside)
-{
-  struct triedge neartri;
-  struct triedge fartri;
-  struct edge faredge;
-  point nearpoint, leftpoint, rightpoint, farpoint;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  lnext(*fixuptri, neartri);
-  sym(neartri, fartri);
-  /* Check if the edge opposite the origin of fixuptri can be flipped. */
-  if (fartri.tri == dummytri) {
-    return;
-  }
-  tspivot(neartri, faredge);
-  if (faredge.sh != dummysh) {
-    return;
-  }
-  /* Find all the relevant vertices. */
-  apex(neartri, nearpoint);
-  org(neartri, leftpoint);
-  dest(neartri, rightpoint);
-  apex(fartri, farpoint);
-  /* Check whether the previous polygon vertex is a reflex vertex. */
-  if (leftside) {
-    if (counterclockwise(nearpoint, leftpoint, farpoint) <= 0.0) {
-      /* leftpoint is a reflex vertex too.  Nothing can */
-      /*   be done until a convex section is found.     */
-      return;
-    }
-  } else {
-    if (counterclockwise(farpoint, rightpoint, nearpoint) <= 0.0) {
-      /* rightpoint is a reflex vertex too.  Nothing can */
-      /*   be done until a convex section is found.      */
-      return;
-    }
-  }
-  if (counterclockwise(rightpoint, leftpoint, farpoint) > 0.0) {
-    /* fartri is not an inverted triangle, and farpoint is not a reflex */
-    /*   vertex.  As there are no reflex vertices, fixuptri isn't an    */
-    /*   inverted triangle, either.  Hence, test the edge between the   */
-    /*   triangles to ensure it is locally Delaunay.                    */
-    if (iincircle(leftpoint, farpoint, rightpoint, nearpoint) <= 0.0) {
-      return;
-    }
-    /* Not locally Delaunay; go on to an edge flip. */
-  }        /* else fartri is inverted; remove it from the stack by flipping. */
-  flip(&neartri);
-  lprevself(*fixuptri);    /* Restore the origin of fixuptri after the flip. */
-  /* Recursively process the two triangles that result from the flip. */
-  delaunayfixup(fixuptri, leftside);
-  delaunayfixup(&fartri, leftside);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  constrainededge()   Force a segment into a constrained Delaunay          */
-/*                      triangulation by deleting the triangles it           */
-/*                      intersects, and triangulating the polygons that      */
-/*                      form on each side of it.                             */
-/*                                                                           */
-/*  Generates a single edge connecting `endpoint1' to `endpoint2'.  The      */
-/*  triangle `starttri' has `endpoint1' as its origin.  `newmark' is the     */
-/*  boundary marker of the segment.                                          */
-/*                                                                           */
-/*  To insert a segment, every triangle whose interior intersects the        */
-/*  segment is deleted.  The union of these deleted triangles is a polygon   */
-/*  (which is not necessarily monotone, but is close enough), which is       */
-/*  divided into two polygons by the new segment.  This routine's task is    */
-/*  to generate the Delaunay triangulation of these two polygons.            */
-/*                                                                           */
-/*  You might think of this routine's behavior as a two-step process.  The   */
-/*  first step is to walk from endpoint1 to endpoint2, flipping each edge    */
-/*  encountered.  This step creates a fan of edges connected to endpoint1,   */
-/*  including the desired edge to endpoint2.  The second step enforces the   */
-/*  Delaunay condition on each side of the segment in an incremental manner: */
-/*  proceeding along the polygon from endpoint1 to endpoint2 (this is done   */
-/*  independently on each side of the segment), each vertex is "enforced"    */
-/*  as if it had just been inserted, but affecting only the previous         */
-/*  vertices.  The result is the same as if the vertices had been inserted   */
-/*  in the order they appear on the polygon, so the result is Delaunay.      */
-/*                                                                           */
-/*  In truth, constrainededge() interleaves these two steps.  The procedure  */
-/*  walks from endpoint1 to endpoint2, and each time an edge is encountered  */
-/*  and flipped, the newly exposed vertex (at the far end of the flipped     */
-/*  edge) is "enforced" upon the previously flipped edges, usually affecting */
-/*  only one side of the polygon (depending upon which side of the segment   */
-/*  the vertex falls on).                                                    */
-/*                                                                           */
-/*  The algorithm is complicated by the need to handle polygons that are not */
-/*  convex.  Although the polygon is not necessarily monotone, it can be     */
-/*  triangulated in a manner similar to the stack-based algorithms for       */
-/*  monotone polygons.  For each reflex vertex (local concavity) of the      */
-/*  polygon, there will be an inverted triangle formed by one of the edge    */
-/*  flips.  (An inverted triangle is one with negative area - that is, its   */
-/*  vertices are arranged in clockwise order - and is best thought of as a   */
-/*  wrinkle in the fabric of the mesh.)  Each inverted triangle can be       */
-/*  thought of as a reflex vertex pushed on the stack, waiting to be fixed   */
-/*  later.                                                                   */
-/*                                                                           */
-/*  A reflex vertex is popped from the stack when a vertex is inserted that  */
-/*  is visible to the reflex vertex.  (However, if the vertex behind the     */
-/*  reflex vertex is not visible to the reflex vertex, a new inverted        */
-/*  triangle will take its place on the stack.)  These details are handled   */
-/*  by the delaunayfixup() routine above.                                    */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::
-constrainededge(struct triedge *starttri, point endpoint2, int newmark)
-{
-  struct triedge fixuptri, fixuptri2;
-  struct edge fixupedge;
-  point endpoint1;
-  point farpoint;
-  REAL area;
-  int collision;
-  int done;
-  triangle ptr;             /* Temporary variable used by sym() and oprev(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  org(*starttri, endpoint1);
-  lnext(*starttri, fixuptri);
-  flip(&fixuptri);
-  /* `collision' indicates whether we have found a point directly */
-  /*   between endpoint1 and endpoint2.                           */
-  collision = 0;
-  done = 0;
-  do {
-    org(fixuptri, farpoint);
-    /* `farpoint' is the extreme point of the polygon we are "digging" */
-    /*   to get from endpoint1 to endpoint2.                           */
-    if ((farpoint[0] == endpoint2[0]) && (farpoint[1] == endpoint2[1])) {
-      oprev(fixuptri, fixuptri2);
-      /* Enforce the Delaunay condition around endpoint2. */
-      delaunayfixup(&fixuptri, 0);
-      delaunayfixup(&fixuptri2, 1);
-      done = 1;
-    } else {
-      /* Check whether farpoint is to the left or right of the segment */
-      /*   being inserted, to decide which edge of fixuptri to dig     */
-      /*   through next.                                               */
-      area = counterclockwise(endpoint1, endpoint2, farpoint);
-      if (area == 0.0) {
-        /* We've collided with a point between endpoint1 and endpoint2. */
-        collision = 1;
-        oprev(fixuptri, fixuptri2);
-        /* Enforce the Delaunay condition around farpoint. */
-        delaunayfixup(&fixuptri, 0);
-        delaunayfixup(&fixuptri2, 1);
-        done = 1;
-      } else {
-        if (area > 0.0) {         /* farpoint is to the left of the segment. */
-          oprev(fixuptri, fixuptri2);
-          /* Enforce the Delaunay condition around farpoint, on the */
-          /*   left side of the segment only.                       */
-          delaunayfixup(&fixuptri2, 1);
-          /* Flip the edge that crosses the segment.  After the edge is */
-          /*   flipped, one of its endpoints is the fan vertex, and the */
-          /*   destination of fixuptri is the fan vertex.               */
-          lprevself(fixuptri);
-        } else {                 /* farpoint is to the right of the segment. */
-          delaunayfixup(&fixuptri, 0);
-          /* Flip the edge that crosses the segment.  After the edge is */
-          /*   flipped, one of its endpoints is the fan vertex, and the */
-          /*   destination of fixuptri is the fan vertex.               */
-          oprevself(fixuptri);
-        }
-        /* Check for two intersecting segments. */
-        tspivot(fixuptri, fixupedge);
-        if (fixupedge.sh == dummysh) {
-          flip(&fixuptri);   /* May create an inverted triangle on the left. */
-        } else {
-          /* We've collided with a segment between endpoint1 and endpoint2. */
-          collision = 1;
-          /* Insert a point at the intersection. */
-          segmentintersection(&fixuptri, &fixupedge, endpoint2);
-          done = 1;
-        }
-      }
-    }
-  } while (!done);
-  /* Insert a shell edge to make the segment permanent. */
-  insertshelle(&fixuptri, newmark);
-  /* If there was a collision with an interceding vertex, install another */
-  /*   segment connecting that vertex with endpoint2.                     */
-  if (collision) {
-    /* Insert the remainder of the segment. */
-    if (!scoutsegment(&fixuptri, endpoint2, newmark)) {
-      constrainededge(&fixuptri, endpoint2, newmark);
-    }
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  insertsegment()   Insert a PSLG segment into a triangulation.            */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::insertsegment(point endpoint1, point endpoint2, int newmark)
-{
-  struct triedge searchtri1, searchtri2;
-  triangle encodedtri;
-  point checkpoint;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (verbose > 1) {
-    printf("  Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
-           endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
-  }
-
-  /* Find a triangle whose origin is the segment's first endpoint. */
-  checkpoint = (point) NULL;
-  encodedtri = point2tri(endpoint1);
-  if (encodedtri != (triangle) NULL) {
-    decode(encodedtri, searchtri1);
-    org(searchtri1, checkpoint);
-  }
-  if (checkpoint != endpoint1) {
-    /* Find a boundary triangle to search from. */
-    searchtri1.tri = dummytri;
-    searchtri1.orient = 0;
-    symself(searchtri1);
-    /* Search for the segment's first endpoint by point location. */
-    if (locate(endpoint1, &searchtri1) != ONVERTEX) {
-      printf(
-        "Internal error in insertsegment():  Unable to locate PSLG point\n");
-      printf("  (%.12g, %.12g) in triangulation.\n",
-             endpoint1[0], endpoint1[1]);
-      internalerror();
-    }
-  }
-  /* Remember this triangle to improve subsequent point location. */
-  triedgecopy(searchtri1, recenttri);
-  /* Scout the beginnings of a path from the first endpoint */
-  /*   toward the second.                                   */
-  if (scoutsegment(&searchtri1, endpoint2, newmark)) {
-    /* The segment was easily inserted. */
-    return;
-  }
-  /* The first endpoint may have changed if a collision with an intervening */
-  /*   vertex on the segment occurred.                                      */
-  org(searchtri1, endpoint1);
-
-  /* Find a triangle whose origin is the segment's second endpoint. */
-  checkpoint = (point) NULL;
-  encodedtri = point2tri(endpoint2);
-  if (encodedtri != (triangle) NULL) {
-    decode(encodedtri, searchtri2);
-    org(searchtri2, checkpoint);
-  }
-  if (checkpoint != endpoint2) {
-    /* Find a boundary triangle to search from. */
-    searchtri2.tri = dummytri;
-    searchtri2.orient = 0;
-    symself(searchtri2);
-    /* Search for the segment's second endpoint by point location. */
-    if (locate(endpoint2, &searchtri2) != ONVERTEX) {
-      printf(
-        "Internal error in insertsegment():  Unable to locate PSLG point\n");
-      printf("  (%.12g, %.12g) in triangulation.\n",
-             endpoint2[0], endpoint2[1]);
-      internalerror();
-    }
-  }
-  /* Remember this triangle to improve subsequent point location. */
-  triedgecopy(searchtri2, recenttri);
-  /* Scout the beginnings of a path from the second endpoint */
-  /*   toward the first.                                     */
-  if (scoutsegment(&searchtri2, endpoint1, newmark)) {
-    /* The segment was easily inserted. */
-    return;
-  }
-  /* The second endpoint may have changed if a collision with an intervening */
-  /*   vertex on the segment occurred.                                       */
-  org(searchtri2, endpoint2);
-
-  if (splitseg) {
-    /* Insert vertices to force the segment into the triangulation. */
-    conformingedge(endpoint1, endpoint2, newmark);
-  } else {
-    /* Insert the segment directly into the triangulation. */
-    constrainededge(&searchtri1, endpoint2, newmark);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  markhull()   Cover the convex hull of a triangulation with shell edges.  */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::markhull()
-{
-  struct triedge hulltri;
-  struct triedge nexttri;
-  struct triedge starttri;
-  triangle ptr;             /* Temporary variable used by sym() and oprev(). */
-
-  /* Find a triangle handle on the hull. */
-  hulltri.tri = dummytri;
-  hulltri.orient = 0;
-  symself(hulltri);
-  /* Remember where we started so we know when to stop. */
-  triedgecopy(hulltri, starttri);
-  /* Go once counterclockwise around the convex hull. */
-  do {
-    /* Create a shell edge if there isn't already one here. */
-    insertshelle(&hulltri, 1);
-    /* To find the next hull edge, go clockwise around the next vertex. */
-    lnextself(hulltri);
-    oprev(hulltri, nexttri);
-    while (nexttri.tri != dummytri) {
-      triedgecopy(nexttri, hulltri);
-      oprev(hulltri, nexttri);
-    }
-  } while (!triedgeequal(hulltri, starttri));
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  formskeleton()   Create the shell edges of a triangulation, including    */
-/*                   PSLG edges and edges on the convex hull.                */
-/*                                                                           */
-/*  The PSLG edges are read from a .poly file.  The return value is the      */
-/*  number of segments in the file.                                          */
-/*                                                                           */
-/*****************************************************************************/
-
-int mesh2d::
-formskeleton(int *segmentlist, int *segmentmarkerlist, int numberofsegments)
-{
-  char polyfilename[6];
-  int index;
-  point endpoint1, endpoint2;
-  int segments;
-  int segmentmarkers;
-  int end1, end2;
-  int boundmarker;
-  int i;
-
-  if (poly) {
-    if (!quiet) {
-      printf("Inserting segments into Delaunay triangulation.\n");
-    }
-    strcpy(polyfilename, "input");
-    segments = numberofsegments;
-    segmentmarkers = segmentmarkerlist != (int *) NULL;
-    index = 0;
-    /* If segments are to be inserted, compute a mapping */
-    /*   from points to triangles.                       */
-    if (segments > 0) {
-      if (verbose) {
-        printf("  Inserting PSLG segments.\n");
-      }
-      makepointmap();
-    }
-
-    boundmarker = 0;
-    /* Read and insert the segments. */
-    for (i = 1; i <= segments; i++) {
-      end1 = segmentlist[index++];
-      end2 = segmentlist[index++];
-      if (segmentmarkers) {
-        boundmarker = segmentmarkerlist[i - 1];
-      }
-      if ((end1 < firstnumber) || (end1 >= firstnumber + inpoints)) {
-        if (!quiet) {
-          printf("Warning:  Invalid first endpoint of segment %d in %s.\n", i,
-                 polyfilename);
-        }
-      } else if ((end2 < firstnumber) || (end2 >= firstnumber + inpoints)) {
-        if (!quiet) {
-          printf("Warning:  Invalid second endpoint of segment %d in %s.\n", i,
-                 polyfilename);
-        }
-      } else {
-        endpoint1 = getpoint(end1);
-        endpoint2 = getpoint(end2);
-        if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
-          if (!quiet) {
-            printf("Warning:  Endpoints of segment %d are coincident in %s.\n",
-                   i, polyfilename);
-          }
-        } else {
-          insertsegment(endpoint1, endpoint2, boundmarker);
-        }
-      }
-    }
-  } else {
-    segments = 0;
-  }
-  if (convex || !poly) {
-    /* Enclose the convex hull with shell edges. */
-    if (verbose) {
-      printf("  Enclosing convex hull with segments.\n");
-    }
-    markhull();
-  }
-  return segments;
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Segment (shell edge) insertion ends here                  *********/
-
-/********* Carving out holes and concavities begins here             *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  infecthull()   Virally infect all of the triangles of the convex hull    */
-/*                 that are not protected by shell edges.  Where there are   */
-/*                 shell edges, set boundary markers as appropriate.         */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::infecthull()
-{
-  struct triedge hulltri;
-  struct triedge nexttri;
-  struct triedge starttri;
-  struct edge hulledge;
-  triangle **deadtri;
-  point horg, hdest;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  if (verbose) {
-    printf("  Marking concavities (external triangles) for elimination.\n");
-  }
-  /* Find a triangle handle on the hull. */
-  hulltri.tri = dummytri;
-  hulltri.orient = 0;
-  symself(hulltri);
-  /* Remember where we started so we know when to stop. */
-  triedgecopy(hulltri, starttri);
-  /* Go once counterclockwise around the convex hull. */
-  do {
-    /* Ignore triangles that are already infected. */
-    if (!infected(hulltri)) {
-      /* Is the triangle protected by a shell edge? */
-      tspivot(hulltri, hulledge);
-      if (hulledge.sh == dummysh) {
-        /* The triangle is not protected; infect it. */
-        infect(hulltri);
-        deadtri = (triangle **) viri.alloc();
-        *deadtri = hulltri.tri;
-      } else {
-        /* The triangle is protected; set boundary markers if appropriate. */
-        if (mark(hulledge) == 0) {
-          setmark(hulledge, 1);
-          org(hulltri, horg);
-          dest(hulltri, hdest);
-          if (pointmark(horg) == 0) {
-            setpointmark(horg, 1);
-          }
-          if (pointmark(hdest) == 0) {
-            setpointmark(hdest, 1);
-          }
-        }
-      }
-    }
-    /* To find the next hull edge, go clockwise around the next vertex. */
-    lnextself(hulltri);
-    oprev(hulltri, nexttri);
-    while (nexttri.tri != dummytri) {
-      triedgecopy(nexttri, hulltri);
-      oprev(hulltri, nexttri);
-    }
-  } while (!triedgeequal(hulltri, starttri));
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  plague()   Spread the virus from all infected triangles to any neighbors */
-/*             not protected by shell edges.  Delete all infected triangles. */
-/*                                                                           */
-/*  This is the procedure that actually creates holes and concavities.       */
-/*                                                                           */
-/*  This procedure operates in two phases.  The first phase identifies all   */
-/*  the triangles that will die, and marks them as infected.  They are       */
-/*  marked to ensure that each triangle is added to the virus pool only      */
-/*  once, so the procedure will terminate.                                   */
-/*                                                                           */
-/*  The second phase actually eliminates the infected triangles.  It also    */
-/*  eliminates orphaned points.                                              */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::plague()
-{
-  struct triedge testtri;
-  struct triedge neighbor;
-  triangle **virusloop;
-  triangle **deadtri;
-  struct edge neighborshelle;
-  point testpoint;
-  point norg, ndest;
-  point deadorg, deaddest, deadapex;
-  int killorg;
-  triangle ptr;             /* Temporary variable used by sym() and onext(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  if (verbose) {
-    printf("  Marking neighbors of marked triangles.\n");
-  }
-  /* Loop through all the infected triangles, spreading the virus to */
-  /*   their neighbors, then to their neighbors' neighbors.          */
-  viri.traversalinit();
-  virusloop = (triangle **) viri.traverse();
-  while (virusloop != (triangle **) NULL) {
-    testtri.tri = *virusloop;
-    /* A triangle is marked as infected by messing with one of its shell */
-    /*   edges, setting it to an illegal value.  Hence, we have to       */
-    /*   temporarily uninfect this triangle so that we can examine its   */
-    /*   adjacent shell edges.                                           */
-    uninfect(testtri);
-    if (verbose > 2) {
-      /* Assign the triangle an orientation for convenience in */
-      /*   checking its points.                                */
-      testtri.orient = 0;
-      org(testtri, deadorg);
-      dest(testtri, deaddest);
-      apex(testtri, deadapex);
-      printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
-             deadorg[0], deadorg[1], deaddest[0], deaddest[1],
-             deadapex[0], deadapex[1]);
-    }
-    /* Check each of the triangle's three neighbors. */
-    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
-      /* Find the neighbor. */
-      sym(testtri, neighbor);
-      /* Check for a shell between the triangle and its neighbor. */
-      tspivot(testtri, neighborshelle);
-      /* Check if the neighbor is nonexistent or already infected. */
-      if ((neighbor.tri == dummytri) || infected(neighbor)) {
-        if (neighborshelle.sh != dummysh) {
-          /* There is a shell edge separating the triangle from its */
-          /*   neighbor, but both triangles are dying, so the shell */
-          /*   edge dies too.                                       */
-          shelledealloc(neighborshelle.sh);
-          if (neighbor.tri != dummytri) {
-            /* Make sure the shell edge doesn't get deallocated again */
-            /*   later when the infected neighbor is visited.         */
-            uninfect(neighbor);
-            tsdissolve(neighbor);
-            infect(neighbor);
-          }
-        }
-      } else {                   /* The neighbor exists and is not infected. */
-        if (neighborshelle.sh == dummysh) {
-          /* There is no shell edge protecting the neighbor, so */
-          /*   the neighbor becomes infected.                   */
-          if (verbose > 2) {
-            org(neighbor, deadorg);
-            dest(neighbor, deaddest);
-            apex(neighbor, deadapex);
-            printf(
-              "    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
-                   deadorg[0], deadorg[1], deaddest[0], deaddest[1],
-                   deadapex[0], deadapex[1]);
-          }
-          infect(neighbor);
-          /* Ensure that the neighbor's neighbors will be infected. */
-          deadtri = (triangle **) viri.alloc();
-          *deadtri = neighbor.tri;
-        } else {               /* The neighbor is protected by a shell edge. */
-          /* Remove this triangle from the shell edge. */
-          stdissolve(neighborshelle);
-          /* The shell edge becomes a boundary.  Set markers accordingly. */
-          if (mark(neighborshelle) == 0) {
-            setmark(neighborshelle, 1);
-          }
-          org(neighbor, norg);
-          dest(neighbor, ndest);
-          if (pointmark(norg) == 0) {
-            setpointmark(norg, 1);
-          }
-          if (pointmark(ndest) == 0) {
-            setpointmark(ndest, 1);
-          }
-        }
-      }
-    }
-    /* Remark the triangle as infected, so it doesn't get added to the */
-    /*   virus pool again.                                             */
-    infect(testtri);
-    virusloop = (triangle **) viri.traverse();
-  }
-
-  if (verbose) {
-    printf("  Deleting marked triangles.\n");
-  }
-  viri.traversalinit();
-  virusloop = (triangle **) viri.traverse();
-  while (virusloop != (triangle **) NULL) {
-    testtri.tri = *virusloop;
-
-    /* Check each of the three corners of the triangle for elimination. */
-    /*   This is done by walking around each point, checking if it is   */
-    /*   still connected to at least one live triangle.                 */
-    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
-      org(testtri, testpoint);
-      /* Check if the point has already been tested. */
-      if (testpoint != (point) NULL) {
-        killorg = 1;
-        /* Mark the corner of the triangle as having been tested. */
-        setorg(testtri, NULL);
-        /* Walk counterclockwise about the point. */
-        onext(testtri, neighbor);
-        /* Stop upon reaching a boundary or the starting triangle. */
-        while ((neighbor.tri != dummytri)
-               && (!triedgeequal(neighbor, testtri))) {
-          if (infected(neighbor)) {
-            /* Mark the corner of this triangle as having been tested. */
-            setorg(neighbor, NULL);
-          } else {
-            /* A live triangle.  The point survives. */
-            killorg = 0;
-          }
-          /* Walk counterclockwise about the point. */
-          onextself(neighbor);
-        }
-        /* If we reached a boundary, we must walk clockwise as well. */
-        if (neighbor.tri == dummytri) {
-          /* Walk clockwise about the point. */
-          oprev(testtri, neighbor);
-          /* Stop upon reaching a boundary. */
-          while (neighbor.tri != dummytri) {
-            if (infected(neighbor)) {
-            /* Mark the corner of this triangle as having been tested. */
-              setorg(neighbor, NULL);
-            } else {
-              /* A live triangle.  The point survives. */
-              killorg = 0;
-            }
-            /* Walk clockwise about the point. */
-            oprevself(neighbor);
-          }
-        }
-        if (killorg) {
-          if (verbose > 1) {
-            printf("    Deleting point (%.12g, %.12g)\n",
-                   testpoint[0], testpoint[1]);
-          }
-          pointdealloc(testpoint);
-        }
-      }
-    }
-
-    /* Record changes in the number of boundary edges, and disconnect */
-    /*   dead triangles from their neighbors.                         */
-    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
-      sym(testtri, neighbor);
-      if (neighbor.tri == dummytri) {
-        /* There is no neighboring triangle on this edge, so this edge    */
-        /*   is a boundary edge.  This triangle is being deleted, so this */
-        /*   boundary edge is deleted.                                    */
-        hullsize--;
-      } else {
-        /* Disconnect the triangle from its neighbor. */
-        dissolve(neighbor);
-        /* There is a neighboring triangle on this edge, so this edge */
-        /*   becomes a boundary edge when this triangle is deleted.   */
-        hullsize++;
-      }
-    }
-    /* Return the dead triangle to the pool of triangles. */
-    triangledealloc(testtri.tri);
-    virusloop = (triangle **) viri.traverse();
-  }
-  /* Empty the virus pool. */
-  viri.restart();
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  regionplague()   Spread regional attributes and/or area constraints      */
-/*                   (from a .poly file) throughout the mesh.                */
-/*                                                                           */
-/*  This procedure operates in two phases.  The first phase spreads an       */
-/*  attribute and/or an area constraint through a (segment-bounded) region.  */
-/*  The triangles are marked to ensure that each triangle is added to the    */
-/*  virus pool only once, so the procedure will terminate.                   */
-/*                                                                           */
-/*  The second phase uninfects all infected triangles, returning them to     */
-/*  normal.                                                                  */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::regionplague(REAL attribute, REAL area)
-{
-  struct triedge testtri;
-  struct triedge neighbor;
-  triangle **virusloop;
-  triangle **regiontri;
-  struct edge neighborshelle;
-  point regionorg, regiondest, regionapex;
-  triangle ptr;             /* Temporary variable used by sym() and onext(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  if (verbose > 1) {
-    printf("  Marking neighbors of marked triangles.\n");
-  }
-  /* Loop through all the infected triangles, spreading the attribute      */
-  /*   and/or area constraint to their neighbors, then to their neighbors' */
-  /*   neighbors.                                                          */
-  viri.traversalinit();
-  virusloop = (triangle **) viri.traverse();
-  while (virusloop != (triangle **) NULL) {
-    testtri.tri = *virusloop;
-    /* A triangle is marked as infected by messing with one of its shell */
-    /*   edges, setting it to an illegal value.  Hence, we have to       */
-    /*   temporarily uninfect this triangle so that we can examine its   */
-    /*   adjacent shell edges.                                           */
-    uninfect(testtri);
-    if (regionattrib) {
-      /* Set an attribute. */
-      setelemattribute(testtri, eextras, attribute);
-    }
-    if (vararea) {
-      /* Set an area constraint. */
-      setareabound(testtri, area);
-    }
-    if (verbose > 2) {
-      /* Assign the triangle an orientation for convenience in */
-      /*   checking its points.                                */
-      testtri.orient = 0;
-      org(testtri, regionorg);
-      dest(testtri, regiondest);
-      apex(testtri, regionapex);
-      printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
-             regionorg[0], regionorg[1], regiondest[0], regiondest[1],
-             regionapex[0], regionapex[1]);
-    }
-    /* Check each of the triangle's three neighbors. */
-    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
-      /* Find the neighbor. */
-      sym(testtri, neighbor);
-      /* Check for a shell between the triangle and its neighbor. */
-      tspivot(testtri, neighborshelle);
-      /* Make sure the neighbor exists, is not already infected, and */
-      /*   isn't protected by a shell edge.                          */
-      if ((neighbor.tri != dummytri) && !infected(neighbor)
-          && (neighborshelle.sh == dummysh)) {
-        if (verbose > 2) {
-          org(neighbor, regionorg);
-          dest(neighbor, regiondest);
-          apex(neighbor, regionapex);
-          printf("    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
-                 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
-                 regionapex[0], regionapex[1]);
-        }
-        /* Infect the neighbor. */
-        infect(neighbor);
-        /* Ensure that the neighbor's neighbors will be infected. */
-        regiontri = (triangle **) viri.alloc();
-        *regiontri = neighbor.tri;
-      }
-    }
-    /* Remark the triangle as infected, so it doesn't get added to the */
-    /*   virus pool again.                                             */
-    infect(testtri);
-    virusloop = (triangle **) viri.traverse();
-  }
-
-  /* Uninfect all triangles. */
-  if (verbose > 1) {
-    printf("  Unmarking marked triangles.\n");
-  }
-  viri.traversalinit();
-  virusloop = (triangle **) viri.traverse();
-  while (virusloop != (triangle **) NULL) {
-    testtri.tri = *virusloop;
-    uninfect(testtri);
-    virusloop = (triangle **) viri.traverse();
-  }
-  /* Empty the virus pool. */
-  viri.restart();
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  carveholes()   Find the holes and infect them.  Find the area            */
-/*                 constraints and infect them.  Infect the convex hull.     */
-/*                 Spread the infection and kill triangles.  Spread the      */
-/*                 area constraints.                                         */
-/*                                                                           */
-/*  This routine mainly calls other routines to carry out all these          */
-/*  functions.                                                               */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::
-carveholes(REAL *holelist, int holes, REAL *regionlist, int regions)
-{
-  struct triedge searchtri;
-  struct triedge triangleloop;
-  struct triedge *regiontris;
-  triangle **holetri;
-  triangle **regiontri;
-  point searchorg, searchdest;
-  enum locateresult intersect;
-  int i;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (!(quiet || (noholes && convex))) {
-    printf("Removing unwanted triangles.\n");
-    if (verbose && (holes > 0)) {
-      printf("  Marking holes for elimination.\n");
-    }
-  }
-
-  if (regions > 0) {
-    /* Allocate storage for the triangles in which region points fall. */
-    regiontris = (struct triedge *) new struct triedge[regions];
-    if (regiontris == (struct triedge *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-
-  if (((holes > 0) && !noholes) || !convex || (regions > 0)) {
-    /* Initialize a pool of viri to be used for holes, concavities, */
-    /*   regional attributes, and/or regional area constraints.     */
-    viri.init(sizeof(triangle *), VIRUSPERBLOCK, POINTER, 0);
-  }
-
-  if (!convex) {
-    /* Mark as infected any unprotected triangles on the boundary. */
-    /*   This is one way by which concavities are created.         */
-    infecthull();
-  }
-
-  if ((holes > 0) && !noholes) {
-    /* Infect each triangle in which a hole lies. */
-    for (i = 0; i < 2 * holes; i += 2) {
-      /* Ignore holes that aren't within the bounds of the mesh. */
-      if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
-          && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)) {
-        /* Start searching from some triangle on the outer boundary. */
-        searchtri.tri = dummytri;
-        searchtri.orient = 0;
-        symself(searchtri);
-        /* Ensure that the hole is to the left of this boundary edge; */
-        /*   otherwise, locate() will falsely report that the hole    */
-        /*   falls within the starting triangle.                      */
-        org(searchtri, searchorg);
-        dest(searchtri, searchdest);
-        if (counterclockwise(searchorg, searchdest, &holelist[i]) > 0.0) {
-          /* Find a triangle that contains the hole. */
-          intersect = locate(&holelist[i], &searchtri);
-          if ((intersect != OUTSIDE) && (!infected(searchtri))) {
-            /* Infect the triangle.  This is done by marking the triangle */
-            /*   as infect and including the triangle in the virus pool.  */
-            infect(searchtri);
-            holetri = (triangle **) viri.alloc();
-            *holetri = searchtri.tri;
-          }
-        }
-      }
-    }
-  }
-
-  /* Now, we have to find all the regions BEFORE we carve the holes, because */
-  /*   locate() won't work when the triangulation is no longer convex.       */
-  /*   (Incidentally, this is the reason why regional attributes and area    */
-  /*   constraints can't be used when refining a preexisting mesh, which     */
-  /*   might not be convex; they can only be used with a freshly             */
-  /*   triangulated PSLG.)                                                   */
-  if (regions > 0) {
-    /* Find the starting triangle for each region. */
-    for (i = 0; i < regions; i++) {
-      regiontris[i].tri = dummytri;
-      /* Ignore region points that aren't within the bounds of the mesh. */
-      if ((regionlist[4 * i] >= xmin) && (regionlist[4 * i] <= xmax) &&
-          (regionlist[4 * i + 1] >= ymin) && (regionlist[4 * i + 1] <= ymax)) {
-        /* Start searching from some triangle on the outer boundary. */
-        searchtri.tri = dummytri;
-        searchtri.orient = 0;
-        symself(searchtri);
-        /* Ensure that the region point is to the left of this boundary */
-        /*   edge; otherwise, locate() will falsely report that the     */
-        /*   region point falls within the starting triangle.           */
-        org(searchtri, searchorg);
-        dest(searchtri, searchdest);
-        if (counterclockwise(searchorg, searchdest, &regionlist[4 * i]) >
-            0.0) {
-          /* Find a triangle that contains the region point. */
-          intersect = locate(&regionlist[4 * i], &searchtri);
-          if ((intersect != OUTSIDE) && (!infected(searchtri))) {
-            /* Record the triangle for processing after the */
-            /*   holes have been carved.                    */
-            triedgecopy(searchtri, regiontris[i]);
-          }
-        }
-      }
-    }
-  }
-
-  if (viri.items > 0) {
-    /* Carve the holes and concavities. */
-    plague();
-  }
-  /* The virus pool should be empty now. */
-
-  if (regions > 0) {
-    if (!quiet) {
-      if (regionattrib) {
-        if (vararea) {
-          printf("Spreading regional attributes and area constraints.\n");
-        } else {
-          printf("Spreading regional attributes.\n");
-        }
-      } else { 
-        printf("Spreading regional area constraints.\n");
-      }
-    }
-    if (regionattrib && !refine) {
-      /* Assign every triangle a regional attribute of zero. */
-      triangles.traversalinit();
-      triangleloop.orient = 0;
-      triangleloop.tri = triangletraverse();
-      while (triangleloop.tri != (triangle *) NULL) {
-        setelemattribute(triangleloop, eextras, 0.0);
-        triangleloop.tri = triangletraverse();
-      }
-    }
-    for (i = 0; i < regions; i++) {
-      if (regiontris[i].tri != dummytri) {
-        /* Make sure the triangle under consideration still exists. */
-        /*   It may have been eaten by the virus.                   */
-        if (regiontris[i].tri[3] != (triangle) NULL) {
-          /* Put one triangle in the virus pool. */
-          infect(regiontris[i]);
-          regiontri = (triangle **) viri.alloc();
-          *regiontri = regiontris[i].tri;
-          /* Apply one region's attribute and/or area constraint. */
-          regionplague(regionlist[4 * i + 2], regionlist[4 * i + 3]);
-          /* The virus pool should be empty now. */
-        }
-      }
-    }
-    if (regionattrib && !refine) {
-      /* Note the fact that each triangle has an additional attribute. */
-      eextras++;
-    }
-  }
-
-  /* Free up memory. */
-  if (((holes > 0) && !noholes) || !convex || (regions > 0)) {
-    viri.deinit();
-  }
-  if (regions > 0) {
-    delete [] regiontris;
-  }
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Carving out holes and concavities ends here               *********/
-
-/********* I/O routines begin here                                   *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  transfernodes()   Read the points from memory.                           */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::transfernodes(REAL *pointlist, REAL *pointattriblist,
-                           int *pointmarkerlist, int numberofpoints,
-                           int numberofpointattribs)
-{
-  point pointloop;
-  REAL x, y;
-  int i, j;
-  int coordindex;
-  int attribindex;
-
-  inpoints = numberofpoints;
-  mesh_dim = 2;
-  nextras = numberofpointattribs;
-  readnodefile = 0;
-  if (inpoints < 3) {
-    printf("Error:  Input must have at least three input points.\n");
-    exit(1);
-  }
-
-  if (!restartsymbol) {
-    initializepointpool();
-  }
-
-  /* Read the points. */
-  coordindex = 0;
-  attribindex = 0;
-  for (i = 0; i < inpoints; i++) {
-    pointloop = (point) points.alloc();
-    /* Read the point coordinates. */
-    x = pointloop[0] = pointlist[coordindex++];
-    y = pointloop[1] = pointlist[coordindex++];
-    /* Read the point attributes. */
-    for (j = 0; j < numberofpointattribs; j++) {
-      pointloop[2 + j] = pointattriblist[attribindex++];
-    }
-    if (pointmarkerlist != (int *) NULL) {
-      /* Read a point marker. */
-      setpointmark(pointloop, pointmarkerlist[i]);
-    } else {
-      /* If no markers are specified, they default to zero. */
-      setpointmark(pointloop, 0);
-    }
-    x = pointloop[0];
-    y = pointloop[1];
-    /* Determine the smallest and largest x and y coordinates. */
-    if (i == 0) {
-      xmin = xmax = x;
-      ymin = ymax = y;
-    } else {
-      xmin = (x < xmin) ? x : xmin;
-      xmax = (x > xmax) ? x : xmax;
-      ymin = (y < ymin) ? y : ymin;
-      ymax = (y > ymax) ? y : ymax;
-    }
-  }
-
-  /* Nonexistent x value used as a flag to mark circle events in sweepline */
-  /*   Delaunay algorithm.                                                 */
-  xminextreme = 10 * xmin - 9 * xmax;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  writenodes()   Number the points and write them to a .node file.         */
-/*                                                                           */
-/*  To save memory, the point numbers are written over the shell markers     */
-/*  after the points are written to a file.                                  */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::
-writenodes(REAL **pointlist, REAL **pointattriblist, int **pointmarkerlist)
-{
-  REAL *plist;
-  REAL *palist;
-  int *pmlist;
-  int coordindex;
-  int attribindex;
-  point pointloop;
-  int pointnumber;
-  int i;
-
-  if (!quiet) {
-    printf("Writing points.\n");
-  }
-  /* Allocate memory for output points if necessary. */
-  if (*pointlist == (REAL *) NULL) {
-    *pointlist = (REAL *) new REAL[points.items * 2];
-    if (*pointlist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  /* Allocate memory for output point attributes if necessary. */
-  if ((nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
-    *pointattriblist = (REAL *) new REAL[points.items * nextras];
-    if (*pointattriblist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  /* Allocate memory for output point markers if necessary. */
-  if (!nobound && (*pointmarkerlist == (int *) NULL)) {
-    *pointmarkerlist = (int *) new int[points.items];
-    if (*pointmarkerlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  plist = *pointlist;
-  palist = *pointattriblist;
-  pmlist = *pointmarkerlist;
-  coordindex = 0;
-  attribindex = 0;
-
-  points.traversalinit();
-  pointloop = pointtraverse();
-  pointnumber = firstnumber;
-  while (pointloop != (point) NULL) {
-    /* X and y coordinates. */
-    plist[coordindex++] = pointloop[0];
-    plist[coordindex++] = pointloop[1];
-    /* Point attributes. */
-    for (i = 0; i < nextras; i++) {
-      palist[attribindex++] = pointloop[2 + i];
-    }
-    if (!nobound) {
-      /* Copy the boundary marker. */
-      pmlist[pointnumber - firstnumber] = pointmark(pointloop);
-    }
-
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  numbernodes()   Number the points.                                       */
-/*                                                                           */
-/*  Each point is assigned a marker equal to its number.                     */
-/*                                                                           */
-/*  Used when writenodes() is not called because no .node file is written.   */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::numbernodes()
-{
-  point pointloop;
-  int pointnumber;
-
-  points.traversalinit();
-  pointloop = pointtraverse();
-  pointnumber = firstnumber;
-  while (pointloop != (point) NULL) {
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  writeelements()   Write the triangles to an .ele file.                   */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::writeelements(int **trianglelist, REAL **triangleattriblist)
-{
-  int *tlist;
-  REAL *talist;
-  int pointindex;
-  int attribindex;
-  struct triedge triangleloop;
-  point p1, p2, p3;
-  point mid1, mid2, mid3;
-  int elementnumber;
-  int i;
-
-  if (!quiet) {
-    printf("Writing triangles.\n");
-  }
-  /* Allocate memory for output triangles if necessary. */
-  if (*trianglelist == (int *) NULL) {
-    *trianglelist = (int *) new int[triangles.items *
-                               ((order + 1) * (order + 2) / 2)];
-    if (*trianglelist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  /* Allocate memory for output triangle attributes if necessary. */
-  if ((eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
-    *triangleattriblist = (REAL *) new REAL[triangles.items * eextras];
-    if (*triangleattriblist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  tlist = *trianglelist;
-  talist = *triangleattriblist;
-  pointindex = 0;
-  attribindex = 0;
-
-  triangles.traversalinit();
-  triangleloop.tri = triangletraverse();
-  triangleloop.orient = 0;
-  elementnumber = firstnumber;
-  while (triangleloop.tri != (triangle *) NULL) {
-    org(triangleloop, p1);
-    dest(triangleloop, p2);
-    apex(triangleloop, p3);
-    if (order == 1) {
-      tlist[pointindex++] = pointmark(p1);
-      tlist[pointindex++] = pointmark(p2);
-      tlist[pointindex++] = pointmark(p3);
-    } else {
-      mid1 = (point) triangleloop.tri[highorderindex + 1];
-      mid2 = (point) triangleloop.tri[highorderindex + 2];
-      mid3 = (point) triangleloop.tri[highorderindex];
-      tlist[pointindex++] = pointmark(p1);
-      tlist[pointindex++] = pointmark(p2);
-      tlist[pointindex++] = pointmark(p3);
-      tlist[pointindex++] = pointmark(mid1);
-      tlist[pointindex++] = pointmark(mid2);
-      tlist[pointindex++] = pointmark(mid3);
-    }
-
-    for (i = 0; i < eextras; i++) {
-      talist[attribindex++] = elemattribute(triangleloop, i);
-    }
-
-    triangleloop.tri = triangletraverse();
-    elementnumber++;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  writepoly()   Write the segments and holes to a .poly file.              */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::writepoly(int **segmentlist, int **segmentmarkerlist)
-{
-  int *slist;
-  int *smlist;
-  int index;
-  struct edge shelleloop;
-  point endpoint1, endpoint2;
-  int shellenumber;
-
-  if (!quiet) {
-    printf("Writing segments.\n");
-  }
-  /* Allocate memory for output segments if necessary. */
-  if (*segmentlist == (int *) NULL) {
-    *segmentlist = (int *) new int[shelles.items * 2];
-    if (*segmentlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  /* Allocate memory for output segment markers if necessary. */
-  if (!nobound && (*segmentmarkerlist == (int *) NULL)) {
-    *segmentmarkerlist = (int *) new int[shelles.items];
-    if (*segmentmarkerlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  slist = *segmentlist;
-  smlist = *segmentmarkerlist;
-  index = 0;
-
-  shelles.traversalinit();
-  shelleloop.sh = shelletraverse();
-  shelleloop.shorient = 0;
-  shellenumber = firstnumber;
-  while (shelleloop.sh != (shelle *) NULL) {
-    sorg(shelleloop, endpoint1);
-    sdest(shelleloop, endpoint2);
-    /* Copy indices of the segment's two endpoints. */
-    slist[index++] = pointmark(endpoint1);
-    slist[index++] = pointmark(endpoint2);
-    if (!nobound) {
-      /* Copy the boundary marker. */
-      smlist[shellenumber - firstnumber] = mark(shelleloop);
-    }
-
-    shelleloop.sh = shelletraverse();
-    shellenumber++;
-  }
-}
-
-void mesh2d::writeedges(int **edgelist, int **edgemarkerlist)
-{
-  int *elist;
-  int *emlist;
-  int index;
-  struct triedge triangleloop, trisym;
-  struct edge checkmark;
-  point p1, p2;
-  int edgenumber;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  if (!quiet) {
-    printf("Writing edges.\n");
-  }
-  /* Allocate memory for edges if necessary. */
-  if (*edgelist == (int *) NULL) {
-    *edgelist = (int *) new int[edges * 2];
-    if (*edgelist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  /* Allocate memory for edge markers if necessary. */
-  if (!nobound && (*edgemarkerlist == (int *) NULL)) {
-    *edgemarkerlist = (int *) new int[edges];
-    if (*edgemarkerlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  elist = *edgelist;
-  emlist = *edgemarkerlist;
-  index = 0;
-
-  triangles.traversalinit();
-  triangleloop.tri = triangletraverse();
-  edgenumber = firstnumber;
-  /* To loop over the set of edges, loop over all triangles, and look at   */
-  /*   the three edges of each triangle.  If there isn't another triangle  */
-  /*   adjacent to the edge, operate on the edge.  If there is another     */
-  /*   adjacent triangle, operate on the edge only if the current triangle */
-  /*   has a smaller pointer than its neighbor.  This way, each edge is    */
-  /*   considered only once.                                               */
-  while (triangleloop.tri != (triangle *) NULL) {
-    for (triangleloop.orient = 0; triangleloop.orient < 3;
-         triangleloop.orient++) {
-      sym(triangleloop, trisym);
-      if ((triangleloop.tri < trisym.tri) || (trisym.tri == dummytri)) {
-        org(triangleloop, p1);
-        dest(triangleloop, p2);
-        elist[index++] = pointmark(p1);
-        elist[index++] = pointmark(p2);
-        if (nobound) {
-        } else {
-          /* Edge number, indices of two endpoints, and a boundary marker. */
-          /*   If there's no shell edge, the boundary marker is zero.      */
-          if (useshelles) {
-            tspivot(triangleloop, checkmark);
-            if (checkmark.sh == dummysh) {
-              emlist[edgenumber - firstnumber] = 0;
-            } else {
-              emlist[edgenumber - firstnumber] = mark(checkmark);
-            }
-          } else {
-            emlist[edgenumber - firstnumber] = trisym.tri == dummytri;
-          }
-        }
-        edgenumber++;
-      }
-    }
-    triangleloop.tri = triangletraverse();
-  }
-}
-
-void mesh2d::writeneighbors(int **neighborlist)
-{
-  int *nlist;
-  int index;
-  struct triedge triangleloop, trisym;
-  int elementnumber;
-  int neighbor1, neighbor2, neighbor3;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (!quiet) {
-    printf("Writing neighbors.\n");
-  }
-  /* Allocate memory for neighbors if necessary. */
-  if (*neighborlist == (int *) NULL) {
-    *neighborlist = (int *) new int[triangles.items * 3];
-    if (*neighborlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  nlist = *neighborlist;
-  index = 0;
-
-  triangles.traversalinit();
-  triangleloop.tri = triangletraverse();
-  triangleloop.orient = 0;
-  elementnumber = firstnumber;
-  while (triangleloop.tri != (triangle *) NULL) {
-    * (int *) (triangleloop.tri + 6) = elementnumber;
-    triangleloop.tri = triangletraverse();
-    elementnumber++;
-  }
-  * (int *) (dummytri + 6) = -1;
-
-  triangles.traversalinit();
-  triangleloop.tri = triangletraverse();
-  elementnumber = firstnumber;
-  while (triangleloop.tri != (triangle *) NULL) {
-    triangleloop.orient = 1;
-    sym(triangleloop, trisym);
-    neighbor1 = * (int *) (trisym.tri + 6);
-    triangleloop.orient = 2;
-    sym(triangleloop, trisym);
-    neighbor2 = * (int *) (trisym.tri + 6);
-    triangleloop.orient = 0;
-    sym(triangleloop, trisym);
-    neighbor3 = * (int *) (trisym.tri + 6);
-    nlist[index++] = neighbor1;
-    nlist[index++] = neighbor2;
-    nlist[index++] = neighbor3;
-
-    triangleloop.tri = triangletraverse();
-    elementnumber++;
-  }
-}
-
-void mesh2d::writegid(int trilibrary)
-{
-  FILE *outfile;
-  point pointloop;
-  char gidfilename[FILENAMESIZE];
-  int pointnumber;
-  int i;
-
-  if (trilibrary) {
-    sprintf(gidfilename, "tmpmesh.gid");
-  }
-
-  if (!quiet) {
-    printf("Writing %s.\n", gidfilename);
-  }
-  outfile = fopen(gidfilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("  Error:  Cannot create file %s.\n", gidfilename);
-    return;
-  }
-
-  fprintf(outfile, "mesh dimension = 2 elemtype triangle nnode = 3\n");
-  fprintf(outfile, "coordinates\n");
-
-  points.traversalinit();
-  pointloop = pointtraverse();
-  pointnumber = firstnumber;
-  while (pointloop != (point) NULL) {
-    // Point number, x and y coordinates.
-    if (firstnumber == 0) {
-      // Gid need start index from one.
-      fprintf(outfile, "%4d    %.17g  %.17g", pointnumber + 1, pointloop[0],
-              pointloop[1]);
-    } else {
-      fprintf(outfile, "%4d    %.17g  %.17g", pointnumber, pointloop[0],
-              pointloop[1]);
-    }
-    for (i = 0; i < nextras; i++) {
-      // Write an attribute.
-      fprintf(outfile, "  %.17g", pointloop[i + 2]);
-    }
-    fprintf(outfile, "\n");
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-
-  fprintf(outfile, "end coordinates\n");
-
-  struct triedge triangleloop;
-  point p1, p2, p3;
-  int elementnumber;
-
-  fprintf(outfile, "elements\n");
-
-  triangles.traversalinit();
-  triangleloop.tri = triangletraverse();
-  triangleloop.orient = 0;
-  elementnumber = 1;
-  while (triangleloop.tri != (triangle *) NULL) {
-    org(triangleloop, p1);
-    dest(triangleloop, p2);
-    apex(triangleloop, p3);
-    // Triangle number, indices for three points.
-    if (firstnumber == 0) {
-      // Gid need start index from one.
-      fprintf(outfile, "%4d    %4d  %4d  %4d", elementnumber,
-              pointmark(p1)+1, pointmark(p2)+1, pointmark(p3)+1);
-    } else {
-      fprintf(outfile, "%4d    %4d  %4d  %4d", elementnumber,
-              pointmark(p1), pointmark(p2), pointmark(p3));
-    }
-
-    for (i = 0; i < eextras; i++) {
-      fprintf(outfile, "  %.17g", elemattribute(triangleloop, i));
-    }
-    fprintf(outfile, "\n");
-
-    triangleloop.tri = triangletraverse();
-    elementnumber++;
-  }
-
-  fprintf(outfile, "end elements\n");
-  fclose(outfile);
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* I/O routines end here                                     *********/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  main() or triangulate()   Gosh, do everything.                           */
-/*                                                                           */
-/*  The sequence is roughly as follows.  Many of these steps can be skipped, */
-/*  depending on the command line switches.                                  */
-/*                                                                           */
-/*  - Initialize constants and parse the command line.                       */
-/*  - Read the points from a file and either                                 */
-/*    - triangulate them (no -r), or                                         */
-/*    - read an old mesh from files and reconstruct it (-r).                 */
-/*  - Insert the PSLG segments (-p), and possibly segments on the convex     */
-/*      hull (-c).                                                           */
-/*  - Read the holes (-p), regional attributes (-pA), and regional area      */
-/*      constraints (-pa).  Carve the holes and concavities, and spread the  */
-/*      regional attributes and area constraints.                            */
-/*  - Enforce the constraints on minimum angle (-q) and maximum area (-a).   */
-/*      Also enforce the conforming Delaunay property (-q and -a).           */
-/*  - Compute the number of edges in the resulting mesh.                     */
-/*  - Promote the mesh's linear triangles to higher order elements (-o).     */
-/*  - Write the output files and print the statistics.                       */
-/*  - Check the consistency and Delaunay property of the mesh (-C).          */
-/*                                                                           */
-/*****************************************************************************/
-
-void mesh2d::triangulate(struct triangulateio *in, struct triangulateio *out,
-                         struct triangulateio *vorout)
-{
-  REAL *holearray;                                        /* Array of holes. */
-  REAL *regionarray;   /* Array of regional attributes and area constraints. */
-
-  transfernodes(in->pointlist, in->pointattributelist, in->pointmarkerlist,
-                in->numberofpoints, in->numberofpointattributes);
-
-  hullsize = delaunay();                        /* Triangulate the points. */
-
-  /* Ensure that no point can be mistaken for a triangular bounding */
-  /*   box point in insertsite().                                   */
-  infpoint1 = (point) NULL;
-  infpoint2 = (point) NULL;
-  infpoint3 = (point) NULL;
-
-  if (useshelles) {
-    checksegments = 1;                  /* Segments will be introduced next. */
-    if (!refine) {
-      /* Insert PSLG segments and/or convex hull segments. */
-      insegments = formskeleton(in->segmentlist, in->segmentmarkerlist,
-                                in->numberofsegments);
-    }
-  }
-
-  if (poly) {
-    holearray = in->holelist;
-    holes = in->numberofholes;
-    regionarray = in->regionlist;
-    regions = in->numberofregions;
-    if (!refine) {
-      /* Carve out holes and concavities. */
-      carveholes(holearray, holes, regionarray, regions);
-    }
-  } else {
-    /* Without a PSLG, there can be no holes or regional attributes   */
-    /*   or area constraints.  The following are set to zero to avoid */
-    /*   an accidental free() later.                                  */
-    holes = 0;
-    regions = 0;
-  }
-
-  /* Compute the number of edges. */
-  edges = (3l * triangles.items + hullsize) / 2l;
-
-  if (!quiet) {
-    printf("\n");
-  }
-
-  if (out) {
-    out->numberofpoints = points.items;
-    out->numberofpointattributes = nextras;
-    out->numberoftriangles = triangles.items;
-    out->numberofcorners = (order + 1) * (order + 2) / 2;
-    out->numberoftriangleattributes = eextras;
-    out->numberofedges = edges;
-    if (useshelles) {
-      out->numberofsegments = shelles.items;
-    } else {
-      out->numberofsegments = hullsize;
-    }
-  }
-  if (vorout != (struct triangulateio *) NULL) {
-    vorout->numberofpoints = triangles.items;
-    vorout->numberofpointattributes = nextras;
-    vorout->numberofedges = edges;
-  }
-  if (out) {
-    /* If not using iteration numbers, don't write a .node file if one was */
-    /*   read, because the original one would be overwritten!              */
-    if (nonodewritten || (noiterationnum && readnodefile)) {
-      if (!quiet) {
-        printf("NOT writing points.\n");
-      }
-      numbernodes();             /* We must remember to number the points. */
-    } else {
-      writenodes(&out->pointlist, &out->pointattributelist,
-                 &out->pointmarkerlist);
-    }
-    if (noelewritten) {
-      if (!quiet) {
-        printf("NOT writing triangles.\n");
-      }
-    } else {
-      writeelements(&out->trianglelist, &out->triangleattributelist);
-    }
-    /* The -c switch (convex switch) causes a PSLG to be written */
-    /*   even if none was read.                                  */
-    if (poly || convex) {
-      /* If not using iteration numbers, don't overwrite the .poly file. */
-      if (nopolywritten || noiterationnum) {
-        if (!quiet) {
-          printf("NOT writing segments.\n");
-        }
-      } else {
-        writepoly(&out->segmentlist, &out->segmentmarkerlist);
-        out->numberofholes = holes;
-        out->numberofregions = regions;
-        if (poly) {
-          if (holes > 0) {
-            out->holelist = new REAL[holes * 2];
-            memcpy(out->holelist, in->holelist, holes * 2* sizeof(REAL));
-          }
-		      if (regions > 0) {
-		        out->regionlist = new REAL[regions * 4];
-		        memcpy(out->regionlist, in->regionlist, regions * 4 * sizeof(REAL));
-		      }
-        } else {
-          out->holelist = (REAL *) NULL;
-          out->regionlist = (REAL *) NULL;
-        }
-      }
-    }
-    if (edgesout) {
-      writeedges(&out->edgelist, &out->edgemarkerlist);
-    }
-    if (neighbors) {
-      writeneighbors(&out->neighborlist);
-    }
-  }
-  if (geomview) {
-    writegid(1);
-  }
-}
diff --git a/Tetgen/trilib.h b/Tetgen/trilib.h
deleted file mode 100644
index f873e4c155..0000000000
--- a/Tetgen/trilib.h
+++ /dev/null
@@ -1,515 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// trilib.h    Declaration class mesh2d for two-dimensional mesh generator.  //
-//                                                                           //
-// Tetgen Version 1.0 beta                                                   //
-// July, 2001                                                                //
-//                                                                           //
-// Si hang                                                                   //
-// Email: sihang@weboo.com                                                   //
-// http://www.weboo.com/sh/tetgen.htm                                        //
-//                                                                           //
-// You are free to use, copy and modify the sources under certain            //
-// circumstances, provided this copyright notice remains intact.             //
-// See the file LICENSE for details.                                         //
-//                                                                           //
-// This file with it's couple file trilib.cpp are modified version of the    //
-// triangle program of Jonathan Richard Shewchuk, which is public available  //
-// from the following Web page with its license(see below):                  //
-//                                                                           //
-//             http://www.cs.cmu.edu/~quake/triangle.html                    //
-//                                                                           //
-// In Tetgen, there frequently need to generate a constrained Delaunay       //
-// triangulation of a given facet. For example, in facet recovery stage, for //
-// each facet, it is necessary maintain a two-dimensional Delaunay triangul- //
-// ation of its vertices, independent from the tetrahedralization in which   //
-// we hope its subfaces will eventually appear. For each triangular subface  //
-// in a facet triangulation, look for a matching face in the tetrahedraliza- //
-// tion.                                                                     //
-//                                                                           //
-// For this purpose, I embeded an object of two-dimensional Delaunay triang- //
-// ulator as member variable of class mesh3d(declared in tetlib.h). The type //
-// (class mesh2d) of this object is declared in this file, it encapsulates   //
-// most of the variables and functions of triangle program.                  //
-//                                                                           //
-// The usage of class mesh2d is very simple. To call mesh2d in functions,    //
-// use the triangulateio structure(defined below). You only write following  //
-// lines in functions:                                                       //
-//                                                                           //
-//      mesh2d mymesh;                                                       //
-//      struct triangulateio in, out;                                        //
-//      char switches[] = "pznQXPN";  // Commandline switches.               //
-//                                                                           //
-//      // Initialize 'in' and 'out'                                         //
-//      triangulateioinit(&in);                                              //
-//      triangulateioinit(&out);                                             //
-//                                                                           //
-//      // Set input PSLG data to 'in'                                       //
-//      ...                                                                  //
-//                                                                           //
-//      // Do mesh, the corresponding result will store in 'out'             //
-//      mymesh(switches, &in, &out, NULL);                                   //
-//                                                                           //
-//      ...                                                                  //
-//                                                                           //
-//      // Before return, don't forget to free 'in' and 'out'                //
-//      triangulateiodeinit(&in);                                            //
-//      triangulateiodeinit(&out);                                           //
-//                                                                           //
-// Please see the above Web page to get more detail descripton of command    //
-// line switches.                                                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-/*****************************************************************************/
-/*                                                                           */
-/*  Traingle program license:                                                */
-/*                                                                           */
-/*  Triangle                                                                 */
-/*  A Two-Dimensional Quality Mesh Generator                                 */
-/*  and Delaunay Triangulator.                                               */
-/*  Version 1.3                                                              */
-/*                                                                           */
-/*  Copyright 1996                                                           */
-/*  Jonathan Richard Shewchuk                                                */
-/*  School of Computer Science                                               */
-/*  Carnegie Mellon University                                               */
-/*  5000 Forbes Avenue                                                       */
-/*  Pittsburgh, Pennsylvania  15213-3891                                     */
-/*  jrs@cs.cmu.edu                                                           */
-/*                                                                           */
-/*  This program may be freely redistributed under the condition that the    */
-/*    copyright notices (including this entire header and the copyright      */
-/*    notice printed when the `-h' switch is selected) are not removed, and  */
-/*    no compensation is received.  Private, research, and institutional     */
-/*    use is free.  You may distribute modified versions of this code UNDER  */
-/*    THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE   */
-/*    SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE   */
-/*    AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR    */
-/*    NOTICE IS GIVEN OF THE MODIFICATIONS.  Distribution of this code as    */
-/*    part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT  */
-/*    WITH THE AUTHOR.  (If you are not directly supplying this code to a    */
-/*    customer, and you are instead telling them how they can obtain it for  */
-/*    free, then you are not required to make any arrangement with me.)      */
-/*                                                                           */
-/*  Disclaimer:  Neither I nor Carnegie Mellon warrant this code in any way  */
-/*    whatsoever.  This code is provided "as-is".  Use at your own risk.     */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef trilibH
-#define trilibH
-
-#include "defines.h"
-#include "linklist.h"
-
-/*****************************************************************************/
-/*                                                                           */
-/*  The `triangulateio' structure.                                           */
-/*                                                                           */
-/*  Used to pass data into and out of the triangulate() procedure.           */
-/*                                                                           */
-/*                                                                           */
-/*  Arrays are used to store points, triangles, markers, and so forth.  In   */
-/*  all cases, the first item in any array is stored starting at index [0].  */
-/*  However, that item is item number `1' unless the `z' switch is used, in  */
-/*  which case it is item number `0'.  Hence, you may find it easier to      */
-/*  index points (and triangles in the neighbor list) if you use the `z'     */
-/*  switch.  Unless, of course, you're calling Triangle from a Fortran       */
-/*  program.                                                                 */
-/*                                                                           */
-/*  Description of fields (except the `numberof' fields, which are obvious): */
-/*                                                                           */
-/*  `pointlist':  An array of point coordinates.  The first point's x        */
-/*    coordinate is at index [0] and its y coordinate at index [1], followed */
-/*    by the coordinates of the remaining points.  Each point occupies two   */
-/*    REALs.                                                                 */
-/*  `pointattributelist':  An array of point attributes.  Each point's       */
-/*    attributes occupy `numberofpointattributes' REALs.                     */
-/*  `pointmarkerlist':  An array of point markers; one int per point.        */
-/*                                                                           */
-/*  `trianglelist':  An array of triangle corners.  The first triangle's     */
-/*    first corner is at index [0], followed by its other two corners in     */
-/*    counterclockwise order, followed by any other nodes if the triangle    */
-/*    represents a nonlinear element.  Each triangle occupies                */
-/*    `numberofcorners' ints.                                                */
-/*  `triangleattributelist':  An array of triangle attributes.  Each         */
-/*    triangle's attributes occupy `numberoftriangleattributes' REALs.       */
-/*  `trianglearealist':  An array of triangle area constraints; one REAL per */
-/*    triangle.  Input only.                                                 */
-/*  `neighborlist':  An array of triangle neighbors; three ints per          */
-/*    triangle.  Output only.                                                */
-/*                                                                           */
-/*  `segmentlist':  An array of segment endpoints.  The first segment's      */
-/*    endpoints are at indices [0] and [1], followed by the remaining        */
-/*    segments.  Two ints per segment.                                       */
-/*  `segmentmarkerlist':  An array of segment markers; one int per segment.  */
-/*                                                                           */
-/*  `holelist':  An array of holes.  The first hole's x and y coordinates    */
-/*    are at indices [0] and [1], followed by the remaining holes.  Two      */
-/*    REALs per hole.  Input only, although the pointer is copied to the     */
-/*    output structure for your convenience.                                 */
-/*                                                                           */
-/*  `regionlist':  An array of regional attributes and area constraints.     */
-/*    The first constraint's x and y coordinates are at indices [0] and [1], */
-/*    followed by the regional attribute and index [2], followed by the      */
-/*    maximum area at index [3], followed by the remaining area constraints. */
-/*    Four REALs per area constraint.  Note that each regional attribute is  */
-/*    used only if you select the `A' switch, and each area constraint is    */
-/*    used only if you select the `a' switch (with no number following), but */
-/*    omitting one of these switches does not change the memory layout.      */
-/*    Input only, although the pointer is copied to the output structure for */
-/*    your convenience.                                                      */
-/*                                                                           */
-/*  `edgelist':  An array of edge endpoints.  The first edge's endpoints are */
-/*    at indices [0] and [1], followed by the remaining edges.  Two ints per */
-/*    edge.  Output only.                                                    */
-/*  `edgemarkerlist':  An array of edge markers; one int per edge.  Output   */
-/*    only.                                                                  */
-/*  `normlist':  An array of normal vectors, used for infinite rays in       */
-/*    Voronoi diagrams.  The first normal vector's x and y magnitudes are    */
-/*    at indices [0] and [1], followed by the remaining vectors.  For each   */
-/*    finite edge in a Voronoi diagram, the normal vector written is the     */
-/*    zero vector.  Two REALs per edge.  Output only.                        */
-/*                                                                           */
-/*                                                                           */
-/*  Any input fields that Triangle will examine must be initialized.         */
-/*  Furthermore, for each output array that Triangle will write to, you      */
-/*  must either provide space by setting the appropriate pointer to point    */
-/*  to the space you want the data written to, or you must initialize the    */
-/*  pointer to NULL, which tells Triangle to allocate space for the results. */
-/*  The latter option is preferable, because Triangle always knows exactly   */
-/*  how much space to allocate.  The former option is provided mainly for    */
-/*  people who need to call Triangle from Fortran code, though it also makes */
-/*  possible some nasty space-saving tricks, like writing the output to the  */
-/*  same arrays as the input.                                                */
-/*                                                                           */
-/*  Triangle will not free() any input or output arrays, including those it  */
-/*  allocates itself; that's up to you.                                      */
-/*                                                                           */
-/*  Here's a guide to help you decide which fields you must initialize       */
-/*  before you call triangulate().                                           */
-/*                                                                           */
-/*  `in':                                                                    */
-/*                                                                           */
-/*    - `pointlist' must always point to a list of points; `numberofpoints'  */
-/*      and `numberofpointattributes' must be properly set.                  */
-/*      `pointmarkerlist' must either be set to NULL (in which case all      */
-/*      markers default to zero), or must point to a list of markers.  If    */
-/*      `numberofpointattributes' is not zero, `pointattributelist' must     */
-/*      point to a list of point attributes.                                 */
-/*    - If the `r' switch is used, `trianglelist' must point to a list of    */
-/*      triangles, and `numberoftriangles', `numberofcorners', and           */
-/*      `numberoftriangleattributes' must be properly set.  If               */
-/*      `numberoftriangleattributes' is not zero, `triangleattributelist'    */
-/*      must point to a list of triangle attributes.  If the `a' switch is   */
-/*      used (with no number following), `trianglearealist' must point to a  */
-/*      list of triangle area constraints.  `neighborlist' may be ignored.   */
-/*    - If the `p' switch is used, `segmentlist' must point to a list of     */
-/*      segments, `numberofsegments' must be properly set, and               */
-/*      `segmentmarkerlist' must either be set to NULL (in which case all    */
-/*      markers default to zero), or must point to a list of markers.        */
-/*    - If the `p' switch is used without the `r' switch, then               */
-/*      `numberofholes' and `numberofregions' must be properly set.  If      */
-/*      `numberofholes' is not zero, `holelist' must point to a list of      */
-/*      holes.  If `numberofregions' is not zero, `regionlist' must point to */
-/*      a list of region constraints.                                        */
-/*    - If the `p' switch is used, `holelist', `numberofholes',              */
-/*      `regionlist', and `numberofregions' is copied to `out'.  (You can    */
-/*      nonetheless get away with not initializing them if the `r' switch is */
-/*      used.)                                                               */
-/*    - `edgelist', `edgemarkerlist', `normlist', and `numberofedges' may be */
-/*      ignored.                                                             */
-/*                                                                           */
-/*  `out':                                                                   */
-/*                                                                           */
-/*    - `pointlist' must be initialized (NULL or pointing to memory) unless  */
-/*      the `N' switch is used.  `pointmarkerlist' must be initialized       */
-/*      unless the `N' or `B' switch is used.  If `N' is not used and        */
-/*      `in->numberofpointattributes' is not zero, `pointattributelist' must */
-/*      be initialized.                                                      */
-/*    - `trianglelist' must be initialized unless the `E' switch is used.    */
-/*      `neighborlist' must be initialized if the `n' switch is used.  If    */
-/*      the `E' switch is not used and (`in->numberofelementattributes' is   */
-/*      not zero or the `A' switch is used), `elementattributelist' must be  */
-/*      initialized.  `trianglearealist' may be ignored.                     */
-/*    - `segmentlist' must be initialized if the `p' or `c' switch is used,  */
-/*      and the `P' switch is not used.  `segmentmarkerlist' must also be    */
-/*      initialized under these circumstances unless the `B' switch is used. */
-/*    - `edgelist' must be initialized if the `e' switch is used.            */
-/*      `edgemarkerlist' must be initialized if the `e' switch is used and   */
-/*      the `B' switch is not.                                               */
-/*    - `holelist', `regionlist', `normlist', and all scalars may be ignored.*/
-/*                                                                           */
-/*  `vorout' (only needed if `v' switch is used):                            */
-/*                                                                           */
-/*    - `pointlist' must be initialized.  If `in->numberofpointattributes'   */
-/*      is not zero, `pointattributelist' must be initialized.               */
-/*      `pointmarkerlist' may be ignored.                                    */
-/*    - `edgelist' and `normlist' must both be initialized.                  */
-/*      `edgemarkerlist' may be ignored.                                     */
-/*    - Everything else may be ignored.                                      */
-/*                                                                           */
-/*  After a call to triangulate(), the valid fields of `out' and `vorout'    */
-/*  will depend, in an obvious way, on the choice of switches used.  Note    */
-/*  that when the `p' switch is used, the pointers `holelist' and            */
-/*  `regionlist' are copied from `in' to `out', but no new space is          */
-/*  allocated; be careful that you don't free() the same array twice.  On    */
-/*  the other hand, Triangle will never copy the `pointlist' pointer (or any */
-/*  others); new space is allocated for `out->pointlist', or if the `N'      */
-/*  switch is used, `out->pointlist' remains uninitialized.                  */
-/*                                                                           */
-/*  All of the meaningful `numberof' fields will be properly set; for        */
-/*  instance, `numberofedges' will represent the number of edges in the      */
-/*  triangulation whether or not the edges were written.  If segments are    */
-/*  not used, `numberofsegments' will indicate the number of boundary edges. */
-/*                                                                           */
-/*****************************************************************************/
-
-struct triangulateio {
-  REAL *pointlist;                                               /* In / out */
-  REAL *pointattributelist;                                      /* In / out */
-  int *pointmarkerlist;                                          /* In / out */
-  int numberofpoints;                                            /* In / out */
-  int numberofpointattributes;                                   /* In / out */
-
-  int *trianglelist;                                             /* In / out */
-  REAL *triangleattributelist;                                   /* In / out */
-  REAL *trianglearealist;                                         /* In only */
-  int *neighborlist;                                             /* Out only */
-  int numberoftriangles;                                         /* In / out */
-  int numberofcorners;                                           /* In / out */
-  int numberoftriangleattributes;                                /* In / out */
-
-  int *segmentlist;                                              /* In / out */
-  int *segmentmarkerlist;                                        /* In / out */
-  int numberofsegments;                                          /* In / out */
-
-  REAL *holelist;                        /* In / pointer to array copied out */
-  int numberofholes;                                      /* In / copied out */
-
-  REAL *regionlist;                      /* In / pointer to array copied out */
-  int numberofregions;                                    /* In / copied out */
-
-  int *edgelist;                                                 /* Out only */
-  int *edgemarkerlist;            /* Not used with Voronoi diagram; out only */
-  REAL *normlist;                /* Used only with Voronoi diagram; out only */
-  int numberofedges;                                             /* Out only */
-};
-
-void triangulateioinit(struct triangulateio*);
-void triangulateiodeinit(struct triangulateio*);
-void triangulateioreport(struct triangulateio*, int, int, int, int, int, int);
-
-/* The triangle data structure.  Each triangle contains three pointers to    */
-/*   adjoining triangles, plus three pointers to vertex points, plus three   */
-/*   pointers to shell edges (defined below; these pointers are usually      */
-/*   `dummysh').  It may or may not also contain user-defined attributes     */
-/*   and/or a floating-point "area constraint".  It may also contain extra   */
-/*   pointers for nodes, when the user asks for high-order elements.         */
-/*   Because the size and structure of a `triangle' is not decided until     */
-/*   runtime, I haven't simply defined the type `triangle' to be a struct.   */
-
-typedef REAL **triangle;            /* Really:  typedef triangle *triangle   */
-
-/* An oriented triangle:  includes a pointer to a triangle and orientation.  */
-/*   The orientation denotes an edge of the triangle.  Hence, there are      */
-/*   three possible orientations.  By convention, each edge is always        */
-/*   directed to point counterclockwise about the corresponding triangle.    */
-
-struct triedge {
-  triangle *tri;
-  int orient;                                         /* Ranges from 0 to 2. */
-};
-
-/* The shell data structure.  Each shell edge contains two pointers to       */
-/*   adjoining shell edges, plus two pointers to vertex points, plus two     */
-/*   pointers to adjoining triangles, plus one shell marker.                 */
-
-typedef REAL **shelle;                  /* Really:  typedef shelle *shelle   */
-
-/* An oriented shell edge:  includes a pointer to a shell edge and an        */
-/*   orientation.  The orientation denotes a side of the edge.  Hence, there */
-/*   are two possible orientations.  By convention, the edge is always       */
-/*   directed so that the "side" denoted is the right side of the edge.      */
-
-struct edge {
-  shelle *sh;
-  int shorient;                                       /* Ranges from 0 to 1. */
-};
-
-/* The point data structure.  Each point is actually an array of REALs.      */
-/*   The number of REALs is unknown until runtime.  An integer boundary      */
-/*   marker, and sometimes a pointer to a triangle, is appended after the    */
-/*   REALs.                                                                  */
-
-typedef REAL *point;
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// class mesh2d                                                              //
-//                                                                           //
-// The class simply encapsulating the well-coded and well-performed 2D unst- //
-// ructed mesh generator TRIANGLE's functions into a single calss so it can  //
-// be called directly from my 3D mesh program.                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-class mesh2d {
-
-  public:
-
-    enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE};
-    enum insertsiteresult {SUCCESSFULPOINT, ENCROACHINGPOINT, VIOLATINGPOINT,
-                           DUPLICATEPOINT};
-    enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
-
-  public:
-
-    memorypool triangles;
-    memorypool shelles;
-    memorypool points;
-    memorypool viri;
-
-    REAL xmin, xmax, ymin, ymax;
-    REAL xminextreme;
-    int inpoints, inelements, insegments, holes, regions;
-    long edges, hullsize;
-    int mesh_dim;
-    int nextras, eextras;
-    int triwords, shwords;
-    int pointmarkindex, point2triindex;
-    int highorderindex, elemattribindex, areaboundindex;
-    int checksegments;
-    int readnodefile;
-    long samples;
-    unsigned long randomseed;
-    long incirclecount, counterclockcount;
-    long circumcentercount;
-
-    int poly, refine, quality, vararea, fixedarea, regionattrib, convex;
-    int firstnumber;
-    int edgesout, voronoi, neighbors, geomview;
-    int nopolywritten, nonodewritten, noelewritten, noiterationnum;
-    int nobound, noholes, nobisect, noexact;
-    int incremental, sweepline, dwyer;
-    int splitseg, steiner, steinerleft;
-    int docheck, quiet, verbose;
-    int useshelles, order;
-    int restartsymbol;
-    REAL minangle, goodangle;
-    REAL maxarea;
-
-    point infpoint1, infpoint2, infpoint3;
-
-    triangle *dummytri;
-    triangle *dummytribase;
-    shelle *dummysh;
-    shelle *dummyshbase;
-
-    struct triedge recenttri;
-
-    static int plus1mod3[3];
-    static int minus1mod3[3];
-
-  public:
-
-    // User interaction routines
-    void syntax();
-    void info();
-    void internalerror();
-    void parsecommandline(int, char**, int);
-
-    // Debugging routines
-    void printtriangle(struct triedge*);
-    void printshelle(struct edge*);
-
-    // Memory management routines
-    void dummyinit(int, int);
-    void initializepointpool();
-    void initializetrisegpools();
-    void triangledealloc(triangle*);
-    triangle *triangletraverse();
-    void shelledealloc(shelle*);
-    shelle *shelletraverse();
-    void pointdealloc(point);
-    point pointtraverse();
-    point getpoint(int number);
-
-    // Constructors
-    void maketriangle(struct triedge*);
-    void makeshelle(struct edge*);
-
-    void triangleinit();
-    void triangledeinit();
-    void trianglerestart();
-
-    // Geometric predicates
-    REAL counterclockwise(point, point, point);
-    REAL iincircle(point, point, point, point);
-
-    // Point location routines
-    unsigned long randomnation(unsigned int);
-    void makepointmap();
-    enum locateresult preciselocate(point, struct triedge*);
-    enum locateresult locate(point, struct triedge*);
-
-    // Mesh transformation routines
-    void insertshelle(struct triedge*, int);
-    void flip(struct triedge*);
-    enum insertsiteresult insertsite(point, struct triedge*, struct edge*,
-                                     int, int);
-
-    // Divide-and-conquer Delaunay triangulation
-    void pointsort(point*, int);
-    void pointmedian(point*, int, int, int);
-    void alternateaxes(point*, int, int);
-    void mergehulls(struct triedge*, struct triedge*, struct triedge*,
-                    struct triedge*, int);
-    void divconqrecurse(point*, int, int, struct triedge*, struct triedge*);
-    long removeghosts(struct triedge*);
-    long divconqdelaunay();
-
-    // General mesh construction routines
-    long delaunay();
-
-    // Segment (shell edge) insertion routines
-    enum finddirectionresult finddirection(struct triedge*, point);
-    void segmentintersection(struct triedge*, struct edge*, point);
-    int scoutsegment(struct triedge*, point, int);
-    void conformingedge(point, point, int);
-    void delaunayfixup(struct triedge*, int);
-    void constrainededge(struct triedge*, point, int);
-    void insertsegment(point endpoint1, point endpoint2, int newmark);
-    void markhull();
-    int formskeleton(int*, int*, int);
-
-    // Carving out holes and concavities routines
-    void infecthull();
-    void plague();
-    void regionplague(REAL attribute, REAL area);
-    void carveholes(REAL*, int, REAL*, int);
-
-    // I/O routines
-    void transfernodes(REAL*, REAL*, int*, int, int);
-    void numbernodes();
-    void writenodes(REAL**, REAL**, int**);
-    void writeelements(int**, REAL**);
-    void writepoly(int**, int**);
-    void writeedges(int**, int**);
-    void writeneighbors(int**);
-    void writegid(int);
-
-  public:
-
-    mesh2d(char* triswtches) {
-      triangleinit();
-      parsecommandline(1, &triswtches, 1);
-    }
-    ~mesh2d() { triangledeinit(); }
-
-    void triangulate(struct triangulateio *in, struct triangulateio *out,
-                     struct triangulateio *vorout);
-};
-
-#endif // ifndef trilibH
-- 
GitLab