diff --git a/contrib/Tetgen/Makefile b/contrib/Tetgen/Makefile
index 639e045d2f25e48e3373d2ab58fac1fcd90db2cf..f9f022f055558b53966e41e5bd00b2c1923b930d 100644
--- a/contrib/Tetgen/Makefile
+++ b/contrib/Tetgen/Makefile
@@ -7,10 +7,22 @@ include ../../variables
 
 LIB = ../../lib/libGmshTetgen${LIBEXT}
 
-# Do not optimize (same as Triangle...) 
+# Don't optimize Tetgen
 CFLAGS = ${FLAGS} ${DASH}DTETLIBRARY
 
-SRC = predicates.cxx tetgen.cxx
+SRC = behavior.cxx\
+      constrain.cxx\
+      delaunay.cxx\
+      flip.cxx\
+      geom.cxx\
+      io.cxx\
+      main.cxx\
+      memorypool.cxx\
+      meshio.cxx\
+      meshstat.cxx\
+      predicates.cxx\
+      surface.cxx
+
 OBJ = ${SRC:.cxx=${OBJEXT}}
 
 .SUFFIXES: ${OBJEXT} .cxx
@@ -37,5 +49,16 @@ depend:
 	rm -f Makefile.new
 
 # DO NOT DELETE THIS LINE
+behavior${OBJEXT}: behavior.cxx tetgen.h
+constrain${OBJEXT}: constrain.cxx tetgen.h
+delaunay${OBJEXT}: delaunay.cxx tetgen.h
+flip${OBJEXT}: flip.cxx tetgen.h
+geom${OBJEXT}: geom.cxx tetgen.h
+io${OBJEXT}: io.cxx tetgen.h
+main${OBJEXT}: main.cxx tetgen.h
+memorypool${OBJEXT}: memorypool.cxx tetgen.h
+meshio${OBJEXT}: meshio.cxx tetgen.h
+meshstat${OBJEXT}: meshstat.cxx tetgen.h
 predicates${OBJEXT}: predicates.cxx tetgen.h
+surface${OBJEXT}: surface.cxx tetgen.h
 tetgen${OBJEXT}: tetgen.cxx tetgen.h
diff --git a/contrib/Tetgen/README b/contrib/Tetgen/README
index 125c22c4fa9ef24105952f8cbf5aa24e888af529..5e86013395d93eb91c6801b98a5f06183fa5e8de 100644
--- a/contrib/Tetgen/README
+++ b/contrib/Tetgen/README
@@ -1,4 +1,4 @@
-This is TetGen version 1.4.2 (released on April 16, 2007)
+This is an EXPERIMENTAL version of TetGen provided by Hang Si for Gmsh
 
 Please see the documentation of TetGen (available at the following link) for
 compiling and using TetGen.
@@ -13,4 +13,4 @@ Please send bugs/comments to Hang Si <si@wias-berlin.de>
 Thank you and enjoy!
 
 Hang Si
-April 16, 2007
+
diff --git a/contrib/Tetgen/behavior.cxx b/contrib/Tetgen/behavior.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..db89a9a53edc7e2e7632a967c282b70c4488b2d1
--- /dev/null
+++ b/contrib/Tetgen/behavior.cxx
@@ -0,0 +1,531 @@
+#ifndef behaviorCXX
+#define behaviorCXX
+
+#include "tetgen.h"
+
+static REAL PI = 3.14159265358979323846264338327950288419716939937510582;
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// tetgenbehavior()    Initialize veriables of 'tetgenbehavior'.             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+tetgenbehavior::tetgenbehavior()
+{
+  // Initialize command line switches.
+  plc = 0;
+  quality = 0;
+  refine = 0;
+  coarse = 0;
+  metric = 0;
+  minratio = 2.0;
+  goodratio = 0.0;
+  minangle = 20.0;
+  goodangle = 0.0;
+  maxdihedral = 165.0;
+  mindihedral = 5.0;
+  varvolume = 0;
+  fixedvolume = 0;
+  maxvolume = -1.0;
+  regionattrib = 0;
+  bowyerwatson = 1;
+  convexity = 0;
+  insertaddpoints = 0;
+  diagnose = 0;
+  conformdel = 0;
+  zeroindex = 0;
+  facesout = 0;
+  edgesout = 0;
+  neighout = 0;
+  voroout = 0;
+  meditview = 0;
+  gidview = 0;
+  geomview = 0;
+  order = 1;
+  nojettison = 0;
+  nobound = 0;
+  nonodewritten = 0;
+  noelewritten = 0;
+  nofacewritten = 0;
+  noiterationnum = 0;
+  nobisect = 0;
+  steiner = -1;
+  nomerge = 0;
+  docheck = 0;
+  quiet = 0;
+  verbose = 0;
+  useshelles = 0;
+  epsilon = 1.0e-8;
+  object = NONE;
+  // Initialize strings
+  commandline[0] = '\0';
+  infilename[0] = '\0';
+  outfilename[0] = '\0';
+  addinfilename[0] = '\0';
+  bgmeshfilename[0] = '\0';
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// versioninfo()    Print the version information of TetGen.                 //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenbehavior::versioninfo()
+{
+  printf("Develop Version (Started on August 9, 2008).\n");
+  printf("\n");
+  printf("Copyright (C) 2002 - 2008\n");
+  printf("Hang Si\n");
+  printf("Mohrenstr. 39, 10117 Berlin, Germany\n");
+  printf("si@wias-berlin.de\n");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// syntax()    Print list of command line switches and exit the program.     //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenbehavior::syntax()
+{
+  printf("  tetgen [-prq_Ra_AiMYS_T_dzo_fenvgGOJBNEFICQVh] input_file\n");
+  printf("    -p  Tetrahedralizes a piecewise linear complex (PLC).\n");
+  printf("    -r  Reconstructs a previously generated mesh.\n");
+  printf("    -q  Quality mesh generation (adding new mesh points to ");
+  printf("improve mesh quality).\n");
+  printf("    -R  Mesh coarsening (deleting redundant mesh points).\n");
+  printf("    -a  Applies a maximum tetrahedron volume constraint.\n");
+  printf("    -A  Assigns attributes to identify tetrahedra in different ");
+  printf("regions.\n");
+  printf("    -i  Inserts a list of additional points into mesh.\n");
+  printf("    -M  Does not merge coplanar facets.\n");
+  printf("    -Y  Suppresses boundary facets/segments splitting.\n");
+  printf("    -S  Specifies maximum number of added points.\n");
+  printf("    -T  Sets a tolerance for coplanar test (default 1e-8).\n");
+  printf("    -d  Detects self-intersections of facets of the PLC.\n");
+  printf("    -z  Numbers all output items starting from zero.\n");
+  printf("    -o2 Generates second-order subparametric elements.\n");
+  printf("    -f  Outputs all faces to .face file.");
+  printf("file.\n");
+  printf("    -e  Outputs all edges to .edge file.\n");
+  printf("    -n  Outputs tetrahedra neighbors to .neigh file.\n");
+  printf("    -v  Outputs Voronoi diagram to files.\n");
+  printf("    -g  Outputs mesh to .mesh file for viewing by Medit.\n");
+  printf("    -G  Outputs mesh to .msh file for viewing by Gid.\n");
+  printf("    -O  Outputs mesh to .off file for viewing by Geomview.\n");
+  printf("    -J  No jettison of unused vertices from output .node file.\n");
+  printf("    -B  Suppresses output of boundary information.\n");
+  printf("    -N  Suppresses output of .node file.\n");
+  printf("    -E  Suppresses output of .ele file.\n");
+  printf("    -F  Suppresses output of .face file.\n");
+  printf("    -I  Suppresses mesh iteration numbers.\n");
+  printf("    -C  Checks the consistency of the final mesh.\n");
+  printf("    -Q  Quiet:  No terminal output except errors.\n");
+  printf("    -V  Verbose:  Detailed information, more terminal output.\n");
+  printf("    -h  Help:  A brief instruction for using TetGen.\n");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// usage()    Print a brief instruction for using TetGen.                    //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenbehavior::usage()
+{
+  printf("TetGen\n");
+  printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
+  printf("Triangulator\n");
+  versioninfo();
+  printf("\n");
+  printf("What Can TetGen Do?\n");
+  printf("\n");
+  printf("  TetGen generates exact Delaunay tetrahedralizations, exact\n");
+  printf("  constrained Delaunay tetrahedralizations, and quality ");
+  printf("tetrahedral\n  meshes. The latter are nicely graded and whose ");
+  printf("tetrahedra have\n  radius-edge ratio bounded, thus are suitable ");
+  printf("for finite element and\n  finite volume analysis.\n"); 
+  printf("\n");
+  printf("Command Line Syntax:\n");
+  printf("\n");
+  printf("  Below is the command line syntax of TetGen with a list of ");
+  printf("short\n");
+  printf("  descriptions. Underscores indicate that numbers may optionally\n");
+  printf("  follow certain switches.  Do not leave any space between a ");
+  printf("switch\n");
+  printf("  and its numeric parameter.  \'input_file\' contains input data\n");
+  printf("  depending on the switches you supplied which may be a ");
+  printf("  piecewise\n");
+  printf("  linear complex or a list of nodes.  File formats and detailed\n");
+  printf("  description of command line switches are found in user's ");
+  printf("manual.\n");
+  printf("\n");
+  syntax();
+  printf("\n");
+  printf("Examples of How to Use TetGen:\n");
+  printf("\n");
+  printf("  \'tetgen object\' reads vertices from object.node, and writes ");
+  printf("their\n  Delaunay tetrahedralization to object.1.node and ");
+  printf("object.1.ele.\n");
+  printf("\n");
+  printf("  \'tetgen -p object\' reads a PLC from object.poly or object.");
+  printf("smesh (and\n  possibly object.node) and writes its constrained ");
+  printf("Delaunay\n  tetrahedralization to object.1.node, object.1.ele and ");
+  printf("object.1.face.\n");
+  printf("\n");
+  printf("  \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
+  printf("  object.smesh (and possibly object.node), generates a mesh ");
+  printf("whose\n  tetrahedra have radius-edge ratio smaller than 1.414 and ");
+  printf("have volume\n  of 0.1 or less, and writes the mesh to ");
+  printf("object.1.node, object.1.ele\n  and object.1.face.\n");
+  printf("\n");
+  printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// parse_commandline()    Read the command line, identify switches, and set  //
+//                        up options and file names.                         //
+//                                                                           //
+// 'argc' and 'argv' are the same parameters passed to the function main()   //
+// of a C/C++ program. They together represent the command line user invoked //
+// from an environment in which TetGen is running.                           //
+//                                                                           //
+// When TetGen is invoked from an environment. 'argc' is nonzero, switches   //
+// and input filename should be supplied as zero-terminated strings in       //
+// argv[0] through argv[argc - 1] and argv[0] shall be the name used to      //
+// invoke TetGen, i.e. "tetgen".  Switches are previously started with a     //
+// dash '-' to identify them from the input filename.                        //
+//                                                                           //
+// When TetGen is called from within another program. 'argc' is set to zero. //
+// switches are given in one zero-terminated string (no previous dash is     //
+// required.), and 'argv' is a pointer points to this string.  No input      //
+// filename is required (usually the input data has been directly created by //
+// user in the 'tetgenio' structure).  A default filename 'tetgen-tmpfile'   //
+// will be created for debugging output purpose.                             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenbehavior::parse_commandline(int argc, char **argv)
+{
+  int startindex;
+  int increment;
+  int meshnumber;
+  int scount;
+  int i, j, k;
+  char workstring[1024];
+
+  // First determine the input style of the switches.
+  if (argc == 0) {
+    startindex = 0;                    // Switches are given without a dash.
+    argc = 1;                    // For running the following for-loop once.
+    commandline[0] = '\0';
+  } else {
+    startindex = 1;
+    strcpy(commandline, argv[0]);
+    strcat(commandline, " ");
+  }
+  
+  // Rcount used to count the number of '-R' be used.
+  scount = 0;
+
+  for (i = startindex; i < argc; i++) {
+    // Remember the command line switches.
+    strcat(commandline, argv[i]);
+    strcat(commandline, " ");
+    if (startindex == 1) {
+      // Is this string a filename?
+      if (argv[i][0] != '-') {
+        strncpy(infilename, argv[i], 1024 - 1);
+        infilename[1024 - 1] = '\0';
+        // Go to the next string directly.
+        continue;                     
+      }
+    }
+    // Parse the individual switch from the string.
+    for (j = startindex; argv[i][j] != '\0'; j++) {
+      if (argv[i][j] == 'p') {
+        plc = 1;
+      } else if (argv[i][j] == 'r') {
+        refine = 1;
+      } else if (argv[i][j] == 'R') {
+        coarse = 1;
+      } else if (argv[i][j] == 'q') {
+        quality++;
+        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';
+          if (quality == 1) {
+            minratio = (REAL) strtod(workstring, (char **) NULL);
+          } else if (quality == 2) {
+            mindihedral = (REAL) strtod(workstring, (char **) NULL);
+          } else if (quality == 3) {
+            maxdihedral = (REAL) strtod(workstring, (char **) NULL);
+          }
+        }
+      } else if (argv[i][j] == 'm') {
+        metric++;
+      } else if (argv[i][j] == 'a') {
+        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] == '.') || (argv[i][j + 1] == 'e') ||
+                 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
+            j++;
+            workstring[k] = argv[i][j];
+            k++;
+          }
+          workstring[k] = '\0';
+          maxvolume = (REAL) strtod(workstring, (char **) NULL);
+        } else {
+          varvolume = 1;
+        }
+      } else if (argv[i][j] == 'A') {
+        regionattrib++;
+      } else if (argv[i][j] == 'b') {
+        bowyerwatson = 0;
+      } else if (argv[i][j] == 'c') {
+        convexity++;
+      } else if (argv[i][j] == 'i') {
+        insertaddpoints = 1;
+      } else if (argv[i][j] == 'd') {
+        diagnose = 1;
+      } else if (argv[i][j] == 'z') {
+        zeroindex = 1;
+      } else if (argv[i][j] == 'f') {
+        facesout = 1;
+      } else if (argv[i][j] == 'e') {
+        edgesout++;
+      } else if (argv[i][j] == 'n') {
+        neighout++;
+      } else if (argv[i][j] == 'v') {
+        voroout = 1;
+      } else if (argv[i][j] == 'g') {
+        meditview = 1;
+      } else if (argv[i][j] == 'G') {
+        gidview = 1;
+      } else if (argv[i][j] == 'O') {
+        geomview = 1;
+      } else if (argv[i][j] == 'M') {
+        nomerge = 1;
+      } else if (argv[i][j] == 'Y') {
+        nobisect++;
+      } else if (argv[i][j] == 'J') {
+        nojettison = 1;
+      } else if (argv[i][j] == 'B') {
+        nobound = 1;
+      } else if (argv[i][j] == 'N') {
+        nonodewritten = 1;
+      } else if (argv[i][j] == 'E') {
+        noelewritten = 1;
+        if (argv[i][j + 1] == '2') {
+          j++;
+          noelewritten = 2;
+        }
+      } else if (argv[i][j] == 'F') {
+        nofacewritten = 1;
+      } else if (argv[i][j] == 'I') {
+        noiterationnum = 1;
+      } else if (argv[i][j] == 'o') {
+        if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
+          k = 0;
+          while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
+            j++;
+            workstring[k] = argv[i][j];
+            k++;
+          }
+          workstring[k] = '\0';
+          order = (int) strtol(workstring, (char **) NULL, 0);
+        }
+      } else if (argv[i][j] == 'S') {
+        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';
+          steiner = (int) strtol(workstring, (char **) NULL, 0);
+        } 
+      } else if (argv[i][j] == 'D') {
+        conformdel++;
+      } else 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';
+          epsilon = (REAL) strtod(workstring, (char **) NULL);
+        } 
+      } else if (argv[i][j] == 'C') {
+        docheck++;
+      } else if (argv[i][j] == 'Q') {
+        quiet = 1;
+      } else if (argv[i][j] == 'V') {
+        verbose++;
+      // } else if (argv[i][j] == 'v') {
+        // versioninfo();
+        // terminatetetgen(0);
+      } else if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
+                 (argv[i][j] == '?')) {
+        usage();
+        terminatetetgen(0);
+      } else {
+        printf("Warning:  Unknown switch -%c.\n", argv[i][j]);
+      }
+    }
+  }
+
+  if (startindex == 0) {
+    // Set a temporary filename for debugging output.
+    strcpy(infilename, "tetgen-tmpfile");
+  } else {
+    if (infilename[0] == '\0') {
+      // No input file name. Print the syntax and exit.
+      syntax();
+      terminatetetgen(0);
+    }
+    // Recognize the object from file extension if it is available.
+    if (!strcmp(&infilename[strlen(infilename) - 5], ".node")) {
+      infilename[strlen(infilename) - 5] = '\0';
+      object = NODES;
+    } else if (!strcmp(&infilename[strlen(infilename) - 5], ".poly")) {
+      infilename[strlen(infilename) - 5] = '\0';
+      object = POLY;
+      plc = 1;
+    } else if (!strcmp(&infilename[strlen(infilename) - 6], ".smesh")) {
+      infilename[strlen(infilename) - 6] = '\0';
+      object = POLY;
+      plc = 1;
+    } else if (!strcmp(&infilename[strlen(infilename) - 4], ".off")) {
+      infilename[strlen(infilename) - 4] = '\0';
+      object = OFF;
+      plc = 1;
+    } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ply")) {
+      infilename[strlen(infilename) - 4] = '\0';
+      object = PLY;
+      plc = 1;
+    } else if (!strcmp(&infilename[strlen(infilename) - 4], ".stl")) {
+      infilename[strlen(infilename) - 4] = '\0';
+      object = STL;
+      plc = 1;
+    } else if (!strcmp(&infilename[strlen(infilename) - 5], ".mesh")) {
+      infilename[strlen(infilename) - 5] = '\0';
+      object = MEDIT;
+      plc = 1;
+    } else if (!strcmp(&infilename[strlen(infilename) - 4], ".vtk")) {
+      infilename[strlen(infilename) - 4] = '\0';
+      object = VTK;
+      plc = 1;
+    } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ele")) {
+      infilename[strlen(infilename) - 4] = '\0';
+      object = MESH;
+      refine = 1;
+    }
+  }
+  plc = plc || diagnose;
+  useshelles = plc || refine || coarse || quality;
+  goodratio = minratio;
+  goodratio *= goodratio;
+
+  // Detect improper combinations of switches.
+  if (plc && refine) {
+    printf("Error:  Switch -r cannot use together with -p.\n");
+    return false;
+  }
+  if (refine && (plc || noiterationnum)) {
+    printf("Error:  Switches %s cannot use together with -r.\n",
+           "-p, -d, and -I");
+    return false;
+  }
+  if (diagnose && (quality || insertaddpoints || (order == 2) || neighout
+      || docheck)) {
+    printf("Error:  Switches %s cannot use together with -d.\n",
+           "-q, -i, -o2, -n, and -C");
+    return false;
+  }
+
+  // Be careful not to allocate space for element area constraints that 
+  //   will never be assigned any value (other than the default -1.0).
+  if (!refine && !plc) {
+    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 || !plc) {
+    regionattrib = 0;
+  }
+  // If '-a' or '-aa' is in use, enable '-q' option too.
+  if (fixedvolume || varvolume) {
+    if (quality == 0) {
+      quality = 1;
+    }
+  }
+  // Calculate the goodangle for testing bad subfaces.
+  goodangle = cos(minangle * PI / 180.0);
+  goodangle *= goodangle;
+
+  increment = 0;
+  strcpy(workstring, infilename);
+  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(outfilename, infilename);
+  } else if (increment == 0) {
+    strcpy(outfilename, infilename);
+    strcat(outfilename, ".1");
+  } else {
+    workstring[increment] = '%';
+    workstring[increment + 1] = 'd';
+    workstring[increment + 2] = '\0';
+    sprintf(outfilename, workstring, meshnumber + 1);
+  }
+  // Additional input file name has the end ".a".
+  strcpy(addinfilename, infilename);
+  strcat(addinfilename, ".a");
+  // Background filename has the form "*.b.ele", "*.b.node", ...
+  strcpy(bgmeshfilename, infilename);
+  strcat(bgmeshfilename, ".b");
+
+  return true;
+}
+
+#endif // ifndef behaviorCXX
diff --git a/contrib/Tetgen/constrain.cxx b/contrib/Tetgen/constrain.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0a25f346b38a6a623213cb98b5899d8b358ed788
--- /dev/null
+++ b/contrib/Tetgen/constrain.cxx
@@ -0,0 +1,3512 @@
+#ifndef constrainCXX
+#define constrainCXX
+
+#include "tetgen.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// finddirection()    Find the tet on the path from one point to another.    //
+//                                                                           //
+// The path starts from 'searchtet''s origin and ends at 'endpt'. On finish, //
+// 'searchtet' contains a tet on the path, its origin does not change.       //
+//                                                                           //
+// The return value indicates one of the following cases (let 'searchtet' be //
+// abcd, a is the origin of the path):                                       //
+//   - ACROSSVERT, edge ab is collinear with the path;                       //
+//   - ACROSSEDGE, edge bc intersects with the path;                         //
+//   - ACROSSFACE, face bcd intersects with the path.                        //
+//                                                                           //
+// WARNING: This routine is designed for convex triangulations, and will not //
+// generally work after the holes and concavities have been carved.          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+enum tetgenmesh::intersection tetgenmesh::finddirection(triface* searchtet, 
+  point endpt)
+{
+  triface neightet;
+  point pa, pb, pc, pd, pn;
+  enum {HMOVE, RMOVE, LMOVE} nextmove;
+  enum {HCOPLANE, RCOPLANE, LCOPLANE, NCOPLANE} cop;
+  REAL hori, rori, lori;
+  REAL dmin, dist;
+
+  tetrahedron ptr;
+  int *iptr, tver;
+
+  // The origin is fixed.
+  pa = org(*searchtet);
+  if ((point) searchtet->tet[7] == dummypoint) {
+    // A hull tet. Choose the neighbor of its base face.
+    searchtet->loc = 0;
+    symself(*searchtet);
+    // Reset the origin to be pa.
+    if ((point) searchtet->tet[4] == pa) {
+      searchtet->loc = 0; searchtet->ver = 0;
+    } else if ((point) searchtet->tet[5] == pa) {
+      searchtet->loc = 0; searchtet->ver = 2;
+    } else if ((point) searchtet->tet[6] == pa) {
+      searchtet->loc = 0; searchtet->ver = 4;
+    } else {
+      assert((point) searchtet->tet[7] == pa); // SELF_CHECK
+      searchtet->loc = 1; searchtet->ver = 2;
+    }
+  }
+  if (searchtet->ver & 01) {
+    // Switch to the 0th edge ring.
+    esymself(*searchtet);
+    enextself(*searchtet);
+  }
+  pb = dest(*searchtet);
+  pc = apex(*searchtet);
+
+  // Check whether the destination or apex is 'endpt'.
+  if (pb == endpt) {
+    // pa->pb is the search edge.
+    return ACROSSVERT;
+  }
+  if (pc == endpt) {
+    // pa->pc is the search edge.
+    enext2self(*searchtet);
+    esymself(*searchtet);
+    return ACROSSVERT;
+  }
+
+  // Walk through tets at pa until the right one is found.
+  while (1) {
+
+    pd = oppo(*searchtet);
+
+    if (b->verbose > 2) {
+      printf("      From tet (%d, %d, %d, %d) to %d.\n", pointmark(pa),
+        pointmark(pb), pointmark(pc), pointmark(pd), pointmark(endpt));
+    }
+
+    // Check whether the opposite vertex is 'endpt'.
+    if (pd == endpt) {
+      // pa->pd is the search edge.
+      enext0fnextself(*searchtet);
+      enext2self(*searchtet);
+      esymself(*searchtet);
+      return ACROSSVERT;
+    }
+    // Check if we have entered outside of the domain.
+    if (pd == dummypoint) {
+      assert(0);
+    }
+
+    // Now assume that the base face abc coincides with the horizon plane,
+    //   and d lies above the horizon.  The search point 'endpt' may lie
+    //   above or below the horizon.  We test the orientations of 'endpt'
+    //   with respect to three planes: abc (horizon), bad (right plane),
+    //   and acd (left plane). 
+    hori = orient3d(pa, pb, pc, endpt);
+    rori = orient3d(pb, pa, pd, endpt);
+    lori = orient3d(pa, pc, pd, endpt);
+    orient3dcount += 3;
+
+    // Now decide the tet to move.  It is possible there are more than one
+    //   tet are viable moves. Use the opposite points of thier neighbors
+    //   to discriminate, i.e., we choose the tet whose opposite point has
+    //   the shortest distance to 'endpt'.
+    if (hori > 0) {
+      if (rori > 0) {
+        if (lori > 0) {
+          // Any of the three neighbors is a viable move.
+          nextmove = HMOVE;
+          sym(*searchtet, neightet);
+          pn = oppo(neightet);
+          if (pn != dummypoint) {
+            dmin = NORM2(endpt[0] - pn[0], endpt[1] - pn[1], endpt[2] - pn[2]);
+          } else {
+            dmin = NORM2(xmax - xmin, ymax - ymin, zmax - zmin);
+          }
+          enext0fnext(*searchtet, neightet);
+          symself(neightet);
+          pn = oppo(neightet);
+          if (pn != dummypoint) {
+            dist = NORM2(endpt[0] - pn[0], endpt[1] - pn[1], endpt[2] - pn[2]);
+          } else {
+            dist = dmin;
+          }
+          if (dist < dmin) {
+            nextmove = RMOVE;
+            dmin = dist;
+          }
+          enext2fnext(*searchtet, neightet);
+          symself(neightet);
+          pn = oppo(neightet);
+          if (pn != dummypoint) {
+            dist = NORM2(endpt[0] - pn[0], endpt[1] - pn[1], endpt[2] - pn[2]);
+          } else {
+            dist = dmin;
+          }
+          if (dist < dmin) {
+            nextmove = LMOVE;
+            dmin = dist;
+          }
+        } else {
+          // Two tets, below horizon and below right, are viable.
+          nextmove = HMOVE;
+          sym(*searchtet, neightet);
+          pn = oppo(neightet);
+          if (pn != dummypoint) {
+            dmin = NORM2(endpt[0] - pn[0], endpt[1] - pn[1], endpt[2] - pn[2]);
+          } else {
+            dmin = NORM2(xmax - xmin, ymax - ymin, zmax - zmin);
+          }
+          enext0fnext(*searchtet, neightet);
+          symself(neightet);
+          pn = oppo(neightet);
+          if (pn != dummypoint) {
+            dist = NORM2(endpt[0] - pn[0], endpt[1] - pn[1], endpt[2] - pn[2]);
+          } else {
+            dist = dmin;
+          }
+          if (dist < dmin) {
+            nextmove = RMOVE;
+            dmin = dist;
+          }
+        }
+      } else {
+        if (lori > 0) {
+          // Two tets, below horizon and below left, are viable.
+          nextmove = HMOVE;
+          sym(*searchtet, neightet);
+          pn = oppo(neightet);
+          if (pn != dummypoint) {
+            dmin = NORM2(endpt[0] - pn[0], endpt[1] - pn[1], endpt[2] - pn[2]);
+          } else {
+            dmin = NORM2(xmax - xmin, ymax - ymin, zmax - zmin);
+          }
+          enext2fnext(*searchtet, neightet);
+          symself(neightet);
+          pn = oppo(neightet);
+          if (pn != dummypoint) {
+            dist = NORM2(endpt[0] - pn[0], endpt[1] - pn[1], endpt[2] - pn[2]);
+          } else {
+            dist = dmin;
+          }
+          if (dist < dmin) {
+            nextmove = LMOVE;
+            dmin = dist;
+          }
+        } else {
+          // The tet below horizon is chosen.
+          nextmove = HMOVE;
+        }
+      }
+    } else {
+      if (rori > 0) {
+        if (lori > 0) {
+          // Two tets, below right and below left, are viable.
+          nextmove = RMOVE;
+          enext0fnext(*searchtet, neightet);
+          symself(neightet);
+          pn = oppo(neightet);
+          if (pn != dummypoint) {
+            dmin = NORM2(endpt[0] - pn[0], endpt[1] - pn[1], endpt[2] - pn[2]);
+          } else {
+            dmin = NORM2(xmax - xmin, ymax - ymin, zmax - zmin);
+          }
+          enext2fnext(*searchtet, neightet);
+          symself(neightet);
+          pn = oppo(neightet);
+          if (pn != dummypoint) {
+            dist = NORM2(endpt[0] - pn[0], endpt[1] - pn[1], endpt[2] - pn[2]);
+          } else {
+            dist = dmin;
+          }
+          if (dist < dmin) {
+            nextmove = LMOVE;
+            dmin = dist;
+          }
+        } else {
+          // The tet below right is chosen.
+          nextmove = RMOVE;
+        }
+      } else {
+        if (lori > 0) {
+          // The tet below left is chosen.
+          nextmove = LMOVE;
+        } else {
+          // 'endpt' lies either on the plane(s) or across face bcd.
+          if (hori == 0) {
+            if (rori == 0) {
+              // pa->'endpt' is COLLINEAR with pa->pb.
+              return ACROSSVERT;
+            }
+            if (lori == 0) {
+              // pa->'endpt' is COLLINEAR with pa->pc.
+              enext2self(*searchtet);
+              esymself(*searchtet);
+              return ACROSSVERT;
+            }
+            // pa->'endpt' crosses the edge pb->pc.
+            // enextself(*searchtet);
+            // return ACROSSEDGE;
+            cop = HCOPLANE;
+            break;
+          }
+          if (rori == 0) {
+            if (lori == 0) {
+              // pa->'endpt' is COLLINEAR with pa->pd.
+              enext0fnextself(*searchtet); // face abd.
+              enext2self(*searchtet);
+              esymself(*searchtet);
+              return ACROSSVERT;
+            }
+            // pa->'endpt' crosses the edge pb->pd.
+            // enext0fnextself(*searchtet); // face abd.
+            // enextself(*searchtet);
+            // return ACROSSEDGE;
+            cop = RCOPLANE;
+            break;
+          }
+          if (lori == 0) {
+            // pa->'endpt' crosses the edge pc->pd.
+            // enext2fnextself(*searchtet);  // face cad
+            // enext2self(*searchtet);
+            // return ACROSSEDGE;
+            cop = LCOPLANE;
+            break;
+          }
+          // pa->'endpt' crosses the face bcd.
+          // enextfnextself(*searchtet);
+          // return ACROSSFACE;
+          cop = NCOPLANE;
+          break;
+        }
+      }
+    }
+
+    // Move to the next tet, fix pa as its origin.
+    if (nextmove == RMOVE) {
+      fnextself(*searchtet);
+    } else if (nextmove == LMOVE) {
+      enext2self(*searchtet);
+      fnextself(*searchtet);
+      enextself(*searchtet);
+    } else { // HMOVE
+      symedgeself(*searchtet);
+      enextself(*searchtet);
+    }
+    assert(org(*searchtet) == pa); // SELF_CHECK
+    pb = dest(*searchtet);
+    pc = apex(*searchtet);
+
+  } // while (1)
+
+  // Either case ACROSSEDGE or ACROSSFACE.
+  if (b->epsilon > 0) {
+    // Use tolerance to re-evaluate the orientations.
+    if (cop != HCOPLANE) {
+      if (iscoplanar(pa, pb, pc, endpt, hori)) hori = 0;
+    }
+    if (cop != RCOPLANE) {
+      if (iscoplanar(pb, pa, pd, endpt, rori)) rori = 0;
+    }
+    if (cop != LCOPLANE) {
+      if (iscoplanar(pa, pc, pd, endpt, lori)) lori = 0;
+    }
+    // It is not possible that all orientations are zero.
+    assert(!((hori == 0) && (rori == 0) && (lori == 0))); // SELF_CHECK
+  }
+  
+  // Now decide the degenerate cases.
+  if (hori == 0) {
+    if (rori == 0) {
+      // pa->'endpt' is COLLINEAR with pa->pb.
+      return ACROSSVERT;
+    }
+    if (lori == 0) {
+      // pa->'endpt' is COLLINEAR with pa->pc.
+      enext2self(*searchtet);
+      esymself(*searchtet);
+      return ACROSSVERT;
+    }
+    // pa->'endpt' crosses the edge pb->pc.
+    return ACROSSEDGE;
+  }
+  if (rori == 0) {
+    if (lori == 0) {
+      // pa->'endpt' is COLLINEAR with pa->pd.
+      enext0fnextself(*searchtet); // face abd.
+      enext2self(*searchtet);
+      esymself(*searchtet);
+      return ACROSSVERT;
+    }
+    // pa->'endpt' crosses the edge pb->pd.
+    enext0fnextself(*searchtet); // face abd.
+    esymself(*searchtet);
+    enextself(*searchtet);
+    return ACROSSEDGE;
+  }
+  if (lori == 0) {
+    // pa->'endpt' crosses the edge pc->pd.
+    enext2fnextself(*searchtet);  // face cad
+    esymself(*searchtet);
+    return ACROSSEDGE;
+  }
+  // pa->'endpt' crosses the face bcd.
+  return ACROSSFACE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// scoutsegment()    Look for a given segment in the tetrahedralization T.   //
+//                                                                           //
+// Search an edge in the tetrahedralization that matches the given segmment. //
+// If such an edge is found, the segment is 'locked' at the edge.            //
+//                                                                           //
+// If 'searchtet' != NULL, it's origin must be the origin of 'sseg'.  It is  //
+// used as the starting tet for searching the edge.                          //
+//                                                                           //
+// The returned value indicates one of the following cases:                  //
+//   - SHAREVERT, the segment exists and is inserted in T;                   //
+//   - ACROSSVERT, a vertex ('refpt') lies on the segment;                   //
+//   - ACROSSEDGE, the segment is missing;                                   //
+//   - ACROSSFACE, the segment is missing;                                   //
+//                                                                           //
+// If the returned value is ACROSSEDGE or ACROSSFACE, i.e., the segment is   //
+// missing, 'refpt' returns the reference point for splitting thus segment,  //
+// 'searchtet' returns a tet containing the 'refpt'.                         //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+enum tetgenmesh::intersection tetgenmesh::scoutsegment(face* sseg,
+  triface* searchtet, point* refpt)
+{
+  triface neightet, reftet;
+  face splitsh, checkseg;
+  point startpt, endpt;
+  point pa, pb, pc, pd;
+  enum location loc;
+  enum intersection dir;
+  REAL angmax, ang;
+  long facecount;
+  bool orgflag;
+  int types[2], poss[4];
+  int shver, pos, i;
+
+  tetrahedron ptr;
+  shellface sptr;
+  int *iptr, tver;
+
+  // Is 'searchtet' a valid handle?
+  if (searchtet->tet == NULL) {
+    orgflag = false;
+    // Search a tet whose origin is one of the endpoints of 'sseg'.
+    for (shver = 0; shver < 2 && !orgflag; shver++) {
+      startpt = (point) sseg->sh[shver + 3];
+      decode(point2tet(startpt), *searchtet);
+      if ((searchtet->tet != NULL) && (searchtet->tet[4] != NULL)) {
+        // Check if this tet contains pa.
+        for (i = 4; i < 8 && !orgflag; i++) {
+          if ((point) searchtet->tet[i] == startpt) {
+            // Found. Set pa as its origin.
+            switch (i) {
+              case 4: searchtet->loc = 0; searchtet->ver = 0; break;
+              case 5: searchtet->loc = 0; searchtet->ver = 2; break;
+              case 6: searchtet->loc = 0; searchtet->ver = 4; break;
+              case 7: searchtet->loc = 1; searchtet->ver = 2; break;
+            }
+            sseg->shver = shver;
+            orgflag = true;
+          }
+        }
+      }
+    }
+    assert(orgflag); // SELF_CHECK
+  } else {
+    startpt = sorg(*sseg);
+    assert(org(*searchtet) == startpt); // SELF_CHECK
+  }
+  endpt = sdest(*sseg);
+
+  if (b->verbose > 1) {
+    printf("    Scout seg (%d, %d).\n", pointmark(startpt), pointmark(endpt));
+  }
+
+  dir = finddirection(searchtet, endpt);
+
+  if (dir == ACROSSVERT) {
+    pd = dest(*searchtet);
+    if (pd == endpt) {
+      // Found! Insert the segment.
+      tsspivot(*searchtet, checkseg);  // SELF_CHECK
+      if (checkseg.sh == NULL) {
+        neightet = *searchtet;
+        do {
+          tssbond1(neightet, *sseg);
+          fnextself(neightet);
+        } while (neightet.tet != searchtet->tet);
+      } else {
+        // Collision! This can happy during facet recovery.
+        // See fig/dump-cavity-case19, -case20.
+        assert(checkseg.sh == sseg->sh); // SELF_CHECK
+      }
+      // The job is done. 
+      return SHAREVERT;
+    } else {
+      // A point is on the path.
+      *refpt = pd;
+      return ACROSSVERT;
+    }
+  }
+
+  if (b->verbose > 1) {
+    printf("    Scout ref point of seg (%d, %d).\n", pointmark(startpt), 
+      pointmark(endpt));
+  }
+  facecount = across_face_count;
+
+  enextfnextself(*searchtet); // Go to the opposite face.
+  symedgeself(*searchtet); // Enter the adjacent tet.
+
+  pa = org(*searchtet);
+  angmax = interiorangle(pa, startpt, endpt, NULL);
+  *refpt = pa;
+  pb = dest(*searchtet);
+  ang = interiorangle(pb, startpt, endpt, NULL);
+  if (ang > angmax) {
+    angmax = ang;
+    *refpt = pb;
+  }
+
+  // Check whether two segments are intersecting.
+  if (dir == ACROSSEDGE) {
+    tsspivot(*searchtet, checkseg);
+    if (checkseg.sh != NULL) {
+      printf("Error:  Invalid PLC. Two segments intersect.\n");
+      startpt = farsorg(*sseg);
+      endpt = farsdest(*sseg);
+      pa = farsorg(checkseg);
+      pb = farsdest(checkseg);
+      printf("  1st: (%d, %d), 2nd: (%d, %d).\n", pointmark(startpt), 
+        pointmark(endpt), pointmark(pa), pointmark(pb));
+      terminatetetgen(1);
+    }
+    across_edge_count++;
+  }
+  
+  pc = apex(*searchtet);
+  ang = interiorangle(pc, startpt, endpt, NULL);
+  if (ang > angmax) {
+    angmax = ang;
+    *refpt = pc;
+  }
+  reftet = *searchtet; // Save the tet containing the refpt.
+
+  // Search intersecting faces along the segment.
+  while (1) {
+
+    pd = oppo(*searchtet);
+    assert(pd != dummypoint);  // SELF_CHECK
+
+    if (b->verbose > 2) {
+      printf("      Passing face (%d, %d, %d, %d), dir(%d).\n", pointmark(pa),
+        pointmark(pb), pointmark(pc), pointmark(pd), (int) dir);
+    }
+    across_face_count++;
+
+    // Stop if we meet 'endpt'.
+    if (pd == endpt) break;
+
+    ang = interiorangle(pd, startpt, endpt, NULL);
+    if (ang > angmax) {
+      angmax = ang;
+      *refpt = pd;
+      reftet = *searchtet;
+    }
+
+    // Find a face intersecting the segment.
+    if (dir == ACROSSFACE) {
+      // One of the three oppo faces in 'searchtet' intersects the segment.
+      neightet.tet = searchtet->tet;
+      neightet.ver = 0;
+      for (i = 0; i < 3; i++) {
+        neightet.loc = locpivot[searchtet->loc][i];
+        pa = org(neightet);
+        pb = dest(neightet);
+        pc = apex(neightet);
+        pd = oppo(neightet); // The above point.
+        if (tri_edge_test(pa, pb, pc, startpt, endpt, pd, 1, types, poss)) {
+          dir = (enum intersection) types[0];
+          pos = poss[0];
+          break;
+        } else {
+          dir = DISJOINT;
+          pos = 0;
+        }
+      }
+      assert(dir != DISJOINT);  // SELF_CHECK
+    } else { // dir == ACROSSEDGE
+      // Check the two opposite faces (of the edge) in 'searchtet'.
+      neightet = *searchtet;
+      neightet.ver = 0;
+      for (i = 0; i < 2; i++) {
+        neightet.loc = locverpivot[searchtet->loc][searchtet->ver][i];
+        pa = org(neightet);
+        pb = dest(neightet);
+        pc = apex(neightet);
+        pd = oppo(neightet); // The above point.
+        if (tri_edge_test(pa, pb, pc, startpt, endpt, pd, 1, types, poss)) {
+          dir = (enum intersection) types[0];
+          pos = poss[0];
+          break;
+        } else {
+          dir = DISJOINT;
+          pos = 0;
+        }
+      }
+      if (dir == DISJOINT) {
+        // No intersection. Go to the next tet.
+        dir = ACROSSEDGE;
+        fnextself(*searchtet);
+        continue;
+      }
+    }
+
+    if (dir == ACROSSVERT) {
+      // This segment passing a vertex. Choose it and return.
+      for (i = 0; i < pos; i++) {
+        enextself(neightet);
+      }
+      pd = org(neightet);
+      if (b->verbose > 2) {
+        angmax = interiorangle(pd, startpt, endpt, NULL);
+      }
+      *refpt = pd;
+      break;
+    }
+    if (dir == ACROSSEDGE) {
+      // Get the edge intersects with the segment.
+      for (i = 0; i < pos; i++) {
+        enextself(neightet);
+      }
+    }
+    // Go to the next tet.
+    symedge(neightet, *searchtet);
+
+    if (dir == ACROSSEDGE) {
+      // Check whether two segments are intersecting.
+      tsspivot(*searchtet, checkseg);
+      if (checkseg.sh != NULL) {
+        printf("Error:  Invalid PLC! Two segments intersect.\n");
+        startpt = farsorg(*sseg);
+        endpt = farsdest(*sseg);
+        pa = farsorg(checkseg);
+        pb = farsdest(checkseg);
+        printf("    1st: (%d, %d), 2nd: (%d, %d).\n", pointmark(startpt), 
+          pointmark(endpt), pointmark(pa), pointmark(pb));
+        terminatetetgen(1);
+      }
+      across_edge_count++;
+    }
+
+  } // while (1)
+
+  // dir is either ACROSSVERT, or ACROSSEDGE, or ACROSSFACE.
+  if (b->verbose > 2) {
+    printf("      Refpt %d (%g), visited %ld faces.\n", pointmark(*refpt),
+      angmax / PI * 180.0, (int) dir, across_face_count - facecount);
+  }
+  if (across_face_count - facecount > across_max_count) {
+    across_max_count = across_face_count - facecount;
+  }
+
+  *searchtet = reftet;
+  return dir;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// getsegmentsplitpoint()    Calculate a split point in the given segment.   //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::getsegmentsplitpoint(face* sseg, point refpt, REAL* vt)
+{
+  point ei, ej, ek;
+  REAL split, L, d, d1, d2, d3;
+  int stype, sign;
+  int i;
+
+  // Decide the type of this segment.
+  sign = 1;
+  ei = sorg(*sseg);
+  ej = sdest(*sseg);
+
+  if (getpointtype(ei) == ACUTEVERTEX) {
+    if (getpointtype(ej) == ACUTEVERTEX) {
+      // Both ei and ej are ACUTEVERTEX.
+      stype = 0;
+    } else {
+      // ej is either a RIDGEVERTEX or a STEINERVERTEX.
+      stype = 1;
+    }
+  } else {
+    if (getpointtype(ei) == RIDGEVERTEX) {
+      if (getpointtype(ej) == ACUTEVERTEX) {
+        stype = 1; sign = -1;
+      } else {
+        if (getpointtype(ej) == RIDGEVERTEX) {
+          // Both ei and ej are non-acute.
+          stype = 0;
+        } else {
+          // ej is a STEINERVETEX.
+          ek = farsdest(*sseg);
+          if (getpointtype(ek) == ACUTEVERTEX) {
+            stype = 1; sign = -1;
+          } else {
+            stype = 0;
+          }
+        }
+      }
+    } else {
+      // ei is a STEINERVERTEX.
+      if (getpointtype(ej) == ACUTEVERTEX) {
+        stype = 1; sign = -1;
+      } else {
+        ek = farsorg(*sseg);
+        if (getpointtype(ej) == RIDGEVERTEX) {
+          if (getpointtype(ek) == ACUTEVERTEX) {
+            stype = 1;
+          } else {
+            stype = 0;
+          }
+        } else {
+          // Both ei and ej are STEINERVETEXs. ei has priority.
+          if (getpointtype(ek) == ACUTEVERTEX) {
+            stype = 1;
+          } else {
+            ek = farsdest(*sseg);
+            if (getpointtype(ek) == ACUTEVERTEX) {
+              stype = 1; sign = -1;
+            } else {
+              stype = 0;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // Adjust the endpoints: ei, ej.
+  if (sign == -1) {
+    sesymself(*sseg);
+    ei = sorg(*sseg);
+    ej = sdest(*sseg);
+  }
+
+  if (b->verbose > 1) {
+    printf("    Split a type-%d seg(%d, %d) ref(%d)", stype,
+      pointmark(ei), pointmark(ej), pointmark(refpt));
+    if (stype) {
+      ek = farsorg(*sseg);
+      printf(" ek(%d)", pointmark(ek));
+    }
+    printf(".\n");
+  }
+
+  // Calculate the split point.
+  if (stype == 0) {
+    // Use rule-1.
+    L = DIST(ei, ej);
+    d1 = DIST(ei, refpt);
+    d2 = DIST(ej, refpt);
+    if (d1 < d2) {
+      // Choose ei as center.
+      if (d1 < 0.5 * L) {
+        split = d1 / L;
+        // Adjust split if it is close to middle. (2009-02-01)
+        if ((split > 0.4) || (split < 0.6)) split = 0.5;
+      } else {
+        split = 0.5;
+      }
+      for (i = 0; i < 3; i++) {
+        vt[i] = ei[i] + split * (ej[i] - ei[i]);
+      }
+    } else {
+      // Choose ej as center.
+      if (d2 < 0.5 * L) {
+        split = d2 / L;
+        // Adjust split if it is close to middle. (2009-02-01)
+        if ((split > 0.4) || (split < 0.6)) split = 0.5;
+      } else {
+        split = 0.5;
+      }
+      for (i = 0; i < 3; i++) {
+        vt[i] = ej[i] + split * (ei[i] - ej[i]);
+      }
+    }
+    r1count++;
+  } else {
+    // Use rule-2.
+    ek = farsorg(*sseg);
+    L = DIST(ek, ej);
+    d = DIST(ek, refpt);
+    split = d / L;
+    for (i = 0; i < 3; i++) {
+      vt[i] = ek[i] + split * (ej[i] - ek[i]);
+    }
+    d1 = DIST(vt, refpt);
+    d2 = DIST(vt, ej);
+    if (d1 > d2) {
+      // Use rule-3.
+      d3 = DIST(ei, refpt);
+      if (d1 < 0.5 * d3) {
+        split = (d - d1) / L;
+      } else {
+        split = (d - 0.5 * d3) / L;
+      }
+      for (i = 0; i < 3; i++) {
+        vt[i] = ek[i] + split * (ej[i] - ek[i]);
+      }
+    }
+    d1 > d2 ? r3count++ : r2count++;
+  }
+
+  if (b->verbose > 1) {
+    printf("    split (%g), vt (%g, %g, %g).\n", split, vt[0], vt[1], vt[2]);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// delaunizesegments()    Recover segments in a Delaunay tetrahedralization. //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::delaunizesegments()
+{
+  triface searchtet;
+  face splitsh;
+  face *psseg, sseg;
+  point refpt, newpt;
+  enum intersection dir;
+  bool visflag;
+
+  if (b->verbose) {
+    printf("  Delaunizing segments.\n");
+  }
+
+  // Loop until 'subsegstack' is empty.
+  while (subsegstack->objects > 0l) {
+    // seglist is used as a stack.
+    subsegstack->objects--;
+    psseg = (face *) fastlookup(subsegstack, subsegstack->objects);
+    sseg = *psseg;
+
+    if (!sinfected(sseg)) continue; // Not a missing segment.
+    suninfect(sseg);
+
+    // Insert the segment.
+    searchtet.tet = NULL;
+    dir = scoutsegment(&sseg, &searchtet, &refpt);
+
+    if (dir != SHAREVERT) {
+      // The segment is missing, split it.
+      spivot(sseg, splitsh);
+      if (dir != ACROSSVERT) {
+        // Create the new point.
+        makepoint(&newpt);
+        getsegmentsplitpoint(&sseg, refpt, newpt);
+        setpointtype(newpt, STEINERVERTEX);
+        // Split the segment by newpt.
+        sinsertvertex(newpt, &splitsh, &sseg, true, false);
+        // Insert newpt into the DT. If 'checksubfaces == 1' the current
+        //   mesh is constrained Delaunay (but may not Delaunay).
+        visflag = (checksubfaces == 1);
+        insertvertex(newpt, &searchtet, true, visflag, false, false);
+      } else {
+        /*if (getpointtype(refpt) != ACUTEVERTEX) {
+          setpointtype(refpt, RIDGEVERTEX);
+        }
+        // Split the segment by refpt.
+        sinsertvertex(refpt, &splitsh, &sseg, true, false);*/
+        printf("Error:  Invalid PLC! A point and a segment intersect.\n");
+        point pa, pb;
+        pa = farsorg(sseg);
+        pb = farsdest(sseg);
+        printf("  Point: %d. Segment: (%d, %d).\n", pointmark(refpt),
+          pointmark(pa), pointmark(pb));
+        terminatetetgen(1);
+      }
+    }
+  }
+
+  if (b->verbose) {
+    printf("  %d protecting points.\n", r1count + r2count + r3count);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// scoutsubface()    Look for a given subface in the tetrahedralization T.   //
+//                                                                           //
+// 'ssub' is the subface, denoted as abc. If abc exists in T, it is 'locked' //
+// at the place where the two tets sharing at it.                            //
+//                                                                           //
+// The returned value indicates one of the following cases:                  //
+//   - SHAREFACE, abc exists and is inserted;                                //
+//   - TOUCHEDGE, a vertex (the origin of 'searchtet') lies on ab.           //
+//   - EDGETRIINT, all three edges of abc are missing.                       //
+//   - ACROSSTET, a tet (in 'searchtet') crosses the facet containg abc.     //
+//                                                                           //
+// If the retunred value is ACROSSTET, the subface is missing.  'searchtet'  //
+// returns a tet which shares the same edge as 'pssub'.                      //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+enum tetgenmesh::intersection tetgenmesh::scoutsubface(face* pssub,
+  triface* searchtet)
+{
+  triface spintet;
+  face checksh;
+  point pa, pb, pc, pd;
+  enum intersection dir;
+  int i;
+
+  tetrahedron ptr;
+  int tver;
+
+  if (searchtet->tet == NULL) {
+    // Search an edge of 'ssub' in tetrahedralization.
+    pssub->shver = 0;
+    for (i = 0; i < 3; i++) {
+      pa = sorg(*pssub);
+      pb = sdest(*pssub);
+      // Do not search dummypoint.
+      assert(pa != dummypoint); // SELF_CHECK
+      assert(pb != dummypoint); // SELF_CHECK
+      // Get a tet whose origin is pa.
+      decode(point2tet(pa), *searchtet);
+      assert(searchtet->tet != NULL); // SELF_CHECK
+      assert(searchtet->tet[4] != NULL); // SELF_CHECK
+      if ((point) searchtet->tet[4] == pa) {
+        searchtet->loc = 0; searchtet->ver = 0;
+      } else if ((point) searchtet->tet[5] == pa) {
+        searchtet->loc = 0; searchtet->ver = 2;
+      } else if ((point) searchtet->tet[6] == pa) {
+        searchtet->loc = 0; searchtet->ver = 4;
+      } else {
+        if ((point) searchtet->tet[7] != pa) {
+          printf("Error: Bad pt-to-tet at %d\n", pointmark(pa));
+          assert(0);
+        }
+        searchtet->loc = 1; searchtet->ver = 2;
+      }
+      // Search the edge from pa->pb.
+      dir = finddirection(searchtet, pb);
+      if (dir == ACROSSVERT) {
+        if (dest(*searchtet) == pb) {
+          // Found the edge. Break the loop.
+          break;
+        } else {
+          // A vertex lies on the search edge. Return it.
+          enextself(*searchtet);
+          return TOUCHEDGE;
+        }
+      }
+      senextself(*pssub);
+    }
+    if (i == 3) {
+      // None of the three edges exists.
+      return EDGETRIINT; // ab intersects the face in 'searchtet'.
+    }
+  } else {
+    // 'searchtet' holds the current edge of 'pssub'.
+    pa = org(*searchtet);
+    pb = dest(*searchtet);
+  }
+
+  pc = sapex(*pssub);
+
+  if (b->verbose > 1) {
+    printf("    Scout subface (%d, %d, %d) (%ld).\n", pointmark(pa),
+      pointmark(pb), pointmark(pc), subfacstack->objects);
+  }
+
+  // Searchtet holds edge pa->pb. Search a face with apex pc.
+  spintet = *searchtet;
+  while (1) {
+    fnextself(spintet);
+    pd = apex(spintet);  // pd may be dummypoint. Search the face anyway.
+    if (pd == pc) {
+      // Found! Insert the subface.
+      tspivot(spintet, checksh); // SELF_CHECK
+      if (checksh.sh == NULL) {
+        tsbond(spintet, *pssub);
+        symedgeself(spintet);
+        tspivot(spintet, checksh); // SELF_CHECK
+        assert(checksh.sh == NULL); // SELF_CHECK
+        tsbond(spintet, *pssub);
+        return SHAREFACE;
+      } else {
+        // Another subface is laready inserted.
+        assert(checksh.sh != pssub->sh); // SELF_CHECK
+        // Comment: This is possible when there are faked tets.
+        *searchtet = spintet;
+        return COLLISIONFACE;
+      }
+    }
+    if (pd == apex(*searchtet)) break;
+  }
+
+  return ACROSSTET;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// scoutcrosstet()    Scout a tetrahedron across a facet.                    //
+//                                                                           //
+// A subface (abc) of the facet (F) is given in 'pssub', 'searchtet' holds   //
+// the edge ab, it is the tet starting the search.  'facpoints' contains all //
+// points which are co-facet with a, b, and c.                               //
+//                                                                           //
+// The subface (abc) was produced by a 2D CDT algorithm under the Assumption //
+// that F is flat. In real data, however, F may not be strictly flat.  Hence //
+// a tet (abde) that crosses abc may be in one of the two cases: (i) abde    //
+// intersects F in its interior, or (ii) abde intersects F on its boundary.  //
+// In case (i) F (or part of it) is missing in DT and needs to be recovered. //
+// In (ii) F is not missing, the surface mesh of F needs to be adjusted.     //
+//                                                                           //
+// This routine distinguishes the two cases by the returned value, which is  //
+//   - ACROSSTET, if it is case (i), 'searchtet' is abde, d and e lies below //
+//     and above abc, respectively, neither d nor e is dummypoint; or        //
+//   - ACROSSFACE, if it is case (ii), 'searchtet' is abde, where the face   //
+//     abd intersects abc, i.e., d is co-facet with abc, e may be co-facet   //
+//     with abc or dummypoint.                                               //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+enum tetgenmesh::intersection tetgenmesh::scoutcrosstet(face *pssub, 
+  triface* searchtet, arraypool* facpoints)
+{
+  triface spintet, crossface;
+  point pa, pb, pc, pd, pe;
+  REAL ori, ori1, len, n[3];
+  REAL r, dr, drmin;
+  bool cofacetflag;
+  int i;
+
+  if (facpoints != NULL) {
+    // Infect all vertices of the facet.
+    for (i = 0; i < facpoints->objects; i++) {
+      pd = * (point *) fastlookup(facpoints, i);
+      pinfect(pd);
+    }
+  }
+
+  // Search an edge crossing the facet containing abc.
+  if (searchtet->ver & 01) {
+    esymself(*searchtet); // Adjust to 0th edge ring.
+    sesymself(*pssub);
+  }
+
+  pa = sorg(*pssub);
+  pb = sdest(*pssub);
+  pc = sapex(*pssub);
+
+  // Search an apex lies below the subface. Note that such apex may not
+  //   exist which indicates there is a co-facet apex.
+  cofacetflag = false;
+  pd = apex(*searchtet);
+  spintet = *searchtet;
+  while (1) {
+    if (pd != dummypoint) {
+      ori = orient3d(pa, pb, pc, pd);
+      if ((ori != 0) && pinfected(pd)) {
+        ori = 0; // Force d be co-facet with abc.
+      }
+      if (ori > 0) {
+        break; // Found a lower point.
+      }
+    }
+    fnextself(spintet); // Go to the next face.
+    pd = apex(spintet);
+    if (pd == apex(*searchtet)) {
+      cofacetflag = true; break; // Not found.
+    }
+  }
+  if (!cofacetflag) {
+    // Search a tet whose apex->oppo crosses the facet containig abc.
+    while (1) {
+      pe = oppo(spintet);
+      if (pe != dummypoint) {
+        ori = orient3d(pa, pb, pc, pe);
+        if ((ori != 0) && pinfected(pe)) {
+          ori = 0; // Force pe be co-facet with abc.
+        }
+        if (ori < 0) {
+          break;  // stop at pd->pe.
+        }
+        if (ori == 0) {
+          cofacetflag = true; break; // Found a co-facet point.
+        }
+      }    
+      fnextself(spintet);
+    }
+    *searchtet = spintet;
+    // Now if "cofacetflag != true", searchtet contains a cross tet (abde), 
+    //   where d and e lie below and above abc, respectively, and 
+    //   orient3d(a, b, d, e) < 0.
+  }
+
+  if (cofacetflag) {
+    // There are co-facet points. Calculate a point above the subface.
+    facenormal(pa, pb, pc, n, 1);
+    len = sqrt(DOT(n, n));
+    n[0] /= len;
+    n[1] /= len;
+    n[2] /= len;
+    len = DIST(pa, pb);
+    len += DIST(pb, pc);
+    len += DIST(pc, pa);
+    len /= 3.0;
+    dummypoint[0] = pa[0] + len * n[0];
+    dummypoint[1] = pa[1] + len * n[1];
+    dummypoint[2] = pa[2] + len * n[2];
+    // Search a co-facet point d, s.t. (i) [a, b, d] intersects [a, b, c],
+    //   AND (ii) a, b, c, d has the closet circumradius of [a, b, c].
+    // NOTE: (ii) is needed since there may be several points satisfy (i).
+    circumsphere(pa, pb, pc, NULL, n, &r);
+    crossface.tet = NULL;
+    pe = apex(*searchtet);
+    spintet = *searchtet;
+    while (1) {
+      pd = apex(spintet);
+      if (pd != dummypoint) {
+        ori = orient3d(pa, pb, pc, pd);
+        if ((ori == 0) || pinfected(pd)) {
+          ori1 = orient3d(pa, pb, dummypoint, pd);
+          if (ori1 > 0) {
+            // [a, b, d] intersects with [a, b, c].
+            if (pinfected(pd)) {
+              len = DIST(n, pd);
+              dr = fabs(len - r);
+              if (crossface.tet == NULL) {
+                // This is the first cross face.
+                crossface = spintet;
+                drmin = dr;
+              } else {
+                if (dr < drmin) {
+                  crossface = spintet;
+                  drmin = dr;
+                }
+              }
+            } else {
+              assert(ori == 0); // SELF_CHECK
+              // Found a coplanar but not co-facet point (pd).
+              printf("Error:  Invalid PLC! A point and a subface intersect\n");
+              // get_origin_facet_corners(pssub, &pa, &pb, &pc);
+              printf("  Point %d. Subface (#%d) (%d, %d, %d)\n", 
+                pointmark(pd), getshellmark(*pssub), pointmark(pa), 
+                pointmark(pb), pointmark(pc));
+              terminatetetgen(1);
+            }
+          }
+        }
+      }
+      fnextself(spintet); // Go to the next face.
+      // assert(apex(spintet) != pe); // SELF_CHECK
+      if (apex(spintet) == pe) {
+        break;
+      }
+    }
+    if(crossface.tet == NULL) {
+      assert(crossface.tet != NULL); // Not handled yet.
+    }
+    *searchtet = crossface;
+    dummypoint[0] = dummypoint[1] = dummypoint[2] = 0;
+  }
+
+  if (cofacetflag) {
+    if (b->verbose > 1) {
+      printf("    Found a co-facet face (%d, %d, %d) op (%d).\n", 
+        pointmark(pa), pointmark(pb), pointmark(apex(*searchtet)), 
+        pointmark(oppo(*searchtet)));
+    }
+    if (facpoints != NULL) {
+      // Unmark all facet vertices.
+      for (i = 0; i < facpoints->objects; i++) {
+        pd = * (point *) fastlookup(facpoints, i);
+        puninfect(pd);
+      }
+    }
+    // Comment: Now no vertex is infected.
+    if (getpointtype(apex(*searchtet)) == VOLVERTEX) {
+      // A vertex lies on the facet.
+      enext2self(*searchtet); // org(*searchtet) == pd
+      return TOUCHFACE;
+    }
+    return ACROSSFACE;
+  } else {
+    // Return a crossing tet.
+    if (b->verbose > 1) {
+      printf("    Found a crossing tet (%d, %d, %d, %d).\n", pointmark(pa),
+        pointmark(pb), pointmark(apex(spintet)), pointmark(pe));
+    }
+    // Comment: if facpoints != NULL, co-facet vertices are stll infected.
+    //   They will be uninfected in formcavity();
+    return ACROSSTET; // abc intersects the volume of 'searchtet'.
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// recoversubfacebyflips()   Recover a subface by flips in the surface mesh. //
+//                                                                           //
+// A subface [a, b, c] ('pssub') intersects with a face [a, b, d] ('cross-   //
+// face'), where a, b, c, and d belong to the same facet.  It indicates that //
+// the face [a, b, d] should appear in the surface mesh.                     //
+//                                                                           //
+// This routine recovers [a, b, d] in the surface mesh through a sequence of //
+// 2-to-2 flips. No Steiner points is needed. 'pssub' returns [a, b, d].     //
+//                                                                           //
+// If 'facfaces' is not NULL, all flipped subfaces are queued for recovery.  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::recoversubfacebyflips(face* pssub, triface* crossface, 
+  arraypool *facfaces)
+{
+  triface neightet;
+  face flipfaces[2];
+  face checkseg;
+  point pa, pb, pc, pd, pe;
+  REAL ori, len, n[3];
+
+  tetrahedron ptr;
+  shellface sptr;
+  int tver;
+
+  // Get the missing subface is [a, b, c].
+  pa = sorg(*pssub);
+  pb = sdest(*pssub);
+  pc = sapex(*pssub);
+
+  // The crossface is [a, b, d, e].
+  // assert(org(*crossface) == pa);
+  // assert(dest(*crossface) == pb);
+  pd = apex(*crossface);
+  pe = dummypoint; // oppo(*crossface);
+
+  if (pe == dummypoint) {
+    // Calculate a point above the faces.
+    facenormal(pa, pb, pd, n, 1);
+    len = sqrt(DOT(n, n));
+    n[0] /= len;
+    n[1] /= len;
+    n[2] /= len;
+    len = DIST(pa, pb);
+    len += DIST(pb, pd);
+    len += DIST(pd, pa);
+    len /= 3.0;
+    pe[0] = pa[0] + len * n[0];
+    pe[1] = pa[1] + len * n[1];
+    pe[2] = pa[2] + len * n[2];
+  }
+
+  // Adjust face [a, b, c], so that edge [b, c] crosses edge [a, d].
+  ori = orient3d(pb, pc, pe, pd);
+  assert(ori != 0); // SELF_CHECK
+
+  if (ori > 0) {
+    // Swap a and b.
+    sesymself(*pssub);
+    symedgeself(*crossface);
+    pa = sorg(*pssub);
+    pb = sdest(*pssub);
+    if (pe == dummypoint) {
+      pe[0] = pe[1] = pe[2] = 0;
+    }
+    pe = dummypoint; // oppo(*crossface);
+  }
+
+  while (1) {
+
+    // Flip edge [b, c], edge [a, d] is missing.
+    senext(*pssub, flipfaces[0]);
+    sspivot(flipfaces[0], checkseg); // SELF_CHECK
+    assert(checkseg.sh == NULL); // SELF_CHECK
+    spivot(flipfaces[0], flipfaces[1]);
+
+    stpivot(flipfaces[1], neightet);
+    if (neightet.tet != NULL) {
+      // A recovered subface, clean sub<==>tet connections.
+      tsdissolve(neightet);
+      symself(neightet);
+      tsdissolve(neightet);
+      stdissolve(flipfaces[1]);
+    }
+
+    flip22(flipfaces, 0);
+
+    // Add them into list (make ensure that they must be recovered).
+    facfaces->newindex((void **) &pssub);
+    *pssub = flipfaces[0];
+    facfaces->newindex((void **) &pssub);
+    *pssub = flipfaces[1];
+
+    // Find the edge [a, b].
+    senext(flipfaces[1], *pssub);
+    assert(sorg(*pssub) == pa); // SELF_CHECK
+    assert(sdest(*pssub) == pb); // SELF_CHECK
+
+    pc = sapex(*pssub);
+    if (pc == pd) break;
+
+    if (pe == dummypoint) {
+      // Calculate a point above the faces.
+      facenormal(pa, pb, pd, n, 1);
+      len = sqrt(DOT(n, n));
+      n[0] /= len;
+      n[1] /= len;
+      n[2] /= len;
+      len = DIST(pa, pb);
+      len += DIST(pb, pd);
+      len += DIST(pd, pa);
+      len /= 3.0;
+      pe[0] = pa[0] + len * n[0];
+      pe[1] = pa[1] + len * n[1];
+      pe[2] = pa[2] + len * n[2];
+    }
+
+    while (1) {
+      ori = orient3d(pb, pc, pe, pd);
+      assert(ori != 0); // SELF_CHECK
+      if (ori > 0) {
+        senext2self(*pssub);
+        spivotself(*pssub);
+        if (sorg(*pssub) != pa) sesymself(*pssub);
+        pb = sdest(*pssub);
+        pc = sapex(*pssub);
+        continue;
+      }
+      break;
+    }
+  }
+
+  if (pe == dummypoint) {
+    pe[0] = pe[1] = pe[2] = 0;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// formcavity()    Form the cavity of a missing region.                      //
+//                                                                           //
+// A missing region R is a set of co-facet (co-palanr) subfaces. 'pssub' is  //
+// a missing subface [a, b, c]. 'crosstets' contains only one tet, [a, b, d, //
+// e], where d and e lie below and above [a, b, c], respectively.  Other     //
+// crossing tets are sought from this tet and saved in 'crosstets'.          //
+//                                                                           //
+// The cavity C is divided into two parts by R,one at top and one at bottom. //
+// 'topfaces' and 'botfaces' return the upper and lower boundary faces of C. //
+// 'toppoints' contains vertices of 'crosstets' in the top part of C, and so //
+// does 'botpoints'. Both 'toppoints' and 'botpoints' contain vertices of R. //
+//                                                                           //
+// NOTE: 'toppoints' may contain points which are not vertices of any top    //
+// faces, and so may 'botpoints'. Such points may belong to other facets and //
+// need to be present after the recovery of this cavity (P1029.poly).        //
+//                                                                           //
+// A pair of boundary faces: 'firsttopface' and 'firstbotface', are saved.   //
+// They share the same edge in the boundary of the missing region.           //
+//                                                                           //
+// 'facpoints' contains all vertices of the facet containing R.  They are    //
+// used for searching the crossing tets. On input all vertices are infected. //
+// They are uninfected after the cavity is formed.                           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::formcavity(face *pssub, arraypool* crosstets, 
+  arraypool* topfaces, arraypool* botfaces, arraypool* toppoints,
+  arraypool* botpoints, arraypool* facpoints)
+{
+  arraypool *crossedges;
+  triface *parytet, crosstet, spintet, neightet, faketet;
+  face neighsh, checksh;
+  face checkseg;
+  point pa, pb, pc, pf, pg;
+  point *ppt;
+  REAL ori;
+  int i, j;
+
+  int *iptr;
+
+  // Get the missing subface abc.
+  pa = sorg(*pssub);
+  pb = sdest(*pssub);
+  pc = sapex(*pssub);
+
+  // Comment: Now all facet vertices are infected.
+
+  // Get a crossing tet abde.
+  parytet = (triface *) fastlookup(crosstets, 0); // face abd.
+  // The edge de crosses the facet. d lies below abc.
+  enext2fnext(*parytet, crosstet);
+  enext2self(crosstet); 
+  esymself(crosstet); // the edge d->e at face [d,e,a]
+  infect(crosstet);
+  *parytet = crosstet; // Save it in list.
+
+  // Temporarily re-use 'topfaces'.
+  crossedges = topfaces;
+  crossedges->newindex((void **) &parytet);
+  *parytet = crosstet;
+
+  // Collect all crossing tets.  Each cross tet is saved in the standard
+  //   form deab, where de is a corrsing edge, orient3d(d,e,a,b) < 0. 
+  // NOTE: hull tets may be collected. See fig/dump-cavity-case2a(b).lua.
+  //   Make sure that neither d nor e is dummypoint.
+  for (i = 0; i < crossedges->objects; i++) {
+    crosstet = * (triface *) fastlookup(crossedges, i);
+    // It may already be tested.
+    if (!edgemarked(crosstet)) {
+      // Collect all tets sharing at the edge.
+      pg = apex(crosstet);
+      spintet = crosstet;
+      while (1) {
+        // Mark this edge as tested.
+        markedge(spintet);
+        if (!infected(spintet)) {
+          infect(spintet);
+          crosstets->newindex((void **) &parytet);
+          *parytet = spintet;
+        }
+        // Go to the neighbor tet.
+        fnextself(spintet);
+        // Check the validity of the PLC.
+        tspivot(spintet, checksh);
+        if (checksh.sh != NULL) {
+          printf("Error:  Invalid PLC! Two subfaces intersect.\n");
+          printf("  1st (#%4d): (%d, %d, %d)\n", getshellmark(*pssub),
+            pointmark(pa), pointmark(pb), pointmark(pc));
+          printf("  2nd (#%4d): (%d, %d, %d)\n", getshellmark(checksh),
+            pointmark(sorg(checksh)), pointmark(sdest(checksh)),
+            pointmark(sapex(checksh)));
+          terminatetetgen(1);
+        }
+        if (apex(spintet) == pg) break;
+      }
+      // Detect new cross edges.
+      while (1) {
+        // Remember: spintet is edge d->e, d lies below abc.
+        pf = apex(spintet);
+        if (pf != dummypoint) { // Do not grab a hull edge.
+          if (!pinfected(pf)) {
+            // There exist a crossing edge, either d->f, or f->e.
+            ori = orient3d(pa, pb, pc, pf);
+            if (ori == 0) {
+              printf("Error:  Invalid PLC! Point and subface intersect.\n");
+              printf("   Point %d, subface (#%4d): (%d, %d, %d)\n", 
+                pointmark(pf), getshellmark(*pssub), pointmark(pa), 
+                pointmark(pb), pointmark(pc));
+              terminatetetgen(1);
+            }
+            if (ori < 0) {
+              // The edge d->f corsses the facet.
+              enext2fnext(spintet, neightet);
+              esymself(neightet); // d->f.
+            } else {
+              // The edge f->e crosses the face.
+              enextfnext(spintet, neightet);
+              esymself(neightet); // f->e.
+            }
+            if (!edgemarked(neightet)) {
+              // Add a new cross edge.
+              crossedges->newindex((void **) &parytet);
+              *parytet = neightet;
+            }
+          }
+        }
+        fnextself(spintet);
+        if (apex(spintet) == pg) break;
+      }
+    }
+  }
+
+  // Unmark all facet vertices.
+  for (i = 0; i < facpoints->objects; i++) {
+    ppt = (point *) fastlookup(facpoints, i);
+    puninfect(*ppt);
+  }
+
+  // Comments: Now no vertex is marked. Next we will mark vertices which 
+  //   belong to the top and bottom boundary faces of the cavity and put
+  //   them in 'toppopints' and 'botpoints', respectively.
+
+  // All cross tets are found. Unmark cross edges.
+  for (i = 0; i < crossedges->objects; i++) {
+    crosstet = * (triface *) fastlookup(crossedges, i);
+    if (edgemarked(crosstet)) {
+      // Add the vertices of the cross edge [d, e] in lists. It must be
+      //   that d lies below the facet (i.e., its a bottom vertex).
+      //   Note that a cross edge contains no dummypoint.
+      pf = org(crosstet);
+      assert(pf != dummypoint); // SELF_CHECK
+      if (!pinfected(pf)) {
+        pinfect(pf);
+        botpoints->newindex((void **) &ppt); // Add a bottom vertex.
+        *ppt = pf;
+      }
+      pf = dest(crosstet);
+      assert(pf != dummypoint); // SELF_CHECK
+      if (!pinfected(pf)) {
+        pinfect(pf);
+        toppoints->newindex((void **) &ppt); // Add a top vertex.
+        *ppt = pf;
+      }
+      // Unmark this edge in all tets containing it.
+      pg = apex(crosstet);
+      spintet = crosstet;
+      while (1) {
+        assert(edgemarked(spintet)); // SELF_CHECK
+        unmarkedge(spintet);
+        fnextself(spintet); // Go to the neighbor tet.
+        if (apex(spintet) == pg) break;
+      }
+    }
+  }
+
+  if (b->verbose > 1) {
+    printf("    Formed cavity: %ld (%ld) cross tets (edges).\n", 
+      crosstets->objects, crossedges->objects);
+  }
+  crossedges->restart();
+
+  // Find a pair of cavity boundary faces from the top and bottom sides of
+  //   the facet each, and they share the same edge. Save them in the
+  //   global variables: firsttopface, firstbotface. They will be used in
+  //   fillcavity() for gluing top and bottom new tets.
+  for (i = 0; i < crosstets->objects; i++) {
+    crosstet = * (triface *) fastlookup(crosstets, i);
+    enextfnext(crosstet, spintet);
+    enextself(spintet);
+    symedge(spintet, neightet);
+    if (!infected(neightet)) {
+      // A top face.
+      firsttopface = neightet;
+    } else {
+      continue; // Go to the next cross tet.
+    }
+    enext2fnext(crosstet, spintet);
+    enext2self(spintet);
+    symedge(spintet, neightet);
+    if (!infected(neightet)) {
+      // A bottom face.
+      firstbotface = neightet;
+    } else {
+      continue;
+    }
+    break;
+  }
+  assert(i < crosstets->objects); // SELF_CHECK
+  
+  // Collect the top and bottom faces and the middle vertices. Since all top
+  //   and bottom vertices have been marked in above. Unmarked vertices are
+  //   middle vertices.
+  // NOTE 1: Hull tets may be collected. Process them as normal one.
+  //   (see fig/dump-cavity-case2.lua.)
+  // NOTE 2: Some previously recovered subfaces may be completely
+  //   contained in a cavity (see fig/dump-cavity-case6.lua). In such case,
+  //   we create two faked tets to hold this subface, one at each side.
+  //   The faked tets will be removed in fillcavity().
+  for (i = 0; i < crosstets->objects; i++) {
+    crosstet = * (triface *) fastlookup(crosstets, i);
+    enextfnext(crosstet, spintet);
+    enextself(spintet);
+    symedge(spintet, neightet);
+    if (!infected(neightet)) {
+      // A top face.
+      topfaces->newindex((void **) &parytet);
+      *parytet = neightet;
+    } else {
+      // Check if this side is a subface.
+      tspivot(spintet, neighsh);
+      if (neighsh.sh != NULL) {
+        // Found a subface (inside the cavity)!
+        maketetrahedron(&faketet);  // Create a faked tet.
+        setorg(faketet, org(spintet));
+        setdest(faketet, dest(spintet));
+        setapex(faketet, apex(spintet));
+        setoppo(faketet, NULL);
+        tsbond(faketet, neighsh); // Let it hold the subface.
+        // Add a top face (at faked tet).
+        topfaces->newindex((void **) &parytet);
+        *parytet = faketet;
+      }
+    }
+    enext2fnext(crosstet, spintet);
+    enext2self(spintet);
+    symedge(spintet, neightet);
+    if (!infected(neightet)) {
+      // A bottom face.
+      botfaces->newindex((void **) &parytet);
+      *parytet = neightet;
+    } else {
+      tspivot(spintet, neighsh);
+      if (neighsh.sh != NULL) {
+        // Found a subface (inside the cavity)!
+        maketetrahedron(&faketet);  // Create a faked tet.
+        setorg(faketet, org(spintet));
+        setdest(faketet, dest(spintet));
+        setapex(faketet, apex(spintet));
+        setoppo(faketet, NULL);
+        tsbond(faketet, neighsh); // Let it hold the subface.
+        // Add a bottom face (at faked tet).
+        botfaces->newindex((void **) &parytet);
+        *parytet = faketet;
+      }
+    }
+    // Add middle vertices if there are (skip dummypoint).
+    pf = org(neightet);
+    if (!pinfected(pf)) {
+      if (pf != dummypoint) {
+        pinfect(pf);
+        botpoints->newindex((void **) &ppt); // Add a bottom vertex.
+        *ppt = pf;
+        toppoints->newindex((void **) &ppt); // Add a top vertex.
+        *ppt = pf;
+      }
+    }
+    pf = dest(neightet);
+    if (!pinfected(pf)) {
+      if (pf != dummypoint) {
+        pinfect(pf);
+        botpoints->newindex((void **) &ppt); // Add a bottom vertex.
+        *ppt = pf;
+        toppoints->newindex((void **) &ppt); // Add a top vertex.
+        *ppt = pf;
+      }
+    }
+  }
+
+  // Unmark all collected top, bottom, and middle vertices.
+  for (i = 0; i < toppoints->objects; i++) {
+    ppt = (point *) fastlookup(toppoints, i);
+    puninfect(*ppt);
+  }
+  for (i = 0; i < botpoints->objects; i++) {
+    ppt = (point *) fastlookup(botpoints, i);
+    puninfect(*ppt);
+  }
+  // Comments: Now no vertex is marked.
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// formedgecavity()    Form the cavity of a missing edge.                    //
+//                                                                           //
+// The edge [a, b] intersects a set of tets in tetrahedralization T, will be //
+// collected in 'crosstets', it is empty on input. 'cavfaces' and 'cavpoints'//
+// return the sets of boundary faces, and vertices of the cavity, resp.      //
+//                                                                           //
+// Some subfaces may be inside this cavity, they are queued for recovery.    //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::formedgecavity(point pa, point pb, arraypool* crosstets,
+  arraypool* cavfaces, arraypool* cavpoints)
+{
+  triface searchtet, neightet, spintet, *parytet;
+  face firstcrosssh, checksh, *parysh;
+  point *ppt, pc, pd, pe, pf, *parypt;
+  enum intersection dir;
+  int types[2], poss[4];
+  int pos, i;
+
+  tetrahedron ptr;
+  int *iptr, tver;
+
+  // Search a tet whose origin is pa.
+  decode(point2tet(pa), searchtet);
+  assert(searchtet.tet != NULL); // SELF_CHECK
+  for (i = 4; i < 8; i++) {
+    if ((point) searchtet.tet[i] == pa) {
+      // Found. Set pa as its origin.
+      switch (i) {
+        case 4: searchtet.loc = 0; searchtet.ver = 0; break;
+        case 5: searchtet.loc = 0; searchtet.ver = 2; break;
+        case 6: searchtet.loc = 0; searchtet.ver = 4; break;
+        case 7: searchtet.loc = 1; searchtet.ver = 2; break;
+      }
+      break;
+    }
+  }
+  assert(i < 8); // SELF_CHECK
+
+  dir = finddirection(&searchtet, pb);
+  if (dir == ACROSSVERT) return; // The edge is not missing.
+
+  // if (b->verbose > 1) {
+    printf("    Form edge cavity (%d, %d).\n", pointmark(pa), pointmark(pb));
+  // }
+  // The possible cases are: ACROSSFACE and ACROSSEDGE.
+
+  // Go to the opposite (intersect) face.
+  enextfnextself(searchtet);
+  // Add this tet into list.
+  infect(searchtet);
+  crosstets->newindex((void **) &parytet);
+  *parytet = searchtet;
+  // Add all vertices of this tet into list.
+  ppt = (point *) &(searchtet.tet[4]);
+  for (i = 0; i < 4; i++) {
+    pinfect(ppt[i]);
+    cavpoints->newindex((void **) &parypt);
+    *parypt = ppt[i];
+  }
+
+  // There may be several subfaces be crossed by [a, b], remember the
+  //   first encountered one. 
+  firstcrosssh.sh = NULL; // Not found a crossing subface yet.
+
+  // Collect crossing tets of the edge [a, b].
+  while (1) {
+
+    // Enter the next crossing tet.
+    symedgeself(searchtet);
+    pf = oppo(searchtet);
+
+    if (dir == ACROSSFACE) {
+      if (!infected(searchtet)) { // Add this tet into list.
+        infect(searchtet);
+        crosstets->newindex((void **) &parytet);
+        *parytet = searchtet;
+      }
+      if (!pinfected(pf)) { // Add the opposite point into list.
+        pinfect(pf);
+        cavpoints->newindex((void **) &parypt);
+        *parypt = pf;
+      }
+      tspivot(searchtet, checksh); // Check if a subface is crossed.
+      if (checksh.sh != NULL) {
+        // Add this subface into list.
+        subfacstack->newindex((void **) &parysh);
+        *parysh = checksh;
+        if (firstcrosssh.sh == NULL) {
+          firstcrosssh = checksh;
+        }
+      }
+    } else { // dir == ACROSSEDGE
+      // Add all tets containing this edge into list.
+      pc = apex(searchtet);
+      spintet = searchtet;
+      while (1) {
+        fnextself(spintet);
+        if (!infected(spintet)) { // Add this tet into list.
+          infect(spintet);
+          crosstets->newindex((void **) &parytet);
+          *parytet = spintet;
+        }
+        pd = oppo(spintet);
+        if (!pinfected(pd)) { // Add the opposite point into list.
+          pinfect(pd);
+          cavpoints->newindex((void **) &parypt);
+          *parypt = pd;
+        }
+        tspivot(spintet, checksh); // Check if a subface is crossed.
+        if (checksh.sh != NULL) {
+          // Add this subface into list.
+          subfacstack->newindex((void **) &parysh);
+          *parysh = checksh;
+          if (firstcrosssh.sh == NULL) {
+            firstcrosssh = checksh;
+          }
+        }
+        if (apex(spintet) == pc) break;
+      }
+    }
+
+    // Stop if we reach the endpoint.
+    if (pf == pb) break;
+
+    // Search the next tet crossing by [a, b].
+    if (dir == ACROSSFACE) {
+      // One of the 3 opposite faces in 'searchtet' must intersect [a, b].
+      neightet.tet = searchtet.tet;
+      neightet.ver = 0;
+      for (i = 0; i < 3; i++) {
+        neightet.loc = locpivot[searchtet.loc][i];
+        pc = org(neightet);
+        pd = dest(neightet);
+        pe = apex(neightet);
+        pf = oppo(neightet); // The above point.
+        // Test if face [c, d, e] intersects edge [a, b]? Report their
+        //   intersection type ('level' = 1).
+        if (tri_edge_test(pc, pd, pe, pa, pb, pf, 1, types, poss)) {
+          dir = (enum intersection) types[0];
+          pos = poss[0];
+          break;
+        } else {
+          dir = DISJOINT;
+          pos = 0;
+        }
+      }
+      assert(dir != DISJOINT);  // SELF_CHECK
+    } else { // dir == ACROSSEDGE
+      // Find a face (or edge) intersecting with [a, b].
+      spintet = searchtet; // Backup the starting tet.
+      while (1) {
+        // Check the two opposite faces (of the edge) in 'searchtet'.
+        neightet.tet = searchtet.tet;
+        neightet.ver = 0;
+        for (i = 0; i < 2; i++) {
+          neightet.loc = locverpivot[searchtet.loc][searchtet.ver][i];
+          pc = org(neightet);
+          pd = dest(neightet);
+          pe = apex(neightet);
+          pf = oppo(neightet); // The above point.
+          // Test if face [c, d, e] intersects edge [a, b]? Report their
+          //   intersection type ('level' = 1).
+          if (tri_edge_test(pc, pd, pe, pa, pb, pf, 1, types, poss)) {
+            dir = (enum intersection) types[0];
+            pos = poss[0];
+            break;
+          } else {
+            dir = DISJOINT;
+            pos = 0;
+          }
+        }
+        if (dir == DISJOINT) {
+          // No intersection. Go to the next tet.
+          // dir = ACROSSEDGE;
+          fnextself(searchtet);
+          // We should NOT return to the starting tet.
+          assert(searchtet.tet != spintet.tet); // SELF_CHECK
+          continue; // Continue the search.
+        }
+        break; // Found!
+      } // while (1)
+    }
+
+    // Go to the intersect face or edge.
+    if (dir != ACROSSFACE) {
+      // 'dir' is either ACROSSFACE or ACROSSEDGE.
+      assert(dir == ACROSSEDGE); // SELF_CHECK
+      for (i = 0; i < pos; i++) {
+        enextself(neightet);
+      }
+    }
+    searchtet = neightet;
+
+  } // while (1)
+
+  if (b->verbose > 1) {
+    printf("    Formed edge cavity: %ld tets, %ld vertices.\n",
+      crosstets->objects, cavpoints->objects);
+  }
+
+  /*// All crossing tets are found (infected). We can form the cavity.
+  for (i = 0; i < crosstets->objects; i++) {
+    parytet = (triface *) fastlookup(crosstets, i);
+    searchtet = *parytet;
+    for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
+      sym(searchtet, neightet);
+      if (!infected(neightet)) {
+        // A bounday face.
+        cavfaces->newindex((void **) &parytet);
+        *parytet = neightet;
+      }
+    }
+  }*/
+
+  // We should find a subface which blocks the visibility between the two
+  //   endpoints of this edge.
+  assert(firstcrosssh.sh != NULL); // SELF_CHECK
+  // Remember this subface.
+  recentsh = firstcrosssh;
+
+  // Only for debugging.
+  for (i = 0; i < crosstets->objects; i++) {
+    parytet = (triface *) fastlookup(crosstets, i);
+    uninfect(*parytet);
+  }
+  for (i = 0; i < cavpoints->objects; i++) {
+    parypt = (point *) fastlookup(cavpoints, i);
+    puninfect(*parypt);
+  }
+  dump_facetof(&firstcrosssh, "facet2.lua");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// delaunizecavity()    Fill a cavity by Delaunay tetrahedra.                //
+//                                                                           //
+// The tetrahedralizing cavity is the half (top or bottom part) of the whole //
+// cavity.  The boundary faces of the half cavity are given in 'cavfaces',   //
+// the bounday faces of the internal facet are not given.  These faces will  //
+// be recovered later in fillcavity().                                       //
+//                                                                           //
+// This routine first constructs the DT of the vertices by the Bowyer-Watson //
+// algorithm.  Then it identifies the boundary faces of the cavity in DT.    //
+// The DT is returned in 'newtets'.                                          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenmesh::delaunizecavity(arraypool *cavpoints, arraypool *cavfaces, 
+  arraypool *cavshells, arraypool *newtets, arraypool *crosstets,
+  arraypool *misfaces)
+{
+  triface *parytet, searchtet, neightet, spintet, *parytet1;
+  face checksh, tmpsh, *parysh;
+  point pa, pb, pc, pd, pt[3], *parypt;
+  // badface *newflipface;
+  enum intersection dir;
+  REAL ori;
+  // int miscount;
+  int i, j;
+
+  tetrahedron ptr;
+  int *iptr, tver;
+
+  if (b->verbose > 1) {
+    printf("    Delaunizing cavity: %ld points, %ld faces.\n", 
+      cavpoints->objects, cavfaces->objects);
+  }
+
+  // Get four non-coplanar points (no dummypoint).
+  parytet = (triface *) fastlookup(cavfaces, 0);
+  pa = org(*parytet);
+  pb = dest(*parytet);
+  pc = apex(*parytet);
+  pinfect(pa);
+  pinfect(pb);
+  pinfect(pc);
+  pd = NULL;
+  for (i = 1; i < cavfaces->objects; i++) {
+    parytet = (triface *) fastlookup(cavfaces, i);
+    pt[0] = org(*parytet);
+    pt[1] = dest(*parytet);
+    pt[2] = apex(*parytet);
+    for (j = 0; j < 3; j++) {
+      if (pt[j] != dummypoint) { // Do not include a hull point.
+        if (!pinfected(pt[j])) {
+          ori = orient3d(pa, pb, pc, pt[j]);
+          if (ori != 0) {
+            pd = pt[j];
+            if (ori > 0) {  // Swap pa and pb.
+              pt[j] = pa; pa = pb; pb = pt[j]; 
+            }
+            break;
+          }
+        }
+      }
+    }
+    if (pd != NULL) break;
+  }
+  assert(i < cavfaces->objects); // SELF_CHECK
+  pinfect(pd);
+
+  // Create an init DT.
+  initialDT(pa, pb, pc, pd);
+
+  for (i = 0; i < cavpoints->objects; i++) {
+    pt[0] = * (point *) fastlookup(cavpoints, i);
+    assert(pt[0] != dummypoint); // SELF_CHECK
+    if (!pinfected(pt[0])) {
+      pinfect(pt[0]); // Mark it as inserted.
+      searchtet = recenttet;
+      insertvertex(pt[0], &searchtet, true, false, false, false);
+    } else {
+      // puninfect(pt[0]); // It is already inserted.
+    }
+  }
+  // Comment: All vertices of the cavity are marked.
+
+  while (1) {
+
+  // Indentify boundary faces. Mark interior tets. Save missing faces.
+  for (i = 0; i < cavfaces->objects; i++) {
+    parytet = (triface *) fastlookup(cavfaces, i);
+    // Skip an interior face (due to the enlargement of the cavity).
+    if (infected(*parytet)) continue;
+    // This face may contain dummypoint (See fig/dum-cavity-case2).
+    //   If so, dummypoint must be its apex.
+    parytet->ver = 4; 
+    pt[0] = org(*parytet);
+    pt[1] = dest(*parytet);
+    pt[2] = apex(*parytet);
+    // Create a temp subface.
+    makeshellface(subfacepool, &tmpsh);
+    setshvertices(tmpsh, pt[0], pt[1], pt[2]);
+    // Insert tmpsh in DT.
+    searchtet.tet = NULL; 
+    dir = scoutsubface(&tmpsh, &searchtet);
+    if (dir == SHAREFACE) {
+      // Identify the inter and outer tets at tempsh.
+      stpivot(tmpsh, neightet);
+      // neightet and tmpsh refer to the same edge [pt[0], pt[1]].
+      //   Moreover, neightet is in 0th edge ring (see decode()).
+      if (org(neightet) != pt[1]) {
+        symedgeself(neightet);
+        assert(org(neightet) == pt[1]); // SELF_CHECK
+        // Make sure that tmpsh is connected with an interior tet. 
+        tsbond(neightet, tmpsh);
+      }
+      assert(dest(neightet) == pt[0]); // SELF_CHECK
+      // Mark neightet as interior.
+      if (!infected(neightet)) {
+        infect(neightet);
+      }
+    } else if (dir == COLLISIONFACE) {
+      // A subface is already inserted (see fig/dum-cavity-case6).
+      assert(oppo(*parytet) == NULL); // It must be a faked tet.
+      // Searchtet's face collides it. Adjust to 0th edge ring.
+      if ((searchtet.ver & 01) != 0) esymself(searchtet);
+      // Let the subface remember its adjacent tet at its inside.
+      if (org(searchtet) != pt[1]) {
+        symedgeself(searchtet);
+        assert(org(searchtet) == pt[1]); // SELF_CHECK
+      }
+      assert(dest(searchtet) == pt[0]); // SELF_CHECK
+      tmpsh.sh[9] = (shellface) encode(searchtet);
+    } else {
+      if (b->verbose > 1) {
+        printf("  p:draw_subface(%d, %d, %d) -- %d is missing\n",
+          pointmark(pt[0]), pointmark(pt[1]), pointmark(pt[2]), i);
+      }
+      shellfacedealloc(subfacepool, tmpsh.sh);
+      // Save this face in list.
+      misfaces->newindex((void **) &parytet1);
+      *parytet1 = *parytet;
+      /*if (dir == EDGETRIINT) {
+        assert(0); // Face unmatched. Not process yet.
+      }
+      // Search an edge crossing this face.
+      dir = scoutcrosstet(&tmpsh, &searchtet, NULL);
+      assert(dir == ACROSSTET); // SELF_CHECK
+      // Save this pair of points.
+      newflipface = (badface *) flippool->alloc();
+      newflipface->forg = apex(searchtet);
+      newflipface->fdest = oppo(searchtet);
+      newflipface->nextitem = futureflip;
+      futureflip = newflipface;
+      // if (b->verbose > 1) {        
+        printf("  p:draw_subseg(%d, %d)\n", pointmark(newflipface->forg),
+          pointmark(newflipface->fdest));
+      // }
+      miscount++;*/
+      continue;
+    }
+    // Remember tmpsh (use the adjacent tet slot). 
+    // parytet->tet[parytet->loc] = (tetrahedron) sencode(tmpsh);
+    tmpsh.sh[0] = (shellface) encode(*parytet);
+    // Save this subface.
+    cavshells->newindex((void **) &parysh);
+    *parysh = tmpsh;
+  }
+
+  if (misfaces->objects > 0) {
+    // Removing tempoaray subfaces.
+    for (i = 0; i < cavshells->objects; i++) {
+      parysh = (face *) fastlookup(cavshells, i);
+      stpivot(*parysh, neightet);
+      uninfect(neightet);
+      tsdissolve(neightet); // Detach it from adj. tets.
+      symself(neightet);
+      tsdissolve(neightet);
+      shellfacedealloc(subfacepool, parysh->sh);
+    }
+    cavshells->restart();
+    // Enlarge the cavity.
+    for (i = 0; i < misfaces->objects; i++) {
+      // Get a missing face.
+      parytet = (triface *) fastlookup(misfaces, i);
+      // Check for a missing subface.
+      tspivot(*parytet, checksh);
+      if (checksh.sh != NULL) {
+        if (b->verbose > 1) {
+          printf("    Queue a subface x%lx (%d, %d, %d).\n", 
+            (unsigned long) checksh.sh, pointmark(sorg(checksh)),
+            pointmark(sdest(checksh)), pointmark(sapex(checksh)));
+        }
+        stdissolve(checksh);
+        subfacstack->newindex((void **) &parysh);
+        *parysh = checksh;
+      }
+      if (!infected(*parytet)) {
+        // Put it into crossing tet list.
+        infect(*parytet);
+        crosstets->newindex((void **) &parytet1);
+        *parytet1 = *parytet;
+        // Insert the opposite point if it is not in DT.
+        pd = oppo(*parytet);
+        if (!pinfected(pd)) {
+          if (b->verbose > 1) {
+            printf("    Insert the opposite point %d.\n", pointmark(pd));
+          }
+          pinfect(pd);
+          cavpoints->newindex((void **) &parypt);
+          *parypt = pd;
+          searchtet = recenttet;
+          insertvertex(pd, &searchtet, true, false, false, false);
+        }
+        // Add three opposite faces into the boundary list.
+        for (j = 0; j < 3; j++) {
+          enext0fnext(*parytet, neightet);
+          symself(neightet);
+          if (!infected(neightet)) {
+            if (b->verbose > 1) {
+              printf("    Add a cavface (%d, %d, %d).\n",
+                pointmark(org(neightet)), pointmark(dest(neightet)),
+                pointmark(apex(neightet)));
+            }
+            cavfaces->newindex((void **) &parytet1);
+            *parytet1 = neightet;
+          } else {
+            // Check if a subface is missing again.
+            tspivot(neightet, checksh);
+            if (checksh.sh != NULL) {
+              if (b->verbose > 1) {
+                printf("    Queue a subface x%lx (%d, %d, %d).\n", 
+                  (unsigned long) checksh.sh, pointmark(sorg(checksh)),
+                  pointmark(sdest(checksh)), pointmark(sapex(checksh)));
+              }
+              stdissolve(checksh);
+              subfacstack->newindex((void **) &parysh);
+              *parysh = checksh;
+            }
+          }
+          enextself(*parytet);
+        } // j
+      } // if (!infected(parytet))
+    }
+    misfaces->restart();
+    cavityexpcount++;
+    continue;
+  }
+
+  break;
+
+  } // while (1)
+
+  // Collect all tets of the DT. All new tets are marktested.
+  marktest(recenttet);
+  newtets->newindex((void **) &parytet);
+  *parytet = recenttet;
+  for (i = 0; i < newtets->objects; i++) {
+    searchtet = * (triface *) fastlookup(newtets, i);
+    for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
+      sym(searchtet, neightet);
+      if (!marktested(neightet)) {
+        marktest(neightet);
+        newtets->newindex((void **) &parytet);
+        *parytet = neightet;
+      }
+    }
+  }
+
+  // Uninfect all points of the DT.
+  for (i = 0; i < cavpoints->objects; i++) {
+    parypt = (point *) fastlookup(cavpoints, i);
+    puninfect(*parypt);
+  }
+  cavpoints->restart();
+  // Comment: Now no vertex is marked.
+  cavfaces->restart();
+
+  if (cavshells->objects > maxcavsize) {
+    maxcavsize = cavshells->objects;
+  }
+
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// fillcavity()    Fill new tets into the cavity.                            //
+//                                                                           //
+// The new tets are stored in two disjoint sets(which share the same facet). //
+// 'topfaces' and 'botfaces' are the boundaries of these two sets, respect-  //
+// ively. 'midfaces' is empty on input, and will store faces in the facet.   //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenmesh::fillcavity(arraypool* topshells, arraypool* botshells,
+  arraypool* midfaces, arraypool* facpoints)
+{
+  arraypool *cavshells;
+  triface *parytet, bdrytet, toptet, bottet, neightet, midface;
+  face checksh, *parysh;
+  face checkseg;
+  point pa, pb, pc, pf, pg;
+  REAL ori, len, n[3];
+  bool mflag, bflag;
+  int i, j, k;
+
+  tetrahedron ptr;
+  int *iptr, tver;
+
+  // Connect newtets to tets outside the cavity.
+  for (k = 0; k < 2; k++) {
+    cavshells = (k == 0 ? topshells : botshells);
+    for (i = 0; i < cavshells->objects; i++) {
+      // Get a temp subface.
+      parysh = (face *) fastlookup(cavshells, i);
+      // Get the boundary tet outsode the cavity.
+      decode(parysh->sh[0], bdrytet);
+      pa = org(bdrytet);
+      pb = dest(bdrytet);
+      pc = apex(bdrytet);
+      // Get the adjacent new tet.
+      stpivot(*parysh, neightet);
+      assert(org(neightet) == pb); // SELF_CHECK
+      assert(dest(neightet) == pa); // SELF_CHECK
+      if (oppo(bdrytet) != NULL) {
+        // Bond the two tets.
+        bond(bdrytet, neightet); // Also cleared the pointer to tmpsh.
+      }
+      // Bond a subface (if it exists).
+      tspivot(bdrytet, checksh);
+      if (checksh.sh != NULL) {
+        tsbond(neightet, checksh); // Also cleared the pointer to tmpsh.
+      } else {
+        tsdissolve(neightet); // No subface, clear the pointer to tmpsh.
+      }
+      // Update the point-to-tets map.
+      point2tet(pa) = encode(neightet);
+      point2tet(pb) = encode(neightet);
+      point2tet(pc) = encode(neightet);
+      // Delete the temp subface.
+      // shellfacedealloc(subfacepool, parysh->sh);
+      if (oppo(bdrytet) == NULL) {
+        // Delete a faked tet.
+        tetrahedrondealloc(bdrytet.tet);
+      }
+    }
+  }
+
+  // Mark all facet vertices for finding middle subfaces.
+  for (i = 0; i < facpoints->objects; i++) {
+    pf = * (point *) fastlookup(facpoints, i);
+    pinfect(pf);
+  }
+
+  mflag = true;  // Initialize it.
+
+  // The first pair of top and bottom tets share the same edge [a, b].
+  // toptet = * (triface *) fastlookup(topfaces, 0);
+  if (infected(firsttopface)) {
+    // The cavity was enlarged. This tet is included in the interior
+    //   (as those of a crossing tet). Find the updated top boundary face
+    //   by rotating the faces around this edge (until an uninfect tet).
+    pa = apex(firsttopface);
+    while (1) {
+      fnextself(firsttopface);
+      if (!infected(firsttopface)) break;
+      assert(apex(firsttopface) != pa); // SELF_CHECK
+    }
+  }
+  toptet = firsttopface;
+  symedgeself(toptet);
+  // Search a subface from the top mesh.
+  while (1) {
+    enext0fnextself(toptet); // The next face in the same tet.
+    pc = apex(toptet);
+    if (pinfected(pc)) break; // [a,b,c] is a subface.
+    symedgeself(toptet); // Go to the same face in the adjacent tet.
+  }
+  // Search the subface [a,b,c] in the bottom mesh.
+  // bottet = * (triface *) fastlookup(botfaces, 0);
+  if (infected(firstbotface)) {
+    pa = apex(firstbotface);
+    while (1) {
+      fnextself(firstbotface);
+      if (!infected(firstbotface)) break;
+      assert(apex(firstbotface) != pa); // SELF_CHECK
+    }
+  }
+  bottet = firstbotface;
+  symedgeself(bottet);
+  while (1) {
+    enext0fnextself(bottet); // The next face in the same tet.
+    pf = apex(bottet);
+    if (pf == pc) break; // Face matched.
+    if (pinfected(pf)) {
+      mflag = false; break; // Not matched.
+    }
+    symedgeself(bottet);
+  }
+  if (mflag) {
+    // Connect the two tets together.
+    bond(toptet, bottet);
+    // Both are interior tets.
+    infect(toptet);
+    infect(bottet);
+    // Add this face into search list.
+    esymself(toptet); // Choose the 0th edge ring.
+    markface(toptet);
+    midfaces->newindex((void **) &parytet);
+    *parytet = toptet;
+  }
+
+  // Match pairs of subfaces (middle faces), connect top and bottom tets.
+  for (i = 0; i < midfaces->objects && mflag; i++) {
+    // Get a matched middle face [a, b, c]
+    midface = * (triface *) fastlookup(midfaces, i);
+    // It is inside the cavity.
+    assert(marktested(midface)); // SELF_CHECK 
+    // Check the neighbors at edges [b, c] and [c, a].
+    for (j = 0; j < 2 && mflag; j++) {
+      enextself(midface); // [b, c] or [c, a].
+      pg = apex(midface);
+      toptet = midface;
+      bflag = false;
+      while (1) {
+        // Go to the next face in the same tet.
+        enext0fnextself(toptet);
+        pc = apex(toptet);
+        if (pinfected(pc)) {
+          break; // Find a subface.
+        }
+        if (pc == dummypoint) {
+          break; // Find a subface.
+        }
+        /* if (pc == pg) {
+          // The adjacent face is not a middle face.
+          bflag = true; break; 
+        }*/
+        // Go to the same face in the adjacent tet.
+        symedgeself(toptet);
+        // Do we walk outside the cavity? 
+        if (!marktested(toptet)) {
+          // Yes, the adjacent face is not a middle face.
+          bflag = true; break; 
+        }
+      }
+      if (!bflag) {
+        // assert(marktested(toptet)); // SELF_CHECK
+        if (!facemarked(toptet)) {
+          symedge(midface, bottet);
+          while (1) {
+            enext0fnextself(bottet);
+            pf = apex(bottet);
+            if (pf == pc) break; // Face matched.
+            if (pinfected(pf)) {
+              mflag = false; break; // Not matched
+            }
+            symedgeself(bottet);
+          }
+          if (mflag) {
+            if (marktested(bottet)) {
+              // Connect two tets together.
+              bond(toptet, bottet);
+              // Both are interior tets.
+              infect(toptet);
+              infect(bottet);
+              // Add this face into list.
+              esymself(toptet);
+              markface(toptet);
+              midfaces->newindex((void **) &parytet);
+              *parytet = toptet;
+            } else {
+              // The 'bottet' is not inside the cavity! 
+              // This case can happen when the cavity was enlarged, and the
+              //   'toptet' is a co-facet (sub)face adjacent to the missing
+              //   region, and it is a boundary face of the top cavity.
+              // So the toptet and bottet should be bonded already through
+              //   a temp subface. See fig/dump-cavity-case18. Check it.
+              symedge(toptet, neightet);
+              assert(neightet.tet == bottet.tet); // SELF_CHECK
+              assert(neightet.loc == bottet.loc); // SELF_CHECK
+              // Do not add this face into 'midfaces'.
+            }
+          }
+        }
+      }
+    } // j
+  } // i
+
+
+  if (mflag) {
+    if (b->verbose > 1) {
+      printf("    Found %ld middle subfaces.\n", midfaces->objects);
+    }
+    if (midfaces->objects > maxregionsize) {
+      maxregionsize = midfaces->objects;
+    }
+    // Unmark middle faces.
+    for (i = 0; i < midfaces->objects; i++) {
+      // Get a matched middle face [a, b, c]
+      midface = * (triface *) fastlookup(midfaces, i);
+      assert(facemarked(midface)); // SELF_CHECK
+      unmarkface(midface);
+    }
+    // Bond subsegments to new tets. 
+    // Comment: *** The following code does redundant job. Should be
+    //   re-placed in the future.
+    for (k = 0; k < 2; k++) {
+      cavshells = (k == 0 ? topshells : botshells);
+      for (i = 0; i < cavshells->objects; i++) {
+        parysh = (face *) fastlookup(cavshells, i);
+        decode(parysh->sh[0], bdrytet);
+        if (bdrytet.tet[4] != NULL) {
+          // Not a faked tet. Bond a subsegment (if it exists).
+          for (j = 0; j < 3; j++) {
+            tsspivot(bdrytet, checkseg);
+            if (checkseg.sh != NULL) {
+              symedge(bdrytet, neightet);
+              assert(marktested(neightet)); // SELF_CHECK
+              while (1) {
+                tssbond1(neightet, checkseg);
+                fnextself(neightet);
+                if (!marktested(neightet)) break;
+              }
+            }
+            enextself(bdrytet);
+          }
+        } else {
+          // A faked tet. There is an interior subface. Use it.
+          // See fig/dump-cavity-case19.
+          stpivot(*parysh, neightet);
+          assert(marktested(neightet)); // SELF_CHECK
+          tspivot(neightet, checksh);
+          assert(checksh.sh != NULL); // SELF_CHECK
+          assert(checksh.sh != parysh->sh); // // SELF_CHECK
+          // Align them at the same directed edge.
+          pa = org(neightet);
+          pb = dest(neightet);
+          for (j = 0; j < 3; j++) {
+            if (sorg(checksh) == pa) break;
+            senextself(checksh);
+          }
+          assert(j < 3); // SELF_CHECK
+          if (sdest(checksh) != pb) {
+            senext2self(checksh);
+            sesymself(checksh);
+          }
+          assert(sdest(checksh) == pb); // SELF_CHECK
+          // Bond a subsegment (if it exists).
+          for (j = 0; j < 3; j++) {
+            sspivot(checksh, checkseg);
+            if (checkseg.sh != NULL) {
+              toptet = neightet;
+              while (1) {
+                tssbond1(toptet, checkseg);
+                fnextself(toptet);
+                if (apex(toptet) == apex(neightet)) break;
+              }
+            }
+            senextself(checksh);
+            enextself(neightet);
+          }
+        }
+      }
+    }
+  } else {
+    // Faces at top and bottom are not matched. There exists non-Delaunay
+    //   subedges. See fig/dump-cavity-case5.lua. 
+    pa = org(toptet);
+    pb = dest(toptet);
+    pc = apex(toptet);
+    pf = apex(bottet);
+    if (b->verbose > 1) {
+      printf("  p:draw_tet(%d, %d, %d, %d) -- top tet.\n", pointmark(pa), 
+        pointmark(pb), pointmark(pc), pointmark(oppo(toptet)));
+      printf("  p:draw_tet(%d, %d, %d, %d) -- bot tet.\n", 
+        pointmark(org(bottet)), pointmark(dest(bottet)), 
+        pointmark(apex(bottet)), pointmark(oppo(bottet)));
+    }
+    // Calculate a point above the faces.
+    facenormal(pa, pb, pc, n, 1);
+    len = sqrt(DOT(n, n));
+    n[0] /= len;
+    n[1] /= len;
+    n[2] /= len;
+    len = DIST(pa, pb);
+    len += DIST(pb, pc);
+    len += DIST(pc, pa);
+    len /= 3.0;
+    dummypoint[0] = pa[0] + len * n[0];
+    dummypoint[1] = pa[1] + len * n[1];
+    dummypoint[2] = pa[2] + len * n[2];
+    // Find the crossing edges.
+    ori = orient3d(pb, pc, dummypoint, pf);
+    assert(ori != 0); // SELF_CHECK
+    if (ori < 0) {
+      // The top edge [b, c] intersects the bot edge [a, f].
+      enextself(toptet); 
+      enextself(bottet);
+    } else {
+      // The top edge [c, a] intersects the bot edge [f, b].
+      enext2self(toptet); 
+      enext2self(bottet); 
+    }
+    // Split one of the edges, choose the one has longer length.
+    n[0] = DIST(org(toptet), dest(toptet));
+    n[1] = DIST(org(bottet), dest(bottet));
+    if (n[0] > n[1]) {
+      pf = org(toptet);
+      pg = dest(toptet);
+    } else {
+      pf = org(bottet);
+      pg = dest(bottet);
+    }
+    if (b->verbose > 1) {
+      printf("  Found a non-Delaunay edge (%d, %d)\n", pointmark(pf), 
+        pointmark(pg));
+    }
+    // Create the midpoint of the non-Delaunay edge.
+    for (i = 0; i < 3; i++) {
+      dummypoint[i] = 0.5 * (pf[i] + pg[i]);
+    }
+    // Set a tet for searching the new point.
+    recenttet = firsttopface;
+    // dummypoint[0] = dummypoint[1] = dummypoint[2] = 0;
+    ndelaunayedgecount++;
+  }
+  // Unmark all facet vertices.
+  for (i = 0; i < facpoints->objects; i++) {
+    pf = * (point *) fastlookup(facpoints, i);
+    puninfect(pf);
+  }
+  // Delete the temp subfaces.
+  for (k = 0; k < 2; k++) {
+    cavshells = (k == 0 ? topshells : botshells);
+    for (i = 0; i < cavshells->objects; i++) {
+      parysh = (face *) fastlookup(cavshells, i);
+      shellfacedealloc(subfacepool, parysh->sh);
+    }
+  }
+  topshells->restart();
+  botshells->restart();
+  midfaces->restart();
+  // Comment: Now no vertex is marked.
+
+  return mflag;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// carvecavity()    Delete old tets and outer new tets of the cavity.        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::carvecavity(arraypool *crosstets, arraypool *topnewtets,
+  arraypool *botnewtets)
+{
+  arraypool *newtets;
+  triface *parytet, *pnewtet, neightet;
+  face checkseg, *parysh;
+  int i, j, k;
+
+  // NOTE: Some subsegments may contained inside the cavity. They must be
+  //   queued for recovery. See fig/dump-cavity-case20.
+  for (i = 0; i < crosstets->objects; i++) {
+    parytet = (triface *) fastlookup(crosstets, i);
+    assert(infected(*parytet)); // SELF_CHECK
+    if (parytet->tet[8] != NULL) {
+      for (j = 0; j < 6; j++) {
+        parytet->loc = edge2locver[j][0];
+        parytet->ver = edge2locver[j][1];
+        tsspivot(*parytet, checkseg);
+        if (checkseg.sh != NULL) {
+          if (!sinfected(checkseg)) {
+            // It is not queued yet.
+            neightet = *parytet;
+            while (1) {
+              fnextself(neightet);
+              if (!infected(neightet)) break;
+              if (apex(neightet) == apex(*parytet)) break;
+            }
+            if (infected(neightet)) {
+              if (b->verbose > 1) {
+                printf("    Queue a missing segment (%d, %d).\n",
+                  pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
+              }
+              sinfect(checkseg);
+              subsegstack->newindex((void **) &parysh);
+              *parysh = checkseg;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // Delete the old tets in cavity.
+  for (i = 0; i < crosstets->objects; i++) {
+    parytet = (triface *) fastlookup(crosstets, i);
+    tetrahedrondealloc(parytet->tet);
+  }
+  crosstets->restart(); // crosstets will be re-used.
+
+  // Collect infected new tets in cavity.
+  for (k = 0; k < 2; k++) {
+    newtets = (k == 0 ? topnewtets : botnewtets);
+    for (i = 0; i < newtets->objects; i++) {
+      parytet = (triface *) fastlookup(newtets, i);
+      if (infected(*parytet)) {
+        crosstets->newindex((void **) &pnewtet);
+        *pnewtet = *parytet;
+      }
+    }
+  }
+  // Collect all new tets in cavity.
+  for (i = 0; i < crosstets->objects; i++) {
+    parytet = (triface *) fastlookup(crosstets, i);
+    for (j = 0; j < 4; j++) {
+      decode(parytet->tet[j], neightet);
+      if (marktested(neightet)) { // Is it a new tet?
+        if (!infected(neightet)) {
+          // Find an interior tet.
+          assert((point) neightet.tet[7] != dummypoint); // SELF_CHECK
+          infect(neightet);
+          crosstets->newindex((void **) &pnewtet);
+          *pnewtet = neightet;
+        }
+      }
+    }
+  }
+
+  // Delete outer new tets.
+  for (k = 0; k < 2; k++) {
+    newtets = (k == 0 ? topnewtets : botnewtets);
+    for (i = 0; i < newtets->objects; i++) {
+      parytet = (triface *) fastlookup(newtets, i);
+      if (infected(*parytet)) {
+        // This is an interior tet.
+        uninfect(*parytet);
+        unmarktest(*parytet);
+      } else {
+        // An outer tet. Delete it.
+        tetrahedrondealloc(parytet->tet);
+      }
+    }
+  }
+
+  crosstets->restart();
+  topnewtets->restart();
+  botnewtets->restart();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// restorecavity()    Reconnect old tets and delete new tets of the cavity.  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::restorecavity(arraypool *crosstets, arraypool *topnewtets,
+  arraypool *botnewtets)
+{
+  triface *parytet, neightet;
+  face checksh;
+  point *ppt;
+  int i, j;
+
+  // Reconnect crossing tets to cavity boundary.
+  for (i = 0; i < crosstets->objects; i++) {
+    parytet = (triface *) fastlookup(crosstets, i);
+    assert(infected(*parytet)); // SELF_CHECK
+    parytet->ver = 0;
+    for (parytet->loc = 0; parytet->loc < 4; parytet->loc++) {
+      symedge(*parytet, neightet);
+      if (!infected(neightet)) {
+        bond(*parytet, neightet);
+        tspivot(*parytet, checksh);
+        if (checksh.sh != NULL) {
+          tsbond(*parytet, checksh);
+        }
+      }
+    }
+    // Update the point-to-tet map.
+    parytet->loc = 0;
+    ppt = (point *) &(parytet->tet[4]);
+    for (j = 0; j < 4; j++) {
+      point2tet(ppt[j]) = encode(*parytet);
+    }
+  }
+
+  // Uninfect all crossing tets.
+  for (i = 0; i < crosstets->objects; i++) {
+    parytet = (triface *) fastlookup(crosstets, i);
+    uninfect(*parytet);
+  }
+
+  // Delete new tets.
+  for (i = 0; i < topnewtets->objects; i++) {
+    parytet = (triface *) fastlookup(topnewtets, i);
+    tetrahedrondealloc(parytet->tet);
+  }
+
+  for (i = 0; i < botnewtets->objects; i++) {
+    parytet = (triface *) fastlookup(botnewtets, i);
+    tetrahedrondealloc(parytet->tet);
+  }
+
+  crosstets->restart();
+  topnewtets->restart();
+  botnewtets->restart();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// splitsubedge()    Split a non-Delaunay edge (not a segment) in the        //
+//                   surface mesh of a facet.                                //
+//                                                                           //
+// The new point 'newpt' will be inserted in the tetrahedral mesh if it does //
+// not cause any existing (sub)segments become non-Delaunay.  Otherwise, the //
+// new point is not inserted and one of such subsegments will be split.      //
+//                                                                           //
+// Next,the actual inserted new point is also inserted into the surface mesh.//
+// Non-Delaunay segments and newly created subfaces are queued for recovery. //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::splitsubedge(point newpt, face *searchsh, arraypool *facfaces,
+  arraypool *facpoints)
+{
+  triface searchtet;
+  face *psseg, sseg;
+  point pa, pb;
+  enum location loc;
+  int s, i;
+
+  // Try to insert the point. Do not insert if it will encroach any segment
+  //   (noencsegflag is TRUE). Queue encroacged subfaces.
+  assert(subsegstack->objects == 0l); // SELF_CHECK
+  searchtet = recenttet; // Start search it from recentet
+  loc = insertvertex(newpt, &searchtet, true, true, true, false);
+
+  if (loc == ENCSEGMENT) {
+    // Some segments are encroached. Randomly pick one to split.
+    assert(subsegstack->objects > 0l);
+    s = randomnation(subsegstack->objects);
+    psseg = (face *) fastlookup(subsegstack, s);
+    sseg = *psseg;
+    pa = sorg(sseg);
+    pb = sdest(sseg);
+    for (i = 0; i < 3; i++) newpt[i] = 0.5 * (pa[i] + pb[i]);
+    // Uninfect all queued segments.
+    for (i = 0; i < subsegstack->objects; i++) {
+      psseg = (face *) fastlookup(subsegstack, i);
+      suninfect(*psseg);
+    }
+    subsegstack->restart();  // Clear the queue.
+    // Split the segment. Two subsegments are queued.
+    sinsertvertex(newpt, searchsh, &sseg, true, false);
+    // Insert the point. Missing segments are queued. 
+    searchtet = recenttet; // Start search it from recentet
+    insertvertex(newpt, &searchtet, true, true, false, false);
+  } else {
+    // Calc an above point for point location in surface triangulation.
+    calculateabovepoint(facpoints, NULL, NULL, NULL); 
+    // Insert the new point on facet. New subfaces are queued for reocvery.
+    loc = sinsertvertex(newpt, searchsh, NULL, true, false);
+    if (loc == OUTSIDE) {
+      assert(0); // Not handled yet.
+    }
+    // Clear the above point.
+    dummypoint[0] = dummypoint[1] = dummypoint[2] = 0;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// constrainedfacets()    Recover subfaces saved in 'subfacestack'.          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::constrainedfacets()
+{
+  arraypool *crosstets, *topnewtets, *botnewtets;
+  arraypool *topfaces, *botfaces, *midfaces;
+  arraypool *topshells, *botshells, *facfaces;
+  arraypool *toppoints, *botpoints, *facpoints;
+  triface *parytet, searchtet, neightet;
+  face *pssub, ssub, neighsh;
+  face checkseg;
+  point *ppt, pt, newpt;
+  enum intersection dir;
+  bool success, delaunayflag;
+  long bakflip22count;
+  long cavitycount;
+  int facetcount;
+  int bakhullsize;
+  int s, i, j;
+
+  if (b->verbose) {
+    printf("  Constraining facets.\n");
+  }
+
+  // Initialize arrays.
+  crosstets = new arraypool(sizeof(triface), 10);
+  topnewtets = new arraypool(sizeof(triface), 10);
+  botnewtets = new arraypool(sizeof(triface), 10);
+  topfaces = new arraypool(sizeof(triface), 10);
+  botfaces = new arraypool(sizeof(triface), 10);
+  midfaces = new arraypool(sizeof(triface), 10);
+  toppoints = new arraypool(sizeof(point), 8);
+  botpoints = new arraypool(sizeof(point), 8);
+  facpoints = new arraypool(sizeof(point), 8);
+  facfaces = new arraypool(sizeof(face), 10);
+  topshells = new arraypool(sizeof(face), 10);
+  botshells = new arraypool(sizeof(face), 10);
+
+  bakflip22count = flip22count;
+  cavitycount = 0;
+  facetcount = 0;
+
+  // Loop until 'subfacstack' is empty.
+  while (subfacstack->objects > 0l) {
+    subfacstack->objects--;
+    pssub = (face *) fastlookup(subfacstack, subfacstack->objects);
+    ssub = *pssub;
+
+    if (ssub.sh[3] == NULL) continue; // Skip a dead subface.
+
+    stpivot(ssub, neightet);
+    if (neightet.tet == NULL) {
+      // Find an unrecovered subface.
+      smarktest(ssub);
+      facfaces->newindex((void **) &pssub);
+      *pssub = ssub;
+      // Get all subfaces and vertices of the same facet.
+      for (i = 0; i < facfaces->objects; i++) {
+        ssub = * (face *) fastlookup(facfaces, i);
+        for (j = 0; j < 3; j++) {
+          sspivot(ssub, checkseg);
+          if (checkseg.sh == NULL) {
+            spivot(ssub, neighsh);
+            assert(neighsh.sh != NULL); // SELF_CHECK
+            if (!smarktested(neighsh)) {
+              // It may be already recovered.
+              stpivot(neighsh, neightet);
+              if (neightet.tet == NULL) {
+                smarktest(neighsh);
+                facfaces->newindex((void **) &pssub);
+                *pssub = neighsh;
+              }
+            }
+          }
+          pt = sorg(ssub);
+          if (!pinfected(pt)) {
+            pinfect(pt);
+            facpoints->newindex((void **) &ppt);
+            *ppt = pt;
+          }
+          senextself(ssub);
+        } // j
+      } // i
+      // Have found all facet subfaces (vertices). Uninfect them.
+      for (i = 0; i < facfaces->objects; i++) {
+        pssub = (face *) fastlookup(facfaces, i);
+        sunmarktest(*pssub);
+      }
+      for (i = 0; i < facpoints->objects; i++) {
+        ppt = (point *) fastlookup(facpoints, i);
+        puninfect(*ppt);
+      }
+      if (b->verbose > 1) {
+        printf("  Recover facet #%d: %ld subfaces, %ld vertices.\n", 
+          facetcount + 1, facfaces->objects, facpoints->objects);
+      }
+      facetcount++;
+
+      // Loop until 'facfaces' is empty.
+      while (facfaces->objects > 0l) {
+        // Get the last subface of this array.
+        facfaces->objects--;
+        pssub = (face *) fastlookup(facfaces, facfaces->objects);
+        ssub = *pssub;
+
+        stpivot(ssub, neightet);
+        if (neightet.tet != NULL) continue; // Not a missing subface.
+
+        // Insert the subface.
+        searchtet.tet = NULL;
+        dir = scoutsubface(&ssub, &searchtet);
+        if (dir == SHAREFACE) continue; // The subface is inserted.
+        assert(dir != COLLISIONFACE); // SELF_CHECK
+
+        // Not exist. Push the subface back into stack.
+        s = randomnation(facfaces->objects + 1);
+        facfaces->newindex((void **) &pssub);
+        *pssub = * (face *) fastlookup(facfaces, s);
+        * (face *) fastlookup(facfaces, s) = ssub;
+
+        if (dir == EDGETRIINT) continue; // All three edges are missing.
+
+        // Search for a crossing tet.
+        dir = scoutcrosstet(&ssub, &searchtet, facpoints);
+
+        if (dir == ACROSSTET) {
+          // Recover subfaces by local retetrahedralization.
+          cavitycount++;
+          bakhullsize = hullsize;
+          checksubsegs = checksubfaces = 0;
+          crosstets->newindex((void **) &parytet);
+          *parytet = searchtet;
+          // Form a cavity of crossing tets.
+          formcavity(&ssub, crosstets, topfaces, botfaces, toppoints,
+            botpoints, facpoints);
+          delaunayflag = true;
+          // Tetrahedralize the top part. Re-use 'midfaces'.
+          success = delaunizecavity(toppoints, topfaces, topshells,
+            topnewtets, crosstets, midfaces);
+          if (success) {
+            // Tetrahedralize the bottom part. Re-use 'midfaces'.
+            success = delaunizecavity(botpoints, botfaces, botshells, 
+              botnewtets, crosstets, midfaces);
+            if (success) {
+              // Fill the cavity with new tets.
+              success = fillcavity(topshells, botshells, midfaces, facpoints);
+              if (success) {
+                // Delete old tets and outer new tets.
+                carvecavity(crosstets, topnewtets, botnewtets);
+              }
+            } else {
+              delaunayflag = false;
+            }
+          } else {
+            delaunayflag = false;
+          }
+          if (!success) {
+            // Restore old tets and delete new tets.
+            restorecavity(crosstets, topnewtets, botnewtets);
+          }
+          /*if (!delaunayflag) {
+            dump_facetof(&ssub, "facet1.lua");
+            while (futureflip != NULL) {
+              formedgecavity(futureflip->forg, futureflip->fdest, crosstets, 
+                topfaces, toppoints);
+              crosstets->restart();
+              topfaces->restart();
+              toppoints->restart();
+              futureflip = futureflip->nextitem;
+            }
+            flippool->restart();
+            outnodes(0);
+            checkmesh();
+            checkshells(1);
+            assert(0); // Stop the program.
+          }*/
+          hullsize = bakhullsize;
+          checksubsegs = checksubfaces = 1;
+        } else if (dir == ACROSSFACE) {
+          // Recover subfaces by flipping edges in surface mesh.
+          recoversubfacebyflips(&ssub, &searchtet, facfaces);
+          success = true;
+        } else { // dir == TOUCHFACE
+          assert(0);
+        }
+        if (!success) break;
+      } // while
+
+      if (facfaces->objects > 0l) {
+        // Found a non-Delaunay edge, split it (or a segment close to it).
+        // Create a new point at the middle of this edge, its coordinates
+        //   were saved in dummypoint in 'fillcavity()'.
+        makepoint(&newpt);
+        for (i = 0; i < 3; i++) newpt[i] = dummypoint[i];
+        setpointtype(newpt, STEINERVERTEX);
+        dummypoint[0] = dummypoint[1] = dummypoint[2] = 0;
+        // Insert the new point. Starting search it from 'ssub'.
+        splitsubedge(newpt, &ssub, facfaces, facpoints);
+        facfaces->restart();
+      }
+      // Clear the list of facet vertices.
+      facpoints->restart();
+
+      // Some subsegments may be queued, recover them.
+      if (subsegstack->objects > 0l) {
+        b->verbose--; // Suppress the message output.
+        delaunizesegments();
+        b->verbose++;
+      }
+      // Now the mesh should be constrained Delaunay.
+    } // if (neightet.tet == NULL) 
+  }
+
+  if (b->verbose) {
+    printf("  %ld subedge flips.\n", flip22count - bakflip22count);
+    printf("  %ld cavities remeshed.\n", cavitycount);
+  }
+
+  // Delete arrays.
+  delete crosstets;
+  delete topnewtets;
+  delete botnewtets;
+  delete topfaces;
+  delete botfaces;
+  delete midfaces;
+  delete toppoints;
+  delete botpoints;
+  delete facpoints;
+  delete facfaces;
+  delete topshells;
+  delete botshells;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// formskeleton()    Form a constrained tetrahedralization.                  //
+//                                                                           //
+// The segments and facets of a PLS will be recovered.                       //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::formskeleton()
+{
+  face *pssub, ssub;
+  REAL bakeps;
+  int s, i;
+
+  if (!b->quiet) {
+    printf("Recovering boundaries.\n");
+  }
+
+  // Bakup the epsilon.
+  bakeps = b->epsilon;
+  b->epsilon = 0;
+
+  // Put all segments into the list.
+  if (b->order == 4) {  // '-o4' option (for debug)
+    // The sequential order.
+    subsegpool->traversalinit();
+    for (i = 0; i < subsegpool->items; i++) {
+      ssub.sh = shellfacetraverse(subsegpool);
+      sinfect(ssub);  // Only save it once.
+      subsegstack->newindex((void **) &pssub);
+      *pssub = ssub;
+    }
+  } else {
+    // Randomly order the segments.
+    subsegpool->traversalinit();
+    for (i = 0; i < subsegpool->items; i++) {
+      s = randomnation(i + 1);
+      // Move the s-th seg to the i-th.
+      subsegstack->newindex((void **) &pssub);
+      *pssub = * (face *) fastlookup(subsegstack, s);
+      // Put i-th seg to be the s-th.
+      ssub.sh = shellfacetraverse(subsegpool);
+      sinfect(ssub);  // Only save it once.
+      pssub = (face *) fastlookup(subsegstack, s);
+      *pssub = ssub;
+    }
+  }
+
+  // Segments will be introduced.
+  checksubsegs = 1;
+  // Recover segments.
+  delaunizesegments();
+
+  // Randomly order the subfaces.
+  subfacepool->traversalinit();
+  for (i = 0; i < subfacepool->items; i++) {
+    s = randomnation(i + 1);
+    // Move the s-th subface to the i-th.
+    subfacstack->newindex((void **) &pssub);
+    *pssub = * (face *) fastlookup(subfacstack, s);
+    // Put i-th subface to be the s-th.
+    ssub.sh = shellfacetraverse(subfacepool);
+    pssub = (face *) fastlookup(subfacstack, s);
+    *pssub = ssub;
+  }
+
+  // Subfaces will be introduced.
+  checksubfaces = 1;
+  // Recover facets.
+  constrainedfacets();
+
+  // checksubsegs = 0;
+  b->epsilon = bakeps;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// carveholes()    Remove tetrahedra not in the mesh domain.                 //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::carveholes()
+{
+  arraypool *tetarray;
+  triface tetloop, neightet, hulltet, *parytet, *parytet1, fliptets[3];
+  triface openface, casface;
+  triface *regiontets;
+  face checksh, neighsh, flipshs[2];
+  face checkseg;
+  point *ppt, pa, pb, pc;
+  enum location loc;
+  REAL volume;
+  int attrnum, attr, maxattr;
+  int flatcount;
+  int i, j, k;
+
+  tetrahedron ptr;
+  int *iptr, tver;
+
+  if (!b->quiet) {
+    printf("Removing exterior tetrahedra.\n");
+  }
+
+  // Initialize the pool of exterior tets.
+  tetarray = new arraypool(sizeof(triface), 10);
+
+  maxattr = 0; // Choose a small number here.
+  attrnum = in->numberoftetrahedronattributes;
+
+  // Mark as infected any unprotected hull tets.
+  tetrahedronpool->traversalinit();
+  tetloop.loc = 0;
+  tetloop.tet = alltetrahedrontraverse();
+  while (tetloop.tet != (tetrahedron *) NULL) {
+    if ((point) tetloop.tet[7] == dummypoint) {
+      // Is this side protected by a subface?
+      tspivot(tetloop, checksh);
+      if (checksh.sh == NULL) {
+        infect(tetloop);
+        tetarray->newindex((void **) &parytet);
+        *parytet = tetloop;
+      }
+    }
+    tetloop.tet = alltetrahedrontraverse();
+  }
+
+  hullsize -= tetarray->objects;
+
+  if (in->numberofholes > 0) {
+    // Mark as infected any tets inside volume holes.
+    for (i = 0; i < 3 * in->numberofholes; i += 3) {
+      // Search a tet containing the i-th hole point.
+      neightet.tet = NULL;
+      randomsample(&(in->holelist[i]), &neightet);
+      loc = locate(&(in->holelist[i]), &neightet);
+      if (loc != OUTSIDE) {
+        infect(neightet);
+        tetarray->newindex((void **) &parytet);
+        *parytet = neightet;
+      }
+    }
+  }
+
+  if (b->regionattrib && (in->numberofregions > 0)) { // If has -A option.
+    // Record the tetrahedra that contains the region points for assigning
+    //   region attributes after the holes have been carved.
+    regiontets = new triface[in->numberofregions];
+    // Mark as marktested any tetrahedra inside volume regions.
+    for (i = 0; i < 5 * in->numberofregions; i += 5) {
+      // Search a tet containing the i-th hole point.
+      neightet.tet = NULL;
+      randomsample(&(in->regionlist[i]), &neightet);
+      loc = locate(&(in->regionlist[i]), &neightet);
+      if (loc != OUTSIDE) {
+        regiontets[i/5] = neightet;
+        if ((int) in->regionlist[i + 3] > maxattr) {
+          maxattr = (int) in->regionlist[i + 3];
+        }
+      } else {
+        if (b->verbose) {
+          printf("Warning:  The %d-th region point is in outside.\n", i/5+1);
+        }
+        regiontets[i/5].tet = NULL;
+      }
+    }
+  }
+
+  // Find and infect all exterior tets.
+  for (i = 0; i < tetarray->objects; i++) {
+    parytet = (triface *) fastlookup(tetarray, i);
+    tetloop = *parytet;
+    for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
+      symedge(tetloop, neightet);
+      // Is this side protected by a subface?
+      tspivot(tetloop, checksh);
+      if (checksh.sh == NULL) {
+        // Not protected. Infect it if it is not a hull tet.
+        if ((point) neightet.tet[7] != dummypoint) {
+          if (!infected(neightet)) {
+            infect(neightet);
+            tetarray->newindex((void **) &parytet);
+            *parytet = neightet;
+          }
+        }
+      } else {
+        // Its adjacent tet is protected.
+        if ((point) neightet.tet[7] == dummypoint) {
+          // A hull tet. It is dead.
+          assert(!infected(neightet));
+          infect(neightet);
+          tetarray->newindex((void **) &parytet);
+          *parytet = neightet;
+          // Both sides of this subface are exterior.
+          stdissolve(checksh);
+          hullsize--;
+        } else {
+          if (!infected(neightet)) {
+            // Let the subface connect to the "live" tet.
+            tsbond(neightet, checksh);
+          } else {
+            // Both sides of this subface are exterior.
+            stdissolve(checksh);
+          }
+        }
+      }
+    }
+  }
+
+  if (b->regionattrib && (in->numberofregions > 0)) {
+    // Re-check saved region tets to see if they lie outside.
+    for (i = 0; i < in->numberofregions; i++) {
+      if (infected(regiontets[i])) {
+        if (b->verbose) {
+          printf("Warning:  The %d-th region point is in outside.\n", i+1);
+        }
+        regiontets[i].tet = NULL;
+      }
+    }
+  }
+
+  // Remove all exterior tetrahedra (including infected hull tets).
+  for (i = 0; i < tetarray->objects; i++) {
+    parytet = (triface *) fastlookup(tetarray, i);
+    tetloop = *parytet;
+    for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
+      symedge(tetloop, neightet);
+      if (!infected(neightet)) {
+        // A "live" tet (may be a hull tet). Clear its adjacent tet.
+        neightet.tet[neightet.loc] = NULL;
+      }
+    }
+    tetrahedrondealloc(parytet->tet);
+  }
+
+  tetarray->restart(); // Re-use it for new hull tets.
+
+  // Create new hull faces and update the point-to-tet map.
+  tetrahedronpool->traversalinit();
+  tetloop.ver = 0;
+  tetloop.tet = tetrahedrontraverse();
+  while (tetloop.tet != (tetrahedron *) NULL) {
+    for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
+      if (tetloop.tet[tetloop.loc] == NULL) {
+        tspivot(tetloop, checksh);
+        assert(checksh.sh != NULL); // SELF_CHECK
+        // Create a new hull tet.
+        maketetrahedron(&hulltet);
+        pa = org(tetloop);
+        pb = dest(tetloop);
+        pc = apex(tetloop);
+        setvertices(hulltet, pb, pa, pc, dummypoint);
+        bond(tetloop, hulltet);
+        tsbond(hulltet, checksh);
+        // Save this hull tet in list.
+        tetarray->newindex((void **) &parytet);
+        *parytet = hulltet;
+      }
+    }
+    tetloop.loc = 0;
+    ptr = encode(tetloop);
+    ppt = (point *) tetloop.tet;
+    for (i = 4; i < 8; i++) {
+      point2tet(ppt[i]) = ptr;
+    }
+    tetloop.tet = tetrahedrontraverse();
+  }
+
+  // Update the hull size.
+  hullsize += tetarray->objects;
+
+  // Connect new hull tets.
+  for (i = 0; i < tetarray->objects; i++) {
+    parytet = (triface *) fastlookup(tetarray, i);
+    hulltet = *parytet;
+    assert(oppo(hulltet) == dummypoint); // SELF_CHECK
+    hulltet.ver = 0;
+    for (j = 0; j < 3; j++) {
+      enext0fnext(hulltet, neightet);
+      if (neightet.tet[neightet.loc] == NULL) {
+        esym(hulltet, casface);
+        while (1) {
+          symedgeself(casface);
+          enext0fnextself(casface);
+          if (apex(casface) == dummypoint) break;
+        }
+        bond(neightet, casface);
+      }
+      enextself(hulltet);
+    }
+  }
+
+  //////////////////////////////////////////////////////////////////////
+  // Peel off "flat" tetrahedra at boundary. 
+
+  tetarray->restart(); // Re-use this array.
+  flatcount = 0;
+
+  // Queue flat tets.
+  tetrahedronpool->traversalinit();
+  tetloop.ver = 0;
+  tetloop.tet = tetrahedrontraverse();
+  while (tetloop.tet != (tetrahedron *) NULL) {
+    // Does this tet contain subfaces?
+    if (tetloop.tet[9] != NULL) {
+      // Look at shared subface at its 6 edges.
+      for (i = 0; i < 6; i++) {
+        tetloop.loc = edge2locver[i][0];
+        tetloop.ver = edge2locver[i][1];
+        // Is this edge a segment?
+        tsspivot(tetloop, checkseg);
+        if (checkseg.sh == NULL) {
+          // No segment. Is this edge shared by two subfaces?
+          tspivot(tetloop, checksh);
+          if (checksh.sh != NULL) {
+            enext0fnext(tetloop, neightet);
+            tspivot(neightet, neighsh);
+            if (neighsh.sh != NULL) {
+              if (b->verbose > 1) {
+                ppt = (point *) &tetloop.tet[4];
+                printf("    p:draw_tet(%d, %d, %d, %d) -- flat\n",
+                  pointmark(ppt[0]), pointmark(ppt[1]), pointmark(ppt[2]),
+                  pointmark(ppt[3]));
+              }
+              tetarray->newindex((void **) &parytet);
+              *parytet = tetloop;
+              break;
+            } // neighsh.sh != NULL
+          } // checksh.sh != NULL
+        } // checkseg.sh != NULL
+      } // i
+    }
+    tetloop.tet = tetrahedrontraverse();
+  }
+
+  if (tetarray->objects > 0) {
+    if (b->verbose) {
+      printf("  Removing flat boundary tetrahedra.\n");
+    }
+  }
+
+  // Remove flat tets, new flat tets are queued.
+  for (i = 0; i < tetarray->objects; i++) {
+    parytet = (triface *) fastlookup(tetarray, i);
+    assert(parytet->tet[4] != NULL); // SELF_CHECK
+    sym(*parytet, neightet);
+    if ((point) neightet.tet[7] != dummypoint) {
+      continue; // An internal face. Can't be peeled off.
+    }
+
+    if (b->verbose > 1) {
+      printf("    i = %d.\n", i);
+    }
+
+    enext0fnext(*parytet, neightet);
+    pa = org(*parytet);
+    pb = dest(*parytet);
+    tspivot(*parytet, flipshs[0]); // [0] abc
+    for (j = 0; j < 3; j++) {
+      if (sorg(flipshs[0]) == pa) break;
+      senextself(flipshs[0]);
+    }
+    assert(j < 3); // SELF_CHECK
+    if (sdest(flipshs[0]) != pb) {
+      senext2self(flipshs[0]);
+      sesymself(flipshs[0]);
+    }
+    assert(sdest(flipshs[0]) == pb); // SELF_CHECK
+    tspivot(neightet, flipshs[1]); // [1] bda
+    for (j = 0; j < 3; j++) {
+      if (sorg(flipshs[1]) == pb) break;
+      senextself(flipshs[1]);
+    }
+    assert(j < 3); // SELF_CHECK
+    if (sdest(flipshs[1]) != pa) {
+      senext2self(flipshs[1]);
+      sesymself(flipshs[1]);
+    }
+    assert(sdest(flipshs[1]) == pa); // SELF_CHECK
+
+    // Detach abc and bad.
+    sym(*parytet, casface);
+    tsdissolve(*parytet);
+    tsdissolve(casface);
+    sym(neightet, casface);
+    tsdissolve(neightet);
+    tsdissolve(casface);
+
+    // flip [0]abc,[1]bad to [0]cdb, [1]dca
+    flip22(flipshs, 0);
+
+    for (k = 0; k < 2; k++) {
+      if (k == 0) {
+        // Insert flipshs[0] [c,d,b] to adjacent tets.
+        enextfnext(*parytet, neightet); // face [b,c,d].
+        enextself(neightet); // edge [c,d] in face [c,d,b].
+      } else {
+        // Insert flipshs[1] [d,c,a] to adjacent tets.
+        enext2fnext(*parytet, neightet); // face [c,a,d].
+        enext2self(neightet); // edge [d,c] in face [d,c,a].
+      }
+      symedge(neightet, casface);
+      assert((point) casface.tet[7] != dummypoint); // SELF_CHECK
+      tspivot(neightet, checksh); // SELF_CHECK
+      assert(checksh.sh == NULL); // SELF_CHECK
+      tsbond(neightet, flipshs[k]);
+      tsbond(casface, flipshs[k]);
+      // Check for new invalid tet(s) (at edge [d,b] and [b,c]).
+      for (j = 0; j < 2; j++) {
+        enextself(casface); // edges [d,b], [b,c].
+        tsspivot(casface, checkseg);
+        if (checkseg.sh == NULL) {
+          enext0fnext(casface, openface);
+          tspivot(openface, checksh);
+          if (checksh.sh != NULL) {
+            if (b->verbose > 1) {
+               ppt = (point *) &casface.tet[4];
+               printf("    p:draw_tet(%d, %d, %d, %d) -- flat\n",
+                 pointmark(ppt[0]), pointmark(ppt[1]), pointmark(ppt[2]),
+                 pointmark(ppt[3]));
+            }
+            tetarray->newindex((void **) &parytet1);
+            *parytet1 = casface;
+            break;
+          }
+        }
+      } // j
+    } // k
+
+    // Peel the flat boundary tet by a flip32.
+    fliptets[0] = *parytet;
+    fnext(fliptets[0], fliptets[1]);
+    fnext(fliptets[1], fliptets[2]);
+    assert(apex(fliptets[2]) == dummypoint); // SELF_CHECK
+    assert(oppo(fliptets[2]) == apex(fliptets[0])); // SELF_CHECK
+
+    // Flip the tets (with hull tets, do not propagate).
+    flip32(fliptets, 1, 0);
+    // Now the flat boundary tet is removed.
+    flatcount++;
+  } // i
+
+  if (tetarray->objects > 0) {
+    if (b->verbose) {
+      printf("  %d flat tets are removed.\n", flatcount);
+    }
+  }
+
+  /////////////////////////////////////////////////////////////////////////
+
+  // Set region attributes (when has -A and -AA options).
+  if (b->regionattrib) {
+
+    if (!b->quiet) {
+      printf("Spreading region attributes.\n");
+    }
+
+    // If has user-defined region attributes.
+    if (in->numberofregions > 0) {
+      // Spread region attributes.
+      for (i = 0; i < 5 * in->numberofregions; i += 5) {
+        if (regiontets[i/5].tet != NULL) {
+          attr = (int) in->regionlist[i + 3];
+          volume = in->regionlist[i + 4];
+          tetarray->restart(); // Re-use this array.
+          infect(regiontets[i/5]);
+          tetarray->newindex((void **) &parytet);
+          *parytet = regiontets[i/5];
+          // Collect and set attrs for all tets of this region.
+          for (j = 0; j < tetarray->objects; j++) {
+            parytet = (triface *) fastlookup(tetarray, j);
+            tetloop = *parytet;
+            setelemattribute(tetloop.tet, attrnum, attr);
+            if (b->varvolume) { // If has -a option.
+              setvolumebound(tetloop.tet, volume);
+            }
+            for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
+              sym(tetloop, neightet);
+              // Is this side protected by a subface?
+              tspivot(tetloop, checksh);
+              if (checksh.sh == NULL) {
+                // Not protected. It must not be a hull tet.
+                // assert((point) neightet.tet[7] != dummypoint);
+                if ((point) neightet.tet[7] == dummypoint) {
+                  assert(0);
+                }
+                if (!infected(neightet)) {
+                  infect(neightet);
+                  tetarray->newindex((void **) &parytet);
+                  *parytet = neightet;
+                }
+              } else {
+                // Protected. Set attribute for hull tet as well.
+                if ((point) neightet.tet[7] == dummypoint) {
+                  setelemattribute(neightet.tet, attrnum, attr);
+                  if (b->varvolume) { // If has -a option.
+                    setvolumebound(neightet.tet, volume);
+                  }
+                }
+              }
+            } // loc
+          } // j
+        }
+      } // i
+      delete [] regiontets;
+    }
+
+    if (b->regionattrib > 1) { // If has -AA option.
+      // Set attributes for all tetrahedra.
+      attr = maxattr + 1;
+      tetrahedronpool->traversalinit();
+      tetloop.tet = tetrahedrontraverse();
+      while (tetloop.tet != (tetrahedron *) NULL) {
+        if (!infected(tetloop)) {
+          // An unmarked region.
+          tetarray->restart(); // Re-use this array.
+          infect(tetloop);
+          tetarray->newindex((void **) &parytet);
+          *parytet = tetloop;
+          // Find and mark all tets.
+          for (j = 0; j < tetarray->objects; j++) {
+            parytet = (triface *) fastlookup(tetarray, j);
+            tetloop = *parytet;
+            setelemattribute(tetloop.tet, attrnum, attr);
+            for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
+              sym(tetloop, neightet);
+              // Is this side protected by a subface?
+              tspivot(tetloop, checksh);
+              if (checksh.sh == NULL) {
+                // Not protected. It must not be a hull tet.
+                assert((point) neightet.tet[7] != dummypoint);
+                if (!infected(neightet)) {
+                  infect(neightet);
+                  tetarray->newindex((void **) &parytet);
+                  *parytet = neightet;
+                }
+              } else {
+                // Protected. Set attribute for hull tet as well.
+                if ((point) neightet.tet[7] == dummypoint) {
+                  setelemattribute(neightet.tet, attrnum, attr);
+                }
+              }
+            } // loc
+          }
+          attr++; // Increase the attribute.
+        }
+        tetloop.tet = tetrahedrontraverse();
+      }
+      // Until here, every tet has a region attribute.
+    }
+
+    // Uninfect processed tets.
+    tetrahedronpool->traversalinit();
+    tetloop.tet = tetrahedrontraverse();
+    while (tetloop.tet != (tetrahedron *) NULL) {
+      uninfect(tetloop);
+      tetloop.tet = tetrahedrontraverse();
+    }
+
+    // Mesh elements contain region attributes now.
+    in->numberoftetrahedronattributes++;
+
+  } // if (b->regionattrib)
+
+  delete tetarray;
+}
+
+#endif // #ifndef constrainCXX
diff --git a/contrib/Tetgen/delaunay.cxx b/contrib/Tetgen/delaunay.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d97a0101e8b9387e356a2789ce69d7bdfeba71d6
--- /dev/null
+++ b/contrib/Tetgen/delaunay.cxx
@@ -0,0 +1,1398 @@
+#ifndef delaunayCXX
+#define delaunayCXX
+
+#include "tetgen.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// randomnation()    Generate a random number between 0 and 'choices' - 1.   //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+unsigned long tetgenmesh::randomnation(unsigned long choices)
+{
+  unsigned long newrandom;
+
+  if (choices >= 714025l) {
+    newrandom = (randomseed * 1366l + 150889l) % 714025l;
+    randomseed = (newrandom * 1366l + 150889l) % 714025l;
+    newrandom = newrandom * (choices / 714025l) + randomseed;
+    if (newrandom >= choices) {
+      return newrandom - choices;
+    } else {
+      return newrandom;
+    }
+  } else {
+    randomseed = (randomseed * 1366l + 150889l) % 714025l;
+    return randomseed % choices;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// randomsample()    Randomly sample the tetrahedra for point loation.       //
+//                                                                           //
+// This routine implements Muecke's Jump-and-walk point location algorithm.  //
+// It improves the simple walk-through by "jumping" to a good starting point //
+// via random sampling.  Searching begins from one of handles:  the input    //
+// 'searchtet', a recently encountered tetrahedron 'recenttet',  or from one //
+// chosen from a random sample.  The choice is made by determining which one //
+// 's origin is closest to the point we are searcing for.  Having chosen the //
+// starting tetrahedron, the simple Walk-through algorithm is executed.      //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::randomsample(point searchpt, triface *searchtet)
+{
+  tetrahedron *firsttet, *tetptr;
+  point torg;
+  void **sampleblock;
+  long sampleblocks, samplesperblock, samplenum;
+  unsigned long alignptr;
+  REAL searchdist, dist;
+  int tetblocks, i, j;
+
+  if ((searchtet->tet != NULL) && (searchtet->tet[4] != NULL)) {
+    // Get the distance from the suggested starting tet to the search point.
+    if ((point) searchtet->tet[7] != dummypoint) {
+      torg = org(*searchtet);
+    } else {
+      torg = (point) searchtet->tet[4];
+    }
+    searchdist = NORM2(searchpt[0] - torg[0], searchpt[1] - torg[1], 
+                       searchpt[2] - torg[2]);
+  } else {
+    searchdist = NORM2(xmax - xmin, ymax - ymin, zmax - zmin);
+  }
+
+  // If a recently encountered tetrahedron has been recorded and has not
+  //   been deallocated, test it as a good starting point.
+  if ((recenttet.tet != NULL) && (recenttet.tet[4] != NULL)) {
+    if ((point) recenttet.tet[7] != dummypoint) {
+      torg = org(recenttet);
+    } else {
+      torg = (point) recenttet.tet[4];
+    }
+    dist = NORM2(searchpt[0] - torg[0], searchpt[1] - torg[1],
+                 searchpt[2] - torg[2]);
+    if (dist <= searchdist) {
+      *searchtet = recenttet;
+      searchdist = dist;
+    }
+  }
+
+  // Select "good" candidate using k random samples, taking the closest one.
+  //   The number of random samples taken is proportional to the fourth root
+  //   of the number of tetrahedra in the mesh.
+  while (samples * samples * samples * samples < tetrahedronpool->items) {
+    samples++;
+  }
+  // Find how much blocks in current tet pool.
+  tetblocks = (tetrahedronpool->maxitems + ELEPERBLOCK - 1) / ELEPERBLOCK;
+  // Find the average samles per block. Each block at least have 1 sample.
+  samplesperblock = (samples + tetblocks - 1) / tetblocks;
+  sampleblocks = samples / samplesperblock;
+  sampleblock = tetrahedronpool->firstblock;
+  for (i = 0; i < sampleblocks; i++) {
+    alignptr = (unsigned long) (sampleblock + 1);
+    firsttet = (tetrahedron *)
+               (alignptr + (unsigned long) tetrahedronpool->alignbytes
+               - (alignptr % (unsigned long) tetrahedronpool->alignbytes));
+    for (j = 0; j < samplesperblock; j++) {
+      if (i == tetblocks - 1) {
+        // This is the last block.
+        samplenum = randomnation((int)
+                      (tetrahedronpool->maxitems - (i * ELEPERBLOCK)));
+      } else {
+        samplenum = randomnation(ELEPERBLOCK);
+      }
+      tetptr = (tetrahedron *)
+               (firsttet + (samplenum * tetrahedronpool->itemwords));
+      if (tetptr[4] != (tetrahedron) NULL) {
+        torg = (point) tetptr[4];
+        dist = NORM2(searchpt[0] - torg[0], searchpt[1] - torg[1],
+	             searchpt[2] - torg[2]);
+        if (dist < searchdist) {
+          searchtet->tet = tetptr;
+          searchtet->loc = 0;
+          searchtet->ver = 0;
+          searchdist = dist;
+        }
+      } else {
+        if (i != tetblocks - 1) j--;
+      }
+    }
+    sampleblock = (void **) *sampleblock;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// locate()    Find a simplex containing a given point.                      //
+//                                                                           //
+// This routine implements the simple Walk-through point location algorithm. //
+// Begins its search from 'searchtet', assume there is a line segment L from //
+// the origin of 'searchtet' to the query point 'searchpt', and simply walk  //
+// towards 'searchpt' by traversing all faces intersected by L.              //
+//                                                                           //
+// On completion, 'searchtet' is a tetrahedron that contains 'searchpt'. The //
+// returned value indicates one of the following cases:                      //
+//   - ONVERTEX, the search point lies on the origin of 'searchtet'.         //
+//   - ONEDGE, the search point lies on an edge of 'searchtet'.              //
+//   - ONFACE, the search point lies on a face of 'searchtet'.               //
+//   - INTET, the search point lies in the interior of 'searchtet'.          //
+//   - OUTSIDE, the search point lies outside the mesh. 'searchtet' is a     //
+//     hull tetrahedron whose base face is visible by the search point.      //
+//                                                                           //
+// WARNING: This routine is designed for convex triangulations, and will not //
+// generally work after the holes and concavities have been carved.          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+enum tetgenmesh::location tetgenmesh::locate(point searchpt,triface* searchtet)
+{
+  triface neightet;
+  point torg, tdest, tapex, toppo, ntoppo;
+  enum {ORGMOVE, DESTMOVE, APEXMOVE} nextmove;
+  REAL ori, oriorg, oridest, oriapex;
+  REAL searchdist, dist;
+
+  tetrahedron ptr;
+  int *iptr;
+
+  if ((point) searchtet->tet[7] == dummypoint) {
+    // A hull tet. Choose the neighbor of its base face.
+    searchtet->loc = 0;
+    symself(*searchtet);
+  } else {
+    // Stay in the 0th edge ring.
+    if (searchtet->ver & 01) esymself(*searchtet);
+  }
+  // Let searchtet be the face such that 'searchpt' lies above to it.
+  for (; ; searchtet->loc = (searchtet->loc + 1) % 4) { 
+    torg = org(*searchtet);
+    tdest = dest(*searchtet);
+    tapex = apex(*searchtet);
+    ori = orient3d(torg, tdest, tapex, searchpt); orient3dcount++;
+    if (ori < 0) {
+      // searchpt lies above searchtet's face.
+      break;
+    } else if (ori > 0) {
+      // searchpt lies below searchtet's face.
+      symself(*searchtet);
+      torg = org(*searchtet);
+      tdest = dest(*searchtet);
+      tapex = apex(*searchtet);
+      break;
+    }
+    // searchpt is coplanar with searchtet's face. Go to the next face.
+  }
+
+  // Walk through tetrahedra to locate the point.
+  while (true) {
+
+    ptloc_count++;  // Algorithimic count.
+
+    toppo = oppo(*searchtet);
+    
+    // Check if we have walked out of the domain.
+    if (toppo == dummypoint) {
+      return OUTSIDE;
+    }
+    
+    // Check if the vertex is we seek.
+    if (toppo == searchpt) {
+      // Adjust the origin of searchtet to be searchpt.
+      enext0fnextself(*searchtet);
+      esymself(*searchtet);
+      enext2self(*searchtet);
+      return ONVERTEX;
+    }
+
+    // We enter from serarchtet's base face. There are three other faces in
+    //   searchtet (all connecting to toppo), which one is the exit?
+    oriorg = orient3d(tdest, tapex, toppo, searchpt); 
+    oridest = orient3d(tapex, torg, toppo, searchpt);
+    oriapex = orient3d(torg, tdest, toppo, searchpt);
+    orient3dcount+=3;
+
+    // Now decide which face to move. It is possible there are more than one
+    //   faces are viable moves. Use the opposite points of thier neighbors
+    //   to discriminate, i.e., we choose the face whose opposite point has
+    //   the shortest distance to searchpt.
+    if (oriorg < 0) {
+      if (oridest < 0) {
+        if (oriapex < 0) {
+          // Any of the three faces is a viable move. 
+          nextmove = ORGMOVE;
+          enextfnext(*searchtet, neightet);
+          symself(neightet);
+          ntoppo = oppo(neightet);
+          if (ntoppo != dummypoint) {
+            searchdist = NORM2(searchpt[0] - ntoppo[0],
+                               searchpt[1] - ntoppo[1],
+                               searchpt[2] - ntoppo[2]);
+          } else {
+            searchdist = NORM2(xmax - xmin, ymax - ymin, zmax - zmin);
+          }
+          enext2fnext(*searchtet, neightet);
+          symself(neightet);
+          ntoppo = oppo(neightet);
+          if (ntoppo != dummypoint) {
+            dist = NORM2(searchpt[0] - ntoppo[0], searchpt[1] - ntoppo[1],
+                         searchpt[2] - ntoppo[2]);
+          } else {
+            dist = searchdist;
+          }
+          if (dist < searchdist) {
+            nextmove = DESTMOVE;
+            searchdist = dist;
+          }
+          enext0fnext(*searchtet, neightet);
+          symself(neightet);
+          ntoppo = oppo(neightet);
+          if (ntoppo != dummypoint) {
+            dist = NORM2(searchpt[0] - ntoppo[0], searchpt[1] - ntoppo[1],
+                         searchpt[2] - ntoppo[2]);
+          } else {
+            dist = searchdist;
+          }
+          if (dist < searchdist) {
+            nextmove = APEXMOVE;
+            searchdist = dist;
+          }
+        } else {
+          // Two faces, opposite to origin and destination, are viable.
+          nextmove = ORGMOVE;
+          enextfnext(*searchtet, neightet);
+          symself(neightet);
+          ntoppo = oppo(neightet);
+          if (ntoppo != dummypoint) {
+            searchdist = NORM2(searchpt[0] - ntoppo[0],
+                               searchpt[1] - ntoppo[1],
+                               searchpt[2] - ntoppo[2]);
+          } else {
+            searchdist = NORM2(xmax - xmin, ymax - ymin, zmax - zmin);
+          }
+          enext2fnext(*searchtet, neightet);
+          symself(neightet);
+          ntoppo = oppo(neightet);
+          if (ntoppo != dummypoint) {
+            dist = NORM2(searchpt[0] - ntoppo[0], searchpt[1] - ntoppo[1],
+                         searchpt[2] - ntoppo[2]);
+          } else {
+            dist = searchdist;
+          }
+          if (dist < searchdist) {
+            nextmove = DESTMOVE;
+            searchdist = dist;
+          }
+        }
+      } else {
+        if (oriapex < 0) {
+          // Two faces, opposite to origin and apex, are viable.
+          nextmove = ORGMOVE;
+          enextfnext(*searchtet, neightet);
+          symself(neightet);
+          ntoppo = oppo(neightet);
+          if (ntoppo != dummypoint) {
+            searchdist = NORM2(searchpt[0] - ntoppo[0],
+                               searchpt[1] - ntoppo[1],
+                               searchpt[2] - ntoppo[2]);
+          } else {
+            searchdist = NORM2(xmax - xmin, ymax - ymin, zmax - zmin);
+          }
+          enext0fnext(*searchtet, neightet);
+          symself(neightet);
+          ntoppo = oppo(neightet);
+          if (ntoppo != dummypoint) {
+            dist = NORM2(searchpt[0] - ntoppo[0], searchpt[1] - ntoppo[1],
+                         searchpt[2] - ntoppo[2]);
+          } else {
+            dist = searchdist;
+          }
+          if (dist < searchdist) {
+            nextmove = APEXMOVE;
+            searchdist = dist;
+          }
+        } else {
+          // Only the face opposite to origin is viable.
+          nextmove = ORGMOVE;
+        }
+      }
+    } else {
+      if (oridest < 0) {
+        if (oriapex < 0) {
+          // Two faces, opposite to destination and apex, are viable.
+          nextmove = DESTMOVE;
+          enext2fnext(*searchtet, neightet);
+          symself(neightet);
+          ntoppo = oppo(neightet);
+          if (ntoppo != dummypoint) {
+            searchdist = NORM2(searchpt[0] - ntoppo[0],
+                               searchpt[1] - ntoppo[1],
+                               searchpt[2] - ntoppo[2]);
+          } else {
+            searchdist = NORM2(xmax - xmin, ymax - ymin, zmax - zmin);
+          }
+          enext0fnext(*searchtet, neightet);
+          symself(neightet);
+          ntoppo = oppo(neightet);
+          if (ntoppo != dummypoint) {
+            dist = NORM2(searchpt[0] - ntoppo[0], searchpt[1] - ntoppo[1],
+                         searchpt[2] - ntoppo[2]);
+          } else {
+            dist = searchdist;
+          }
+          if (dist < searchdist) {
+            nextmove = APEXMOVE;
+            searchdist = dist;
+          }
+        } else {
+          // Only the face opposite to destination is viable.
+          nextmove = DESTMOVE;
+        }
+      } else {
+        if (oriapex < 0) {
+          // Only the face opposite to apex is viable.
+          nextmove = APEXMOVE;
+        } else {
+          // The point we seek must be on the boundary of or inside this
+          //   tetrahedron. Check for boundary cases.
+          if (oriorg == 0) {
+            // Go to the face opposite to origin.
+            enextfnextself(*searchtet);
+            if (oridest == 0) {
+              enextself(*searchtet); // edge apex->oppo
+              if (oriapex == 0) {
+                enextself(*searchtet); // oppo is duplicated with p.
+                return ONVERTEX;
+              }
+              return ONEDGE;
+            }
+            if (oriapex == 0) {
+              enext2self(*searchtet);
+              return ONEDGE;
+            }
+            return ONFACE;
+          }
+          if (oridest == 0) {
+            // Go to the face opposite to destination.
+            enext2fnextself(*searchtet);
+            if (oriapex == 0) {
+              enextself(*searchtet);
+              return ONEDGE;
+            }
+            return ONFACE;
+          }
+          if (oriapex == 0) {
+            // Go to the face opposite to apex
+            enext0fnextself(*searchtet);
+            return ONFACE;
+          }
+          return INTET;
+        }
+      }
+    }
+    
+    // Move to the selected face.
+    if (nextmove == ORGMOVE) {
+      enextfnextself(*searchtet);
+    } else if (nextmove == DESTMOVE) {
+      enext2fnextself(*searchtet);
+    } else {
+      enext0fnextself(*searchtet);
+    }
+    // Move to the adjacent tetrahedron (maybe a hull tetrahedron).
+    symself(*searchtet);
+    // Retreat the three vertices of the base face.
+    torg = org(*searchtet);
+    tdest = dest(*searchtet);
+    tapex = apex(*searchtet);
+
+  } // while (true)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// initialDT()    Create an initial Delaunay tetrahedralization.             //
+//                                                                           //
+// The tetrahedralization contains only one tetrahedron abcd, and four hull  //
+// tetrahedra.  The points pa, pb, pc, and pd must be linearly independent.  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::initialDT(point pa, point pb, point pc, point pd)
+{
+  triface firsttet, tetopa, tetopb, tetopc, tetopd;
+  triface worktet, worktet1;
+  int *iptr;
+
+  if (b->verbose > 1) {
+    printf("    Create init tet (%d, %d, %d, %d)\n", pointmark(pa),
+      pointmark(pb), pointmark(pc), pointmark(pd));
+  }
+
+  // Create the first tetrahedron.
+  maketetrahedron(&firsttet);
+  setvertices(firsttet, pa, pb, pc, pd);
+  // Create four hull tetrahedra.
+  maketetrahedron(&tetopa);
+  setvertices(tetopa, pb, pc, pd, dummypoint);
+  maketetrahedron(&tetopb);
+  setvertices(tetopb, pc, pa, pd, dummypoint);
+  maketetrahedron(&tetopc);
+  setvertices(tetopc, pa, pb, pd, dummypoint);
+  maketetrahedron(&tetopd);
+  setvertices(tetopd, pb, pa, pc, dummypoint);
+  hullsize += 4;
+
+  // Connect hull tetrahedra to firsttet (at four faces of firsttet).
+  bond(firsttet, tetopd); // ab
+  enext0fnext(firsttet, worktet);
+  bond(worktet, tetopc); // ab
+  enextfnext(firsttet, worktet);
+  bond(worktet, tetopa); // bc 
+  enext2fnext(firsttet, worktet);
+  bond(worktet, tetopb); // ca
+
+  // Connect hull tetrahedra together (at six edges of firsttet).
+  enext0fnext(tetopc, worktet); 
+  enext0fnext(tetopd, worktet1);
+  bond(worktet, worktet1); // ab
+  enext0fnext(tetopa, worktet);
+  enext2fnext(tetopd, worktet1);
+  bond(worktet, worktet1); // bc
+  enext0fnext(tetopb, worktet);
+  enextfnext(tetopd, worktet1);
+  bond(worktet, worktet1); // ca
+  enext2fnext(tetopc, worktet);
+  enextfnext(tetopb, worktet1);
+  bond(worktet, worktet1); // da
+  enext2fnext(tetopa, worktet);
+  enextfnext(tetopc, worktet1);
+  bond(worktet, worktet1); // db
+  enext2fnext(tetopb, worktet);
+  enextfnext(tetopa, worktet1);
+  bond(worktet, worktet1); // dc
+
+  // Set the vertex type.
+  if (getpointtype(pa) == UNUSEDVERTEX) {
+    setpointtype(pa, VOLVERTEX);
+  }
+  if (getpointtype(pb) == UNUSEDVERTEX) {
+    setpointtype(pb, VOLVERTEX);
+  }
+  if (getpointtype(pc) == UNUSEDVERTEX) {
+    setpointtype(pc, VOLVERTEX);
+  }
+  if (getpointtype(pd) == UNUSEDVERTEX) {
+    setpointtype(pd, VOLVERTEX);
+  }
+
+  // Update the point-to-tet map.
+  // if (checksubsegs || checksubfaces) {
+    point2tet(pa) = encode(firsttet);
+    point2tet(pb) = encode(firsttet);
+    point2tet(pc) = encode(firsttet);
+    point2tet(pd) = encode(firsttet);
+  // }
+
+  // Remember the first tetrahedron.
+  recenttet = firsttet;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// insertvertex()    Insert a point (p) into tetrahedralization (T).         //
+//                                                                           //
+// The point p will be first located in T. 'searchtet' is a suggested start- //
+// tetrahedron, it can be NULL. Note that p may lies outside T. In such case,//
+// the convex hull of T will be updated to include p as a vertex.            //
+//                                                                           //
+// If 'bwflag' is TRUE, the Bowyer-Watson algorithm is used to recover the   //
+// Delaunayness of T. Otherwise, do nothing with regard to the Delaunayness  //
+// T (T may be non-Delaunay after this function).                            //
+//                                                                           //
+// If 'visflag' is TRUE, force to check the visibility of the boundary faces //
+// of cavity. This is needed when T is not Delaunay.                         //
+//                                                                           //
+// If 'noencflag' is TRUE, only insert the new point p if it does not cause  //
+// any existing (sub)segment be non-Delaunay. This option only is checked    //
+// when the global variable 'checksubsegs' is set.                           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+enum tetgenmesh::location tetgenmesh::insertvertex(point insertpt, 
+  triface *searchtet, bool bwflag, bool visflag, bool noencsegflag,
+  bool noencsubflag)
+{
+  triface *cavetet, *parytet, spintet, neightet, newtet, neineitet;
+  face *pssub, checksh;
+  face *psseg, sseg;
+  point *pts, pa, pb, pc;
+  enum location loc;
+  REAL sign, ori;
+  long tetcount;
+  bool enqflag;
+  int i, j, k;
+
+  badface *newflip, *lastflip;  // for bowyerwatson
+  triface fliptets[5], baktets[2];
+
+  tetrahedron ptr;
+  int *iptr, tver;
+
+  arraypool *swaplist; // for updating cavity.
+  long updatecount;
+
+  // clock_t loc_start, loc_end;
+
+  if (b->verbose > 1) {
+    printf("    Insert point %d\n", pointmark(insertpt));
+  }
+
+  // loc_start = clock();
+
+  tetcount = ptloc_count;
+  updatecount = 0l;
+  
+  if (searchtet->tet == NULL) {
+    randomsample(insertpt, searchtet);
+  }
+  loc = locate(insertpt, searchtet);
+
+  // loc_end = clock();
+  // tloctime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
+
+  if (b->verbose > 1) {
+    printf("    Walk distance (# tets): %ld\n", ptloc_count - tetcount);
+  }
+
+  if (ptloc_max_count < (ptloc_count - tetcount)) {
+    ptloc_max_count = (ptloc_count - tetcount);
+  }
+
+  if (b->verbose > 1) {
+    printf("    Located (%d) tet (%d, %d, %d, %d).\n", (int) loc,
+      pointmark(org(*searchtet)), pointmark(dest(*searchtet)), 
+      pointmark(apex(*searchtet)), pointmark(oppo(*searchtet)));
+  }
+
+  if (loc == ONVERTEX) {
+    // The point already exists. Mark it and do nothing on it.
+    if (b->object != tetgenbehavior::STL) {
+      if (!b->quiet) {
+        printf("Warning:  Point #%d is duplicated with Point #%d. Ignored!\n",
+          pointmark(insertpt), pointmark(org(*searchtet)));
+      }
+    }
+    point2ppt(insertpt) = org(*searchtet);
+    setpointtype(insertpt, DUPLICATEDVERTEX);
+    dupverts++;
+    return loc;
+  }
+
+  // loc_start = clock();
+
+  tetcount = 0l;  // The number of deallocated tets.
+
+  // Create the initial boundary of the cavity.
+  if (loc == INTET || loc == OUTSIDE) {
+    // Add four adjacent boundary tets into list.
+    for (i = 0; i < 4; i++) {
+      decode(searchtet->tet[i], neightet);
+      cavetetlist->newindex((void **) &parytet);
+      *parytet = neightet;
+    }
+    if ((point) searchtet->tet[7] == dummypoint) hullsize--;
+    // tetrahedrondealloc(searchtet->tet);
+    infect(*searchtet);
+    caveoldtetlist->newindex((void **) &parytet);
+    *parytet = *searchtet;
+    tetcount = 1;
+    flip14count++;
+  } else if (loc == ONFACE) {
+    // Add six adjacent boundary tets into list.
+    for (i = 0; i < 3; i++) {
+      decode(searchtet->tet[locpivot[searchtet->loc][i]], neightet);
+      cavetetlist->newindex((void **) &parytet);
+      *parytet = neightet;
+    }
+    decode(searchtet->tet[searchtet->loc], spintet);
+    for (i = 0; i < 3; i++) {
+      decode(spintet.tet[locpivot[spintet.loc][i]], neightet);
+      cavetetlist->newindex((void **) &parytet);
+      *parytet = neightet;
+    }
+    if ((point) spintet.tet[7] == dummypoint) hullsize--;
+    if ((point) searchtet->tet[7] == dummypoint) hullsize--;
+    // tetrahedrondealloc(spintet.tet);
+    infect(spintet);
+    caveoldtetlist->newindex((void **) &parytet);
+    *parytet = spintet;
+    // tetrahedrondealloc(searchtet->tet);
+    infect(*searchtet);
+    caveoldtetlist->newindex((void **) &parytet);
+    *parytet = *searchtet;
+    tetcount = 2;
+    flip26count++;
+  } else if (loc == ONEDGE) {
+    // Add all adjacent boundary tets into list.
+    spintet = *searchtet;
+    tetcount = 0;
+    do {
+      fnextself(spintet);
+      tetcount++;
+      decode(spintet.tet[locverpivot[spintet.loc][spintet.ver][0]], neightet);
+      cavetetlist->newindex((void **) &parytet);
+      *parytet = neightet;
+      decode(spintet.tet[locverpivot[spintet.loc][spintet.ver][1]], neightet);
+      cavetetlist->newindex((void **) &parytet);
+      *parytet = neightet;
+    } while (spintet.tet != searchtet->tet);
+    // Delete old tets in the cavity.
+    spintet = *searchtet;
+    for (i = 0; i < tetcount; i++) {
+      fnext(spintet, neightet);
+      if ((point) spintet.tet[7] == dummypoint) hullsize--;
+      // tetrahedrondealloc(spintet.tet);
+      infect(spintet);
+      caveoldtetlist->newindex((void **) &parytet);
+      *parytet = spintet;
+      spintet = neightet;
+    }
+    flipn2ncount++;
+  }
+
+  // Form the cavity by including tets from initial boundary.
+  for (i = 0; i < cavetetlist->objects; i++) {
+    // 'cavetet' is actually an adjacent tet to the cavity.
+    cavetet = (triface *) fastlookup(cavetetlist, i);
+    // Do check if it is not infected (not deleted yet).
+    if (!infected(*cavetet)) { // if (cavetet->tet[4] != NULL) {
+      // Check for two possible cases for this tet: 
+      //   (1) It is a cavity tet, or
+      //   (2) it is a cavity boundary face.
+      // In case (1), the three other faces of this tet are added into
+      //   'cavetetlist' for later checking (we use a bread-first search),
+      //   and this tet gets deleted (infected).
+      enqflag = false;
+      if (!marktested(*cavetet)) {
+        pts = (point *) cavetet->tet;
+        if (pts[7] != dummypoint) {
+          // A volume tet. Operate on it if it has not been tested yet.
+          if (bwflag) {
+            // Use Bowyer-Watson algorithm, do Delaunay check.
+            sign = insphere_sos(pts[4], pts[5], pts[6], pts[7], insertpt);
+            enqflag = (sign < 0.0);
+          }
+        } else {
+          // It is a hull tet. Check if its base face is visible by p. 
+          //   This happens when p lies outside the hull face.
+          ori = orient3d(pts[4], pts[5], pts[6], insertpt); orient3dcount++;
+          enqflag = (ori < 0.0);
+          // Check if this face is coplanar with p. This case may create
+          //   a degenerate tet (zero volume). 
+          // Note: for convex domain, it can only happen at a hull face.
+          if (bwflag && (ori == 0.0)) {
+            newflip = (badface *) flippool->alloc();
+            newflip->tt = *cavetet; // Queue the adjacent tet (not in cavity).
+            newflip->tt.loc = 0; // Must be at the base face.
+            newflip->nextitem = NULL;
+            if (futureflip == NULL) {
+              lastflip = futureflip = newflip;
+            } else {
+              lastflip->nextitem = newflip;
+              lastflip = newflip;
+            }
+          }
+        } // if (pts[7] != dummypoint)
+        marktest(*cavetet); // Only test it once.
+      }
+      /*// Validation is needed when T is not a Delaunay triangulation. The
+      //   default cavity may not be star-shaped (fig/dump-cavity-case8).
+      if (visflag && !enqflag) {
+        if ((point) cavetet->tet[7] != dummypoint) {
+          // A non-hull cavity boundary face. Validate it.
+          cavetet->ver = 4;
+          pa = org(*cavetet);
+          pb = dest(*cavetet);
+          pc = apex(*cavetet);
+          ori = orient3d(pa, pb, pc, insertpt); orient3dcount++;
+          assert(ori != 0.0); // SELF_CHECK
+          enqflag = (ori < 0.0);
+          if (enqflag) {
+            updatecount++; // Cavity is updated.
+          }
+        }
+      }*/
+      if (enqflag) {
+        // Found a tet in the cavity. Put other three faces in check list.
+        for (j = 0; j < 3; j++) {
+          decode(cavetet->tet[locpivot[cavetet->loc][j]], neightet);
+          cavetetlist->newindex((void **) &parytet);
+          *parytet = neightet;
+        }
+        if ((point) cavetet->tet[7] == dummypoint) hullsize--;
+        // tetrahedrondealloc(cavetet->tet);
+        infect(*cavetet);
+        caveoldtetlist->newindex((void **) &parytet);
+        *parytet = *cavetet;
+        tetcount++;
+      } else {
+        // Found a boundary face of the cavity. It may be a face of a hull
+        //   tet which contains 'dummypoint'. Choose the edge in the face 
+        //   such that its endpoints are not 'dummypoint', while its apex
+        //   may be 'dummypoint' (see Fig. 1.4).
+        cavetet->ver = 4;
+        cavebdrylist->newindex((void **) &parytet);
+        *parytet = *cavetet;
+      }
+    } // if (cavetet->tet[4] != NULL)
+  }
+
+  if (b->verbose > 1) {
+    printf("    Size of the cavity: %d faces %d tets.\n",
+           cavebdrylist->objects, tetcount);
+  }
+
+  totaldeadtets += tetcount;
+  totalbowatcavsize += cavebdrylist->objects;
+  if (maxbowatcavsize < cavebdrylist->objects) {
+    maxbowatcavsize = cavebdrylist->objects;
+  }
+
+  if (checksubsegs || noencsegflag) {
+    // Check if some (sub)segments are inside the cavity.
+    for (i = 0; i < caveoldtetlist->objects; i++) {
+      cavetet = (triface *) fastlookup(caveoldtetlist, i);
+      for (j = 0; j < 6; j++) {
+        cavetet->loc = edge2locver[j][0];
+        cavetet->ver = edge2locver[j][1];
+        tsspivot(*cavetet, sseg);
+        if ((sseg.sh != NULL) && !sinfected(sseg)) {
+          // Check if this segment is inside the cavity.
+          spintet = *cavetet;
+          pa = apex(spintet);
+          enqflag = true;
+          while (1) {
+            fnextself(spintet);
+            if (!infected(spintet)) {
+              enqflag = false; break; // It is not inside.
+            }
+            if (apex(spintet) == pa) break;
+          }
+          if (enqflag) {
+            if (b->verbose > 1) {
+              printf("      Queue a missing segment (%d, %d).\n",
+                pointmark(sorg(sseg)), pointmark(sdest(sseg)));
+            }
+            sinfect(sseg);  // Only save it once.
+            subsegstack->newindex((void **) &psseg);
+            *psseg = sseg;
+          }
+        }
+      }
+    }
+  }
+
+  if (noencsegflag && (subsegstack->objects > 0)) {
+    // Found encroached subsegments! Do not insert this point.
+    for (i = 0; i < caveoldtetlist->objects; i++) {
+      cavetet = (triface *) fastlookup(caveoldtetlist, i);
+      uninfect(*cavetet);
+      unmarktest(*cavetet);
+    }
+    for (i = 0; i < cavebdrylist->objects; i++) {
+      cavetet = (triface *) fastlookup(cavebdrylist, i);
+      unmarktest(*cavetet); // Unmark it.
+    }
+    if (bwflag && (futureflip != NULL)) {
+      flippool->restart();
+      futureflip = NULL;
+    }
+    cavetetlist->restart();
+    cavebdrylist->restart();
+    caveoldtetlist->restart();
+    return ENCSEGMENT;
+  }
+
+  if (checksubfaces || noencsubflag) {
+    // Check if some subfaces are inside the cavity.
+    for (i = 0; i < caveoldtetlist->objects; i++) {
+      cavetet = (triface *) fastlookup(caveoldtetlist, i);
+      neightet.tet = cavetet->tet;
+      for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
+        tspivot(neightet, checksh);
+        if (checksh.sh != NULL) {
+          sym(neightet, neineitet);
+          // Do not check it if it is a hull tet.
+          if (infected(neineitet)) {
+            if (b->verbose > 1) {
+              printf("      Queue a missing subface (%d, %d, %d).\n",
+                pointmark(sorg(checksh)), pointmark(sdest(checksh)),
+                pointmark(sapex(checksh)));
+            }
+            tsdissolve(neineitet); // Disconnect a tet-sub bond.
+            stdissolve(checksh); // Disconnect the sub-tet bond.
+            // Add the missing subface into list.
+            subfacstack->newindex((void **) &pssub);
+            *pssub = checksh;
+          }
+        }
+      }
+    }
+  }
+
+  if (noencsubflag && (subfacstack->objects > 0)) {
+    // Found encroached subfaces! Do not insert this point.
+    for (i = 0; i < caveoldtetlist->objects; i++) {
+      cavetet = (triface *) fastlookup(caveoldtetlist, i);
+      uninfect(*cavetet);
+      unmarktest(*cavetet);
+    }
+    for (i = 0; i < cavebdrylist->objects; i++) {
+      cavetet = (triface *) fastlookup(cavebdrylist, i);
+      unmarktest(*cavetet); // Unmark it.
+    }
+    if (bwflag && (futureflip != NULL)) {
+      flippool->restart();
+      futureflip = NULL;
+    }
+    cavetetlist->restart();
+    cavebdrylist->restart();
+    caveoldtetlist->restart();
+    return ENCFACE;
+  }
+
+  if (visflag) {
+    // If T is not a Delaunay triangulation, the formed cavity may not be
+    //   star-shaped (fig/dump-cavity-case8). Validation is needed.
+    cavetetlist->restart(); // Re-use it.
+    for (i = 0; i < cavebdrylist->objects; i++) {
+      cavetet = (triface *) fastlookup(cavebdrylist, i);
+      // 'cavetet' is an exterior tet adjacent to the cavity.
+      assert(cavetet->ver == 4); // SELF_CHECK
+      symedge(*cavetet, neightet);
+      if (infected(neightet)) {
+        if ((point) cavetet->tet[7] != dummypoint) {
+          pa = org(*cavetet);
+          pb = dest(*cavetet);
+          pc = apex(*cavetet);
+          ori = orient3d(pa, pb, pc, insertpt); orient3dcount++;
+          assert(ori != 0.0); // SELF_CHECK
+          enqflag = (ori > 0.0);
+        } else {
+          enqflag = true; // A hull face.
+        }
+        if (enqflag) {
+          // This face is valid, save it.
+          cavetetlist->newindex((void **) &parytet);
+          *parytet = *cavetet; 
+        } else {
+          if (b->verbose > 1) {
+            printf("    Cut tet (%d, %d, %d, %d)\n", pointmark(pb), 
+              pointmark(pa), pointmark(pc), pointmark(oppo(neightet)));
+          }
+          uninfect(neightet);
+          unmarktest(neightet);
+          updatecount++;
+          // Add three new faces to find new boundaries.
+          for (j = 0; j < 3; j++) {
+            enext0fnext(neightet, neineitet);
+            neineitet.ver = 4;
+            cavebdrylist->newindex((void **) &parytet);
+            *parytet = neineitet;
+            enextself(neightet);
+          }
+        }
+      } else {
+        // This face is not on the cavity boundary anymore.
+        unmarktest(*cavetet);
+      }
+    }
+    if (updatecount > 0) {
+      // Update the cavity boundary faces (fig/dump-cavity-case9).
+      cavebdrylist->restart();
+      for (i = 0; i < cavetetlist->objects; i++) {
+        cavetet = (triface *) fastlookup(cavetetlist, i);
+        // 'cavetet' was an exterior tet adjacent to the cavity.
+        assert(cavetet->ver == 4); // SELF_CHECK
+        symedge(*cavetet, neightet);
+        if (infected(neightet)) {
+          // It is a cavity boundary face.
+          cavebdrylist->newindex((void **) &parytet);
+          *parytet = *cavetet;
+        } else {
+          // Not a cavity boundary face.
+          unmarktest(*cavetet);
+        }
+      }
+      // Update the list of old tets.
+      cavetetlist->restart();
+      for (i = 0; i < caveoldtetlist->objects; i++) {
+        cavetet = (triface *) fastlookup(caveoldtetlist, i);
+        if (infected(*cavetet)) {
+          cavetetlist->newindex((void **) &parytet);
+          *parytet = *cavetet;
+        }
+      }
+      assert(cavetetlist->objects < i);
+      // Swap 'cavetetlist' and 'caveoldtetlist'.
+      swaplist = caveoldtetlist;
+      caveoldtetlist = cavetetlist;
+      cavetetlist = swaplist;
+      if (b->verbose > 1) {
+        printf("    Size of the updated cavity: %d faces %d tets.\n",
+          cavebdrylist->objects, caveoldtetlist->objects);
+      }
+    }
+  }
+
+  // Re-use this list for new cavity faces.
+  cavetetlist->restart();
+
+  // Create new tetrahedra in the Bowyer-Watson cavity and Connect them.
+  for (i = 0; i < cavebdrylist->objects; i++) {
+    cavetet = (triface *) fastlookup(cavebdrylist, i);
+    neightet = *cavetet;
+    unmarktest(neightet); // Unmark it.
+    // Get the oldtet (inside the cavity).
+    symedge(neightet, neineitet);
+    if (apex(neightet) != dummypoint) {
+      // Create a new tet in the cavity (see Fig. bowyerwatson 1 or 3).
+      maketetrahedron(&newtet);
+      setorg(newtet, dest(neightet));
+      setdest(newtet, org(neightet));
+      setapex(newtet, apex(neightet));
+      setoppo(newtet, insertpt);
+    } else {
+      // Create a new hull tet (see Fig. bowyerwatson 2).
+      hullsize++;
+      maketetrahedron(&newtet);
+      setorg(newtet, org(neightet));
+      setdest(newtet, dest(neightet));
+      setapex(newtet, insertpt);
+      setoppo(newtet, dummypoint);
+      // Note: the cavity boundary face is at the enext0fnext place.
+      enext0fnextself(newtet);
+    }
+    // Connect newtet <==> neightet, this also disconnect the old bond.
+    bond(newtet, neightet);
+    // Let the oldtet knows newtet (for connecting adjacent new tets).
+    if (org(newtet) != org(neineitet)) esymself(newtet);
+    neineitet.tet[neineitet.loc] = encode(newtet);
+    // Replace the old boundary face with the old tet in list.
+    *cavetet = neineitet; // *cavetet = newtet;
+    if (checksubsegs) {
+      newtet.ver &= ~1;  // Keep in 0th edge ring.
+      for (j = 0; j < 3; j++) {
+        tsspivot(neightet, sseg);
+        if (sseg.sh != NULL) {
+          if (sinfected(sseg)) {
+            // This case is only possible when the cavity has been updated.
+            assert(updatecount > 0); // SELF_CHECK
+            suninfect(sseg); // Dequeue a non-missing segment.
+          }
+          tssbond1(newtet, sseg);
+        }
+        enextself(neightet);
+        enext2self(newtet);
+      }
+    }
+    if (checksubfaces) {
+      tspivot(neightet, checksh);
+      if (checksh.sh != NULL) {
+        tsbond(newtet, checksh); // Also disconnect the old bond.
+      }
+    }
+    if (updatecount > 0l) {
+      // Save this face for locally Delaunay test.
+      cavetetlist->newindex((void **) &parytet);
+      *parytet = newtet;
+    }
+  }
+
+  // Set a handle for speeding point location.
+  recenttet = newtet;
+  point2tet(insertpt) = encode(newtet);
+
+  /*// Connect the set of new tetrahedra together.
+  for (i = 0; i < cavebdrylist->objects; i++) {
+    cavetet = (triface *) fastlookup(cavebdrylist, i);
+    cavetet->ver = 0;
+    for (j = 0; j < 3; j++) {
+      enext0fnext(*cavetet, newtet); // Go to the face.
+      // Operate on it if it is open.
+      if (newtet.tet[newtet.loc] == NULL) {
+        // Find its adjacent face by rotating faces around the edge of
+        //   cavetet. The rotating direction is opposite to newtet.
+        //   Stop the rotate at a face which is open.
+        esym(*cavetet, neightet); // Set the rotate dir.
+        do {
+          fnextself(neightet); // Go to the face in the adjacent tet.
+        } while (neightet.tet[neightet.loc] != NULL);
+        bond(newtet, neightet); // Connect newtet <==> neightet.
+      }
+      if (checksubsegs || checksubfaces) {
+        point2tet(org(*cavetet)) = encode(*cavetet);
+      }
+      enextself(*cavetet);
+    }
+  }*/
+
+  // Connect adjacent new tetrahedra together.
+  for (i = 0; i < cavebdrylist->objects; i++) {
+    cavetet = (triface *) fastlookup(cavebdrylist, i);
+    decode(cavetet->tet[cavetet->loc], newtet);
+    // assert(org(newtet) == org(*cavetet)); // SELF_CHECK
+    for (j = 0; j < 3; j++) {
+      enext0fnext(newtet, neightet); // Go to the face.
+      if (neightet.tet[neightet.loc] == NULL) {
+        spintet = *cavetet;
+        while (1) {
+          enext0fnextself(spintet);
+          decode(spintet.tet[spintet.loc], neineitet);
+          if (!infected(neineitet)) break;
+          symedgeself(spintet);
+        }
+        // Find the corresponding edge in neineitet.
+        pa = dest(newtet);
+        for (k = 0; k < 3; k++) {
+          if (org(neineitet) == pa) break;
+          enextself(neineitet);
+        }
+        assert(k < 3);  // SELF_CHECK
+        assert(dest(neineitet) == org(newtet)); // SELF_CHECK
+        enext0fnextself(neineitet);
+        bond(neightet, neineitet);
+        // Queue the internal face if the visflag is set.
+        //   See also fig/dump-cavity-case13.
+        if (visflag) {
+          cavetetlist->newindex((void **) &parytet);
+          *parytet = neightet;
+        }
+      }
+      point2tet(org(newtet)) = encode(newtet);
+      enextself(newtet);
+      enextself(*cavetet);
+    }
+  }
+
+  // Delete the old cavity tets.
+  for (i = 0; i < caveoldtetlist->objects; i++) {
+    cavetet = (triface *) fastlookup(caveoldtetlist, i);
+    tetrahedrondealloc(cavetet->tet);
+  }
+
+  // loc_end = clock();
+  // tinserttime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
+
+  if (bwflag && (futureflip != NULL)) {
+    // There may exist degenerate tets. Check and remove them.
+    while (futureflip != NULL) {
+      // Dequeue an adjacent tet to the cavity.
+      fliptets[0] = futureflip->tt;
+      futureflip = futureflip->nextitem;
+
+      // Skip it if it is dead (by previous flip32s).
+      if (fliptets[0].tet[4] == NULL) continue;
+
+      // The possible degenerate tet, check it.
+      symself(fliptets[0]); 
+      // Skip it if its oppo is not 'p'. 
+      if (oppo(fliptets[0]) != insertpt) continue;
+      // This must be a new tet.
+      assert(oppo(fliptets[0]) == insertpt); // SELF_CHECK
+
+      pts = (point *) fliptets[0].tet;
+      ori = orient3d(pts[4], pts[5], pts[6], pts[7]); orient3dcount++;
+      
+      if (ori == 0) {
+        if (b->verbose > 1) {
+          printf("    Removing tet (%d, %d, %d, %d).\n", pointmark(pts[4]),
+            pointmark(pts[5]), pointmark(pts[6]), pointmark(pts[7]));
+        }
+        // Find the hull edge in cavetet.
+        fliptets[0].ver = 0;
+        for (j = 0; j < 3; j++) {
+          enext0fnext(fliptets[0], neightet);
+          symself(neightet);
+          if ((point) neightet.tet[7] == dummypoint) break;
+          enextself(fliptets[0]);
+        }
+        // Because of existing multiple degenerate cases. It is possible
+        //   that the other hull face is not pop yet.
+        if (j < 3) {
+          // Collect tets for flipping the edge.
+          for (j = 0; j < 3; j++) {
+            fnext(fliptets[j], fliptets[j + 1]);
+          }
+          if (fliptets[3].tet != fliptets[0].tet) {
+            printf("Internal error in insertvertex(): Unknown flip case.\n");
+            terminatetetgen(1);
+          }
+          // Do a 3-to-2 flip to remove the degenerate tet.
+          flip32(fliptets, 1, 0);
+          // Rememebr the new tet.
+          recenttet = fliptets[0];
+        } else {
+          // Put the face back into queue.
+          symself(fliptets[0]);
+          newflip = (badface *) flippool->alloc();
+          newflip->tt = fliptets[0]; // the adjacent tet (not in cavity).
+          newflip->nextitem = NULL;
+          if (futureflip == NULL) {
+            lastflip = futureflip = newflip;
+          } else {
+            lastflip->nextitem = newflip;
+            lastflip = newflip;
+          }
+        } // if (j < 3)
+      } // if (ori == 0)
+    }
+    flippool->restart();
+  }
+
+  if (bwflag && visflag) {
+    // Some new faces may be locally non-Delaunay. Check and fix them.
+    for (i = 0; i < cavetetlist->objects; i++) {
+      // Get a new face (whose opposite is p).
+      parytet = (triface *) fastlookup(cavetetlist, i);
+      if ((point) parytet->tet[7] == dummypoint) continue; // A hull face.
+      pa = oppo(*parytet);
+      futureflip = flippush(futureflip, parytet, pa);
+    }
+    // Recover Delaunay faces.
+    //   Set 'flipflag' = 2, s.t. all faces are checked for flipping.
+    lawsonflip3d(2);
+  }
+
+  // Set the point type.
+  if (getpointtype(insertpt) == UNUSEDVERTEX) {
+    setpointtype(insertpt, VOLVERTEX);
+  }
+
+  cavetetlist->restart();
+  cavebdrylist->restart();
+  caveoldtetlist->restart();
+  return loc;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flipinsertvertex()    Insert a vertex (p) into tetrahedralization (T).    //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::flipinsertvertex(point insertpt, triface* searchtet, 
+  int flipflag)
+{
+  enum location loc;
+  long tetcount;
+
+  if (b->verbose > 1) {
+    printf("    Insert point %d\n", pointmark(insertpt));
+  }
+
+  tetcount = ptloc_count;
+  
+  if (searchtet->tet == NULL) {
+    randomsample(insertpt, searchtet);
+  }
+  loc = locate(insertpt, searchtet);
+
+  if (b->verbose > 1) {
+    printf("    Walk distance (# tets): %ld\n", ptloc_count - tetcount);
+  }
+
+  if (ptloc_max_count < (ptloc_count - tetcount)) {
+    ptloc_max_count = (ptloc_count - tetcount);
+  }
+
+  if (b->verbose > 1) {
+    printf("    Located (%d) tet (%d, %d, %d, %d).\n", (int) loc,
+      pointmark(org(*searchtet)), pointmark(dest(*searchtet)), 
+      pointmark(apex(*searchtet)), pointmark(oppo(*searchtet)));
+  }
+  
+  if (loc == ONVERTEX) {
+    // The point already exists. Mark it and do nothing on it.
+    // In a STL mesh, duplicated points are implicitly included.
+    if (b->object != tetgenbehavior::STL) {
+      if (!b->quiet) {
+        printf("Warning:  Point #%d is duplicated with Point #%d. Ignored!\n",
+          pointmark(insertpt), pointmark(org(*searchtet)));
+      }
+    }
+    point2ppt(insertpt) = org(*searchtet);
+    setpointtype(insertpt, DUPLICATEDVERTEX);
+    dupverts++;
+    return;
+  }
+
+  // Clear flip stack.
+  futureflip = (badface *) NULL;
+
+  // Insert the new point by flipping.
+  if (loc == ONFACE) {
+    flip26(insertpt, searchtet, flipflag);
+  } else if (loc == ONEDGE) {
+    flipn2n(insertpt, searchtet, flipflag);
+  } else { // (loc == INTET) || (loc == OUTSIDE)
+    flip14(insertpt, searchtet, flipflag);
+  }
+
+  recenttet = *searchtet; // Remember a handle.
+
+  // Set the point type.
+  if (getpointtype(insertpt) == UNUSEDVERTEX) {
+    setpointtype(insertpt, VOLVERTEX);
+  }
+
+  // If flipflag > 0, do Delaunay flip.
+  if (flipflag > 0) {
+    lawsonflip3d(flipflag);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// incrementaldelaunay()    Form a Delaunay tetrahedralization by increment- //
+//                          ally inserting vertices.                         //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::incrementaldelaunay()
+{
+  triface searchtet;
+  point *permutarray, swapvertex;
+  REAL v1[3], v2[3], n[3];
+  REAL bboxsize, bboxsize2, bboxsize3, ori;
+  int randindex, i, j;
+
+  if (!b->quiet) {
+    printf("Delaunizing vertices.\n");
+  }
+
+  // Form a random permuation (uniformly at random) of the set of vertices.
+  permutarray = new point[in->numberofpoints];
+  pointpool->traversalinit();
+  if (b->order == 3) { // '-o3' option (for debug)
+    for (i = 0; i < in->numberofpoints; i++) {
+      permutarray[i] = (point) pointpool->traverse();
+    }
+  } else {
+    for (i = 0; i < in->numberofpoints; i++) {
+      randindex = randomnation(i + 1);
+      permutarray[i] = permutarray[randindex];
+      permutarray[randindex] = (point) pointpool->traverse();
+    }
+  }
+
+  // Calculate the diagonal size of its bounding box.
+  bboxsize = sqrt(NORM2(xmax - xmin, ymax - ymin, zmax - zmin));
+  bboxsize2 = bboxsize * bboxsize;
+  bboxsize3 = bboxsize2 * bboxsize;
+  
+  // Make sure the second vertex is not identical with the first one.
+  i = 1;
+  while ((DIST(permutarray[0], permutarray[i]) / bboxsize) < b->epsilon) {
+    i++;
+    if (i == in->numberofpoints - 1) {
+      printf("Exception:  All vertices are (nearly) identical (Tol = %g).\n",
+             b->epsilon);
+      terminatetetgen(1);
+    }
+  }
+  if (i > 1) {
+    // Swap to move the non-indetical vertex from index i to index 1.
+    swapvertex = permutarray[i];
+    permutarray[i] = permutarray[1];
+    permutarray[1] = swapvertex;
+  }
+
+  // Make sure the third vertex is not collinear with the first two.
+  i = 2;
+  for (j = 0; j < 3; j++) {
+    v1[j] = permutarray[1][j] - permutarray[0][j];
+    v2[j] = permutarray[i][j] - permutarray[0][j];
+  }
+  CROSS(v1, v2, n);
+  while ((sqrt(NORM2(n[0], n[1], n[2])) / bboxsize2) < b->epsilon) {
+    i++;
+    if (i == in->numberofpoints - 1) {
+      printf("Exception:  All vertices are (nearly) collinear (Tol = %g).\n",
+             b->epsilon);
+      terminatetetgen(1);
+    }
+    for (j = 0; j < 3; j++) {
+      v2[j] = permutarray[i][j] - permutarray[0][j];
+    }
+    CROSS(v1, v2, n);
+  }
+  if (i > 2) {
+    // Swap to move the non-indetical vertex from index i to index 1.
+    swapvertex = permutarray[i];
+    permutarray[i] = permutarray[2];
+    permutarray[2] = swapvertex;
+  }
+
+  // Make sure the fourth vertex is not coplanar with the first three.
+  i = 3;
+  ori = orient3d(permutarray[0], permutarray[1], permutarray[2], 
+                 permutarray[i]);
+  while ((fabs(ori) / bboxsize3) < b->epsilon) {
+    i++;
+    if (i == in->numberofpoints) {
+      printf("Exception:  All vertices are coplanar (Tol = %g).\n",
+             b->epsilon);
+      terminatetetgen(1);
+    }
+    ori = orient3d(permutarray[0], permutarray[1], permutarray[2], 
+                   permutarray[i]);
+  }
+  if (i > 3) {
+    // Swap to move the non-indetical vertex from index i to index 1.
+    swapvertex = permutarray[i];
+    permutarray[i] = permutarray[3];
+    permutarray[3] = swapvertex;
+  }
+
+  // Orient the first four vertices in permutarray so that they follow the
+  //   right-hand rule.
+  if (ori > 0.0) {
+    // Swap the first two vertices.
+    swapvertex = permutarray[0];
+    permutarray[0] = permutarray[1];
+    permutarray[1] = swapvertex;
+  }
+
+  // Create the initial Delaunay tetrahedralization.
+  initialDT(permutarray[0], permutarray[1], permutarray[2], permutarray[3]);
+
+  if (b->verbose) {
+    printf("  Incremental inserting vertices.\n");
+  }
+
+  if (b->bowyerwatson) {
+    // Use incremental Bowyer-Watson algorithm.
+    for (i = 4; i < in->numberofpoints; i++) {
+      if (b->verbose > 1) printf("    #%d", i);
+      searchtet.tet = NULL;  // Randomly sample tetrahedra.
+      insertvertex(permutarray[i], &searchtet, true, false, false, false);
+    }
+  } else {
+    // Use incremental flip algorithm.
+    for (i = 4; i < in->numberofpoints; i++) {
+      if (b->verbose > 1) printf("    #%d", i);
+      searchtet.tet = NULL;  // Randomly sample tetrahedra.
+      flipinsertvertex(permutarray[i], &searchtet, 1); 
+    }
+  }
+
+  delete [] permutarray;
+}
+
+#endif // #ifndef delaunayCXX
\ No newline at end of file
diff --git a/contrib/Tetgen/flip.cxx b/contrib/Tetgen/flip.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..12b0ba76c15c49c4df0e35bf9c0018049feadc47
--- /dev/null
+++ b/contrib/Tetgen/flip.cxx
@@ -0,0 +1,2043 @@
+#ifndef flipCXX
+#define flipCXX
+
+#include "tetgen.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flipshpush()    Push a subface edge into flip stack.                      //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+tetgenmesh::badface* tetgenmesh::flipshpush(badface* flipstack, face* flipedge)
+{
+  badface *newflipface;
+
+  newflipface = (badface *) flippool->alloc();
+  newflipface->ss = *flipedge;
+  newflipface->forg = sorg(*flipedge);
+  newflipface->fdest = sdest(*flipedge);
+  newflipface->nextitem = flipstack;
+
+  return newflipface;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flip13()    Insert a vertex by transforming 1-to-3 subfaces.              //
+//                                                                           //
+// 'newpt' (p) lies in the interior of 'splitface' (abc).  This routine del- //
+// ete abc and replaces it by three subfaces: abp, bcp, and cap, respective- //
+// ly.  Return abp in 'splitface'.                                           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::flip13(point newpt, face* splitface, int flipflag)
+{
+  face newfaces[3], bdedge, casout, casin;
+  face checkface, checkseg;
+  point pa, pb, pc;
+  int i;
+
+  REAL area;
+  int shmark;
+
+  splitface->shver &= ~1;  // Stay in the 0th edge ring.
+
+  pa = sorg(*splitface);
+  pb = sdest(*splitface);
+  pc = sapex(*splitface);
+
+  if (b->verbose > 1) {
+    printf("    flip 1-to-3: %d, (%d, %d, %d)\n", pointmark(newpt),
+      pointmark(pa), pointmark(pb), pointmark(pc));
+  }
+  flip13count++;
+
+  // We need two new subfaces.
+  newfaces[0] = *splitface;
+  makeshellface(subfacepool, &(newfaces[1]));
+  makeshellface(subfacepool, &(newfaces[2]));
+
+  // Insert the new point p.
+  setsapex(newfaces[0], newpt);  // abc->abp.
+  setshvertices(newfaces[1], pb, pc, newpt); // bcp.
+  setshvertices(newfaces[2], pc, pa, newpt); // cap.
+
+  shmark = getshellmark(newfaces[0]);
+  setshellmark(newfaces[1], shmark);
+  setshellmark(newfaces[2], shmark);
+  if (checkconstraints) {
+    area = areabound(newfaces[0]);
+    areabound(newfaces[1]) = area;
+    areabound(newfaces[2]) = area;
+  }
+
+  // Connect outer boundary faces to new faces.
+  senext(newfaces[0], bdedge);
+  for (i = 1; i < 3; i++) {
+    spivot(bdedge, casout);
+    sspivot(bdedge, checkseg);
+    if (casout.sh != NULL) {
+      casin = casout;
+      if (checkseg.sh != NULL) {
+        spivot(casin, checkface);
+        while (checkface.sh != bdedge.sh) {
+          casin = checkface;
+          spivot(casin, checkface);
+        }
+      }
+      sbond1(newfaces[i], casout);
+      sbond1(casin, newfaces[i]);
+    }
+    if (checkseg.sh != NULL) {
+      ssdissolve(bdedge);
+      ssbond(newfaces[i], checkseg);
+    }
+    senextself(bdedge);
+  }
+
+  // Connect the three subfaces together. Reuse casout, casin.
+  for (i = 0; i < 3; i++) {
+    senext(newfaces[i], casout);
+    senext2(newfaces[(i + 1) % 3], casin);
+    sbond2(casout, casin);
+  }
+
+  if (flipflag) {
+    // Put the boundary edges into flip stack.
+    for (i = 0; i < 3; i++) {
+      futureflip = flipshpush(futureflip, &(newfaces[i]));
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flipn2nf()    Insert a vertex by transforming n-to-2n subfaces.           //
+//                                                                           //
+// The 'newpt'(p) lies on the edge (ab) of 'splitedge'(abc). Let the n faces //
+// containing ab be: abp[0], ..., abp[n-1], use an array 'flipfaces':  flip- //
+// faces[0], ..., flipfaces[n-1], to store them.  This routine removes the n //
+// subfaces and replaces them with 2n new subfaces: app[0], ..., app[n-1] (  //
+// (at top), pbp[0], ..., pbp[n-1] (at bottom), respectively.  On return,    //
+// 'splitedge' is apc.                                                       //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::flipn2nf(point newpt, face* splitedges, int flipflag)
+{
+  face *abdedges, *bbdedges, *boutfaces, *binfaces;
+  face aseg, bseg, aoutseg, boutseg;
+  face checkface, checkseg;
+  point pa, pb, *pt;
+  int n, i;
+
+  shellface sptr;
+
+  splitedges[0].shver &= ~1;  // Stay in the 0th edge ring.
+
+  // Count the number of faces at ab.
+  n = 0;
+  checkface = splitedges[0];
+  do {
+    spivotself(checkface);
+    n++;
+  } while ((checkface.sh != NULL) && (checkface.sh != splitedges[0].sh));
+
+  // Allocate spaces.
+  abdedges = new face[n];
+  bbdedges = new face[n];
+  boutfaces = new face[n];
+  binfaces = new face[n];
+  pt = new point[n];
+
+  // Collect the faces, abp[0], ..., abp[n-1].
+  abdedges[0] = splitedges[0];
+  pt[0] = sapex(abdedges[0]);
+  for (i = 0; i < n - 1; i++) {
+    spivot(abdedges[i], abdedges[i + 1]);
+    if (sorg(abdedges[i + 1]) != sorg(splitedges[0])) {
+      sesymself(abdedges[i + 1]);
+    }
+    pt[i + 1] = sapex(abdedges[i + 1]);
+  }
+
+  pa = sorg(splitedges[0]);
+  pb = sdest(splitedges[0]);
+
+  if (b->verbose > 1) {
+    printf("    flip n-to-2n: %d, (%d, %d) %d ... (%d faces) \n", 
+      pointmark(newpt), pointmark(pa), pointmark(pb), pointmark(pt[0]), n); 
+  }
+  flipn2nfcount++;
+
+  // Get the old boundary edges: p[i]a, bp[i], i = 0, ..., n-1
+  for (i = 0; i < n; i++) {
+    senext(abdedges[i], bbdedges[i]);
+    senext2self(abdedges[i]);
+  }
+
+  // Collect outer boundary faces at bp[i].
+  for (i = 0; i < n; i++) {
+    spivot(bbdedges[i], boutfaces[i]);
+    binfaces[i] = boutfaces[i];
+    if (boutfaces[i].sh != NULL) {
+      sspivot(bbdedges[i], checkseg);
+      if (checkseg.sh != NULL) {
+        spivot(binfaces[i], checkface);
+        while (checkface.sh != bbdedges[i].sh) {
+          binfaces[i] = checkface;
+          spivot(binfaces[i], checkface);
+        }
+      }
+    }
+  }
+
+  // Insert the new point p.
+  for (i = 0; i < n; i++) {
+    setsapex(abdedges[i], newpt);  // ap[i]b->ap[i]p.
+    makeshellface(subfacepool, &(bbdedges[i]));
+    setshvertices(bbdedges[i], pb, pt[i], newpt); // bp[i]p.
+    setshellmark(bbdedges[i], getshellmark(abdedges[i]));
+    if (checkconstraints) {
+      areabound(bbdedges[i]) = areabound(abdedges[i]);
+    }
+  }
+
+  // Connect new boundary edges to outer faces.
+  for (i = 0; i < n; i++) {
+    if (boutfaces[i].sh != NULL) {
+      sbond1(bbdedges[i], boutfaces[i]);
+      sbond1(binfaces[i], bbdedges[i]);
+    }
+    senext2(abdedges[i], checkface);
+    sspivot(checkface, checkseg);  // Check subsegment.
+    if (checkseg.sh != NULL) {
+      ssdissolve(checkface);  // Clear the old bond.
+      ssbond(bbdedges[i], checkseg);
+    }
+  }
+
+  // Connect new subfaces to updated subfaces. (Reuse boutfaces, binfaces).
+  for (i = 0; i < n; i++) {
+    senext2(abdedges[i], boutfaces[i]);
+    senext(bbdedges[i], binfaces[i]);
+    sbond2(boutfaces[i], binfaces[i]);
+  }
+
+  // Create new subfaces ring at edge pb.
+  if (n > 1) {
+    for (i = 0; i < n; i++) {
+      senext2(bbdedges[i], boutfaces[i]);
+      senext2(bbdedges[(i + 1) % n], boutfaces[(i + 1) % n]);
+      sbond1(boutfaces[i], boutfaces[(i + 1) % n]);
+    }
+  }
+
+  // Check edge ab to see if it is a subsegment.
+  sspivot(splitedges[0], aseg);
+  if (aseg.sh != NULL) {
+    // Split a subsegment ab to ap and pb.
+    // if (sorg(aseg) != pa) sesymself(aseg);
+    aseg.shver = 0;
+    if (b->verbose > 1) {
+      printf("    flip 1-to-2: %d, (%d, %d).\n", pointmark(newpt), 
+        pointmark(sorg(aseg)), pointmark(sdest(aseg)));
+    }
+    // Insert the new point p.
+    makeshellface(subsegpool, &bseg);
+    setshvertices(bseg, newpt, sdest(aseg), NULL);
+    setsdest(aseg, newpt);
+    setshellmark(bseg, getshellmark(aseg));
+    if (checkconstraints) {
+      areabound(bseg) = areabound(aseg);
+    }
+    // Connect pb<->b#.
+    senext(aseg, aoutseg);
+    spivotself(aoutseg);
+    if (aoutseg.sh != NULL) {
+      senext(bseg, boutseg);
+      sbond2(boutseg, aoutseg);
+    }
+    // Connect ap <-> pb.
+    senext(aseg, aoutseg);
+    senext2(bseg, boutseg);
+    sbond2(aoutseg, boutseg);
+    // Connect seg ap to face ring of splitshs[0], this will disconnect the
+    //   old bonds as well. *** Because we mixed the edge versions ***
+    if (sorg(aseg) == sorg(splitedges[0])) {
+      for (i = 0; i < n; i++) {
+        senext(abdedges[i], boutfaces[i]);
+        ssbond(boutfaces[i], aseg);
+      }
+      // Connect seg pb to subfaces having it.
+      for (i = 0; i < n; i++) {
+        senext2(bbdedges[i], boutfaces[i]);
+        ssbond(boutfaces[i], bseg);
+      }
+    } else {
+      // The edge version is reversed.
+      assert(sdest(bseg) == sorg(splitedges[0]));
+      for (i = 0; i < n; i++) {
+        senext(abdedges[i], boutfaces[i]);
+        ssbond(boutfaces[i], bseg);
+      }
+      for (i = 0; i < n; i++) {
+        senext2(bbdedges[i], boutfaces[i]);
+        ssbond(boutfaces[i], aseg);
+      }
+    }
+  }
+
+  if (flipflag) {
+    // Put the boundary edges into flip stack.
+    for (i = 0; i < n; i++) {
+      futureflip = flipshpush(futureflip, &abdedges[i]);
+      futureflip = flipshpush(futureflip, &bbdedges[i]);
+    }
+  }
+
+  // Return apc = app[0] = splitedges[0].
+  senext2(bbdedges[0], splitedges[1]); // return pbp[0].
+
+  delete [] abdedges;
+  delete [] bbdedges;
+  delete [] boutfaces;
+  delete [] binfaces;
+  delete [] pt;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flip22()    Remove an edge by transforming 2-to-2 subfaces.               //
+//                                                                           //
+// 'flipfaces' contains two faces: abc and bad. This routine removes these 2 //
+// faces and replaces them by two new faces: cdb and dca.                    //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::flip22(face* flipfaces, int flipflag)
+{
+  face bdedges[4], outfaces[4], infaces[4], bdsegs[4];
+  face checkface, checkseg;
+  point pa, pb, pc, pd;
+  int i;
+
+  // Orient the two faces properly: abc and bad.
+  if (sorg(flipfaces[0]) == sorg(flipfaces[1])) {
+    sesymself(flipfaces[1]);
+  }
+
+  pa = sorg(flipfaces[0]);
+  pb = sdest(flipfaces[0]);
+  pc = sapex(flipfaces[0]);
+  pd = sapex(flipfaces[1]);
+
+  if (b->verbose > 1) {
+    printf("    flip 2-to-2: (%d, %d, %d, %d)\n", pointmark(pa),
+      pointmark(pb), pointmark(pc), pointmark(pd));
+  }
+  flip22count++;
+
+  // Collect the four boundary edges.
+  senext(flipfaces[0], bdedges[0]);
+  senext2(flipfaces[0], bdedges[1]);
+  senext(flipfaces[1], bdedges[2]);
+  senext2(flipfaces[1], bdedges[3]);
+
+  // Collect outer boundary faces.
+  for (i = 0; i < 4; i++) {
+    spivot(bdedges[i], outfaces[i]);
+    infaces[i] = outfaces[i];
+    sspivot(bdedges[i], bdsegs[i]);
+    if (outfaces[i].sh != NULL) {
+      sspivot(bdedges[i], checkseg);
+      if (checkseg.sh != NULL) {
+        spivot(infaces[i], checkface);
+        while (checkface.sh != bdedges[i].sh) {
+          infaces[i] = checkface;
+          spivot(infaces[i], checkface);
+        }
+      }
+    }
+  }
+
+  // Transform abc -> cdb.
+  setshvertices(flipfaces[0], pc, pd, pb);
+  // Transform bad -> dca.
+  setshvertices(flipfaces[1], pd, pc, pa);
+
+  // Reconnect boundary edges to outer boundary faces.
+  for (i = 0; i < 4; i++) {
+    if (outfaces[(3 + i) % 4].sh != NULL) {
+      sbond1(bdedges[i], outfaces[(3 + i) % 4]);
+      sbond1(infaces[(3 + i) % 4], bdedges[i]);
+    } else {
+      sdissolve(bdedges[i]);
+    }
+    if (bdsegs[(3 + i) % 4].sh != NULL) {
+      ssbond(bdedges[i], bdsegs[(3 + i) % 4]);
+    } else {
+      ssdissolve(bdedges[i]);
+    }
+  }
+
+  recentsh = flipfaces[0];
+
+  if (flipflag) {
+    // Put the boundary edges into flip stack.
+    for (i = 0; i < 4; i++) {
+      futureflip = flipshpush(futureflip, &bdedges[i]);
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// lawsonflip()    Flip non-locally Delaunay edges.                          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::lawsonflip()
+{
+  face flipfaces[2];
+  face checkseg;
+  point pa, pb, pc, pd;
+  REAL sign;
+  long flipcount;
+
+  if (b->verbose > 1) {
+    printf("    Lawson flip %ld edges.\n", flippool->items);
+  }
+  flipcount = flip22count;
+
+  while (futureflip != (badface *) NULL) {
+    // Pop an edge from the stack.
+    flipfaces[0] = futureflip->ss;
+    pa = futureflip->forg;
+    pb = futureflip->fdest;
+    futureflip = futureflip->nextitem;
+
+    // Skip it if it is dead.
+    if (flipfaces[0].sh[3] == NULL) continue;
+    // Skip it if it is not the same edge as we saved.
+    if ((sorg(flipfaces[0]) != pa) || (sdest(flipfaces[0]) != pb)) continue;
+    // Skip it if it is a subsegment.
+    sspivot(flipfaces[0], checkseg);
+    if (checkseg.sh != NULL) continue;
+
+    // Get the adjacent face.
+    spivot(flipfaces[0], flipfaces[1]);
+    if (flipfaces[1].sh == NULL) continue; // Skip a hull edge.
+    pc = sapex(flipfaces[0]);
+    pd = sapex(flipfaces[1]);
+
+    sign = incircle3d(pa, pb, pc, pd);
+
+    if (sign < 0) {
+      // It is non-locally Delaunay. Flip it.
+      flip22(flipfaces, 1);
+    }
+  }
+
+  if (b->verbose > 1) {
+    printf("    %ld edges stacked, %ld flips.\n", flippool->items,
+      flip22count - flipcount);
+  }
+
+  flippool->restart();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flippush()    Push a face (possibly will be flipped) into stack.          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+tetgenmesh::badface* tetgenmesh::flippush(badface* flipstack, 
+  triface* flipface, point pushpt)
+{
+  badface *newflipface;
+
+  newflipface = (badface *) flippool->alloc();
+  newflipface->tt = *flipface;
+  newflipface->foppo = pushpt;
+  newflipface->nextitem = flipstack;
+
+  return newflipface;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flip14()    Insert a vertex by transforming 1-to-4 tetrahedra.            //
+//                                                                           //
+// 'newpt' (p) lies in the interior of 'splittet' (abcd).  This routine abcd //
+// abcd and replaces it by 4 new tets: abpd, bcpd, capd, and abcp, resepcti- //
+// vely.  Return abcp in 'splittet'.                                         //
+//                                                                           //
+// If abcd is a hull tet, we adjust it and let d be the dummypoint. In this  //
+// case, the three new tets: abpd, bcpd, and capd are hull tets.             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::flip14(point newpt, triface* splittet, int flipflag)
+{
+  triface fliptets[3], castets[3];
+  triface newface, casface;
+  face checksh, checkseg;
+  point pa, pb, pc, pd;
+  int i;
+
+  int *iptr;
+
+  // Check if the original tet is a hull tet.
+  if ((point) splittet->tet[7] == dummypoint) {
+    splittet->loc = 0;
+  }
+  splittet->ver = 0;
+
+  pa = org(*splittet);
+  pb = dest(*splittet);
+  pc = apex(*splittet);
+  pd = oppo(*splittet);
+
+  if (b->verbose > 1) {
+    printf("    flip 1-to-4: %d (%d, %d, %d, %d)\n", pointmark(newpt), 
+      pointmark(pa), pointmark(pb), pointmark(pc), pointmark(pd));
+  }
+  flip14count++;
+
+  // Get the outer boundary faces.
+  for(i = 0; i < 3; i++) {
+    fnext(*splittet, castets[i]);
+    enextself(*splittet);
+  }
+
+  if (checksubsegs) {
+    // Dealloc the space to subsegments.
+    if (splittet->tet[8] != NULL) {
+      tet2segpool->dealloc((shellface *) splittet->tet[8]);
+    }
+    splittet->tet[8] = NULL;
+  }
+  if (checksubfaces) {
+    // Dealloc the space to subfaces.
+    if (splittet->tet[9] != NULL) {
+      tet2subpool->dealloc((shellface *) splittet->tet[9]);
+    }
+    splittet->tet[9] = NULL;
+  }
+
+  // Update the number of hull tets.
+  if (pd == dummypoint) {
+    // We remove one old hull tet (abcp), but add three new hull tets.
+    hullsize += 2;
+  }
+  
+  // Create three new tets for abpd, bcpd, and capd.
+  maketetrahedron(&(fliptets[0]));
+  maketetrahedron(&(fliptets[1]));
+  maketetrahedron(&(fliptets[2]));
+  // Set the vertices.
+  setvertices(fliptets[0], pa, pb, newpt, pd);
+  setvertices(fliptets[1], pb, pc, newpt, pd);
+  setvertices(fliptets[2], pc, pa, newpt, pd);
+  // Update the old tet to abcp.
+  setoppo(*splittet, newpt);
+
+  // Bond the new tets to outer boundary tets.
+  for (i = 0; i < 3; i++) {
+    enext0fnext(fliptets[i], newface);
+    bond(newface, castets[i]);
+  }
+  // Bond the new tets together (at six interior faces).
+  for (i = 0; i < 3; i++) {
+    enext0fnext(*splittet, newface);
+    bond(newface, fliptets[i]);
+    enextself(*splittet);
+  }
+  for (i = 0; i < 3; i++) {
+    enextfnext(fliptets[i], newface);
+    enext2fnext(fliptets[(i + 1) % 3], casface);
+    bond(newface, casface);
+  }
+
+  if (checksubsegs) {
+    // Bond segments to new tets. Each new tet has three edges to be
+    //   checked, e.g., abpd has [a,b], [b,d], and [d,a]. The base tet 
+    //   abcd has three edges [a,b], [b,c] and [c,a], total 12 edges.
+    for (i = 0; i < 3; i++) {
+      enext0fnext(fliptets[i], newface); // [a,b], [b,c], [c,a].
+      tsspivot(castets[i], checkseg); 
+      if (checkseg.sh != NULL) {
+        tssbond1(*splittet, checkseg);
+        tssbond1(newface, checkseg);
+      }
+      enextself(newface); // [b,d], [c,d], [a,d]
+      enext(castets[i], casface);
+      tsspivot(casface, checkseg); 
+      if (checkseg.sh != NULL) {
+        tssbond1(newface, checkseg);
+      }
+      enextself(newface); // [d,a], [d,b], [d,c]
+      enext2(castets[i], casface);
+      tsspivot(casface, checkseg);
+      if (checkseg.sh != NULL) {
+        tssbond1(newface, checkseg);
+      }
+      enextself(*splittet);
+    }
+  }
+
+  if (checksubfaces) {
+    // Bond subfaces to new tets.
+    sym(*splittet, casface);
+    tspivot(casface, checksh);
+    if (checksh.sh != NULL) {
+      tsbond(*splittet, checksh);
+    }
+    for (i = 0; i < 3; i++) {
+      enext0fnext(fliptets[i], newface);
+      tspivot(castets[i], checksh);
+      if (checksh.sh != NULL) {
+        tsbond(newface, checksh);
+      }
+    }
+  }
+
+  // Update the point-to-tet map.
+  point2tet(newpt) = encode(*splittet);
+  // The values in pa, pb, and pc are not changed.
+  point2tet(pd) = encode(fliptets[0]);
+
+  if (flipflag > 0) {
+    // Queue faces which may be locally non-Delaunay.
+    for (i = 0; i < 3; i++) {
+      enext0fnext(fliptets[i], newface);
+      futureflip = flippush(futureflip, &newface, newpt);
+    }
+    futureflip = flippush(futureflip, splittet, newpt);
+  }
+
+  // Return abcp in 'splittet'.
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flip26()    Insert a vertex by transforming 2-to-6 tetrahedra.            //
+//                                                                           //
+// The 'newpt' (p) lies in the face 'splitface' (abc).  This routine removes //
+// the two tets sharing at abc: abcd and bace, replaces them with 6 new tets //
+// : abpd, bcpd, capd (at top), bape, cbpe, and acpe (at bottom). On return, //
+// 'splitface' is abpd.                                                      //
+//                                                                           //
+// On input, a, b, or c should not be dummypoint. If d is dummypoint, the 3  //
+// top new tets are hull tets.  If e is dummypoint,  we reconfigure e to d,  //
+// i.e., turn the two tets up-side down.                                     //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::flip26(point newpt, triface* splitface, int flipflag)
+{
+  triface fliptets[4], castets[4];
+  triface symface, newface, casface;
+  face checksh, checkseg;
+  point pa, pb, pc, pd, pe;
+  int i, j;
+
+  int *iptr;
+
+  splitface->ver &= ~1;
+  symedge(*splitface, symface);
+
+  if (oppo(symface) == dummypoint) {
+    // Swap the two old tets.
+    newface = *splitface;
+    *splitface = symface;
+    symface = newface;
+  }
+
+  pa = org(*splitface);
+  pb = dest(*splitface);
+  pc = apex(*splitface);
+  pd = oppo(*splitface);
+  pe = oppo(symface);
+
+  if (b->verbose > 1) {
+    printf("    flip 2-to-6: (%d, %d, %d, %d, %d)\n", pointmark(pa),
+      pointmark(pb), pointmark(pc), pointmark(pd), pointmark(pe));
+  }
+  flip26count++;
+
+  // Get the outer boundary faces.
+  enext(*splitface, fliptets[0]);
+  enext2(*splitface, fliptets[1]);
+  enext2(symface, fliptets[2]);
+  enext(symface, fliptets[3]);
+
+  for (i = 0; i < 4; i++) {
+    fnext(fliptets[i], castets[i]);
+  }
+
+  if (checksubsegs) {
+    // Dealloc the space to subsegments.
+    if (splitface->tet[8] != NULL) {
+      tet2segpool->dealloc((shellface *) splitface->tet[8]);
+    }
+    splitface->tet[8] = NULL;
+    if (symface.tet[8] != NULL) {
+      tet2segpool->dealloc((shellface *) symface.tet[8]);
+    }
+    symface.tet[8] = NULL;
+  }
+  if (checksubfaces) {
+    // Dealloc the space to subfaces.
+    if (splitface->tet[9] != NULL) {
+      tet2subpool->dealloc((shellface *) splitface->tet[9]);
+    }
+    splitface->tet[9] = NULL;
+    if (symface.tet[9] != NULL) {
+      tet2subpool->dealloc((shellface *) symface.tet[9]);
+    }
+    symface.tet[9] = NULL;
+  }
+
+  // Update the number of hull tets.
+  if (pd == dummypoint) {
+    // We remove one old hull tet (abcp), but add three new hull tets.
+    hullsize += 2;
+  }
+
+  // Create new tets.
+  maketetrahedron(&(fliptets[0])); // bcpd
+  maketetrahedron(&(fliptets[1])); // capd
+  maketetrahedron(&(fliptets[2])); // cbpe
+  maketetrahedron(&(fliptets[3])); // acpe
+
+  // Set new vertices.
+  setapex(*splitface, newpt);
+  setvertices(fliptets[0], pb, pc, newpt, pd);
+  setvertices(fliptets[1], pc, pa, newpt, pd);
+  setapex(symface, newpt);
+  setvertices(fliptets[2], pc, pb, newpt, pe);
+  setvertices(fliptets[3], pa, pc, newpt, pe);
+
+  // Bond the new tets to outer boundary faces.
+  for (i = 0; i < 4; i++) {
+    enext0fnext(fliptets[i], newface);
+    bond(newface, castets[i]);
+  }
+
+  // Bond the top and bottom new tets together.
+  bond(fliptets[0], fliptets[2]);
+  bond(fliptets[1], fliptets[3]);
+
+  // Bond the new tets together.
+  enextfnext(*splitface, newface);
+  enext2fnext(fliptets[0], casface);
+  bond(newface, casface);
+  enextfnext(fliptets[0], newface);
+  enext2fnext(fliptets[1], casface);
+  bond(newface, casface);
+  enextfnext(fliptets[1], newface);
+  enext2fnext(*splitface, casface);
+  bond(newface, casface);
+
+  enext2fnext(symface, newface);
+  enextfnext(fliptets[2], casface);
+  bond(newface, casface);
+  enext2fnext(fliptets[2], newface);
+  enextfnext(fliptets[3], casface);
+  bond(newface, casface);
+  enext2fnext(fliptets[3], newface);
+  enextfnext(symface, casface);
+  bond(newface, casface);
+
+  if (checksubsegs) {
+    // Bond segments. For each tet there are three edges to be checked,
+    //   total there are 18 edges.
+    for (i = 0; i < 3; i++) {
+      if (i < 2) {
+        enext0fnext(fliptets[i], newface);
+        casface = castets[i];
+      } else {
+        enext0fnext(*splitface, newface);
+        symedge(newface, casface);
+      }
+      for (j = 0; j < 3; j++) {
+        tsspivot(casface, checkseg);
+        if (checkseg.sh != NULL) {
+          tssbond1(newface, checkseg);
+        }
+        enextself(casface);
+        enextself(newface);
+      }
+    }
+    for (i = 0; i < 3; i++) {
+      if (i < 2) {
+        enext0fnext(fliptets[i + 2], newface);
+        casface = castets[i + 2];
+      } else {
+        enext0fnext(symface, newface);
+        symedge(newface, casface);
+      }
+      for (j = 0; j < 3; j++) {
+        tsspivot(casface, checkseg);
+        if (checkseg.sh != NULL) {
+          tssbond1(newface, checkseg);
+        }
+        enextself(casface);
+        enextself(newface);
+      }
+    }
+  }
+
+  if (checksubfaces) {
+    // Bond subfaces. There are total 6 faces to be checked.
+    for (i = 0; i < 3; i++) {
+      if (i < 2) {
+        enext0fnext(fliptets[i], newface);
+        casface = castets[i];
+      } else {
+        enext0fnext(*splitface, newface);
+        symedge(newface, casface);
+      }
+      tspivot(casface, checksh);
+      if (checksh.sh != NULL) {
+        tsbond(newface, checksh);
+      }
+    }
+    for (i = 0; i < 3; i++) {
+      if (i < 2) {
+        enext0fnext(fliptets[i + 2], newface);
+        casface = castets[i + 2];
+      } else {
+        enext0fnext(symface, newface);
+        symedge(newface, casface);
+      }
+      tspivot(casface, checksh);
+      if (checksh.sh != NULL) {
+        tsbond(newface, checksh);
+      }
+    }
+  }
+
+  // Update point-to-tet map.
+  point2tet(newpt) = encode(*splitface);
+  // The values in pa and pb are not changed.
+  point2tet(pc) = encode(fliptets[0]);
+  point2tet(pd) = encode(fliptets[0]);
+  point2tet(pe) = encode(fliptets[2]);
+
+  if (flipflag > 0) {
+    enext0fnext(*splitface, newface);
+    futureflip = flippush(futureflip, &newface, newpt);
+    enext0fnext(symface, newface);
+    futureflip = flippush(futureflip, &newface, newpt);
+    for (i = 0; i < 4; i++) {
+      enext0fnext(fliptets[i], newface);
+      futureflip = flippush(futureflip, &newface, newpt);
+    }
+  }
+
+  // Return abpd in 'splitface'.
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flipn2n()    Insert a vertex by transforming n-to-2n tetrahedra.          //
+//                                                                           //
+// The 'newpt'(p) lies on the edge (ab) of 'splitedge'(abcd). Let the n tets //
+// containing ab be: abp[0]p[1], ..., abp[n-1]p[0], use an array 'fliptets': //
+// 'fliptets[0]', ..., 'fliptets[n-1]', to store them.  This routine removes //
+// the n tets and replaces them with 2n new tets: app[0]p[1], ..., app[n-1]- //
+// p[0] (at top), pbp[0]p[1], ..., pbp[n-1]p[0] (at bottom) in 'fliptets[0]',//
+// ..., 'fliptets[2n-1]', respectively.  On return, 'splitedge' is apcd.     //
+//                                                                           //
+// On input, a and b should not be dummypoint. If p[0] is dummypoint, the 2  //
+// new tets connecting to p[0] are hull tets. If p[i], i != 0 is dummypoint, //
+// we reconfigure p[i] to p[0], i.e., up-shift the tets i times.             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::flipn2n(point newpt, triface* splitedge, int flipflag)
+{
+  triface *fliptets, *bfliptets, *castets;
+  triface newface, casface;
+  face checksh, checkseg;
+  point pa, pb, *pt;
+  int dummyflag; // 0 or 1.
+  int n, i, j;
+
+  int *iptr;
+
+  n = 0;
+  dummyflag = 0;
+
+  // First count the number n of tets having ab.
+  splitedge->ver &= ~1;
+  casface = *splitedge;
+  do {
+    n++;
+    if (apex(casface) == dummypoint) {
+      // Remeber this face (it's apex is dummypoint).
+      newface = casface;
+      dummyflag = n;
+    }
+    fnextself(casface);
+  } while (casface.tet != splitedge->tet);
+
+  // Allocate spaces for fliptets.
+  fliptets = new triface[n];
+  bfliptets = new triface[n];
+  castets = new triface[n];
+  pt = new point[n];
+
+  // Get the n old tets.
+  fliptets[0] = (dummyflag == 0 ? *splitedge : newface);
+  for (i = 0; i < n - 1; i++) {
+    fnext(fliptets[i], fliptets[i + 1]);
+  }
+  // Get the n apexes.
+  for (i = 0; i < n; i++) {
+    pt[i] = apex(fliptets[i]); 
+  }
+  pa = org(fliptets[0]);
+  pb = dest(fliptets[0]);
+
+  if (b->verbose > 1) {
+    printf("    flip n-to-2n: (%d, %d) %d %d ..., (n = %d)\n", pointmark(pa),
+      pointmark(pb), pointmark(pt[0]), pointmark(pt[1]), n);
+  }
+  flipn2ncount++;
+
+  // Get the outer boundary faces.
+  for (i = 0; i < n; i++) {
+    enext(fliptets[i], casface);  // at edge bp[i].
+    fnext(casface, castets[i]);
+  }
+
+  if (checksubsegs) {
+    for (i = 0; i < n; i++) {
+      if (fliptets[i].tet[8] != NULL) {
+        tet2segpool->dealloc((shellface *) fliptets[i].tet[8]);
+      }
+      fliptets[i].tet[8] = NULL;
+    }
+  }
+  if (checksubfaces) {
+    for (i = 0; i < n; i++) {
+      if (fliptets[i].tet[9] != NULL) {
+        tet2segpool->dealloc((shellface *) fliptets[i].tet[9]);
+      }
+      fliptets[i].tet[9] = NULL;
+    }
+  }
+
+  // Update the number of hull tets.
+  if (pt[0] == dummypoint) {
+    // We remove 2 old hull tet (abcp), but add 4 new hull tets.
+    hullsize += 2;
+  }
+
+  // Create n new tets.
+  if (pt[0] != dummypoint) {
+    setdest(fliptets[0], newpt);  // app[0]p[1]
+    setdest(fliptets[n - 1], newpt);  // app[n-1]p[0]
+    maketetrahedron(&(bfliptets[0])); // pbp[0]p[1]
+    maketetrahedron(&(bfliptets[n - 1])); // pbp[n-1]p[0]
+    setvertices(bfliptets[0], newpt, pb, pt[0], pt[1]);
+    setvertices(bfliptets[n - 1], newpt, pb, pt[n - 1], pt[0]);
+  } else {
+    // NOTE: the base face must contain no 'dummypoint'.
+    setdest(fliptets[0], newpt);  // app[0]p[1]
+    setdest(fliptets[n - 1], newpt);  // app[n-1]p[0]
+    maketetrahedron(&(bfliptets[0])); // pbp[0]p[1]
+    maketetrahedron(&(bfliptets[n - 1])); 
+    setvertices(bfliptets[0], pb, newpt, pt[1], pt[0]);
+    setvertices(bfliptets[n - 1], newpt, pb, pt[n - 1], pt[0]);
+    // Adjust the face of and bfliptets[0].
+    enext0fnextself(bfliptets[0]);
+    esymself(bfliptets[0]);
+  }
+  for (i = 1; i < n - 1; i++) {
+    setdest(fliptets[i], newpt); // app[i]p[i+1]
+    maketetrahedron(&(bfliptets[i])); // pbp[i]p[i+1]
+    setvertices(bfliptets[i], newpt, pb, pt[i], pt[i + 1]);
+  }
+
+  // Bond new tets to outer boundary faces.
+  for (i = 0; i < n; i++) {
+    enextfnext(bfliptets[i], newface);
+    bond(newface, castets[i]);
+  }
+  // Bond new tets together.
+  for (i = 0; i < n; i++) {
+    enext0fnext(bfliptets[i], newface);
+    bond(newface, bfliptets[(i + 1) % n]);
+  }
+  // Bond top and bottom new tets togther
+  for (i = 0; i < n; i++) {
+    enextfnext(fliptets[i], newface);
+    enext2fnext(bfliptets[i], casface);
+    bond(newface, casface);
+  }
+
+  if (checksubsegs) {
+    // Bond segments. There are total n x 3 edges.
+    for (i = 0; i < n; i++) {  // Top edges.
+      enext2fnext(fliptets[i], newface);
+      symedge(newface, casface);
+      for(j = 0; j < 3; j++) {
+        tsspivot(casface, checkseg);
+        if (checkseg.sh != NULL) {
+          tssbond1(newface, checkseg);
+        }
+        enextself(casface);
+        enextself(newface);
+      }
+    }
+    for (i = 0; i < n; i++) {  // Bottom edges.
+      enextfnext(bfliptets[i], newface);
+      casface = castets[i];
+      for(j = 0; j < 3; j++) {
+        tsspivot(casface, checkseg);
+        if (checkseg.sh != NULL) {
+          tssbond1(newface, checkseg);
+        }
+        enextself(casface);
+        enextself(newface);
+      }
+    }
+  }
+
+  if (checksubfaces) {
+    // Bond subfaces.
+    for (i = 0; i < n; i++) {  // Top faces.
+      enext2fnext(fliptets[i], newface);
+      symedge(newface, casface);
+      tspivot(casface, checksh);
+      if (checksh.sh != NULL) {
+        tsbond(newface, checksh);
+      }
+    }
+    for (i = 0; i < n; i++) {  // Bottom faces.
+      enextfnext(bfliptets[i], newface);
+      casface = castets[i];
+      tspivot(casface, checksh);
+      if (checksh.sh != NULL) {
+        tsbond(newface, checksh);
+      }
+    }
+  }
+
+  // Update the point-to-tet map.
+  point2tet(newpt) = encode(fliptets[0]);
+  // The values in pa, p[0], ..., p[n-1] are not changed.
+  point2tet(pb) = encode(bfliptets[0]);
+
+  if (flipflag > 0) {
+    for (i = 0; i < n; i++) {
+      enext2fnext(fliptets[i], newface);
+      futureflip = flippush(futureflip, &newface, newpt);
+    }
+    for (i = 0; i < n; i++) {
+      enextfnext(bfliptets[i], newface);
+      futureflip = flippush(futureflip, &newface, newpt);
+    }
+  }
+
+  // If dummyflag !=0, the original tet is shifted by (n - dummyflag + 1).
+  //*splitedge = (dummyflag == 0 ? fliptets[0] : fliptets[n - dummyflag + 1]);
+
+  delete [] fliptets;
+  delete [] bfliptets;
+  delete [] castets;
+  delete [] pt;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flip23()    Remove a face by tranforming 2-to-3 tetrahedra.               //
+//                                                                           //
+// 'flipface' (abc) is shared by two tets: abcd and bace. This routine rep-  //
+// laces them by three new tets:  edab, edbc, and edca. As a result, the abc //
+// is replaced by the edge de. On return, 'flipface' is edab.                //
+//                                                                           //
+// If 'hullflag' > 0, one of {a, b, c, d, e} may be 'dummypoint'. There may  //
+// be hull tets involved in this flip.  There are two cases:                 //
+//   (1) If d is 'dummypoint', all three new tets are hull tets.  If e is    //
+//       'dummypoint', we reconfigure e to d, i.e., turn it up-side down.    //
+//   (2) If c is 'dummypoint' , two new tets edbc and edca are hull tets.    //
+//       If a or b is 'dummypoint', we reconfigure it to c, i.e., rotate the //
+//       three old tets counterclockwisely (right-hand rule) until a or b    //
+//       is in c's position (see Fig.).                                      //
+//                                                                           //
+// If 'flipflag != 0', the convex hull faces will be checked and flipped if  //
+// they are locally non-Delaunay. If 'flipflag == 1', we assume that d is a  //
+// newly inserted vertex, so only the lower part of the convex hull will be  //
+// checked (this avoids unnecessary insphere() testes).                      //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::flip23(triface* fliptets, int hullflag, int flipflag)
+{
+  triface topcastets[3], botcastets[3];
+  triface newface, casface;
+  point pa, pb, pc, pd, pe;
+  int dummyflag;  // range = {-1, 0, 1, 2}.
+  int i;
+
+  face *pssub, checksh;
+  face checkseg;
+
+  int *iptr;
+
+  if (hullflag > 0) {
+    // Check if e is dummypoint.
+    if (oppo(fliptets[1]) == dummypoint) {
+      // Swap the two old tets.
+      newface = fliptets[0];
+      fliptets[0] = fliptets[1];
+      fliptets[1] = newface;
+      dummyflag = -1;  // e is dummypoint.
+    } else {
+      // Check if a or b is dummypoint.
+      if (org(fliptets[0]) == dummypoint) {
+        dummyflag = 1;  // a is dummypoint.
+      } else if (dest(fliptets[0]) == dummypoint) {
+        dummyflag = 2;  // b is dummypoint.
+      } else {
+        dummyflag = 0;  // either c or d is dummypoint.
+      }
+      i = dummyflag;
+      // Rotate i times.
+      for (; i > 0; i--) {
+        enextself(fliptets[0]);
+        enext2self(fliptets[1]);
+      }
+    }
+  }
+
+  pa = org(fliptets[0]);
+  pb = dest(fliptets[0]);
+  pc = apex(fliptets[0]);
+  pd = oppo(fliptets[0]);
+  pe = oppo(fliptets[1]);
+
+  if (b->verbose > 1) {
+    printf("    flip 2-to-3: (%d, %d, %d, %d, %d)\n", pointmark(pa),
+      pointmark(pb), pointmark(pc), pointmark(pd), pointmark(pe));
+  }
+  flip23count++;
+
+  // Get the outer boundary faces.
+  for (i = 0; i < 3; i++) {
+    fnext(fliptets[0], topcastets[i]);
+    enextself(fliptets[0]);
+  }
+  for (i = 0; i < 3; i++) {
+    fnext(fliptets[1], botcastets[i]);
+    enext2self(fliptets[1]);
+  }
+
+  if (checksubfaces) {
+    // Check if the flip face is subfaces.
+    tspivot(fliptets[0], checksh);
+    if (checksh.sh != NULL) {
+      if (b->verbose > 1) {
+        printf("      Queue a flipped subface (%d, %d, %d).\n",
+          pointmark(sorg(checksh)), pointmark(sdest(checksh)),
+          pointmark(sapex(checksh)));
+      }
+      stdissolve(checksh); // Disconnect the sub-tet bond.
+      // Add the missing subface into list.
+      subfacstack->newindex((void **) &pssub);
+      *pssub = checksh;
+    }
+  }
+
+  // Re-use fliptets[0] and fliptets[1].
+  fliptets[0].loc = fliptets[0].ver = 0;
+  fliptets[1].loc = fliptets[1].ver = 0;
+  elemmarker(fliptets[0].tet) = 0;
+  elemmarker(fliptets[1].tet) = 0;
+  if (checksubsegs) {
+    // Dealloc the space to subsegments.
+    if (fliptets[0].tet[8] != NULL) {
+      tet2segpool->dealloc((shellface *) fliptets[0].tet[8]);
+    }
+    fliptets[0].tet[8] = NULL;
+    if (fliptets[1].tet[8] != NULL) {
+      tet2segpool->dealloc((shellface *) fliptets[1].tet[8]);
+    }
+    fliptets[1].tet[8] = NULL;
+  }
+  if (checksubfaces) {
+    // Dealloc the space to subfaces.
+    if (fliptets[0].tet[9] != NULL) {
+      tet2subpool->dealloc((shellface *) fliptets[0].tet[9]);
+    }
+    fliptets[0].tet[9] = NULL;
+    if (fliptets[1].tet[9] != NULL) {
+      tet2subpool->dealloc((shellface *) fliptets[1].tet[9]);
+    }
+    fliptets[1].tet[9] = NULL;
+  }
+
+  if (hullflag > 0) {
+    // Check if d is dummytet.
+    if (pd != dummypoint) {
+      // Update fliptets[0] to edab.
+      setvertices(fliptets[0], pe, pd, pa, pb);
+      // Update fliptets[1] to edbc.
+      setvertices(fliptets[1], pe, pd, pb, pc);
+      // Create new tet edca.
+      maketetrahedron(&(fliptets[2]));
+      // Check if c is dummypoint.
+      if (pc != dummypoint) {
+        setvertices(fliptets[2], pe, pd, pc, pa);
+      } else {
+        setvertices(fliptets[2], pd, pe, pa, pc);
+        // Adjust deac->edca
+        enext0fnextself(fliptets[2]);
+        esymself(fliptets[2]);
+      }
+      // The hullsize does not change.
+    } else {
+      // d is dummypoint.
+      setvertices(fliptets[0], pa, pb, pe, pd); // Create abed.
+      setvertices(fliptets[1], pb, pc, pe, pd); // Create bced.
+      maketetrahedron(&(fliptets[2])); // Create caed.    
+      setvertices(fliptets[2], pc, pa, pe, pd);
+      // Adjust abed->edab, bced->edbc, caed->edca
+      for (i = 0; i < 3; i++) {
+        enext2fnextself(fliptets[i]);
+        enext2self(fliptets[i]);
+        esymself(fliptets[i]);
+      }
+      // We removed one old hull tet, and added three new hull tets.
+      hullsize += 2;
+    }
+  } else {
+    // Update fliptets[0] to edab.
+    setvertices(fliptets[0], pe, pd, pa, pb);
+    // Update fliptets[1] to edbc.
+    setvertices(fliptets[1], pe, pd, pb, pc);
+    // Create new tet edca.
+    maketetrahedron(&(fliptets[2]));
+    setvertices(fliptets[2], pe, pd, pc, pa);
+  }
+
+  // Bond three new tets together.
+  for (i = 0; i < 3; i++) {
+    enext0fnext(fliptets[i], newface);
+    bond(newface, fliptets[(i + 1) % 3]);
+  }
+  // Bond to top outer boundary faces (at abcd).
+  for (i = 0; i < 3; i++) {
+    enextfnext(fliptets[i], newface);
+    enextself(newface);
+    bond(newface, topcastets[i]);
+  }
+  // Bond bottom outer boundary faces (at bace).
+  for (i = 0; i < 3; i++) {
+    enext2fnext(fliptets[i], newface);
+    enext2self(newface);
+    bond(newface, botcastets[i]);
+  }
+
+  // Bond 15 subsegments if there are.
+  if (checksubsegs) {
+    // The middle three: ab, bc, ca.
+    for (i = 0; i < 3; i++) {
+      tsspivot(topcastets[i], checkseg);
+      if (checkseg.sh != NULL) {
+        enextfnext(fliptets[i], newface);
+        enextself(newface);
+        tssbond1(newface, checkseg);
+      }
+    }
+    // The top three: da, db, dc. Each edge belongs to two tets.
+    for (i = 0; i < 3; i++) {
+      enext2(topcastets[i], casface);
+      tsspivot(casface, checkseg);
+      if (checkseg.sh != NULL) {
+        enext(fliptets[i], newface);
+        tssbond1(newface, checkseg);
+        enext0fnext(fliptets[(i + 2) % 3], newface);
+        enextself(newface);
+        tssbond1(newface, checkseg);
+      }
+    }
+    // The bot three: ae, be, ce. Each edge belongs to two tets.
+    for (i = 0; i < 3; i++) {
+      enext(botcastets[i], casface);
+      tsspivot(casface, checkseg);
+      if (checkseg.sh != NULL) {
+        enext2(fliptets[i], newface);
+        tssbond1(newface, checkseg);
+        enext0fnext(fliptets[(i + 2) % 3], newface);
+        enext2self(newface);
+        tssbond1(newface, checkseg);
+      }
+    }
+  }
+
+  // Bond 6 subfaces if there are.
+  if (checksubfaces) {
+    for (i = 0; i < 3; i++) {
+      tspivot(topcastets[i], checksh);
+      if (checksh.sh != NULL) {
+        enextfnext(fliptets[i], newface);
+        enextself(newface);
+        tsbond(newface, checksh);
+      }
+    }
+    for (i = 0; i < 3; i++) {
+      tspivot(botcastets[i], checksh);
+      if (checksh.sh != NULL) {
+        enext2fnext(fliptets[i], newface);
+        enext2self(newface);
+        tsbond(newface, checksh);
+      }
+    }
+  }
+
+  // if (checksubsegs || checksubfaces) {
+    // Update the point-to-tet map.
+    point2tet(pa) = encode(fliptets[0]);
+    point2tet(pb) = encode(fliptets[0]);
+    point2tet(pc) = encode(fliptets[1]);
+    point2tet(pd) = encode(fliptets[0]);
+    point2tet(pe) = encode(fliptets[0]);
+  // }
+
+  if (hullflag > 0) {
+    if (dummyflag != 0) {
+      // Restore the original position of the points (for flipnm()).
+      if (dummyflag == -1) { 
+        // Reverse the edge.
+        for (i = 0; i < 3; i++) {
+          enext0fnextself(fliptets[i]);
+          esymself(fliptets[i]);
+        }
+        // Swap the last two new tets.
+        newface = fliptets[1];
+        fliptets[1] = fliptets[2];
+        fliptets[2] = newface;
+      } else {
+        // either a or b were swapped.
+        i = dummyflag;
+        // Down-shift new tets i times.
+        for (; i > 0; i--) {
+          newface = fliptets[0];
+          fliptets[0] = fliptets[2];
+          fliptets[2] = fliptets[1];
+          fliptets[1] = newface;
+        }
+      }
+    }
+  }
+
+  if (flipflag > 0) {
+    // Queue faces which may be locally non-Delaunay.  
+    pd = dest(fliptets[0]);
+    for (i = 0; i < 3; i++) {
+      enext2fnext(fliptets[i], newface);
+      futureflip = flippush(futureflip, &newface, pd);
+    }
+    if (flipflag > 1) {
+      pe = org(fliptets[0]);
+      for (i = 0; i < 3; i++) {
+        enextfnext(fliptets[i], newface);
+        futureflip = flippush(futureflip, &newface, pe);
+      }
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flip32()    Remove an edge by transforming 3-to-2 tetrahedra.             //
+//                                                                           //
+// 'flipedge' (ab) is shared by three tets: edab, edbc, and edca. This rout- //
+// ine replaces them by two new tets:  abcd and bace.  As a result, the edge //
+// ab is replaced by the face abc. On return, 'flipedge' is abcd.            //
+//                                                                           //
+// If 'hullflag' > 0, one of {a, b, c, d, e} may be 'dummypoint'. There may  //
+// be hull tets involved in this flip.  There are two cases:                 //
+//   (1) If d is 'dummypoint', then abcd is hull tet, and bace is normal.    //
+//       If e is 'dummypoint', we reconfigure e to d, i.e., turnover it.     //
+//   (2) If c is 'dummypoint' then both abcd and bace are hull tets.         //
+//       If a or b is 'dummypoint', we reconfigure it to c, i.e., rotate the //
+//       three old tets counterclockwisely (right-hand rule) until a or b    //
+//       is in c's position (see Fig.).                                      //
+//                                                                           //
+// If 'flipflag != 0', the convex hull faces will be checked and flipped if  //
+// they are locally non-Delaunay. If 'flipflag == 1', we assume that a is a  //
+// newly inserted vertex, so only the two opposite faces of the convex hull  //
+// will be checked (this avoids unnecessary insphere() testes).              //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::flip32(triface* fliptets, int hullflag, int flipflag)
+{
+  triface topcastets[3], botcastets[3];
+  triface newface, casface;
+  point pa, pb, pc, pd, pe;
+  int dummyflag;  // Rangle = {-1, 0, 1, 2}
+  int i;
+
+  face *pssub, checksh;
+  face checkseg;
+
+  int *iptr; 
+
+  if (hullflag > 0) {
+    // Check if e is 'dummypoint'.
+    if (org(fliptets[0]) == dummypoint) {
+      // Reverse the edge.
+      for (i = 0; i < 3; i++) {
+        enext0fnextself(fliptets[i]);
+        esymself(fliptets[i]);
+      }
+      // Swap the last two tets.
+      newface = fliptets[1];
+      fliptets[1] = fliptets[2];
+      fliptets[2] = newface;
+      dummyflag = -1; // e is dummypoint.
+    } else {
+      // Check if a or b is the 'dummypoint'.
+      if (apex(fliptets[0]) == dummypoint) { 
+        dummyflag = 1;  // a is dummypoint.
+      } else if (apex(fliptets[1]) == dummypoint) {
+        dummyflag = 2;  // b is dummypoint.
+      } else {
+        dummyflag = 0;  // either c or d is dummypoint.
+      }
+      i = dummyflag;
+      // Down-shift i times.
+      for (; i > 0; i--) {
+        newface = fliptets[2];
+        fliptets[2] = fliptets[1];
+        fliptets[1] = fliptets[0];
+        fliptets[0] = newface;
+      }
+    }
+  }
+
+  pa = apex(fliptets[0]);
+  pb = apex(fliptets[1]);
+  pc = apex(fliptets[2]);
+  pd = dest(fliptets[0]);
+  pe = org(fliptets[0]);
+
+  if (b->verbose > 1) {
+    printf("    flip 3-to-2: (%d, %d, %d, %d, %d)\n", pointmark(pa),
+      pointmark(pb), pointmark(pc), pointmark(pd), pointmark(pe));
+  }
+  flip32count++;
+
+  // Get the outer boundary faces.
+  for (i = 0; i < 3; i++) {
+    enextfnext(fliptets[i], casface);
+    enextself(casface);
+    symedge(casface, topcastets[i]);
+  }
+  for (i = 0; i < 3; i++) {
+    enext2fnext(fliptets[i], casface);
+    enext2self(casface);
+    symedge(casface, botcastets[i]);
+  }
+
+  if (checksubsegs) {
+    // Check if the flip edge is subsegment.
+    tsspivot(fliptets[0], checkseg);
+    if ((checkseg.sh != NULL) && !sinfected(checkseg)) {
+      // This subsegment will be flipped. Queue it.
+      if (b->verbose > 1) {
+        printf("      Queue a flipped segment (%d, %d).\n",
+          pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
+      }
+      sinfect(checkseg);  // Only save it once.
+      subsegstack->newindex((void **) &pssub);
+      *pssub = checkseg;
+    }
+  }
+
+  if (checksubfaces) {
+    // Check if the three flip faces are subfaces.
+    for (i = 0; i < 3; i++) {
+      tspivot(fliptets[i], checksh);
+      if (checksh.sh != NULL) {
+        if (b->verbose > 1) {
+          printf("      Queue a flipped subface (%d, %d, %d).\n",
+            pointmark(sorg(checksh)), pointmark(sdest(checksh)),
+            pointmark(sapex(checksh)));
+        }
+        stdissolve(checksh); // Disconnect the sub-tet bond.
+        // Add the missing subface into list.
+        subfacstack->newindex((void **) &pssub);
+        *pssub = checksh;
+      }
+    }
+  }
+
+  // Re-use fliptets[0] and fliptets[1].
+  fliptets[0].loc = fliptets[0].ver = 0;
+  fliptets[1].loc = fliptets[1].ver = 0;
+  elemmarker(fliptets[0].tet) = 0;
+  elemmarker(fliptets[1].tet) = 0;
+  if (checksubsegs) {
+    // Dealloc the space to subsegments.
+    if (fliptets[0].tet[8] != NULL) {
+      tet2segpool->dealloc((shellface *) fliptets[0].tet[8]);
+    }
+    fliptets[0].tet[8] = NULL;
+    if (fliptets[1].tet[8] != NULL) {
+      tet2segpool->dealloc((shellface *) fliptets[1].tet[8]);
+    }
+    fliptets[1].tet[8] = NULL;
+  }
+  if (checksubfaces) {
+    // Dealloc the space to subfaces.
+    if (fliptets[0].tet[9] != NULL) {
+      tet2subpool->dealloc((shellface *) fliptets[0].tet[9]);
+    }
+    fliptets[0].tet[9] = NULL;
+    if (fliptets[1].tet[9] != NULL) {
+      tet2subpool->dealloc((shellface *) fliptets[1].tet[9]);
+    }
+    fliptets[1].tet[9] = NULL;
+  }
+
+  // Delete an old tet.
+  tetrahedrondealloc(fliptets[2].tet);
+
+  if (hullflag > 0) {
+    // Check if c is dummypointc.
+    if (pc != dummypoint) {
+      // Check if d is dummypoint.
+      if (pd != dummypoint) {
+        // No hull tet is involved.
+      } else {
+        // We removed three old hull tets, and added on new hull tet.
+        hullsize -= 2;
+      }
+      setvertices(fliptets[0], pa, pb, pc, pd);
+      setvertices(fliptets[1], pb, pa, pc, pe);
+    } else {
+      // c is dummypoint. The two new tets are hull tets.
+      setvertices(fliptets[0], pb, pa, pd, pc);
+      setvertices(fliptets[1], pa, pb, pe, pc);
+      // Adjust badc -> abcd.
+      enext0fnextself(fliptets[0]);
+      esymself(fliptets[0]);
+      // Adjust abec -> bace.
+      enext0fnextself(fliptets[1]);
+      esymself(fliptets[1]);
+      // The hullsize does not changle.
+    }
+  } else {
+    setvertices(fliptets[0], pa, pb, pc, pd);
+    setvertices(fliptets[1], pb, pa, pc, pe);
+  }
+  
+  // Bond abcd <==> bace.
+  bond(fliptets[0], fliptets[1]);
+  // Bond new faces to top outer boundary faces (at abcd).
+  for (i = 0; i < 3; i++) {
+    enext0fnext(fliptets[0], newface);
+    bond(newface, topcastets[i]);
+    enextself(fliptets[0]);
+  }
+  // Bond new faces to bottom outer boundary faces (at bace).
+  for (i = 0; i < 3; i++) {
+    enext0fnext(fliptets[1], newface);
+    bond(newface, botcastets[i]);
+    enext2self(fliptets[1]);
+  }
+
+  if (checksubsegs) {
+    // Bond segments to new (flipped) tets.
+    for (i = 0; i < 3; i++) {
+      tsspivot(topcastets[i], checkseg);
+      if (checkseg.sh != NULL) {
+        tssbond1(fliptets[0], checkseg);
+      }
+      enextself(fliptets[0]);
+    }
+    // The three top edges.
+    for (i = 0; i < 3; i++) {
+      enext0fnext(fliptets[0], newface);
+      enextself(newface); // edge b->d, c->d, a->d.
+      enext(topcastets[i], casface);
+      tsspivot(casface, checkseg);
+      if (checkseg.sh != NULL) {
+        tssbond1(newface, checkseg);
+      }
+      enextself(fliptets[0]);
+    }
+    // Process the bottom tet bace.
+    for (i = 0; i < 3; i++) {
+      tsspivot(botcastets[i], checkseg);
+      if (checkseg.sh != NULL) {
+        tssbond1(fliptets[1], checkseg);
+      }
+      enext2self(fliptets[1]);
+    }
+    // The three bot edges.
+    for (i = 0; i < 3; i++) {
+      enext0fnext(fliptets[1], newface);
+      enext2self(newface); // edge b<-e, c<-e, a<-e.
+      enext2(botcastets[i], casface);
+      tsspivot(casface, checkseg);
+      if (checkseg.sh != NULL) {
+        tssbond1(newface, checkseg);
+      }
+      enext2self(fliptets[1]);
+    }
+  }
+
+  if (checksubfaces) {
+    // Bond the top three casing subfaces.
+    for (i = 0; i < 3; i++) {
+      tspivot(topcastets[i], checksh);
+      if (checksh.sh != NULL) {
+        enext0fnext(fliptets[0], newface);
+        tsbond(newface, checksh);
+      }
+      enextself(fliptets[0]);
+    }
+    // Bond the bottom three casing subfaces.
+    for (i = 0; i < 3; i++) {
+      tspivot(botcastets[i], checksh);
+      if (checksh.sh != NULL) {
+        enext0fnext(fliptets[1], newface);
+        tsbond(newface, checksh);
+      }
+      enext2self(fliptets[1]);
+    }
+  }
+
+  // if (checksubsegs || checksubfaces) {
+    // Update the point-to-tet map.
+    point2tet(pa) = encode(fliptets[0]);
+    point2tet(pb) = encode(fliptets[0]);
+    point2tet(pc) = encode(fliptets[0]);
+    point2tet(pd) = encode(fliptets[0]);
+    point2tet(pe) = encode(fliptets[1]);
+  // }
+
+  if (hullflag > 0) {
+    if (dummyflag != 0) {
+      // Restore the original position of the points (for flipnm()).
+      if (dummyflag == -1) {
+        // e were dummypoint. Swap the two new tets.
+        newface = fliptets[0];
+        fliptets[0] = fliptets[1];
+        fliptets[1] = newface;
+      } else {
+        // a or b was dummypoint.
+        i = dummyflag;
+        // Rotate toward left i times.
+        for (; i > 0; i--) {
+          enextself(fliptets[0]);
+          enext2self(fliptets[1]);
+        }
+      }
+    }
+  }
+  
+  if (flipflag > 0) {
+    // Queue faces which may be locally non-Delaunay.  
+    pa = org(fliptets[0]);
+    enextfnext(fliptets[0], newface);
+    futureflip = flippush(futureflip, &newface, pa);
+    enext2fnext(fliptets[1], newface);
+    futureflip = flippush(futureflip, &newface, pa);
+    if (flipflag > 1) {
+      pb = dest(fliptets[0]);
+      enext2fnext(fliptets[0], newface);
+      futureflip = flippush(futureflip, &newface, pb);
+      enextfnext(fliptets[1], newface);
+      futureflip = flippush(futureflip, &newface, pb);
+      pc = apex(fliptets[0]);
+      enext0fnext(fliptets[0], newface);
+      futureflip = flippush(futureflip, &newface, pc);
+      enext0fnext(fliptets[1], newface);
+      futureflip = flippush(futureflip, &newface, pc);
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// flipnm()    Remove an edge by transforming n-to-m tetrahedra.             //
+//                                                                           //
+// This routine attemps to remove an edge, denoted as ab, by transforming a  //
+// set K of n tetrahedra containing ab into a set K' of m tetrahedra, where  //
+// K and K' have the same outer boundary, and ab is not in K', where n >= 3, //
+// m = 2 * n - 4. It can be viwed as a n-to-m flip.                          //
+//                                                                           //
+// 'oldtets' contains n tets sharing at ab. Imaging that ab perpendicularly  //
+// crosses your screen, b lies in front of a. Let the projections of the n   //
+// apexes, denoted as p[0], p[1], ..., p[n-1], onto screen in counterclock-  //
+// wise order (right-hand rule). The n tets are: abp[0]p[1], abp[1]p[2],..., //
+// abp[n-1]p[0], respectively.  If one of p[i] is dummypoint, we reconfigure //
+// it such that p[0] is dummypoint. a or b should not be dummypoint.         //
+//                                                                           //
+// The principle of the transformation is to recursively reduce the link of  //
+// ab by perform 2-to-3 flips until the link size of ab is 3, hence a 3-to-2 //
+// flip can be applied to remove the edge.                                   //
+//                                                                           //
+// Consider a face abp[i] (i in [0, n-1]), a flip23() can be applied if the  //
+// edge p[(i-1) % n]p[(i+1) % n] crosses it in its interior. Relabel p[i] to //
+// c, p[(i-1) % n] to e, and p[(i+1) % n] to d. This transforms the two tets,//
+// abcd and bace, to three tets, edab, edbc, and edca. The tet edab remains  //
+// in the star of ab, while edbc, and edca do not. As a result, p[i] (c) is  //
+// not on the link of ab anymore. The link size is reduced by 1. A recursion //
+// can be applied if n - 1 > 3.                                              //
+//                                                                           //
+// NOTE: In above, the flip23() can be applied even if the edge de crosses   //
+// ab, i.e., a, b, e, and d are coplanar. Although this will creare a degen- //
+// erate tet edab (has zero volume), it will be removed after ab is removed. //
+//                                                                           //
+// The number m can be counted as follows: there are n - 3 '2-to-3' flips, 1 //
+// '3-to-2' flip. Each '2-to-3' flip produces two new tets, and the '3-to-2' //
+// flip produces two new tets, hence m = (n - 3) * 2 + 2 = 2 * n - 4.        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+bool tetgenmesh::flipnm(int n, triface* oldtets, triface* newtets,
+  bool delaunay, queue* flipque)
+{
+  triface *recuroldtets, tmpoldtets[2], baktet;
+  point pa, pb, pc, pd, pe, pf;
+  bool success, doflip;
+  REAL sign, ori;
+  int *iptr, i, j;
+
+  // Check if any apex of ab is dummypoint.
+  for (i = n - 1; i > 0; i--) {
+    if (apex(oldtets[i]) == dummypoint) break;
+  }
+  // Now i is the shift distance to the first one.
+  for (; i > 0; i--) {
+    baktet = oldtets[0];
+    for (j = 0; j < n - 1; j++) {
+      oldtets[j] = oldtets[j + 1];
+    }
+    oldtets[n - 1] = baktet;
+  }
+
+  pa = org(oldtets[0]);
+  pb = dest(oldtets[0]);
+
+  if (b->verbose > 1) {
+    printf("    flip %d-to-%d: (%d, %d)\n", n, 2 * n - 4, pointmark(pa),
+           pointmark(pb));
+  }
+  flipnmcount++;
+
+  success = false;
+
+  for (i = 0; i < n; i++) {
+    pc = apex(oldtets[i]);
+    pd = apex(oldtets[(i + 1) % n]);
+    pe = apex(oldtets[(i != 0) ? i - 1 : n - 1]);
+    // Decide if the face abc is flipable.
+    if (pc != dummypoint) {
+      if ((pd != dummypoint) && (pc != dummypoint)) {
+        ori = orient3d(pa, pb, pd, pe);
+        if (ori >= 0) {  // Allow ori == 0, support 4-to-4 flip.
+          ori = orient3d(pb, pc, pd, pe);
+          if (ori > 0) {
+            ori = orient3d(pc, pa, pd, pe);
+          }
+        }
+        doflip = ori > 0;
+        if (doflip && delaunay) {
+          // Only do flip if abc is not a locally Delaunay face.
+          sign = insphere_sos(pa, pb, pc, pd, pe);
+          doflip = (sign < 0);
+        }
+      } else {
+        doflip = false;
+      }
+    } else {
+      // Two faces abd and abe are on the hull.
+      doflip = true; // 2-to-2 flip is possible.
+      if (delaunay) {
+        // Only do flip if ab is not a locally Delaunay edge.
+        pf = apex(oldtets[(i + 2) % n]);
+        sign = insphere_sos(pa, pb, pd, pf, pe);
+        doflip = (sign < 0);
+      }
+    }
+    if (doflip) {
+      // Get the two old tets.
+      tmpoldtets[0] = oldtets[i];
+      tmpoldtets[1] = oldtets[(i != 0) ? i - 1 : n - 1];
+      // Adjust tmpoldtets[1] (abec) -> bace.
+      enext0fnextself(tmpoldtets[1]);
+      esymself(tmpoldtets[1]);
+      // Adjust the tets so that newtets[2] will be edca (see Fig.).
+      enextself(tmpoldtets[0]);
+      enext2self(tmpoldtets[1]);
+      // Do flip23() on abp[i] (abc).
+      flip23(tmpoldtets, newtets, flipque);
+      // Form the new star of ab which has n-1 tets.
+      recuroldtets = new triface[n - 1];
+      // Set the remaining n-2 tets around ab.
+      for (j = 0; j < n - 2 ; j++) {
+        recuroldtets[j] = oldtets[(i + 1 + j) % n];
+      }
+      // Put the last tet having ab. Leave a copy in baktet.
+      recuroldtets[j] = baktet = newtets[2];
+      // Adjust recuroldtets[j] to abp[0]p[1] (see Fig.).
+      enext2fnextself(recuroldtets[j]);  // j == n - 2;
+      enext2self(recuroldtets[j]);
+      esymself(recuroldtets[j]);
+      // Check the size of the link of ab.
+      if (n > 4) {  // Actually, if (n - 1 > 3)
+        // Recursively do flipnm().
+        success = flipnm(n-1, recuroldtets, &(newtets[2]), delaunay, flipque);
+        // Are we success?
+        if (!success) {
+          if (!delaunay) {
+            // No! Reverse the flip23() operation.
+            newtets[2] = baktet; // Do we really need this?
+            flip32(newtets, tmpoldtets, flipque);
+            // Adjust the tets back to original position (see Fig.).
+            enext2self(tmpoldtets[0]);
+            enextself(tmpoldtets[1]);
+            // Adjust back to abp[(i-1) % n].
+            enext0fnextself(tmpoldtets[1]);
+            esymself(tmpoldtets[1]);
+            // Delete the two original old tets first.
+            tetrahedrondealloc(oldtets[i].tet);
+            tetrahedrondealloc(oldtets[(i != 0) ? i - 1 : n - 1].tet);
+            // Set the tets back to their original positions.
+            oldtets[i] = tmpoldtets[0];
+            oldtets[(i != 0) ? i - 1 : n - 1] = tmpoldtets[1];
+            // Delete the three new tets.
+            tetrahedrondealloc(newtets[0].tet);
+            tetrahedrondealloc(newtets[1].tet);
+            tetrahedrondealloc(newtets[2].tet); // = recuroldtets[j].tet
+          } else {
+            // Only delete the first two old tets. Their common face is
+            //   not locally Delaunay and has been flipped.
+            tetrahedrondealloc(oldtets[i].tet);
+            tetrahedrondealloc(oldtets[(i != 0) ? i - 1 : n - 1].tet);
+            // Here the tet recuroldtets[j] does not get deleted. It is
+            //   a part of current mesh.
+          }
+        } else {
+          // Delete the last tet in 'recuroldtets'. This tet is neither in
+          //   'oldtets' nor in 'newtets'.
+          tetrahedrondealloc(recuroldtets[j].tet);  // j == n - 2
+        } 
+      } else {
+        // Remove ab by a flip32().
+        flip32(recuroldtets, &(newtets[2]), flipque);
+        // Delete the last tet in 'recuroldtets'. This one is just created
+        //   by the flip 2-to-3 operation within this routine.
+        tetrahedrondealloc(recuroldtets[j].tet);  // j == n - 2
+        success = true;
+      }      
+      // The other tets in 'recuroldtets' are still in 'oldtets'.
+      delete [] recuroldtets;
+      break;
+    } // if (doflip)
+  } // for (i = 0; i < n; i++)
+  
+  return success;
+}
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// lawsonflip()    Flip non-locally Delaunay faces by primitive flips.       //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::lawsonflip3d(int flipflag)
+{ 
+  triface fliptets[5], baktets[2];
+  triface fliptet, neightet, *parytet;
+  face checksh, checkseg;
+  point *pt, pd, pe;
+  REAL sign, ori;
+  long flipcount;
+  // bool bflag; // for flipflag = 3.
+  int n, i;
+
+  int *iptr;
+
+  if (b->verbose > 1) {
+    printf("    Lawson flip %ld faces.\n", flippool->items);
+    flipcount = flip23count + flip32count;
+  }
+
+  while (futureflip != (badface *) NULL) {
+
+    // Pop a face from the stack.
+    fliptet = futureflip->tt;  // abcd (may be a hull tet)
+    pd = futureflip->foppo;  // The new vertex.
+    futureflip = futureflip->nextitem;
+
+    // Skip it if it is a dead tet.
+    if (fliptet.tet[4] == NULL) continue;
+    // Skip it if it is not the same tet as we saved.
+    if (oppo(fliptet) != pd) continue;
+
+    // Get its opposite tet.
+    fliptet.ver = 4;
+    symedge(fliptet, neightet);
+
+    if ((point) neightet.tet[7] == dummypoint) {
+      // A hull tet. Check if its base face is visible by d.
+      pt = (point *) neightet.tet;
+      ori = orient3d(pt[4], pt[5], pt[6], pd); orient3dcount++;
+      if (ori < 0) {
+        // Visible! Found a 2-to-3 flip on abc.
+        fliptets[0] = fliptet;
+        fliptets[1] = neightet;
+        flip23(fliptets, 1, flipflag); // flip a hull tet.
+        recenttet = fliptets[0];
+      } else if (ori == 0) {
+        // Handle degenerate case ori == 0.
+        if (oppo(fliptet) == oppo(neightet)) {
+          // Two hull tets (fliptet and neightet) have the same base face.
+          for (i = 0; i < 3; i++) {
+            fnext(fliptet, fliptets[0]);
+            fnext(neightet, fliptets[1]);
+            bond(fliptets[0], fliptets[1]);
+            if (i == 0) {
+              // apex(fliptets[0]) is the new point. The opposite face may
+              // be not locally Delaunay. Put it in flip stack.
+              // assert(apex(fliptets[0]) == pd); // SELF_CHECK
+              enext0fnextself(fliptets[0]);
+              futureflip = flippush(futureflip, &(fliptets[0]), pd);
+              // assert(apex(fliptets[1]) == pd); // SELF_CHECK
+              enext0fnextself(fliptets[1]);
+              futureflip = flippush(futureflip, &(fliptets[1]), pd);
+            }
+            enextself(fliptet);
+            enext2self(neightet);
+          }
+          // Delete the two tets.
+          tetrahedrondealloc(fliptet.tet);
+          tetrahedrondealloc(neightet.tet);
+          // Update the hull size.
+          hullsize -= 2;
+        }
+      }
+      continue;
+    }
+
+    pe = oppo(neightet);
+    pt = (point *) fliptet.tet;
+    // assert((point) fliptet.tet[7] != dummypoint); // SELF_CHECK
+
+    sign = insphere_sos(pt[4], pt[5], pt[6], pt[7], pe);
+
+    if (b->verbose > 2) {
+      printf("  Insphere: (%d, %d, %d) %d, %d\n", pointmark(org(fliptet)),
+        pointmark(dest(fliptet)), pointmark(apex(fliptet)),
+        pointmark(oppo(fliptet)), pointmark(pe));
+    }
+     
+    // Flip it if it is not locally Delaunay.
+    if (sign < 0) {
+      // Check the convexity of its three edges.
+      fliptet.ver = 0;
+      for (i = 0; i < 3; i++) {
+        ori = orient3d(org(fliptet), dest(fliptet), pd, pe); orient3dcount++;
+        if (ori <= 0) break;
+        enextself(fliptet);
+      }
+      if (i == 3) {
+        // A 2-to-3 flip is found.
+        // if (flipflag == 3) {
+        //   // Do not flip a subface.
+        //   tspivot(fliptet, checksh);
+        //   bflag = (checksh.sh == NULL);
+        // } else {
+        //   bflag = true;
+        // }
+        // if (bflag) {
+          fliptets[0] = fliptet; // tet abcd, d is the new vertex.
+          symedge(fliptets[0], fliptets[1]); // tet bace.
+          flip23(fliptets, 0, flipflag);
+          recenttet = fliptets[0]; // for point location.
+        // }
+      } else {
+        // A 3-to-2 or 4-to-4 may possible.
+        // if (flipflag == 3) {
+        //   // Do not flip a subsegment.
+        //   tsspivot(fliptet, checkseg);
+        //   bflag = (checkseg.sh == NULL);
+        // } else {
+        //   bflag = true;
+        // }
+        // if (bflag) {
+          enext0fnext(fliptet, fliptets[0]);
+          esymself(fliptets[0]); // tet badc, d is the new vertex.
+          n = 0;
+          do {
+            fnext(fliptets[n], fliptets[n + 1]);
+            n++;
+          } while ((fliptets[n].tet != fliptet.tet) && (n < 5));
+          if (n == 3) {
+            // Found a 3-to-2 flip.
+            flip32(fliptets, 0, flipflag);
+            recenttet = fliptets[0]; // for point location.
+          } else if ((n == 4) && (ori == 0)) {
+            // Find a 4-to-4 flip.
+            flipnmcount++;
+            // First do a 2-to-3 flip.
+            fliptets[0] = fliptet; // tet abcd, d is the new vertex.
+            baktets[0] = fliptets[2];
+            baktets[1] = fliptets[3];
+            flip23(fliptets, 1, flipflag); // hull tet may involve.
+            // Then do a 3-to-2 flip. 
+            enextfnextself(fliptets[0]);  // fliptets[0] is edab.
+            enextself(fliptets[0]);
+            esymself(fliptets[0]);  // tet badc, d is the new vertex.
+            fliptets[1] = baktets[0];
+            fliptets[2] = baktets[1];
+            flip32(fliptets, 1, flipflag); // hull tet may involve.
+            recenttet = fliptets[0]; // for point location.
+          } else {
+            // An unflipable face. Will be flipped later.
+            if (flipflag > 1) {
+              // Queue all other faces at the edge for flipping.
+              pe = apex(fliptets[0]);
+              fliptets[1] = fliptets[0];
+              while (1) {
+                pd = oppo(fliptets[1]);
+                futureflip = flippush(futureflip, &fliptets[1], pd);
+                fnextself(fliptets[1]);
+                if (apex(fliptets[1]) == pe) break;
+              }
+            }
+          }
+        // } // bflag
+      } // if (i == 3)
+    } // if (sign < 0)
+  }
+
+  if (b->verbose > 1) {
+    printf("    %ld faces stacked, %ld flips.\n", flippool->items, 
+      flip23count + flip32count - flipcount);
+  }
+
+  flippool->restart();
+}
+
+#endif // #ifndef flipCXX
\ No newline at end of file
diff --git a/contrib/Tetgen/geom.cxx b/contrib/Tetgen/geom.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..275df658dd2f88317b096ae9d460eefcc14d2dc4
--- /dev/null
+++ b/contrib/Tetgen/geom.cxx
@@ -0,0 +1,4517 @@
+#ifndef geomCXX
+#define geomCXX
+
+#include "tetgen.h"
+
+REAL tetgenmesh::PI = 3.14159265358979323846264338327950288419716939937510582;
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// tri_edge_2d()    Triangle-edge coplanar intersection test.                //
+//                                                                           //
+// This routine takes a triangle T (with vertices A, B, C) and an edge E (P, //
+// Q) in a plane in 3D, and tests if they intersect each other.  Return 1 if //
+// they are intersected, i.e., T \cap E is not empty, otherwise, return 0.   //
+//                                                                           //
+// If the point 'R' is not NULL, it lies strictly above T [A, B, C].         //
+//                                                                           //
+// If T1 and T2 intersect each other (return 1), they may intersect in diff- //
+// erent ways. If 'level' > 0, their intersection type will be reported in   //
+// combinations of 'types' and 'pos'.                                        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+int tetgenmesh::tri_edge_2d(point A, point B, point C, point P, point Q, 
+  point R, int level, int *types, int *pos)
+{
+  point U[3], V[3];  // The permuted vectors of points.
+  int pu[3], pv[3];  // The original positions of points.
+  REAL sA, sB, sC;
+  REAL s1, s2, s3, s4;
+  int z1;
+
+  if (R == NULL) {
+    REAL n[3], len;
+    // Calculate a lift point, saved in dummypoint.
+    facenormal(A, B, C, n, 1);
+    len = sqrt(DOT(n, n));
+    n[0] /= len;
+    n[1] /= len;
+    n[2] /= len;
+    len = DIST(A, B);
+    len += DIST(B, C);
+    len += DIST(C, A);
+    len /= 3.0;
+    R = dummypoint;
+    R[0] = A[0] + len * n[0];
+    R[1] = A[1] + len * n[1];
+    R[2] = A[2] + len * n[2];
+  }
+
+  // Test A's, B's, and C's orientations wrt plane PQR. 
+  sA = orient3d(P, Q, R, A);
+  sB = orient3d(P, Q, R, B);
+  sC = orient3d(P, Q, R, C);
+  orient3dcount+=3;
+
+  if (b->epsilon) {
+    // Re-evaluate the sign with respect to the tolerance.
+    if ((sA != 0) && iscoplanar(P, Q, R, A, sA)) sA = 0;
+    if ((sB != 0) && iscoplanar(P, Q, R, B, sB)) sB = 0;
+    if ((sC != 0) && iscoplanar(P, Q, R, C, sC)) sC = 0;
+  }
+
+  if (b->verbose > 2) {
+    printf("      Tri-edge-2d (%d %d %d)-(%d %d)-(%d) (%c%c%c)", pointmark(A),
+      pointmark(B), pointmark(C), pointmark(P), pointmark(Q), pointmark(R),
+      sA > 0 ? '+' : (sA < 0 ? '-' : '0'), sB>0 ? '+' : (sB<0 ? '-' : '0'),
+      sC>0 ? '+' : (sC<0 ? '-' : '0'));
+  }
+  triedgcopcount++;
+
+  if (sA < 0) {
+    if (sB < 0) {
+      if (sC < 0) { // (---).
+        return 0; 
+      } else {
+        if (sC > 0) { // (--+).
+          // All points are in the right positions.
+          SETVECTOR3(U, A, B, C);  // I3
+          SETVECTOR3(V, P, Q, R);  // I2
+          SETVECTOR3(pu, 0, 1, 2);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 0;
+        } else { // (--0).
+          SETVECTOR3(U, A, B, C);  // I3
+          SETVECTOR3(V, P, Q, R);  // I2
+          SETVECTOR3(pu, 0, 1, 2);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 1;
+        }
+      }
+    } else { 
+      if (sB > 0) {
+        if (sC < 0) { // (-+-).
+          SETVECTOR3(U, C, A, B);  // PT = ST
+          SETVECTOR3(V, P, Q, R);  // I2
+          SETVECTOR3(pu, 2, 0, 1);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 0;
+        } else {
+          if (sC > 0) { // (-++).
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 1, 2, 0);
+            SETVECTOR3(pv, 1, 0, 2);
+            z1 = 0;
+          } else { // (-+0).
+            SETVECTOR3(U, C, A, B);  // PT = ST
+            SETVECTOR3(V, P, Q, R);  // I2
+            SETVECTOR3(pu, 2, 0, 1);
+            SETVECTOR3(pv, 0, 1, 2);
+            z1 = 2;
+          }
+        }
+      } else {
+        if (sC < 0) { // (-0-).
+          SETVECTOR3(U, C, A, B);  // PT = ST
+          SETVECTOR3(V, P, Q, R);  // I2
+          SETVECTOR3(pu, 2, 0, 1);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 1;
+        } else {
+          if (sC > 0) { // (-0+).
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 1, 2, 0);
+            SETVECTOR3(pv, 1, 0, 2);
+            z1 = 2;
+          } else { // (-00).
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 1, 2, 0);
+            SETVECTOR3(pv, 1, 0, 2);
+            z1 = 3; 
+          }
+        }
+      }
+    }
+  } else {
+    if (sA > 0) {
+      if (sB < 0) {
+        if (sC < 0) { // (+--).
+          SETVECTOR3(U, B, C, A);  // PT = ST x ST
+          SETVECTOR3(V, P, Q, R);  // I2
+          SETVECTOR3(pu, 1, 2, 0);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 0;
+        } else {
+          if (sC > 0) { // (+-+).
+            SETVECTOR3(U, C, A, B);  // PT = ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 2, 0, 1);
+            SETVECTOR3(pv, 1, 0, 2);
+            z1 = 0;
+          } else { // (+-0).
+            SETVECTOR3(U, C, A, B);  // PT = ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 2, 0, 1);
+            SETVECTOR3(pv, 1, 0, 2);
+            z1 = 2;
+          }
+        }
+      } else { 
+        if (sB > 0) {
+          if (sC < 0) { // (++-).
+            SETVECTOR3(U, A, B, C);  // I3
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 0, 1, 2);
+            SETVECTOR3(pv, 1, 0, 2);
+            z1 = 0;
+          } else {
+            if (sC > 0) { // (+++).
+              return 0; 
+            } else { // (++0).
+              SETVECTOR3(U, A, B, C);  // I3
+              SETVECTOR3(V, Q, P, R);  // PL = SL
+              SETVECTOR3(pu, 0, 1, 2);
+              SETVECTOR3(pv, 1, 0, 2);
+              z1 = 1; 
+            }
+          }
+        } else { // (+0#)
+          if (sC < 0) { // (+0-).
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(V, P, Q, R);  // I2
+            SETVECTOR3(pu, 1, 2, 0);
+            SETVECTOR3(pv, 0, 1, 2);
+            z1 = 2;
+          } else {
+            if (sC > 0) { // (+0+).
+              SETVECTOR3(U, C, A, B);  // PT = ST
+              SETVECTOR3(V, Q, P, R);  // PL = SL
+              SETVECTOR3(pu, 2, 0, 1);
+              SETVECTOR3(pv, 1, 0, 2);
+              z1 = 1;
+            } else { // (+00).
+              SETVECTOR3(U, B, C, A);  // PT = ST x ST
+              SETVECTOR3(V, P, Q, R);  // I2
+              SETVECTOR3(pu, 1, 2, 0);
+              SETVECTOR3(pv, 0, 1, 2);
+              z1 = 3; 
+            }
+          }
+        }
+      }
+    } else { 
+      if (sB < 0) {
+        if (sC < 0) { // (0--).
+          SETVECTOR3(U, B, C, A);  // PT = ST x ST
+          SETVECTOR3(V, P, Q, R);  // I2
+          SETVECTOR3(pu, 1, 2, 0);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 1;
+        } else {
+          if (sC > 0) { // (0-+).
+            SETVECTOR3(U, A, B, C);  // I3
+            SETVECTOR3(V, P, Q, R);  // I2
+            SETVECTOR3(pu, 0, 1, 2);
+            SETVECTOR3(pv, 0, 1, 2);
+            z1 = 2;
+          } else { // (0-0).
+            SETVECTOR3(U, C, A, B);  // PT = ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 2, 0, 1);
+            SETVECTOR3(pv, 1, 0, 2);
+            z1 = 3; 
+          }
+        }
+      } else { 
+        if (sB > 0) {
+          if (sC < 0) { // (0+-).
+            SETVECTOR3(U, A, B, C);  // I3
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 0, 1, 2);
+            SETVECTOR3(pv, 1, 0, 2);
+            z1 = 2;
+          } else {
+            if (sC > 0) { // (0++).
+              SETVECTOR3(U, B, C, A);  // PT = ST x ST
+              SETVECTOR3(V, Q, P, R);  // PL = SL
+              SETVECTOR3(pu, 1, 2, 0);
+              SETVECTOR3(pv, 1, 0, 2);
+              z1 = 1;
+            } else { // (0+0).
+              SETVECTOR3(U, C, A, B);  // PT = ST
+              SETVECTOR3(V, P, Q, R);  // I2
+              SETVECTOR3(pu, 2, 0, 1);
+              SETVECTOR3(pv, 0, 1, 2);
+              z1 = 3; 
+            }
+          }
+        } else { // (00#)
+          if (sC < 0) { // (00-).
+            SETVECTOR3(U, A, B, C);  // I3
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 0, 1, 2);
+            SETVECTOR3(pv, 1, 0, 2);
+            z1 = 3; 
+          } else {
+            if (sC > 0) { // (00+).
+              SETVECTOR3(U, A, B, C);  // I3
+              SETVECTOR3(V, P, Q, R);  // I2
+              SETVECTOR3(pu, 0, 1, 2);
+              SETVECTOR3(pv, 0, 1, 2);
+              z1 = 3; 
+            } else { // (000)
+              // Not possible unless ABC is degenerate.
+              z1 = 4;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  s1 = orient3d(U[0], U[2], R, V[1]);  // A, C, R, Q
+  s2 = orient3d(U[1], U[2], R, V[0]);  // B, C, R, P
+  orient3dcount+=2;
+
+  if (b->epsilon) {
+    if ((s1 != 0) && iscoplanar(U[0], U[2], R, V[1], s1)) s1 = 0;
+    if ((s2 != 0) && iscoplanar(U[1], U[2], R, V[0], s2)) s2 = 0;
+  }
+
+  if (b->verbose > 2) {
+    printf("      Tri-edge-2d (%d %d %d)-(%d %d %d) (%d) (%c%c)\n",
+      pointmark(U[0]), pointmark(U[1]), pointmark(U[2]), pointmark(V[0]),
+      pointmark(V[1]), pointmark(V[2]), z1, s1>0 ? '+' : (s1<0 ? '-' : '0'),
+      s2>0 ? '+' : (s2<0 ? '-' : '0'));
+  }
+  assert(z1 != 4); // SELF_CHECK
+
+  if (s1 > 0) {
+    return 0;
+  }
+  if (s2 < 0) {
+    return 0;
+  }
+
+  if (level == 0) {
+    return 1;  // They are intersected.
+  }
+
+  if (z1 == 1) {
+    if (s1 == 0) {  // (0###)
+      // C = Q.
+      types[0] = (int) SHAREVERT;
+      pos[0] = pu[2]; // C
+      pos[1] = pv[1]; // Q
+      types[1] = (int) DISJOINT;
+    } else {
+      if (s2 == 0) { // (#0##)
+        // C = P.
+        types[0] = (int) SHAREVERT;
+        pos[0] = pu[2]; // C
+        pos[1] = pv[0]; // P
+        types[1] = (int) DISJOINT;
+      } else { // (-+##)
+        // C in [P, Q].
+        types[0] = (int) ACROSSVERT;
+        pos[0] = pu[2]; // C
+        pos[1] = pv[0]; // [P, Q]
+        types[1] = (int) DISJOINT;
+      }
+    }
+    return 1;
+  }
+
+  s3 = orient3d(U[0], U[2], R, V[0]);  // A, C, R, P
+  s4 = orient3d(U[1], U[2], R, V[1]);  // B, C, R, Q
+  orient3dcount+=2;
+      
+  if (b->epsilon) {
+    if ((s3 != 0) && iscoplanar(U[0], U[2], R, V[0], s3)) s3 = 0;
+    if ((s4 != 0) && iscoplanar(U[1], U[2], R, V[1], s4)) s4 = 0;
+  }
+
+  if (z1 == 0) {  // (tritri-03)
+    if (s1 < 0) {
+      if (s3 > 0) {
+        assert(s2 > 0); // SELF_CHECK
+        if (s4 > 0) {
+          // [P, Q] overlaps [k, l] (-+++).
+          types[0] = (int) ACROSSEDGE;
+          pos[0] = pu[2]; // [C, A]
+          pos[1] = pv[0]; // [P, Q]
+          types[1] = (int) TOUCHFACE;
+          pos[2] = 3;     // [A, B, C]
+          pos[3] = pv[1]; // Q
+        } else {
+          if (s4 == 0) {
+            // Q = l, [P, Q] contains [k, l] (-++0).
+            types[0] = (int) ACROSSEDGE;
+            pos[0] = pu[2]; // [C, A]
+            pos[1] = pv[0]; // [P, Q]
+            types[1] = (int) TOUCHEDGE;
+            pos[2] = pu[1]; // [B, C]
+            pos[3] = pv[1]; // Q
+          } else { // s4 < 0
+            // [P, Q] contains [k, l] (-++-).
+            types[0] = (int) ACROSSEDGE;
+            pos[0] = pu[2]; // [C, A]
+            pos[1] = pv[0]; // [P, Q]
+            types[1] = (int) ACROSSEDGE;
+            pos[2] = pu[1]; // [B, C]
+            pos[3] = pv[0]; // [P, Q]
+          }
+        }
+      } else {
+        if (s3 == 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // P = k, [P, Q] in [k, l] (-+0+).
+            types[0] = (int) TOUCHEDGE;
+            pos[0] = pu[2]; // [C, A]
+            pos[1] = pv[0]; // P
+            types[1] = (int) TOUCHFACE;
+            pos[2] = 3;     // [A, B, C]
+            pos[3] = pv[1]; // Q
+          } else {
+            if (s4 == 0) {
+              // [P, Q] = [k, l] (-+00).
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = pu[2]; // [C, A]
+              pos[1] = pv[0]; // P
+              types[1] = (int) TOUCHEDGE;
+              pos[2] = pu[1]; // [B, C]
+              pos[3] = pv[1]; // Q
+            } else {
+              // P = k, [P, Q] contains [k, l] (-+0-).
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = pu[2]; // [C, A]
+              pos[1] = pv[0]; // P
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = pu[1]; // [B, C]
+              pos[3] = pv[0]; // [P, Q]
+            }
+          }
+        } else { // s3 < 0
+          if (s2 > 0) {
+            if (s4 > 0) {
+              // [P, Q] in [k, l] (-+-+).
+              types[0] = (int) TOUCHFACE;
+              pos[0] = 3;     // [A, B, C]
+              pos[1] = pv[0]; // P
+              types[1] = (int) TOUCHFACE;
+              pos[2] = 3;     // [A, B, C]
+              pos[3] = pv[1]; // Q
+            } else {
+              if (s4 == 0) {
+                // Q = l, [P, Q] in [k, l] (-+-0).
+                types[0] = (int) TOUCHFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = pv[0]; // P
+                types[1] = (int) TOUCHEDGE;
+                pos[2] = pu[1]; // [B, C]
+                pos[3] = pv[1]; // Q
+              } else { // s4 < 0
+                // [P, Q] overlaps [k, l] (-+--).
+                types[0] = (int) TOUCHFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = pv[0]; // P
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = pu[1]; // [B, C]
+                pos[3] = pv[0]; // [P, Q]
+              }
+            }
+          } else { // s2 == 0
+            // P = l (#0##).
+            types[0] = (int) TOUCHEDGE;
+            pos[0] = pu[1]; // [B, C]
+            pos[1] = pv[0]; // P
+            types[1] = (int) DISJOINT;
+          }
+        }
+      }
+    } else { // s1 == 0
+      // Q = k (0####)
+      types[0] = (int) TOUCHEDGE;
+      pos[0] = pu[2]; // [C, A]
+      pos[1] = pv[1]; // Q
+      types[1] = (int) DISJOINT;
+    }
+  } else if (z1 == 2) {  // (tritri-23)
+    if (s1 < 0) {
+      if (s3 > 0) {
+        assert(s2 > 0); // SELF_CHECK
+        if (s4 > 0) {
+          // [P, Q] overlaps [A, l] (-+++).
+          types[0] = (int) ACROSSVERT;
+          pos[0] = pu[0]; // A
+          pos[1] = pv[0]; // [P, Q]
+          types[1] = (int) TOUCHFACE;
+          pos[2] = 3;     // [A, B, C]
+          pos[3] = pv[1]; // Q
+        } else {
+          if (s4 == 0) {
+            // Q = l, [P, Q] contains [A, l] (-++0).
+            types[0] = (int) ACROSSVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = pv[0]; // [P, Q]
+            types[1] = (int) TOUCHEDGE;
+            pos[2] = pu[1]; // [B, C]
+            pos[3] = pv[1]; // Q
+          } else { // s4 < 0
+            // [P, Q] contains [A, l] (-++-).
+            types[0] = (int) ACROSSVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = pv[0]; // [P, Q]
+            types[1] = (int) ACROSSEDGE;
+            pos[2] = pu[1]; // [B, C]
+            pos[3] = pv[0]; // [P, Q]
+          }
+        }
+      } else {
+        if (s3 == 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // P = A, [P, Q] in [A, l] (-+0+).
+            types[0] = (int) SHAREVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = pv[0]; // P
+            types[1] = (int) TOUCHFACE;
+            pos[2] = 3;     // [A, B, C]
+            pos[3] = pv[1]; // Q
+          } else {
+            if (s4 == 0) {
+              // [P, Q] = [A, l] (-+00).
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = pv[0]; // P
+              types[1] = (int) TOUCHEDGE;
+              pos[2] = pu[1]; // [B, C]
+              pos[3] = pv[1]; // Q
+            } else { // s4 < 0
+              // Q = l, [P, Q] in [A, l] (-+0-).
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = pv[0]; // P
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = pu[1]; // [B, C]
+              pos[3] = pv[0]; // [P, Q]
+            }
+          }
+        } else { // s3 < 0
+          if (s2 > 0) {
+            if (s4 > 0) {
+              // [P, Q] in [A, l] (-+-+).
+              types[0] = (int) TOUCHFACE;
+              pos[0] = 3;     // [A, B, C]
+              pos[1] = pv[0]; // P
+              types[0] = (int) TOUCHFACE;
+              pos[0] = 3;     // [A, B, C]
+              pos[1] = pv[1]; // Q
+            } else {
+              if (s4 == 0) {
+                // Q = l, [P, Q] in [A, l] (-+-0).
+                types[0] = (int) TOUCHFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = pv[0]; // P
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = pu[1]; // [B, C]
+                pos[1] = pv[1]; // Q
+              } else { // s4 < 0
+                // [P, Q] overlaps [A, l] (-+--).
+                types[0] = (int) TOUCHFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = pv[0]; // P
+                types[0] = (int) ACROSSEDGE;
+                pos[0] = pu[1]; // [B, C]
+                pos[1] = pv[0]; // [P, Q]
+              }
+            }
+          } else { // s2 == 0
+            // P = l (#0##).
+            types[0] = (int) TOUCHEDGE;
+            pos[0] = pu[1]; // [B, C]
+            pos[1] = pv[0]; // P
+            types[1] = (int) DISJOINT;
+          }
+        }
+      }
+    } else { // s1 == 0
+      // Q = A (0###).
+      types[0] = (int) SHAREVERT;
+      pos[0] = pu[0]; // A
+      pos[1] = pv[1]; // Q
+      types[1] = (int) DISJOINT;
+    }
+  } else if (z1 == 3) {  // (tritri-33)
+    if (s1 < 0) {
+      if (s3 > 0) {
+        assert(s2 > 0); // SELF_CHECK
+        if (s4 > 0) {
+          // [P, Q] overlaps [A, B] (-+++).
+          types[0] = (int) ACROSSVERT;
+          pos[0] = pu[0]; // A
+          pos[1] = pv[0]; // [P, Q]
+          types[1] = (int) TOUCHEDGE;
+          pos[2] = pu[0]; // [A, B]
+          pos[3] = pv[1]; // Q
+        } else {
+          if (s4 == 0) {
+            // Q = B, [P, Q] contains [A, B] (-++0).
+            types[0] = (int) ACROSSVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = pv[0]; // [P, Q]
+            types[1] = (int) SHAREVERT;
+            pos[2] = pu[1]; // B
+            pos[3] = pv[1]; // Q
+          } else { // s4 < 0
+            // [P, Q] contains [A, B] (-++-).
+            types[0] = (int) ACROSSVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = pv[0]; // [P, Q]
+            types[1] = (int) ACROSSVERT;
+            pos[2] = pu[1]; // B
+            pos[3] = pv[0]; // [P, Q]
+          }
+        }
+      } else {
+        if (s3 == 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // P = A, [P, Q] in [A, B] (-+0+).
+            types[0] = (int) SHAREVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = pv[0]; // P
+            types[1] = (int) TOUCHEDGE;
+            pos[2] = pu[0]; // [A, B]
+            pos[3] = pv[1]; // Q
+          } else {
+            if (s4 == 0) {
+              // [P, Q] = [A, B] (-+00).
+              types[0] = (int) SHAREEDGE;
+              pos[0] = pu[0]; // [A, B]
+              pos[1] = pv[0]; // [P, Q]
+              types[1] = (int) DISJOINT;
+            } else { // s4 < 0
+              // P= A, [P, Q] in [A, B] (-+0-).
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = pv[0]; // P
+              types[1] = (int) ACROSSVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = pv[0]; // [P, Q]
+            }
+          }
+        } else { // s3 < 0
+          if (s2 > 0) {
+            if (s4 > 0) {
+              // [P, Q] in [A, B] (-+-+).
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = pu[0]; // [A, B]
+              pos[1] = pv[0]; // P
+              types[1] = (int) TOUCHEDGE;
+              pos[2] = pu[0]; // [A, B]
+              pos[3] = pv[1]; // Q
+            } else {
+              if (s4 == 0) {
+                // Q = B, [P, Q] in [A, B] (-+-0).
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = pu[0]; // [A, B]
+                pos[1] = pv[0]; // P
+                types[1] = (int) SHAREVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = pv[1]; // Q
+              } else { // s4 < 0
+                // [P, Q] overlaps [A, B] (-+--).
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = pu[0]; // [A, B]
+                pos[1] = pv[0]; // P
+                types[1] = (int) ACROSSVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = pv[0]; // [P, Q]
+              }
+            }
+          } else { // s2 == 0
+            // P = B (#0##).
+            types[0] = (int) SHAREVERT;
+            pos[0] = pu[1]; // B
+            pos[1] = pv[0]; // P
+            types[1] = (int) DISJOINT;
+          }
+        }
+      }
+    } else { // s1 == 0
+      // Q = A (0###).
+      types[0] = (int) SHAREVERT;
+      pos[0] = pu[0]; // A
+      pos[1] = pv[1]; // Q
+      types[1] = (int) DISJOINT;
+    }
+  }
+
+  return 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// tri_edge_test()    Triangle-edge intersection test.                       //
+//                                                                           //
+// This routine takes a triangle T (with vertices A, B, C) and an edge E (P, //
+// Q) in 3D, and tests if they intersect each other.  Return 1 if they are   //
+// intersected, i.e., T \cap E is not empty, otherwise, return 0.            //
+//                                                                           //
+// If the point 'R' is not NULL, it lies strictly above the plane defined by //
+// A, B, C. It is used in test when T and E are coplanar.                    //
+//                                                                           //
+// If T1 and T2 intersect each other (return 1), they may intersect in diff- //
+// erent ways. If 'level' > 0, their intersection type will be reported in   //
+// combinations of 'types' and 'pos'.                                        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+int tetgenmesh::tri_edge_test(point A, point B, point C, point P, point Q, 
+  point R, int level, int *types, int *pos)
+{
+  point U[3], V[3], Ptmp;
+  int pu[3], pv[3], itmp;
+  REAL sP, sQ, s1, s2, s3;
+  int z1;
+
+  // Test the locations of P and Q with respect to ABC.
+  sP = orient3d(A, B, C, P);
+  sQ = orient3d(A, B, C, Q);
+  orient3dcount+=2;
+
+  if (b->epsilon > 0) {
+    if ((sP != 0) && iscoplanar(A, B, C, P, sP)) sP = 0;
+    if ((sQ != 0) && iscoplanar(A, B, C, Q, sQ)) sQ = 0;
+  }
+
+  if (b->verbose > 2) {
+    printf("      Tri-edge (%d %d %d)-(%d %d) (%c%c).\n", pointmark(A),
+      pointmark(B), pointmark(C), pointmark(P), pointmark(Q),
+      sP>0 ? '+' : (sP<0 ? '-' : '0'), sQ>0 ? '+' : (sQ<0 ? '-' : '0'));
+  }
+  triedgcount++;
+
+  if (sP < 0) {
+    if (sQ < 0) { // (--) disjoint
+      return 0;
+    } else {
+      if (sQ > 0) { // (-+)
+        SETVECTOR3(U, A, B, C);
+        SETVECTOR3(V, P, Q, R);
+        SETVECTOR3(pu, 0, 1, 2);
+        SETVECTOR3(pv, 0, 1, 2);
+        z1 = 0;
+      } else { // (-0)
+        SETVECTOR3(U, A, B, C);
+        SETVECTOR3(V, P, Q, R);
+        SETVECTOR3(pu, 0, 1, 2);
+        SETVECTOR3(pv, 0, 1, 2);
+        z1 = 1;
+      }
+    }
+  } else {
+    if (sP > 0) { // (+-)
+      if (sQ < 0) {
+        SETVECTOR3(U, A, B, C);
+        SETVECTOR3(V, Q, P, R);  // P and Q are flipped.
+        SETVECTOR3(pu, 0, 1, 2);
+        SETVECTOR3(pv, 1, 0, 2);
+        z1 = 0;
+      } else {
+        if (sQ > 0) { // (++) disjoint
+          return 0;
+        } else { // (+0)
+          SETVECTOR3(U, B, A, C); // A and B are flipped.
+          SETVECTOR3(V, P, Q, R);
+          SETVECTOR3(pu, 1, 0, 2);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 1;
+        }
+      }
+    } else { // sP == 0
+      if (sQ < 0) { // (0-)
+        SETVECTOR3(U, A, B, C);
+        SETVECTOR3(V, Q, P, R);  // P and Q are flipped.
+        SETVECTOR3(pu, 0, 1, 2);
+        SETVECTOR3(pv, 1, 0, 2);
+        z1 = 1;
+      } else {
+        if (sQ > 0) { // (0+)
+          SETVECTOR3(U, B, A, C);  // A and B are flipped.
+          SETVECTOR3(V, Q, P, R);  // P and Q are flipped.
+          SETVECTOR3(pu, 1, 0, 2);
+          SETVECTOR3(pv, 1, 0, 2);
+          z1 = 1;
+        } else { // (00)
+          // A, B, C, P, and Q are coplanar.
+          z1 = 2;
+        }
+      }
+    }
+  }
+
+  if (z1 == 2) {
+    // The triangle and the edge are coplanar.
+    return tri_edge_2d(A, B, C, P, Q, R, level, types, pos);
+  }
+
+  s1 = orient3d(U[0], U[1], V[0], V[1]); orient3dcount++;
+  if (b->epsilon) {
+    if ((s1 != 0) && iscoplanar(U[0], U[1], V[0], V[1], s1)) s1 = 0;
+  }
+  if (s1 < 0) {
+    return 0;
+  }
+
+  s2 = orient3d(U[1], U[2], V[0], V[1]); orient3dcount++;
+  if (b->epsilon) {
+    if ((s2 != 0) && iscoplanar(U[1], U[2], V[0], V[1], s2)) s2 = 0;
+  }
+  if (s2 < 0) {
+    return 0;
+  }
+
+  s3 = orient3d(U[2], U[0], V[0], V[1]); orient3dcount++;
+  if (b->epsilon) {
+    if ((s3 != 0) && iscoplanar(U[2], U[0], V[0], V[1], s3)) s3 = 0;
+  }
+  if (s3 < 0) {
+    return 0;
+  }
+
+  if (b->verbose > 2) {
+    printf("      Tri-edge (%d %d %d)-(%d %d) (%c%c%c).\n", pointmark(U[0]),
+      pointmark(U[1]), pointmark(U[2]), pointmark(V[0]), pointmark(V[1]),
+      s1>0 ? '+' : (s1<0 ? '-' : '0'), s2>0 ? '+' : (s2<0 ? '-' : '0'),
+      s3>0 ? '+' : (s3<0 ? '-' : '0'));
+  }
+
+  if (level == 0) {
+    return 1;  // The are intersected.
+  }
+
+  types[1] = (int) DISJOINT; // No second intersection point.
+
+  if (z1 == 0) {
+    if (s1 > 0) {
+      if (s2 > 0) {
+        if (s3 > 0) { // (+++)
+          // [P, Q] passes interior of [A, B, C].
+          types[0] = (int) ACROSSFACE;
+          pos[0] = 3;  // interior of [A, B, C]
+          pos[1] = 0;  // [P, Q]
+        } else { // s3 == 0 (++0)
+          // [P, Q] intersects [C, A].
+          types[0] = (int) ACROSSEDGE;
+          pos[0] = pu[2];  // [C, A]
+          pos[1] = 0;  // [P, Q]
+        }
+      } else { // s2 == 0
+        if (s3 > 0) { // (+0+)
+          // [P, Q] intersects [B, C].
+          types[0] = (int) ACROSSEDGE;
+          pos[0] = pu[1];  // [B, C]
+          pos[1] = 0;  // [P, Q]
+        } else { // s3 == 0 (+00)
+          // [P, Q] passes C.
+          types[0] = (int) ACROSSVERT;
+          pos[0] = pu[2];  // C
+          pos[1] = 0;  // [P, Q]
+        }
+      }
+    } else { // s1 == 0
+      if (s2 > 0) {
+        if (s3 > 0) { // (0++)
+          // [P, Q] intersects [A, B].
+          types[0] = (int) ACROSSEDGE;
+          pos[0] = pu[0];  // [A, B]
+          pos[1] = 0;  // [P, Q]
+        } else { // s3 == 0 (0+0)
+          // [P, Q] passes A.
+          types[0] = (int) ACROSSVERT;
+          pos[0] = pu[0];  // A
+          pos[1] = 0;  // [P, Q]
+        }
+      } else { // s2 == 0
+        if (s3 > 0) { // (00+)
+          // [P, Q] passes B.
+          types[0] = (int) ACROSSVERT;
+          pos[0] = pu[1];  // B
+          pos[1] = 0;  // [P, Q]
+        } else { // s3 == 0 (000)
+          // Impossible.
+          assert(0);
+        }
+      }
+    }
+  } else { // z1 == 1
+    if (s1 > 0) {
+      if (s2 > 0) {
+        if (s3 > 0) { // (+++)
+          // Q lies in [A, B, C].
+          types[0] = (int) TOUCHFACE;
+          pos[0] = 0; // [A, B, C]
+          pos[1] = pv[1]; // Q
+        } else { // s3 == 0 (++0)
+          // Q lies on [C, A].
+          types[0] = (int) TOUCHEDGE;
+          pos[0] = pu[2]; // [C, A]
+          pos[1] = pv[1]; // Q
+        }
+      } else { // s2 == 0
+        if (s3 > 0) { // (+0+)
+          // Q lies on [B, C].
+          types[0] = (int) TOUCHEDGE;
+          pos[0] = pu[1]; // [B, C]
+          pos[1] = pv[1]; // Q
+        } else { // s3 == 0 (+00)
+          // Q = C.
+          types[0] = (int) SHAREVERT;
+          pos[0] = pu[2]; // C
+          pos[1] = pv[1]; // Q
+        }
+      }
+    } else { // s1 == 0
+      if (s2 > 0) {
+        if (s3 > 0) { // (0++)
+          // Q lies on [A, B].
+          types[0] = (int) TOUCHEDGE;
+          pos[0] = pu[0]; // [A, B]
+          pos[1] = pv[1]; // Q
+        } else { // s3 == 0 (0+0)
+          // Q = A.
+          types[0] = (int) SHAREVERT;
+          pos[0] = pu[0]; // A
+          pos[1] = pv[1]; // Q
+        }
+      } else { // s2 == 0
+        if (s3 > 0) { // (00+)
+          // Q = B.
+          types[0] = (int) SHAREVERT;
+          pos[0] = pu[1]; // B
+          pos[1] = pv[1]; // Q
+        } else { // s3 == 0 (000)
+          // Impossible.
+          assert(0);
+        }
+      }
+    }
+  }
+
+  return 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// tri_tri_2d()    Triangle-triangle coplanar intersection test.             //
+//                                                                           //
+// This routine takes two triangles T1 (with vertices A, B, C) and T2 (with  //
+// vertices P, Q, R) in 3D, and T1 and T2 are coplanar, and tests if they    //
+// intersect each other.  Return 1 if they intersect, ie., T1 \cap T2 is not //
+// empty, otherwise, return 0.                                               //
+//                                                                           //
+// If 'O' is not NULL, it lies strictly above A, B, C.                       //
+//                                                                           //
+// If T1 and T2 intersect (return 1) and if 'level' > 0,                     //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+int tetgenmesh::tri_tri_2d(point A, point B, point C, point P, point Q, 
+  point R, point O, int level, int *types, int *pos)
+{
+  point U[3], V[3];
+  int pu[3], pv[3], pe[3];
+  REAL s1, s2, s3, s4;
+  REAL s5, s6 ,s7, s8, s9;
+  int z1;
+
+  if (O == NULL) {
+    REAL n[3], len;
+    // Calculate a lift point, saved in dummypoint.
+    facenormal(A, B, C, n, 1);
+    len = sqrt(DOT(n, n));
+    n[0] /= len;
+    n[1] /= len;
+    n[2] /= len;
+    len = DIST(A, B);
+    len += DIST(B, C);
+    len += DIST(C, A);
+    len /= 3.0;
+    O = dummypoint;
+    O[0] = A[0] + len * n[0];
+    O[1] = A[1] + len * n[1];
+    O[2] = A[2] + len * n[2];
+  }
+
+  s1 = orient3d(A, B, O, P);
+  s2 = orient3d(B, C, O, P);
+  s3 = orient3d(C, A, O, P);
+  orient3dcount+=3;
+
+  if (b->epsilon) {
+    if ((s1 != 0) && iscoplanar(A, B, O, P, s1)) s1 = 0;
+    if ((s2 != 0) && iscoplanar(B, C, O, P, s2)) s2 = 0;
+    if ((s3 != 0) && iscoplanar(C, A, O, P, s3)) s3 = 0;
+  }
+
+  if (b->verbose > 2) {
+    printf("      Tri-tri-2d (%d %d %d)-(%d %d %d) (%c%c%c)\n", pointmark(A),
+      pointmark(B), pointmark(C), pointmark(P), pointmark(Q), pointmark(R),
+      s1>0 ? '+' : (s1 < 0 ? '-' : '0'), s2>0 ? '+' : (s2<0 ? '-' : '0'),
+      s3>0 ? '+' : (s3<0 ? '-' : '0'));
+  }
+
+  if (s1 < 0) {
+    if (s2 < 0) {
+      if (s3 < 0) { // (---)
+        assert(0); // Not possible.
+      } else {
+        if (s3 > 0) { // (--+)
+          SETVECTOR3(U, B, C, A);  // PT = ST x ST
+          SETVECTOR3(pu, 1, 2, 0);
+          z1 = 2;
+        } else { // (--0)
+          assert(0); // Not possible.
+        }
+      }
+    } else {
+      if (s2 > 0) {
+        if (s3 < 0) { // (-+-)
+          SETVECTOR3(U, A, B, C);  // I3
+          SETVECTOR3(pu, 0, 1, 2);
+          z1 = 2;
+        } else {
+          if (s3 > 0) { // (-++)
+            SETVECTOR3(U, A, B, C);  // I3
+            SETVECTOR3(pu, 0, 1, 2);
+            z1 = 1;
+          } else { // (-+0)
+            SETVECTOR3(U, A, B, C);  // I3
+            SETVECTOR3(pu, 0, 1, 2);
+            z1 = 4;
+          }
+        }
+      } else { // s2 == 0
+        if (s3 < 0) { //(-0-)
+          assert(0); // Not possible
+        } else {
+          if (s3 > 0) { // (-0+)
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(pu, 1, 2, 0);
+            z1 = 3;
+          } else { // (-00)
+            assert(0); // Not possible
+          }
+        }
+      }
+    }
+  } else {
+    if (s1 > 0) {
+      if (s2 < 0) {
+        if (s3 < 0) { // (+--)
+          SETVECTOR3(U, C, A, B);  // PT = ST
+          SETVECTOR3(pu, 2, 0, 1);
+          z1 = 2;
+        } else {
+          if (s3 > 0) { // (+-+)
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(pu, 1, 2, 0);
+            z1 = 1;
+          } else { // (+-0)
+            SETVECTOR3(U, C, A, B);  // PT = ST
+            SETVECTOR3(pu, 2, 0, 1);
+            z1 = 3;
+          }
+        }
+      } else { 
+        if (s2 > 0) {
+          if (s3 < 0) { // (++-)
+            SETVECTOR3(U, C, A, B);  // PT = ST
+            SETVECTOR3(pu, 2, 0, 1);
+            z1 = 1;
+          } else {
+            if (s3 > 0) { // (+++)
+              SETVECTOR3(U, A, B, C);  // I3
+              SETVECTOR3(pu, 0, 1, 2);
+              z1 = 7;
+            } else { // (++0)
+              SETVECTOR3(U, C, A, B);  // PT = ST
+              SETVECTOR3(pu, 2, 0, 1);
+              z1 = 5;
+            }
+          }
+        } else { // s2 == 0
+          if (s3 < 0) { // (+0-)
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(pu, 1, 2, 0);
+            z1 = 4;
+          } else {
+            if (s3 > 0) { // (+0+)
+              SETVECTOR3(U, B, C, A);  // PT = ST x ST
+              SETVECTOR3(pu, 1, 2, 0);
+              z1 = 5;
+            } else { // (+00)
+              SETVECTOR3(U, C, A, B);  // PT = ST
+              SETVECTOR3(pu, 2, 0, 1);
+              z1 = 6;
+            }
+          }
+        }
+      }
+    } else { // s1 == 0
+      if (s2 < 0) {
+        if (s3 < 0) { // (0--)
+          assert(0); // Not possible
+        } else {
+          if (s3 > 0) { // (0-+)
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(pu, 1, 2, 0);
+            z1 = 4;
+          } else { // (0-0)
+            assert(0); // Not possible
+          }
+        }
+      } else {
+        if (s2 > 0) {
+          if (s3 < 0) { // (0+-)
+            SETVECTOR3(U, A, B, C);  // I3
+            SETVECTOR3(pu, 0, 1, 2);
+            z1 = 3;
+          } else {
+            if (s3 > 0) { // (0++)
+              SETVECTOR3(U, A, B, C);  // I3
+              SETVECTOR3(pu, 0, 1, 2);
+              z1 = 5;
+            } else { // (0+0)
+              SETVECTOR3(U, A, B, C);  // I3
+              SETVECTOR3(pu, 0, 1, 2);
+              z1 = 6;
+            }
+          }
+        } else { // s2 == 0
+          if (s3 < 0) { // (00-)
+            assert(0); // Not possible
+          } else {
+            if (s3 > 0) { // (00+)
+              SETVECTOR3(U, B, C, A);  // PT = ST x ST
+              SETVECTOR3(pu, 1, 2, 0);
+              z1 = 6;
+            } else { // (000)
+              assert(0); // Not possible
+            }
+          }
+        }
+      }
+    }
+  }
+
+  if (b->verbose > 2) {
+    printf("      Tri-tri-2d (%d %d %d)-(%d) z1(%d)\n", pointmark(U[0]), 
+      pointmark(U[1]), pointmark(U[2]), pointmark(P), z1);
+  }
+
+  if (z1 == 5) { // P in [A, B]
+    if (level > 0) {
+      s4 = orient3d(U[0], U[1], O, V[1]); // A, B, Q
+      if (s4 < 0) {
+        s5 = orient3d(U[0], U[1], O, V[2]); // A, B, R
+        if (s5 < 0) {
+          // P touches [A, B]
+          types[0] = (int) TOUCHEDGE;
+          pos[0] = pu[0]; // [A, B]
+          pos[1] = 0; // P
+          types[1] = (int) DISJOINT;
+        } else { // s5 >= 0
+          // [R, P] intersects [A, B, C]
+          types[0] = (int) EDGETRIINT;
+          pos[0] = 3; // [A, B, C]
+          pos[1] = 2; // [R, P]
+          types[1] = (int) DISJOINT;
+        }
+      } else { // s4 >= 0
+        // [P, Q] intersects [A, B, C]
+        types[0] = (int) EDGETRIINT;
+        pos[0] = 3; // [A, B, C]
+        pos[1] = 0; // [P, Q]
+        types[1] = (int) DISJOINT;
+      }
+    }
+    return 1;
+  }
+
+  if (z1 == 7) { // P in [A, B, C]
+    if (level > 0) {
+      // [P, Q] intersects [A, B, C]
+      types[0] = (int) EDGETRIINT;
+      pos[0] = 3; // [A, B, C]
+      pos[1] = 0; // [P, Q]
+      types[1] = (int) DISJOINT;
+    }
+    return 1;
+  }
+
+  // Orient P, Q, R to be CCW wrt O, keep P as origin
+  s4 = orient3d(P, Q, R, O);
+  orient3dcount++;
+  if (b->epsilon) {
+    if ((s4 != 0) && iscoplanar(P, Q, R, O, s4)) s4 = 0;
+  }
+
+  assert(s4 != 0);
+  if (s4 < 0) {
+    SETVECTOR3(V, P, Q, R);
+    SETVECTOR3(pv, 0, 1, 2);
+    SETVECTOR3(pe, 0, 1, 2);
+  } else {
+    SETVECTOR3(V, P, R, Q);
+    SETVECTOR3(pv, 0, 2, 1);
+    SETVECTOR3(pe, 2, 1, 0);
+  }
+
+  //////////////////////////// z1 == 1 ///////////////////////////////////////
+
+  if (z1 == 1) {
+
+    s5 = orient3d(U[0], U[1], O, V[1]); // A, B, Q
+    if (s5 < 0) {
+      s6 = orient3d(U[0], U[1], O, V[2]); // A, B, R
+      if (s6 < 0) {
+        return 0;
+      } else { // s6 >= 0
+        s7 = orient3d(V[1], V[2], O, U[0]); // Q, R, A
+        if (s7 < 0) {
+          return 0;
+        } else { // s7 >= 0
+          s8 = orient3d(V[0], U[1], O, V[2]); // P, B, R
+          if (s8 >= 0) { 
+            // z2 = 1;
+          } else {
+            return 0;
+          }
+          // NOTE: in the reference, the above two cases are reversed.
+          // It should be an error by the authors.
+        }
+      }
+    } else { // s5 >= 0
+      s6 = orient3d(U[0], V[0], O, V[1]); // A, P, Q
+      if (s6 < 0) {
+        return 0;
+      } else { // s6 >= 0
+        s7 = orient3d(V[0], U[1], O, V[1]); // P, B, Q
+        if (s7 < 0) {
+          s8 = orient3d(V[0], U[1], O, V[2]); // P, B, R
+          if (s8 < 0) {
+            return 0;
+          } else { // s8 >= 0
+            s9 = orient3d(V[1], V[2], O, U[1]); // Q, R, B
+            if (s9 < 0) {
+              return 0;
+            } else { // s9 >= 0
+              // z2 = 2;
+            }
+          }
+        } else { // s7 >= 0
+          // z2 = 3;
+        }
+      }
+    }
+
+    if (level == 0) {
+      return 1;
+    }
+
+    if (s5 < 0) {
+      if (s6 > 0) { // (tritri2d-R1-1)
+        if (s7 > 0) {
+          if (s8 > 0) {
+            // [A, B] intersects [P, Q, R]
+            types[0] = (int) EDGETRIINT;
+            pos[0] = pu[0]; // [A, B]
+            pos[1] = 3; // [P, Q, R]
+            types[1] = (int) DISJOINT;
+          } else { // s8 == 0
+            // [R, P] passes B
+            types[0] = (int) ACROSSVERT;
+            pos[0] = pu[1]; // B
+            pos[1] = pe[2]; // [R, P]
+            types[1] = (int) DISJOINT;
+          }
+        } else { // s7 == 0
+          assert(s8 > 0);
+          // [Q, R] passes A.
+          types[0] = (int) ACROSSVERT;
+          pos[0] = pu[0]; // A
+          pos[1] = pe[1]; // [Q, R]
+          types[1] = (int) DISJOINT;
+        }
+      } else { // s6 == 0 // (tritri2d-R1-1a)
+        if (s7 > 0) {
+          if (s8 > 0) {
+            // R touches [A, B]
+            types[0] = (int) TOUCHEDGE;
+            pos[0] = pu[0]; // [A, B]
+            pos[1] = pv[2]; // R
+            types[1] = (int) DISJOINT;
+          } else { // s8 == 0
+            // R = B
+            types[0] = (int) SHAREVERT;
+            pos[0] = pu[1]; // B
+            pos[1] = pv[2]; // R
+            types[1] = (int) DISJOINT;
+          }
+        } else { // s7 == 0
+          assert(s8 > 0);
+          // R = A
+          types[0] = (int) SHAREVERT;
+          pos[0] = pu[0]; // A
+          pos[1] = pv[2]; // R
+          types[1] = (int) DISJOINT;
+        }
+      }
+    } else { // s5 >= 0
+      if (s5 > 0) {
+        if (s6 > 0) {
+          if (s7 < 0) { // (tritri2d-R1-2)
+            if (s8 > 0) {
+              if (s9 > 0) {
+                // [A, B] intersects [P, Q, R]
+                types[0] = (int) EDGETRIINT;
+                pos[0] = pu[0]; // [A, B]
+                pos[1] = 3; // [P, Q, R]
+                types[1] = (int) DISJOINT;
+              } else { // s9 == 0
+                // [Q, R] passes B
+                types[0] = (int) ACROSSVERT;
+                pos[0] = pu[1]; // B
+                pos[1] = pe[1]; // [Q, R]
+                types[1] = (int) DISJOINT;
+              }
+            } else { // s8 == 0
+              if (s9 > 0) {
+                // [R, P] passes B
+                types[0] = (int) ACROSSVERT;
+                pos[0] = pu[1]; // B
+                pos[1] = pe[2]; // [R, P]
+                types[1] = (int) DISJOINT;
+              } else { // s9 == 0
+                // R = B
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[1]; // B
+                pos[1] = pv[2]; // R
+                types[1] = (int) DISJOINT;
+              }
+            }
+          } else { // s7 >= 0 (tritri2d-R1-3)
+            if (s7 > 0) {
+              // [P, Q] intersects [A, B, C]
+              // [A, B] intersects [P, Q, R]
+              types[0] = (int) EDGETRIINT;
+              pos[0] = pu[0]; // [A, B]
+              pos[1] = 3; // [P, Q, R]
+              types[1] = (int) DISJOINT;
+            } else { // s7 == 0
+              // [P, Q] passes B
+              // [A, B] intersects [P, Q, R]
+              types[0] = (int) EDGETRIINT;
+              pos[0] = pu[0]; // [A, B]
+              pos[1] = 3; // [P, Q, R]
+              types[1] = (int) DISJOINT;
+            }
+          }
+        } else { // s6 == 0 (tritri2d-R1-3 bottom)
+          // [P, Q] passes A
+          types[0] = (int) ACROSSVERT;
+          pos[0] = pu[0]; // A
+          pos[1] = pe[0]; // [P, Q]
+          types[1] = (int) DISJOINT;
+        }
+      } else { // s5 == 0
+        if (s6 > 0) {
+          if (s7 < 0) { // (tritri2d-R1-2a)
+            if (s8 > 0) {
+              assert(s9 > 0);
+              // [A, B] intersects [P, Q, R]
+              types[0] = (int) EDGETRIINT;
+              pos[0] = pu[0]; // [A, B]
+              pos[1] = 3; // [P, Q, R]
+              types[1] = (int) DISJOINT;
+            } else { // s8 == 0
+              assert(s9 > 0);
+              // [R, P] passes B
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[1]; // B
+              pos[1] = pe[2]; // [R, P]
+              types[1] = (int) DISJOINT;
+            }
+          } else { // s7 >= 0 (tritri2d-R1-3a)
+            if (s7 > 0) {
+              // [A, B] intersects [P, Q, R]
+              types[0] = (int) EDGETRIINT;
+              pos[0] = pu[0]; // [A, B]
+              pos[1] = 3; // [P, Q, R]
+              types[1] = (int) DISJOINT;
+            } else { // s7 == 0
+              s8 = orient3d(U[0], U[1], O, V[2]); // A, B, R
+              if (s8 < 0) {
+                // Q = B
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[1]; // B
+                pos[1] = pv[1]; // Q
+                types[1] = (int) DISJOINT;
+              } else {
+                if (s8 > 0) {
+                  // [A, B] intersects [P, Q, R]
+                  types[0] = (int) EDGETRIINT;
+                  pos[0] = pu[0]; // [A, B]
+                  pos[1] = 3; // [P, Q, R]
+                  types[1] = (int) DISJOINT;
+                } else { // s8 == 0
+                  s9 = orient3d(U[0], V[0], O, V[2]); // A, P, R
+                  if (s9 != 0) {
+                    // [Q, R] intersects [A, B, C]
+                    // [A, B] intersects [P, Q, R]
+                    types[0] = (int) EDGETRIINT;
+                    pos[0] = pu[0]; // [A, B]
+                    pos[1] = 3; // [P, Q, R]
+                    types[1] = (int) DISJOINT;
+                  } else { // s9 == 0
+                    // [Q, R] = [A, B]
+                    types[0] = (int) SHAREEDGE;
+                    pos[0] = pu[0]; // [A, B]
+                    pos[1] = pe[1]; // [Q, R]
+                    types[1] = (int) DISJOINT;
+                  }
+                }
+              }
+            }
+          }
+        } else { // s6 == 0 (tritri2d-R1-3b)
+          // Q = A
+          types[0] = (int) SHAREVERT;
+          pos[0] = pu[0]; // A
+          pos[1] = pv[1]; // Q
+          types[1] = (int) DISJOINT;
+        }
+      }
+    }
+
+    return 1;
+  } // z1 == 1
+
+  //////////////////////////// z1 == 2, 3, 4 /////////////////////////////////
+
+  if ((z1 == 2) || (z1 == 3) || (z1 == 4)) {
+
+    s5 = orient3d(U[0], U[1], O, V[1]); // A, B, Q
+    if (s5 < 0) {
+      s6 = orient3d(U[0], U[1], O, V[2]); // A, B, R
+      if (s6 < 0) {
+        return 0;
+      } else { // s6 >= 0
+        s7 = orient3d(V[1], V[2], O, U[0]); // Q, R, A
+        if (s7 < 0) {
+          s8 = orient3d(V[1], V[2], O, U[2]); // Q, R, C
+          if (s8 < 0) {
+            return 0;
+          } else {
+            s9 = orient3d(U[2], U[0], O, V[2]); // C, A, R
+            if (s9 < 0) {
+              return 0;
+            } else {
+              // z2 = 1;
+            }
+          }
+        } else { // s7 >= 0
+          s8 = orient3d(V[2], V[0], O, U[1]); // R, P, B
+          if (s8 < 0) {
+            return 0;
+          } else {
+            // z2 = 2;
+          }
+        }
+      }
+    } else { // s5 >= 0
+      s6 = orient3d(U[2], U[0], O, V[1]); // C, A, Q
+      if (s6 < 0) {
+        s7 = orient3d(V[0], U[2], O, V[1]); // P, C, Q
+        if (s7 > 0) { 
+          // Comments! To my analysis, it should be s7 >= 0.
+          // See fig. tritri2d-R2-3a
+          return 0;
+        } else { // s7 <= 0
+          s8 = orient3d(U[2], U[0], O, V[2]); // C, A, R
+          if (s8 < 0) {
+            return 0;
+          } else { // s8 >= 0
+            s9 = orient3d(V[1], V[2], O, U[2]); // Q, R, C
+            if (s9 < 0) {
+              return 0;
+            } else {
+              // z2 = 3;
+            }
+          }
+        }
+      } else { // s6 >= 0
+        s7 = orient3d(V[0], U[1], O, V[1]); // P, B, Q
+        if (s7 < 0) {
+          s8 = orient3d(V[0], U[1], O, V[2]); // P, B, R
+          if (s8 < 0) {
+            return 0;
+          } else { // s8 >= 0
+            s9 = orient3d(U[0], U[1], O, V[2]); // A, B, R
+            if (s9 < 0) {
+              return 0;
+            } else {
+              // z2 = 4;
+            }
+          }
+        } else { // s7 >= 0
+          s8 = orient3d(V[0], U[2], O, V[1]); // P, C, Q
+          if (s8 > 0) {
+            return 0;
+          } else { // s8 <= 0
+            // z2 = 5;
+          }
+        }
+      }
+    }
+
+    if (level == 0) {
+      return 1;
+    }
+
+    if (s5 < 0) { 
+      if (s6 > 0) {
+        if (s7 < 0) { // (tritri2d-R2-1)
+          if (s8 > 0) {
+            if (s9 > 0) { // top-left
+              // [Q, R] intersects [A, B, C]
+              types[0] = (int) TRIEDGEINT;
+              pos[0] = 3; // [A, B, C]
+              pos[1] = pe[1]; // [Q, R]
+              types[1] = (int) DISJOINT;
+            } else { // s9 == 0 top-right
+              // R touches [C, A]
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = pu[2]; // [C, A]
+              pos[1] = pv[2]; // R
+              types[1] = (int) DISJOINT;
+            }
+          } else { // s8 == 0 
+            if (s9 > 0) { // bot-left
+              // [Q, R] passes C.
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[2]; // C
+              pos[1] = pe[1]; // [Q, R]
+              types[1] = (int) DISJOINT;
+            } else { // s9 == 0 bot-right
+              // R = C
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[2]; // C
+              pos[1] = pv[2]; // R
+              types[1] = (int) DISJOINT;
+            }
+          }
+        } else { // s7 >= 0 (tritri2d-R2-2)
+          if (s7 > 0) {
+            if (s8 > 0) { 
+              // [A, B] intersects [P, Q, R]
+              types[0] = (int) EDGETRIINT;
+              pos[0] = pu[0]; // [A, B]
+              pos[1] = 3; // [P, Q, R]
+              types[1] = (int) DISJOINT;
+            } else { // s8 == 0 (s6 > 0) R != B (top-right)
+              if ((z1 == 2) || (z1 == 4)) {
+                // [R, P] passes B
+                types[0] = (int) ACROSSVERT;
+                pos[0] = pu[1]; // B
+                pos[1] = pe[2]; // [R, P]
+                types[1] = (int) DISJOINT;
+              } else { // z1 == 3 (tritri2d-R3-2)
+                // [R, P] intersects [A, B, C]
+                // [A, B] intersects [P, Q, R]
+                types[0] = (int) EDGETRIINT;
+                pos[0] = pu[0]; // [A, B]
+                pos[1] = 3; // [P, Q, R]
+                types[1] = (int) DISJOINT;
+              }
+            }
+          } else { // s7 == 0 (s6 > 0) R != A (bottom)
+            assert(s8 > 0); 
+            s9 = orient3d(V[1], V[2], O, U[2]); // Q, R, C
+            // Note: if z1 == 4, it must be s9 < 0.
+            if (s9 < 0) {
+              // [Q, R] passes A
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = pe[1]; // [Q, R]
+              types[1] = (int) DISJOINT;
+            } else { // s9 >= 0
+              // [A, C] intersects [P, Q, R]
+              types[0] = (int) EDGETRIINT;
+              pos[0] = pu[2]; // [C, A]
+              pos[1] = 3; // [P, Q, R]
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else { // s6 == 0 (tritri2d-R2-2a)
+        assert(s7 >= 0); // s7 < 0 is not possible
+        if (s7 > 0) {
+          if ((z1 == 2) || (z1 == 4)) {
+            if (s8 > 0) {
+              // R touches [A, B]
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = pu[0]; // [A, B]
+              pos[1] = pv[2]; // R
+              types[1] = (int) DISJOINT;
+            } else { // s8 == 0
+              // R = B
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[1]; // B
+              pos[1] = pv[2]; // R
+              types[1] = (int) DISJOINT;
+            }
+          } else { // z1 == 3 (tritri2d-R3-2a)
+            // [R, P] intersects [A, B, C]
+            // [A, B] intersects [P, Q, R]
+            types[0] = (int) EDGETRIINT;
+            pos[0] = pu[0]; // [A, B]
+            pos[1] = 3; // [P, Q, R]
+            types[1] = (int) DISJOINT;
+          }
+        } else { // s7 == 0
+          // R = A
+          types[0] = (int) SHAREVERT;
+          pos[0] = pu[0]; // A
+          pos[1] = pv[2]; // R
+          types[1] = (int) DISJOINT;
+        }
+      }
+    } else { // s5 >= 0
+      if (s5 > 0) {
+        if (s6 < 0) {
+          if (s7 < 0) { // (tritri2d-R2-3)
+            if (s8 > 0) {
+              if (s9 > 0) { 
+                // [C, A] intersects [P, Q, R]
+                types[0] = (int) EDGETRIINT;
+                pos[0] = pu[2]; // [C, A]
+                pos[1] = 3; // [P, Q, R]
+                types[1] = (int) DISJOINT;
+              } else { // s9 == 0
+                // [Q, R] passes C
+                types[0] = (int) ACROSSVERT;
+                pos[0] = pu[2]; // C
+                pos[1] = pe[1]; // [Q, R]
+                types[1] = (int) DISJOINT;
+              }
+            } else { // s8 == 0
+              if (s9 > 0) {
+                // R touches [C, A]
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = pu[2]; // [C, A]
+                pos[1] = pv[2]; // R
+                types[1] = (int) DISJOINT;
+              } else { // s9 == 0
+                // R = C
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[2]; // C
+                pos[1] = pv[2]; // R
+                types[1] = (int) DISJOINT;
+              }
+            }
+          } else { // s7 == 0 (see tritri2d-R2-3a)
+            // Not possible be intersecting!
+            assert(0);
+          }
+        } else { // s6 >= 0
+          if (s6 > 0) {
+            if (s7 < 0) { // (tritri2d-R2-4)
+              if (s8 > 0) { // (top-left)
+                // [A, B] intersects [P, Q, R]
+                types[0] = (int) EDGETRIINT;
+                pos[0] = pu[0]; // [A, B]
+                pos[1] = 3; // [P, Q, R]
+                types[1] = (int) DISJOINT;
+              } else { // s8 == 0
+                if (s9 > 0) { // (top-right)
+                  // [R, P] passes B
+                  types[0] = (int) ACROSSVERT;
+                  pos[0] = pu[1]; // B
+                  pos[1] = pe[2]; // [R, P]
+                  types[1] = (int) DISJOINT;
+                } else { // s9 == 0 (bot-left)
+                  // R = B
+                  types[0] = (int) SHAREVERT;
+                  pos[0] = pu[1]; // B
+                  pos[1] = pv[2]; // R
+                  types[1] = (int) DISJOINT;
+                }
+              }
+            } else { // s7 >= 0
+              if (s7 > 0) { // (tritri2d-R2-5)
+                if (s8 < 0) { // (top-left)
+                  // [P, Q] intersects [A, B, C]
+                  types[0] = (int) TRIEDGEINT;
+                  pos[0] = 3; // [A, B, C]
+                  pos[1] = pe[0]; // [P, Q]
+                  types[1] = (int) DISJOINT;
+                } else { // s8 == 0 (top-right)
+                  if ((z1 == 2) || (z1 == 3)) {
+                    // [P, Q] passes C
+                    types[0] = (int) ACROSSVERT;
+                    pos[0] = pu[2]; // C
+                    pos[1] = pe[0]; // [P, Q]
+                    types[1] = (int) DISJOINT;
+                  } else { // z1 == 4 (tritri2d-R4-5)
+                    // [P, Q] intersects [A, B, C]
+                    // [C, A] intersects [P, Q, R]
+                    types[0] = (int) EDGETRIINT;
+                    pos[0] = pu[2]; // [C, A]
+                    pos[1] = 3; // [P, Q, R]
+                    types[1] = (int) DISJOINT;
+                  }
+                }
+              } else { // s7 == 0 (bot-left)
+                // [A, B] intersects [P, Q, R]
+                types[0] = (int) EDGETRIINT;
+                pos[0] = pu[0]; // [A, B]
+                pos[1] = 3; // [P, Q, R]
+                types[1] = (int) DISJOINT;
+              }
+            }
+          } else { // s6 == 0 (tritri2d-R2-5a)
+            if ((z1 == 2) || (z1 == 3)) {
+              if (s7 > 0) {
+                if (s8 < 0) {
+                  // Q touches [C, A]
+                  types[0] = (int) TOUCHEDGE;
+                  pos[0] = pu[2]; // [C, A]
+                  pos[1] = pv[1]; // Q
+                  types[1] = (int) DISJOINT;
+                } else { // s8 == 0
+                  // Q = C
+                  types[0] = (int) SHAREVERT;
+                  pos[0] = pu[2]; // C
+                  pos[1] = pv[1]; // Q
+                  types[1] = (int) DISJOINT;
+                }
+              } else { // s7 == 0
+                assert(0); // Not possible
+              }
+            } else { // z1 == 4 (tritri2d-R4-5a)
+              // [P, Q] intersects [A, B, C]
+              // [C, A] intersects [P, Q, R]
+              types[0] = (int) EDGETRIINT;
+              pos[0] = pu[2]; // [C, A]
+              pos[1] = 3; // [P, Q, R]
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else { // s5 == 0
+        if (s6 < 0) { // (tritri2d-R2-3b)
+          if (s7 < 0) {
+            if (s8 > 0) {
+              if (s9 > 0) {
+                // [C, A] intersects [P, Q, R]
+                types[0] = (int) EDGETRIINT;
+                pos[0] = pu[2]; // [C, A]
+                pos[1] = 3; // [P, Q, R]
+                types[1] = (int) DISJOINT;
+              } else { // s9 == 0
+                // [Q, R] passes C
+                types[0] = (int) ACROSSVERT;
+                pos[0] = pu[2]; // C
+                pos[1] = pe[1]; // [Q, R]
+                types[1] = (int) DISJOINT;
+              }
+            } else { // s8 == 0
+              if (s9 > 0) {
+                // R touches [C, A]
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = pu[2]; // [C, A]
+                pos[1] = pv[2]; // R
+                types[1] = (int) DISJOINT;
+              } else { // s9 == 0
+                // R = C
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[2]; // C
+                pos[1] = pv[2]; // R
+                types[1] = (int) DISJOINT;
+              }
+            }
+          } else { // s7 == 0 (see tritri2d-R2-3c)
+            assert(0); // To my analysis should be disjoint. 
+          }
+        } else {
+          if (s6 > 0) {
+            if (s7 < 0) { // (tritri2d-R2-4a)
+              if (s8 > 0) {
+                if (s9 > 0) {
+                  // [A, B] intersects [P, Q, R]
+                  types[0] = (int) EDGETRIINT;
+                  pos[0] = pu[0]; // [A, B]
+                  pos[1] = 3; // [P, Q, R]
+                  types[1] = (int) DISJOINT;
+                } else { // s9 == 0
+                  // [A, B] intersects [P, Q, R]
+                  types[0] = (int) EDGETRIINT;
+                  pos[0] = pu[0]; // [A, B]
+                  pos[1] = 3; // [P, Q, R]
+                  types[1] = (int) DISJOINT;
+                }
+              } else { // s8 == 0
+                if (s9 > 0) {
+                  // [R, P] passes B
+                  types[0] = (int) ACROSSVERT;
+                  pos[0] = pu[1]; // B
+                  pos[1] = pe[2]; // [R, P]
+                  types[1] = (int) DISJOINT;
+                } else { // s9 == 0
+                  // R = B
+                  types[0] = (int) SHAREVERT;
+                  pos[0] = pu[1]; // B
+                  pos[1] = pv[2]; // R
+                  types[1] = (int) DISJOINT;
+                }
+              }
+            } else { // s7 >= 0
+              if (s7 > 0) {
+                assert(0); // Not possible (see tritri2d-R2-5b)
+              } else { // s7 == 0
+                if (z1 == 3) {// (tritri2d-R3-5b)
+                  // [P, Q] intersects [A, B, C]
+                  // [A, B] intersects [P, Q, R]
+                  types[0] = (int) EDGETRIINT;
+                  pos[0] = pu[0]; // [A, B]
+                  pos[1] = 3; // [P, Q, R]
+                  types[1] = (int) DISJOINT;
+                } else { // (tritri2d-R2-5b)
+                  s8 = orient3d(U[0], U[1], O, V[2]); // A, B, R
+                  if (s8 < 0) {
+                    // Q = B 
+                    types[0] = (int) SHAREVERT;
+                    pos[0] = pu[1]; // B
+                    pos[1] = pv[1]; // Q
+                    types[1] = (int) DISJOINT;
+                  } else {
+                    if (s8 > 0) {
+                      // [A, B] intersect [P, Q, R]
+                      types[0] = (int) EDGETRIINT;
+                      pos[0] = pu[0]; // [A, B]
+                      pos[1] = 3; // [P, Q, R]
+                      types[1] = (int) DISJOINT;
+                    } else { // s8 == 0
+                      s9 = orient3d(U[0], U[2], O, V[2]); // A, C, R
+                      if (s9 == 0) {
+                        // [A, B] = [Q, R]
+                        types[0] = (int) SHAREEDGE;
+                        pos[0] = pu[0]; // [A, B]
+                        pos[1] = pe[2]; // [R, P]
+                        types[1] = (int) DISJOINT;
+                      } else {
+                        // [P, Q] intersects [A, B, C]
+                        // [A, B] intersect [P, Q, R]
+                        types[0] = (int) EDGETRIINT;
+                        pos[0] = pu[0]; // [A, B]
+                        pos[1] = 3; // [P, Q, R]
+                        types[1] = (int) DISJOINT;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          } else { // s6 == 0 (tritri2d-R2-6)
+            // Q = A. Note that R must above P, Q.
+            s7 = orient3d(V[1], V[2], O, U[2]); // Q, R, C
+            // Note: if z1 == 4, it must be s7 > 0
+            if (s7 < 0) {
+              // [Q, R] intersects [A, B, C]
+              types[0] = (int) EDGETRIINT;
+              pos[0] = 3; // [A, B, C]
+              pos[1] = pe[1]; // [Q, R]
+              types[1] = (int) DISJOINT;
+            } else {
+              if (s7 > 0) {
+                // Q = A
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = pv[1]; // Q
+                types[1] = (int) DISJOINT;
+              } else { // s7 == 0
+                s8 = orient3d(V[0], V[2], O, U[2]); // P, R, C
+                if (s8 == 0) {
+                  // [Q, R] = [A, C]
+                  types[0] = (int) SHAREEDGE;
+                  pos[0] = pu[2]; // [C, A]
+                  pos[1] = pe[1]; // [Q, R]
+                  types[1] = (int) DISJOINT;
+                } else { // s8 > 0 || s8 < 0
+                  // [A, C] intersects [P, Q, R]
+                  types[0] = (int) EDGETRIINT;
+                  pos[0] = pu[2]; // [C, A]
+                  pos[1] = 3; // [P, Q, R]
+                  types[1] = (int) DISJOINT;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return 1;
+  } // z1 == 2 || z1 == 3 || z1 == 4
+
+  if (z1 == 6) { // P = A
+
+    if (level > 0) {
+      s5 = orient3d(U[0], U[1], O, V[1]); // A, B, Q
+      if (s5 < 0) {
+        s6 = orient3d(U[0], U[1], O, V[2]); // A, B, R
+        if (s6 < 0) { // (tritri2d-R6--)
+          // P = A
+          types[0] = (int) SHAREVERT;
+          pos[0] = pu[0]; // A
+          pos[1] = pv[0]; // P
+          types[1] = (int) DISJOINT;
+        } else {
+          if (s6 > 0) { // (tritri2d-R6-+)
+            // Note: it must be orient3d(Q, R, A) > 0.
+            // [P, Q] intersects [A, B, C]
+            types[0] = (int) TRIEDGEINT;
+            pos[0] = 3; // [A, B, C]
+            pos[1] = pe[0]; // [P, Q]
+            types[1] = (int) DISJOINT;
+          } else { // s6 == 0 (tritri2d-R6-0)
+            // Note: it must be orient3d(Q, R, A) > 0.
+            s7 = orient3d(V[1], V[2], O, U[1]); // Q, R, B
+            if (s7 == 0) {
+              // [R, P] = [A, B]
+              types[0] = (int) SHAREEDGE;
+              pos[0] = pu[0]; // [A, B]
+              pos[1] = pe[2]; // [R, P]
+              types[1] = (int) DISJOINT;
+            } else {
+              // [R, P] intersects [A, B, C]
+              // [A, B] intersects [P, Q, R]
+              types[0] = (int) EDGETRIINT;
+              pos[0] = pu[0]; // [A, B]
+              pos[1] = 3; // [P, Q, R]
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else { // s5 >= 0
+        if (s5 > 0) {
+          s6 = orient3d(U[0], U[2], O, V[1]); // A, C, Q
+          if (s6 < 0) { // (tritri2d-R6+-)
+            // [P, Q] intersects [A, B, C]
+            types[0] = (int) TRIEDGEINT;
+            pos[0] = 3; // [A, B, C]
+            pos[1] = pe[0]; // [P, Q]
+            types[1] = (int) DISJOINT;
+          } else { // s6 >= 0
+            if (s6 > 0) { // (tritri2d-R6++) (not draw)
+              // P = A
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = pv[0]; // P
+              types[1] = (int) DISJOINT;  
+            } else { // s6 == 0 // (tritri2d-R6+0)
+              s7 = orient3d(V[1], V[2], O, U[2]); // Q, R, O, C
+              if (s7 == 0) {
+                // [P, Q] = [C, A]
+                types[0] = (int) SHAREEDGE;
+                pos[0] = pu[2]; // [C, A]
+                pos[1] = pe[0]; // [P, Q]
+                types[1] = (int) DISJOINT;
+              } else {
+                // [P, Q] intersects [A, B, C]
+                // [A, C] intersects [P, Q, R]
+                types[0] = (int) TRIEDGEINT;
+                pos[0] = 3; // [A, B, C]
+                pos[1] = pe[0]; // [P, Q]
+                types[1] = (int) DISJOINT;
+              }
+            }
+          }
+        } else { // s5 == 0
+          s6 = orient3d(V[1], V[2], O, U[1]); // Q, R, B
+          if (s6 == 0) {
+            // [P, Q] = [A, B]
+            types[0] = (int) SHAREEDGE;
+            pos[0] = pu[0]; // [A, B]
+            pos[1] = pe[0]; // [P, Q]
+            types[1] = (int) DISJOINT;
+          } else {
+            // [P, Q] intersects [A, B, C]
+            // [A, B] intersects [P, Q, R]
+            types[0] = (int) TRIEDGEINT;
+            pos[0] = 3; // [A, B, C]
+            pos[1] = pe[0]; // [P, Q]
+            types[1] = (int) DISJOINT;
+          }
+        }
+      }
+    } // if (level > 0)
+
+    return 1;
+  } // z1 == 6
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// tri_tri_test()    Triangle-triangle intersection test.                    //
+//                                                                           //
+// This routine takes two triangles T1 (with vertices A, B, C) and T2 (P, Q  //
+// R) in 3D, and tests if they intersect each other.  Return 1 if they are   //
+// intersected, i.e., T1 \cap T2 is not empty, otherwise, return 0.          //
+//                                                                           //
+// If the point 'O' is not NULL, it lies strictly above the plane defined by //
+// A, B, C. It is used in test when T1 and T2 are coplanar.                  //
+//                                                                           //
+// If T1 and T2 intersect each other (return 1), they may intersect in diff- //
+// erent ways. If 'level' > 0, their intersection type will be reported in   //
+// combinations of 'types' and 'pos'.                                        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+int tetgenmesh::tri_tri_test(point A, point B, point C, point P, point Q, 
+  point R, point O, int level, int *types, int *pos)
+{
+  point U[3], V[3], W[3], Ptmp;  // The permuted vectors of points.
+  int pu[3], pv[3], pw[3], iu, iv, itmp; 
+  REAL sA, sB, sC, sP, sQ, sR;
+  REAL s1, s2, s3, s4;
+  int z1, z2;
+
+  // Test A's, B's, and C's orientations wrt plane PQR. 
+  sA = orient3d(P, Q, R, A);
+  sB = orient3d(P, Q, R, B);
+  sC = orient3d(P, Q, R, C);
+  orient3dcount+=3;
+
+  if (b->epsilon) {
+    if ((sA != 0) && iscoplanar(P, Q, R, A, sA)) sA = 0;
+    if ((sB != 0) && iscoplanar(P, Q, R, B, sB)) sB = 0;
+    if ((sC != 0) && iscoplanar(P, Q, R, C, sC)) sC = 0;
+  }
+
+  if (b->verbose > 2) {
+    printf("      Tri-tri (%d %d %d)-(%d %d %d) (%c%c%c)\n", pointmark(A),
+      pointmark(B), pointmark(C), pointmark(P), pointmark(Q), pointmark(R),
+      sA > 0 ? '+' : (sA < 0 ? '-' : '0'), sB>0 ? '+' : (sB<0 ? '-' : '0'),
+      sC>0 ? '+' : (sC<0 ? '-' : '0'));
+  }
+  // tritricount++;
+  iu = iv = 0;
+
+  if (sA < 0) {
+    if (sB < 0) {
+      if (sC < 0) { // (---).
+        return DISJOINT; 
+      } else {
+        if (sC > 0) { // (--+).
+          // All points are in the right positions.
+          SETVECTOR3(U, A, B, C);  // I3
+          SETVECTOR3(V, P, Q, R);  // I2
+          SETVECTOR3(pu, 0, 1, 2);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 0;
+        } else { // (--0).
+          SETVECTOR3(U, A, B, C);  // I3
+          SETVECTOR3(V, P, Q, R);  // I2
+          SETVECTOR3(pu, 0, 1, 2);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 1;
+        }
+      }
+    } else { 
+      if (sB > 0) {
+        if (sC < 0) { // (-+-).
+          SETVECTOR3(U, C, A, B);  // PT = ST
+          SETVECTOR3(V, P, Q, R);  // I2
+          SETVECTOR3(pu, 2, 0, 1);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 0;
+        } else {
+          if (sC > 0) { // (-++).
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 1, 2, 0);
+            SETVECTOR3(pv, 1, 0, 2); iv = 1;
+            z1 = 0;
+          } else { // (-+0).
+            SETVECTOR3(U, C, A, B);  // PT = ST
+            SETVECTOR3(V, P, Q, R);  // I2
+            SETVECTOR3(pu, 2, 0, 1);
+            SETVECTOR3(pv, 0, 1, 2);
+            z1 = 2;
+          }
+        }
+      } else {
+        if (sC < 0) { // (-0-).
+          SETVECTOR3(U, C, A, B);  // PT = ST
+          SETVECTOR3(V, P, Q, R);  // I2
+          SETVECTOR3(pu, 2, 0, 1);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 1;
+        } else {
+          if (sC > 0) { // (-0+).
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 1, 2, 0);
+            SETVECTOR3(pv, 1, 0, 2); iv = 1;
+            z1 = 2;
+          } else { // (-00).
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 1, 2, 0);
+            SETVECTOR3(pv, 1, 0, 2); iv = 1;
+            z1 = 3;
+          }
+        }
+      }
+    }
+  } else {
+    if (sA > 0) {
+      if (sB < 0) {
+        if (sC < 0) { // (+--).
+          SETVECTOR3(U, B, C, A);  // PT = ST x ST
+          SETVECTOR3(V, P, Q, R);  // I2
+          SETVECTOR3(pu, 1, 2, 0);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 0;
+        } else {
+          if (sC > 0) { // (+-+).
+            SETVECTOR3(U, C, A, B);  // PT = ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 2, 0, 1);
+            SETVECTOR3(pv, 1, 0, 2); iv = 1;
+            z1 = 0;
+          } else { // (+-0).
+            SETVECTOR3(U, C, A, B);  // PT = ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 2, 0, 1);
+            SETVECTOR3(pv, 1, 0, 2); iv = 1;
+            z1 = 2;
+          }
+        }
+      } else { 
+        if (sB > 0) {
+          if (sC < 0) { // (++-).
+            SETVECTOR3(U, A, B, C);  // I3
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 0, 1, 2);
+            SETVECTOR3(pv, 1, 0, 2); iv = 1;
+            z1 = 0;
+          } else {
+            if (sC > 0) { // (+++).
+              return DISJOINT; 
+            } else { // (++0).
+              SETVECTOR3(U, A, B, C);  // I3
+              SETVECTOR3(V, Q, P, R);  // PL = SL
+              SETVECTOR3(pu, 0, 1, 2);
+              SETVECTOR3(pv, 1, 0, 2); iv = 1;
+              z1 = 1; 
+            }
+          }
+        } else {
+          if (sC < 0) { // (+0-).
+            SETVECTOR3(U, B, C, A);  // PT = ST x ST
+            SETVECTOR3(V, P, Q, R);  // I2
+            SETVECTOR3(pu, 1, 2, 0);
+            SETVECTOR3(pv, 0, 1, 2);
+            z1 = 2;
+          } else {
+            if (sC > 0) { // (+0+).
+              SETVECTOR3(U, C, A, B);  // PT = ST
+              SETVECTOR3(V, Q, P, R);  // PL = SL
+              SETVECTOR3(pu, 2, 0, 1);
+              SETVECTOR3(pv, 1, 0, 2); iv = 1;
+              z1 = 1;
+            } else { // (+00).
+              SETVECTOR3(U, B, C, A);  // PT = ST x ST
+              SETVECTOR3(V, P, Q, R);  // I2
+              SETVECTOR3(pu, 1, 2, 0);
+              SETVECTOR3(pv, 0, 1, 2);
+              z1 = 3; 
+            }
+          }
+        }
+      }
+    } else { 
+      if (sB < 0) {
+        if (sC < 0) { // (0--).
+          SETVECTOR3(U, B, C, A);  // PT = ST x ST
+          SETVECTOR3(V, P, Q, R);  // PL = I2
+          SETVECTOR3(pu, 1, 2, 0);
+          SETVECTOR3(pv, 0, 1, 2);
+          z1 = 1;
+        } else {
+          if (sC > 0) { // (0-+).
+            SETVECTOR3(U, A, B, C);  // I3
+            SETVECTOR3(V, P, Q, R);  // I2
+            SETVECTOR3(pu, 0, 1, 2);
+            SETVECTOR3(pv, 0, 1, 2);
+            z1 = 2;
+          } else { // (0-0).
+            SETVECTOR3(U, C, A, B);  // PT = ST
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 2, 0, 1);
+            SETVECTOR3(pv, 1, 0, 2); iv = 1;
+            z1 = 3; 
+          }
+        }
+      } else { 
+        if (sB > 0) {
+          if (sC < 0) { // (0+-).
+            SETVECTOR3(U, A, B, C);  // I3
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 0, 1, 2);
+            SETVECTOR3(pv, 1, 0, 2); iv = 1;
+            z1 = 2;
+          } else {
+            if (sC > 0) { // (0++).
+              SETVECTOR3(U, B, C, A);  // PT = ST x ST
+              SETVECTOR3(V, Q, P, R);  // PL = SL
+              SETVECTOR3(pu, 1, 2, 0);
+              SETVECTOR3(pv, 1, 0, 2); iv = 1;
+              z1 = 1;
+            } else { // (0+0).
+              SETVECTOR3(U, C, A, B);  // PT = ST
+              SETVECTOR3(V, P, Q, R);  // I2
+              SETVECTOR3(pu, 2, 0, 1);
+              SETVECTOR3(pv, 0, 1, 2);
+              z1 = 3; 
+            }
+          }
+        } else {
+          if (sC < 0) { // (00-).
+            SETVECTOR3(U, A, B, C);  // I3
+            SETVECTOR3(V, Q, P, R);  // PL = SL
+            SETVECTOR3(pu, 0, 1, 2);
+            SETVECTOR3(pv, 1, 0, 2); iv = 1;
+            z1 = 3; 
+          } else {
+            if (sC > 0) { // (00+).
+              SETVECTOR3(U, A, B, C);  // I3
+              SETVECTOR3(V, P, Q, R);  // I2
+              SETVECTOR3(pu, 0, 1, 2);
+              SETVECTOR3(pv, 0, 1, 2);
+              z1 = 3; 
+            } else { // (000)
+              // (A, B, C) is coplanar with (P, Q, R).
+              SETVECTOR3(U, A, B, C);  // I3
+              SETVECTOR3(V, P, Q, R);  // I2
+              SETVECTOR3(pu, 0, 1, 2);
+              SETVECTOR3(pv, 0, 1, 2);
+              z1 = -1;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  sP = orient3d(U[0], U[1], U[2], V[0]);
+  sQ = orient3d(U[0], U[1], U[2], V[1]);
+  sR = orient3d(U[0], U[1], U[2], V[2]);
+  orient3dcount+=3;
+
+  if (b->epsilon) {
+    if ((sP != 0) && iscoplanar(U[0], U[1], U[2], V[0], sP)) sP = 0;
+    if ((sQ != 0) && iscoplanar(U[0], U[1], U[2], V[1], sQ)) sQ = 0;
+    if ((sR != 0) && iscoplanar(U[0], U[1], U[2], V[2], sR)) sR = 0;
+  }
+
+  if (b->verbose > 2) {
+    printf("      Tri-tri (%d %d %d)-(%d %d %d) (%c%c%c)\n", pointmark(U[0]),
+      pointmark(U[1]), pointmark(U[2]), pointmark(V[0]), pointmark(V[1]), 
+      pointmark(V[2]), sP>0 ? '+' : (sP<0 ? '-' : '0'), 
+      sQ>0 ? '+' : (sQ<0 ? '-' : '0'), sR>0 ? '+' : (sR<0 ? '-' : '0'));
+  }
+
+  if (sP < 0) {
+    if (sQ < 0) {
+      if (sR < 0) {  // (---)
+        return DISJOINT;
+      } else {
+        if (sR > 0) { // (--+)
+          // P1->Q1 is opposite to A1->B1. Swicth A1 and B1.
+          SETVECTOR3(W, V[0], V[1], V[2]);  // I3
+          SWAP2(U[0], U[1], Ptmp);  // PL = SL
+          SETVECTOR3(pw, pv[0], pv[1], pv[2]);
+          SWAP2(pu[0], pu[1], itmp); iu = 1;
+          z2 = 0;
+        } else {  // (--0)
+          SETVECTOR3(W, V[0], V[1], V[2]);  // I3
+          SWAP2(U[0], U[1], Ptmp);  // PL = SL
+          SETVECTOR3(pw, pv[0], pv[1], pv[2]);
+          SWAP2(pu[0], pu[1], itmp); iu = 1;
+          z2 = 1;
+        }
+      }
+    } else {
+      if (sQ > 0) {
+        if (sR < 0) {  // (-+-)
+          SETVECTOR3(W, V[2], V[0], V[1]);  // PT = ST
+          SWAP2(U[0], U[1], Ptmp);  // PL = SL
+          SETVECTOR3(pw, pv[2], pv[0], pv[1]);
+          SWAP2(pu[0], pu[1], itmp); iu = 1;
+          z2 = 0;
+        } else {
+          if (sR > 0) { // (-++)
+            SETVECTOR3(W, V[1], V[2], V[0]);  // PT = ST x ST
+            SETVECTOR3(pw, pv[1], pv[2], pv[0]);
+            z2 = 0;
+          } else { // (-+0)
+            SETVECTOR3(W, V[2], V[0], V[1]);  // PT = ST
+            SWAP2(U[0], U[1], Ptmp); // PL = SL
+            SETVECTOR3(pw, pv[2], pv[0], pv[1]);
+            SWAP2(pu[0], pu[1], itmp); iu = 1;
+            z2 = 2;
+          }
+        }
+      } else {
+        if (sR < 0) {  // (-0-)
+          SETVECTOR3(W, V[2], V[0], V[1]);  // PT = ST
+          SWAP2(U[0], U[1], Ptmp); // PL = SL
+          SETVECTOR3(pw, pv[2], pv[0], pv[1]);
+          SWAP2(pu[0], pu[1], itmp); iu = 1;
+          z2 = 1;
+        } else {
+          if (sR > 0) {  // (-0+)
+            SETVECTOR3(W, V[1], V[2], V[0]);  // PT = ST x ST
+            SETVECTOR3(pw, pv[1], pv[2], pv[0]);
+            z2 = 2;
+          } else {  // (-00)
+            SETVECTOR3(W, V[1], V[2], V[0]);  // PT = ST x ST
+            SETVECTOR3(pw, pv[1], pv[2], pv[0]);
+            z2 = 3;
+          }
+        }
+      }
+    }
+  } else {
+    if (sP > 0) {
+      if (sQ < 0) {
+        if (sR < 0) {  // (+--)
+          SETVECTOR3(W, V[1], V[2], V[0]);  // PT = ST x ST
+          SWAP2(U[0], U[1], Ptmp); // PL = SL
+          SETVECTOR3(pw, pv[1], pv[2], pv[0]);
+          SWAP2(pu[0], pu[1], itmp); iu = 1;
+          z2 = 0;
+        } else {
+          if (sR > 0) {  // (+-+)
+            SETVECTOR3(W, V[2], V[0], V[1]);  // PT = ST
+            SETVECTOR3(pw, pv[2], pv[0], pv[1]);
+            z2 = 0;
+          } else {  // (+-0)
+            SETVECTOR3(W, V[2], V[0], V[1]);  // PT = ST
+            SETVECTOR3(pw, pv[2], pv[0], pv[1]);
+            z2 = 2;
+          }
+        }
+      } else {
+        if (sQ > 0) {
+          if (sR < 0) {  // (++-)
+            SETVECTOR3(W, V[0], V[1], V[2]);  // I3
+            SETVECTOR3(pw, pv[0], pv[1], pv[2]);
+            z2 = 0;
+          } else {
+            if (sR > 0) {  // (+++)
+              return DISJOINT;
+            } else {  // (++0)
+              SETVECTOR3(W, V[0], V[1], V[2]);  // I3
+              SETVECTOR3(pw, pv[0], pv[1], pv[2]);
+              z2 = 1;
+            }
+          }
+        } else { // sQ == 0
+          if (sR < 0) {  // (+0-)
+            SETVECTOR3(W, V[1], V[2], V[0]);  // PT = ST x ST
+            SWAP2(U[0], U[1], Ptmp); // PL = SL
+            SETVECTOR3(pw, pv[1], pv[2], pv[0]);
+            SWAP2(pu[0], pu[1], itmp); iu = 1;
+            z2 = 2;
+          } else {
+            if (sR > 0) {  // (+0+)
+              SETVECTOR3(W, V[2], V[0], V[1]);  // PT = ST
+              SETVECTOR3(pw, pv[2], pv[0], pv[1]);
+              z2 = 1;
+            } else {  // (+00)
+              SETVECTOR3(W, V[1], V[2], V[0]);  // PT = ST x ST
+              SWAP2(U[0], U[1], Ptmp); // PL = SL
+              SETVECTOR3(pw, pv[1], pv[2], pv[0]);
+              SWAP2(pu[0], pu[1], itmp); iu = 1;
+              z2 = 3;
+            }
+          }
+        }
+      }
+    } else { // sP == 0
+      if (sQ < 0) {
+        if (sR < 0) {  // (0--)
+          SETVECTOR3(W, V[1], V[2], V[0]);  // PT = ST x ST
+          SWAP2(U[0], U[1], Ptmp); // PL = SL
+          SETVECTOR3(pw, pv[1], pv[2], pv[0]);
+          SWAP2(pu[0], pu[1], itmp); iu = 1;
+          z2 = 1;
+        } else {
+          if (sR > 0) {  // (0-+)
+            SETVECTOR3(W, V[0], V[1], V[2]);  // I3
+            SWAP2(U[0], U[1], Ptmp); // PL = SL
+            SETVECTOR3(pw, pv[0], pv[1], pv[2]);
+            SWAP2(pu[0], pu[1], itmp); iu = 1;
+            z2 = 2;
+          } else {  // (0-0)
+            SETVECTOR3(W, V[2], V[0], V[1]);  // PT = ST
+            SETVECTOR3(pw, pv[2], pv[0], pv[1]);
+            z2 = 3;
+          }
+        }
+      } else {
+        if (sQ > 0) {
+          if (sR < 0) {  // (0+-)
+            SETVECTOR3(W, V[0], V[1], V[2]);  // I3
+            SETVECTOR3(pw, pv[0], pv[1], pv[2]);
+            z2 = 2;
+          } else {
+            if (sR > 0) {  // (0++)
+              SETVECTOR3(W, V[1], V[2], V[0]);  // PT = ST x ST
+              SETVECTOR3(pw, pv[1], pv[2], pv[0]);
+              z2 = 1;
+            } else {  // (0+0)
+              SETVECTOR3(W, V[2], V[0], V[1]);  // PT = ST
+              SWAP2(U[0], U[1], Ptmp); // PL = SL
+              SETVECTOR3(pw, pv[2], pv[0], pv[1]);
+              SWAP2(pu[0], pu[1], itmp); iu = 1;
+              z2 = 3;
+            }
+          }
+        } else { // sQ == 0
+          if (sR < 0) {  // (00-)
+            SETVECTOR3(W, V[0], V[1], V[2]);  // I3
+            SETVECTOR3(pw, pv[0], pv[1], pv[2]);
+            z2 = 3;
+          } else {
+            if (sR > 0) {  // (00+)
+              SETVECTOR3(W, V[0], V[1], V[2]);  // I3
+              SWAP2(U[0], U[1], Ptmp); // PL = SL
+              SETVECTOR3(pw, pv[0], pv[1], pv[2]);
+              SWAP2(pu[0], pu[1], itmp); iu = 1;
+              z2 = 3;
+            } else {  // (000)
+              z2 = -1;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  if (z1 == -1) {
+    assert(z2 == -1);  // SELF_CHECK
+    return tri_tri_2d(A, B, C, P, Q, R, O, level, types, pos);
+  }
+
+  if ((iu == 1) && (z1 == 2)) {
+    z1 = 4; // A and B are inverted.
+  }
+
+  if (z2 == 1) {
+    s1 = orient3d(U[0], U[2], W[0], W[2]);  // A, C, P, R
+    s2 = orient3d(U[1], U[2], W[1], W[2]);  // B, C, Q, R
+    orient3dcount+=2;
+    if (b->epsilon > 0) {
+      if ((s1 != 0) && iscoplanar(U[0], U[2], W[0], W[2], s1)) s1 = 0;
+      if ((s2 != 0) && iscoplanar(U[1], U[2], W[1], W[2], s2)) s2 = 0;
+    }
+  } else {
+    s1 = orient3d(U[0], U[2], W[2], W[1]);  // A, C, R, Q
+    s2 = orient3d(U[1], U[2], W[2], W[0]);  // B, C, R, P
+    orient3dcount+=2;
+    if (b->epsilon > 0) {
+      if ((s1 != 0) && iscoplanar(U[0], U[2], W[2], W[1], s1)) s1 = 0;
+      if ((s2 != 0) && iscoplanar(U[1], U[2], W[2], W[0], s2)) s2 = 0;
+    }
+  }
+
+  if (b->verbose > 2) {
+    printf("      Tri-tri (%d %d %d)-(%d %d %d) (%d-%d) (%c%c)\n",
+      pointmark(U[0]), pointmark(U[1]), pointmark(U[2]), pointmark(W[0]), 
+      pointmark(W[1]), pointmark(W[2]), z1, z2,
+      s1>0 ? '+' : (s1<0 ? '-' : '0'), s2>0 ? '+' : (s2<0 ? '-' : '0'));
+  }
+
+  if (z2 == 1) {
+    if (s1 < 0) {
+      return 0;
+    }
+    if (s2 > 0) {
+      return 0;
+    }
+  } else {
+    if (s1 > 0) {
+      return 0;
+    }
+    if (s2 < 0) {
+      return 0;
+    }
+  }
+
+  if (level == 0) {
+    return 1;
+  }
+
+  if (z2 == 1) {
+
+    if (z1 == 0) {  // (01)
+      if (s1 == 0) {
+        // R = k in [A, C] (tritri-010###).
+        types[0] = (int) TOUCHEDGE;
+        pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+        pos[1] = pw[2]; // R
+        types[1] = (int) DISJOINT;
+      } else {
+        if (s2 == 0) {
+          // R = l in [B, C] (tritri-01#0##).
+          types[0] = (int) TOUCHEDGE;
+          pos[0] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+          pos[1] = pw[2]; // R
+          types[1] = (int) DISJOINT;  
+        } else {
+          // R in [k, l] in [A, B, C] (tritri-01+-##).
+          types[0] = (int) TOUCHFACE;
+          pos[0] = 3; // [A, B, C]
+          pos[1] = pw[2]; // R
+          types[1] = (int) DISJOINT;  
+        }
+      }
+    } else if (z1 == 1) {  // (11)
+      assert(s1 == 0); // SELF_CHECK
+      // C = R (tritri-110###).
+      types[0] = (int) SHAREVERT;
+      pos[0] = pu[2]; // C
+      pos[1] = pw[2]; // R
+      types[1] = (int) DISJOINT;  
+    } else if (z1 == 2) {  // (21)
+      if (s1 == 0) {
+        // R = A (tritri-210###).
+        types[0] = (int) SHAREVERT;
+        pos[0] = pu[0]; // A
+        pos[1] = pw[2]; // R
+        types[1] = (int) DISJOINT;  
+      } else {
+        if (s2 == 0) {
+          // R = l, R in [B, C] (tritri-21#0##).
+          types[0] = (int) TOUCHEDGE;
+          pos[0] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+          pos[1] = pw[2]; // R
+          types[1] = (int) DISJOINT;  
+        } else {
+          // R in [k, l] in [A, B, C] (tritri-21+-##).
+          types[0] = (int) TOUCHFACE;
+          pos[0] = 3; // Interior of [A, B, C]
+          pos[1] = pw[2]; // R
+          types[1] = (int) DISJOINT;  
+        }
+      }
+    } else if (z1 == 3) {  // (31)
+      if (s1 == 0) {
+        // R = A (tritri-310###).
+        types[0] = (int) SHAREVERT;
+        pos[0] = pu[0]; // A
+        pos[1] = pw[2]; // R
+        types[1] = (int) DISJOINT;  
+      } else {
+        if (s2 == 0) {
+          // R = B (tritri-31#0##).
+          types[0] = (int) SHAREVERT;
+          pos[0] = pu[1]; // B
+          pos[1] = pw[2]; // R
+          types[1] = (int) DISJOINT;  
+        } else {
+          // R in [A, B] (tritri-31+-##).
+          types[0] = (int) TOUCHEDGE;
+          pos[0] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // [A, B]
+          pos[1] = pw[2]; // R
+          types[1] = (int) DISJOINT;  
+        }
+      }
+    } else if (z1 == 4) { // (41)
+      if (s1 == 0) { // (tritri-410###).
+        // R touches [C, A]
+        types[0] = (int) TOUCHEDGE;
+        pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+        pos[1] = pw[2]; // R
+        types[1] = (int) DISJOINT;
+      } else {
+        if (s2 == 0) { // (tritri-41#0##).
+          // R = B
+          types[0] = (int) SHAREVERT;
+          pos[0] = pu[1]; // B
+          pos[1] = pw[2]; // R
+          types[1] = (int) DISJOINT;
+        } else { // (tritri-41+-##)
+          // R in [k, l]
+          types[0] = (int) TOUCHFACE;
+          pos[0] = 3; // [A, B, C]
+          pos[1] = pw[2]; // R
+          types[1] = (int) DISJOINT;
+        }
+      }
+    }
+
+    return 1;
+  } // z2 == 1
+
+  if (z1 == 1) {
+  
+    if (z2 == 0) { // (10)
+      if (s1 == 0) {
+        // C = j, C in [Q, R] (tritri-100###).
+        types[0] = (int) ACROSSVERT;
+        pos[0] = pu[2]; // C
+        pos[1] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+        types[1] = (int) DISJOINT;  
+      } else {
+        if (s2 == 0) {
+          // C = i, C in [P, R] (tritri-10#0##).
+          types[0] = (int) ACROSSVERT;
+          pos[0] = pu[2]; // C
+          pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+          types[1] = (int) DISJOINT;  
+        } else {
+          // C in [i, j] in [P, Q, R] (tritri-10-+##).
+          types[0] = (int) ACROSSVERT;
+          pos[0] = pu[2]; // C
+          pos[1] = 3; // Interior of [P, Q, R]
+          types[1] = (int) DISJOINT;  
+        }
+      }
+    } else if (z2 == 2) {  // (12)
+      if (s1 == 0) { // 
+        // C = j, C in [Q, R] (tritri-120###).
+        types[0] = (int) ACROSSVERT;
+        pos[0] = pu[2]; // C
+        pos[1] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+        types[1] = (int) DISJOINT;  
+      } else {
+        if (s2 == 0) {
+          // C = P (tritri-12#0##).
+          types[0] = (int) SHAREVERT;
+          pos[0] = pu[2]; // C
+          pos[1] = pw[0]; // P
+          types[1] = (int) DISJOINT;  
+        } else {
+          // C in [i, j] in [P, Q, R] (tritri-12-+##).
+          types[0] = (int) ACROSSVERT;
+          pos[0] = pu[2]; // C
+          pos[1] = 3; // Interior of [P, Q, R]
+          types[1] = (int) DISJOINT;  
+        }
+      }
+    } else if (z2 == 3) {  // (13)
+      if (s1 == 0) {
+        // C = Q (tritri-130###).
+        types[0] = (int) SHAREVERT;
+        pos[0] = pu[2]; // C
+        pos[1] = pw[1]; // Q
+        types[1] = (int) DISJOINT;  
+      } else {
+        if (s2 == 0) {
+          // C = P (tritri-13#0##).
+          types[0] = (int) SHAREVERT;
+          pos[0] = pu[2]; // C
+          pos[1] = pw[0]; // P
+          types[1] = (int) DISJOINT;  
+        } else {
+          // C in [P, Q] (tritri-13-+##).
+          types[0] = (int) ACROSSVERT;
+          pos[0] = pu[2]; // C
+          pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // [P, Q]
+          types[1] = (int) DISJOINT;  
+        }
+      }
+    }
+
+    return 1;
+  } // if (z1 == 1)
+
+  // Two additional orientation tests are needed.
+  s3 = orient3d(U[0], U[2], W[2], W[0]);  // A, C, R, P
+  s4 = orient3d(U[1], U[2], W[2], W[1]);  // B, C, R, Q
+  orient3dcount+=2;
+  if (b->epsilon > 0) {
+    if ((s3 != 0) && iscoplanar(U[0], U[2], W[2], W[0], s3)) s3 = 0;
+    if ((s4 != 0) && iscoplanar(U[1], U[2], W[2], W[1], s4)) s4 = 0;
+  }
+
+  if (b->verbose > 2) {
+    printf("      (tritri-%d%d%c%c%c%c)\n", z1, z2, 
+      s1>0 ? '+' : (s1<0 ? '-' : '0'), s2>0 ? '+' : (s2<0 ? '-' : '0'), 
+      s3>0 ? '+' : (s3<0 ? '-' : '0'), s4>0 ? '+' : (s4<0 ? '-' : '0'));
+  }
+
+  if (z1 == 0) {
+    
+    if (z2 == 0) {  // (00)
+      if (s1 < 0) {
+        if (s3 > 0) {
+          assert(s2 > 0); // SELF_CHECK.
+          if (s4 > 0) {
+            // [i, j] overlaps [k, l] (tritri-00-+++).
+            types[0] = (int) ACROSSEDGE;
+            pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+            pos[1] = 3;     // [P, Q, R]
+            types[1] = (int) ACROSSFACE;
+            pos[2] = 3;     // [A, B, C]
+            pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+          } else {
+            if (s4 == 0) {
+              // j = l, [i, j] contains [k, l] (tritri-00-++0).
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else {
+              // [i, j] contains [k, l] (tritri-00-++-).
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = 3;     // [P, Q, R]
+            }
+          }
+        } else {
+          if (s3 == 0) { // (00-+0#)
+            assert(s2 > 0); // SELF_CHECK.
+            if (s4 > 0) {
+              // i = k, [i, j] overlaps [k, l] (tritri-00-+0+).
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+              types[1] = (int) ACROSSFACE;
+              pos[2] = 3;     // [A, B, C]
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else {
+              if (s4 == 0) {
+                // [i, j] = [k, l] (tritri-00-+00).
+                types[0] = (int) ACROSSEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else {
+                // i = k, [i, j] contains [k, l] (tritri-00-+0-).
+                types[0] = (int) ACROSSEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = 3;     // [P, Q, R] 
+              }
+            }
+          } else { // s3 < 0
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [i, j] in [k, l] in [A, B, C] (tritri-00-+-+).
+                types[0] = (int) ACROSSFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSFACE;
+                pos[2] = 3;     // [A, B, C]
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else {
+                if (s4 == 0) {
+                  // j = l, [i, j] in [k, l] (tritri-00-+-0)
+                  types[0] = (int) ACROSSFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                  types[1] = (int) ACROSSEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+                } else { // s4 < 0
+                  // [i, j] overlaps [k, l] (tritri-00-+--)
+                  types[0] = (int) ACROSSFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                  types[1] = (int) ACROSSEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = 3;     // [P, Q, R]
+                }
+              }
+            } else { // s2 == 0
+              assert(s4 < 0); // SELF_CHECK
+              // i = l, [P, R] intersects [B, C] (tritri-00#0##).
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else { // s1 == 0
+        // j = k, [Q, R] intersects [A, B] (tritri-000###).
+        types[0] = (int) ACROSSEDGE;
+        pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+        pos[1] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+        types[1] = (int) DISJOINT;
+      }
+    } else if (z2 == 2) {  // (02)
+      if (s1 < 0) {
+        if (s3 > 0) { // (02-#+#)
+          assert(s2 > 0); // SELF_CHECK;
+          if (s4 > 0) {
+            // [P, j] overlaps [k, l] (tritri-02-+++).
+            types[0] = (int) ACROSSEDGE;
+            pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+            pos[1] = 3;     // [P, Q, R]
+            types[1] = (int) ACROSSFACE;
+            pos[2] = 3;     // [A, B, C]
+            pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+          } else {
+            if (s4 == 0) {
+              // j = k, [i, j] contains [k, l] (tritri-02-++0).
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else { // s4 < 0
+              // [i, j] contains [k, l] (tritri-02-++-).
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = 3;     // [P, Q, R]
+            }
+          }
+        } else {
+          if (s3 == 0) { // (02-#0#)
+            assert(s2 > 0); // SELF_CHECK
+            if (s4 > 0) {
+              // P = k, [P, j] in [k, l] (tritri-02-+0+).
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = pw[0]; // P
+              types[1] = (int) ACROSSFACE;
+              pos[2] = 3;     // [A, B, C]
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else {
+              if (s4 == 0) {
+                // [P, j] = [k, l] (tritri-02-+00).
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else {  // s4 < 0
+                // P = k, [P, j] contains [k, l] (tritri-02-+0-).
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = 3;     // [P, Q, R]
+              }
+            }
+          } else { // s3 < 0.
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [P, j] in [k, l] in [A, B, C] (tritri-02-+-+).
+                types[0] = (int) TOUCHFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSFACE;
+                pos[2] = 3;     // [A, B, C]
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else {
+                if (s4 == 0) {
+                  // j = l, [P, j] overlaps [k, l] (tritri-02-+-0).
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+                } else { // s4 < 0
+                  // [P, j] overlaps [k, l] (tritri-02-+--).
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = 3;     // [P, Q, R]
+                }
+              }
+            } else {  // s2 == 0
+              assert(s4 < 0); // SELF_CHECK
+              // P = k, P in [B, C] (tritri-02#0##).
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[1] = pw[0]; // P
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else { // s1 == 0
+        // j = k, [Q, R] intersects [A, C] (tritri-020###).
+        types[0] = (int) ACROSSEDGE;
+        pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+        pos[1] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+        types[1] = (int) DISJOINT;
+      }
+    } else if (z2 == 3) {  // (03)
+      if (s1 < 0) {
+        if (s3 > 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // [P, Q] overlaps [k, l] (tritri-03-+++).
+            types[0] = (int) ACROSSEDGE;
+            pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+            pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+            types[1] = (int) TOUCHFACE;
+            pos[2] = 3;     // [A, B, C]
+            pos[3] = pw[1]; // Q
+          } else {
+            if (s4 == 0) {
+              // Q = l, [P, Q] contains [k, l] (tritri-03-++0).
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              types[1] = (int) TOUCHEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = pw[1]; // Q
+            } else { // s4 < 0
+              // [P, Q] contains [k, l] (tritri-03-++-).
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+            }
+          }
+        } else {
+          if (s3 == 0) {
+            assert(s2 > 0);  // SELF_CHECK
+            if (s4 > 0) {
+              // P = k, [P, Q] in [k, l] (tritri-03-+0+).
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = pw[0]; // P
+              types[1] = (int) TOUCHFACE;
+              pos[2] = 3;     // [A, B, C]
+              pos[3] = pw[1]; // Q
+            } else {
+              if (s4 == 0) {
+                // [P, Q] = [k, l] (tritri-03-+00).
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = pw[0]; // P
+                types[1] = (int) TOUCHEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = pw[1]; // Q
+              } else {  // s4 < 0
+                // P = k, [P, Q] contains [k, l] (tritri-03-+0-).
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              }
+            }
+          } else { // s3 < 0
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [P, Q] in [k, l] (tritri-03-+-+).
+                types[0] = (int) TOUCHFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = pw[0]; // P
+                types[1] = (int) TOUCHFACE;
+                pos[2] = 3;     // [A, B, C]
+                pos[3] = pw[1]; // Q
+              } else {
+                if (s4 == 0) {
+                  // Q = l, [P, Q] in [k, l] (tritri-03-+-0).
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) TOUCHEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = pw[1]; // Q
+                } else { // s4 < 0
+                  // [P, Q] overlaps [k, l] (tritri-03-+--).
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+                }
+              }
+            } else {  // s2 == 0
+              // P = l in [B, C] (tritri-03#0##).
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[1] = pw[0]; // P
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else {
+        // Q = k in [A, C] (tritri-030###).
+        types[0] = (int) TOUCHEDGE;
+        pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+        pos[1] = pw[1]; // Q
+        types[1] = (int) DISJOINT;
+      }
+    }
+
+    return 1;
+  } // if (z1 == 0)
+
+  if (z1 == 2) {
+
+    if (z2 == 0) {  // (20)
+      if (s1 < 0) {
+        if (s3 > 0) {
+          assert(s2 > 0);  // SELF_CHECK
+          if (s4 > 0) {
+            // [i, j] overlaps [A, l] (tritri-20-+++).
+            types[0] = (int) ACROSSVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = 3;     // [P, Q, R]
+            types[1] = (int) ACROSSFACE;
+            pos[2] = 3;     // [A, B, C]
+            pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+          } else {
+            if (s4 == 0) {
+              // j = l, [i, j] contains [A, l] (tritri-20-++0).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else {  // s4 < 0
+              // [i, j] contains [A, l] (tritri-20-++-).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = 3;     // [P, Q, R]
+            }
+          }
+        } else {
+          if (s3 == 0) {
+            assert(s2 > 0); // SELF_CHECK
+            if (s4 > 0) {
+              // i = A, [i, j] overlaps [A, l] (tritri-20-+0+).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+              types[1] = (int) ACROSSFACE;
+              pos[2] = 3;     // [A, B, C]
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else {
+              if (s4 == 0) {
+                // [i, j] = [A, l] (tritri-20-+00).
+                types[0] = (int) ACROSSVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else { // s4 < 0
+                // i = A, [i, j] contains [A, l] (tritri-20-+0-).
+                types[0] = (int) ACROSSVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = 3;     // [P, Q, R]
+              }
+            }
+          } else { // s3 < 0
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [i, j] in [A, l] in [A, B, C] (tritri-20-+-+).
+                types[0] = (int) ACROSSFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSFACE;
+                pos[2] = 3;     // [A, B, C]
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else {
+                if (s4 == 0) {
+                  // j = l, [i, j] in [A, l] (tritri-20-+-0).
+                  types[0] = (int) ACROSSFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                  types[1] = (int) ACROSSEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+                } else { // s4 < 0
+                  // [i, j] overlaps [A, l] (tritri-20-+--).
+                  types[0] = (int) ACROSSFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                  types[1] = (int) ACROSSEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = 3;     // [P, Q, R]
+                }
+              }
+            } else { // s2 == 0
+              // i = l, [P, R] intersects [B, C] (tritri-20#0##).
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else { // s1 == 0
+        // j = A in [Q, R] (tritri-200###).
+        types[0] = (int) ACROSSVERT;
+        pos[0] = pu[0]; // A
+        pos[1] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+        types[1] = (int) DISJOINT;
+      }
+    } else if (z2 == 2) {  // (22)
+      if (s1 < 0) {
+        if (s3 > 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // [P, j] overlaps [A, l] (tritri-22-+++).
+            types[0] = (int) ACROSSVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = 3;     // [P, Q, R]
+            types[1] = (int) ACROSSFACE;
+            pos[2] = 3;     // [A, B, C]
+            pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+          } else {
+            if (s4 == 0) {
+              // j = l, [P, j] contains [A, l] (tritri-22-++0).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else { // s4 < 0
+              // [P, j] contains [A, l] (tritri-22-++-).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = 3;     // [P, Q, R]
+            }
+          }
+        } else {
+          if (s3 == 0) {
+            assert(s2 > 0); // SELF_CHECK
+            if (s4 > 0) {
+              // P = A, [P, j] in [A, l] (tritri-22-+0+).
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = pw[0]; // P
+              types[1] = (int) ACROSSFACE;
+              pos[2] = 3;     // [A, B, C]
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else {
+              if (s4 == 0) {
+                // [P, j] = [A, l] (tritri-22-+00).
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else { // s4 < 0
+                // P = A, [P, j] contains [A, l] (tritri-22-+0-).
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = 3;     // [P, Q, R]
+              }
+            }
+          } else { // s3 < 0
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [P, j] in [A, l] in [A, B, C] (tritri-22-+-+).
+                types[0] = (int) TOUCHFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSFACE;
+                pos[2] = 3;     // [A, B, C]
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else {
+                if (s4 == 0) {
+                  // j = l, [P, j] in [A, l] (tritri-22-+-0).
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+                } else { // s4 < 0
+                  // P, j] overlaps [A, l] (tritri-22-+--).
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = 3;     // [P, Q, R]
+                }
+              }
+            } else { // s2 == 0
+              // P = l, P in [B, C] (tritri-22#0##).
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // Int({[B, C])
+              pos[1] = pw[0]; // P
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else {
+        // j = A in [Q, R] (tritri-220###).
+        types[0] = (int) ACROSSVERT;
+        pos[0] = pu[0]; // A
+        pos[1] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+        types[1] = (int) DISJOINT;
+      }
+    } else if (z2 == 3) {  // (23)
+      if (s1 < 0) {
+        if (s3 > 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // [P, Q] overlaps [A, l] (tritri-23-+++).
+            types[0] = (int) ACROSSVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+            types[1] = (int) TOUCHFACE;
+            pos[2] = 3;     // [A, B, C]
+            pos[3] = pw[1]; // Q
+          } else {
+            if (s4 == 0) {
+              // Q = l, [P, Q] contains [A, l] (tritri-23-++0).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              types[1] = (int) TOUCHEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = pw[1]; // Q
+            } else { // s4 < 0
+              // [P, Q] contains [A, l] (tritri-23-++-).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+            }
+          }
+        } else {
+          if (s3 == 0) {
+            assert(s2 > 0); // SELF_CHECK
+            if (s4 > 0) {
+              // P = A, [P, Q] in [A, l] (tritri-23-+0+).
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = pw[0]; // P
+              types[1] = (int) TOUCHFACE;
+              pos[2] = 3;     // [A, B, C]
+              pos[3] = pw[1]; // Q
+            } else {
+              if (s4 == 0) {
+                // [P, Q] = [A, l] (tritri-23-+00).
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = pw[0]; // P
+                types[1] = (int) TOUCHEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = pw[1]; // Q
+              } else {  // s4 < 0
+                // [P, Q] contains [A, l] (tritri-23-+0-).
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              }
+            }
+          } else { // s3 < 0
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [P, Q] in [A, l] (tritri-23-+-+).
+                types[0] = (int) TOUCHFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = pw[0]; // P
+                types[1] = (int) TOUCHFACE;
+                pos[2] = 3;     // [A, B, C]
+                pos[3] = pw[1]; // Q
+              } else {
+                if (s4 == 0) {
+                  // Q = l, [P, Q] in [A, l] (tritri-23-+-0).
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) TOUCHEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = pw[1]; // Q
+                } else { // s4 < 0
+                  // [P, Q] overlaps [A, l] (tritri-23-+--).
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSEDGE;
+                  pos[2] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+                  pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+                }
+              }
+            } else { // s2 == 0
+              // P = l in [B, C] (tritri-23#0##).
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = (iu == 0 ? pu[1] : mi1mo3[pu[1]]); // [B, C]
+              pos[1] = pw[0]; // P
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else {
+        // Q = A (tritri-230###).
+        types[0] = (int) SHAREVERT;
+        pos[0] = pu[0]; // A
+        pos[1] = pw[1]; // Q
+        types[1] = (int) DISJOINT;
+      }
+    }
+
+    return 1;
+  } // if (z1 == 2)
+
+  if (z1 == 3) {
+
+    if (z2 == 0) {  // (30)
+      if (s1 < 0) {
+        if (s3 > 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // [i, j] overlaps [A, B] (tritri-30-+++).
+            types[0] = (int) ACROSSVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = 3;     // [P, Q, R]
+            types[1] = (int) ACROSSEDGE;
+            pos[2] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+            pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+          } else {
+            if (s4 == 0) {
+              // j = B, [i, j] contains [A, B] (tritri-30-++0).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else { // s4 < 0
+              // [i, j] contains [A, B] (tritri-30-++-).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = 3;     // [P, Q, R]
+            }
+          }
+        } else {
+          if (s3 == 0) {
+            assert(s2 > 0); // SELF_CHECK
+            if (s4 > 0) {
+              // i = A, [i, j] in [A, B] (tritri-30-+0+).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else {
+              if (s4 == 0) {
+                // [i, j] = [A, B] (tritri-30-+00).
+                types[0] = (int) ACROSSVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else { // s4 < 0
+                // i = A, [i, j] contains [A, B] (tritri-30-+0-).
+                types[0] = (int) ACROSSVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = 3;     // [P, Q, R]
+              }
+            }
+          } else { // s3 < 0
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [i, j] in [A, B] (tritri-30-+-+).
+                types[0] = (int) ACROSSEDGE;
+                pos[0] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else {
+                if (s4 == 0) {
+                  // j = B, [i, j] in [A, B] (tritri-30-+-0).
+                  types[0] = (int) ACROSSEDGE;
+                  pos[0] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                  pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                  types[1] = (int) ACROSSVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+                } else { // s4 < 0
+                  // [i, j] overlaps [A, B] (tritri-30-+--).
+                  types[0] = (int) ACROSSEDGE;
+                  pos[0] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                  pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                  types[1] = (int) ACROSSVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = 3;     // [P, Q, R]
+                }
+              }
+            } else { // s2 == 0
+              // i = B in [P, R] (tritri-30#0##).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[1]; // B
+              pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else {
+        // j = A in [Q, R] (tritri-300###).
+        types[0] = (int) ACROSSVERT;
+        pos[0] = pu[0]; // A
+        pos[1] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+        types[1] = (int) DISJOINT;
+      }
+    } else if (z2 == 2) {  // (32)
+      if (s1 < 0) {
+        if (s3 > 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // [P, j] overlaps [A, B] (tritri-32-+++).
+            types[0] = (int) ACROSSVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = 3;     // [P, Q, R]
+            types[1] = (int) ACROSSEDGE;
+            pos[2] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+            pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+          } else {
+            if (s4 == 0) {
+              // j = B, [P, j] contains [A, B] (tritri-32-++0).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else { // s4 < 0
+              // [P, j] contains [A, B] (tritri-32-++-).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = 3;     // [P, Q, R]
+            }
+          }
+        } else {
+          if (s3 == 0) {
+            assert(s2 > 0); // SELF_CHECK
+            if (s4 > 0) {
+              // P = A, [P, j] in [A, B] (tritri-32-+0+).
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = pw[0]; // P
+              types[1] = (int) ACROSSEDGE;
+              pos[2] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else {
+              if (s4 == 0) {
+                // [P, j] = [A, B] (tritri-32-+00).
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else { // s4 < 0
+                // P = A, [P, j] contains [A, B] (tritri-32-+0-).
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = 3;     // [P, Q, R]
+              }
+            }
+          } else { // s3 < 0
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [P, j] in [A, B] (tritri-32-+-+).
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSEDGE;
+                pos[2] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else {
+                if (s4 == 0) {
+                  // j = B, [P, j] in [A, B] (tritri-32-+-0).
+                  types[0] = (int) TOUCHEDGE;
+                  pos[0] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+                } else { // s4 < 0
+                  // [P, j] overlaps [A, B] (tritri-32-+--).
+                  types[0] = (int) TOUCHEDGE;
+                  pos[0] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = 3;     // [P, Q, R]
+                }
+              }
+            } else { // s2 == 0
+              // P = B (tritri-32#0##).
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[1]; // B
+              pos[1] = pw[0]; // P
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else {
+        // j = A in [Q, R] (tritri-320###).
+        types[0] = (int) ACROSSVERT;
+        pos[0] = pu[0]; // A
+        pos[1] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+        types[1] = (int) DISJOINT;
+      }
+    } else if (z2 == 3) {  // (33)
+      if (s1 < 0) {
+        if (s3 > 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // [P, Q] overlaps [A, B] (tritri-33-+++).
+            types[0] = (int) ACROSSVERT;
+            pos[0] = pu[0]; // A
+            pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+            types[1] = (int) TOUCHEDGE;
+            pos[2] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+            pos[3] = pw[1]; // Q
+          } else {
+            if (s4 == 0) {
+              // Q = B, [P, Q] contains [A, B] (tritri-33-++0).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              types[1] = (int) SHAREVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = pw[1]; // Q
+            } else { // s4 < 0
+              // [P, Q] contains [A, B] (tritri-33-++-).
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              types[1] = (int) ACROSSVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+            }
+          }
+        } else {
+          if (s3 == 0) {
+            assert(s2 > 0); // SELF_CHECK
+            if (s4 > 0) {
+              // P = A, [P, Q] in [A, B] (tritri-33-+0+).
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[0]; // A
+              pos[1] = pw[0]; // P
+              types[1] = (int) TOUCHEDGE;
+              pos[2] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+              pos[3] = pw[1]; // Q
+            } else {
+              if (s4 == 0) {
+                // [P, Q] = [A, B] (tritri-33-+00).
+                types[0] = (int) SHAREEDGE;
+                pos[0] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+                types[1] = DISJOINT;
+              } else { // s4 < 0
+                // P = A, [P, Q] contains [A, B] (tritri-33-+0-).
+                types[0] = (int) SHAREVERT;
+                pos[0] = pu[0]; // A
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSVERT;
+                pos[2] = pu[0]; // A
+                pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              }
+            }
+          } else { // s3 < 0
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [P, Q] in [A, B] (tritri-33-+-+).
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                pos[1] = pw[0]; // P
+                types[1] = (int) TOUCHEDGE;
+                pos[2] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                pos[3] = pw[1]; // Q
+              } else {
+                if (s4 == 0) {
+                  // Q = B, [P, Q] overlaps [A, B] (tritri-33-+-0).
+                  types[0] = (int) TOUCHEDGE;
+                  pos[0] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) SHAREVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = pw[1]; // Q
+                } else { // s4 < 0
+                  // [P, Q] overlaps [A, B] (tritri-33-+--).
+                  types[0] = (int) TOUCHEDGE;
+                  pos[0] = (iu == 0 ? pu[0] : mi1mo3[pu[0]]); // Int([A, B])
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+                }
+              }
+            } else { // s2 == 0
+              // P = B (tritri-33#0##).
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[1]; // B
+              pos[1] = pw[0]; // P
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else {
+        // Q = A (tritri-330###).
+        types[0] = (int) SHAREVERT;
+        pos[0] = pu[0]; // A
+        pos[1] = pw[1]; // Q
+        types[1] = (int) DISJOINT;
+      }
+    }
+
+    return 1;
+  } // if (z1 == 3)
+
+  if (z1 == 4) {
+
+    if (z2 == 0) { // (40)
+      if (s1 < 0) {
+        if (s3 > 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // [i, j] overlaps [k, B] (tritri-40-+++)
+            types[0] = (int) ACROSSEDGE;
+            pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+            pos[1] = 3;     // [P, Q, R]
+            types[1] = (int) ACROSSFACE;
+            pos[2] = 3;     // [A, B, C]
+            pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+          } else {
+            if (s4 == 0) {
+              // j = B, [i, j] overlaps [k, B] (tritri-40-++0)
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else { // s4 < 0
+              // [i, j] contains [k, B] (tritri-40-++-)
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = 3; // [P, Q, R]
+            }
+          }
+        } else {
+          if (s3 == 0) {
+            assert(s2 > 0); // SELF_CHECK
+            if (s4 > 0) {
+              // i = k, [i, j] in [k, B] (tritri-40-+0+)
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+              types[1] = (int) ACROSSFACE;
+              pos[2] = 3;     // [A, B, C]
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else {
+              if (s4 == 0) {
+                // [i, j] = [k, B] (tritri-40-+00)
+                types[0] = (int) ACROSSEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else { // s4 < 0
+                // i = k, [i, j] contains [k, B] (tritri-40-+0-)
+                types[0] = (int) ACROSSEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = 3; // [P, Q, R]
+              }
+            }
+          } else { // s3 < 0
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [i, j] in [k, B] (tritri-40-+-+)
+                types[0] = (int) ACROSSFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                types[1] = (int) ACROSSFACE;
+                pos[2] = 3;     // [A, B, C]
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else {
+                if (s4 == 0) {
+                  // j = B, [i, j] in [k, B] (tritri-40-+-0)
+                  types[0] = (int) ACROSSFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                  types[1] = (int) ACROSSVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+                } else { // s4 < 0
+                  // [i, j] overlaps [k, B] (tritri-40-+--)
+                  types[0] = (int) ACROSSFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+                  types[1] = (int) ACROSSVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = 3;     // [P, Q, R]
+                }
+              }
+            } else { // s2 == 0
+              // assert(s4 < 0); // SELF_CHECK
+              // i = B (tritri-40#0##)
+              types[0] = (int) ACROSSVERT;
+              pos[0] = pu[1]; // B
+              pos[1] = (iv == 0 ? pw[2] : mi1mo3[pw[2]]); // [R, P]
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else { // s1 == 0
+        // j = k (tritri-400###)
+        types[0] = (int) ACROSSEDGE;
+        pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+        pos[1] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+        types[1] = (int) DISJOINT;
+      }
+    } else if (z2 == 2) { // (42)
+      if (s1 < 0) {
+        if (s3 > 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // [P, j] overlaps [k, B] (tritri-42-+++)
+            types[0] = (int) ACROSSEDGE;
+            pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+            pos[1] = 3;     // [P, Q, R]
+            types[1] = (int) ACROSSFACE;
+            pos[2] = 3;     // [A, B, C]
+            pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+          } else {
+            if (s4 == 0) {
+              // j = B, [P, j] contains [k, B] (tritri-42-++0)
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else { // s4 < 0
+              // [P, j] contains [k, B] (tritri-42-++-)
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = 3;     // [P, Q, R]
+              types[1] = (int) ACROSSVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = 3;     // [P, Q, R]
+            }
+          }
+        } else {
+          if (s3 == 0) {
+            assert(s2 > 0); // SELF_CHECK
+            if (s4 > 0) {
+              // P = k, [P, j] in [k, B] (tritri-42-+0+)
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = pw[0]; // P
+              types[1] = (int) ACROSSFACE;
+              pos[2] = 3;     // [A, B, C]
+              pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+            } else {
+              if (s4 == 0) {
+                // [P, j] = [k, B] (tritri-42-+00)
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else { // s4 < 0
+                // P = k, [P, j] in [k, B] (tritri-42-+0-)
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = 3;     // [P, Q, R]
+              }
+            }
+          } else { // s3 < 0
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [P, j] in [k, B] (tritri-42-+-+)
+                types[0] = (int) TOUCHFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSFACE;
+                pos[2] = 3;     // [A, B, C]
+                pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+              } else {
+                if (s4 == 0) {
+                  // j = B, [P, j] in [k, B] (tritri-42-+-0)
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+                } else { // s4 < 0
+                  // [P, j] overlaps [k, B] (tritri-42-+--)
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = 3;     // [P, Q, R]
+                }
+              }
+            } else { // s2 == 0
+              // assert(s4 < 0); // SELF_CHECK
+              // P = B (tritri-42#0##)
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[1]; // B
+              pos[1] = pw[0]; // P
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else { // s1 == 0
+        // j = k (tritri-420###)
+        types[0] = (int) ACROSSEDGE;
+        pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+        pos[1] = (iv == 0 ? pw[1] : mi1mo3[pw[1]]); // [Q, R]
+        types[1] = (int) DISJOINT;
+      }
+    } else if (z2 == 3) { // (43)
+      if (s1 < 0) {
+        if (s3 > 0) {
+          assert(s2 > 0); // SELF_CHECK
+          if (s4 > 0) {
+            // [P, Q] overlaps [k, B] (tritri-43-+++)
+            types[0] = (int) ACROSSEDGE;
+            pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+            pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+            types[1] = (int) TOUCHFACE;
+            pos[2] = 3;     // [A, B, C]
+            pos[3] = pw[1]; // Q
+          } else {
+            if (s4 == 0) {
+              // Q = B, [P, Q] contains [k, B] (tritri-43-++0)
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              types[1] = (int) SHAREVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = pw[1]; // Q
+            } else { // s4 < 0
+              // [P, Q] contains [k, B] (tritri-43-++-)
+              types[0] = (int) ACROSSEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              types[1] = (int) ACROSSVERT;
+              pos[2] = pu[1]; // B
+              pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+            }
+          }
+        } else {
+          if (s3 == 0) {
+            assert(s2 > 0); // SELF_CHECK
+            if (s4 > 0) {
+              // P = k, [P, Q] in [k, B] (tritri-43-+0+)
+              types[0] = (int) TOUCHEDGE;
+              pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+              pos[1] = pw[0]; // P
+              types[1] = (int) TOUCHFACE;
+              pos[2] = 3;     // [A, B, C]
+              pos[3] = pw[1]; // Q
+            } else {
+              if (s4 == 0) {
+                // [P, Q] = [k, B] (tritri-43-+00)
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = pw[0]; // P
+                types[1] = (int) SHAREVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = pw[1]; // Q
+              } else { // s4 < 0
+                // P = k, [P, Q] contains [k, B] (tritri-43-+0-)
+                types[0] = (int) TOUCHEDGE;
+                pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+                pos[1] = pw[0]; // P
+                types[1] = (int) ACROSSVERT;
+                pos[2] = pu[1]; // B
+                pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+              }
+            }
+          } else { // s3 < 0
+            if (s2 > 0) {
+              if (s4 > 0) {
+                // [P, Q] in [k, B] (tritri-43-+-+)
+                types[0] = (int) TOUCHFACE;
+                pos[0] = 3;     // [A, B, C]
+                pos[1] = pw[0]; // P
+                types[1] = (int) TOUCHFACE;
+                pos[2] = 3;     // [A, B, C]
+                pos[3] = pw[1]; // Q
+              } else {
+                if (s4 == 0) {
+                  // Q = B, [P, Q] in [k, B] (tritri-43-+-0)
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) SHAREVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = pw[1]; // Q
+                } else { // s4 < 0
+                  // [P, Q] overlaps [k, B] (tritri-43-+--)
+                  types[0] = (int) TOUCHFACE;
+                  pos[0] = 3;     // [A, B, C]
+                  pos[1] = pw[0]; // P
+                  types[1] = (int) ACROSSVERT;
+                  pos[2] = pu[1]; // B
+                  pos[3] = (iv == 0 ? pw[0] : mi1mo3[pw[0]]); // Int([P, Q])
+                }
+              }
+            } else { // s2 == 0
+              // assert(s4 < 0); // SELF_CHECK
+              // P = B (tritri-43#0##)
+              types[0] = (int) SHAREVERT;
+              pos[0] = pu[1]; // B
+              pos[1] = pw[0]; // P
+              types[1] = (int) DISJOINT;
+            }
+          }
+        }
+      } else { // s1 == 0
+        // Q = k (tritri-430###)
+        types[0] = (int) TOUCHEDGE;
+        pos[0] = (iu == 0 ? pu[2] : mi1mo3[pu[2]]); // [C, A]
+        pos[1] = pw[1]; // Q
+        types[1] = (int) DISJOINT;
+      }
+    }
+
+    return 1;
+  } // if (z1 == 4)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// insphere_sos()    Insphere test with symbolic perturbation.               //
+//                                                                           //
+// Given four points pa, pb, pc, and pd, test if the point pe lies inside or //
+// outside the circumscirbed sphere of the four points.  Here we assume that //
+// the orientation of the sequence {pa, pb, pc, pd} is negative (NOT zero),  //
+// i.e., pd lies at the negative side of the plane defined by pa, pb, and pc.//
+//                                                                           //
+// Return a positive value (> 0) if pe lies outside, a negative value (< 0)  //
+// if pe lies inside the sphere, the returned value will not be zero.        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+REAL tetgenmesh::insphere_sos(point pa, point pb, point pc, point pd, point pe)
+{
+  REAL sign;
+
+  inspherecount++;
+
+  sign = insphere(pa, pb, pc, pd, pe);
+  if (sign != 0.0) {
+    return sign;
+  }
+
+  insphere_sos_count++;
+
+  // Symbolic perturbation.
+  point pt[5], swappt;
+  REAL oriA, oriB;
+  int swaps, count;
+  int n, i;
+
+  pt[0] = pa;
+  pt[1] = pb;
+  pt[2] = pc;
+  pt[3] = pd;
+  pt[4] = pe;
+  
+  // Sort the five points such that their indices are in the increasing
+  //   order. An optimized bubble sort algorithm is used, i.e., it has
+  //   the worst case O(n^2) runtime, but it is usually much faster.
+  swaps = 0; // Record the total number of swaps.
+  n = 5;
+  do {
+    count = 0;
+    n = n - 1;
+    for (i = 0; i < n; i++) {
+      if (pointmark(pt[i]) > pointmark(pt[i+1])) {
+        swappt = pt[i]; pt[i] = pt[i+1]; pt[i+1] = swappt;
+        count++;
+      }
+    }
+    swaps += count;
+  } while (count > 0); // Continue if some points are swapped.
+
+  oriA = orient3d(pt[1], pt[2], pt[3], pt[4]);
+  if (oriA != 0.0) {
+    // Flip the sign if there are odd number of swaps.
+    if ((swaps % 2) != 0) oriA = -oriA;
+    return oriA;
+  }
+  
+  oriB = -orient3d(pt[0], pt[2], pt[3], pt[4]);
+  assert(oriB != 0.0); // SELF_CHECK
+  // Flip the sign if there are odd number of swaps.
+  if ((swaps % 2) != 0) oriB = -oriB;
+  return oriB;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// isincircle()    Test if d lies inside the circumcircle of abc.            //
+//                                                                           //
+// Return a positive value (> 0) if pd lies outside, a negative value (< 0)  //
+// if pd lies inside the circle, a zero if pd lies on the circle.            //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+/*  This version (which uses insphere test) is not save. It may give 
+  undesired result when four points are nearly coplanar.
+  An example is in fig/dump-incircle3d-case1.*/
+
+/*REAL tetgenmesh::incircle3d(point pa, point pb, point pc, point pd)
+{
+  REAL area2[2], n1[3], n2[3], pe[3];
+  REAL sign, L, len;
+
+  // Calculate the areas of the two triangles [a, b, c] and [b, a, d].
+  facenormal(pa, pb, pc, n1, 1);
+  area2[0] = DOT(n1, n1);
+  facenormal(pb, pa, pd, n2, 1);
+  area2[1] = DOT(n2, n2);
+  L = DIST(pa, pb);
+
+  if (area2[0] > area2[1]) {
+    // Choose [a, b, c] as the base triangle.
+    len = sqrt(area2[0]);
+    n1[0] /= len;
+    n1[1] /= len;
+    n1[2] /= len;
+    L += DIST(pb, pc);
+    L += DIST(pc, pa);
+    L /= 3.0;
+    pe[0] = pa[0] + L * n1[0];
+    pe[1] = pa[1] + L * n1[1];
+    pe[2] = pa[2] + L * n1[2];
+    sign = insphere(pa, pb, pc, pe, pd);
+  } else {
+    // Choose [b, a, d] as the base triangle.
+    len = sqrt(area2[1]);
+    n2[0] /= len;
+    n2[1] /= len;
+    n2[2] /= len;
+    L += DIST(pa, pd);
+    L += DIST(pd, pb);
+    L /= 3.0;
+    pe[0] = pa[0] + L * n2[0];
+    pe[1] = pa[1] + L * n2[1];
+    pe[2] = pa[2] + L * n2[2];
+    sign = insphere(pb, pa, pd, pe, pc);
+  }
+
+  return sign;
+}*/
+
+/* This code had problem with file2.poly*/
+REAL tetgenmesh::incircle3d(point pa, point pb, point pc, point pd)
+{
+  REAL area2[2], n1[3], n2[3], c[3];
+  REAL sign, r, d;
+
+  // Calculate the areas of the two triangles [a, b, c] and [b, a, d].
+  facenormal(pa, pb, pc, n1, 1);
+  area2[0] = DOT(n1, n1);
+  facenormal(pb, pa, pd, n2, 1);
+  area2[1] = DOT(n2, n2);
+
+  if (area2[0] > area2[1]) {
+    // Choose [a, b, c] as the base triangle.
+    assert(area2[0] > 0); // SELF_CHECK
+    circumsphere(pa, pb, pc, NULL, c, &r);
+    d = DIST(c, pd);
+  } else {
+    // Choose [b, a, d] as the base triangle.
+    assert(area2[1] > 0); // SELF_CHECK
+    circumsphere(pb, pa, pd, NULL, c, &r);
+    d = DIST(c, pc);
+  }
+
+  sign = d - r;
+  if (fabs(sign) / r < b->epsilon) {
+    sign = 0;
+  }
+
+  return sign;
+}
+
+/*
+REAL tetgenmesh::incircle3d(point pa, point pb, point pc, point pd)
+{
+  point pk, pl, pm, pn;
+  REAL area2[4], n[3], c[3];
+  REAL amax, sign, r, l, q;
+  int imax;
+
+  // Calculate the areas of the four triangles in a, b, c, and d.
+  //   Get the base triangle which has the largest area.
+  facenormal(pa, pb, pc, n, 1);
+  area2[0] = DOT(n, n); 
+  facenormal(pb, pa, pd, n, 1);
+  area2[1] = DOT(n, n);
+  if (area2[0] < area2[1]) {
+    amax = area2[1]; imax = 1;
+  } else {
+    amax = area2[0]; imax = 0;
+  }
+  facenormal(pc, pd, pb, n, 1);
+  area2[2] = DOT(n, n);
+  if (amax < area2[2]) {
+    amax = area2[2]; imax = 2;
+  }
+  facenormal(pd, pc, pa, n, 1);
+  area2[3] = DOT(n, n);
+  if (amax < area2[3]) {
+    amax = area2[3]; imax = 3;
+  }
+
+  // Permute the vertices s. t. the base triangle is (pk, pl, pm).
+  if (imax == 0) {
+    pk = pa; pl = pb; pm = pc; pn = pd; sign = 1.0;
+  } else if (imax == 1) {
+    pk = pb; pl = pa; pm = pd; pn = pc; sign = 1.0;
+  } else if (imax == 2) {
+    pk = pc; pl = pd; pm = pb; pn = pa; sign = -1.0;
+  } else {
+    pk = pd; pl = pc; pm = pa; pn = pb; sign = -1.0;
+  }
+
+  // Make sure that the base triangle is not degenerate.
+  l = DIST(pk, pl);
+  l += DIST(pl, pm);
+  l += DIST(pm, pk);
+  l /= 3.0;
+
+  if (sqrt(amax) > (l * l * b->epsilon)) {
+    // Calculate the circumcenter and radius.
+    circumsphere(pk, pl, pm, NULL, c, &r);
+    l = DIST(c, pn);
+    q = fabs((l - r) / r);
+  } else {
+    // A (nearly) degenerate base triangle.
+    assert(0);  // Not handle yet.
+    q = 0;
+  }
+
+  if (q > b->epsilon) {
+    return (l - r) * sign;  // Adjust the sign.
+  } else {
+    return 0;  // Round to zero.
+  }
+}*/
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// iscoplanar()    Check if four points are approximately coplanar.          //
+//                                                                           //
+// 'tol' is the relative error tolerance.  The coplanarity is determined by  //
+// the equation q < tol, where q = fabs(6 * vol) / L^3, vol is the volume of //
+// the tet klmn, and L is the average edge length of the tet.                //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenmesh::iscoplanar(point k, point l, point m, point n, REAL ori)
+{
+  REAL L, q;
+
+  L = DIST(k, l);
+  L += DIST(l, m);
+  L += DIST(m, k);
+  L += DIST(k, n);
+  L += DIST(l, n);
+  L += DIST(m, n);
+  assert(L > 0.0);  // SELF_CHECK
+  L /= 6.0;
+
+  q = fabs(ori) / (L * L * L);
+
+  return q <= b->epsilon;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// interiorangle()    Return the interior angle (0 - 2 * PI) between vectors //
+//                    o->p1 and o->p2.                                       //
+//                                                                           //
+// 'n' is the normal of the plane containing face (o, p1, p2).  The interior //
+// angle is the total angle rotating from o->p1 around n to o->p2.  Exchange //
+// the position of p1 and p2 will get the complement angle of the other one. //
+// i.e., interiorangle(o, p1, p2) = 2 * PI - interiorangle(o, p2, p1).  Set  //
+// 'n' be NULL if you only want the interior angle between 0 - PI.           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+REAL tetgenmesh::interiorangle(point o, point p1, point p2, REAL* n)
+{
+  REAL v1[3], v2[3], np[3];
+  REAL theta, costheta, lenlen;
+  REAL ori, len1, len2;
+
+  // Get the interior angle (0 - PI) between o->p1, and o->p2.
+  v1[0] = p1[0] - o[0];
+  v1[1] = p1[1] - o[1];
+  v1[2] = p1[2] - o[2];
+  v2[0] = p2[0] - o[0];
+  v2[1] = p2[1] - o[1];
+  v2[2] = p2[2] - o[2];
+  len1 = sqrt(DOT(v1, v1));
+  len2 = sqrt(DOT(v2, v2));
+  lenlen = len1 * len2;
+  assert(lenlen != 0.0);  // SELF_CHECK
+  costheta = DOT(v1, v2) / lenlen;
+  if (costheta > 1.0) {
+    costheta = 1.0; // Roundoff. 
+  } else if (costheta < -1.0) {
+    costheta = -1.0; // Roundoff. 
+  }
+  theta = acos(costheta);
+  if (n != NULL) {
+    // Get a point above the face (o, p1, p2);
+    np[0] = o[0] + n[0];
+    np[1] = o[1] + n[1];
+    np[2] = o[2] + n[2];
+    // Adjust theta (0 - 2 * PI).
+    ori = orient3d(p1, o, np, p2);
+    if (ori > 0.0) {
+      theta = 2 * PI - theta;
+    }
+  }
+
+  return theta;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// facenormal()    Calculate the normal of the face.                         //
+//                                                                           //
+// The normal of the face abc can be calculated by the cross product of 2 of //
+// its 3 edge vectors.  A better choice of two edge vectors will reduce the  //
+// numerical error during the calculation.  Burdakov proved that the optimal //
+// basis problem is equivalent to the minimum spanning tree problem with the //
+// edge length be the functional, see Burdakov, "A greedy algorithm for the  //
+// optimal basis problem", BIT 37:3 (1997), 591-599. If 'pivot' > 0, the two //
+// short edges in abc are chosen for the calculation.                        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::facenormal(point pa, point pb, point pc, REAL *n, int pivot)
+{
+  REAL v1[3], v2[3], v3[3], *pv1, *pv2;
+  REAL L1, L2, L3;
+
+  v1[0] = pb[0] - pa[0];  // edge vector v1: a->b
+  v1[1] = pb[1] - pa[1];
+  v1[2] = pb[2] - pa[2];
+  v2[0] = pa[0] - pc[0];  // edge vector v2: c->a
+  v2[1] = pa[1] - pc[1];
+  v2[2] = pa[2] - pc[2];
+
+  // Default, normal is calculated by: v1 x (-v2) (see Fig. fnormal).
+  if (pivot > 0) {
+    // Choose edge vectors by Burdakov's algorithm.
+    v3[0] = pc[0] - pb[0];  // edge vector v3: b->c
+    v3[1] = pc[1] - pb[1];
+    v3[2] = pc[2] - pb[2];
+    L1 = DOT(v1, v1);
+    L2 = DOT(v2, v2);
+    L3 = DOT(v3, v3);
+    // Sort the three edge lengths.
+    if (L1 < L2) {
+      if (L2 < L3) {
+        pv1 = v1; pv2 = v2; // n = v1 x (-v2).
+      } else {
+        pv1 = v3; pv2 = v1; // n = v3 x (-v1).
+      }
+    } else {
+      if (L1 < L3) {
+        pv1 = v1; pv2 = v2; // n = v1 x (-v2).
+      } else {
+        pv1 = v2; pv2 = v3; // n = v2 x (-v3).
+      }
+    }
+  } else {
+    pv1 = v1; pv2 = v2; // n = v1 x (-v2).
+  }
+
+  // Calculate the face normal.
+  CROSS(pv1, pv2, n);
+  // Inverse the direction;
+  n[0] = -n[0];
+  n[1] = -n[1];
+  n[2] = -n[2];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// circumsphere()    Calculate the smallest circumsphere (center and radius) //
+//                   of the given three or four points.                      //
+//                                                                           //
+// The circumsphere of four points (a tetrahedron) is unique if they are not //
+// degenerate. If 'pd == NULL', the smallest circumsphere of three points is //
+// the diametral sphere of the triangle (pa, pb, pc).                        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::circumsphere(point pa, point pb, point pc, point pd,
+  REAL* cent, REAL* radius)
+{
+  REAL A[4][4], rhs[4], D;
+  int indx[4];
+
+  // Compute the coefficient matrix A (3x3).
+  A[0][0] = pb[0] - pa[0];
+  A[0][1] = pb[1] - pa[1];
+  A[0][2] = pb[2] - pa[2];
+  A[1][0] = pc[0] - pa[0];
+  A[1][1] = pc[1] - pa[1];
+  A[1][2] = pc[2] - pa[2];
+  if (pd != NULL) {
+    A[2][0] = pd[0] - pa[0];
+    A[2][1] = pd[1] - pa[1]; 
+    A[2][2] = pd[2] - pa[2];
+  } else {
+    CROSS(A[0], A[1], A[2]);
+  }
+
+  // Compute the right hand side vector b (3x1).
+  rhs[0] = 0.5 * DOT(A[0], A[0]);
+  rhs[1] = 0.5 * DOT(A[1], A[1]);
+  if (pd != NULL) {
+    rhs[2] = 0.5 * DOT(A[2], A[2]);
+  } else {
+    rhs[2] = 0.0;
+  }
+
+  // Solve the 3 by 3 equations use LU decomposition with partial pivoting
+  //   and backward and forward substitute..
+  if (!lu_decmp(A, 3, indx, &D, 0)) {
+    assert(0);  // No solution.
+  }
+  lu_solve(A, 3, indx, rhs, 0);
+  if (cent != (REAL *) NULL) {
+    cent[0] = pa[0] + rhs[0];
+    cent[1] = pa[1] + rhs[1];
+    cent[2] = pa[2] + rhs[2];
+  }
+  if (radius != (REAL *) NULL) {
+    *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// lu_decmp()    Compute the LU decomposition of a matrix.                   //
+//                                                                           //
+// Compute the LU decomposition of a (non-singular) square matrix A using    //
+// partial pivoting and implicit row exchanges.  The result is:              //
+//     A = P * L * U,                                                        //
+// where P is a permutation matrix, L is unit lower triangular, and U is     //
+// upper triangular.  The factored form of A is used in combination with     //
+// 'lu_solve()' to solve linear equations: Ax = b, or invert a matrix.       //
+//                                                                           //
+// The inputs are a square matrix 'lu[N..n+N-1][N..n+N-1]', it's size is 'n'.//
+// On output, 'lu' is replaced by the LU decomposition of a rowwise permuta- //
+// tion of itself, 'ps[N..n+N-1]' is an output vector that records the row   //
+// permutation effected by the partial pivoting, effectively,  'ps' array    //
+// tells the user what the permutation matrix P is; 'd' is output as +1/-1   //
+// depending on whether the number of row interchanges was even or odd,      //
+// respectively.                                                             //
+//                                                                           //
+// Return true if the LU decomposition is successfully computed, otherwise,  //
+// return false in case that A is a singular matrix.                         //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenmesh::lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N)
+{
+  REAL scales[4];
+  REAL pivot, biggest, mult, tempf;
+  int pivotindex = 0;
+  int i, j, k;
+
+  *d = 1.0;                                      // No row interchanges yet.
+
+  for (i = N; i < n + N; i++) {                             // For each row.
+    // Find the largest element in each row for row equilibration
+    biggest = 0.0;
+    for (j = N; j < n + N; j++)
+      if (biggest < (tempf = fabs(lu[i][j])))
+        biggest  = tempf;
+    if (biggest != 0.0)
+      scales[i] = 1.0 / biggest;
+    else {
+      scales[i] = 0.0;
+      return false;                            // Zero row: singular matrix.
+    }
+    ps[i] = i;                                 // Initialize pivot sequence.
+  }
+
+  for (k = N; k < n + N - 1; k++) {                      // For each column.
+    // Find the largest element in each column to pivot around.
+    biggest = 0.0;
+    for (i = k; i < n + N; i++) {
+      if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
+        biggest = tempf;
+        pivotindex = i;
+      }
+    }
+    if (biggest == 0.0) {
+      return false;                         // Zero column: singular matrix.
+    }
+    if (pivotindex != k) {                         // Update pivot sequence.
+      j = ps[k];
+      ps[k] = ps[pivotindex];
+      ps[pivotindex] = j;
+      *d = -(*d);                          // ...and change the parity of d.
+    }
+
+    // Pivot, eliminating an extra variable  each time
+    pivot = lu[ps[k]][k];
+    for (i = k + 1; i < n + N; i++) {
+      lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
+      if (mult != 0.0) {
+        for (j = k + 1; j < n + N; j++)
+          lu[ps[i]][j] -= mult * lu[ps[k]][j];
+      }
+    }
+  }
+
+  // (lu[ps[n + N - 1]][n + N - 1] == 0.0) ==> A is singular.
+  return lu[ps[n + N - 1]][n + N - 1] != 0.0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// lu_solve()    Solves the linear equation:  Ax = b,  after the matrix A    //
+//               has been decomposed into the lower and upper triangular     //
+//               matrices L and U, where A = LU.                             //
+//                                                                           //
+// 'lu[N..n+N-1][N..n+N-1]' is input, not as the matrix 'A' but rather as    //
+// its LU decomposition, computed by the routine 'lu_decmp'; 'ps[N..n+N-1]'  //
+// is input as the permutation vector returned by 'lu_decmp';  'b[N..n+N-1]' //
+// is input as the right-hand side vector, and returns with the solution     //
+// vector. 'lu', 'n', and 'ps' are not modified by this routine and can be   //
+// left in place for successive calls with different right-hand sides 'b'.   //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N)
+{
+  int i, j;
+  REAL X[4], dot;
+
+  for (i = N; i < n + N; i++) X[i] = 0.0;
+
+  // Vector reduction using U triangular matrix.
+  for (i = N; i < n + N; i++) {
+    dot = 0.0;
+    for (j = N; j < i + N; j++)
+      dot += lu[ps[i]][j] * X[j];
+    X[i] = b[ps[i]] - dot;
+  }
+
+  // Back substitution, in L triangular matrix.
+  for (i = n + N - 1; i >= N; i--) {
+    dot = 0.0;
+    for (j = i + 1; j < n + N; j++)
+      dot += lu[ps[i]][j] * X[j];
+    X[i] = (X[i] - dot) / lu[ps[i]][i];
+  }
+
+  for (i = N; i < n + N; i++) b[i] = X[i];
+}
+
+#endif // #ifndef geomCXX
\ No newline at end of file
diff --git a/contrib/Tetgen/io.cxx b/contrib/Tetgen/io.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9cf198a6bdab98aa0ac1fa9232c57f605473c3a6
--- /dev/null
+++ b/contrib/Tetgen/io.cxx
@@ -0,0 +1,3148 @@
+#ifndef tetgenioCXX
+#define tetgenioCXX
+
+#include "tetgen.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// initialize()    Initialize all variables of 'tetgenio'.                   //
+//                                                                           //
+// It is called by the only class constructor 'tetgenio()' implicitly. Thus, //
+// all variables are guaranteed to be initialized. Each array is initialized //
+// to be a 'NULL' pointer, and its length is equal zero. Some variables have //
+// their default value, 'firstnumber' equals zero, 'mesh_dim' equals 3,  and //
+// 'numberofcorners' equals 4.  Another possible use of this routine is to   //
+// call it before to re-use an object.                                       //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenio::initialize()
+{
+  firstnumber = 0;              // Default item index is numbered from Zero.
+  mesh_dim = 3;                              // Default mesh dimension is 3.
+  useindex = true;
+
+  pointlist = (REAL *) NULL;
+  pointattributelist = (REAL *) NULL;
+  pointmtrlist = (REAL *) NULL;
+  pointmarkerlist = (int *) NULL;
+  numberofpoints = 0;
+  numberofpointattributes = 0;
+  numberofpointmtrs = 0;
+
+  tetrahedronlist = (int *) NULL;
+  tetrahedronattributelist = (REAL *) NULL;
+  tetrahedronvolumelist = (REAL *) NULL;
+  neighborlist = (int *) NULL;
+  numberoftetrahedra = 0;
+  numberofcorners = 4;                   // Default is 4 nodes per element.
+  numberoftetrahedronattributes = 0;
+
+  trifacelist = (int *) NULL;
+  adjtetlist = (int *) NULL;
+  trifacemarkerlist = (int *) NULL;
+  numberoftrifaces = 0; 
+
+  facetlist = (facet *) NULL;
+  facetmarkerlist = (int *) NULL;
+  numberoffacets = 0; 
+
+  edgelist = (int *) NULL;
+  edgemarkerlist = (int *) NULL;
+  numberofedges = 0;
+
+  holelist = (REAL *) NULL;
+  numberofholes = 0;
+
+  regionlist = (REAL *) NULL;
+  numberofregions = 0;
+
+  facetconstraintlist = (REAL *) NULL;
+  numberoffacetconstraints = 0;
+  segmentconstraintlist = (REAL *) NULL;
+  numberofsegmentconstraints = 0;
+
+  pbcgrouplist = (pbcgroup *) NULL;
+  numberofpbcgroups = 0;
+
+  vpointlist = (REAL *) NULL;
+  vedgelist = (voroedge *) NULL;
+  vfacetlist = (vorofacet *) NULL; 
+  vcelllist = (int **) NULL; 
+  numberofvpoints = 0;
+  numberofvedges = 0;
+  numberofvfacets = 0;
+  numberofvcells = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// deinitialize()    Free the memory allocated in 'tetgenio'.                //
+//                                                                           //
+// It is called by the class destructor '~tetgenio()' implicitly. Hence, the //
+// occupied memory by arrays of an object will be automatically released on  //
+// the deletion of the object. However, this routine assumes that the memory //
+// is allocated by C++ memory allocation operator 'new', thus it is freed by //
+// the C++ array deletor 'delete []'. If one uses the C/C++ library function //
+// 'malloc()' to allocate memory for arrays, one has to free them with the   //
+// 'free()' function, and call routine 'initialize()' once to disable this   //
+// routine on deletion of the object.                                        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenio::deinitialize()
+{
+  facet *f;
+  polygon *p;
+  pbcgroup *pg;
+  int i, j;
+
+  if (pointlist != (REAL *) NULL) {
+    delete [] pointlist;
+  }
+  if (pointattributelist != (REAL *) NULL) {
+    delete [] pointattributelist;
+  }
+  if (pointmtrlist != (REAL *) NULL) {
+    delete [] pointmtrlist;
+  }
+  if (pointmarkerlist != (int *) NULL) {
+    delete [] pointmarkerlist;
+  }
+
+  if (tetrahedronlist != (int *) NULL) {
+    delete [] tetrahedronlist;
+  }
+  if (tetrahedronattributelist != (REAL *) NULL) {
+    delete [] tetrahedronattributelist;
+  }
+  if (tetrahedronvolumelist != (REAL *) NULL) {
+    delete [] tetrahedronvolumelist;
+  }
+  if (neighborlist != (int *) NULL) {
+    delete [] neighborlist;
+  }
+
+  if (trifacelist != (int *) NULL) {
+    delete [] trifacelist;
+  }
+  if (adjtetlist != (int *) NULL) {
+    delete [] adjtetlist;
+  }
+  if (trifacemarkerlist != (int *) NULL) {
+    delete [] trifacemarkerlist;
+  }
+
+  if (edgelist != (int *) NULL) {
+    delete [] edgelist;
+  }
+  if (edgemarkerlist != (int *) NULL) {
+    delete [] edgemarkerlist;
+  }
+
+  if (facetlist != (facet *) NULL) {
+    for (i = 0; i < numberoffacets; i++) {
+      f = &facetlist[i];
+      for (j = 0; j < f->numberofpolygons; j++) {
+        p = &f->polygonlist[j];
+        delete [] p->vertexlist;
+      }
+      delete [] f->polygonlist;
+      if (f->holelist != (REAL *) NULL) {
+        delete [] f->holelist;
+      }
+    }
+    delete [] facetlist;
+  }
+  if (facetmarkerlist != (int *) NULL) {
+    delete [] facetmarkerlist;
+  }
+
+  if (holelist != (REAL *) NULL) {
+    delete [] holelist;
+  }
+  if (regionlist != (REAL *) NULL) {
+    delete [] regionlist;
+  }
+  if (facetconstraintlist != (REAL *) NULL) {
+    delete [] facetconstraintlist;
+  }
+  if (segmentconstraintlist != (REAL *) NULL) {
+    delete [] segmentconstraintlist;
+  }
+  if (pbcgrouplist != (pbcgroup *) NULL) {
+    for (i = 0; i < numberofpbcgroups; i++) {
+      pg = &(pbcgrouplist[i]);
+      if (pg->pointpairlist != (int *) NULL) {
+        delete [] pg->pointpairlist;
+      }
+    }
+    delete [] pbcgrouplist;
+  }
+  if (vpointlist != (REAL *) NULL) {
+    delete [] vpointlist;
+  }
+  if (vedgelist != (voroedge *) NULL) {
+    delete [] vedgelist;
+  }
+  if (vfacetlist != (vorofacet *) NULL) {
+    for (i = 0; i < numberofvfacets; i++) {
+      delete [] vfacetlist[i].elist;
+    }
+    delete [] vfacetlist;
+  }
+  if (vcelllist != (int **) NULL) {
+    for (i = 0; i < numberofvcells; i++) {
+      delete [] vcelllist[i];
+    }
+    delete [] vcelllist;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_node_call()    Load a list of nodes.                                 //
+//                                                                           //
+// It is a support routine for routines: 'load_nodes()', 'load_poly()', and  //
+// 'load_tetmesh()'.  'infile' is the file handle contains the node list. It //
+// may point to a .node, or .poly or .smesh file.  'markers' indicates each  //
+// node contains an additional marker (integer) or not. 'infilename' is the  //
+// name of the file being read,  it is only appeared in error message.       //
+//                                                                           //
+// The 'firstnumber' (0 or 1) is automatically determined by the number of   //
+// the first index of the first point.                                       //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_node_call(FILE* infile,int markers,const char* infilename)
+{
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+  REAL x, y, z, attrib;
+  int firstnode, currentmarker;
+  int index, attribindex;
+  int i, j;
+
+  // Initialize 'pointlist', 'pointattributelist', and 'pointmarkerlist'.
+  pointlist = new REAL[numberofpoints * 3];
+  if (pointlist == (REAL *) NULL) {
+    printf("Error:  Out of memory.\n");
+    terminatetetgen(1);
+  }
+  if (numberofpointattributes > 0) {
+    pointattributelist = new REAL[numberofpoints * numberofpointattributes];
+    if (pointattributelist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      terminatetetgen(1);
+    }
+  }
+  if (markers) {
+    pointmarkerlist = new int[numberofpoints];
+    if (pointmarkerlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      terminatetetgen(1);
+    }
+  }
+
+  // Read the point section.
+  index = 0;
+  attribindex = 0;
+  for (i = 0; i < numberofpoints; i++) {
+    stringptr = readnumberline(inputline, infile, infilename);
+    if (useindex) {
+      if (i == 0) {
+        firstnode = (int) strtol (stringptr, &stringptr, 0);
+        if ((firstnode == 0) || (firstnode == 1)) {
+          firstnumber = firstnode;
+        }
+      }
+      stringptr = findnextnumber(stringptr);
+    } // if (useindex)
+    if (*stringptr == '\0') {
+      printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
+      break;
+    }
+    x = (REAL) strtod(stringptr, &stringptr);
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr == '\0') {
+      printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
+      break;
+    }
+    y = (REAL) strtod(stringptr, &stringptr);
+    if (mesh_dim == 3) {
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
+        break;
+      }
+      z = (REAL) strtod(stringptr, &stringptr);
+    } else {
+      z = 0.0; // mesh_dim == 2;
+    }
+    pointlist[index++] = x;
+    pointlist[index++] = y;
+    pointlist[index++] = z;
+    // Read the point attributes.
+    for (j = 0; j < numberofpointattributes; j++) {
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        attrib = 0.0;
+      } else {
+        attrib = (REAL) strtod(stringptr, &stringptr);
+      }
+      pointattributelist[attribindex++] = attrib;
+    }
+    if (markers) {
+      // Read a point marker.
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        currentmarker = 0;
+      } else {
+        currentmarker = (int) strtol (stringptr, &stringptr, 0);
+      }
+      pointmarkerlist[i] = currentmarker;
+    }
+  }
+  if (i < numberofpoints) {
+    // Failed to read points due to some error.
+    delete [] pointlist;
+    pointlist = (REAL *) NULL;
+    if (markers) {
+      delete [] pointmarkerlist;
+      pointmarkerlist = (int *) NULL;
+    }
+    if (numberofpointattributes > 0) {
+      delete [] pointattributelist;
+      pointattributelist = (REAL *) NULL;
+    }
+    numberofpoints = 0;
+    return false;
+  }
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_node()    Load a list of nodes from a .node file.                    //
+//                                                                           //
+// 'filename' is the inputfile without suffix. The node list is in 'filename.//
+// node'. On completion, the node list is returned in 'pointlist'.           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_node(const char* filename)
+{
+  FILE *infile;
+  char innodefilename[FILENAMESIZE];
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+  int markers;
+
+  // Assembling the actual file names we want to open.
+  strcpy(innodefilename, filename);
+  strcat(innodefilename, ".node");
+
+  // Try to open a .node file.
+  infile = fopen(innodefilename, "r");
+  if (infile == (FILE *) NULL) {
+    printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
+    return false;
+  }
+  printf("Opening %s.\n", innodefilename);  
+  // Read the first line of the file.
+  stringptr = readnumberline(inputline, infile, innodefilename);
+  // Is this list of points generated from rbox?
+  stringptr = strstr(inputline, "rbox");
+  if (stringptr == NULL) {
+    // Read number of points, number of dimensions, number of point
+    //   attributes, and number of boundary markers. 
+    stringptr = inputline;
+    numberofpoints = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr == '\0') {
+      mesh_dim = 3;
+    } else {
+      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr == '\0') {
+      numberofpointattributes = 0;
+    } else {
+      numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr == '\0') {
+      markers = 0;
+    } else {
+      markers = (int) strtol (stringptr, &stringptr, 0);
+    }
+  } else {
+    // It is a rbox (qhull) input file.
+    stringptr = inputline;
+    // Get the dimension.
+    mesh_dim = (int) strtol (stringptr, &stringptr, 0);
+    // Get the number of points.
+    stringptr = readnumberline(inputline, infile, innodefilename);
+    numberofpoints = (int) strtol (stringptr, &stringptr, 0);
+    // There is no index column.
+    useindex = 0;
+  }
+
+  if (numberofpoints < (mesh_dim + 1)) {
+    printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
+    fclose(infile);
+    return false;
+  }
+
+  // Load the list of nodes.
+  if (!load_node_call(infile, markers, innodefilename)) {
+    fclose(infile);
+    return false;
+  }
+  fclose(infile);
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_pbc()    Load a list of pbc groups into 'pbcgrouplist'.              //
+//                                                                           //
+// 'filename' is the filename of the original inputfile without suffix. The  //
+// pbc groups are found in file 'filename.pbc'.                              //
+//                                                                           //
+// This routine will be called both in load_poly() and load_tetmesh().       //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_pbc(const char* filename)
+{
+  FILE *infile;
+  char pbcfilename[FILENAMESIZE];
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+  pbcgroup *pg;
+  int index, p1, p2;
+  int i, j, k;
+
+  // Pbc groups are saved in file "filename.pbc".
+  strcpy(pbcfilename, filename);
+  strcat(pbcfilename, ".pbc");
+  infile = fopen(pbcfilename, "r");
+  if (infile != (FILE *) NULL) {
+    printf("Opening %s.\n", pbcfilename);
+  } else {
+    // No such file. Return.
+    return false;
+  }
+
+  // Read the number of pbc groups.
+  stringptr = readnumberline(inputline, infile, pbcfilename);
+  numberofpbcgroups = (int) strtol (stringptr, &stringptr, 0);
+  if (numberofpbcgroups == 0) {
+    // It looks this file contains no point.
+    fclose(infile);
+    return false; 
+  }
+  // Initialize 'pbcgrouplist';
+  pbcgrouplist = new pbcgroup[numberofpbcgroups];
+
+  // Read the list of pbc groups.
+  for (i = 0; i < numberofpbcgroups; i++) {
+    pg = &(pbcgrouplist[i]);
+    // Initialize pbcgroup i;
+    pg->numberofpointpairs = 0;
+    pg->pointpairlist = (int *) NULL;
+    // Read 'fmark1', 'fmark2'.
+    stringptr = readnumberline(inputline, infile, pbcfilename);
+    if (*stringptr == '\0') break;
+    pg->fmark1 = (int) strtol(stringptr, &stringptr, 0);
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr == '\0') break;
+    pg->fmark2 = (int) strtol(stringptr, &stringptr, 0);
+    // Read 'transmat'.
+    do {
+      stringptr = readline(inputline, infile, NULL);
+    } while ((*stringptr != '[') && (*stringptr != '\0'));
+    if (*stringptr == '\0') break;
+    for (j = 0; j < 4; j++) {
+      for (k = 0; k < 4; k++) {
+        // Read the entry of [j, k].
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          // Try to read another line.
+          stringptr = readnumberline(inputline, infile, pbcfilename);
+          if (*stringptr == '\0') break;
+        }
+        pg->transmat[j][k] = (REAL) strtod(stringptr, &stringptr);
+      }
+      if (k < 4) break; // Not complete!
+    }
+    if (j < 4) break; // Not complete!
+    // Read 'numberofpointpairs'.
+    stringptr = readnumberline(inputline, infile, pbcfilename);
+    if (*stringptr == '\0') break;
+    pg->numberofpointpairs = (int) strtol(stringptr, &stringptr, 0);
+    if (pg->numberofpointpairs > 0) {
+      pg->pointpairlist = new int[pg->numberofpointpairs * 2];
+      // Read the point pairs.
+      index = 0;
+      for (j = 0; j < pg->numberofpointpairs; j++) {
+        stringptr = readnumberline(inputline, infile, pbcfilename);
+        p1 = (int) strtol(stringptr, &stringptr, 0);
+        stringptr = findnextnumber(stringptr);
+        p2 = (int) strtol(stringptr, &stringptr, 0);
+        pg->pointpairlist[index++] = p1;
+        pg->pointpairlist[index++] = p2;
+      }
+    }
+  }
+  fclose(infile);
+
+  if (i < numberofpbcgroups) {
+    // Failed to read to additional points due to some error.
+    delete [] pbcgrouplist;
+    pbcgrouplist = (pbcgroup *) NULL;
+    numberofpbcgroups = 0;
+    return false;
+  }
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_var()    Load variant constraints applied on facets, segments, nodes.//
+//                                                                           //
+// 'filename' is the filename of the original inputfile without suffix. The  //
+// constraints are found in file 'filename.var'.                             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_var(const char* filename)
+{
+  FILE *infile;
+  char varfilename[FILENAMESIZE];
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+  int index;
+  int i;
+
+  // Variant constraints are saved in file "filename.var".
+  strcpy(varfilename, filename);
+  strcat(varfilename, ".var");
+  infile = fopen(varfilename, "r");
+  if (infile != (FILE *) NULL) {
+    printf("Opening %s.\n", varfilename);
+  } else {
+    // No such file. Return.
+    return false;
+  }
+
+  // Read the facet constraint section.
+  stringptr = readnumberline(inputline, infile, varfilename);
+  if (*stringptr != '\0') {
+    numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0);
+  } else {
+    numberoffacetconstraints = 0;
+  }
+  if (numberoffacetconstraints > 0) {
+    // Initialize 'facetconstraintlist'.
+    facetconstraintlist = new REAL[numberoffacetconstraints * 2];
+    index = 0;
+    for (i = 0; i < numberoffacetconstraints; i++) {
+      stringptr = readnumberline(inputline, infile, varfilename);
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  facet constraint %d has no facet marker.\n",
+               firstnumber + i);
+        break;
+      } else {
+        facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
+      }
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  facet constraint %d has no maximum area bound.\n",
+               firstnumber + i);
+        break;
+      } else {
+        facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
+      }
+    }
+    if (i < numberoffacetconstraints) {
+      // This must be caused by an error.
+      fclose(infile);
+      return false;
+    }
+  }
+
+  // Read the segment constraint section.
+  stringptr = readnumberline(inputline, infile, varfilename);
+  if (*stringptr != '\0') {
+    numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0);
+  } else {
+    numberofsegmentconstraints = 0;
+  }
+  if (numberofsegmentconstraints > 0) {
+    // Initialize 'segmentconstraintlist'.
+    segmentconstraintlist = new REAL[numberofsegmentconstraints * 3];
+    index = 0;
+    for (i = 0; i < numberofsegmentconstraints; i++) {
+      stringptr = readnumberline(inputline, infile, varfilename);
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  segment constraint %d has no frist endpoint.\n",
+               firstnumber + i);
+        break;
+      } else {
+        segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
+      }
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  segment constraint %d has no second endpoint.\n",
+               firstnumber + i);
+        break;
+      } else {
+        segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
+      }
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  segment constraint %d has no maximum length bound.\n",
+               firstnumber + i);
+        break;
+      } else {
+        segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
+      }
+    }
+    if (i < numberofsegmentconstraints) {
+      // This must be caused by an error.
+      fclose(infile);
+      return false;
+    }
+  }
+
+  fclose(infile);
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_mtr()    Load a size specification map from file.                    //
+//                                                                           //
+// 'filename' is the filename of the original inputfile without suffix. The  //
+// size map is found in file 'filename.mtr'.                                 //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_mtr(const char* filename)
+{
+  FILE *infile;
+  char mtrfilename[FILENAMESIZE];
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+  REAL mtr;
+  int mtrindex;
+  int i, j;
+
+  strcpy(mtrfilename, filename);
+  strcat(mtrfilename, ".mtr");
+  infile = fopen(mtrfilename, "r");
+  if (infile != (FILE *) NULL) {
+    printf("Opening %s.\n", mtrfilename);
+  } else {
+    // No such file. Return.
+    return false;
+  }
+
+  // Read number of points, number of columns (1, 3, or 6).
+  stringptr = readnumberline(inputline, infile, mtrfilename);
+  stringptr = findnextnumber(stringptr); // Skip number of points.
+  if (*stringptr != '\0') {
+    numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0);
+  }
+  if (numberofpointmtrs == 0) {
+    // Column number doesn't match. Set a default number (1).
+    numberofpointmtrs = 1;
+  }
+
+  // Allocate space for pointmtrlist.
+  pointmtrlist = new REAL[numberofpoints * numberofpointmtrs];
+  if (pointmtrlist == (REAL *) NULL) {
+    printf("Error:  Out of memory.\n");
+    terminatetetgen(1);
+  }
+  mtrindex = 0;
+  for (i = 0; i < numberofpoints; i++) {
+    // Read metrics.
+    stringptr = readnumberline(inputline, infile, mtrfilename);
+    for (j = 0; j < numberofpointmtrs; j++) {
+      if (*stringptr == '\0') {
+        printf("Error:  Metric %d is missing value #%d in %s.\n",
+               i + firstnumber, j + 1, mtrfilename);
+        terminatetetgen(1);
+      }
+      mtr = (REAL) strtod(stringptr, &stringptr);
+      pointmtrlist[mtrindex++] = mtr;
+      stringptr = findnextnumber(stringptr);
+    }
+  }
+
+  fclose(infile);
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_poly()    Load a piecewise linear complex from a .poly or .smesh.    //
+//                                                                           //
+// 'filename' is the inputfile without suffix. The PLC is in 'filename.poly' //
+// or 'filename.smesh', and possibly plus 'filename.node' (when the first    //
+// line of the file starts with a zero).                                     //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_poly(const char* filename)
+{
+  FILE *infile, *polyfile;
+  char innodefilename[FILENAMESIZE];
+  char inpolyfilename[FILENAMESIZE];
+  char insmeshfilename[FILENAMESIZE];
+  char inputline[INPUTLINESIZE];
+  char *stringptr, *infilename;
+  int smesh, markers, currentmarker;
+  int readnodefile, index;
+  int i, j, k;
+
+  // Assembling the actual file names we want to open.
+  strcpy(innodefilename, filename);
+  strcpy(inpolyfilename, filename);
+  strcpy(insmeshfilename, filename);
+  strcat(innodefilename, ".node");
+  strcat(inpolyfilename, ".poly");
+  strcat(insmeshfilename, ".smesh");
+
+  // First assume it is a .poly file.
+  smesh = 0;
+  // Try to open a .poly file.
+  polyfile = fopen(inpolyfilename, "r");
+  if (polyfile == (FILE *) NULL) {
+    // .poly doesn't exist! Try to open a .smesh file.
+    polyfile = fopen(insmeshfilename, "r");
+    if (polyfile == (FILE *) NULL) {
+      printf("File I/O Error:  Cannot access file %s and %s.\n",
+             inpolyfilename, insmeshfilename);
+      return false;
+    } else {
+      printf("Opening %s.\n", insmeshfilename);
+    }
+    smesh = 1;
+  } else {
+    printf("Opening %s.\n", inpolyfilename);
+  }
+  // Initialize the default values.
+  mesh_dim = 3;  // Three-dimemsional accoordinates.
+  numberofpointattributes = 0;  // no point attribute.
+  markers = 0;  // no boundary marker.
+  // Read number of points, number of dimensions, number of point
+  //   attributes, and number of boundary markers.
+  stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+  numberofpoints = (int) strtol (stringptr, &stringptr, 0);
+  stringptr = findnextnumber(stringptr);
+  if (*stringptr != '\0') {
+    mesh_dim = (int) strtol (stringptr, &stringptr, 0);      
+  }
+  stringptr = findnextnumber(stringptr);
+  if (*stringptr != '\0') {
+    numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
+  }
+  stringptr = findnextnumber(stringptr);
+  if (*stringptr != '\0') {
+    markers = (int) strtol (stringptr, &stringptr, 0);
+  }
+  if (numberofpoints > 0) {
+    readnodefile = 0;
+    if (smesh) {
+      infilename = insmeshfilename;
+    } else {
+      infilename = inpolyfilename;
+    } 
+    infile = polyfile;
+  } else {
+    // If the .poly or .smesh file claims there are zero points, that
+    //   means the points should be read from a separate .node file.
+    readnodefile = 1;
+    infilename = innodefilename;
+  }
+
+  if (readnodefile) {
+    // Read the points from the .node file.
+    printf("Opening %s.\n", innodefilename);
+    infile = fopen(innodefilename, "r");
+    if (infile == (FILE *) NULL) {
+      printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
+      return false;
+    }
+    // Initialize the default values.
+    mesh_dim = 3;  // Three-dimemsional accoordinates.
+    numberofpointattributes = 0;  // no point attribute.
+    markers = 0;  // no boundary marker.
+    // Read number of points, number of dimensions, number of point
+    //   attributes, and number of boundary markers.
+    stringptr = readnumberline(inputline, infile, innodefilename);
+    numberofpoints = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr != '\0') {
+      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr != '\0') {
+      numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr != '\0') {
+      markers = (int) strtol (stringptr, &stringptr, 0);
+    }
+  }
+
+  if ((mesh_dim != 3) && (mesh_dim != 2)) {
+    printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
+    fclose(infile);
+    return false;
+  }
+  if (numberofpoints < (mesh_dim + 1)) {
+    printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
+    fclose(infile);
+    return false;
+  }
+
+  // Load the list of nodes.
+  if (!load_node_call(infile, markers, infilename)) {
+    fclose(infile);
+    return false;
+  }
+
+  if (readnodefile) {
+    fclose(infile);
+  }
+
+  facet *f;
+  polygon *p;
+
+  if (mesh_dim == 3) {
+
+    // Read number of facets and number of boundary markers.
+    stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+    numberoffacets = (int) strtol (stringptr, &stringptr, 0);
+    if (numberoffacets <= 0) {
+      // No facet list, return.
+      fclose(polyfile);
+      return true;
+    }
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr == '\0') {
+      markers = 0;  // no boundary marker.
+    } else {
+      markers = (int) strtol (stringptr, &stringptr, 0);
+    }
+
+    // Initialize the 'facetlist', 'facetmarkerlist'.
+    facetlist = new facet[numberoffacets];
+    if (markers == 1) {
+      facetmarkerlist = new int[numberoffacets];
+    }
+
+    // Read data into 'facetlist', 'facetmarkerlist'.
+    if (smesh == 0) {
+      // Facets are in .poly file format.
+      for (i = 1; i <= numberoffacets; i++) {
+        f = &(facetlist[i - 1]);
+        init(f);
+        f->numberofholes = 0;
+        currentmarker = 0;
+        // Read number of polygons, number of holes, and a boundary marker.
+        stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+        f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr != '\0') {
+          f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
+          if (markers == 1) {
+            stringptr = findnextnumber(stringptr);
+            if (*stringptr != '\0') {
+              currentmarker = (int) strtol(stringptr, &stringptr, 0);
+            }
+          }
+        }
+        // Initialize facetmarker if it needs.
+        if (markers == 1) {
+          facetmarkerlist[i - 1] = currentmarker; 
+        }
+        // Each facet should has at least one polygon.
+        if (f->numberofpolygons <= 0) {
+          printf("Error:  Wrong number of polygon in %d facet.\n", i);
+          break; 
+        }
+        // Initialize the 'f->polygonlist'.
+        f->polygonlist = new polygon[f->numberofpolygons];
+        // Go through all polygons, read in their vertices.
+        for (j = 1; j <= f->numberofpolygons; j++) {
+          p = &(f->polygonlist[j - 1]);
+          init(p);
+          // Read number of vertices of this polygon.
+          stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+          p->numberofvertices = (int) strtol(stringptr, &stringptr, 0);
+          if (p->numberofvertices < 1) {
+            printf("Error:  Wrong polygon %d in facet %d\n", j, i);
+            break;
+          }
+          // Initialize 'p->vertexlist'.
+          p->vertexlist = new int[p->numberofvertices];
+          // Read all vertices of this polygon.
+          for (k = 1; k <= p->numberofvertices; k++) {
+            stringptr = findnextnumber(stringptr);
+            if (*stringptr == '\0') {
+              // Try to load another non-empty line and continue to read the
+              //   rest of vertices.
+              stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+              if (*stringptr == '\0') {
+                printf("Error: Missing %d endpoints of polygon %d in facet %d",
+                       p->numberofvertices - k, j, i);
+                break;
+              }
+            }
+            p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
+          }
+        } 
+        if (j <= f->numberofpolygons) {
+          // This must be caused by an error. However, there're j - 1
+          //   polygons have been read. Reset the 'f->numberofpolygon'.
+          if (j == 1) {
+            // This is the first polygon.
+            delete [] f->polygonlist;
+          }
+          f->numberofpolygons = j - 1;
+          // No hole will be read even it exists.
+          f->numberofholes = 0;
+          break;
+        }
+        // If this facet has hole pints defined, read them.
+        if (f->numberofholes > 0) {
+          // Initialize 'f->holelist'.
+          f->holelist = new REAL[f->numberofholes * 3];
+          // Read the holes' coordinates.
+          index = 0;
+          for (j = 1; j <= f->numberofholes; j++) {
+            stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+            for (k = 1; k <= 3; k++) {
+              stringptr = findnextnumber(stringptr);
+              if (*stringptr == '\0') {
+                printf("Error:  Hole %d in facet %d has no coordinates", j, i);
+                break;
+              }
+              f->holelist[index++] = (REAL) strtod (stringptr, &stringptr);
+            }
+            if (k <= 3) {
+              // This must be caused by an error.
+              break;
+            }
+          }
+          if (j <= f->numberofholes) {
+            // This must be caused by an error.
+            break;
+          }
+        }
+      }
+      if (i <= numberoffacets) {
+        // This must be caused by an error.
+        numberoffacets = i - 1;
+        fclose(polyfile);
+        return false;
+      }
+    } else { // poly == 0
+      // Read the facets from a .smesh file.
+      for (i = 1; i <= numberoffacets; i++) {
+        f = &(facetlist[i - 1]);
+        init(f);
+        // Initialize 'f->facetlist'. In a .smesh file, each facetlist only
+        //   contains exactly one polygon, no hole.
+        f->numberofpolygons = 1;
+        f->polygonlist = new polygon[f->numberofpolygons];
+        p = &(f->polygonlist[0]);
+        init(p);
+        // Read number of vertices of this polygon.
+        stringptr = readnumberline(inputline, polyfile, insmeshfilename);
+        p->numberofvertices = (int) strtol (stringptr, &stringptr, 0);
+        if (p->numberofvertices < 1) {
+          printf("Error:  Wrong number of vertex in facet %d\n", i);
+          break;
+        }
+        // Initialize 'p->vertexlist'.
+        p->vertexlist = new int[p->numberofvertices];
+        for (k = 1; k <= p->numberofvertices; k++) {
+          stringptr = findnextnumber(stringptr);
+          if (*stringptr == '\0') {
+            // Try to load another non-empty line and continue to read the
+            //   rest of vertices.
+            stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+            if (*stringptr == '\0') {
+              printf("Error:  Missing %d endpoints in facet %d",
+                     p->numberofvertices - k, i);
+              break;
+            }
+          }
+          p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
+        }
+        if (k <= p->numberofvertices) {
+          // This must be caused by an error.
+          break;
+        }
+        // Read facet's boundary marker at last.
+        if (markers == 1) {
+          stringptr = findnextnumber(stringptr);
+          if (*stringptr == '\0') {
+            currentmarker = 0;
+          } else {
+            currentmarker = (int) strtol(stringptr, &stringptr, 0);
+          }
+          facetmarkerlist[i - 1] = currentmarker;
+        }
+      }
+      if (i <= numberoffacets) {
+        // This must be caused by an error.
+        numberoffacets = i - 1;
+        fclose(polyfile);
+        return false;
+      }
+    }
+
+    // Read the hole section.
+    stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+    if (*stringptr != '\0') {
+      numberofholes = (int) strtol (stringptr, &stringptr, 0);
+    } else {
+      numberofholes = 0;
+    }
+    if (numberofholes > 0) {
+      // Initialize 'holelist'.
+      holelist = new REAL[numberofholes * 3];
+      for (i = 0; i < 3 * numberofholes; i += 3) {
+        stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Hole %d has no x coord.\n", firstnumber + (i / 3));
+          break;
+        } else {
+          holelist[i] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Hole %d has no y coord.\n", firstnumber + (i / 3));
+          break;
+        } else {
+          holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Hole %d has no z coord.\n", firstnumber + (i / 3));
+          break;
+        } else {
+          holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
+        }
+      }
+      if (i < 3 * numberofholes) {
+        // This must be caused by an error.
+        fclose(polyfile);
+        return false;
+      }
+    }
+
+    // Read the region section.  The 'region' section is optional, if we
+    //   don't reach the end-of-file, try read it in.
+    stringptr = readnumberline(inputline, polyfile, NULL);
+    if (stringptr != (char *) NULL && *stringptr != '\0') {
+      numberofregions = (int) strtol (stringptr, &stringptr, 0);
+    } else {
+      numberofregions = 0;
+    }
+    if (numberofregions > 0) {
+      // Initialize 'regionlist'.
+      regionlist = new REAL[numberofregions * 5];
+      index = 0;
+      for (i = 0; i < numberofregions; i++) {
+        stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Region %d has no x coordinate.\n", firstnumber + i);
+          break;
+        } else {
+          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Region %d has no y coordinate.\n", firstnumber + i);
+          break;
+        } else {
+          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Region %d has no z coordinate.\n", firstnumber + i);
+          break;
+        } else {
+          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Region %d has no region attrib.\n", firstnumber + i);
+          break;
+        } else {
+          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          regionlist[index] = regionlist[index - 1];
+        } else {
+          regionlist[index] = (REAL) strtod(stringptr, &stringptr);
+        }
+        index++;
+      }
+      if (i < numberofregions) {
+        // This must be caused by an error.
+        fclose(polyfile);
+        return false;
+      }
+    }
+
+    /*// Read the edge (segment) section.  This section is optional, if we
+    //   don't reach the end-of-file, try read it in.
+    stringptr = readnumberline(inputline, polyfile, NULL);
+    if (stringptr != (char *) NULL && *stringptr != '\0') {
+      numberofedges = (int) strtol (stringptr, &stringptr, 0);
+    } else {
+      numberofedges = 0;
+    }
+    if (numberofedges > 0) {
+      // Initialize 'edgelist'.
+      edgelist = new int[numberofedges * 2];
+      edgemarkerlist = new int[numberofedges];
+      index = 0;
+      for (i = 0; i < numberofedges; i++) {
+        stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+        for (j = 0; j < 2; j++) {
+          stringptr = findnextnumber(stringptr);
+          if (*stringptr == '\0') {
+            printf("Error:  Segment %d has no endpoint.\n", firstnumber + i);
+            break;
+          } else {
+            edgelist[index++] = (int) strtol(stringptr, &stringptr, 0);
+          }
+        }
+        if (j < 2) break;
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          edgemarkerlist[i] = 0;  // Set a default segment marker.
+        } else {
+          edgemarkerlist[i] = (int) strtol(stringptr, &stringptr, 0);
+        }
+      }
+      if (i < numberofedges) {
+        // This must be caused by an error.
+        fclose(polyfile);
+        return false;
+      }
+    }
+    */
+
+  } else {
+
+    // Read a PSLG from Triangle's poly file.
+    assert(mesh_dim == 2);
+    // A PSLG is a facet of a PLC.
+    numberoffacets = 1;
+    // Initialize the 'facetlist'.
+    facetlist = new facet[numberoffacets];
+    facetmarkerlist = (int *) NULL; // No facet markers.
+    f = &(facetlist[0]);
+    init(f);
+    // Read number of segments.
+    stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+    // Segments are degenerate polygons.
+    f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
+    if (f->numberofpolygons > 0) {
+      f->polygonlist = new polygon[f->numberofpolygons];
+    }
+    // Go through all segments, read in their vertices.
+    for (j = 0; j < f->numberofpolygons; j++) {
+      p = &(f->polygonlist[j]);
+      init(p);
+      // Read in a segment.
+      stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+      stringptr = findnextnumber(stringptr); // Skip its index.
+      p->numberofvertices = 2; // A segment always has two vertices.
+      p->vertexlist = new int[p->numberofvertices];
+      p->vertexlist[0] = (int) strtol (stringptr, &stringptr, 0);
+      stringptr = findnextnumber(stringptr);
+      p->vertexlist[1] = (int) strtol (stringptr, &stringptr, 0);
+    }
+    // Read number of holes.
+    stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+    f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
+    if (f->numberofholes > 0) {
+      // Initialize 'f->holelist'.
+      f->holelist = new REAL[f->numberofholes * 3];
+      // Read the holes' coordinates.
+      for (j = 0; j < f->numberofholes; j++) {
+        // Read a 2D hole point.
+        stringptr = readnumberline(inputline, polyfile, inpolyfilename);
+        stringptr = findnextnumber(stringptr); // Skip its index.
+        f->holelist[j * 3] = (REAL) strtod (stringptr, &stringptr);
+        stringptr = findnextnumber(stringptr);
+        f->holelist[j * 3 + 1] = (REAL) strtod (stringptr, &stringptr);
+        f->holelist[j * 3 + 2] = 0.0; // The z-coord.
+      }
+    }
+    // The regions are skipped.
+
+  }
+
+  // End of reading poly/smesh file.
+  fclose(polyfile);
+
+  // Try to load a .var file if it exists.
+  load_var(filename);
+  // Try to load a .mtr file if it exists.
+  load_mtr(filename);
+  // Try to read a .pbc file if it exists.
+  load_pbc(filename);
+
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_off()    Load a polyhedron described in a .off file.                 //
+//                                                                           //
+// The .off format is one of file formats of the Geomview, an interactive    //
+// program for viewing and manipulating geometric objects.  More information //
+// is available form: http://www.geomview.org.                               //
+//                                                                           //
+// 'filename' is a input filename with extension .off or without extension ( //
+// the .off will be added in this case). On completion, the polyhedron is    //
+// returned in 'pointlist' and 'facetlist'.                                  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_off(const char* filename)
+{
+  FILE *fp;
+  tetgenio::facet *f;
+  tetgenio::polygon *p;
+  char infilename[FILENAMESIZE];
+  char buffer[INPUTLINESIZE];
+  char *bufferp;
+  double *coord;
+  int nverts = 0, iverts = 0;
+  int nfaces = 0, ifaces = 0;
+  int nedges = 0;
+  int line_count = 0, i;
+
+  strncpy(infilename, filename, 1024 - 1);
+  infilename[FILENAMESIZE - 1] = '\0';
+  if (infilename[0] == '\0') {
+    printf("Error:  No filename.\n");
+    return false;
+  }
+  if (strcmp(&infilename[strlen(infilename) - 4], ".off") != 0) {
+    strcat(infilename, ".off");
+  }
+
+  if (!(fp = fopen(infilename, "r"))) {
+    printf("File I/O Error:  Unable to open file %s\n", infilename);
+    return false;
+  }
+  printf("Opening %s.\n", infilename);
+
+  // OFF requires the index starts from '0'.
+  firstnumber = 0;
+
+  while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
+    // Check section
+    if (nverts == 0) {
+      // Read header 
+      bufferp = strstr(bufferp, "OFF");
+      if (bufferp != NULL) {
+        // Read mesh counts
+        bufferp = findnextnumber(bufferp); // Skip field "OFF".
+        if (*bufferp == '\0') {
+          // Read a non-empty line.
+          bufferp = readline(buffer, fp, &line_count);
+        }
+        if ((sscanf(bufferp, "%d%d%d", &nverts, &nfaces, &nedges) != 3) 
+            || (nverts == 0)) {
+          printf("Syntax error reading header on line %d in file %s\n",
+                 line_count, infilename);
+          fclose(fp);
+          return false;
+        }
+        // Allocate memory for 'tetgenio'
+        if (nverts > 0) {
+          numberofpoints = nverts;
+          pointlist = new REAL[nverts * 3];
+        }
+        if (nfaces > 0) {        
+          numberoffacets = nfaces;
+          facetlist = new tetgenio::facet[nfaces];
+        }
+      }
+    } else if (iverts < nverts) {
+      // Read vertex coordinates
+      coord = &pointlist[iverts * 3];
+      for (i = 0; i < 3; i++) {
+        if (*bufferp == '\0') {
+          printf("Syntax error reading vertex coords on line %d in file %s\n",
+                 line_count, infilename);
+          fclose(fp);
+          return false;
+        }
+        coord[i] = (REAL) strtod(bufferp, &bufferp);
+        bufferp = findnextnumber(bufferp);
+      }
+      iverts++;
+    } else if (ifaces < nfaces) {
+      // Get next face
+      f = &facetlist[ifaces];
+      init(f);      
+      // In .off format, each facet has one polygon, no hole.
+      f->numberofpolygons = 1;
+      f->polygonlist = new tetgenio::polygon[1];
+      p = &f->polygonlist[0];
+      init(p);
+      // Read the number of vertices, it should be greater than 0.
+      p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
+      if (p->numberofvertices == 0) {
+        printf("Syntax error reading polygon on line %d in file %s\n",
+               line_count, infilename);
+        fclose(fp);
+        return false;
+      }
+      // Allocate memory for face vertices
+      p->vertexlist = new int[p->numberofvertices];
+      for (i = 0; i < p->numberofvertices; i++) {
+        bufferp = findnextnumber(bufferp);
+        if (*bufferp == '\0') {
+          printf("Syntax error reading polygon on line %d in file %s\n",
+                 line_count, infilename);
+          fclose(fp);
+          return false;
+        }
+        p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
+      }
+      ifaces++;
+    } else {
+      // Should never get here
+      printf("Found extra text starting at line %d in file %s\n", line_count,
+             infilename);
+      break;
+    }
+  }
+
+  // Close file
+  fclose(fp);
+
+  // Check whether read all points
+  if (iverts != nverts) {
+    printf("Expected %d vertices, but read only %d vertices in file %s\n",
+           nverts, iverts, infilename);
+    return false;
+  }
+
+  // Check whether read all faces
+  if (ifaces != nfaces) {
+    printf("Expected %d faces, but read only %d faces in file %s\n",
+           nfaces, ifaces, infilename);
+    return false;
+  }
+
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_ply()    Load a polyhedron described in a .ply file.                 //
+//                                                                           //
+// 'filename' is the file name with extension .ply or without extension (the //
+// .ply will be added in this case).                                         //
+//                                                                           //
+// This is a simplified version of reading .ply files, which only reads the  //
+// set of vertices and the set of faces. Other informations (such as color,  //
+// material, texture, etc) in .ply file are ignored. Complete routines for   //
+// reading and writing ,ply files are available from:                        //
+//       http://www.cc.gatech.edu/projects/large_models/ply.html             //
+// Except the header section,ply file format has exactly the same format for //
+// listing vertices and polygons as off file format.                         //
+//                                                                           //
+// On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_ply(const char* filename)
+{
+  FILE *fp;
+  tetgenio::facet *f;
+  tetgenio::polygon *p;
+  char infilename[FILENAMESIZE];
+  char buffer[INPUTLINESIZE];
+  char *bufferp, *str;
+  double *coord;
+  int endheader = 0, format = 0;
+  int nverts = 0, iverts = 0;
+  int nfaces = 0, ifaces = 0;
+  int line_count = 0, i;
+
+  strncpy(infilename, filename, FILENAMESIZE - 1);
+  infilename[FILENAMESIZE - 1] = '\0';
+  if (infilename[0] == '\0') {
+    printf("Error:  No filename.\n");
+    return false;
+  }
+  if (strcmp(&infilename[strlen(infilename) - 4], ".ply") != 0) {
+    strcat(infilename, ".ply");
+  }
+
+  if (!(fp = fopen(infilename, "r"))) {
+    printf("Error:  Unable to open file %s\n", infilename);
+    return false;
+  }
+  printf("Opening %s.\n", infilename);
+
+  // PLY requires the index starts from '0'.
+  firstnumber = 0;
+
+  while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
+    if (!endheader) {
+      // Find if it is the keyword "end_header".
+      str = strstr(bufferp, "end_header");
+      // strstr() is case sensitive.
+      if (!str) str = strstr(bufferp, "End_header");
+      if (!str) str = strstr(bufferp, "End_Header");
+      if (str) {
+        // This is the end of the header section.
+        endheader = 1; 
+        continue;
+      }
+      // Parse the number of vertices and the number of faces.
+      if (nverts == 0 || nfaces == 0) {
+        // Find if it si the keyword "element".
+        str = strstr(bufferp, "element");
+        if (!str) str = strstr(bufferp, "Element");
+        if (str) {
+          bufferp = findnextfield(str);
+          if (*bufferp == '\0') {
+            printf("Syntax error reading element type on line%d in file %s\n",
+                   line_count, infilename);
+            fclose(fp);
+            return false;
+          }
+          if (nverts == 0) {
+            // Find if it is the keyword "vertex".
+            str = strstr(bufferp, "vertex");
+            if (!str) str = strstr(bufferp, "Vertex");
+            if (str) {
+              bufferp = findnextnumber(str);
+              if (*bufferp == '\0') {
+                printf("Syntax error reading vertex number on line");
+                printf(" %d in file %s\n", line_count, infilename);
+                fclose(fp);
+                return false;
+              }
+              nverts = (int) strtol(bufferp, &bufferp, 0);
+              // Allocate memory for 'tetgenio'
+              if (nverts > 0) {
+                numberofpoints = nverts;
+                pointlist = new REAL[nverts * 3];
+              }
+            }
+          }
+          if (nfaces == 0) {
+            // Find if it is the keyword "face".
+            str = strstr(bufferp, "face");
+            if (!str) str = strstr(bufferp, "Face");
+            if (str) {
+              bufferp = findnextnumber(str);
+              if (*bufferp == '\0') {
+                printf("Syntax error reading face number on line");
+                printf(" %d in file %s\n", line_count, infilename);
+                fclose(fp);
+                return false;
+              }
+              nfaces = (int) strtol(bufferp, &bufferp, 0);
+              // Allocate memory for 'tetgenio'
+              if (nfaces > 0) {        
+                numberoffacets = nfaces;
+                facetlist = new tetgenio::facet[nfaces];
+              }
+            }
+          }
+        } // It is not the string "element". 
+      }
+      if (format == 0) {
+        // Find the keyword "format".
+        str = strstr(bufferp, "format");
+        if (!str) str = strstr(bufferp, "Format");
+        if (str) {
+          format = 1;
+          bufferp = findnextfield(str);
+          // Find if it is the string "ascii".
+          str = strstr(bufferp, "ascii");
+          if (!str) str = strstr(bufferp, "ASCII");
+          if (!str) {
+            printf("This routine only reads ascii format of ply files.\n");
+            printf("Hint: You can convert the binary to ascii format by\n");
+            printf("  using the provided ply tools:\n");
+            printf("  ply2ascii < %s > ascii_%s\n", infilename, infilename);
+            fclose(fp);
+            return false;
+          }
+        }
+      }
+    } else if (iverts < nverts) {
+      // Read vertex coordinates
+      coord = &pointlist[iverts * 3];
+      for (i = 0; i < 3; i++) {
+        if (*bufferp == '\0') {
+          printf("Syntax error reading vertex coords on line %d in file %s\n",
+                 line_count, infilename);
+          fclose(fp);
+          return false;
+        }
+        coord[i] = (REAL) strtod(bufferp, &bufferp);
+        bufferp = findnextnumber(bufferp);
+      }
+      iverts++;
+    } else if (ifaces < nfaces) {
+      // Get next face
+      f = &facetlist[ifaces];
+      init(f);      
+      // In .off format, each facet has one polygon, no hole.
+      f->numberofpolygons = 1;
+      f->polygonlist = new tetgenio::polygon[1];
+      p = &f->polygonlist[0];
+      init(p);
+      // Read the number of vertices, it should be greater than 0.
+      p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
+      if (p->numberofvertices == 0) {
+        printf("Syntax error reading polygon on line %d in file %s\n",
+               line_count, infilename);
+        fclose(fp);
+        return false;
+      }
+      // Allocate memory for face vertices
+      p->vertexlist = new int[p->numberofvertices];
+      for (i = 0; i < p->numberofvertices; i++) {
+        bufferp = findnextnumber(bufferp);
+        if (*bufferp == '\0') {
+          printf("Syntax error reading polygon on line %d in file %s\n",
+                 line_count, infilename);
+          fclose(fp);
+          return false;
+        }
+        p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
+      }
+      ifaces++;
+    } else {
+      // Should never get here
+      printf("Found extra text starting at line %d in file %s\n", line_count,
+             infilename);
+      break;
+    }
+  }
+
+  // Close file
+  fclose(fp);
+
+  // Check whether read all points
+  if (iverts != nverts) {
+    printf("Expected %d vertices, but read only %d vertices in file %s\n",
+           nverts, iverts, infilename);
+    return false;
+  }
+
+  // Check whether read all faces
+  if (ifaces != nfaces) {
+    printf("Expected %d faces, but read only %d faces in file %s\n",
+           nfaces, ifaces, infilename);
+    return false;
+  }
+
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_stl()    Load a surface mesh described in a .stl file.               //
+//                                                                           //
+// 'filename' is the file name with extension .stl or without extension (the //
+// .stl will be added in this case).                                         //
+//                                                                           //
+// The .stl or stereolithography format is an ASCII or binary file used in   //
+// manufacturing.  It is a list of the triangular surfaces that describe a   //
+// computer generated solid model. This is the standard input for most rapid //
+// prototyping machines.                                                     //
+//                                                                           //
+// On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
+// Note: After load_stl(), there exist many duplicated points in 'pointlist'.//
+// They will be unified during the Delaunay tetrahedralization process.      //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_stl(const char* filename)
+{
+  FILE *fp;
+  facet *f;
+  polygon *p;
+  char infilename[FILENAMESIZE];
+  char buffer[INPUTLINESIZE];
+  char *bufferp, *str;
+  double *tmplist, *coord;
+  int solid = 0;
+  int maxverts = 1024, nverts = 0, iverts = 0;
+  int nfaces = 0;
+  int line_count = 0, i;
+
+  strncpy(infilename, filename, FILENAMESIZE - 1);
+  infilename[FILENAMESIZE - 1] = '\0';
+  if (infilename[0] == '\0') {
+    printf("Error:  No filename.\n");
+    return false;
+  }
+  if (strcmp(&infilename[strlen(infilename) - 4], ".stl") != 0) {
+    strcat(infilename, ".stl");
+  }
+
+  if (!(fp = fopen(infilename, "r"))) {
+    printf("Error:  Unable to open file %s\n", infilename);
+    return false;
+  }
+  printf("Opening %s.\n", infilename);
+
+  // STL file has no number of points available. Use a list to read points.
+  tmplist = (double *) malloc(sizeof(double) * 3 * maxverts); 
+
+  while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
+    // The ASCII .stl file must start with the lower case keyword solid and
+    //   end with endsolid.
+    if (solid == 0) {
+      // Read header 
+      bufferp = strstr(bufferp, "solid");
+      if (bufferp != NULL) {
+        solid = 1;
+      }
+    } else {
+      // We're inside the block of the solid.
+      str = bufferp;
+      // Is this the end of the solid.
+      bufferp = strstr(bufferp, "endsolid");
+      if (bufferp != NULL) {
+        solid = 0;
+      } else {
+        // Read the XYZ coordinates if it is a vertex.
+        bufferp = str;
+        bufferp = strstr(bufferp, "vertex");
+        if (bufferp != NULL) {
+	  // Check if we have enough memory.
+	  if (nverts == maxverts) {
+	    maxverts += 1024;
+	    tmplist = (double *) realloc(tmplist, sizeof(double)*3*maxverts);
+	  }
+          coord = &(tmplist[nverts * 3]);
+          for (i = 0; i < 3; i++) {
+            bufferp = findnextnumber(bufferp);
+            if (*bufferp == '\0') {
+              printf("Syntax error reading vertex coords on line %d\n",
+                     line_count);
+              free(tmplist);
+              fclose(fp);
+              return false;
+            }
+            coord[i] = (REAL) strtod(bufferp, &bufferp);
+          }
+	  nverts++;
+        }
+      }
+    }
+  }
+  fclose(fp);
+
+  // nverts should be an integer times 3 (every 3 vertices denote a face).
+  if (nverts == 0 || (nverts % 3 != 0)) {
+    printf("Error:  Wrong number of vertices in file %s.\n", infilename);
+    free(tmplist);
+    return false;
+  }
+  numberofpoints = nverts;
+  pointlist = new REAL[nverts * 3];
+  for (i = 0; i < nverts; i++) {
+    coord = &(tmplist[i * 3]);
+    iverts = i * 3;
+    pointlist[iverts] = (REAL) coord[0];
+    pointlist[iverts + 1] = (REAL) coord[1];
+    pointlist[iverts + 2] = (REAL) coord[2];
+  }
+
+  nfaces = (int) (nverts / 3);
+  numberoffacets = nfaces;
+  facetlist = new facet[nfaces];
+
+  // Default use '1' as the array starting index.
+  firstnumber = 1;
+  iverts = firstnumber;
+  for (i = 0; i < nfaces; i++) {
+    f = &facetlist[i];
+    init(f);      
+    // In .stl format, each facet has one polygon, no hole.
+    f->numberofpolygons = 1;
+    f->polygonlist = new polygon[1];
+    p = &f->polygonlist[0];
+    init(p);
+    // Each polygon has three vertices.
+    p->numberofvertices = 3;
+    p->vertexlist = new int[p->numberofvertices];
+    p->vertexlist[0] = iverts;
+    p->vertexlist[1] = iverts + 1;
+    p->vertexlist[2] = iverts + 2;
+    iverts += 3;
+  }
+
+  free(tmplist);
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_medit()    Load a surface mesh described in .mesh file.              //
+//                                                                           //
+// 'filename' is the file name with extension .mesh or without entension (   //
+// the .mesh will be added in this case). .mesh is the file format of Medit, //
+// a user-friendly interactive mesh viewing program.                         //
+//                                                                           //
+// This routine ONLY reads the sections containing vertices, triangles, and  //
+// quadrilaters. Other sections (such as tetrahedra, edges, ...) are ignored.//
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_medit(const char* filename)
+{
+  FILE *fp;
+  tetgenio::facet *tmpflist, *f;
+  tetgenio::polygon *p;
+  char infilename[FILENAMESIZE];
+  char buffer[INPUTLINESIZE];
+  char *bufferp, *str;
+  double *coord;
+  int *tmpfmlist;
+  int dimension = 0;
+  int nverts = 0;
+  int nfaces = 0;
+  int line_count = 0;
+  int corners = 0; // 3 (triangle) or 4 (quad).
+  int i, j;
+
+  strncpy(infilename, filename, FILENAMESIZE - 1);
+  infilename[FILENAMESIZE - 1] = '\0';
+  if (infilename[0] == '\0') {
+    printf("Error:  No filename.\n");
+    return false;
+  }
+  if (strcmp(&infilename[strlen(infilename) - 5], ".mesh") != 0) {
+    strcat(infilename, ".mesh");
+  }
+  
+  if (!(fp = fopen(infilename, "r"))) {
+    printf("Error:  Unable to open file %s\n", infilename);
+    return false;
+  }
+  printf("Opening %s.\n", infilename);
+
+  // Default uses the index starts from '1'.
+  firstnumber = 1;
+
+  while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
+    if (*bufferp == '#') continue;  // A comment line is skipped.
+    if (dimension == 0) {
+      // Find if it is the keyword "Dimension".
+      str = strstr(bufferp, "Dimension");
+      if (!str) str = strstr(bufferp, "dimension");
+      if (!str) str = strstr(bufferp, "DIMENSION");
+      if (str) {
+        // Read the dimensions
+        bufferp = findnextnumber(str); // Skip field "Dimension".
+        if (*bufferp == '\0') {
+          // Read a non-empty line.
+          bufferp = readline(buffer, fp, &line_count);
+        }
+        dimension = (int) strtol(bufferp, &bufferp, 0);
+        if (dimension != 2 && dimension != 3) {
+          printf("Unknown dimension in file on line %d in file %s\n",
+                 line_count, infilename);
+          fclose(fp);
+          return false;
+        }
+        mesh_dim = dimension;
+      }
+    }
+    if (nverts == 0) {
+      // Find if it is the keyword "Vertices".
+      str = strstr(bufferp, "Vertices");
+      if (!str) str = strstr(bufferp, "vertices");
+      if (!str) str = strstr(bufferp, "VERTICES");
+      if (str) {
+        // Read the number of vertices.
+        bufferp = findnextnumber(str); // Skip field "Vertices".
+        if (*bufferp == '\0') {
+          // Read a non-empty line.
+          bufferp = readline(buffer, fp, &line_count);
+        }
+        nverts = (int) strtol(bufferp, &bufferp, 0);
+        // Allocate memory for 'tetgenio'
+        if (nverts > 0) {
+          numberofpoints = nverts;
+          pointlist = new REAL[nverts * 3];
+        }
+        // Read the follwoing node list.
+        for (i = 0; i < nverts; i++) {
+          bufferp = readline(buffer, fp, &line_count);
+          if (bufferp == NULL) {
+            printf("Unexpected end of file on line %d in file %s\n",
+                   line_count, infilename);
+            fclose(fp);
+            return false;
+          }
+          // Read vertex coordinates
+          coord = &pointlist[i * 3];
+          for (j = 0; j < 3; j++) {
+            if (*bufferp == '\0') {
+              printf("Syntax error reading vertex coords on line");
+              printf(" %d in file %s\n", line_count, infilename);
+              fclose(fp);
+              return false;
+            }
+            if ((j < 2) || (dimension == 3)) {
+              coord[j] = (REAL) strtod(bufferp, &bufferp);
+            } else {
+              assert((j == 2) && (dimension == 2));
+              coord[j] = 0.0;
+            }
+            bufferp = findnextnumber(bufferp);
+          }
+        }
+        continue;
+      }
+    } 
+    if (nfaces == 0) {
+      // Find if it is the keyword "Triangles" or "Quadrilaterals".
+      corners = 0;
+      str = strstr(bufferp, "Triangles");
+      if (!str) str = strstr(bufferp, "triangles");
+      if (!str) str = strstr(bufferp, "TRIANGLES");
+      if (str) {
+        corners = 3;
+      } else {
+        str = strstr(bufferp, "Quadrilaterals");
+        if (!str) str = strstr(bufferp, "quadrilaterals");
+        if (!str) str = strstr(bufferp, "QUADRILATERALS");
+        if (str) {
+          corners = 4;
+        }
+      }
+      if (corners == 3 || corners == 4) {
+        // Read the number of triangles (or quadrilaterals).
+        bufferp = findnextnumber(str); // Skip field "Triangles".
+        if (*bufferp == '\0') {
+          // Read a non-empty line.
+          bufferp = readline(buffer, fp, &line_count);
+        }
+        nfaces = strtol(bufferp, &bufferp, 0);
+        // Allocate memory for 'tetgenio'
+        if (nfaces > 0) {
+          if (numberoffacets > 0) {
+            // facetlist has already been allocated. Enlarge arrays.
+            tmpflist = new tetgenio::facet[numberoffacets + nfaces];
+            tmpfmlist = new int[numberoffacets + nfaces];
+            // Copy the data of old arrays into new arrays.
+            for (i = 0; i < numberoffacets; i++) {
+              f = &(tmpflist[i]);
+              tetgenio::init(f);
+              *f = facetlist[i];
+              tmpfmlist[i] = facetmarkerlist[i];
+            }
+            // Release old arrays.
+            delete [] facetlist;
+            delete [] facetmarkerlist;
+            // Remember the new arrays.
+            facetlist = tmpflist;
+            facetmarkerlist = tmpfmlist;
+          } else {
+            // This is the first time to allocate facetlist.
+            facetlist = new tetgenio::facet[nfaces];
+            facetmarkerlist = new int[nfaces];
+          }
+        }
+        // Read the following list of faces.
+        for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
+          bufferp = readline(buffer, fp, &line_count);
+          if (bufferp == NULL) {
+            printf("Unexpected end of file on line %d in file %s\n",
+                   line_count, infilename);
+            fclose(fp);
+            return false;
+          }
+          f = &facetlist[i];
+          tetgenio::init(f);
+          // In .mesh format, each facet has one polygon, no hole.
+          f->numberofpolygons = 1;
+          f->polygonlist = new tetgenio::polygon[1];
+          p = &f->polygonlist[0];
+          tetgenio::init(p);
+          p->numberofvertices = corners;
+          // Allocate memory for face vertices
+          p->vertexlist = new int[p->numberofvertices];
+          // Read the vertices of the face.
+          for (j = 0; j < corners; j++) {
+            if (*bufferp == '\0') {
+              printf("Syntax error reading face on line %d in file %s\n",
+                     line_count, infilename);
+              fclose(fp);
+              return false;
+            }
+            p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0);
+            if (firstnumber == 1) {
+              // Check if a '0' index appears.
+              if (p->vertexlist[j] == 0) {
+                // The first index is set to be 0.
+                firstnumber = 0;
+              }
+            }
+            bufferp = findnextnumber(bufferp);
+          }
+          // Read the marker of the face if it exists.
+          facetmarkerlist[i] = 0;
+          if (*bufferp != '\0') {
+            facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
+          }
+        }
+        // Have read in a list of triangles/quads.
+        numberoffacets += nfaces;
+        nfaces = 0;
+      }
+    }
+    // if (nverts > 0 && nfaces > 0) break; // Ignore other data.
+  }
+
+  // Close file
+  fclose(fp);
+
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_vtk()    Load VTK surface mesh from file (.vtk ascii or binary).     //
+//                                                                           //
+// 'filename' is a string containing the file name with or without suffix.   //
+//                                                                           //
+// This function is contributed by user: Bryn Lloyd (May 7, 2007).           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void swapBytes(unsigned char* var, int size)
+{
+  int i = 0;
+  int j = size - 1;
+  char c;
+
+  while (i < j) {
+    c = var[i]; var[i] = var[j]; var[j] = c;
+    i++, j--;
+  }
+}
+
+bool testIsBigEndian()
+{
+  short word = 0x4321;
+  if((*(char *)& word) != 0x21)
+    return true;
+  else 
+    return false;
+}
+
+bool tetgenio::load_vtk(const char* filename)
+{
+  FILE *fp;
+  tetgenio::facet *f;
+  tetgenio::polygon *p;
+  char infilename[FILENAMESIZE];
+  char line[INPUTLINESIZE];
+  char mode[128], id[256], fmt[64];
+  char *bufferp;
+  double *coord;
+  float _x, _y, _z;
+  int nverts = 0;
+  int nfaces = 0;
+  int line_count = 0;
+  int dummy;
+  int id1, id2, id3;
+  int nn = -1;
+  int nn_old = -1;
+  int i, j;
+  bool ImALittleEndian = !testIsBigEndian();
+
+  strncpy(infilename, filename, FILENAMESIZE - 1);
+  infilename[FILENAMESIZE - 1] = '\0';
+  if (infilename[0] == '\0') {
+    printf("Error:  No filename.\n");
+    return false;
+  }
+  if (strcmp(&infilename[strlen(infilename) - 4], ".vtk") != 0) {
+    strcat(infilename, ".vtk");
+  }
+  if (!(fp = fopen(infilename, "r"))) {
+    printf("Error:  Unable to open file %s\n", infilename);
+    return false;
+  }
+  printf("Opening %s.\n", infilename);
+
+  // Default uses the index starts from '0'.
+  firstnumber = 0;
+  strcpy(mode, "BINARY");
+
+  while((bufferp = readline(line, fp, &line_count)) != NULL) {
+    if(strlen(line) == 0) continue;
+    //swallow lines beginning with a comment sign or white space
+    if(line[0] == '#' || line[0]=='\n' || line[0] == 10 || line[0] == 13 || 
+       line[0] == 32) continue;
+
+    sscanf(line, "%s", id);
+    if(!strcmp(id, "ASCII")) {
+      strcpy(mode, "ASCII");
+    }
+
+    if(!strcmp(id, "POINTS")) {
+      sscanf(line, "%s %d %s", id, &nverts, fmt);
+      if (nverts > 0) {
+        numberofpoints = nverts;
+        pointlist = new REAL[nverts * 3];
+      }
+
+      if(!strcmp(mode, "BINARY")) {
+        for(i = 0; i < nverts; i++) {
+          coord = &pointlist[i * 3];
+          if(!strcmp(fmt, "double")) {
+            fread((char*)(&(coord[0])), sizeof(double), 1, fp);
+            fread((char*)(&(coord[1])), sizeof(double), 1, fp);
+            fread((char*)(&(coord[2])), sizeof(double), 1, fp);
+            if(ImALittleEndian){
+              swapBytes((unsigned char *) &(coord[0]), sizeof(coord[0]));
+              swapBytes((unsigned char *) &(coord[1]), sizeof(coord[1]));
+              swapBytes((unsigned char *) &(coord[2]), sizeof(coord[2]));
+            }
+          } else if(!strcmp(fmt, "float")) {
+            fread((char*)(&_x), sizeof(float), 1, fp);
+            fread((char*)(&_y), sizeof(float), 1, fp);
+            fread((char*)(&_z), sizeof(float), 1, fp);
+            if(ImALittleEndian){
+              swapBytes((unsigned char *) &_x, sizeof(_x));
+              swapBytes((unsigned char *) &_y, sizeof(_y));
+              swapBytes((unsigned char *) &_z, sizeof(_z));
+            }
+            coord[0] = double(_x);
+            coord[1] = double(_y);
+            coord[2] = double(_z);
+          } else {
+            printf("Error: Only float or double formats are supported!\n");
+            return false;
+          }
+        }
+      } else if(!strcmp(mode, "ASCII")) {
+        for(i = 0; i < nverts; i++){
+          bufferp = readline(line, fp, &line_count);
+          if (bufferp == NULL) {
+            printf("Unexpected end of file on line %d in file %s\n",
+                   line_count, infilename);
+            fclose(fp);
+            return false;
+          }
+          // Read vertex coordinates
+          coord = &pointlist[i * 3];
+          for (j = 0; j < 3; j++) {
+            if (*bufferp == '\0') {
+              printf("Syntax error reading vertex coords on line");
+              printf(" %d in file %s\n", line_count, infilename);
+              fclose(fp);
+              return false;
+            }
+            coord[j] = (REAL) strtod(bufferp, &bufferp);
+            bufferp = findnextnumber(bufferp);
+          }
+        }
+      }
+      continue;
+    }
+
+    if(!strcmp(id, "POLYGONS")) {
+      sscanf(line, "%s %d  %d", id, &nfaces, &dummy);
+      if (nfaces > 0) {
+        numberoffacets = nfaces;
+        facetlist = new tetgenio::facet[nfaces];
+      }
+
+      if(!strcmp(mode, "BINARY")) {
+        for(i = 0; i < nfaces; i++){
+          fread((char*)(&nn), sizeof(int), 1, fp);
+          if(ImALittleEndian){
+            swapBytes((unsigned char *) &nn, sizeof(nn));
+          }
+          if (i == 0)
+            nn_old = nn;
+          if (nn != nn_old) {
+            printf("Error:  No mixed cells are allowed.\n");
+            return false;
+          }
+
+          if(nn == 3){
+            fread((char*)(&id1), sizeof(int), 1, fp);
+            fread((char*)(&id2), sizeof(int), 1, fp);
+            fread((char*)(&id3), sizeof(int), 1, fp);
+            if(ImALittleEndian){
+              swapBytes((unsigned char *) &id1, sizeof(id1));
+              swapBytes((unsigned char *) &id2, sizeof(id2));
+              swapBytes((unsigned char *) &id3, sizeof(id3));
+            }
+            f = &facetlist[i];
+            init(f);
+            // In .off format, each facet has one polygon, no hole.
+            f->numberofpolygons = 1;
+            f->polygonlist = new tetgenio::polygon[1];
+            p = &f->polygonlist[0];
+            init(p);
+            // Set number of vertices
+            p->numberofvertices = 3;
+            // Allocate memory for face vertices
+            p->vertexlist = new int[p->numberofvertices];
+            p->vertexlist[0] = id1;
+            p->vertexlist[1] = id2;
+            p->vertexlist[2] = id3;
+          } else {
+            printf("Error: Only triangles are supported\n");
+            return false;
+          }
+        }
+      } else if(!strcmp(mode, "ASCII")) {
+        for(i = 0; i < nfaces; i++) {
+          bufferp = readline(line, fp, &line_count);
+          nn = (int) strtol(bufferp, &bufferp, 0);
+          if (i == 0)
+            nn_old = nn;
+          if (nn != nn_old) {
+            printf("Error:  No mixed cells are allowed.\n");
+            return false;
+          }
+
+          if (nn == 3) {
+            bufferp = findnextnumber(bufferp); // Skip the first field.
+            id1 = (int) strtol(bufferp, &bufferp, 0);
+            bufferp = findnextnumber(bufferp);
+            id2 = (int) strtol(bufferp, &bufferp, 0);
+            bufferp = findnextnumber(bufferp);
+            id3 = (int) strtol(bufferp, &bufferp, 0);
+            f = &facetlist[i];
+            init(f);
+            // In .off format, each facet has one polygon, no hole.
+            f->numberofpolygons = 1;
+            f->polygonlist = new tetgenio::polygon[1];
+            p = &f->polygonlist[0];
+            init(p);
+            // Set number of vertices
+            p->numberofvertices = 3;
+            // Allocate memory for face vertices
+            p->vertexlist = new int[p->numberofvertices];
+            p->vertexlist[0] = id1;
+            p->vertexlist[1] = id2;
+            p->vertexlist[2] = id3;
+          } else {
+            printf("Error:  Only triangles are supported.\n");
+            return false;
+          }
+        }
+      }
+
+      fclose(fp);
+      return true;
+    }
+
+    if(!strcmp(id,"LINES") || !strcmp(id,"CELLS")){
+      printf("Warning:  load_vtk(): cannot read formats LINES, CELLS.\n");
+    }
+  } // while ()
+
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_plc()    Load a piecewise linear complex from file.                  //
+//                                                                           //
+// This is main entrance for loading plcs from different file formats into   //
+// tetgenio.  'filename' is the input file name without extention. 'object'  //
+// indicates which file format is used to describ the plc.                   //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_plc(const char* filename, int object)
+{
+  enum tetgenbehavior::objecttype type;
+
+  type = (enum tetgenbehavior::objecttype) object;
+  switch (type) {
+  case tetgenbehavior::NODES:
+    return load_node(filename);
+  case tetgenbehavior::POLY:
+    return load_poly(filename);
+  case tetgenbehavior::OFF:
+    return load_off(filename);
+  case tetgenbehavior::PLY:
+    return load_ply(filename);
+  case tetgenbehavior::STL:
+    return load_stl(filename);
+  case tetgenbehavior::MEDIT:
+    return load_medit(filename);
+  case tetgenbehavior::VTK:
+    return load_vtk(filename);
+  default:
+    return load_poly(filename);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_tetmesh()    Load a tetrahedral mesh from files.                     //
+//                                                                           //
+// 'filename' is the inputfile without suffix.  The nodes of the tetrahedral //
+// mesh is in "filename.node",  the elements is in "filename.ele", if the    //
+// "filename.face" and "filename.vol" exists, they will also be read.        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_tetmesh(const char* filename)
+{
+  FILE *infile;
+  char innodefilename[FILENAMESIZE];
+  char inelefilename[FILENAMESIZE];
+  char infacefilename[FILENAMESIZE];
+  char inedgefilename[FILENAMESIZE];
+  char involfilename[FILENAMESIZE];
+  char inputline[INPUTLINESIZE];
+  char *stringptr, *infilename;
+  REAL attrib, volume;
+  int volelements;
+  int markers, corner;
+  int index, attribindex;
+  int i, j;
+
+  // Assembling the actual file names we want to open.
+  strcpy(innodefilename, filename);
+  strcpy(inelefilename, filename);
+  strcpy(infacefilename, filename);
+  strcpy(inedgefilename, filename);
+  strcpy(involfilename, filename);
+  strcat(innodefilename, ".node");
+  strcat(inelefilename, ".ele");
+  strcat(infacefilename, ".face");
+  strcat(inedgefilename, ".edge");
+  strcat(involfilename, ".vol");
+
+  // Read the points from a .node file.
+  infilename = innodefilename;
+  printf("Opening %s.\n", infilename);
+  infile = fopen(infilename, "r");
+  if (infile == (FILE *) NULL) {
+    printf("File I/O Error:  Cannot access file %s.\n", infilename);
+    return false;
+  }
+  // Read the first line of the file.
+  stringptr = readnumberline(inputline, infile, infilename); 
+  // Is this list of points generated from rbox?
+  stringptr = strstr(inputline, "rbox");
+  if (stringptr == NULL) {
+    // Read number of points, number of dimensions, number of point
+    //   attributes, and number of boundary markers.
+    stringptr = inputline;
+    numberofpoints = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr == '\0') {
+      mesh_dim = 3;
+    } else {
+      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr == '\0') {
+      numberofpointattributes = 0;
+    } else {
+      numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr == '\0') {
+      markers = 0;  // Default value.
+    } else {
+      markers = (int) strtol (stringptr, &stringptr, 0);
+    }
+  } else {
+    // It is a rbox (qhull) input file.
+    stringptr = inputline;
+    // Get the dimension.
+    mesh_dim = (int) strtol (stringptr, &stringptr, 0);
+    // Get the number of points.
+    stringptr = readnumberline(inputline, infile, infilename);
+    numberofpoints = (int) strtol (stringptr, &stringptr, 0);
+    // There is no index column.
+    useindex = 0;
+  }
+
+  // Load the list of nodes.
+  if (!load_node_call(infile, markers, infilename)) {
+    fclose(infile);
+    return false;
+  }
+  fclose(infile);
+
+  // Read the elements from an .ele file.
+  if (mesh_dim == 3) {
+    infilename = inelefilename;
+    infile = fopen(infilename, "r");
+    if (infile != (FILE *) NULL) {
+      printf("Opening %s.\n", infilename);
+      // Read number of elements, number of corners (4 or 10), number of
+      //   element attributes.
+      stringptr = readnumberline(inputline, infile, infilename);
+      numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0);
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        numberofcorners = 4;  // Default read 4 nodes per element.
+      } else {
+        numberofcorners = (int) strtol(stringptr, &stringptr, 0);
+      }
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        numberoftetrahedronattributes = 0; // Default no attribute.
+      } else {
+        numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0);
+      }
+      if (numberofcorners != 4 && numberofcorners != 10) {
+        printf("Error:  Wrong number of corners %d (should be 4 or 10).\n", 
+               numberofcorners);
+        fclose(infile);
+        return false;
+      }
+      // Allocate memory for tetrahedra.
+      if (numberoftetrahedra > 0) {
+        tetrahedronlist = new int[numberoftetrahedra * numberofcorners]; 
+        if (tetrahedronlist == (int *) NULL) {
+          printf("Error:  Out of memory.\n");
+          terminatetetgen(1);
+        }
+        // Allocate memory for output tetrahedron attributes if necessary.
+        if (numberoftetrahedronattributes > 0) {
+          tetrahedronattributelist = new REAL[numberoftetrahedra *
+                                          numberoftetrahedronattributes];
+          if (tetrahedronattributelist == (REAL *) NULL) {
+            printf("Error:  Out of memory.\n");
+            terminatetetgen(1);
+          }
+        }
+      }
+      // Read the list of tetrahedra.
+      index = 0;
+      attribindex = 0;
+      for (i = 0; i < numberoftetrahedra; i++) {
+        // Read tetrahedron index and the tetrahedron's corners.
+        stringptr = readnumberline(inputline, infile, infilename);
+        for (j = 0; j < numberofcorners; j++) {
+          stringptr = findnextnumber(stringptr);
+          if (*stringptr == '\0') {
+            printf("Error:  Tetrahedron %d is missing vertex %d in %s.\n",
+                   i + firstnumber, j + 1, infilename);
+            terminatetetgen(1);
+          }
+          corner = (int) strtol(stringptr, &stringptr, 0);
+          if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
+            printf("Error:  Tetrahedron %d has an invalid vertex index.\n",
+                   i + firstnumber);
+            terminatetetgen(1);
+          }
+          tetrahedronlist[index++] = corner;
+        }
+        // Read the tetrahedron's attributes.
+        for (j = 0; j < numberoftetrahedronattributes; j++) {
+          stringptr = findnextnumber(stringptr);
+          if (*stringptr == '\0') {
+            attrib = 0.0;
+          } else {
+            attrib = (REAL) strtod(stringptr, &stringptr);
+          }
+          tetrahedronattributelist[attribindex++] = attrib;
+        }
+      }
+      fclose(infile);
+    }
+  } // if (meshdim == 3)
+  
+  // Read the hullfaces or subfaces from a .face file if it exists.
+  if (mesh_dim == 3) {
+    infilename = infacefilename;
+  } else {
+    infilename = inelefilename;
+  }
+  infile = fopen(infilename, "r");
+  if (infile != (FILE *) NULL) {
+    printf("Opening %s.\n", infilename);
+    // Read number of faces, boundary markers.
+    stringptr = readnumberline(inputline, infile, infilename);
+    numberoftrifaces = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findnextnumber(stringptr);
+    if (mesh_dim == 2) {
+      // Skip a number.
+      stringptr = findnextnumber(stringptr);
+    }
+    if (*stringptr == '\0') {
+      markers = 0;  // Default there is no marker per face.
+    } else {
+      markers = (int) strtol (stringptr, &stringptr, 0);
+    }
+    if (numberoftrifaces > 0) {
+      trifacelist = new int[numberoftrifaces * 3];
+      if (trifacelist == (int *) NULL) {
+        printf("Error:  Out of memory.\n");
+        terminatetetgen(1);
+      }
+      if (markers) {
+        trifacemarkerlist = new int[numberoftrifaces * 3];
+        if (trifacemarkerlist == (int *) NULL) {
+          printf("Error:  Out of memory.\n");
+          terminatetetgen(1);
+        }
+      }
+    }
+    // Read the list of faces.
+    index = 0;
+    for (i = 0; i < numberoftrifaces; i++) {
+      // Read face index and the face's three corners.
+      stringptr = readnumberline(inputline, infile, infilename);
+      for (j = 0; j < 3; j++) {
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Face %d is missing vertex %d in %s.\n",
+                 i + firstnumber, j + 1, infilename);
+          terminatetetgen(1);
+        }
+        corner = (int) strtol(stringptr, &stringptr, 0);
+        if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
+          printf("Error:  Face %d has an invalid vertex index.\n",
+                 i + firstnumber);
+          terminatetetgen(1);
+        }
+        trifacelist[index++] = corner;
+      }
+      // Read the boundary marker if it exists.
+      if (markers) {
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          attrib = 0.0;
+        } else {
+          attrib = (REAL) strtod(stringptr, &stringptr);
+        }
+        trifacemarkerlist[i] = (int) attrib;
+      }
+    }
+    fclose(infile);
+  }
+
+  // Read the boundary edges from a .edge file if it exists.
+  infilename = inedgefilename;
+  infile = fopen(infilename, "r");
+  if (infile != (FILE *) NULL) {
+    printf("Opening %s.\n", infilename);
+    // Read number of boundary edges.
+    stringptr = readnumberline(inputline, infile, infilename);
+    numberofedges = (int) strtol (stringptr, &stringptr, 0);
+    if (numberofedges > 0) {
+      edgelist = new int[numberofedges * 2];
+      if (edgelist == (int *) NULL) {
+        printf("Error:  Out of memory.\n");
+        terminatetetgen(1);
+      }
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        markers = 0;  // Default value.
+      } else {
+        markers = (int) strtol (stringptr, &stringptr, 0);
+      }
+      if (markers > 0) {
+        edgemarkerlist = new int[numberofedges];
+      }
+    }
+    // Read the list of faces.
+    index = 0;
+    for (i = 0; i < numberofedges; i++) {
+      // Read face index and the edge's two endpoints.
+      stringptr = readnumberline(inputline, infile, infilename);
+      for (j = 0; j < 2; j++) {
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Edge %d is missing vertex %d in %s.\n",
+                 i + firstnumber, j + 1, infilename);
+          terminatetetgen(1);
+        }
+        corner = (int) strtol(stringptr, &stringptr, 0);
+        if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
+          printf("Error:  Edge %d has an invalid vertex index.\n",
+                 i + firstnumber);
+          terminatetetgen(1);
+        }
+        edgelist[index++] = corner;
+      }
+      // Read the edge marker if it has.
+      if (markers) {
+        stringptr = findnextnumber(stringptr);
+        edgemarkerlist[i] = (int) strtol(stringptr, &stringptr, 0);
+      }
+    }
+    fclose(infile);
+  }
+
+  // Read the volume constraints from a .vol file if it exists.
+  infilename = involfilename;
+  infile = fopen(infilename, "r");
+  if (infile != (FILE *) NULL) {
+    printf("Opening %s.\n", infilename);
+    // Read number of tetrahedra.
+    stringptr = readnumberline(inputline, infile, infilename);
+    volelements = (int) strtol (stringptr, &stringptr, 0);
+    if (volelements != numberoftetrahedra) {
+      printf("Warning:  %s and %s disagree on number of tetrahedra.\n",
+             inelefilename, involfilename);
+      volelements = 0;
+    }
+    if (volelements > 0) {
+      tetrahedronvolumelist = new REAL[volelements];
+      if (tetrahedronvolumelist == (REAL *) NULL) {
+        printf("Error:  Out of memory.\n");
+        terminatetetgen(1);
+      }
+    }
+    // Read the list of volume constraints.
+    for (i = 0; i < volelements; i++) {
+      stringptr = readnumberline(inputline, infile, infilename);
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        volume = -1.0; // No constraint on this tetrahedron.
+      } else {
+        volume = (REAL) strtod(stringptr, &stringptr);
+      }
+      tetrahedronvolumelist[i] = volume;
+    }
+    fclose(infile);
+  }
+
+  // Try to load a .mtr file if it exists.
+  load_mtr(filename);
+  // Try to read a .pbc file if it exists.
+  load_pbc(filename);
+
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// load_voronoi()    Load a Voronoi diagram from files.                      //
+//                                                                           //
+// 'filename' is the inputfile without suffix.  The Voronoi diagram is read  //
+// from files: filename.v.node, filename.v.edge, and filename.v.face.        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenio::load_voronoi(const char* filename)
+{
+  FILE *infile;
+  char innodefilename[FILENAMESIZE];
+  char inedgefilename[FILENAMESIZE];
+  char inputline[INPUTLINESIZE];
+  char *stringptr, *infilename;
+  voroedge *vedge;
+  REAL x, y, z;
+  int firstnode, corner;
+  int index;
+  int i, j;
+
+  // Assembling the actual file names we want to open.
+  strcpy(innodefilename, filename);
+  strcpy(inedgefilename, filename);
+  strcat(innodefilename, ".v.node");
+  strcat(inedgefilename, ".v.edge");
+
+  // Read the points from a .v.node file.
+  infilename = innodefilename;
+  printf("Opening %s.\n", infilename);
+  infile = fopen(infilename, "r");
+  if (infile == (FILE *) NULL) {
+    printf("File I/O Error:  Cannot access file %s.\n", infilename);
+    return false;
+  }
+  // Read the first line of the file.
+  stringptr = readnumberline(inputline, infile, infilename); 
+  // Is this list of points generated from rbox?
+  stringptr = strstr(inputline, "rbox");
+  if (stringptr == NULL) {
+    // Read number of points, number of dimensions, number of point
+    //   attributes, and number of boundary markers.
+    stringptr = inputline;
+    numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr == '\0') {
+      mesh_dim = 3;  // Default.
+    } else {
+      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
+    }
+    useindex = 1;  // There is an index column.
+  } else {
+    // It is a rbox (qhull) input file.
+    stringptr = inputline;
+    // Get the dimension.
+    mesh_dim = (int) strtol (stringptr, &stringptr, 0);
+    // Get the number of points.
+    stringptr = readnumberline(inputline, infile, infilename);
+    numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
+    useindex = 0;  // No index column.
+  }
+  // Initialize 'vpointlist'.
+  vpointlist = new REAL[numberofvpoints * 3];
+  if (vpointlist == (REAL *) NULL) {
+    printf("Error:  Out of memory.\n");
+    terminatetetgen(1);
+  }
+  // Read the point section.
+  index = 0;
+  for (i = 0; i < numberofvpoints; i++) {
+    stringptr = readnumberline(inputline, infile, infilename);
+    if (useindex) {
+      if (i == 0) {
+        firstnode = (int) strtol (stringptr, &stringptr, 0);
+        if ((firstnode == 0) || (firstnode == 1)) {
+          firstnumber = firstnode;
+        }
+      }
+      stringptr = findnextnumber(stringptr);
+    } // if (useindex)
+    if (*stringptr == '\0') {
+      printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
+      terminatetetgen(1);
+    }
+    x = (REAL) strtod(stringptr, &stringptr);
+    stringptr = findnextnumber(stringptr);
+    if (*stringptr == '\0') {
+      printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
+      terminatetetgen(1);
+    }
+    y = (REAL) strtod(stringptr, &stringptr);
+    if (mesh_dim == 3) {
+      stringptr = findnextnumber(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
+        terminatetetgen(1);
+      }
+      z = (REAL) strtod(stringptr, &stringptr);
+    } else {
+      z = 0.0; // mesh_dim == 2;
+    }
+    vpointlist[index++] = x;
+    vpointlist[index++] = y;
+    vpointlist[index++] = z;
+  }
+  fclose(infile);
+
+  // Read the Voronoi edges from a .v.edge file if it exists.
+  infilename = inedgefilename;
+  infile = fopen(infilename, "r");
+  if (infile != (FILE *) NULL) {
+    printf("Opening %s.\n", infilename);
+    // Read number of boundary edges.
+    stringptr = readnumberline(inputline, infile, infilename);
+    numberofvedges = (int) strtol (stringptr, &stringptr, 0);
+    if (numberofvedges > 0) {
+      vedgelist = new voroedge[numberofvedges];
+    }
+    // Read the list of faces.
+    index = 0;
+    for (i = 0; i < numberofvedges; i++) {
+      // Read edge index and the edge's two endpoints.
+      stringptr = readnumberline(inputline, infile, infilename);
+      vedge = &(vedgelist[i]);
+      for (j = 0; j < 2; j++) {
+        stringptr = findnextnumber(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Edge %d is missing vertex %d in %s.\n",
+                 i + firstnumber, j + 1, infilename);
+          terminatetetgen(1);
+        }
+        corner = (int) strtol(stringptr, &stringptr, 0);
+        j == 0 ? vedge->v1 = corner : vedge->v2 = corner;
+      }
+      if (vedge->v2 < 0) {
+        for (j = 0; j < mesh_dim; j++) {
+          stringptr = findnextnumber(stringptr);
+          if (*stringptr == '\0') {
+            printf("Error:  Edge %d is missing normal in %s.\n",
+                   i + firstnumber, infilename);
+            terminatetetgen(1);
+          }
+          vedge->vnormal[j] = (REAL) strtod(stringptr, &stringptr);
+        }
+        if (mesh_dim == 2) {
+          vedge->vnormal[2] = 0.0;
+        }
+      } else {
+        vedge->vnormal[0] = 0.0;
+        vedge->vnormal[1] = 0.0;
+        vedge->vnormal[2] = 0.0;
+      }
+    }
+    fclose(infile);
+  }
+
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// save_nodes()    Save points to a .node file.                              //
+//                                                                           //
+// 'filename' is a string containing the file name without suffix.           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenio::save_nodes(const char* filename)
+{
+  FILE *fout;
+  char outnodefilename[FILENAMESIZE];
+  char outmtrfilename[FILENAMESIZE];
+  int i, j;
+
+  sprintf(outnodefilename, "%s.node", filename);
+  printf("Saving nodes to %s\n", outnodefilename);
+  fout = fopen(outnodefilename, "w");
+  fprintf(fout, "%d  %d  %d  %d\n", numberofpoints, mesh_dim,
+          numberofpointattributes, pointmarkerlist != NULL ? 1 : 0);
+  for (i = 0; i < numberofpoints; i++) {
+    if (mesh_dim == 2) {
+      fprintf(fout, "%d  %.16g  %.16g", i + firstnumber, pointlist[i * 3],
+              pointlist[i * 3 + 1]);
+    } else {
+      fprintf(fout, "%d  %.16g  %.16g  %.16g", i + firstnumber,
+              pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
+    }
+    for (j = 0; j < numberofpointattributes; j++) {
+      fprintf(fout, "  %.16g", 
+              pointattributelist[i * numberofpointattributes + j]);
+    }
+    if (pointmarkerlist != NULL) {
+      fprintf(fout, "  %d", pointmarkerlist[i]);
+    }
+    fprintf(fout, "\n");
+  }
+  fclose(fout);
+
+  // If the point metrics exist, output them to a .mtr file.
+  if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
+    sprintf(outmtrfilename, "%s.mtr", filename);
+    printf("Saving metrics to %s\n", outmtrfilename);
+    fout = fopen(outmtrfilename, "w");
+    fprintf(fout, "%d  %d\n", numberofpoints, numberofpointmtrs);
+    for (i = 0; i < numberofpoints; i++) {
+      for (j = 0; j < numberofpointmtrs; j++) {
+        fprintf(fout, "%.16g ", pointmtrlist[i * numberofpointmtrs + j]);
+      }
+      fprintf(fout, "\n");
+    }
+    fclose(fout);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// save_elements()    Save elements to a .ele file.                          //
+//                                                                           //
+// 'filename' is a string containing the file name without suffix.           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenio::save_elements(const char* filename)
+{
+  FILE *fout;
+  char outelefilename[FILENAMESIZE];
+  int i, j;
+
+  sprintf(outelefilename, "%s.ele", filename);
+  printf("Saving elements to %s\n", outelefilename);
+  fout = fopen(outelefilename, "w");
+  if (mesh_dim == 3) {
+    fprintf(fout, "%d  %d  %d\n", numberoftetrahedra, numberofcorners,
+            numberoftetrahedronattributes);
+    for (i = 0; i < numberoftetrahedra; i++) {
+      fprintf(fout, "%d", i + firstnumber);
+      for (j = 0; j < numberofcorners; j++) {
+        fprintf(fout, "  %5d", tetrahedronlist[i * numberofcorners + j]);
+      }
+      for (j = 0; j < numberoftetrahedronattributes; j++) {
+        fprintf(fout, "  %g",
+          tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
+      }
+      fprintf(fout, "\n");
+    }
+  } else {
+    // Save a two-dimensional mesh.
+    fprintf(fout, "%d  %d  %d\n", numberoftrifaces,3,trifacemarkerlist ? 1:0);
+    for (i = 0; i < numberoftrifaces; i++) {
+      fprintf(fout, "%d", i + firstnumber);
+      for (j = 0; j < 3; j++) {
+        fprintf(fout, "  %5d", trifacelist[i * 3 + j]);
+      }
+      if (trifacemarkerlist != NULL) {
+        fprintf(fout, "  %d", trifacemarkerlist[i]);
+      }
+      fprintf(fout, "\n");
+    }
+  }
+
+  fclose(fout);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// save_faces()    Save faces to a .face file.                               //
+//                                                                           //
+// 'filename' is a string containing the file name without suffix.           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenio::save_faces(const char* filename)
+{
+  FILE *fout;
+  char outfacefilename[FILENAMESIZE];
+  int i;
+
+  sprintf(outfacefilename, "%s.face", filename);
+  printf("Saving faces to %s\n", outfacefilename);
+  fout = fopen(outfacefilename, "w");
+  fprintf(fout, "%d  %d\n", numberoftrifaces, 
+          trifacemarkerlist != NULL ? 1 : 0);
+  for (i = 0; i < numberoftrifaces; i++) {
+    fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber, trifacelist[i * 3],
+            trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
+    if (trifacemarkerlist != NULL) {
+      fprintf(fout, "  %d", trifacemarkerlist[i]);
+    }
+    fprintf(fout, "\n");
+  }
+
+  fclose(fout);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// save_edges()    Save egdes to a .edge file.                               //
+//                                                                           //
+// 'filename' is a string containing the file name without suffix.           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenio::save_edges(const char* filename)
+{
+  FILE *fout;
+  char outedgefilename[FILENAMESIZE];
+  int i;
+
+  sprintf(outedgefilename, "%s.edge", filename);
+  printf("Saving edges to %s\n", outedgefilename);
+  fout = fopen(outedgefilename, "w");
+  fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
+  for (i = 0; i < numberofedges; i++) {
+    fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
+            edgelist[i * 2 + 1]);
+    if (edgemarkerlist != NULL) {
+      fprintf(fout, "  %d", edgemarkerlist[i]);
+    }
+    fprintf(fout, "\n");
+  }
+
+  fclose(fout);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// save_neighbors()    Save egdes to a .neigh file.                          //
+//                                                                           //
+// 'filename' is a string containing the file name without suffix.           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenio::save_neighbors(const char* filename)
+{
+  FILE *fout;
+  char outneighborfilename[FILENAMESIZE];
+  int i;
+
+  sprintf(outneighborfilename, "%s.neigh", filename);
+  printf("Saving neighbors to %s\n", outneighborfilename);
+  fout = fopen(outneighborfilename, "w");
+  fprintf(fout, "%d  %d\n", numberoftetrahedra, mesh_dim + 1);
+  for (i = 0; i < numberoftetrahedra; i++) {
+    if (mesh_dim == 2) {
+      fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber,  neighborlist[i * 3],
+              neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]);
+    } else {
+      fprintf(fout, "%d  %5d  %5d  %5d  %5d", i + firstnumber,
+              neighborlist[i * 4], neighborlist[i * 4 + 1],
+              neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]);
+    }
+    fprintf(fout, "\n");
+  }
+
+  fclose(fout);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// save_poly()    Save segments or facets to a .poly file.                   //
+//                                                                           //
+// 'filename' is a string containing the file name without suffix.  It only  //
+// save the facets, holes and regions.  The nodes are saved in a .node file  //
+// by routine save_nodes().                                                  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenio::save_poly(const char* filename)
+{
+  FILE *fout;
+  facet *f;
+  polygon *p;
+  char outpolyfilename[FILENAMESIZE];
+  int i, j, k;
+
+  sprintf(outpolyfilename, "%s.poly", filename);
+  printf("Saving poly to %s\n", outpolyfilename);
+  fout = fopen(outpolyfilename, "w");
+
+  // The zero indicates that the vertices are in a separate .node file.
+  //   Followed by number of dimensions, number of vertex attributes,
+  //   and number of boundary markers (zero or one).
+  fprintf(fout, "%d  %d  %d  %d\n", 0, mesh_dim, numberofpointattributes,
+          pointmarkerlist != NULL ? 1 : 0);
+
+  // Save segments or facets.
+  if (mesh_dim == 2) {
+    // Number of segments, number of boundary markers (zero or one).
+    fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
+    for (i = 0; i < numberofedges; i++) {
+      fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
+              edgelist[i * 2 + 1]);
+      if (edgemarkerlist != NULL) {
+        fprintf(fout, "  %d", edgemarkerlist[i]);
+      }
+      fprintf(fout, "\n");
+    }
+  } else {
+    // Number of facets, number of boundary markers (zero or one).
+    fprintf(fout, "%d  %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0);
+    for (i = 0; i < numberoffacets; i++) {
+      f = &(facetlist[i]);
+      fprintf(fout, "%d  %d  %d  # %d\n", f->numberofpolygons,f->numberofholes,
+            facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber);
+      // Output polygons of this facet.
+      for (j = 0; j < f->numberofpolygons; j++) {
+        p = &(f->polygonlist[j]);
+        fprintf(fout, "%d  ", p->numberofvertices);
+        for (k = 0; k < p->numberofvertices; k++) {
+          if (((k + 1) % 10) == 0) {
+            fprintf(fout, "\n  ");
+          }
+          fprintf(fout, "  %d", p->vertexlist[k]);
+        }
+        fprintf(fout, "\n");
+      }
+      // Output holes of this facet.
+      for (j = 0; j < f->numberofholes; j++) {
+        fprintf(fout, "%d  %.12g  %.12g  %.12g\n", j + firstnumber,
+           f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]);
+      }
+    }
+  }
+
+  // Save holes.
+  fprintf(fout, "%d\n", numberofholes);
+  for (i = 0; i < numberofholes; i++) {
+    // Output x, y coordinates.
+    fprintf(fout, "%d  %.12g  %.12g", i + firstnumber, holelist[i * mesh_dim],
+            holelist[i * mesh_dim + 1]);
+    if (mesh_dim == 3) {
+      // Output z coordinate.
+      fprintf(fout, "  %.12g", holelist[i * mesh_dim + 2]);
+    }
+    fprintf(fout, "\n");
+  }
+
+  // Save regions.
+  fprintf(fout, "%d\n", numberofregions);
+  for (i = 0; i < numberofregions; i++) {
+    if (mesh_dim == 2) {
+      // Output the index, x, y coordinates, attribute (region number)
+      //   and maximum area constraint (maybe -1).
+      fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
+              regionlist[i * 4], regionlist[i * 4 + 1],
+              regionlist[i * 4 + 2], regionlist[i * 4 + 3]);
+    } else {
+      // Output the index, x, y, z coordinates, attribute (region number)
+      //   and maximum volume constraint (maybe -1).
+      fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
+              regionlist[i * 5], regionlist[i * 5 + 1],
+              regionlist[i * 5 + 2], regionlist[i * 5 + 3],
+              regionlist[i * 5 + 4]);
+    }
+  }
+
+  fclose(fout);  
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// readline()   Read a nonempty line from a file.                            //
+//                                                                           //
+// A line is considered "nonempty" if it contains something more than white  //
+// spaces.  If a line is considered empty, it will be dropped and the next   //
+// line will be read, this process ends until reaching the end-of-file or a  //
+// non-empty line.  Return NULL if it is the end-of-file, otherwise, return  //
+// a pointer to the first non-whitespace character of the line.              //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+char* tetgenio::readline(char *string, FILE *infile, int *linenumber)
+{
+  char *result;
+
+  // Search for a non-empty line.
+  do {
+    result = fgets(string, INPUTLINESIZE - 1, infile);
+    if (linenumber) (*linenumber)++;
+    if (result == (char *) NULL) {
+      return (char *) NULL;
+    }
+    // Skip white spaces.
+    while ((*result == ' ') || (*result == '\t')) result++;
+    // If it's end of line, read another line and try again.
+  } while (*result == '\0');
+  return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// findnextfield()   Find the next field of a string.                        //
+//                                                                           //
+// Jumps past the current field by searching for whitespace or a comma, then //
+// jumps past the whitespace or the comma to find the next field.            //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+char* tetgenio::findnextfield(char *string)
+{
+  char *result;
+
+  result = string;
+  // Skip the current field.  Stop upon reaching whitespace or a comma.
+  while ((*result != '\0') && (*result != ' ') &&  (*result != '\t') && 
+         (*result != ',') && (*result != ';')) {
+    result++;
+  }
+  // Now skip the whitespace or the comma, stop at anything else that looks
+  //   like a character, or the end of a line. 
+  while ((*result == ' ') || (*result == '\t') || (*result == ',') ||
+         (*result == ';')) {
+    result++;
+  }
+  return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// readnumberline()   Read a nonempty number line from a file.               //
+//                                                                           //
+// A line is considered "nonempty" if it contains something that looks like  //
+// a number.  Comments (prefaced by `#') are ignored.                        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+char* tetgenio::readnumberline(char *string, FILE *infile, 
+  const char *infilename)
+{
+  char *result;
+
+  // Search for something that looks like a number.
+  do {
+    result = fgets(string, INPUTLINESIZE, infile);
+    if (result == (char *) NULL) {
+      if (infilename != (char *) NULL) {
+        printf("  Error:  Unexpected end of file in %s.\n", infilename);
+        terminatetetgen(1);
+      }
+      return result;
+    }
+    // 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;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// findnextnumber()   Find the next field of a number string.                //
+//                                                                           //
+// Jumps past the current field by searching for whitespace or a comma, then //
+// jumps past the whitespace or the comma to find the next field that looks  //
+// like a number.                                                            //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+char* tetgenio::findnextnumber(char *string)
+{
+  char *result;
+
+  result = string;
+  // Skip the current field.  Stop upon reaching whitespace or a comma.
+  while ((*result != '\0') && (*result != '#') && (*result != ' ') && 
+         (*result != '\t') && (*result != ',')) {
+    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;
+}
+
+#endif // #ifndef tetgenioCXX
\ No newline at end of file
diff --git a/contrib/Tetgen/main.cxx b/contrib/Tetgen/main.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..dafc3a88779712980127b355ae6e461a29329e9b
--- /dev/null
+++ b/contrib/Tetgen/main.cxx
@@ -0,0 +1,374 @@
+#ifndef mainCXX
+#define mainCXX
+
+#include "tetgen.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// test_tri_tri()    Triangle-triangle intersection tests.                   //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void test_tri_tri(tetgenbehavior *b, tetgenio *in)
+{
+  tetgenmesh m;
+  tetgenmesh::face s1, s2;
+  tetgenmesh::point U[3], V[3], T1[3], T2[3];
+  tetgenmesh::intersection dir;
+  int types[2], pos[4];
+  int i, j;
+
+  m.b = b;
+  m.in = in;
+  exactinit();
+  m.initializepools();
+  m.transfernodes();
+  m.meshsurface();
+
+  m.subfacepool->traversalinit();
+  s1.sh = m.shellfacetraverse(m.subfacepool);
+  s2.sh = m.shellfacetraverse(m.subfacepool);
+
+  V[0] = (tetgenmesh::point) s1.sh[3]; // P
+  V[1] = (tetgenmesh::point) s1.sh[4]; // Q
+  V[2] = (tetgenmesh::point) s1.sh[5]; // R
+
+  U[0] = (tetgenmesh::point) s2.sh[3]; // A
+  U[1] = (tetgenmesh::point) s2.sh[4]; // B
+  U[2] = (tetgenmesh::point) s2.sh[5]; // C
+
+  // The permuations of {0, 1, 2}
+  int perm[6][3] = { 
+    {0, 1, 2}, 
+    {2, 0, 1}, 
+    {1, 2, 0},
+    {1, 0, 2}, 
+    {2, 1, 0}, 
+    {0, 2, 1}};
+
+  b->epsilon = 0;
+  b->verbose = 3;
+
+  for (j = 0; j < 36; j++) {
+
+    // Get the permuation of the vertices.
+    T1[0] = U[perm[j/6][0]];
+    T1[1] = U[perm[j/6][1]];
+    T1[2] = U[perm[j/6][2]];
+    
+    T2[0] = V[perm[j%6][0]];
+    T2[1] = V[perm[j%6][1]];
+    T2[2] = V[perm[j%6][2]];
+
+    i = m.tri_tri_test(T1[0], T1[1], T1[2], T2[0], T2[1], T2[2], NULL, 1, 
+                       types, pos);
+    if (i == 0) {
+      printf("  [%d] DISJOINT.\n", j);
+      continue;
+    }
+
+    // Report the intersection types and positions.
+    for (i = 0; i < 2; i++) {
+      dir = (enum tetgenmesh::intersection) types[i];
+      switch (dir) {
+      case tetgenmesh::DISJOINT: 
+        printf("  [%d] DISJOINT\n", j); break;
+      case tetgenmesh::SHAREVERT: 
+        printf("  [%d] SHAREVERT %d %d\n", j, pos[i*2], pos[i*2+1]); break;
+      case tetgenmesh::SHAREEDGE: 
+        printf("  [%d] SHAREEDGE %d %d\n", j, pos[i*2], pos[i*2+1]); break;
+      case tetgenmesh::SHAREFACE: 
+        printf("  [%d] SHAREFACE\n", j); break;
+      case tetgenmesh::TOUCHEDGE: 
+        printf("  [%d] TOUCHEDGE %d %d\n", j, pos[i*2], pos[i*2+1]); break;
+      case tetgenmesh::TOUCHFACE: 
+        printf("  [%d] TOUCHFACE %d %d\n", j, pos[i*2], pos[i*2+1]); break;
+      case tetgenmesh::ACROSSVERT: 
+        printf("  [%d] ACROSSVERT %d %d\n", j, pos[i*2], pos[i*2+1]); break;
+      case tetgenmesh::ACROSSEDGE: 
+        printf("  [%d] ACROSSEDGE %d %d\n", j, pos[i*2], pos[i*2+1]); break;
+      case tetgenmesh::ACROSSFACE: 
+        printf("  [%d] ACROSSFACE %d %d\n", j, pos[i*2], pos[i*2+1]); break;
+      case tetgenmesh::ACROSSTET: 
+        printf("  [%d] ACROSSTET\n", j); break;
+      case tetgenmesh::TRIEDGEINT:
+        printf("  [%d] TRIEDGEINT %d %d\n", j, pos[i*2], pos[i*2+1]); break;
+      case tetgenmesh::EDGETRIINT:
+        printf("  [%d] EDGETRIINT %d %d\n", j, pos[i*2], pos[i*2+1]); break;
+      }
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// tetrahedralize()    The interface for users using TetGen library to       //
+//                     generate tetrahedral meshes with all features.        //
+//                                                                           //
+// 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 vertices from a file and either                                //
+//   - tetrahedralize them (no -r), or                                       //
+//   - read an old mesh from files and reconstruct it (-r).                  //
+// - Insert the PLC segments and facets (-p).                                //
+// - Read the holes (-p), regional attributes (-pA), and regional volume     //
+//   constraints (-pa).  Carve the holes and concavities, and spread the     //
+//   regional attributes and volume constraints.                             //
+// - Enforce the constraints on minimum quality bound (-q) and maximum       //
+//   volume (-a). Also enforce the conforming Delaunay property (-q and -a). //
+// - Promote the mesh's linear tetrahedra to higher order elements (-o).     //
+// - Write the output files and print the statistics.                        //
+// - Check the consistency and Delaunay property of the mesh (-C).           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
+  tetgenio *addin, tetgenio *bgmin)
+{
+  tetgenmesh m;
+  // Variables for timing the performance of TetGen (defined in time.h).
+  clock_t tv[17];
+
+  tv[0] = clock();
+
+  m.b = b;
+  m.in = in;
+  exactinit();
+  m.initializepools();
+  m.transfernodes();
+
+  tv[1] = clock();
+
+  if (b->refine) {
+    // m.reconstructmesh();
+  } else {
+    m.incrementaldelaunay();
+  }
+
+  tv[2] = clock();
+
+  if (!b->quiet) {
+    if (b->refine) {
+      printf("Mesh reconstruction seconds:");
+    } else {
+      printf("Delaunay seconds:");
+    }
+    printf("  %g\n", (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
+  }
+
+  if (b->plc) { // if has -p option
+    m.meshsurface();
+  }
+
+  tv[3] = clock();
+
+  if (!b->quiet) {
+    if (b->plc) {
+      printf("Surface meshing seconds:  %g\n", 
+        (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
+    }
+  }
+
+  if (b->plc) { // if has -p option
+    m.formskeleton();
+  }
+  
+  tv[4] = clock();
+
+  if (!b->quiet) {
+    if (b->plc) {
+      if (b->diagnose != 1) {
+        printf("Boundary recovery ");
+      } else {
+        printf("Intersection "); 
+      }
+      printf("seconds:  %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
+    }
+  }
+
+  if (b->plc) { 
+    if (b->convexity == 0) { // if has no -c option.
+      m.carveholes();
+    }
+  }
+
+  tv[5] = clock();
+
+  if (!b->quiet) {
+    if (b->plc) {
+      if (b->convexity == 0) { // if has no -c option.
+        printf("Holes and region seconds:  %g\n", 
+          (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
+      }
+    }
+  }
+
+  printf("\n");
+
+  if (out != (tetgenio *) NULL) {
+    out->firstnumber = in->firstnumber;
+    out->mesh_dim = in->mesh_dim;
+  }
+
+  if (b->nonodewritten || b->noiterationnum) {
+    if (!b->quiet) {
+      printf("NOT writing a .node file.\n");
+    }
+  } else {
+    m.outnodes(out);
+  }
+
+  if (b->noelewritten == 1) {
+    if (!b->quiet) {
+      printf("NOT writing an .ele file.\n");
+    }
+    m.numberedges();
+  } else {
+    m.outelements(out);
+  }
+
+  if (b->nofacewritten) {
+    if (!b->quiet) {
+      printf("NOT writing an .face file.\n");
+    }
+    if (b->plc || b->refine) {
+      m.numbersubedges();
+    }
+  } else {
+    if (b->facesout) {
+      if (m.tetrahedronpool->items > 0l) {
+        m.outfaces(out);  // Output all faces.
+      }
+      if (b->plc || b->refine) {
+        m.numberedges();
+      }
+    } else {
+      if (b->plc || b->refine) {
+        if (m.subfacepool->items > 0l) {
+          m.outsubfaces(out); // Output boundary faces.
+        }
+      } else {
+        if (m.tetrahedronpool->items > 0l) {
+          m.outhullfaces(out); // Output convex hull faces.
+        }
+      }
+    }
+  }
+
+  if (b->edgesout) {
+    if (b->edgesout > 1) {
+      m.outedges(out); // -ee, output all mesh edges. 
+    } else {
+      m.outsubsegments(out); // -e, only output subsegments.
+    }
+  }
+
+  if (b->neighout) {
+    m.outneighbors(out);
+  }
+
+  if (b->voroout) {
+    // m.outvoronoi(out);
+  }
+
+  tv[6] = clock();
+
+  if (!b->quiet) {
+    printf("\nOutput seconds:  %g\n",
+           (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
+    printf("Total running seconds:  %g\n\n",
+           (tv[6] - tv[0]) / (REAL) CLOCKS_PER_SEC);
+  }
+
+  if (b->docheck) {
+    if (b->plc) {
+      m.checkshells(1);
+    }
+    if (m.checkdelaunay(b->plc) > 0) assert(0);
+  }
+
+  if (!b->quiet) {
+    m.statistics();
+  }
+}
+
+#ifndef TETLIBRARY
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// main()    The entrance for running TetGen from command line.              //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+int main(int argc, char *argv[])
+
+#else // with TETLIBRARY
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// tetrahedralize()    The entrance for calling TetGen from another program. //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
+  tetgenio *addin, tetgenio *bgmin)
+
+#endif // not TETLIBRARY
+
+{
+  tetgenbehavior b;
+
+#ifndef TETLIBRARY
+
+  tetgenio in, addin, bgmin;
+  
+  if (!b.parse_commandline(argc, argv)) {
+    terminatetetgen(1);
+  }
+  if (b.refine) {
+    if (!in.load_tetmesh(b.infilename)) {
+      terminatetetgen(1);
+    }
+  } else {
+    if (!in.load_plc(b.infilename, (int) b.object)) {
+      terminatetetgen(1);
+    }
+  }
+  if (b.insertaddpoints) {
+    if (!addin.load_node(b.addinfilename)) {
+      addin.numberofpoints = 0l;
+    }
+  }
+  if (b.metric) {
+    if (!bgmin.load_tetmesh(b.bgmeshfilename)) {
+      bgmin.numberoftetrahedra = 0l;
+    }
+  }
+
+  // FOR DEBUG -S1 option.
+  if (b.steiner > 0) {
+    test_tri_tri(&b, &in);
+    terminatetetgen(0);
+  }
+
+  if (bgmin.numberoftetrahedra > 0l) {
+    tetrahedralize(&b, &in, NULL, &addin, &bgmin);
+  } else {
+    tetrahedralize(&b, &in, NULL, &addin, NULL);
+  }
+
+  return 0;
+
+#else // with TETLIBRARY
+
+  if (!b.parse_commandline(switches)) {
+    terminatetetgen(1);
+  }
+  tetrahedralize(&b, in, out, addin, bgmin);
+
+#endif // not TETLIBRARY
+}
+
+#endif // #ifndef mainCXX
\ No newline at end of file
diff --git a/contrib/Tetgen/memorypool.cxx b/contrib/Tetgen/memorypool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..21a0ff623e60af959ac08bb4359ffcc341466e20
--- /dev/null
+++ b/contrib/Tetgen/memorypool.cxx
@@ -0,0 +1,981 @@
+#ifndef memorypoolCXX
+#define memorypoolCXX
+
+#include "tetgen.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// restart()    Deallocate all objects in this pool.                         //
+//                                                                           //
+// The pool returns to a fresh state, like after it was initialized, except  //
+// that no memory is freed to the operating system.  Rather, the previously  //
+// allocated blocks are ready to be used.                                    //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::arraypool::restart()
+{
+  objects = 0l;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// poolinit()    Initialize an arraypool for allocation of objects.          //
+//                                                                           //
+// Before the pool may be used, it must be initialized by this procedure.    //
+// After initialization, memory can be allocated and freed in this pool.     //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::arraypool::poolinit(int sizeofobject, int log2objperblk)
+{
+  // Each object must be at least one byte long.
+  objectbytes = sizeofobject > 1 ? sizeofobject : 1;
+
+  log2objectsperblock = log2objperblk;
+  // Compute the number of objects in each block.
+  objectsperblock = ((int) 1) << log2objectsperblock;
+
+  // No memory has been allocated.
+  totalmemory = 0l;
+  // The top array has not been allocated yet.
+  toparray = (char **) NULL;
+  toparraylen = 0;
+
+  // Ready all indices to be allocated.
+  restart();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// arraypool()    The constructor and destructor.                            //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+tetgenmesh::arraypool::arraypool(int sizeofobject, int log2objperblk)
+{
+  poolinit(sizeofobject, log2objperblk);
+}
+
+tetgenmesh::arraypool::~arraypool()
+{
+  int i;
+
+  // Has anything been allocated at all?
+  if (toparray != (char **) NULL) {
+    // Walk through the top array.
+    for (i = 0; i < toparraylen; i++) {
+      // Check every pointer; NULLs may be scattered randomly.
+      if (toparray[i] != (char *) NULL) {
+        // Free an allocated block.
+        free((void *) toparray[i]);
+      }
+    }
+    // Free the top array.
+    free((void *) toparray);
+  }
+
+  // The top array is no longer allocated.
+  toparray = (char **) NULL;
+  toparraylen = 0;
+  objects = 0;
+  totalmemory = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// getblock()    Return (and perhaps create) the block containing the object //
+//               with a given index.                                         //
+//                                                                           //
+// This function takes care of allocating or resizing the top array if nece- //
+// ssary, and of allocating the block if it hasn't yet been allocated.       //
+//                                                                           //
+// Return a pointer to the beginning of the block (NOT the object).          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+char* tetgenmesh::arraypool::getblock(int objectindex)
+{
+  char **newarray;
+  char *block;
+  int newsize;
+  int topindex;
+  int i;
+
+  // Compute the index in the top array (upper bits).
+  topindex = objectindex >> log2objectsperblock;
+  // Does the top array need to be allocated or resized?
+  if (toparray == (char **) NULL) {
+    // Allocate the top array big enough to hold 'topindex', and NULL out
+    //   its contents.
+    newsize = topindex + 128;
+    toparray = (char **) malloc((size_t) (newsize * sizeof(char *)));
+    toparraylen = newsize;
+    for (i = 0; i < newsize; i++) {
+      toparray[i] = (char *) NULL;
+    }
+    // Account for the memory.
+    totalmemory = newsize * (unsigned long) sizeof(char *);
+  } else if (topindex >= toparraylen) {
+    // Resize the top array, making sure it holds 'topindex'.
+    newsize = 3 * toparraylen;
+    if (topindex >= newsize) {
+      newsize = topindex + 128;
+    }
+    // Allocate the new array, copy the contents, NULL out the rest, and
+    //   free the old array.
+    newarray = (char **) malloc((size_t) (newsize * sizeof(char *)));
+    for (i = 0; i < toparraylen; i++) {
+      newarray[i] = toparray[i];
+    }
+    for (i = toparraylen; i < newsize; i++) {
+      newarray[i] = (char *) NULL;
+    }
+    free(toparray);
+    // Account for the memory.
+    totalmemory += (newsize - toparraylen) * sizeof(char *);
+    toparray = newarray;
+    toparraylen = newsize;
+  }
+
+  // Find the block, or learn that it hasn't been allocated yet.
+  block = toparray[topindex];
+  if (block == (char *) NULL) {
+    // Allocate a block at this index.
+    block = (char *) malloc((size_t) (objectsperblock * objectbytes));
+    toparray[topindex] = block;
+    // Account for the memory.
+    totalmemory += objectsperblock * objectbytes;
+  }
+
+  // Return a pointer to the block.
+  return block;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// lookup()    Return the pointer to the object with a given index, or NULL  //
+//             if the object's block doesn't exist yet.                      //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void* tetgenmesh::arraypool::lookup(int objectindex)
+{
+  char *block;
+  int topindex;
+
+  // Has the top array been allocated yet?
+  if (toparray == (char **) NULL) {
+    return (void *) NULL;
+  }
+
+  // Compute the index in the top array (upper bits).
+  topindex = objectindex >> log2objectsperblock;
+  // Does the top index fit in the top array?
+  if (topindex >= toparraylen) {
+    return (void *) NULL;
+  }
+
+  // Find the block, or learn that it hasn't been allocated yet.
+  block = toparray[topindex];
+  if (block == (char *) NULL) {
+    return (void *) NULL;
+  }
+
+  // Compute a pointer to the object with the given index.  Note that
+  //   'objectsperblock' is a power of two, so the & operation is a bit mask
+  //   that preserves the lower bits.
+  return (void *)(block + (objectindex & (objectsperblock - 1)) * objectbytes);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// newindex()    Allocate space for a fresh object from the pool.            //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+int tetgenmesh::arraypool::newindex(void **newptr)
+{
+  void *newobject;
+  int newindex;
+
+  // Allocate an object at index 'firstvirgin'.
+  newindex = objects;
+  newobject = (void *) (getblock(objects) +
+    (objects & (objectsperblock - 1)) * objectbytes);
+  objects++;
+
+  // If 'newptr' is not NULL, use it to return a pointer to the object.
+  if (newptr != (void **) NULL) {
+    *newptr = newobject;
+  }
+  return newindex;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// restart()   Deallocate all items in this 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 tetgenmesh::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;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// alloc()   Allocate space for an item.                                     //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void* tetgenmesh::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 **) malloc(itemsperblock * itembytes + sizeof(void *) 
+                                    + alignbytes);
+        if (newblock == (void **) NULL) {
+          printf("Error:  Out of memory.\n");
+          terminatetetgen(1);
+        }
+        *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 *) ((REAL *) 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 tetgenmesh::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 tetgenmesh::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.  It can usually be done more space-efficiently by //
+// a routine that knows something about the structure of the item.           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void* tetgenmesh::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 *) ((REAL *) pathitem + itemwords);
+  }
+  pathitemsleft--;
+  return newitem;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// poolinit()    Initialize a pool of memory for allocation of items.        //
+//                                                                           //
+// A 'pool' is created whose records have size at least 'bytecount'.  Items  //
+// will be allocated 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 `alignment'-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.                  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::memorypool::poolinit(int bytecount, int itemcount,
+  enum wordtype wtype, int alignment)
+{
+  int wordsize;
+
+  // Initialize values in the pool.
+  itemwordtype = wtype;
+  wordsize = (itemwordtype == POINTER) ? sizeof(void *) : sizeof(REAL);
+  // 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 ((int) sizeof(void *) > alignbytes) {
+    alignbytes = (int) 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 **) malloc(itemsperblock * itembytes + sizeof(void *)
+                                + alignbytes); 
+  if (firstblock == (void **) NULL) {
+    printf("Error:  Out of memory.\n");
+    terminatetetgen(1);
+  }
+  // Set the next block pointer to NULL.
+  *(firstblock) = (void *) NULL;
+  restart();
+}
+
+tetgenmesh::memorypool::memorypool(int bytecount, int itemcount,
+  enum wordtype wtype, int alignment)
+{
+  poolinit(bytecount, itemcount, wtype, alignment);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// ~memorypool()   Free to the operating system all memory taken by a pool.  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+tetgenmesh::memorypool::~memorypool()
+{
+  while (firstblock != (void **) NULL) {
+    nowblock = (void **) *(firstblock);
+    free(firstblock);
+    firstblock = nowblock;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// initializepools()    Initialize pools of mesh elements.                   //
+//                                                                           //
+// The sizes of the tetrahedron, shellface, and point will be calculated.    //
+// Some class variables, such as 'pointmarkindex', 'elemmarkindex', 'volume- //
+// boundindex', 'dummypoint', etc, are initialized. The pools of tetrahedra, //
+// points, subfaces, and segments are allocated.                             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::initializepools()
+{
+  enum wordtype wtype;
+  int ptsize, elesize, shsize;
+
+  // A point contains 3 coordinates, 1 weight, plus 'n' attributes in REALs,
+  //   and other fields, such as pointers, boundary markers, etc. The total
+  //   size (in byte) of a point is calcualted below.
+  ptsize = (4 + in->numberofpointattributes) * sizeof(REAL);
+  // The index within each point at which an element pointer is found, where
+  //   the index is measured in pointers. Ensure the index is aligned to a
+  //   sizeof(tetrahedron)-byte address.
+  point2tetindex = (ptsize + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
+  // Increase the point size by two pointers, which are
+  //   - a pointer to a tet, read by point2tet(), or
+  //   - a pointer to a parent point, read by point2ppt().
+  ptsize = (point2tetindex + 2) * sizeof(tetrahedron);
+  // The index within each point at which the boundary marker is found,
+  //   Ensure the marker is aligned to a sizeof(int)-byte address.
+  pointmarkindex = (ptsize + sizeof(int) - 1) / sizeof(int);
+  // Increase the point size by two integers, which are:
+  //   - an integer for boundary marker, read by pointmark();
+  //   - an integer for vertex type, read by pointtype();
+  ptsize = (pointmarkindex + 2) * sizeof(int);
+  // Decide the wordtype used in point pool.
+  wtype = (sizeof(REAL) >= sizeof(tetrahedron)) ? FLOATINGPOINT : POINTER;
+  // Initialize the pool of vertices.
+  pointpool = new memorypool(ptsize, VERPERBLOCK, wtype, 0);
+  
+  // Initialize spaces for 'dummypoint'.
+  dummypoint = new REAL[(ptsize + sizeof(REAL) - 1) / sizeof(REAL)];
+  dummypoint[0] = dummypoint[1] = dummypoint[2] = dummypoint[3] = 0.0;
+  pointmark(dummypoint) = -1;
+
+  // The number of bytes occupied by a tetrahedron.  There are 4 pointers
+  //   to other tetrahedra, 4 pointers to corners, and possibly 1 pointers
+  //   to an array of subfaces/subsegments.
+  elesize = (8 + (b->useshelles ? 2 : 0)) * sizeof(tetrahedron);
+  // The index within each element at which its attributes are found, where
+  //   the index is measured in REALs. 
+  elemattribindex = (elesize + sizeof(REAL) - 1) / sizeof(REAL);
+  // The index within each element at which the maximum voulme bound is
+  //   found, where the index is measured in REALs.  Note that if the
+  //   `b->regionattrib' flag is set, an additional attribute will be added.
+  volumeboundindex = elemattribindex + in->numberoftetrahedronattributes
+                   + (b->regionattrib > 0);
+  // If element attributes or an constraint are needed, increase the number
+  //   of bytes occupied by an element.
+  elesize = (volumeboundindex + (b->varvolume > 0)) * sizeof(REAL);
+  // The index within each element at which its marker is found, where the
+  //   index is measured in ints.
+  elemmarkerindex = (elesize + sizeof(int) - 1) / sizeof(int);
+  // Increase the size by one interger.
+  elesize = (elemmarkerindex + 1) * sizeof(int);
+  // If -o2 switch is used, an additional pointer pointed to the list of
+  //   higher order nodes is allocated for each element.
+  highorderindex = (elesize + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
+  if (b->order == 2) {
+    elesize = (highorderindex + 1) * sizeof(tetrahedron);
+  }
+  // Having determined the memory size of an element, initialize the pools.
+  tetrahedronpool = new memorypool(elesize, ELEPERBLOCK, POINTER, 16);
+
+  if (b->useshelles) {
+    // The number of bytes occupied by a subface.  The list of pointers
+    //   stored in a subface are: three to other subfaces, three to corners,
+    //   three to subsegments, one to an adjacent tetrahedron.
+    shsize = 10 * sizeof(shellface);
+    // The index within each subface at which the maximum area bound is
+    //   found, where the index is measured in REALs.
+    areaboundindex = (shsize + sizeof(REAL) - 1) / sizeof(REAL);
+    // If -q switch is in use, increase the number of bytes occupied by
+    //   a subface for saving maximum area bound.
+    if (b->quality && checkconstraints) {
+      shsize = (areaboundindex + 1) * sizeof(REAL);
+    } else {
+      shsize = areaboundindex * sizeof(REAL);
+    }
+    // The index within subface at which the facet marker is found. Ensure
+    //   the marker is aligned to a sizeof(int)-byte address.
+    shmarkindex = (shsize + sizeof(int) - 1) / sizeof(int);
+    // Increase the number of bytes by two or three integers, one for facet
+    //   marker, one for shellface type, and optionally one for pbc group.
+    shsize = (shmarkindex + 2 + checkpbcs) * sizeof(int);
+    // Initialize the pool of subfaces. Each subface record is eight-byte
+    //   aligned so it has room to store an edge version (from 0 to 5) in
+    //   the least three bits.
+    subfacepool = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
+    // Initialize the pool of subsegments.
+    subsegpool = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
+
+    // Initialize the pool for tet-subseg connections.
+    tet2segpool = new memorypool(6*sizeof(shellface), SUBPERBLOCK, POINTER, 0);
+    // Initialize the pool for tet-subface connections.
+    tet2subpool = new memorypool(4*sizeof(shellface), SUBPERBLOCK, POINTER, 0);
+
+    // Initialize arraypools for segment & facet recovery.
+    subsegstack = new arraypool(sizeof(face), 10);
+    subfacstack = new arraypool(sizeof(face), 10);
+
+    // Initialize arraypools for surface Bowyer-Watson algorithm.
+    caveshlist = new arraypool(sizeof(face), 8);
+    caveshbdlist = new arraypool(sizeof(face), 8);
+  }
+
+  // Initialize the pool for flips.
+  flippool = new memorypool(sizeof(badface), 1024, POINTER, 0);
+
+  // Initialize the arraypools for Bowyer-Watson algorithm.
+  cavetetlist = new arraypool(sizeof(triface), 10);
+  cavebdrylist = new arraypool(sizeof(triface), 10);
+  caveoldtetlist = new arraypool(sizeof(triface), 10);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// tetrahedrondealloc()    Deallocate space for a tet, marking it dead.      //
+//                                                                           //
+// Set the first vertex of 'dyingtet' to NULL. So we can detect dead tets    //
+// when when traversing the list of all tetrahedra.                          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtet)
+{
+  // Mark it as a dead tet.
+  dyingtet[4] = (tetrahedron) NULL;
+
+  if (b->useshelles) {
+    // Dealloc the space to subfaces/subsegments.
+    if (dyingtet[8] != NULL) {
+      tet2segpool->dealloc((shellface *) dyingtet[8]);
+    }
+    if (dyingtet[9] != NULL) {
+      tet2subpool->dealloc((shellface *) dyingtet[9]);
+    }
+  }
+
+  // Actually pool->dealloc();
+  *((void **) (dyingtet)) = tetrahedronpool->deaditemstack;
+  tetrahedronpool->deaditemstack = (void *) (dyingtet);
+  tetrahedronpool->items--;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// tetrahedrontraverse()    Traverse the tetrahedra, skipping dead ones.     //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse()
+{
+  tetrahedron *newtetrahedron;
+
+  // Skip dead and hull tetrahedra.
+  do {
+    newtetrahedron = (tetrahedron *) tetrahedronpool->traverse();
+    if (newtetrahedron == (tetrahedron *) NULL) {
+      return (tetrahedron *) NULL;
+    }
+  } while ((newtetrahedron[4] == (tetrahedron) NULL) ||
+    ((point) newtetrahedron[7] == dummypoint)); 
+  return newtetrahedron;
+}
+
+tetgenmesh::tetrahedron* tetgenmesh::alltetrahedrontraverse()
+{
+  tetrahedron *newtetrahedron;
+
+  do {
+    newtetrahedron = (tetrahedron *) tetrahedronpool->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.  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::shellfacedealloc(memorypool *pool, shellface *dyingsh)
+{
+  dyingsh[3] = (shellface) NULL;
+  pool->dealloc((void *) dyingsh);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// shellfacetraverse()    Traverse the subfaces, skipping dead ones.         //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+tetgenmesh::shellface* tetgenmesh::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;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// badfacedealloc()    Deallocate space for a badface, marking it dead.      //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::badfacedealloc(memorypool *pool, badface *dying)
+{
+  dying->forg = (point) NULL;
+  pool->dealloc((void *) dying);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// badfacetraverse()    Traverse the pools, skipping dead ones.              //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+tetgenmesh::badface* tetgenmesh::badfacetraverse(memorypool *pool)
+{
+  badface *newsh;
+
+  do {
+    newsh = (badface *) pool->traverse();
+    if (newsh == (badface *) NULL) {
+      return (badface *) NULL;
+    }
+  } while (newsh->forg == (point) NULL); // Skip dead ones.
+  return newsh;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// pointdealloc()    Deallocate space for a point, marking it dead.          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::pointdealloc(point dyingpoint)
+{
+  setpointtype(dyingpoint, DEADVERTEX);
+  pointpool->dealloc((void *) dyingpoint);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// pointtraverse()    Traverse the points, skipping dead ones.               //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+tetgenmesh::point tetgenmesh::pointtraverse()
+{
+  point newpoint;
+
+  do {
+    newpoint = (point) pointpool->traverse();
+    if (newpoint == (point) NULL) {
+      return (point) NULL;
+    }
+  } while (getpointtype(newpoint) == DEADVERTEX); // Skip dead ones.
+  return newpoint;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// maketetrahedron()    Create a new tetrahedron.                            //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::maketetrahedron(triface *newtet)
+{
+  int i;
+
+  newtet->tet = (tetrahedron *) tetrahedronpool->alloc();
+  for (i = 0; i < 8; i++) {
+    newtet->tet[i] = (tetrahedron) NULL;
+  }
+  if (b->useshelles) {
+    newtet->tet[8] = (tetrahedron) NULL;
+    newtet->tet[9] = (tetrahedron) NULL;
+  }
+  for (i = 0; i < in->numberoftetrahedronattributes; i++) {
+    setelemattribute(newtet->tet, i, 0);
+  }
+  if (b->varvolume) {
+    setvolumebound(newtet->tet, -1.0);
+  }
+  elemmarker(newtet->tet) = 0;
+  newtet->loc = 0;
+  newtet->ver = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// makeshellface()    Create a new shellface and initialize its data fields. //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::makeshellface(memorypool* pool, face* newsh)
+{
+  int i;
+
+  newsh->sh = (shellface *) pool->alloc();
+  for (i = 0; i < 10; i++) {
+    newsh->sh[i] = (shellface) NULL;
+  }
+  if (checkconstraints) {
+    areabound(*newsh) = 0.0;
+  }
+  // setshelltype(*newsh, NSHARP);
+  // if (checkpbcs) {
+    // setshellpbcgroup(*newsh, -1);
+  // }
+  ((int *) (newsh->sh))[shmarkindex] = 0;
+  // Initialize the version to be Zero.
+  newsh->shver = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// makepoint()    Create a new point.                                        //
+//                                                                           //
+// The new point is indexed (starting from 'in->firstnumber'). It's type is  //
+// initialized as UNUSEDVERTEX.                                              //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::makepoint(point* pnewpt)
+{
+  int i;
+
+  *pnewpt = (point) pointpool->alloc();
+  // Initialize the list of coordinates and user-defined attributes.
+  for (i = 0; i < 4 + in->numberofpointattributes; i++) {
+    (*pnewpt)[i] = 0.0;
+  }
+  // Initialize the point marker (starting from in->firstnumber).
+  pointmark(*pnewpt) = (int) pointpool->items - (in->firstnumber ? 0 : 1);
+  point2tet(*pnewpt) = NULL;
+  setpointtype(*pnewpt, UNUSEDVERTEX);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// makeindex2pointmap()    Make a map from indices to points.                //
+//                                                                           //
+// The first index of the point is 'in->firstnumber' (0 or 1). '*pidx2ptmap' //
+// return this map. NOTE: it is allocated but not deleted in this function.  //
+// The caller has to deleted it.                                             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::makeindex2pointmap(point*& idx2ptmap)
+{
+  point pt;
+  int idx;
+
+  if (b->verbose> 1) {
+    printf("  Making a map from indices to points.\n");
+  }
+
+  idx2ptmap = new point[pointpool->items + 1];
+  pointpool->traversalinit();
+  idx = in->firstnumber;
+  pt = pointtraverse();
+  while (pt != NULL) {
+    idx2ptmap[idx++] = pt;
+    pt = pointtraverse();
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// makesubfacemap()    Create a map from vertex to subfaces incident at it.  //
+//                                                                           //
+// The map is returned in two arrays 'idx2faclist' and 'facperverlist'.  All //
+// subfaces incident at i-th vertex (i is counted from 0) are found in the   //
+// array facperverlist[j], where idx2faclist[i] <= j < idx2faclist[i + 1].   //
+// Each entry in facperverlist[j] is a subface whose origin is the vertex.   //
+//                                                                           //
+// NOTE: These two arrays will be created inside this routine, don't forget  //
+// to free them after using.                                                 //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::makepoint2submap(memorypool* pool, int*& idx2faclist,
+  face*& facperverlist)
+{
+  face shloop;
+  int i, j, k;
+
+  if (b->verbose > 1) {
+    printf("  Making a map from points to subfaces.\n");
+  }
+
+  // Initialize 'idx2faclist'.
+  idx2faclist = new int[pointpool->items + 1];
+  for (i = 0; i < pointpool->items + 1; i++) idx2faclist[i] = 0;
+
+  // Loop all subfaces, counter the number of subfaces incident at a vertex.
+  pool->traversalinit();
+  shloop.sh = shellfacetraverse(pool);
+  while (shloop.sh != (shellface *) NULL) {
+    // Increment the number of incident subfaces for each vertex.
+    j = pointmark((point) shloop.sh[3]) - in->firstnumber;
+    idx2faclist[j]++;
+    j = pointmark((point) shloop.sh[4]) - in->firstnumber;
+    idx2faclist[j]++;
+    // Skip the third corner if it is a segment.
+    if (shloop.sh[5] != NULL) {
+      j = pointmark((point) shloop.sh[5]) - in->firstnumber;
+      idx2faclist[j]++;
+    }
+    shloop.sh = shellfacetraverse(pool);
+  }
+
+  // Calculate the total length of array 'facperverlist'.
+  j = idx2faclist[0];
+  idx2faclist[0] = 0;  // Array starts from 0 element.
+  for (i = 0; i < pointpool->items; i++) {
+    k = idx2faclist[i + 1];
+    idx2faclist[i + 1] = idx2faclist[i] + j;
+    j = k;
+  }
+
+  // The total length is in the last unit of idx2faclist.
+  facperverlist = new face[idx2faclist[i]];
+
+  // Loop all subfaces again, remember the subfaces at each vertex.
+  pool->traversalinit();
+  shloop.sh = shellfacetraverse(pool);
+  while (shloop.sh != (shellface *) NULL) {
+    j = pointmark((point) shloop.sh[3]) - in->firstnumber;
+    shloop.shver = 0; // save the origin.
+    facperverlist[idx2faclist[j]] = shloop;
+    idx2faclist[j]++;
+    // Is it a subface or a subsegment?
+    if (shloop.sh[5] != NULL) {
+      j = pointmark((point) shloop.sh[4]) - in->firstnumber;
+      shloop.shver = 2; // save the origin.
+      facperverlist[idx2faclist[j]] = shloop;
+      idx2faclist[j]++;
+      j = pointmark((point) shloop.sh[5]) - in->firstnumber;
+      shloop.shver = 4; // save the origin.
+      facperverlist[idx2faclist[j]] = shloop;
+      idx2faclist[j]++;
+    } else {
+      j = pointmark((point) shloop.sh[4]) - in->firstnumber;
+      shloop.shver = 1; // save the origin.
+      facperverlist[idx2faclist[j]] = shloop;
+      idx2faclist[j]++;
+    }
+    shloop.sh = shellfacetraverse(pool);
+  }
+
+  // Contents in 'idx2faclist' are shifted, now shift them back.
+  for (i = pointpool->items - 1; i >= 0; i--) {
+    idx2faclist[i + 1] = idx2faclist[i];
+  }
+  idx2faclist[0] = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// makepoint2tetmap()    Make a map from points to tetrahedra.               //
+//                                                                           //
+// Traverses all the tetrahedra,  provides each corner of each tetrahedron   //
+// with a pointer to that tetrahedera.  Some pointers will be overwritten by //
+// other pointers because each point may be a corner of several tetrahedra,  //
+// but in the end every point will point to a tetrahedron that contains it.  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::makepoint2tetmap()
+{
+  tetrahedron *tptr;
+  point *pt;
+
+  if (b->verbose > 1) {
+    printf("  Making a map from points to tetrahedra.\n");
+  }
+
+  tetrahedronpool->traversalinit();
+  tptr = tetrahedrontraverse();
+  while (tptr != (tetrahedron *) NULL) {
+    pt  = (point *) tptr;
+    point2tet(pt[4]) = (tetrahedron) tptr;
+    point2tet(pt[5]) = (tetrahedron) tptr;
+    point2tet(pt[6]) = (tetrahedron) tptr;
+    point2tet(pt[7]) = (tetrahedron) tptr;
+    tptr = tetrahedrontraverse();
+  }
+}
+
+#endif // #ifndef memorypoolCXX
\ No newline at end of file
diff --git a/contrib/Tetgen/meshio.cxx b/contrib/Tetgen/meshio.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c3258a2f9a45cd5a4b1c4e42470a902bdbade0d6
--- /dev/null
+++ b/contrib/Tetgen/meshio.cxx
@@ -0,0 +1,1237 @@
+#ifndef meshioCXX
+#define meshioCXX
+
+#include "tetgen.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// transfernodes()    Transfer points from 'in->pointlist' to 'pointpool'.   //
+//                                                                           //
+// While transfering the points, the size of the bounding box (xmax, ....,   //
+// zmin) is caclulated.                                                      //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::transfernodes()
+{
+  point pointloop;
+  REAL x, y, z;
+  int coordindex;
+  int attribindex;
+  int i, j;
+
+  // Read the points.
+  coordindex = 0;
+  attribindex = 0;
+  for (i = 0; i < in->numberofpoints; i++) {
+    makepoint(&pointloop);
+    // Read the point coordinates.
+    x = pointloop[0] = in->pointlist[coordindex++];
+    y = pointloop[1] = in->pointlist[coordindex++];
+    z = pointloop[2] = in->pointlist[coordindex++];
+    // Read the point attributes.
+    for (j = 0; j < in->numberofpointattributes; j++) {
+      pointloop[4 + j] = in->pointattributelist[attribindex++];
+    }
+    // Determine the smallest and largests x, y and z 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 < zmin) ? z : zmin;
+      zmax = (z > zmax) ? z : zmax;
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// jettisonnodes()    Jettison unused or duplicated vertices.                //
+//                                                                           //
+// Unused points are those input points which are outside the mesh domain or //
+// have no connection (isolated) to the mesh.  Duplicated points exist for   //
+// example if the input PLC is read from a .stl mesh file (marked during the //
+// Delaunay tetrahedralization step. This routine remove these points from   //
+// points list. All existing points are reindexed.                           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::jettisonnodes()
+{
+  point pointloop;
+  bool jetflag;
+  int oldidx, newidx;
+  int remcount;
+
+  if (!b->quiet) {
+    printf("Jettisoning redundants points.\n");
+  }
+
+  pointpool->traversalinit();
+  pointloop = pointtraverse();
+  oldidx = newidx = 0; // in->firstnumber;
+  remcount = 0;
+  while (pointloop != (point) NULL) {
+    jetflag = (getpointtype(pointloop) == DUPLICATEDVERTEX) || 
+      (getpointtype(pointloop) == UNUSEDVERTEX);
+    jetflag = (getpointtype(pointloop) == DUPLICATEDVERTEX);
+    if (jetflag) {
+      // It is a duplicated point, delete it.
+      pointdealloc(pointloop);
+      remcount++;
+    } else {
+      // Re-index it.
+      pointmark(pointloop) = newidx + in->firstnumber;
+      if (in->pointmarkerlist != (int *) NULL) {
+        if (oldidx < in->numberofpoints) {
+          // Re-index the point marker as well.
+          in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
+        }
+      }
+      newidx++;
+    }
+    oldidx++;
+    if (oldidx == in->numberofpoints) {
+      // Update the numbe of input points (Because some were removed).
+      in->numberofpoints -= remcount;
+      // Remember this number for output original input nodes.
+      // jettisoninverts = remcount;
+    }
+    pointloop = pointtraverse();
+  }
+  if (b->verbose) {
+    printf("  %d duplicated vertices have been removed.\n", dupverts);
+    // printf("  %d unused vertices have been removed.\n", unuverts);
+  }
+  dupverts = 0; 
+  // unuverts = 0;
+
+  // The following line ensures that dead items in the pool of nodes cannot
+  //   be allocated for the new created nodes. This ensures that the input
+  //   nodes will occur earlier in the output files, and have lower indices.
+  pointpool->deaditemstack = (void *) NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// numberedges()    Count the number of mesh edges (in 'meshedges').         //
+//                                                                           //
+// The edges will be automatically counted in routine 'outelements()'.  This //
+// routine is needed only -E option is used.                                 //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::numberedges()
+{
+  triface worktet, spintet;
+  int i;
+
+  meshedges = 0l;
+  tetrahedronpool->traversalinit();
+  worktet.tet = tetrahedrontraverse();
+  while (worktet.tet != NULL) {
+    // Count the number of Voronoi faces. Look at the six edges of this
+    //   tet. Count an edge only if this tet's pointer is smaller than
+    //   those of other non-hull tets which share this edge.
+    for (i = 0; i < 6; i++) {
+      worktet.loc = edge2locver[i][0];
+      worktet.ver = edge2locver[i][1];
+      fnext(worktet, spintet);
+      do {
+        if ((point) spintet.tet[7] != dummypoint) {
+          if (spintet.tet < worktet.tet) break;
+        }
+        fnextself(spintet);
+      } while (spintet.tet != worktet.tet);
+      // Count this edge if no adjacent tets are smaller than this tet.
+      if (spintet.tet == worktet.tet) {
+        meshedges++;
+      }
+    }
+    worktet.tet = tetrahedrontraverse();
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// numbersubedges()    Count the number of boundary mesh edges (in           //
+//                     'meshsubedges').                                      //
+//                                                                           //
+// The number of boundary edges will be automatically counted in routine     //
+// 'outsubfaces()'.  This routine is needed only -F option is used.          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::numbersubedges()
+{
+  face faceloop, spinsh;
+  int i;
+
+  shellface sptr;
+
+  meshsubedges = 0l;
+  subfacepool->traversalinit();
+  faceloop.sh = shellfacetraverse(subfacepool);
+  while (faceloop.sh != NULL) {
+    // Count the number of boundary edges. Look at all subfaces sharing at 
+    //   this edge. Count it only if this subface's pointer is the smallest.
+    faceloop.shver = 0;
+    for (i = 0; i < 3; i++) {
+      spivot(faceloop, spinsh);
+      if (spinsh.sh != NULL) {
+        while (spinsh.sh != faceloop.sh) {
+          if ((unsigned long) spinsh.sh < (unsigned long) faceloop.sh) break;
+          spivotself(spinsh);
+        }
+        if (spinsh.sh == faceloop.sh) {
+          meshsubedges++;
+        }
+      } else {
+        meshsubedges++;
+      }
+      senextself(faceloop);
+    }
+    faceloop.sh = shellfacetraverse(subfacepool);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// outnodes()    Output the points to a .node file or a tetgenio structure.  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::outnodes(tetgenio* out)
+{
+  FILE *outfile;
+  char outnodefilename[FILENAMESIZE];
+  point pointloop;
+  int nextras, bmark, marker;
+  int coordindex, attribindex;
+  int pointnumber, firstindex;
+  int index, i;
+  
+  if (out == (tetgenio *) NULL) {
+    strcpy(outnodefilename, b->outfilename);
+    strcat(outnodefilename, ".node");
+  }
+  
+  if (!b->quiet) {
+    if (out == (tetgenio *) NULL) {
+      printf("Writing %s.\n", outnodefilename);
+    } else {
+      printf("Writing nodes.\n");
+    }
+  }
+
+  nextras = in->numberofpointattributes;
+  bmark = !b->nobound && in->pointmarkerlist;
+
+  if (out == (tetgenio *) NULL) {
+    outfile = fopen(outnodefilename, "w");
+    if (outfile == (FILE *) NULL) {
+      printf("File I/O Error:  Cannot create file %s.\n", outnodefilename);
+      terminatetetgen(1);
+    }
+    // Number of pointpool, number of dimensions, number of point attributes,
+    //   and number of boundary markers (zero or one).
+    fprintf(outfile, "%ld  %d  %d  %d\n", pointpool->items, 3, nextras, bmark);
+  } else {
+    // Allocate space for 'pointlist';
+    out->pointlist = new REAL[pointpool->items * 3];
+    if (out->pointlist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      terminatetetgen(1);
+    }
+    // Allocate space for 'pointattributelist' if necessary;
+    if (nextras > 0) {
+      out->pointattributelist = new REAL[pointpool->items * nextras];
+      if (out->pointattributelist == (REAL *) NULL) {
+        printf("Error:  Out of memory.\n");
+        terminatetetgen(1);
+      }
+    }
+    // Allocate space for 'pointmarkerlist' if necessary;
+    if (bmark) {
+      out->pointmarkerlist = new int[pointpool->items];
+      if (out->pointmarkerlist == (int *) NULL) {
+        printf("Error:  Out of memory.\n");
+        terminatetetgen(1);
+      }
+    }
+    out->numberofpoints = pointpool->items;
+    out->numberofpointattributes = nextras;
+    coordindex = 0;
+    attribindex = 0;
+  }
+  
+  // Determine the first index (0 or 1).
+  firstindex = b->zeroindex ? 0 : in->firstnumber;
+
+  pointpool->traversalinit();
+  pointloop = pointtraverse();
+  pointnumber = firstindex; // in->firstnumber;
+  index = 0;
+  while (pointloop != (point) NULL) {
+    if (bmark) {
+      // Default the vertex has a zero marker.
+      marker = 0;
+      // Is it an input vertex?
+      if (index < in->numberofpoints) {
+        // Input point's marker is directly copied to output.
+        marker = in->pointmarkerlist[index];
+      }
+    }
+    if (out == (tetgenio *) 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[4 + i]);
+      }
+      if (bmark) {
+        // Write the boundary marker.
+        fprintf(outfile, "    %d", marker);
+      }
+      fprintf(outfile, "\n");
+    } else {
+      // X, y, and z coordinates.
+      out->pointlist[coordindex++] = pointloop[0];
+      out->pointlist[coordindex++] = pointloop[1];
+      out->pointlist[coordindex++] = pointloop[2];
+      // Point attributes.
+      for (i = 0; i < nextras; i++) {
+        // Output an attribute.
+        out->pointattributelist[attribindex++] = pointloop[4 + i];
+      }
+      if (bmark) {
+        // Output the boundary marker.  
+        out->pointmarkerlist[index] = marker;
+      }
+    }
+    pointloop = pointtraverse();
+    pointnumber++; 
+    index++;
+  }
+
+  if (out == (tetgenio *) NULL) {
+    fprintf(outfile, "# Generated by %s\n", b->commandline);
+    fclose(outfile);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// outelements()    Output tetrahedra to an .ele file or a tetgenio object.  //
+//                                                                           //
+// The total number of mesh edges 'meshedges' (the number of Voronoi faces)  //
+// are counted in this function.                                             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::outelements(tetgenio* out)
+{
+  FILE *outfile;
+  char outelefilename[FILENAMESIZE];
+  tetrahedron* tptr;
+  triface worktet, spintet;
+  point p1, p2, p3, p4;
+  point *extralist;
+  REAL *talist;
+  int *tlist;
+  long ntets;
+  int firstindex, shift;
+  int pointindex, attribindex;
+  int elementnumber;
+  int eextras;
+  int i;
+
+  if (out == (tetgenio *) NULL) {
+    strcpy(outelefilename, b->outfilename);
+    strcat(outelefilename, ".ele");
+  }
+
+  if (!b->quiet) {
+    if (out == (tetgenio *) NULL) {
+      printf("Writing %s.\n", outelefilename);
+    } else {
+      printf("Writing elements.\n");
+    }
+  }
+
+  // The number of tets excluding hull tets.
+  ntets = tetrahedronpool->items - hullsize;
+
+  eextras = in->numberoftetrahedronattributes;
+  if (out == (tetgenio *) NULL) {
+    outfile = fopen(outelefilename, "w");
+    if (outfile == (FILE *) NULL) {
+      printf("File I/O Error:  Cannot create file %s.\n", outelefilename);
+      terminatetetgen(1);
+    }
+    // Number of tetras, points per tetra, attributes per tetra.
+    fprintf(outfile, "%ld  %d  %d\n", ntets, b->order == 1 ? 4 : 10, eextras);
+  } else {
+    // Allocate memory for output tetrahedra.
+    out->tetrahedronlist = new int[ntets * (b->order == 1 ? 4 : 10)];
+    if (out->tetrahedronlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      terminatetetgen(1);
+    }
+    // Allocate memory for output tetrahedron attributes if necessary.
+    if (eextras > 0) {
+      out->tetrahedronattributelist = new REAL[ntets * eextras];
+      if (out->tetrahedronattributelist == (REAL *) NULL) {
+        printf("Error:  Out of memory.\n");
+        terminatetetgen(1);
+      }
+    }
+    out->numberoftetrahedra = ntets;
+    out->numberofcorners = b->order == 1 ? 4 : 10;
+    out->numberoftetrahedronattributes = eextras;
+    tlist = out->tetrahedronlist;
+    talist = out->tetrahedronattributelist;
+    pointindex = 0;
+    attribindex = 0;
+  }
+
+  // Determine the first index (0 or 1).
+  firstindex = b->zeroindex ? 0 : in->firstnumber;
+  shift = 0; // Default no shiftment.
+  if ((in->firstnumber == 1) && (firstindex == 0)) {
+    shift = 1; // Shift the output indices by 1.
+  }
+
+  // Count the total edge numbers.
+  meshedges = 0l;
+
+  tetrahedronpool->traversalinit();
+  tptr = tetrahedrontraverse();
+  elementnumber = firstindex; // in->firstnumber;
+  while (tptr != (tetrahedron *) NULL) {
+    // Reverse the orientation so that Orient3D() > 0.
+    p1 = (point) tptr[5];
+    p2 = (point) tptr[4];
+    p3 = (point) tptr[6];
+    p4 = (point) tptr[7];
+    if (out == (tetgenio *) NULL) {
+      // Tetrahedron number, indices for four points.
+      fprintf(outfile, "%5d   %5d %5d %5d %5d", elementnumber,
+              pointmark(p1) - shift, pointmark(p2) - shift,
+              pointmark(p3) - shift, pointmark(p4) - shift);
+      if (b->order == 2) {
+        extralist = (point *) tptr[highorderindex];
+        // Tetrahedron number, indices for four points plus six extra points.
+        fprintf(outfile, "  %5d %5d %5d %5d %5d %5d",
+          pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
+          pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
+          pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
+      }
+      for (i = 0; i < eextras; i++) {
+        fprintf(outfile, "    %.17g", elemattribute(tptr, i));
+      }
+      fprintf(outfile, "\n");
+    } else {
+      tlist[pointindex++] = pointmark(p1) - shift;
+      tlist[pointindex++] = pointmark(p2) - shift;
+      tlist[pointindex++] = pointmark(p3) - shift;
+      tlist[pointindex++] = pointmark(p4) - shift;
+      if (b->order == 2) {
+        extralist = (point *) tptr[highorderindex];
+        tlist[pointindex++] = pointmark(extralist[0]) - shift;
+        tlist[pointindex++] = pointmark(extralist[1]) - shift;
+        tlist[pointindex++] = pointmark(extralist[2]) - shift;
+        tlist[pointindex++] = pointmark(extralist[3]) - shift;
+        tlist[pointindex++] = pointmark(extralist[4]) - shift;
+        tlist[pointindex++] = pointmark(extralist[5]) - shift;
+      }
+      for (i = 0; i < eextras; i++) {
+        talist[attribindex++] = elemattribute(tptr, i);
+      }
+    }
+    if (b->neighout) {
+      // Remember the index of this element.
+      * (int *) (tptr + elemmarkerindex) = elementnumber;
+    }
+    // Count the number of Voronoi faces. Look at the six edges of this
+    //   tet. Count an edge only if this tet's pointer is smaller than
+    //   those of other non-hull tets which share this edge.
+    worktet.tet = tptr;
+    for (i = 0; i < 6; i++) {
+      worktet.loc = edge2locver[i][0];
+      worktet.ver = edge2locver[i][1];
+      fnext(worktet, spintet);
+      do {
+        if ((point) spintet.tet[7] != dummypoint) {
+          if (spintet.tet < worktet.tet) break;
+        }
+        fnextself(spintet);
+      } while (spintet.tet != worktet.tet);
+      // Count this edge if no adjacent tets are smaller than this tet.
+      if (spintet.tet == worktet.tet) {
+        meshedges++;
+      }
+    }
+    tptr = tetrahedrontraverse();
+    elementnumber++;
+  }
+
+  if (out == (tetgenio *) NULL) {
+    fprintf(outfile, "# Generated by %s\n", b->commandline);
+    fclose(outfile);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// outfaces()    Output all faces to a .face file or a tetgenio object.      //
+//                                                                           //
+// The total number of faces f can be calculated as following:  Let t be the //
+// total number of tets. Since each tet has 4 faces, the number t * 4 counts //
+// each interior face twice and each hull face once. So f = (t * 4 + h) / 2, //
+// where h is the total number of hull faces (which is known).               //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::outfaces(tetgenio* out)
+{
+  FILE *outfile;
+  char facefilename[FILENAMESIZE];
+  triface tface, tsymface;
+  face checkmark;
+  point torg, tdest, tapex;
+  long ntets, faces;
+  int *elist, *emlist;
+  int neigh1, neigh2;
+  int bmark, faceid, marker;
+  int firstindex, shift;
+  int facenumber;
+  int index;
+
+  if (out == (tetgenio *) NULL) {
+    strcpy(facefilename, b->outfilename);
+    strcat(facefilename, ".face");
+  }
+
+  if (!b->quiet) {
+    if (out == (tetgenio *) NULL) {
+      printf("Writing %s.\n", facefilename);
+    } else {
+      printf("Writing faces.\n");
+    }
+  }
+
+  ntets = tetrahedronpool->items - hullsize;
+  faces = (ntets * 4l + hullsize) / 2l;
+  bmark = !b->nobound && in->facetmarkerlist;
+
+  if (out == (tetgenio *) NULL) {
+    outfile = fopen(facefilename, "w");
+    if (outfile == (FILE *) NULL) {
+      printf("File I/O Error:  Cannot create file %s.\n", facefilename);
+      terminatetetgen(1);
+    }
+    fprintf(outfile, "%ld  %d\n", faces, bmark);
+  } else {
+    // Allocate memory for 'trifacelist'.
+    out->trifacelist = new int[faces * 3];
+    if (out->trifacelist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      terminatetetgen(1);
+    }
+    // Allocate memory for 'trifacemarkerlist' if necessary.
+    if (bmark) {
+      out->trifacemarkerlist = new int[faces];
+      if (out->trifacemarkerlist == (int *) NULL) {
+        printf("Error:  Out of memory.\n");
+        terminatetetgen(1);
+      }
+    }
+    if (b->neighout > 1) {
+      // '-nn' switch.
+      out->adjtetlist = new int[faces * 2];
+      if (out->adjtetlist == (int *) NULL) {
+        printf("Error:  Out of memory.\n");
+        terminatetetgen(1);
+      }
+    }
+    out->numberoftrifaces = faces;
+    elist = out->trifacelist;
+    emlist = out->trifacemarkerlist;
+    index = 0;
+  }
+
+  // Determine the first index (0 or 1).
+  firstindex = b->zeroindex ? 0 : in->firstnumber;
+  shift = 0; // Default no shiftment.
+  if ((in->firstnumber == 1) && (firstindex == 0)) {
+    shift = 1; // Shift the output indices by 1.
+  }
+
+  tetrahedronpool->traversalinit();
+  tface.tet = tetrahedrontraverse();
+  facenumber = firstindex; // in->firstnumber;
+  // To loop over the set of faces, loop over all tetrahedra, and look at
+  //   the four faces of each one. If its adjacent tet is a hull tet,
+  //   operate on the face, otherwise, operate on the face only if the
+  //   current tet has a smaller pointer than its neighbor.
+  while (tface.tet != (tetrahedron *) NULL) {
+    for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
+      sym(tface, tsymface);
+      if (((point) tsymface.tet[7] == dummypoint) || 
+          (tface.tet < tsymface.tet)) {
+        torg = org(tface);
+        tdest = dest(tface);
+        tapex = apex(tface);
+        if (bmark) {
+          // Get the boundary marker of this face. If it is an inner face,
+          //   it has no boundary marker, set it be zero.
+          if (b->useshelles) {
+            // Shell face is used.
+            // tspivot(tface, checkmark);
+            if (checkmark.sh == NULL) {
+              marker = 0;  // It is an inner face.
+            } else {
+              faceid = getshellmark(checkmark) - 1;
+              marker = in->facetmarkerlist[faceid];
+            }
+          } else {
+            // Shell face is not used, only distinguish outer and inner face.
+            marker = tsymface.tet != NULL ? 1 : 0;
+          }
+        }
+        if (b->neighout > 1) {
+          // '-nn' switch. Output adjacent tets indices.
+          neigh1 = * (int *)(tface.tet + elemmarkerindex);
+          if (tsymface.tet != NULL) {
+            neigh2 = * (int *)(tsymface.tet + elemmarkerindex);
+          } else {
+            neigh2 = -1;  
+          }
+        }
+        if (out == (tetgenio *) NULL) {
+          // Face number, indices of three vertices.
+          fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
+                  pointmark(torg) - shift, pointmark(tdest) - shift,
+                  pointmark(tapex) - shift);
+          if (bmark) {
+            // Output a boundary marker.
+            fprintf(outfile, "  %d", marker);
+          }
+          if (b->neighout > 1) {
+            fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
+          }
+          fprintf(outfile, "\n");
+        } else {
+          // Output indices of three vertices.
+          elist[index++] = pointmark(torg) - shift;
+          elist[index++] = pointmark(tdest) - shift;
+          elist[index++] = pointmark(tapex) - shift;
+          if (bmark) {
+            emlist[facenumber - in->firstnumber] = marker;
+          }
+          if (b->neighout > 1) {
+            out->adjtetlist[(facenumber - in->firstnumber) * 2]     = neigh1;
+            out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
+          }
+        }
+        facenumber++;
+      }
+    }
+    tface.tet = tetrahedrontraverse();
+  }
+
+  if (out == (tetgenio *) NULL) {
+    fprintf(outfile, "# Generated by %s\n", b->commandline);
+    fclose(outfile);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// outhullfaces()    Output hull faces to a .face file or a tetgenio object. //
+//                                                                           //
+// The normal of each face is pointing to the outside of the domain.         //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::outhullfaces(tetgenio* out)
+{
+  FILE *outfile;
+  char facefilename[FILENAMESIZE];
+  triface hulltet;
+  point torg, tdest, tapex;
+  int *elist;
+  int firstindex, shift;
+  int facenumber;
+  int index;
+
+  if (out == (tetgenio *) NULL) {
+    strcpy(facefilename, b->outfilename);
+    strcat(facefilename, ".face");
+  }
+
+  if (!b->quiet) {
+    if (out == (tetgenio *) NULL) {
+      printf("Writing %s.\n", facefilename);
+    } else {
+      printf("Writing faces.\n");
+    }
+  }
+
+  if (out == (tetgenio *) NULL) {
+    outfile = fopen(facefilename, "w");
+    if (outfile == (FILE *) NULL) {
+      printf("File I/O Error:  Cannot create file %s.\n", facefilename);
+      terminatetetgen(1);
+    }
+    fprintf(outfile, "%ld  0\n", hullsize);
+  } else {
+    // Allocate memory for 'trifacelist'.
+    out->trifacelist = new int[hullsize * 3];
+    if (out->trifacelist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      terminatetetgen(1);
+    }
+    out->numberoftrifaces = hullsize;
+    elist = out->trifacelist;
+    index = 0;
+  }
+
+  // Determine the first index (0 or 1).
+  firstindex = b->zeroindex ? 0 : in->firstnumber;
+  shift = 0; // Default no shiftment.
+  if ((in->firstnumber == 1) && (firstindex == 0)) {
+    shift = 1; // Shift the output indices by 1.
+  }
+
+  tetrahedronpool->traversalinit();
+  hulltet.tet = alltetrahedrontraverse();
+  facenumber = firstindex;
+  while (hulltet.tet != (tetrahedron *) NULL) {
+    if ((point) hulltet.tet[7] == dummypoint) {
+      torg = (point) hulltet.tet[4];
+      tdest = (point) hulltet.tet[5];
+      tapex = (point) hulltet.tet[6];
+      if (out == (tetgenio *) NULL) {
+        // Face number, indices of three vertices.
+        fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
+          pointmark(torg) - shift, pointmark(tdest) - shift,
+          pointmark(tapex) - shift);
+        fprintf(outfile, "\n");
+      } else {
+        // Output indices of three vertices.
+        elist[index++] = pointmark(torg) - shift;
+        elist[index++] = pointmark(tdest) - shift;
+        elist[index++] = pointmark(tapex) - shift;
+      }
+      facenumber++;
+    }
+    hulltet.tet = alltetrahedrontraverse();
+  }
+  
+  if (out == (tetgenio *) NULL) {
+    fprintf(outfile, "# Generated by %s\n", b->commandline);
+    fclose(outfile);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// outsubfaces()    Output subfaces to a .face file or a tetgenio object.    //
+//                                                                           //
+// The number of mesh boundary edges ('meshsubedges') will be counted.       //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::outsubfaces(tetgenio* out)
+{
+  FILE *outfile;
+  char facefilename[FILENAMESIZE];
+  int *elist;
+  int *emlist;
+  int index, index1=0, index2=0;
+  triface abuttingtet;
+  face faceloop, spinsh;
+  point torg, tdest, tapex;
+  int bmark, faceid, marker;
+  int firstindex, shift;
+  int neigh1, neigh2;
+  int facenumber, i;
+
+  shellface sptr;
+
+  if (out == (tetgenio *) NULL) {
+    strcpy(facefilename, b->outfilename);
+    strcat(facefilename, ".face");
+  }
+
+  if (!b->quiet) {
+    if (out == (tetgenio *) NULL) {
+      printf("Writing %s.\n", facefilename);
+    } else {
+      printf("Writing faces.\n");
+    }
+  }
+
+  bmark = !b->nobound && in->facetmarkerlist;
+
+  if (out == (tetgenio *) NULL) {
+    outfile = fopen(facefilename, "w");
+    if (outfile == (FILE *) NULL) {
+      printf("File I/O Error:  Cannot create file %s.\n", facefilename);
+      terminatetetgen(1);
+    }
+    // Number of subfaces.
+    fprintf(outfile, "%ld  %d\n", subfacepool->items, bmark);
+  } else {
+    // Allocate memory for 'trifacelist'.
+    out->trifacelist = new int[subfacepool->items * 3];
+    if (out->trifacelist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      terminatetetgen(1);
+    }
+    if (bmark) {
+      // Allocate memory for 'trifacemarkerlist'.
+      out->trifacemarkerlist = new int[subfacepool->items];
+      if (out->trifacemarkerlist == (int *) NULL) {
+        printf("Error:  Out of memory.\n");
+        terminatetetgen(1);
+      }
+    }
+    if (b->neighout > 1) {
+      // '-nn' switch.
+      out->adjtetlist = new int[subfacepool->items * 2];
+      if (out->adjtetlist == (int *) NULL) {
+        printf("Error:  Out of memory.\n");
+        terminatetetgen(1);
+      }
+    }
+    out->numberoftrifaces = subfacepool->items;
+    elist = out->trifacelist;
+    emlist = out->trifacemarkerlist;
+  }
+
+  // Determine the first index (0 or 1).
+  firstindex = b->zeroindex ? 0 : in->firstnumber;
+  shift = 0; // Default no shiftment.
+  if ((in->firstnumber == 1) && (firstindex == 0)) {
+    shift = 1; // Shift the output indices by 1.
+  }
+
+  meshsubedges = 0l;
+
+  subfacepool->traversalinit();
+  faceloop.sh = shellfacetraverse(subfacepool);
+  facenumber = firstindex; // in->firstnumber;
+  while (faceloop.sh != (shellface *) NULL) {
+    abuttingtet.tet = NULL; // stpivot(faceloop, abuttingtet);
+    if (abuttingtet.tet != NULL) {
+      // There is a tetrahedron containing this subface, orient it.
+      abuttingtet.ver = 0;
+      torg = org(abuttingtet);
+      tdest = dest(abuttingtet);
+      tapex = apex(abuttingtet);
+    } else {
+      // This may happen when only a surface mesh be generated.
+      torg = sorg(faceloop);
+      tdest = sdest(faceloop);
+      tapex = sapex(faceloop);
+    }
+    if (bmark) {
+      faceid = getshellmark(faceloop) - 1;
+      marker = in->facetmarkerlist[faceid];
+    }
+    if (b->neighout > 1) {
+      // '-nn' switch. Output adjacent tets indices.
+      neigh1 = -1;
+      // stpivot(faceloop, abuttingtet);
+      if (abuttingtet.tet != NULL) {
+        neigh1 = * (int *)(abuttingtet.tet + elemmarkerindex);
+      }
+      neigh2 = -1;
+      sesymself(faceloop);
+      // stpivot(faceloop, abuttingtet);
+      if (abuttingtet.tet != NULL) {
+        neigh2 = * (int *)(abuttingtet.tet + elemmarkerindex);
+      }
+    }
+    if (out == (tetgenio *) NULL) {
+      fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
+              pointmark(torg) - shift, pointmark(tdest) - shift,
+              pointmark(tapex) - shift);
+      if (bmark) {
+        fprintf(outfile, "    %d", marker);
+      }
+      if (b->neighout > 1) {
+        fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
+      }
+      fprintf(outfile, "\n");
+    } else {
+      // Output three vertices of this face;
+      elist[index++] = pointmark(torg) - shift;
+      elist[index++] = pointmark(tdest) - shift;
+      elist[index++] = pointmark(tapex) - shift;
+      if (bmark) {
+        emlist[index1++] = marker;
+      }
+      if (b->neighout > 1) {
+        out->adjtetlist[index2++] = neigh1;
+        out->adjtetlist[index2++] = neigh2;
+      }
+    }
+    // Count the number of boundary edges. Look at all subfaces sharing at 
+    //   this edge. Count it only if this subface's pointer is the smallest.
+    faceloop.shver = 0;
+    for (i = 0; i < 3; i++) {
+      spivot(faceloop, spinsh);
+      if (spinsh.sh != NULL) {
+        while (spinsh.sh != faceloop.sh) {
+          if ((unsigned long) spinsh.sh < (unsigned long) faceloop.sh) break;
+          spivotself(spinsh);
+        }
+        if (spinsh.sh == faceloop.sh) {
+          meshsubedges++;
+        }
+      } else {
+        meshsubedges++;
+      }
+      senextself(faceloop);
+    }
+    facenumber++;
+    faceloop.sh = shellfacetraverse(subfacepool);
+  }
+
+  if (out == (tetgenio *) NULL) {
+    fprintf(outfile, "# Generated by %s\n", b->commandline);
+    fclose(outfile);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// outedges()    Output all edges to a .edge file or a tetgenio object.      //
+//                                                                           //
+// Note: This routine must be called after outelements(),  so that the total //
+// number of edges 'meshedges' has been counted.                             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::outedges(tetgenio* out)
+{
+  FILE *outfile;
+  char edgefilename[FILENAMESIZE];
+  triface tetloop, worktet, spintet;
+  point torg, tdest;
+  int *elist, *emlist;
+  int firstindex, shift;
+  int edgenumber;
+  int index;
+  int i;
+
+  if (out == (tetgenio *) NULL) {
+    strcpy(edgefilename, b->outfilename);
+    strcat(edgefilename, ".edge");
+  }
+
+  if (!b->quiet) {
+    if (out == (tetgenio *) NULL) {
+      printf("Writing %s.\n", edgefilename);
+    } else {
+      printf("Writing edges.\n");
+    }
+  }
+
+  if (out == (tetgenio *) NULL) {
+    outfile = fopen(edgefilename, "w");
+    if (outfile == (FILE *) NULL) {
+      printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
+      terminatetetgen(1);
+    }
+    // Write the number of edges, boundary markers (0 or 1).
+    fprintf(outfile, "%ld  %d\n", meshedges, !b->nobound);
+  } else {
+    // Allocate memory for 'edgelist'.
+    out->edgelist = new int[meshedges * 2];
+    if (out->edgelist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      terminatetetgen(1);
+    }
+    if (!b->nobound) {
+      out->edgemarkerlist = new int[meshedges];
+    }
+    out->numberofedges = meshedges;
+    elist = out->edgelist;
+    emlist = out->edgemarkerlist;
+    index = 0;
+  }
+
+  // Determine the first index (0 or 1).
+  firstindex = b->zeroindex ? 0 : in->firstnumber;
+  shift = 0; // Default no shiftment.
+  if ((in->firstnumber == 1) && (firstindex == 0)) {
+    shift = 1; // Shift (reduce) the output indices by 1.
+  }
+
+  tetrahedronpool->traversalinit();
+  tetloop.tet = tetrahedrontraverse();
+  edgenumber = firstindex; // in->firstnumber;
+  while (tetloop.tet != (tetrahedron *) NULL) {
+    // Count the number of Voronoi faces. Look at the six edges of this
+    //   tet. Count an edge only if this tet's pointer is smaller than
+    //   those of other non-hull tets which share this edge.
+    worktet.tet = tetloop.tet;
+    for (i = 0; i < 6; i++) {
+      worktet.loc = edge2locver[i][0];
+      worktet.ver = edge2locver[i][1];
+      fnext(worktet, spintet);
+      do {
+        if ((point) spintet.tet[7] != dummypoint) {
+          if (spintet.tet < worktet.tet) break;
+        }
+        fnextself(spintet);
+      } while (spintet.tet != worktet.tet);
+      // Count this edge if no adjacent tets are smaller than this tet.
+      if (spintet.tet == worktet.tet) {
+        torg = org(worktet);
+        tdest = dest(worktet);
+        if (out == (tetgenio *) NULL) {
+          fprintf(outfile, "%5d   %4d  %4d", edgenumber,
+                  pointmark(torg) - shift, pointmark(tdest) - shift);
+        } else {
+          // Output three vertices of this face;
+          elist[index++] = pointmark(torg) - shift;
+          elist[index++] = pointmark(tdest) - shift;
+        }
+        /*
+        if (!b->nobound) {
+          // Check if the edge is a segment.
+          tsspivot(&worktet, &checkseg);
+          if (checkseg.sh != dummysh) {
+            marker = shellmark(checkseg);
+            if (marker == 0) {  // Does it have no marker?
+              marker = 1;  // Set the default marker for this segment.
+            }
+          } else {
+            marker = 0;  // It's not a segment.
+          }
+          if (out == (tetgenio *) NULL) {
+            fprintf(outfile, "  %d", marker);
+          } else {
+            emlist[index1++] = marker;
+          }
+        }
+        */
+        if (out == (tetgenio *) NULL) {
+          fprintf(outfile, "\n");
+        }
+        edgenumber++;
+      }
+    }
+    tetloop.tet = tetrahedrontraverse();
+  }
+
+  if (out == (tetgenio *) NULL) {
+    fprintf(outfile, "# Generated by %s\n", b->commandline);
+    fclose(outfile);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// outsubsegments()    Output subsegments into an .edge file or an object.   //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::outsubsegments(tetgenio* out)
+{
+  FILE *outfile;
+  char edgefilename[FILENAMESIZE];
+  int *elist;
+  int index;
+  face edgeloop;
+  point torg, tdest;
+  int firstindex, shift;
+  int edgenumber;
+
+  if (out == (tetgenio *) NULL) {
+    strcpy(edgefilename, b->outfilename);
+    strcat(edgefilename, ".edge");
+  }
+
+  if (!b->quiet) {
+    if (out == (tetgenio *) NULL) {
+      printf("Writing %s.\n", edgefilename);
+    } else {
+      printf("Writing edges.\n");
+    }
+  }
+
+  // Avoid compile warnings.
+  outfile = (FILE *) NULL;
+  elist = (int *) NULL;
+  index = 0;  
+
+  if (out == (tetgenio *) NULL) {
+    outfile = fopen(edgefilename, "w");
+    if (outfile == (FILE *) NULL) {
+      printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
+      terminatetetgen(1);
+    }
+    // Number of subsegments.
+    fprintf(outfile, "%ld\n", subsegpool->items);
+  } else {
+    // Allocate memory for 'edgelist'.
+    out->edgelist = new int[subsegpool->items * 2];
+    if (out->edgelist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      terminatetetgen(1);
+    }
+    out->numberofedges = subsegpool->items;
+    elist = out->edgelist;
+  }
+
+  // Determine the first index (0 or 1).
+  firstindex = b->zeroindex ? 0 : in->firstnumber;
+  shift = 0; // Default no shiftment.
+  if ((in->firstnumber == 1) && (firstindex == 0)) {
+    shift = 1; // Shift the output indices by 1.
+  }
+
+  subsegpool->traversalinit();
+  edgeloop.sh = shellfacetraverse(subsegpool);
+  edgenumber = firstindex; // in->firstnumber;
+  while (edgeloop.sh != (shellface *) NULL) {
+    torg = sorg(edgeloop);
+    tdest = sdest(edgeloop);
+    if (out == (tetgenio *) NULL) {
+      fprintf(outfile, "%5d   %4d  %4d\n", edgenumber,
+              pointmark(torg) - shift, pointmark(tdest) - shift);
+    } else {
+      // Output three vertices of this face;
+      elist[index++] = pointmark(torg) - shift;
+      elist[index++] = pointmark(tdest) - shift;
+    }
+    edgenumber++;
+    edgeloop.sh = shellfacetraverse(subsegpool);
+  }
+
+  if (out == (tetgenio *) NULL) {
+    fprintf(outfile, "# Generated by %s\n", b->commandline);
+    fclose(outfile);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// outneighbors()    Output tet neighbors to a .neigh file or an object.     //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::outneighbors(tetgenio* out)
+{
+  FILE *outfile;
+  char neighborfilename[FILENAMESIZE];
+  int *nlist;
+  int index;
+  triface tetloop, tetsym;
+  int neighbor1, neighbor2, neighbor3, neighbor4;
+  int firstindex;
+  int elementnumber;
+  long ntets;
+
+  if (out == (tetgenio *) NULL) {
+    strcpy(neighborfilename, b->outfilename);
+    strcat(neighborfilename, ".neigh");
+  }
+
+  if (!b->quiet) {
+    if (out == (tetgenio *) NULL) {
+      printf("Writing %s.\n", neighborfilename);
+    } else {
+      printf("Writing neighbors.\n");
+    }
+  }
+
+  ntets = tetrahedronpool->items - hullsize;
+
+  if (out == (tetgenio *) NULL) {
+    outfile = fopen(neighborfilename, "w");
+    if (outfile == (FILE *) NULL) {
+      printf("File I/O Error:  Cannot create file %s.\n", neighborfilename);
+      terminatetetgen(1);
+    }
+    // Number of tetrahedra, four faces per tetrahedron.
+    fprintf(outfile, "%ld  %d\n", ntets, 4);
+  } else {
+    // Allocate memory for 'neighborlist'.
+    out->neighborlist = new int[ntets * 4];
+    if (out->neighborlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      terminatetetgen(1);
+    }
+    nlist = out->neighborlist;
+  }
+
+  // Determine the first index (0 or 1).
+  firstindex = b->zeroindex ? 0 : in->firstnumber;
+
+  tetrahedronpool->traversalinit();
+  tetloop.tet = tetrahedrontraverse();
+  elementnumber = firstindex; // in->firstnumber;
+  while (tetloop.tet != (tetrahedron *) NULL) {
+    tetloop.loc = 2;
+    sym(tetloop, tetsym);
+    if ((point) tetsym.tet[7] != dummypoint) {
+      neighbor1 = * (int *) (tetsym.tet + elemmarkerindex);
+    } else {
+      neighbor1 = -1;
+    }
+    tetloop.loc = 3;
+    sym(tetloop, tetsym);
+    if ((point) tetsym.tet[7] != dummypoint) {
+      neighbor2 = * (int *) (tetsym.tet + elemmarkerindex);
+    } else {
+      neighbor1 = -1;
+    }
+    tetloop.loc = 1;
+    sym(tetloop, tetsym);
+    if ((point) tetsym.tet[7] != dummypoint) {
+      neighbor3 = * (int *) (tetsym.tet + elemmarkerindex);
+    } else {
+      neighbor1 = -1;
+    }
+    tetloop.loc = 0;
+    sym(tetloop, tetsym);
+    if ((point) tetsym.tet[7] != dummypoint) {
+      neighbor4 = * (int *) (tetsym.tet + elemmarkerindex);
+    } else {
+      neighbor1 = -1;
+    }
+    if (out == (tetgenio *) NULL) {
+      // Tetrahedra number, neighboring tetrahedron numbers.
+      fprintf(outfile, "%4d    %4d  %4d  %4d  %4d\n", elementnumber,
+              neighbor1, neighbor2, neighbor3, neighbor4);
+    } else {
+      nlist[index++] = neighbor1;
+      nlist[index++] = neighbor2;
+      nlist[index++] = neighbor3;
+      nlist[index++] = neighbor4;
+    }
+    tetloop.tet = tetrahedrontraverse();
+    elementnumber++;
+  }
+
+  if (out == (tetgenio *) NULL) {
+    fprintf(outfile, "# Generated by %s\n", b->commandline);
+    fclose(outfile);
+  }
+}
+
+#endif // #ifndef meshioCXX
diff --git a/contrib/Tetgen/meshstat.cxx b/contrib/Tetgen/meshstat.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..8c4e7ec30492c9bd11a3358b269b6ba20013d6da
--- /dev/null
+++ b/contrib/Tetgen/meshstat.cxx
@@ -0,0 +1,1574 @@
+#ifndef meshstatCXX
+#define meshstatCXX
+
+#include "tetgen.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Initialize fast look-up tables.                                           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+int tetgenmesh::ve[6] = { 2, 5, 4, 1, 0, 3 };
+int tetgenmesh::ve2[6] = { 4, 3, 0, 5, 2, 1 };
+
+int tetgenmesh::vo[6] = { 0, 1, 1, 2, 2, 0 };
+int tetgenmesh::vd[6] = { 1, 0, 2, 1, 0, 2 };
+int tetgenmesh::va[6] = { 2, 2, 0, 0, 1, 1 };
+
+int tetgenmesh::verver2zero[6][6] = {
+  {0, 0, 2, 2, 4, 4},
+  {0, 0, 2, 2, 4, 4},
+  {2, 2, 4, 4, 0, 0},
+  {2, 2, 4, 4, 0, 0},
+  {4, 4, 0, 0, 2, 2},
+  {4, 4, 0, 0, 2, 2}
+};
+
+int tetgenmesh::ver2zero[6] = {0, 0, 2, 2, 4, 4};
+
+int tetgenmesh::zero2ver[6][6] = {
+  {0, 0, 2, 2, 4, 4}, 
+  {0, 0, 2, 2, 4, 4},
+  {4, 4, 0, 0, 2, 2},
+  {4, 4, 0, 0, 2, 2},
+  {2, 2, 4, 4, 0, 0},
+  {2, 2, 4, 4, 0, 0}
+};
+
+int tetgenmesh::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 tetgenmesh::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 tetgenmesh::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}
+};
+
+int tetgenmesh::loc2oppo[4] = { 3, 2, 0, 1 };
+
+int tetgenmesh::locver2nextf[32] = {
+  1, 5, 2, 5, 3, 5, 0, 0,
+  3, 3, 2, 1, 0, 1, 0, 0,
+  1, 3, 3, 1, 0, 3, 0, 0,
+  2, 3, 1, 1, 0, 5, 0, 0
+};
+
+int tetgenmesh::locver2edge[4][6] = {
+  {0, 0, 1, 1, 2, 2},
+  {3, 3, 4, 4, 0, 0},
+  {4, 4, 5, 5, 1, 1},
+  {5, 5, 3, 3, 2, 2}
+};
+
+int tetgenmesh::edge2locver[6][2] = {
+  {0, 0}, // 0  v0 -> v1
+  {0, 2}, // 1  v1 -> v2
+  {0, 4}, // 2  v2 -> v0
+  {1, 0}, // 3  v0 -> v3
+  {1, 2}, // 4  v1 -> v3
+  {2, 2}  // 5  v2 -> v3
+};
+
+int tetgenmesh::locpivot[4][3] = {
+  {1, 2, 3},
+  {0, 2, 3},
+  {0, 1, 3},
+  {0, 1, 2}
+};
+
+int tetgenmesh::locverpivot[4][6][2] = {
+  {{2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 2}, {1, 2}},
+  {{0, 2}, {0, 2}, {0, 3}, {0, 3}, {2, 3}, {2, 3}},
+  {{0, 3}, {0, 3}, {0, 1}, {0, 1}, {1, 3}, {1, 3}},
+  {{0, 1}, {0, 1}, {0, 2}, {0, 2}, {1, 2}, {1, 2}}
+};
+
+int tetgenmesh::mi1mo3[3] = {2, 0, 1};
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// checkmesh()    Test mesh for geometrical and topological consistencies.   //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::checkmesh()
+{
+  triface tetloop;
+  triface neightet, symtet;
+  point pa, pb, pc, pd;
+  REAL ori;
+  int horrors;
+
+  if (!b->quiet) {
+    printf("  Checking consistency of mesh...\n");
+  }
+
+  horrors = 0;
+  tetloop.ver = 0;
+  // Run through the list of tetrahedra, checking each one.
+  tetrahedronpool->traversalinit();
+  tetloop.tet = tetrahedrontraverse();
+  while (tetloop.tet != (tetrahedron *) NULL) {
+    // Check all four faces of the tetrahedron.
+    for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
+      pa = org(tetloop);
+      pb = dest(tetloop);
+      pc = apex(tetloop);
+      pd = oppo(tetloop);
+      if (tetloop.loc == 0) {  // Only test for inversion once.
+        if (pd != dummypoint) {  // Only do test if it is not a hull tet.
+          ori = orient3d(pa, pb, pc, pd);
+          if (ori >= 0.0) {
+            printf("  !! !! %s ", ori > 0.0 ? "Inverted" : "Degenerated");
+            printf("  (%d, %d, %d, %d) (ori = %.17g)\n", pointmark(pa),
+              pointmark(pb), pointmark(pc), pointmark(pd), ori);
+            horrors++;
+          }
+        }
+        if (infected(tetloop)) {
+          printf("  !! (%d, %d, %d, %d) is infected.\n", pointmark(pa),
+            pointmark(pb), pointmark(pc), pointmark(pd));
+        }
+        if (marktested(tetloop)) {
+          printf("  !! (%d, %d, %d, %d) is marked.\n", pointmark(pa),
+            pointmark(pb), pointmark(pc), pointmark(pd));
+        }
+      }
+      if (tetloop.tet[tetloop.loc] == NULL) {
+        printf("  !! !! No neighbor at face (%d, %d, %d).\n", pointmark(pa),
+            pointmark(pb), pointmark(pc));
+        horrors++;
+      } else {
+        // Find the neighboring tetrahedron on this face.
+        symedge(tetloop, neightet);
+        // Check that the tetrahedron's neighbor knows it's a neighbor.
+        sym(neightet, symtet);
+        if ((tetloop.tet != symtet.tet) || (tetloop.loc != symtet.loc)) {
+          printf("  !! !! Asymmetric tetra-tetra bond:\n");
+          if (tetloop.tet == symtet.tet) {
+            printf("   (Right tetrahedron, wrong orientation)\n");
+          }
+          printf("    First:  (%d, %d, %d, %d)\n", pointmark(pa),
+            pointmark(pb), pointmark(pc), pointmark(pd));
+          printf("    Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)),
+            pointmark(dest(neightet)), pointmark(apex(neightet)),
+            pointmark(oppo(neightet)));
+          horrors++;
+        }
+        // Check if they have the same edge (the bond() operation).
+        if ((org(neightet) != pb) || (dest(neightet) != pa)) {
+          printf("  !! !! Wrong edge-edge bond:\n");
+          printf("    First:  (%d, %d, %d, %d)\n", pointmark(pa),
+            pointmark(pb), pointmark(pc), pointmark(pd));
+          printf("    Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)),
+            pointmark(dest(neightet)), pointmark(apex(neightet)),
+            pointmark(oppo(neightet)));
+          horrors++;
+        }
+        // Check if they have the same opposite.
+        if (oppo(neightet) == pd) {
+          printf("  !! !! Two identical tetra:\n");
+          printf("    First:  (%d, %d, %d, %d)\n", pointmark(pa),
+            pointmark(pb), pointmark(pc), pointmark(pd));
+          printf("    Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)),
+            pointmark(dest(neightet)), pointmark(apex(neightet)),
+            pointmark(oppo(neightet)));
+          horrors++;
+        }
+      }
+    }
+    tetloop.tet = tetrahedrontraverse();
+  }
+  if (horrors == 0) {
+    if (!b->quiet) {
+      printf("  In my studied opinion, the mesh appears to be consistent.\n");
+    }
+  } else {
+    printf("  !! !! !! !! %d %s witnessed.\n", horrors, 
+      horrors > 1 ? "abnormity" : "abnormities");
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// checkshells()    Test the surface mesh for consistencies.                 //
+//                                                                           //
+// If 'sub2tet' > 0, it also checks the subface-to-tet connections.          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+int tetgenmesh::checkshells(int sub2tet)
+{
+  triface neightet, symtet;
+  face shloop, spinsh, nextsh;
+  face checkseg;
+  point pa, pb;
+  int horrors, i;
+
+  tetrahedron ptr;
+
+  if (!b->quiet) {
+    printf("  Checking consistency of the mesh boundary...\n");
+  }
+  horrors = 0;
+
+  void **bakpathblock = subfacepool->pathblock;
+  void *bakpathitem = subfacepool->pathitem;
+  int bakpathitemsleft = subfacepool->pathitemsleft;
+  int bakalignbytes = subfacepool->alignbytes;
+
+  subfacepool->traversalinit();
+  shloop.sh = shellfacetraverse(subfacepool);
+  while (shloop.sh != NULL) {
+    shloop.shver = 0;
+    for (i = 0; i < 3; i++) {
+      // Check the face ring at this edge.
+      pa = sorg(shloop);
+      pb = sdest(shloop);
+      spinsh = shloop;
+      spivot(spinsh, nextsh);
+      while ((nextsh.sh != NULL) && (nextsh.sh != shloop.sh)) {
+        // check if they have the same edge.
+        if (!((sorg(nextsh) == pa) && (sdest(nextsh) == pb) ||
+             (sorg(nextsh) == pb) && (sdest(nextsh) == pa))) {
+           printf("  !! !! Wrong subface-subface connection.\n");
+           printf("    First: x%lx (%d, %d, %d).\n", (unsigned long) spinsh.sh,
+             pmark(sorg(spinsh)), pmark(sdest(spinsh)), pmark(sapex(spinsh)));
+           printf("    Scond: x%lx (%d, %d, %d).\n", (unsigned long) nextsh.sh,
+             pmark(sorg(nextsh)), pmark(sdest(nextsh)), pmark(sapex(nextsh)));
+           horrors++;
+        }
+        spinsh = nextsh;
+        spivot(spinsh, nextsh);
+      }
+      // Check subface-subseg bond.
+      sspivot(shloop, checkseg);
+      if (checkseg.sh != NULL) {
+        if (!((sorg(checkseg) == pa) && (sdest(checkseg) == pb) ||
+             (sorg(checkseg) == pb) && (sdest(checkseg) == pa))) {
+          printf("  !! !! Wrong subface-subseg connection.\n");
+          printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long) shloop.sh,
+            pmark(sorg(shloop)), pmark(sdest(shloop)), pmark(sapex(shloop)));
+          printf("    Seg: x%lx (%d, %d).\n", (unsigned long) checkseg.sh,
+            pmark(sorg(checkseg)), pmark(sdest(checkseg)));
+          horrors++;
+        }
+      }
+      senextself(shloop);
+    }
+    if (sub2tet > 0) {
+      // Check the tet-subface connections.
+      stpivot(shloop, neightet);
+      if (neightet.tet != NULL) {
+        tspivot(neightet, spinsh);
+        if (spinsh.sh != shloop.sh) {
+          printf("  !! !! Wrong connection betwee tet and subface.\n");
+          printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long) shloop.sh,
+            pmark(sorg(shloop)), pmark(sdest(shloop)), pmark(sapex(shloop)));
+          printf("    Tet: x%lx (%d, %d, %d, %d).\n", 
+            (unsigned long) neightet.tet, pmark(org(neightet)), 
+            pmark(dest(neightet)), pmark(apex(neightet)), 
+            pmark(oppo(neightet)));
+          horrors++;
+        } else {
+          symself(neightet);
+          tspivot(neightet, spinsh);
+          if (spinsh.sh != shloop.sh) {
+            printf("  !! !! Wrong connection betwee tet and subface.\n");
+            printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long) shloop.sh,
+              pmark(sorg(shloop)), pmark(sdest(shloop)), pmark(sapex(shloop)));
+            printf("    Tet: x%lx (%d, %d, %d, %d).\n", 
+              (unsigned long) neightet.tet, pmark(org(neightet)), 
+              pmark(dest(neightet)), pmark(apex(neightet)), 
+              pmark(oppo(neightet)));
+            horrors++;
+          }
+        }
+      } else {
+        // printf("  !! A dangling subface.\n");
+        // printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long) shloop.sh,
+        //   pmark(sorg(shloop)), pmark(sdest(shloop)), pmark(sapex(shloop)));
+        // horrors++;
+      }
+    }
+    shloop.sh = shellfacetraverse(subfacepool);
+  }
+
+  if (horrors == 0) {
+    if (!b->quiet) {
+      printf("  Mesh boundaries connected correctly.\n");
+    }
+  } else {
+    printf("  !! !! !! !! %d boundary connection viewed with horror.\n",
+           horrors);
+  }
+
+  subfacepool->pathblock = bakpathblock;
+  subfacepool->pathitem = bakpathitem;
+  subfacepool->pathitemsleft = bakpathitemsleft;
+  subfacepool->alignbytes = bakalignbytes;
+
+  return horrors;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// checkdelaunay()    Ensure that the mesh is (constrained) Delaunay.        //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+int tetgenmesh::checkdelaunay(int constrained)
+{
+  triface tetloop;
+  triface symtet;
+  face checksh;
+  point pa, pb, pc, pd, pe;
+  REAL sign;
+  int horrors;
+
+  if (!b->quiet) {
+    printf("  Checking %s property of the mesh...\n",  constrained > 0 ? 
+      "constrained Delaunay" : "Delaunay");
+  }
+  
+  horrors = 0;
+  tetloop.ver = 0;
+  // Run through the list of triangles, checking each one.
+  tetrahedronpool->traversalinit();
+  tetloop.tet = tetrahedrontraverse();
+  while (tetloop.tet != (tetrahedron *) NULL) {
+    // Check all four faces of the tetrahedron.
+    for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
+      sym(tetloop, symtet);
+      // Only do test if its adjoining tet is not a hull tet or its pointer
+      //   is larger (to ensure that each pair isn't tested twice).
+      if (((point) symtet.tet[7] != dummypoint)&&(tetloop.tet < symtet.tet)) {
+        pa = org(tetloop);
+        pb = dest(tetloop);
+        pc = apex(tetloop);
+        pd = oppo(tetloop);
+        pe = oppo(symtet);
+        sign = insphere_sos(pa, pb, pc, pd, pe);
+        if (sign < 0.0) {
+          if (constrained > 0) {
+            tspivot(tetloop, checksh);
+          }
+          if ((constrained == 0) || 
+             ((constrained > 0) && (checksh.sh == NULL))) {
+            printf("  !! Non-locally Delaunay (%d, %d, %d) - %d, %d\n",
+              pointmark(pa), pointmark(pb), pointmark(pc), pointmark(pd),
+              pointmark(pe));
+            horrors++;
+          }
+        }
+      }
+    }
+    tetloop.tet = tetrahedrontraverse();
+  }
+
+  if (horrors == 0) {
+    if (!b->quiet) {
+      printf("  The mesh is %s.\n", constrained > 0 ? "constrained Delaunay" 
+        : "Delaunay");
+    }
+  } else {
+    printf("  !! !! !! !! Found %d non-Delaunay faces.\n", horrors);
+  }
+
+  return horrors;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// checksegments()    Check the connections between tetrahedra and segments. //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+int tetgenmesh::checksegments()
+{
+  triface tetloop, neightet;
+  shellface *segs;
+  face sseg, checkseg;
+  point pa, pb;
+  int horrors, i;
+
+  if (!b->quiet) {
+    printf("  Checking tet-seg connections...\n");
+  }
+
+  horrors = 0;
+  tetrahedronpool->traversalinit();
+  tetloop.tet = tetrahedrontraverse();
+  while (tetloop.tet != NULL) {
+    // Loop the six edges of the tet.
+    if (tetloop.tet[8] != NULL) {
+      segs = (shellface *) tetloop.tet[8];
+      for (i = 0; i < 6; i++) {
+        sdecode(segs[i], sseg);
+        if (sseg.sh != NULL) {
+          // Get the edge of the tet.
+          tetloop.loc = edge2locver[i][0];
+          tetloop.ver = edge2locver[i][1];
+          // Check if they are the same edge.
+          pa = (point) sseg.sh[3];
+          pb = (point) sseg.sh[4];
+          if (!(((org(tetloop) == pa) && (dest(tetloop) == pb)) ||
+                ((org(tetloop) == pb) && (dest(tetloop) == pa)))) {
+            printf("  !! Wrong tet-seg connection.\n");
+            printf("    Tet: x%lx (%d, %d, %d, %d) - Seg: x%lx (%d, %d).\n", 
+              (unsigned long) tetloop.tet, pointmark(org(tetloop)),
+              pointmark(dest(tetloop)), pointmark(apex(tetloop)),
+              pointmark(oppo(tetloop)), (unsigned long) sseg.sh,
+              pointmark(pa), pointmark(pb));
+            horrors++;
+          } else {
+            // Loop all tets sharing at this edge.
+            neightet = tetloop;
+            do {
+              tsspivot(neightet, checkseg);
+              if (checkseg.sh != sseg.sh) {
+                printf("  !! Wrong tet-seg connection.\n");
+                printf("    Tet: x%lx (%d, %d, %d, %d) - ", 
+                  (unsigned long) tetloop.tet, pointmark(org(tetloop)),
+                  pointmark(dest(tetloop)), pointmark(apex(tetloop)),
+                  pointmark(oppo(tetloop)));
+                if (checkseg.sh != NULL) {
+                  printf("Seg x%lx (%d, %d).\n", (unsigned long) checkseg.sh,
+                  pointmark(sorg(checkseg)), pointmark(sdest(checkseg))); 
+                } else {
+                  printf("Seg: NULL.\n");
+                }
+                horrors++;
+              }
+              fnextself(neightet);
+            } while (neightet.tet != tetloop.tet);
+          }
+        }
+      }
+    }
+    tetloop.tet = tetrahedrontraverse();
+  }
+
+  if (horrors == 0) {
+    printf("  Segments are connected properly.\n");
+  } else {
+    printf("  !! !! !! !! Found %d missing connections.\n", horrors);
+  }
+
+  return horrors;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// algorithmstatistics()    Report algorithmic performances.                 //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::algorithmstatistics()
+{
+  /*// Report memory usages.
+    unsigned long totalmeshbytes;
+    printf("Memory allocation statistics:\n\n");
+    printf("  Maximum number of vertices: %ld\n", pointpool->maxitems);
+    totalmeshbytes = pointpool->maxitems * pointpool->itembytes;
+    printf("  Maximum number of tetrahedra: %ld\n", tetrahedronpool->maxitems);
+    totalmeshbytes += tetrahedronpool->maxitems * tetrahedronpool->itembytes;
+    if (subfacepool != (memorypool *) NULL) {
+      printf("  Maximum number of subfaces: %ld\n", subfacepool->maxitems);
+      totalmeshbytes += subfacepool->maxitems * subfacepool->itembytes;
+    }
+    if (subsegpool != (memorypool *) NULL) {
+      printf("  Maximum number of segments: %ld\n", subsegpool->maxitems);
+      totalmeshbytes += subsegpool->maxitems * subsegpool->itembytes;
+    }
+    printf("  Heap memory used by the mesh (K bytes): %g\n\n",
+           ((double) totalmeshbytes) / 1024.0);
+  */
+
+  printf("Algorithmic statistics:\n\n");
+
+  printf("  Number of orient3d tests: %ld\n", orient3dcount);
+  printf("  Number of insphere tests: %ld\n", inspherecount);
+  printf("  Number of symbolic insphere tests: %ld\n", insphere_sos_count);
+  printf("  Number of visited tets in point location: %ld\n", ptloc_count);
+  printf("  Maximal number of tets per point location: %ld\n",ptloc_max_count);
+  printf("  Number of 1-to-4 flips: %ld\n", flip14count);
+  printf("  Number of 2-to-6 flips: %ld\n", flip26count);
+  printf("  Number of n-t-2n flips: %ld\n", flipn2ncount);
+
+  if (!b->plc) {
+    if (b->bowyerwatson) {
+      printf("  Number of deleted tets: %ld\n", totaldeadtets);
+      printf("  Number of created tets: %ld\n", totalbowatcavsize);
+      printf("  Maximum number of tets per new point: %ld\n", maxbowatcavsize);
+      printf("  Number of 3-to-2 flips: %ld\n", flip32count);
+    } else {
+      printf("  Number of 3-to-2 flips: %ld\n", flip32count);
+      printf("  Number of 2-to-3 flips: %ld\n", flip23count);
+      printf("  Number of n-to-m flips: %ld\n", flipnmcount);
+      printf("  Total number of primitive flips: %ld\n",
+        flip23count + flip32count);
+    }
+  }
+
+  if (b->plc) {
+    printf("  Number of 2-to-2 flips: %ld\n", flip22count);
+    printf("  Number of tri-edge inter (coplanar) tests: %ld (%ld)\n",
+      triedgcount, triedgcopcount);
+    printf("  Number of crossed faces (edges) in scout segs: %ld (%ld)\n",
+      across_face_count, across_edge_count);
+    printf("  Maximal number of crossed faces per segment: %ld\n",
+      across_max_count);
+    printf("  Number of rule-1 points: %ld\n", r1count);
+    printf("  Number of rule-2 points: %ld\n", r2count);
+    printf("  Number of rule-3 points: %ld\n", r3count);
+    printf("  Maximal size of a missing region: %ld\n", maxregionsize);
+    printf("  Maximal size of a recovered cavity: %ld\n", maxcavsize);
+    printf("  Number of non-Delaunay edges: %ld\n", ndelaunayedgecount);
+    printf("  Number of cavity expansions: %ld\n", cavityexpcount);
+  }
+  
+  // printf("  Total point location time (millisec):  %g\n", tloctime * 1e+3);
+  // printf("  Total point insertion time (millisec):  %g\n",tinserttime*1e+3);
+  // if (b->bowyerwatson == 0) {
+  //   printf("  Total flip time (millisec):  %g\n", tfliptime * 1e+3);
+  // }
+
+  printf("\n");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// statistics()    Print all sorts of cool facts.                            //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::statistics()
+{
+  long tetnumber, facenumber;
+
+  printf("\nStatistics:\n\n");
+  printf("  Input points: %d\n", in->numberofpoints);
+  if (b->refine) {
+    printf("  Input tetrahedra: %d\n", in->numberoftetrahedra);
+  }
+  if (b->plc) {
+    printf("  Input facets: %d\n", in->numberoffacets);
+    printf("  Input segments: %ld\n", insegments);
+    printf("  Input holes: %d\n", in->numberofholes);
+    printf("  Input regions: %d\n", in->numberofregions);
+  }
+
+  tetnumber = tetrahedronpool->items - hullsize;
+  facenumber = (tetnumber * 4l + hullsize) / 2l;
+
+  printf("\n  Mesh points: %ld\n", pointpool->items);
+  printf("  Mesh tetrahedra: %ld\n", tetnumber);
+  printf("  Mesh faces: %ld\n", facenumber);
+  printf("  Mesh edges: %ld\n", meshedges);
+
+  if (b->plc || b->refine) {
+    printf("  Mesh boundary faces: %ld\n", subfacepool->items);
+    printf("  Mesh boundary edges: %ld\n", meshsubedges);
+    printf("  Mesh subsegments: %ld\n", subsegpool->items);
+  } else {
+    printf("  Convex hull faces: %ld\n", hullsize);
+  }
+  printf("\n");
+
+  if (b->verbose > 0) {
+    printf("  Euler characteristic of mesh domain: %ld\n", pointpool->items 
+      - meshedges + facenumber - tetnumber);
+    printf("  Euler characteristic of boundary: %ld\n", pointpool->items 
+      - meshsubedges + subfacepool->items);
+    printf("\n");
+  }
+
+  if (b->verbose > 0) {
+    // qualitystatistics();
+    algorithmstatistics();
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// terminatetetgen()    Terminate TetGen with a given exit code.             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void terminatetetgen(int x)
+{
+#ifdef TETLIBRARY
+  throw x;
+#else
+  exit(x);
+#endif // #ifdef TETLIBRARY
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Debug functions.                                                          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Print the detail informations of a tetrahedron.
+
+void tetgenmesh::ptet(triface* t)
+{
+  triface tmpface, prtface;
+  shellface *shells;
+  face checksh;
+  point *pts, tmppt;
+  REAL ori;
+  int facecount;
+
+  printf("Tetra x%lx with loc(%i) ver(%i):",
+         (unsigned long)(t->tet), t->loc, t->ver);
+  if (t->tet == NULL) {
+    printf("  !! NOT A VALID HANDLE\n");
+    return;
+  }
+  pts = (point *) t->tet;
+  if (pts[4] == NULL) {
+    printf("  !! A DEAD TET\n");
+    return;
+  }
+  if (pts[7] != dummypoint) {
+    ori = orient3d(pts[4], pts[5], pts[6], pts[7]);
+    printf("  ori = %g.\n", ori);
+  } else {
+    printf("  (hull tet).\n");
+  }
+  // Report the status of this tet.
+  printf("      ");
+  if (infected(*t)) {
+    printf("(infected) ");
+  }
+  if (marktested(*t)) {
+    printf("(marktested) ");
+  }
+  if (edgemarked(*t)) {
+    printf("(edgemarked) ");
+  }
+  if (b->regionattrib) {
+    printf("attr(%d)", elemattribute(t->tet, 0));
+  }
+  printf("\n");
+
+  tmpface = *t;
+  facecount = 0;
+  while(facecount < 4) {
+    tmpface.loc = facecount;
+    sym(tmpface, prtface);
+    if (prtface.tet == NULL) {
+      printf("      [%i] Open !!\n", facecount);
+    } else {
+      printf("      [%i] x%lx  loc(%i) ver(%i)", facecount,
+             (unsigned long)(prtface.tet), prtface.loc, prtface.ver);
+      if ((point) prtface.tet[7] == dummypoint) {
+        printf("  (hull tet)");
+      }
+      if (infected(prtface)) {
+        printf(" (infected)");
+      }
+      printf("\n");
+    }
+    facecount++;
+  }
+
+  tmppt = org(*t);
+  if(tmppt == (point) NULL) {
+    printf("      Org [%i] NULL\n", locver2org[t->loc][t->ver]);
+  } else {
+    printf("      Org [%i] x%lx (%.12g,%.12g,%.12g) %d\n",
+           locver2org[t->loc][t->ver], (unsigned long)(tmppt),
+           tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
+  }
+  tmppt = dest(*t);
+  if(tmppt == (point) NULL) {
+    printf("      Dest[%i] NULL\n", locver2dest[t->loc][t->ver]);
+  } else {
+    printf("      Dest[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
+           locver2dest[t->loc][t->ver], (unsigned long)(tmppt),
+           tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
+  }
+  tmppt = apex(*t);
+  if(tmppt == (point) NULL) {
+    printf("      Apex[%i] NULL\n", locver2apex[t->loc][t->ver]);
+  } else {
+    printf("      Apex[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
+           locver2apex[t->loc][t->ver], (unsigned long)(tmppt),
+           tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
+  }
+  tmppt = oppo(*t);
+  if(tmppt == (point) NULL) {
+    printf("      Oppo[%i] NULL\n", loc2oppo[t->loc]);
+  } else {
+    printf("      Oppo[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
+           loc2oppo[t->loc], (unsigned long)(tmppt),
+           tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
+  }
+
+  if (checksubsegs) {
+    if (t->tet[8] != NULL) {
+      shells = (shellface *) t->tet[8];
+      for (facecount = 0; facecount < 6; facecount++) {
+        sdecode(shells[facecount], checksh);
+        if (checksh.sh != NULL) {
+          printf("      [%d] x%lx %d.", facecount, (unsigned long) checksh.sh,
+            checksh.shver);
+        } else {
+          printf("      [%d] NULL.", facecount);
+        }
+        if (locver2edge[t->loc][t->ver] == facecount) {
+          printf(" (*)");  // It is the current edge.
+        }
+        printf("\n");
+      }
+    }
+  }
+
+  if (checksubfaces) {
+    if (t->tet[9] != NULL) {
+      shells = (shellface *) t->tet[9];
+      for (facecount = 0; facecount < 4; facecount++) {
+        sdecode(shells[facecount], checksh);
+        if (checksh.sh != NULL) {
+          printf("      [%d] x%lx %d.", facecount, (unsigned long) checksh.sh,
+            checksh.shver);
+        } else {
+          printf("      [%d] NULL.", facecount);
+        }
+        if (t->loc == facecount) {
+          printf(" (*)");  // It is the current face.
+        }
+        printf("\n");
+      }
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Print the detail informations of a shellface.
+
+void tetgenmesh::psh(face *s)
+{
+  face prtsh;
+  triface prttet;
+  point *pt, printpoint;
+  REAL n[3];
+
+  if (s->sh == NULL) {
+    printf("Not a handle.\n");
+    return;
+  }
+
+  if (s->sh[3] == NULL) {
+    printf("A dead subface x%lx.\n", (unsigned long)(s->sh));
+    return;
+  }
+
+  pt = (point *) s->sh;
+  if (s->sh[5] != NULL) {
+    printf("subface x%lx, ver %d, mark %d:\n",(unsigned long)(s->sh),s->shver,
+      getshellmark(*s));
+    facenormal(pt[3], pt[4], pt[5], n, 1);
+    printf("      area %g, edge lengths %g %g %g\n", 0.5 * sqrt(DOT(n, n)),
+      DIST(pt[3], pt[4]), DIST(pt[4], pt[5]), DIST(pt[5], pt[3]));
+  } else {
+    printf("Subsegment x%lx, ver %d, mark %d:\n", (unsigned long)(s->sh),
+      s->shver, getshellmark(*s));
+    printf("      length %g", DIST(pt[3], pt[4]));
+  }
+  if (sinfected(*s)) {
+    printf(" (infected)");
+  }
+  if (smarktested(*s)) {
+    printf(" (marked)");
+  }
+  // if (shell2badface(*sface)) {
+  //   printf(" (queued)");
+  // }
+  // if (checkpbcs) {
+  //   if (shellpbcgroup(*sface) >= 0) {
+  //     printf(" (pbc %d)", shellpbcgroup(*sface));
+  //   }
+  // }
+  printf("\n");
+
+  sdecode(s->sh[0], prtsh);
+  if (prtsh.sh == NULL) {
+    printf("      [0] = No shell\n");
+  } else {
+    printf("      [0] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
+  }
+  sdecode(s->sh[1], prtsh);
+  if (prtsh.sh == NULL) {
+    printf("      [1] = No shell\n");
+  } else {
+    printf("      [1] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
+  }
+  sdecode(s->sh[2], prtsh);
+  if (prtsh.sh == NULL) {
+    printf("      [2] = No shell\n");
+  } else {
+    printf("      [2] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
+  }
+
+  printpoint = sorg(*s);
+  if (printpoint == (point) NULL)
+    printf("      Org [%d] = NULL\n", vo[s->shver]);
+  else
+    printf("      Org [%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
+           vo[s->shver], (unsigned long)(printpoint), printpoint[0],
+           printpoint[1], printpoint[2], pointmark(printpoint));
+  printpoint = sdest(*s);
+  if (printpoint == (point) NULL)
+    printf("      Dest[%d] = NULL\n", vd[s->shver]);
+  else
+    printf("      Dest[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
+           vd[s->shver], (unsigned long)(printpoint), printpoint[0],
+           printpoint[1], printpoint[2], pointmark(printpoint));
+
+  printpoint = sapex(*s);
+  if (printpoint == (point) NULL)
+    printf("      Apex[%d] = NULL\n", va[s->shver]);
+  else
+    printf("      Apex[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
+           va[s->shver], (unsigned long)(printpoint), printpoint[0],
+           printpoint[1], printpoint[2], pointmark(printpoint));
+
+  if (s->sh[5] != NULL) {
+    sdecode(s->sh[6], prtsh);
+    if (prtsh.sh == NULL) {
+      printf("      [6] = No subsegment\n");
+    } else {
+      printf("      [6] = x%lx  %d\n", (unsigned long) prtsh.sh, prtsh.shver);
+    }
+    sdecode(s->sh[7], prtsh);
+    if (prtsh.sh == NULL) {
+      printf("      [7] = No subsegment\n");
+    } else {
+      printf("      [7] = x%lx  %d\n", (unsigned long) prtsh.sh, prtsh.shver);
+    }
+    sdecode(s->sh[8], prtsh);
+    if (prtsh.sh == NULL) {
+      printf("      [8] = No subsegment\n");
+    } else {
+      printf("      [8] = x%lx  %d\n", (unsigned long) prtsh.sh, prtsh.shver);
+    }
+
+    decode(s->sh[9], prttet);
+    if (prttet.tet == NULL) {
+      printf("      [9] = Outer space\n");
+    } else {
+      printf("      [9] = x%lx  %d\n",(unsigned long) prttet.tet, prttet.loc);
+    }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Find and print the tetrahedron (or face or edge) with the given indices.
+// Do not handle 'dummypoint' (-1).
+
+void tetgenmesh::pteti(int i, int j, int k, int l)
+{
+  triface t;
+  point *pts;
+  int *marklist;
+  int ii;
+
+  marklist = new int[pointpool->items + 1];
+  for (ii = 0; ii < pointpool->items + 1; ii++) marklist[ii] = 0;
+  // Marke the given indices. 
+  marklist[i] = marklist[j] = marklist[k] = marklist[l] = 1;
+
+  t.loc = t.ver = 0;
+  tetrahedronpool->traversalinit();
+  t.tet = tetrahedrontraverse();
+  while (t.tet != NULL) {
+    pts = (point *) t.tet;
+    if (pts[7] != dummypoint) {
+      if ((marklist[pointmark(pts[4])] + marklist[pointmark(pts[5])] +
+           marklist[pointmark(pts[6])] + marklist[pointmark(pts[7])]) == 4) {
+        ptet(&t);  // Find!
+        break;
+      }
+    }
+    t.tet = tetrahedrontraverse();
+  }
+  
+  if (t.tet == NULL) {
+    printf("  !! Not exist.\n");
+  }
+  delete [] marklist;
+}
+
+void tetgenmesh::pface(int i, int j, int k)
+{
+  triface t, t1;
+  point *pts;
+  REAL sign;
+  int *marklist;
+  int ii;
+
+  marklist = new int[pointpool->items + 1];
+  for (ii = 0; ii < pointpool->items + 1; ii++) marklist[ii] = 0;
+  // Marke the given indices. 
+  marklist[i] = marklist[j] = marklist[k] = 1;
+
+  t.ver = t1.ver = 0;
+  tetrahedronpool->traversalinit();
+  t.tet = tetrahedrontraverse();
+  while (t.tet != NULL) {
+    pts = (point *) t.tet;
+    if (pts[7] != dummypoint) {
+      if ((marklist[pointmark(pts[4])] + marklist[pointmark(pts[5])] +
+           marklist[pointmark(pts[6])] + marklist[pointmark(pts[7])]) == 3) {
+        // Find a tet containing the search face.
+        for (t.loc = 0; t.loc < 4; t.loc++) {
+          sym(t, t1);
+          pts = (point *) t1.tet;
+          if ((marklist[pointmark(pts[4])] + marklist[pointmark(pts[5])] +
+              marklist[pointmark(pts[6])] + 
+              (pts[7] != dummypoint ? marklist[pointmark(pts[7])] : 0)) == 3)
+            break;
+        }
+        assert(t.loc < 4);
+        // Now t and t1 share the face.
+        printf("  tet x%lx (%d, %d, %d, %d) %d\n", (unsigned long) t.tet,
+          pointmark(org(t)), pointmark(dest(t)), pointmark(apex(t)), 
+          pointmark(oppo(t)), t.loc);
+        printf("  tet x%lx (%d, %d, %d, %d) %d\n", (unsigned long) t1.tet,
+          pointmark(org(t1)), pointmark(dest(t1)), pointmark(apex(t1)),
+          pointmark(oppo(t1)), t1.loc);
+        if ((point) t1.tet[7] != dummypoint) {
+          pts = (point *) t.tet;
+          sign = insphere(pts[4], pts[5], pts[6], pts[7], oppo(t1));
+          printf("  %s (sign = %.g).\n", sign > 0 ? "Delaunay" :
+            (sign < 0 ? "Non-Delaunay" : "Cosphere"), sign);
+          if (sign == 0) {
+            sign = insphere_sos(pts[4], pts[5], pts[6], pts[7], oppo(t1));
+            printf("  %s (symbolic).\n", sign > 0 ? "Delaunay":"Non-Delaunay");
+          }
+        }
+        break;
+      }
+    }
+    t.tet = tetrahedrontraverse();
+  }
+  
+  if (t.tet == NULL) {
+    printf("  !! Not exist.\n");
+  }
+  delete [] marklist;
+}
+
+bool tetgenmesh::pedge(int i, int j)
+{
+  triface t, t1;
+  face ssub, sseg;
+  int ii;
+
+  t.ver = t1.ver = 0;
+  tetrahedronpool->traversalinit();
+  t.tet = tetrahedrontraverse();
+  while (t.tet != NULL) {
+    for (ii = 0; ii < 6; ii++) {
+      t.loc = edge2locver[ii][0];
+      t.ver = edge2locver[ii][1];
+      if ((pointmark(org(t)) == i && pointmark(dest(t)) == j) ||
+          (pointmark(org(t)) == j && pointmark(dest(t)) == i)) break;
+    }
+    if (ii < 6) {
+      // Now t is the edge (i, j). Find all tets at (i, j).
+      t1 = t;
+      do {
+        printf("  tet x%lx (%d, %d, %d, %d)", (unsigned long) t1.tet,
+          pointmark(org(t1)), pointmark(dest(t1)), pointmark(apex(t1)), 
+          pointmark(oppo(t1)));
+        if (checksubsegs) {
+          tsspivot(t1, sseg);
+          if (sseg.sh != NULL) {
+            printf(" (seg)");
+          }
+        }
+        if (checksubfaces) {
+          tspivot(t1, ssub);
+          if (ssub.sh != NULL) {
+            printf(" (sub)");
+          }
+        } 
+        if (edgemarked(t1)) {
+          printf(" (marked)");
+        }
+        printf("\n");
+        // Go to the next tet.
+        fnextself(t1);
+      } while (t1.tet != t.tet);
+      break;
+    }
+    t.tet = tetrahedrontraverse();
+  }
+  
+  if (t.tet == NULL) {
+    printf("  !! Not exist.\n");
+  }
+  return t.tet != NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Find the subface with indices (i, j, k)
+
+void tetgenmesh::psubface(int i, int j, int k)
+{
+  triface t, t1;
+  face s, s1;
+  point *pts;
+  REAL n[3], sign;
+  int *marklist;
+  int ii;
+
+  void **bakpathblock = subfacepool->pathblock;
+  void *bakpathitem = subfacepool->pathitem;
+  int bakpathitemsleft = subfacepool->pathitemsleft;
+  int bakalignbytes = subfacepool->alignbytes;
+
+  marklist = new int[pointpool->items + 1];
+  for (ii = 0; ii < pointpool->items + 1; ii++) marklist[ii] = 0;
+  // Marke the given indices. 
+  marklist[i] = marklist[j] = marklist[k] = 1;
+
+  s.shver = 0;
+  subfacepool->traversalinit();
+  s.sh = shellfacetraverse(subfacepool);
+  while (s.sh != NULL) {
+    pts = (point *) s.sh;
+    if (pts[3] != NULL) {
+      if ((marklist[pointmark(pts[3])] + marklist[pointmark(pts[4])] +
+           marklist[pointmark(pts[5])]) == 3) {
+        // Found.
+        printf("  sub x%lx (%d, %d, %d) mark=%d\n", (unsigned long) s.sh,
+          pointmark(pts[3]), pointmark(pts[4]), pointmark(pts[5]),
+          getshellmark(s));
+        facenormal(pts[3], pts[4], pts[5], n, 1);
+        printf("    area=%g, lengths: %g, %g, %g\n", 0.5 * sqrt(DOT(n, n)),
+          DIST(pts[3], pts[4]), DIST(pts[4], pts[5]), DIST(pts[5], pts[3]));
+        // Print coplanar adjacent subfaces.
+        s.shver = 0;
+        for (ii = 0; ii < 3; ii++) {
+          sspivot(s, s1);
+          if (s1.sh != NULL) {
+            printf("  seg x%lx (%d, %d)\n", (unsigned long) s1.sh, 
+              pointmark(sorg(s1)), pointmark(sdest(s1)));
+          } else {
+            spivot(s, s1);
+            if (s1.sh != NULL) {
+              printf("  sub x%lx (%d, %d, %d)\n", (unsigned long) s1.sh, 
+          pointmark(sorg(s1)), pointmark(sdest(s1)), pointmark(sapex(s1)));
+            } else {
+              printf("  No seg and sub at (%d, %d)!\n", pointmark(sorg(s)), 
+                pointmark(sdest(s)));
+            }
+          }
+          senextself(s);
+        }
+        stpivot(s, t);
+        if (t.tet != NULL) {
+          // Print two adjacent tets.
+          symedge(t, t1);
+          // Now t and t1 share the face.
+          printf("  tet x%lx (%d, %d, %d, %d) %d\n", (unsigned long) t.tet,
+            pointmark(org(t)), pointmark(dest(t)), pointmark(apex(t)), 
+            pointmark(oppo(t)), t.loc);
+          printf("  tet x%lx (%d, %d, %d, %d) %d\n", (unsigned long) t1.tet,
+            pointmark(org(t1)), pointmark(dest(t1)), pointmark(apex(t1)),
+            pointmark(oppo(t1)), t1.loc);
+          if (((point) t1.tet[7] != dummypoint) && 
+              ((point) t.tet[7] != dummypoint)) {
+            pts = (point *) t.tet;
+            sign = insphere(pts[4], pts[5], pts[6], pts[7], oppo(t1));
+            printf("  %s (sign = %.g).\n", sign > 0 ? "Delaunay" :
+              (sign < 0 ? "Non-Delaunay" : "Cosphere"), sign);
+            if (sign == 0) {
+            sign = insphere_sos(pts[4], pts[5], pts[6], pts[7], oppo(t1));
+            printf("  %s (symbolic).\n", sign > 0 ? "Delaunay":"Non-Delaunay");
+            }
+          }
+        }
+        break;
+      }
+    }
+    s.sh = shellfacetraverse(subfacepool);
+  }
+
+  if (s.sh == NULL) {
+    printf("  !! Not exist.\n");
+  }
+  delete [] marklist;
+
+  subfacepool->pathblock = bakpathblock;
+  subfacepool->pathitem = bakpathitem;
+  subfacepool->pathitemsleft = bakpathitemsleft;
+  subfacepool->alignbytes = bakalignbytes;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Print the information of the subsegment (i, j).
+
+void tetgenmesh::psubseg(int i, int j)
+{
+  face s; //, s1;
+  point forg, fdest;
+  bool bflag;
+
+  bflag = false;
+  s.shver = 0;
+  subsegpool->traversalinit();
+  s.sh = shellfacetraverse(subsegpool);
+  while (s.sh != NULL) {
+    if (pointmark(sorg(s)) == i) {
+      if (pointmark(sdest(s)) == j) {
+        bflag = true;
+      }
+    } else if (pointmark(sorg(s)) == j) {
+      if (pointmark(sdest(s)) == i) {
+        sesymself(s);
+        bflag = true;
+      }
+    }
+    if (bflag) {
+      // Print the original segment containing [i, j]
+      forg = farsorg(s);
+      fdest = farsdest(s);
+      printf("  seg x%lx (%d, %d) < (%d, %d)\n", (unsigned long) s.sh, i, j,
+        pointmark(forg), pointmark(fdest));
+      /*// Print the adjacent subsegments at i and j.
+      senext2(s, s1);
+      spivotself(s1);
+      if (s1.sh != NULL) {
+        if (sdest(s1) != i) sesymself(s1);
+        printf("  [%d] seg x%lx (%d, %d)\n", i, (unsigned long) s1.sh,
+          pointmark(sorg(s1)), pointmark(sdest(s1))); 
+      } else {
+        printf("  [%d] NULL", i);
+      }
+      senext(s, s1);
+      spivotself(s1);
+      if (s1.sh != NULL) {
+        if (sorg(s1) != j) sesymself(s1);
+        printf("  [%d] seg x%lx (%d, %d)\n", j, (unsigned long) s1.sh,
+          pointmark(sorg(s1)), pointmark(sdest(s1))); 
+      } else {
+        printf("  [%d] NULL", j);
+      }*/
+      break;
+    }
+    s.sh = shellfacetraverse(subsegpool);
+  }
+
+  if (!bflag) {
+    printf("  !! Not exist.\n");
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Print the index of the point.
+
+int tetgenmesh::pmark(point p)
+{
+  return pointmark(p);
+}
+
+void tetgenmesh::pvert(point pt)
+{
+  triface adjtet;
+  int idx;
+
+  idx = ((int *) (pt))[pointmarkindex];
+  printf("  vertex %d: x%lx\n", idx, (unsigned long) pt);
+  idx = ((int *) (pt))[pointmarkindex + 1];
+  printf("  type: %d (%s infected).\n", idx >> 1, idx & 1 ? " " : "not");
+
+  decode(point2tet(pt), adjtet);
+  if (adjtet.tet != NULL) {
+    printf("  adjtet: x%lx (%d, %d, %d, %d).\n", (unsigned long) adjtet.tet,
+      pointmark(adjtet.tet[4]), pointmark(adjtet.tet[5]),
+      pointmark(adjtet.tet[6]), pointmark(adjtet.tet[7]));
+  } else {
+    printf("  No adjacent tet.\n");
+  }
+}
+
+int tetgenmesh::pverti(int idx)
+{
+  triface adjtet;
+  point pt;
+
+  // Search the vertex.
+  pointpool->traversalinit();
+  pt = pointtraverse();
+  while (pt != NULL) {
+    if (idx == ((int *) (pt))[pointmarkindex]) break;
+    pt = pointtraverse();
+  }
+
+  if (pt == NULL) {
+    printf(" Not exist.\n");
+    return 0;
+  }
+
+  printf("  vertex %d: x%lx\n", idx, (unsigned long) pt);
+  idx = ((int *) (pt))[pointmarkindex + 1];
+  printf("  type: %d (%s infected).\n", idx >> 1, idx & 1 ? " " : "not");
+
+  decode(point2tet(pt), adjtet);
+  if (adjtet.tet == NULL) {
+    printf("  No adjacent tet.\n");
+    return 0;
+  }
+  if (adjtet.tet[4] == NULL) {
+    printf("  !! A DEAD adjacent tet.\n");
+    return 0;
+  }
+  printf("  adjtet: x%lx (%d, %d, %d, %d).\n", (unsigned long) adjtet.tet,
+    pointmark(adjtet.tet[4]), pointmark(adjtet.tet[5]),
+    pointmark(adjtet.tet[6]), pointmark(adjtet.tet[7]));
+
+  if (((point) adjtet.tet[4] == pt) || ((point) adjtet.tet[5] == pt) ||
+      ((point) adjtet.tet[6] == pt) || ((point) adjtet.tet[7] == pt)) {
+    return 0;
+  } else {
+    return 1;  // Bad point-to-tet map.
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Geometrical tests.
+
+REAL tetgenmesh::test_orient3d(int i, int j, int k, int l)
+{
+  point *idx2ptmap;
+  REAL ori;
+  int idx;
+
+  idx = (int) pointpool->items;
+  if ((i > idx) || (j > idx) || (k > idx) || (l > idx)) {
+    printf("Input indices are invalid.\n");
+    return 0;
+  }
+
+  makeindex2pointmap(idx2ptmap);
+  ori = orient3d(idx2ptmap[i], idx2ptmap[j], idx2ptmap[k], idx2ptmap[l]);
+  delete [] idx2ptmap;
+  
+  return ori;
+}
+
+REAL tetgenmesh::test_insphere(int i, int j, int k, int l, int m)
+{
+  point *idx2ptmap;
+  REAL sign;
+  int idx;
+
+  idx = (int) pointpool->items;
+  if ((i > idx) || (j > idx) || (k > idx) || (l > idx) || (m > idx)) {
+    printf("Input indices are invalid.\n");
+    return 0;
+  }
+
+  makeindex2pointmap(idx2ptmap);
+  sign = insphere(idx2ptmap[i], idx2ptmap[j], idx2ptmap[k], idx2ptmap[l],
+                  idx2ptmap[m]);
+  if (sign == 0) {
+    printf("  sign == 0.0! (symbolic perturbed) \n");
+    sign = insphere_sos(idx2ptmap[i], idx2ptmap[j], idx2ptmap[k], idx2ptmap[l],
+                        idx2ptmap[m]);
+  }
+  delete [] idx2ptmap;
+  
+  return sign;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// test_tritri()    Test if two triangles are intersecting.
+
+int tetgenmesh::test_tritri(int a, int b, int c, int p,  int q, int r)
+{
+  point *idx2ptmap;
+  point A, B, C, P, Q, R;
+  enum intersection dir;
+  int ret, types[2], pos[4];
+  int idx, i;
+
+  idx = (int) pointpool->items;
+  if ((a > idx) || (b > idx) || (c > idx) || 
+      (p > idx) || (q > idx) || (r > idx) ||
+      (a<in->firstnumber) || (b<in->firstnumber) || (c<in->firstnumber) || 
+      (p<in->firstnumber) || (q<in->firstnumber) || (r<in->firstnumber)) {
+    printf("Input indices are invalid.\n");
+    return 0;
+  }
+
+  makeindex2pointmap(idx2ptmap);
+  A = idx2ptmap[a];
+  B = idx2ptmap[b];
+  C = idx2ptmap[c];
+  P = idx2ptmap[p];
+  Q = idx2ptmap[q];
+  R = idx2ptmap[r];
+
+  ret = tri_tri_test(A, B, C, P, Q, R, NULL, 1, types, pos);
+
+  // Report the intersection types and positions.
+  for (i = 0; i < 2; i++) {
+    dir = (enum tetgenmesh::intersection) types[i];
+    switch (dir) {
+    case tetgenmesh::DISJOINT: 
+      printf("  DISJOINT\n"); break;
+    case tetgenmesh::SHAREVERT: 
+      printf("  SHAREVERT %d %d\n", pos[i*2], pos[i*2+1]); break;
+    case tetgenmesh::SHAREEDGE: 
+      printf("  SHAREEDGE %d %d\n", pos[i*2], pos[i*2+1]); break;
+    case tetgenmesh::SHAREFACE: 
+      printf("  SHAREFACE\n"); break;
+    case tetgenmesh::TOUCHEDGE: 
+      printf("  TOUCHEDGE %d %d\n", pos[i*2], pos[i*2+1]); break;
+    case tetgenmesh::TOUCHFACE: 
+      printf("  TOUCHFACE %d %d\n", pos[i*2], pos[i*2+1]); break;
+    case tetgenmesh::ACROSSVERT: 
+      printf("  ACROSSVERT %d %d\n", pos[i*2], pos[i*2+1]); break;
+    case tetgenmesh::ACROSSEDGE: 
+      printf("  ACROSSEDGE %d %d\n", pos[i*2], pos[i*2+1]); break;
+    case tetgenmesh::ACROSSFACE: 
+      printf("  ACROSSFACE %d %d\n", pos[i*2], pos[i*2+1]); break;
+    case tetgenmesh::ACROSSTET: 
+      printf("  ACROSSTET\n"); break;
+    case tetgenmesh::TRIEDGEINT:
+      printf("  TRIEDGEINT %d %d\n", pos[i*2], pos[i*2+1]); break;
+    case tetgenmesh::EDGETRIINT:
+      printf("  EDGETRIINT %d %d\n", pos[i*2], pos[i*2+1]); break;
+    }
+  }
+
+  delete [] idx2ptmap;
+  return ret;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Print an array of tetrahedra (in draw command)
+
+void tetgenmesh::print_cavebdrylist()
+{
+  FILE *fout;
+  triface *cavetet;
+  int i;
+
+  printf("  Dump %ld faces to dump_cavebdry.lua.\n", cavebdrylist->objects);
+
+  fout = fopen("dump_cavebdry.lua", "w");
+  for (i = 0; i < cavebdrylist->objects; i++) {
+    cavetet = (triface *) fastlookup(cavebdrylist, i);
+    fprintf(fout, "p:draw_subface(%d, %d, %d) -- %d\n", 
+      pointmark(org(*cavetet)), pointmark(dest(*cavetet)), 
+      pointmark(apex(*cavetet)), i);
+  }
+  fclose(fout);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Print current faces in flipstack (in draw command)
+
+void tetgenmesh::print_flipstack()
+{
+  badface *traveface;
+  int i;
+
+  traveface = futureflip; 
+  i = 0;
+  while (traveface != NULL) {
+    if (traveface->tt.tet[4] != NULL) {
+      printf("%2d  (%d, %d, %d, %d) - %d\n",i+1,pointmark(org(traveface->tt)),
+        pointmark(dest(traveface->tt)), pointmark(apex(traveface->tt)),
+        pointmark(oppo(traveface->tt)), pointmark(traveface->foppo));
+    }
+    traveface = traveface->nextitem;
+    i++;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Print an array of tetrahedra, faces, subfaces (in draw command)
+// If 'nohulltet' is TRUE, ignore hull tets.
+
+void tetgenmesh::print_tetarray(arraypool *tetarray, bool nohulltet)
+{
+  triface *parytet;
+  int i;
+
+  for (i = 0; i < tetarray->objects; i++) {
+    parytet = (triface *) fastlookup(tetarray, i);
+    if (parytet->tet == NULL) {
+      printf("-- NOT A TET -- %d\n", i + 1); continue;
+    }
+    if (nohulltet) {
+      if ((point) parytet->tet[7] == dummypoint) continue;
+    }
+    if (parytet->tet[4] == NULL) {
+      printf("-- A DEAD TET -- %d\n", i + 1); continue;
+    }
+    if ((point) parytet->tet[7] != dummypoint) {
+      printf("p:draw_tet(%d, %d, %d, %d) -- %d", 
+        pointmark(org(*parytet)), pointmark(dest(*parytet)),
+        pointmark(apex(*parytet)), pointmark(oppo(*parytet)), i + 1);
+    } else {
+      printf("-- p:draw_tet(%d, %d, %d, %d) -- %d (hulltet)", 
+        pointmark(org(*parytet)), pointmark(dest(*parytet)),
+        pointmark(apex(*parytet)), pointmark(oppo(*parytet)), i + 1);
+    }
+    if (marktested(*parytet)) {
+      printf(" (marked)");
+    }
+    if (infected(*parytet)) {
+      printf(" (infect)");
+    }
+    printf("\n");
+  }
+}
+
+void tetgenmesh::print_facearray(arraypool *facearray)
+{
+  triface *parytet;
+  int i;
+
+  for (i = 0; i < facearray->objects; i++) {
+    parytet = (triface *) fastlookup(facearray, i);
+    printf("p:draw_subface(%d, %d, %d) -- %d\n", 
+      pointmark(org(*parytet)), pointmark(dest(*parytet)),
+      pointmark(apex(*parytet)), i + 1);
+  }
+}
+
+void tetgenmesh::print_subfacearray(arraypool *subfacearray)
+{
+  face *parysub;
+  int i;
+
+  for (i = 0; i < subfacearray->objects; i++) {
+    parysub = (face *) fastlookup(subfacearray, i);
+    printf("p:draw_subface(%d, %d, %d) -- %d\n", 
+      pointmark(sorg(*parysub)), pointmark(sdest(*parysub)),
+      pointmark(sapex(*parysub)), i + 1);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// dump the boundary faces of a cavity into file "cavity.lua"
+// 'topfaces' and 'botfaces' are two arrays. 
+// NOTE: hull tets may be included.
+
+void tetgenmesh::dump_cavity(arraypool *topfaces, arraypool *botfaces = NULL)
+{
+  FILE *fout;
+  arraypool *cavfaces;
+  triface *paryface;
+  int i, k;
+
+  printf("  dump %ld topfaces to cavity.lua\n", topfaces->objects);
+  if (botfaces != NULL) {
+    printf("  dump %ld botfaces to cavity.lua\n", botfaces->objects);
+  }
+  fout = fopen("cavity.lua", "w");
+
+  for (k = 0; k < 2; k++) {
+    cavfaces = (k == 0 ? topfaces : botfaces);
+    if (cavfaces != NULL) {
+      for (i = 0; i < cavfaces->objects; i++) {
+        paryface = (triface *) fastlookup(cavfaces, i);
+        fprintf(fout, "p:draw_subface(%d, %d, %d) -- %d\n", 
+          pointmark(org(*paryface)), pointmark(dest(*paryface)),
+          pointmark(apex(*paryface)), i + 1);
+      }
+    }
+  }
+
+  fclose(fout);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// dump a facet containing a given subface s.
+
+void tetgenmesh::dump_facetof(face *pssub, char *filename)
+{
+  FILE *fout;
+  char outfilename[256];
+  arraypool *tmpfaces;
+  face *parysh, *parysh2, s;
+  face checkseg;
+  int ii, jj;
+
+  tmpfaces = new arraypool(sizeof(face), 8);
+
+  smarktest(*pssub);
+  tmpfaces->newindex((void **) &parysh);
+  *parysh = *pssub;
+
+  for (ii = 0; ii < tmpfaces->objects; ii++) {
+    parysh = (face *) fastlookup(tmpfaces, ii);
+    for (jj = 0; jj < 3; jj++) {
+      sspivot(*parysh, checkseg);
+      if (checkseg.sh == NULL) {
+        spivot(*parysh, s);
+        if (s.sh != NULL) {
+          if (!smarktested(s)) {
+            smarktest(s);
+            tmpfaces->newindex((void **) &parysh2);
+            *parysh2 = s;
+          }
+        }
+      }
+      senextself(*parysh);
+    }
+  }
+
+  for (ii = 0; ii < tmpfaces->objects; ii++) {
+    parysh = (face *) fastlookup(tmpfaces, ii);
+    sunmarktest(*parysh);
+  }
+
+  if (filename != NULL) {
+    sprintf(outfilename, filename);
+  } else {
+    sprintf(outfilename, "facet.lua");
+  }
+
+  printf("  dump %ld subfaces to %s\n", tmpfaces->objects, outfilename);
+  fout = fopen(outfilename, "w");
+
+  for (ii = 0; ii < tmpfaces->objects; ii++) {
+    parysh = (face *) fastlookup(tmpfaces, ii);
+    fprintf(fout, "p:draw_subface(%d, %d, %d) -- %d\n", 
+      pointmark(sorg(*parysh)), pointmark(sdest(*parysh)),
+      pointmark(sapex(*parysh)), ii + 1);
+  }
+
+  fclose(fout);
+
+  delete tmpfaces;
+}
+
+#endif // #ifndef meshstatCXX
\ No newline at end of file
diff --git a/contrib/Tetgen/surface.cxx b/contrib/Tetgen/surface.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b0305591abb2247454d9e24ef258673532bb8f1e
--- /dev/null
+++ b/contrib/Tetgen/surface.cxx
@@ -0,0 +1,1779 @@
+#ifndef surfaceCXX
+#define surfaceCXX
+
+#include "tetgen.h"
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// calculateabovepoint()    Calculate a point above a facet in 'dummypoint'. //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenmesh::calculateabovepoint(arraypool *facpoints, point *ppa,
+  point *ppb, point *ppc)
+{
+  point *ppt, pa, pb, pc;
+  REAL v1[3], v2[3], n[3];
+  REAL lab, len, A, area;
+  REAL x, y, z;
+  int i;
+
+  ppt = (point *) fastlookup(facpoints, 0);
+  pa = *ppt; // a is the first point.
+
+  // Get a point b s.t. the length of [a, b] is maximal.
+  lab = 0;
+  for (i = 1; i < facpoints->objects; i++) {
+    ppt = (point *) fastlookup(facpoints, i);
+    x = (*ppt)[0] - pa[0];
+    y = (*ppt)[1] - pa[1];
+    z = (*ppt)[2] - pa[2];
+    len = x * x + y * y + z * z;
+    if (len > lab) {
+      lab = len;
+      pb = *ppt;
+    }
+  }
+  lab = sqrt(lab);
+  if (lab == 0) {
+    if (!b->quiet) {
+      printf("Warning:  All points of a facet are coincident with %d.\n",
+        pointmark(pa));
+    }
+    return false;
+  }
+
+  // Get a point c s.t. the area of [a, b, c] is maximal.
+  v1[0] = pb[0] - pa[0];
+  v1[1] = pb[1] - pa[1];
+  v1[2] = pb[2] - pa[2];
+  A = 0;
+  for (i = 1; i < facpoints->objects; i++) {
+    ppt = (point *) fastlookup(facpoints, i);
+    v2[0] = (*ppt)[0] - pa[0];
+    v2[1] = (*ppt)[1] - pa[1];
+    v2[2] = (*ppt)[2] - pa[2];
+    CROSS(v1, v2, n);
+    area = DOT(n, n);
+    if (area > A) {
+      A = area;
+      pc = *ppt;
+    }
+  }
+  if (A == 0) {
+    // All points are collinear. No above point.
+    if (!b->quiet) {
+      printf("Warning:  All points of a facet are collinaer with [%d, %d].\n",
+        pointmark(pa), pointmark(pb));
+    }
+    return false;
+  }
+
+  // Calculate an above point of this facet.
+  facenormal(pa, pb, pc, n, 1);
+  len = sqrt(DOT(n, n));
+  n[0] /= len;
+  n[1] /= len;
+  n[2] /= len;
+  lab /= 2.0;
+  dummypoint[0] = 0.5 * (pa[0] + pb[0]) + lab * n[0];
+  dummypoint[1] = 0.5 * (pa[1] + pb[1]) + lab * n[1];
+  dummypoint[2] = 0.5 * (pa[2] + pb[2]) + lab * n[2];
+
+  if (ppa != NULL) {
+    // Return the three points.
+    *ppa = pa;
+    *ppb = pb;
+    *ppc = pc;
+  }
+
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// slocate()    Locate a point in a surface triangulation.                   //
+//                                                                           //
+// Search the point (p) from the input 'searchsh' (it should not be NULL).   //
+//                                                                           //
+// It is assumed that 'dummypoint' lies above the facet of the triangulation,//
+// hence a CCW test (2D orientation) is equal to a below-plane (3D) test.    //
+//                                                                           //
+// The returned value inducates the following cases:                         //
+//   - ONVERTEX, p is the origin of 'searchsh'.                              //
+//   - ONEDGE, p lies on the edge of 'searchsh'.                             //
+//   - ONFACE, p lies in the interior of 'searchsh'.                         //
+//   - OUTSIDE, p lies outside of the triangulation, p is on the left-hand   //
+//     side of the edge 'searchsh'(s), i.e., org(s), dest(s), p are CW.      //
+//                                                                           //
+// If 'cflag' is not TRUE, the triangulation may not be convex.  Stop search //
+// when a segment is met and return OUTSIDE.                                 //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+enum tetgenmesh::location tetgenmesh::slocate(point searchpt, face* searchsh, 
+  bool cflag)
+{
+  face neighsh;
+  face checkseg;
+  point pa, pb, pc, pd;
+  REAL ori, ori_bc, ori_ca;
+  REAL dist_bc, dist_ca;
+  int i;
+
+  enum {MOVE_BC, MOVE_CA} nextmove;
+
+  shellface sptr;
+
+  // Adjust the face orientation s.t. 'dummypt' lies above to it.
+  pa = sorg(*searchsh);
+  pb = sdest(*searchsh);
+  pc = sapex(*searchsh);
+  ori = orient3d(pa, pb, pc, dummypoint);
+  assert(ori != 0); // SELF_CHECK
+  if (ori > 0) {
+    sesymself(*searchsh); // Reverse the face orientation.
+  }
+
+  // Find an edge of the face s.t. p lies on its right-hand side (CCW).
+  for (i = 0; i < 3; i++) {
+    pa = sorg(*searchsh);
+    pb = sdest(*searchsh);
+    ori = orient3d(pa, pb, dummypoint, searchpt);
+    if (ori > 0) break;
+    senextself(*searchsh);
+  }
+  assert(i < 3); // SELF_CHECK
+
+  while (1) {
+
+    pc = sapex(*searchsh);
+
+    if (pc == searchpt) {
+      senext2self(*searchsh);
+      return ONVERTEX;
+    }
+
+    ori_bc = orient3d(pb, pc, dummypoint, searchpt);
+    ori_ca = orient3d(pc, pa, dummypoint, searchpt);
+
+    if (ori_bc < 0) {
+      if (ori_ca < 0) { // (--)
+        // Any of the edges is a viable move.
+        senext(*searchsh, neighsh); // At edge [b, c].
+        spivotself(neighsh);
+        if (neighsh.sh != NULL) {
+          pd = sapex(neighsh);
+          dist_bc = NORM2(searchpt[0] - pd[0], searchpt[1] - pd[1],
+            searchpt[2] - pd[2]);
+        } else {
+          dist_bc = NORM2(xmax - xmin, ymax - ymin, zmax - zmin);
+        }
+        senext2(*searchsh, neighsh); // At edge [c, a].
+        spivotself(neighsh);
+        if (neighsh.sh != NULL) {
+          pd = sapex(neighsh);
+          dist_ca = NORM2(searchpt[0] - pd[0], searchpt[1] - pd[1],
+            searchpt[2] - pd[2]);
+        } else {
+          dist_ca = dist_bc;
+        }
+        if (dist_ca < dist_bc) {
+          nextmove = MOVE_CA;
+        } else {
+          nextmove = MOVE_BC;
+        }
+      } else { // (-#)
+        // Edge [b, c] is viable.
+        nextmove = MOVE_BC;
+      }
+    } else {
+      if (ori_ca < 0) { // (#-)
+        // Edge [c, a] is viable.
+        nextmove = MOVE_CA;
+      } else {
+        if (ori_bc > 0) {
+          if (ori_ca > 0) { // (++)
+            return ONFACE;  // Inside [a, b, c].
+          } else { // (+0)
+            senext2self(*searchsh); // On edge [c, a].
+            return ONEDGE;
+          }
+        } else { // ori_bc == 0
+          if (ori_ca > 0) { // (0+)
+            senextself(*searchsh); // On edge [b, c].
+            return ONEDGE;
+          } else { // (00)
+            // On vertex c. Should be checked in above.
+            assert(0); // SELF_CHECK
+          }
+        }
+      }
+    }
+
+    // Move to the next face.
+    if (nextmove == MOVE_BC) {
+      senextself(*searchsh);
+    } else {
+      senext2self(*searchsh);
+    }
+    if (!cflag) {
+      // NON-convex case. Chekc if we will cross a boundary.
+      sspivot(*searchsh, checkseg);
+      if (checkseg.sh != NULL) {
+        return OUTSIDE; // Do not cross a boundary edge.
+      }
+    }
+    spivot(*searchsh, neighsh);
+    if (neighsh.sh == NULL) {
+      return OUTSIDE; // A hull edge.
+    }
+    // Adjust the edge orientation.
+    if (sorg(neighsh) != sdest(*searchsh)) {
+      sesymself(neighsh);
+    }
+    assert(sorg(neighsh) == sdest(*searchsh)); // SELF_CHECK
+
+    // Update the newly discovered face and its endpoints.
+    *searchsh = neighsh;
+    pa = sorg(*searchsh);
+    pb = sdest(*searchsh);
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// sinsertvertex()    Insert a vertex into a triangulation of a facet.       //
+//                                                                           //
+// The new point (p) will be located. Searching from 'splitsh'. If 'splitseg'//
+// is not NULL, p is on a segment, no search is needed.                      //
+//                                                                           //
+// If 'cflag' is not TRUE, the triangulation may be not convex. Don't insert //
+// p if it is found in outside.                                              //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+enum tetgenmesh::location tetgenmesh::sinsertvertex(point insertpt, 
+  face *splitsh, face *splitseg, bool bwflag, bool cflag)
+{
+  face *abfaces, *parysh, *pssub;
+  face neighsh, newsh, casout, casin;
+  face aseg, bseg, aoutseg, boutseg;
+  face checkseg;
+  triface neightet;
+  point pa, pb, pc;
+  enum location loc;
+  REAL sign, ori, area;
+  int n, s, i, j;
+
+  tetrahedron ptr;
+  shellface sptr;
+
+  if (splitseg != NULL) {
+    spivot(*splitseg, *splitsh);
+    loc = ONEDGE;
+  } else {
+    assert(splitsh->sh != NULL); // SELF_CHECK
+    loc = slocate(insertpt, splitsh, false);
+  }
+
+  // Return if p lies on a vertex.
+  if (loc == ONVERTEX) return loc;
+
+  if (loc == OUTSIDE) {
+    // Return if 'cflag' is not set.
+    if (!cflag) return loc;
+  }
+
+  if (loc == ONEDGE) {
+    if (splitseg == NULL) {
+      // Do not split a segment.
+      sspivot(*splitsh, checkseg);
+      if (checkseg.sh != NULL) return loc; // return ONSUBSEG;
+      // Check if this edge is on the hull.
+      spivot(*splitsh, neighsh);
+      if (neighsh.sh == NULL) {
+        // A convex hull edge. The new point is on the hull.
+        loc = OUTSIDE;
+      }
+    }
+  }
+
+  if (b->verbose > 1) {
+    pa = sorg(*splitsh);
+    pb = sdest(*splitsh);
+    pc = sapex(*splitsh);
+    printf("    Insert point %d (%d, %d, %d) loc %d\n", pointmark(insertpt),
+      pointmark(pa), pointmark(pb), pointmark(pc), (int) loc);
+  }
+
+  // Does 'insertpt' lie on a segment?
+  if (splitseg != NULL) {
+    splitseg->shver = 0;
+    pa = sorg(*splitseg);
+    // Count the number of faces at segment [a, b].
+    n = 0;
+    neighsh = *splitsh;
+    do {
+      spivotself(neighsh);
+      n++;
+    } while ((neighsh.sh != NULL) && (neighsh.sh != splitsh->sh));
+    // n is at least 1.
+    abfaces = new face[n];
+    // Collect faces at seg [a, b].
+    abfaces[0] = *splitsh;
+    if (sorg(abfaces[0]) != pa) sesymself(abfaces[0]);
+    for (i = 1; i < n; i++) {
+      spivot(abfaces[i - 1], abfaces[i]);
+      if (sorg(abfaces[i]) != pa) sesymself(abfaces[i]);
+    }
+  }
+
+  // Initialize the cavity.
+  if (loc == ONEDGE) {
+    smarktest(*splitsh);
+    caveshlist->newindex((void **) &parysh);
+    *parysh = *splitsh;
+    if (splitseg != NULL) {
+      for (i = 1; i < n; i++) {
+        smarktest(abfaces[i]);
+        caveshlist->newindex((void **) &parysh);
+        *parysh = abfaces[i];
+      }
+    } else {
+      spivot(*splitsh, neighsh);
+      if (neighsh.sh != NULL) {
+        smarktest(neighsh);
+        caveshlist->newindex((void **) &parysh);
+        *parysh = neighsh;
+      }
+    }
+  } else if (loc == ONFACE) {
+    smarktest(*splitsh);
+    caveshlist->newindex((void **) &parysh);
+    *parysh = *splitsh;
+  } else { // loc == OUTSIDE;
+    // This is only possible when T is convex.
+    assert(cflag); // SELF_CHECK
+    // Assume p is on top of the edge ('splitsh'). Find a right-most edge
+    //   which is visible by p.
+    neighsh = *splitsh;
+    while (1) {
+      senext2self(neighsh);
+      spivot(neighsh, casout);
+      if (casout.sh == NULL) {
+        // A convex hull edge. Is it visible by p.
+        pa = sorg(neighsh);
+        pb = sdest(neighsh);
+        ori = orient3d(pa, pb, dummypoint, insertpt);
+        if (ori < 0) {
+          *splitsh = neighsh; // Update 'splitsh'.
+        } else {
+          break; // 'splitsh' is the right-most visible edge.
+        }
+      } else {
+        if (sorg(casout) != sdest(neighsh)) sesymself(casout);
+        neighsh = casout;
+      }
+    }
+    // Create new triangles for all visible edges of p (from right to left).
+    casin.sh = NULL;  // No adjacent face at right.
+    pa = sorg(*splitsh);
+    pb = sdest(*splitsh);
+    while (1) {
+      // Create a new subface on top of the (visible) edge.
+      makeshellface(subfacepool, &newsh); 
+      setshvertices(newsh, pb, pa, insertpt);
+      setshellmark(newsh, getshellmark(*splitsh));
+      if (checkconstraints) {
+        area = areabound(*splitsh);
+        areabound(newsh) = area;
+      }
+      // Connect the new subface to the bottom subfaces.
+      sbond1(newsh, *splitsh);
+      sbond1(*splitsh, newsh);
+      // Connect the new subface to its right-adjacent subface.
+      if (casin.sh != NULL) {
+        senext(newsh, casout);
+        sbond1(casout, casin);
+        sbond1(casin, casout);
+      }
+      // The left-adjacent subface has not been created yet.
+      senext2(newsh, casin);
+      // Add the new face into list.
+      smarktest(newsh);
+      caveshlist->newindex((void **) &parysh);
+      *parysh = newsh;
+      // Move to the convex hull edge at the left of 'splitsh'.
+      neighsh = *splitsh;
+      while (1) {
+        senextself(neighsh);
+        spivot(neighsh, casout);
+        if (casout.sh == NULL) {
+          *splitsh = neighsh;
+          break;
+        }
+        if (sorg(casout) != sdest(neighsh)) sesymself(casout);
+        neighsh = casout;
+      }
+      // A convex hull edge. Is it visible by p.
+      pa = sorg(*splitsh);
+      pb = sdest(*splitsh);
+      ori = orient3d(pa, pb, dummypoint, insertpt);
+      if (ori >= 0) break;
+    }
+  }
+
+  // Form the Bowyer-Watson cavity.
+  for (i = 0; i < caveshlist->objects; i++) {
+    parysh = (face *) fastlookup(caveshlist, i);
+    for (j = 0; j < 3; j++) {
+      sspivot(*parysh, checkseg);
+      if (checkseg.sh == NULL) {
+        spivot(*parysh, neighsh);
+        if (neighsh.sh != NULL) {
+          if (!smarktested(neighsh)) {
+            if (bwflag) {
+              pa = sorg(neighsh);
+              pb = sdest(neighsh);
+              pc = sapex(neighsh);
+              sign = incircle3d(pa, pb, pc, insertpt);
+              if (sign < 0) {
+                smarktest(neighsh);
+                caveshlist->newindex((void **) &pssub);
+                *pssub = neighsh;
+              }
+            } else {
+              sign = 1; // A boundary edge.
+            }
+          } else {
+            sign = -1; // Not a boundary edge.
+          }
+        } else {
+          if (loc == OUTSIDE) {
+            // It is a boundary edge if it does not contain insertp.
+            if ((sorg(*parysh)==insertpt) || (sdest(*parysh)==insertpt)) {
+              sign = -1; // Not a boundary edge.
+            } else {
+              sign = 1; // A boundary edge.
+            }
+          } else {
+            sign = 1; // A boundary edge.
+          }
+        }
+      } else {
+        sign = 1; // A segment!
+      }
+      if (sign >= 0) {
+        // Add a boundary edge.
+        caveshbdlist->newindex((void **) &pssub);
+        *pssub = *parysh;
+      }
+      senextself(*parysh);
+    }
+  }
+
+  // Creating new subfaces.
+  for (i = 0; i < caveshbdlist->objects; i++) {
+    parysh = (face *) fastlookup(caveshbdlist, i);
+    sspivot(*parysh, checkseg);
+    if ((parysh->shver & 01) != 0) sesymself(*parysh);
+    pa = sorg(*parysh);
+    pb = sdest(*parysh);
+    // Create a new subface.
+    makeshellface(subfacepool, &newsh); 
+    setshvertices(newsh, pa, pb, insertpt);
+    setshellmark(newsh, getshellmark(*parysh));
+    if (checkconstraints) {
+      area = areabound(*parysh);
+      areabound(newsh) = area;
+    }
+    // Connect newsh to outer subfaces.
+    spivot(*parysh, casout);
+    if (casout.sh != NULL) {
+      casin = casout;
+      if (checkseg.sh != NULL) {
+        spivot(casin, neighsh);
+        while (neighsh.sh != parysh->sh) {
+          casin = neighsh;
+          spivot(casin, neighsh);
+        }
+      }
+      sbond1(newsh, casout);
+      sbond1(casin, newsh);
+    }
+    if (checkseg.sh != NULL) {
+      ssbond(newsh, checkseg);
+    }
+    // Connect oldsh <== newsh (for connecting adjacent new subfaces).
+    sbond1(*parysh, newsh);
+  }
+
+  // Set a handle for searching.
+  recentsh = newsh;
+
+  // Connect adjacent new subfaces together.
+  for (i = 0; i < caveshbdlist->objects; i++) {
+    // Get an old subface at edge [a, b].
+    parysh = (face *) fastlookup(caveshbdlist, i);
+    sspivot(*parysh, checkseg);
+    spivot(*parysh, newsh); // The new subface [a, b, p].
+    senextself(newsh); // At edge [b, p].
+    spivot(newsh, neighsh);
+    if (neighsh.sh == NULL) {
+      // Find the adjacent new subface at edge [b, p].
+      pb = sdest(*parysh);
+      neighsh = *parysh;
+      while (1) {
+        senextself(neighsh);
+        spivotself(neighsh);
+        if (neighsh.sh == NULL) break;
+        if (!smarktested(neighsh)) break;
+        if (sdest(neighsh) != pb) sesymself(neighsh);
+      }
+      if (neighsh.sh != NULL) {
+        // Now 'neighsh' is a new subface at edge [b, #].
+        if (sorg(neighsh) != pb) sesymself(neighsh);
+        assert(sorg(neighsh) == pb); // SELF_CHECK
+        assert(sapex(neighsh) == insertpt); // SELF_CHECK
+        senext2self(neighsh); // Go to the open edge [p, b].
+        spivot(neighsh, casout); // SELF_CHECK
+        assert(casout.sh == NULL); // SELF_CHECK
+        sbond2(newsh, neighsh);
+      } else {
+        assert(loc == OUTSIDE); // SELF_CHECK
+      }
+    }
+    spivot(*parysh, newsh); // The new subface [a, b, p].
+    senext2self(newsh); // At edge [p, a].
+    spivot(newsh, neighsh);
+    if (neighsh.sh == NULL) {
+      // Find the adjacent new subface at edge [p, a].
+      pa = sorg(*parysh);
+      neighsh = *parysh;
+      while (1) {
+        senext2self(neighsh);
+        spivotself(neighsh);
+        if (neighsh.sh == NULL) break;
+        if (!smarktested(neighsh)) break;
+        if (sorg(neighsh) != pa) sesymself(neighsh);
+      }
+      if (neighsh.sh != NULL) {
+        // Now 'neighsh' is a new subface at edge [#, a].
+        if (sdest(neighsh) != pa) sesymself(neighsh);
+        assert(sdest(neighsh) == pa); // SELF_CHECK
+        assert(sapex(neighsh) == insertpt); // SELF_CHECK
+        senextself(neighsh); // Go to the open edge [a, p].
+        spivot(neighsh, casout); // SELF_CHECK
+        assert(casout.sh == NULL); // SELF_CHECK
+        sbond2(newsh, neighsh);
+      } else {
+        assert(loc == OUTSIDE); // SELF_CHECK
+      }
+    }
+  }
+
+  if (checksubfaces) {
+    // Add all new subfaces into list.
+    for (i = 0; i < caveshbdlist->objects; i++) {
+      // Get an old subface at edge [a, b].
+      parysh = (face *) fastlookup(caveshbdlist, i);
+      spivot(*parysh, newsh); // The new subface [a, b, p].
+      if (b->verbose > 1) {
+        printf("      Queue a new subface (%d, %d, %d).\n",
+          pointmark(sorg(newsh)), pointmark(sdest(newsh)),
+          pointmark(sapex(newsh)));
+      }
+      subfacstack->newindex((void **) &pssub);
+      *pssub = newsh;
+    }
+  }
+
+  if (splitseg != NULL) {
+    // Split the segment [a, b].
+    aseg = *splitseg;
+    pa = sorg(aseg);
+    pb = sdest(aseg);
+    if (b->verbose > 1) {
+      printf("    Split seg (%d, %d) by %d.\n", pointmark(pa), pointmark(pb), 
+        pointmark(insertpt));
+    }
+    // Insert the new point p.
+    makeshellface(subsegpool, &bseg);
+    setshvertices(bseg, insertpt, pb, NULL);
+    setsdest(aseg, insertpt);
+    setshellmark(bseg, getshellmark(aseg));
+    if (checkconstraints) {
+      areabound(bseg) = areabound(aseg);
+    }
+    // Connect [p, b]<->[b, #].
+    senext(aseg, aoutseg);
+    spivotself(aoutseg);
+    if (aoutseg.sh != NULL) {
+      senext(bseg, boutseg);
+      sbond2(boutseg, aoutseg);
+    }
+    // Connect [a, p] <-> [p, b].
+    senext(aseg, aoutseg);
+    senext2(bseg, boutseg);
+    sbond2(aoutseg, boutseg);
+    // Connect subsegs [a, p] and [p, b] to the true new subfaces.
+    for (i = 0; i < n; i++) {
+      spivot(abfaces[i], newsh); // The faked new subface.
+      if (sorg(newsh) != pa) sesymself(newsh);
+      senext2(newsh, neighsh); // The edge [p, a] in newsh
+      spivot(neighsh, casout);
+      ssbond(casout, aseg);
+      senext(newsh, neighsh); // The edge [b, p] in newsh
+      spivot(neighsh, casout);
+      ssbond(casout, bseg);
+    }
+    if (n > 1) {
+      // Create the two face rings at [a, p] and [p, b].
+      for (i = 0; i < n; i++) {
+        spivot(abfaces[i], newsh); // The faked new subface.
+        if (sorg(newsh) != pa) sesymself(newsh);
+        spivot(abfaces[(i + 1) % n], neighsh); // The next faked new subface.
+        if (sorg(neighsh) != pa) sesymself(neighsh);
+        senext2(newsh, casout); // The edge [p, a] in newsh.
+        senext2(neighsh, casin); // The edge [p, a] in neighsh.
+        spivotself(casout);
+        spivotself(casin);
+        sbond1(casout, casin); // Let the i's face point to (i+1)'s face.
+        senext(newsh, casout); // The edge [b, p] in newsh.
+        senext(neighsh, casin); // The edge [b, p] in neighsh.
+        spivotself(casout);
+        spivotself(casin);
+        sbond1(casout, casin);
+      }
+    } else { 
+      // Only one subface contains this segment.
+      // assert(n == 1);
+      spivot(abfaces[0], newsh);  // The faked new subface.
+      if (sorg(newsh) != pa) sesymself(newsh);
+      senext2(newsh, casout); // The edge [p, a] in newsh.
+      spivotself(casout);
+      sdissolve(casout); // Disconnect to faked subface.
+      senext(newsh, casout); // The edge [b, p] in newsh.
+      spivotself(casout);
+      sdissolve(casout); // Disconnect to faked subface.
+    }
+    // Delete the faked new subfaces.
+    for (i = 0; i < n; i++) {
+      spivot(abfaces[i], newsh); // The faked new subface.
+      shellfacedealloc(subfacepool, newsh.sh);
+    }
+    if (checksubsegs) {
+      // Add two subsegs into stack (for recovery).
+      if (!sinfected(aseg)) {
+        s = randomnation(subsegstack->objects + 1);
+        subsegstack->newindex((void **) &parysh);
+        *parysh = * (face *) fastlookup(subsegstack, s);
+        sinfect(aseg); 
+        parysh = (face *) fastlookup(subsegstack, s);
+        *parysh = aseg;
+      }
+      assert(!sinfected(bseg)); // SELF_CHECK
+      s = randomnation(subsegstack->objects + 1);
+      subsegstack->newindex((void **) &parysh);
+      *parysh = * (face *) fastlookup(subsegstack, s);
+      sinfect(bseg);
+      parysh = (face *) fastlookup(subsegstack, s);
+      *parysh = bseg;
+    }
+    delete [] abfaces;
+  }
+
+  // Delete the old subfaces.
+  for (i = 0; i < caveshlist->objects; i++) {
+    parysh = (face *) fastlookup(caveshlist, i);
+    if (checksubfaces) {		 
+      // Disconnect in the neighbor tets.		 
+      stpivot(*parysh, neightet);		 
+      if (neightet.tet != NULL) {		 
+        tsdissolve(neightet);		 
+        symself(neightet);		 
+        tsdissolve(neightet);		 
+      }		 
+    }
+    shellfacedealloc(subfacepool, parysh->sh);
+  }
+
+  // Clean the working lists.
+  caveshlist->restart();
+  caveshbdlist->restart();
+
+  return loc;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// sscoutsegment()    Look for a segment in surface triangulation.           //
+//                                                                           //
+// The segment is given by the origin of 'searchsh' and 'endpt'.  Assume the //
+// orientation of 'searchsh' is CCW w.r.t. the above point.                  //
+//                                                                           //
+// If an edge in T is found matching this segment, the segment is "locaked"  //
+// in T at the edge.  Otherwise, flip the first edge in T that the segment   //
+// crosses. Continue the search from the flipped face.                       //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+enum tetgenmesh::intersection tetgenmesh::sscoutsegment(face *searchsh,
+  point endpt)
+{
+  face flipshs[2], neighsh;
+  face newseg, checkseg;
+  point startpt, pa, pb, pc, pd;
+  enum intersection dir;
+  REAL ori_ab, ori_ca;
+  REAL dist_b, dist_c;
+
+  enum {MOVE_AB, MOVE_CA} nextmove;
+
+  shellface sptr;
+
+  // The origin of 'searchsh' is fixed.
+  startpt = sorg(*searchsh); // pa = startpt;
+
+  if (b->verbose > 1) {
+    printf("    Scout segment (%d, %d).\n", pointmark(startpt),
+      pointmark(endpt));
+  }
+
+  // Search an edge in 'searchsh' on the path of this segment.
+  while (1) {
+
+    pb = sdest(*searchsh);
+    if (pb == endpt) {
+      dir = SHAREEDGE; // Found!
+      break;
+    }
+
+    pc = sapex(*searchsh);
+    if (pc == endpt) {
+      senext2self(*searchsh);
+      sesymself(*searchsh);
+      dir = SHAREEDGE; // Found!
+      break;
+    }
+
+    ori_ab = orient3d(startpt, pb, dummypoint, endpt);
+    ori_ca = orient3d(pc, startpt, dummypoint, endpt);
+
+    if (ori_ab < 0) {
+      if (ori_ca < 0) { // (--)
+        // Both sides are viable moves.
+        spivot(*searchsh, neighsh); // At edge [a, b].
+        assert(neighsh.sh != NULL); // SELF_CHECK
+        pd = sapex(neighsh);
+        dist_b = NORM2(endpt[0] - pd[0], endpt[1] - pd[1], endpt[2] - pd[2]);
+        senext2(*searchsh, neighsh); // At edge [c, a].
+        spivotself(neighsh);
+        assert(neighsh.sh != NULL); // SELF_CHECK
+        pd = sapex(neighsh);
+        dist_c = NORM2(endpt[0] - pd[0], endpt[1] - pd[1], endpt[2] - pd[2]);
+        if (dist_c < dist_b) {
+          nextmove = MOVE_CA;
+        } else {
+          nextmove = MOVE_AB;
+        }
+      } else { // (-#)
+        nextmove = MOVE_AB;
+      }
+    } else {
+      if (ori_ca < 0) { // (#-)
+        nextmove = MOVE_CA;
+      } else {
+        if (ori_ab > 0) {
+          if (ori_ca > 0) { // (++)
+            // The segment intersects with edge [b, c].
+            dir = ACROSSEDGE;
+            break;
+          } else { // (+0)
+            // The segment collinear with edge [c, a].
+            senext2self(*searchsh);
+            sesymself(*searchsh);
+            dir = ACROSSVERT;
+            break;
+          }
+        } else {
+          if (ori_ca > 0) { // (0+)
+            // The segment collinear with edge [a, b].
+            dir = ACROSSVERT;
+            break;
+          } else { // (00)
+            // startpt == endpt. Not possible.
+            assert(0); // SELF_CHECK
+          }
+        }
+      }
+    }
+
+    // Move 'searchsh' to the next face, keep the origin unchanged.
+    if (nextmove == MOVE_AB) {
+      spivot(*searchsh, neighsh);
+      if (sorg(neighsh) != pb) sesymself(neighsh);
+      senext(neighsh, *searchsh);      
+    } else {
+      senext2(*searchsh, neighsh);
+      spivotself(neighsh);
+      if (sdest(neighsh) != pc) sesymself(neighsh);
+      *searchsh = neighsh;
+    }
+    assert(sorg(*searchsh) == startpt); // SELF_CHECK
+
+  } // while
+
+  if (dir == SHAREEDGE) {
+    // Insert the segment into the triangulation.
+    makeshellface(subsegpool, &newseg);
+    setshvertices(newseg, startpt, endpt, NULL);
+    ssbond(*searchsh, newseg);
+    spivot(*searchsh, neighsh);
+    if (neighsh.sh != NULL) {
+      ssbond(neighsh, newseg);
+    }
+    return dir;
+  }
+
+  if (dir == ACROSSVERT) {
+    // A point is found collinear with this segment.
+    return dir;
+  }
+
+  if (dir == ACROSSEDGE) {
+    // Edge [b, c] intersects with the segment.
+    senext(*searchsh, flipshs[0]);
+    sspivot(flipshs[0], checkseg);
+    if (checkseg.sh != NULL) {
+      printf("Error:  Invalid PLC.\n");
+      pb = sorg(flipshs[0]);
+      pc = sdest(flipshs[0]);
+      printf("  Two segments (%d, %d) and (%d, %d) intersect.\n",
+        pointmark(startpt), pointmark(endpt), pointmark(pb), pointmark(pc));
+      terminatetetgen(2);
+    }
+    // Flip edge [b, c], queue unflipped edges (for Delaunay checks).
+    spivot(flipshs[0], flipshs[1]);
+    assert(flipshs[1].sh != NULL); // SELF_CHECK
+    if (sorg(flipshs[1]) != sdest(flipshs[0])) sesymself(flipshs[1]);
+    flip22(flipshs, 1);
+    // The flip may create an invered triangle, check it.
+    pa = sapex(flipshs[1]);
+    pb = sapex(flipshs[0]);
+    pc = sorg(flipshs[0]);
+    pd = sdest(flipshs[0]);
+    // Check if pa and pb are on the different sides of [pc, pd]. 
+    // Re-use ori_ab, ori_ca for the tests.
+    ori_ab = orient3d(pc, pd, dummypoint, pb);
+    ori_ca = orient3d(pd, pc, dummypoint, pa);
+    assert(ori_ab * ori_ca != 0); // SELF_CHECK
+    if (ori_ab < 0) {
+      if (b->verbose > 1) {
+        printf("    Queue an inversed triangle (%d, %d, %d) %d\n",
+          pointmark(pc), pointmark(pd), pointmark(pb), pointmark(pa));
+      }
+      futureflip = flipshpush(futureflip, &flipshs[0]);
+    } else if (ori_ca < 0) {
+      if (b->verbose > 1) {
+        printf("    Queue an inversed triangle (%d, %d, %d) %d\n",
+          pointmark(pd), pointmark(pc), pointmark(pa), pointmark(pb));
+      }
+      futureflip = flipshpush(futureflip, &flipshs[1]);
+    }
+    // Set 'searchsh' s.t. its origin is 'startpt'.
+    *searchsh = flipshs[0];
+    assert(sorg(*searchsh) == startpt);
+  }
+
+  return sscoutsegment(searchsh, endpt);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// scarveholes()    Remove triangles not in the facet.                       //
+//                                                                           //
+// This routine re-uses the two global arrays: caveshlist and caveshbdlist.  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::scarveholes(int holes, REAL* holelist)
+{
+  face *parysh, searchsh, neighsh;
+  face checkseg;
+  enum location loc;
+  int i, j;
+
+  // Get all triangles. Infect unprotected convex hull triangles. 
+  smarktest(recentsh);
+  caveshlist->newindex((void **) &parysh);
+  *parysh = recentsh;
+  for (i = 0; i < caveshlist->objects; i++) {
+    parysh = (face *) fastlookup(caveshlist, i);
+    searchsh = *parysh;
+    searchsh.shver = 0;
+    for (j = 0; j < 3; j++) {
+      spivot(searchsh, neighsh);
+      // Is this side on the convex hull?
+      if (neighsh.sh != NULL) {
+        if (!smarktested(neighsh)) {
+          smarktest(neighsh);
+          caveshlist->newindex((void **) &parysh);
+          *parysh = neighsh;
+        }
+      } else {
+        // A hull side. Check if it is protected by a segment.
+        sspivot(searchsh, checkseg);
+        if (checkseg.sh == NULL) {
+          // Not protected. Save this face.
+          if (!sinfected(searchsh)) {
+            sinfect(searchsh);
+            caveshbdlist->newindex((void **) &parysh);
+            *parysh = searchsh;
+          }
+        }
+      }
+      senextself(searchsh);
+    }
+  }
+
+  // Infect the triangles in the holes.
+  for (i = 0; i < 3 * holes; i += 3) {
+    searchsh = recentsh;
+    loc = slocate(&(holelist[i]), &searchsh, true);
+    if (loc != OUTSIDE) {
+      sinfect(searchsh);
+      caveshbdlist->newindex((void **) &parysh);
+      *parysh = searchsh;
+    }
+  }
+
+  // Find and infect all exterior triangles.
+  for (i = 0; i < caveshbdlist->objects; i++) {
+    parysh = (face *) fastlookup(caveshbdlist, i);
+    searchsh = *parysh;
+    searchsh.shver = 0;
+    for (j = 0; j < 3; j++) {
+      spivot(searchsh, neighsh);
+      if (neighsh.sh != NULL) {
+        sspivot(searchsh, checkseg);
+        if (checkseg.sh == NULL) {
+          if (!sinfected(neighsh)) {
+            sinfect(neighsh);
+            caveshbdlist->newindex((void **) &parysh);
+            *parysh = neighsh;
+          }
+        } else {
+          sdissolve(neighsh); // Disconnect a protected face.
+        }
+      }
+      senextself(searchsh);
+    }
+  }
+
+  // Delete exterior triangles, unmark interior triangles.
+  for (i = 0; i < caveshlist->objects; i++) {
+    parysh = (face *) fastlookup(caveshlist, i);
+    if (sinfected(*parysh)) {
+      shellfacedealloc(subfacepool, parysh->sh);
+    } else {
+      sunmarktest(*parysh);
+    }
+  }
+
+  caveshlist->restart();
+  caveshbdlist->restart();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// triangulate()    Create a CDT for the facet.                              //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::triangulate(int shmark, arraypool* ptlist, arraypool* conlist,
+  int holes, REAL* holelist)
+{
+  face searchsh, newsh; 
+  face newseg;
+  point pa, pb, pc, *ppt, *cons;
+  enum location loc;
+  int i;
+
+  if (b->verbose > 1) {
+    printf("    %ld vertices, %ld segments",ptlist->objects,conlist->objects);
+    if (holes > 0) {
+      printf(", %d holes", holes);
+    }
+    printf(", shmark: %d.\n", shmark);
+  }
+
+  if (ptlist->objects < 3l) {
+    return; // No enough points. Do nothing.
+  }
+  if (conlist->objects < 3l) {
+    return; // No enough segments. Do nothing.
+  }
+
+  if (ptlist->objects == 3l) {
+    // The facet has only one triangle.
+    pa = * (point *) fastlookup(ptlist, 0);
+    pb = * (point *) fastlookup(ptlist, 1);
+    pc = * (point *) fastlookup(ptlist, 2);
+    makeshellface(subfacepool, &newsh);
+    setshvertices(newsh, pa, pb, pc);
+    setshellmark(newsh, shmark);
+    // Create three new segments.
+    for (i = 0; i < 3; i++) {
+      makeshellface(subsegpool, &newseg);
+      setshvertices(newseg, sorg(newsh), sdest(newsh), NULL);
+      ssbond(newsh, newseg);
+      senextself(newsh);
+    }
+    if (getpointtype(pa) == VOLVERTEX) {
+      setpointtype(pa, FACETVERTEX);
+    }
+    if (getpointtype(pb) == VOLVERTEX) {
+      setpointtype(pb, FACETVERTEX);
+    }
+    if (getpointtype(pc) == VOLVERTEX) {
+      setpointtype(pc, FACETVERTEX);
+    }
+    return;
+  }
+
+  // Calulcate an above point of this facet.
+  if (!calculateabovepoint(ptlist, &pa, &pb, &pc)) {
+    return; // The point set is degenerate.
+  }
+
+  // Create an initial triangulation.
+  makeshellface(subfacepool, &newsh);
+  setshvertices(newsh, pa, pb, pc);
+  setshellmark(newsh, shmark);
+  recentsh = newsh;
+
+  if (getpointtype(pa) == VOLVERTEX) {
+    setpointtype(pa, FACETVERTEX);
+  }
+  if (getpointtype(pb) == VOLVERTEX) {
+    setpointtype(pb, FACETVERTEX);
+  }
+  if (getpointtype(pc) == VOLVERTEX) {
+    setpointtype(pc, FACETVERTEX);
+  }
+
+  // Incrementally build the triangulation.
+  pinfect(pa);
+  pinfect(pb);
+  pinfect(pc);
+  for (i = 0; i < ptlist->objects; i++) {
+    ppt = (point *) fastlookup(ptlist, i);
+    if (!pinfected(*ppt)) {
+      searchsh = recentsh;
+      loc = sinsertvertex(*ppt, &searchsh, NULL, true, true);
+      if (getpointtype(*ppt) == VOLVERTEX) {
+        setpointtype(*ppt, FACETVERTEX);
+      }
+    } else {
+      puninfect(*ppt); // This point has inserted.
+    }
+  }
+
+  // Insert the segments.
+  for (i = 0; i < conlist->objects; i++) {
+    cons = (point *) fastlookup(conlist, i);
+    searchsh = recentsh;
+    loc = slocate(cons[0], &searchsh, true);
+    assert(loc == ONVERTEX); // SELF_CHECK
+    // Recover the segment. Some edges may be flipped.
+    sscoutsegment(&searchsh, cons[1]);
+    if (futureflip != NULL) {
+      // Recover locally Delaunay edges.
+      lawsonflip();
+    }
+  }
+
+  // Remove exterior and hole triangles.
+  scarveholes(holes, holelist);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// unifysubfaces()    Unify two identical subfaces.                          //
+//                                                                           //
+// Two subfaces, f1 [a, b, c] and f2 [a, b, d], share the same edge [a, b].  //
+// If c = d, then f1 and f2 are identical. In such case, f2 is deleted, all  //
+// connections to f2 are re-directed to f1.  Otherwise, these two subfaces   //
+// intersect, and the mesher is stopped.                                     //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::unifysubfaces(face *f1, face *f2)
+{
+  face casout, casin, neighsh;
+  face sseg, checkseg;
+  point pa, pb, pc, pd;
+  int i;
+
+  assert(f1->sh != f2->sh); // SELF_CHECK
+
+  pa = sorg(*f1);
+  pb = sdest(*f1);
+  pc = sapex(*f1);
+
+  assert(sorg(*f2) == pa); // SELF_CHECK
+  assert(sdest(*f2) == pb); // SELF_CHECK
+  pd = sapex(*f2);
+
+  if (pc != pd) {
+    printf("Error:  Invalid PLC! Two coplanar subfaces intersect.\n");
+    printf("  1st (#%4d): (%d, %d, %d)\n", getshellmark(*f1),
+      pointmark(pa), pointmark(pb), pointmark(pc));
+    printf("  2nd (#%4d): (%d, %d, %d)\n", getshellmark(*f2),
+      pointmark(pa), pointmark(pb), pointmark(pd));
+    terminatetetgen(2);
+  }
+
+  // f1 and f2 are identical, replace f2 by f1.
+  if (!b->quiet) {
+    printf("Warning:  Facet #%d is duplicated with Facet #%d. Removed!\n",
+      getshellmark(*f2), getshellmark(*f1));
+  }
+
+  // Make possible disconnections/reconnections at neighbors of f2.
+  for (i = 0; i < 3; i++) {
+    spivot(*f1, casout);
+    if (casout.sh == NULL) {
+      // f1 has no adjacent subfaces yet.
+      spivot(*f2, casout);
+      if (casout.sh != NULL) {
+        // Re-direct the adjacent connections of f2 to f1.
+        casin = casout;
+        spivot(casin, neighsh);
+        while (neighsh.sh != f2->sh) {
+          casin = neighsh;
+          spivot(casin, neighsh);
+        }
+        // Connect casout <= f1 <= casin.
+        sbond1(*f1, casout);
+        sbond1(casin, *f1);
+      }
+    }
+    sspivot(*f2, sseg); 
+    if (sseg.sh != NULL) {
+      // f2 has a segment. It must be different to f1's.
+      sspivot(*f1, checkseg); // SELF_CHECK
+      if (checkseg.sh != NULL) { // SELF_CHECK
+        assert(checkseg.sh != sseg.sh); // SELF_CHECK
+      }
+      // Disconnect bonds of subfaces to this segment.
+      spivot(*f2, casout);
+      if (casout.sh != NULL) {
+        casin = casout;
+        ssdissolve(casin);
+        spivot(casin, neighsh);
+        while (neighsh.sh != f2->sh) {
+          casin = neighsh;
+          ssdissolve(casin);
+          spivot(casin, neighsh);
+        }
+      }
+      // Delete the segment.
+      shellfacedealloc(subsegpool, sseg.sh);
+    }
+    spivot(*f2, casout);
+    if (casout.sh != NULL) {
+      // Find the subface (casin) pointing to f2.
+      casin = casout;
+      spivot(casin, neighsh);
+      while (neighsh.sh != f2->sh) {
+        casin = neighsh;
+        spivot(casin, neighsh);
+      }
+      // Disconnect f2 <= casin.
+      sdissolve(casin);
+    }
+    senextself(*f1);
+    senextself(*f2);
+  } // i
+
+  // Delete f2.
+  shellfacedealloc(subfacepool, f2->sh);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// unifysegments()    Remove redundant segments and create face links.       //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::unifysegments()
+{
+  badface *facelink, *newlinkitem, *f1, *f2;
+  face *facperverlist, sface;
+  face subsegloop, testseg;
+  point torg, tdest;
+  REAL ori1, ori2, ori3;
+  REAL n1[3], n2[3];
+  int *idx2faclist;
+  int segmarker;
+  int idx, k, m;
+
+  if (b->verbose > 1) {
+    printf("  Unifying segments.\n");
+  }
+
+  // Create a mapping from vertices to subfaces.
+  makepoint2submap(subfacepool, idx2faclist, facperverlist);
+
+  segmarker = 1;
+  subsegloop.shver = 0;
+  subsegpool->traversalinit();
+  subsegloop.sh = shellfacetraverse(subsegpool);
+  while (subsegloop.sh != (shellface *) NULL) {
+    torg = sorg(subsegloop);
+    tdest = sdest(subsegloop);
+
+    idx = pointmark(torg) - in->firstnumber;
+    // Loop through the set of subfaces containing 'torg'.  Get all the
+    //   subfaces containing the edge (torg, tdest). Save and order them
+    //   in 'sfacelist', the ordering is defined by the right-hand rule
+    //   with thumb points from torg to tdest.
+    for (k = idx2faclist[idx]; k < idx2faclist[idx + 1]; k++) {
+      sface = facperverlist[k];
+      // The face may be deleted if it is a duplicated face.
+      if (sface.sh[3] == NULL) continue;
+      // Search the edge torg->tdest.
+      assert(sorg(sface) == torg); // SELF_CHECK
+      if (sdest(sface) != tdest) {
+        senext2self(sface);
+        sesymself(sface);
+      }
+      if (sdest(sface) != tdest) continue;
+
+      // Save the face f in facelink.
+      if (flippool->items >= 2) {
+        f1 = facelink;
+        for (m = 0; m < flippool->items - 1; m++) {
+          f2 = f1->nextitem;
+          ori1 = orient3d(torg, tdest, sapex(f1->ss), sapex(f2->ss));
+          ori2 = orient3d(torg, tdest, sapex(f1->ss), sapex(sface));
+          if (ori1 > 0) {
+            // apex(f2) is below f1.
+            if (ori2 > 0) {
+              // apex(f) is below f1 (see Fig.1). 
+              ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
+              if (ori3 > 0) {
+                // apex(f) is below f2, insert it.
+                break; 
+              } else if (ori3 < 0) {
+                // apex(f) is above f2, continue.
+              } else { // ori3 == 0; 
+                // f is coplanar and codirection with f2.
+                unifysubfaces(&(f2->ss), &sface);
+                break;
+              }
+            } else if (ori2 < 0) {
+              // apex(f) is above f1 below f2, inset it (see Fig. 2).
+              break;
+            } else { // ori2 == 0;
+              // apex(f) is coplanar with f1 (see Fig. 5).
+              ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
+              if (ori3 > 0) {
+                // apex(f) is below f2, insert it.
+                break; 
+              } else {
+                // f is coplanar and codirection with f1.
+                unifysubfaces(&(f1->ss), &sface);
+                break;
+              }
+            }
+          } else if (ori1 < 0) {
+            // apex(f2) is above f1.
+            if (ori2 > 0) {
+              // apex(f) is below f1, continue (see Fig. 3).
+            } else if (ori2 < 0) {
+              // apex(f) is above f1 (see Fig.4).
+              ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
+              if (ori3 > 0) {
+                // apex(f) is below f2, insert it.
+                break;
+              } else if (ori3 < 0) {
+                // apex(f) is above f2, continue.
+              } else { // ori3 == 0;
+                // f is coplanar and codirection with f2.
+                unifysubfaces(&(f2->ss), &sface);
+                break;
+              }
+            } else { // ori2 == 0;
+              // f is coplanar and with f1 (see Fig. 6).
+              ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
+              if (ori3 > 0) {
+                // f is also codirection with f1.
+                unifysubfaces(&(f1->ss), &sface);
+                break;
+              } else {
+                // f is above f2, continue.
+              }
+            }
+          } else { // ori1 == 0;
+            // apex(f2) is coplanar with f1. By assumption, f1 is not
+            //   coplanar and codirection with f2.
+            if (ori2 > 0) {
+              // apex(f) is below f1, continue (see Fig. 7).
+            } else if (ori2 < 0) {
+              // apex(f) is above f1, insert it (see Fig. 7).
+              break;
+            } else { // ori2 == 0.
+              // apex(f) is coplanar with f1 (see Fig. 8).
+              // f is either codirection with f1 or is codirection with f2. 
+              facenormal(torg, tdest, sapex(f1->ss), n1, 1);
+              facenormal(torg, tdest, sapex(sface), n2, 1);
+              if (DOT(n1, n2) > 0) {
+                unifysubfaces(&(f1->ss), &sface);
+              } else {
+                unifysubfaces(&(f2->ss), &sface);
+              }
+              break;
+            }
+          }
+          // Go to the next item;
+          f1 = f2;
+        } // for (m = 0; ...)
+        if (sface.sh[3] != NULL) {
+          // Insert sface between f1 and f2.
+          newlinkitem = (badface *) flippool->alloc();
+          newlinkitem->ss = sface;
+          newlinkitem->nextitem = f1->nextitem;
+          f1->nextitem = newlinkitem;
+        }
+      } else if (flippool->items == 1) {
+        f1 = facelink;
+        // Make sure that f is not coplanar and codirection with f1.
+        ori1 = orient3d(torg, tdest, sapex(f1->ss), sapex(sface));
+        if (ori1 == 0) {
+          // f is coplanar with f1 (see Fig. 8).
+          facenormal(torg, tdest, sapex(f1->ss), n1, 1);
+          facenormal(torg, tdest, sapex(sface), n2, 1);
+          if (DOT(n1, n2) > 0) {
+            // The two faces are codirectional as well.
+            unifysubfaces(&(f1->ss), &sface);
+          }
+        }
+        // Add this face to link if it is not deleted.
+        if (sface.sh[3] != NULL) {
+          // Add this face into link.
+          newlinkitem = (badface *) flippool->alloc();
+          newlinkitem->ss = sface;
+          newlinkitem->nextitem = NULL;
+          f1->nextitem = newlinkitem;
+        }
+      } else {
+        // The first face.
+        newlinkitem = (badface *) flippool->alloc();
+        newlinkitem->ss = sface;
+        newlinkitem->nextitem = NULL;
+        facelink = newlinkitem;
+      }
+    } // for (k = idx2faclist[idx]; ...)
+
+    if (b->verbose > 1) {
+      printf("    Found %ld segments at (%d  %d).\n", flippool->items,
+             pointmark(torg), pointmark(tdest));
+    }
+
+    // Set the connection between this segment and faces containing it,
+    //   at the same time, remove redundant segments.
+    f1 = facelink;
+    for (k = 0; k < flippool->items; k++) {
+      sspivot(f1->ss, testseg);
+      // If 'testseg' is not 'subsegloop' and is not dead, it is redundant.
+      if ((testseg.sh != subsegloop.sh) && (testseg.sh[3] != NULL)) {
+        shellfacedealloc(subsegpool, testseg.sh);
+      }
+      // Bonds the subface and the segment together.
+      ssbond(f1->ss, subsegloop);
+      f1 = f1->nextitem;
+    }
+
+    // Create the face ring at the segment.
+    if (flippool->items > 1) {
+      f1 = facelink;
+      for (k = 1; k <= flippool->items; k++) {
+        k < flippool->items ? f2 = f1->nextitem : f2 = facelink;
+        if (b->verbose > 2) {
+          printf("    Bond subfaces (%d, %d, %d) and (%d, %d, %d).\n",
+                 pointmark(torg), pointmark(tdest), pointmark(sapex(f1->ss)),
+                 pointmark(torg), pointmark(tdest), pointmark(sapex(f2->ss)));
+        }
+        sbond1(f1->ss, f2->ss);
+        f1 = f2;
+      }
+    }
+
+    // Set the unique segment marker into the unified segment.
+    setshellmark(subsegloop, segmarker);
+    segmarker++;
+    flippool->restart();
+
+    subsegloop.sh = shellfacetraverse(subsegpool);
+  }
+
+  delete [] idx2faclist;
+  delete [] facperverlist;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// mergefacets()    Merge adjacent coplanar facets.                          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::mergefacets()
+{
+  arraypool *ptlist;
+  face parentsh, neighsh, neineighsh;
+  face segloop;
+  point eorg, edest, *parypt;
+  REAL ori, ori1, ori2;
+  bool mergeflag, aboveflag;
+  int* segspernodelist;
+  int fidx1, fidx2;
+  int i, j;
+
+  if (b->verbose > 1) {
+    printf("  Merging adjacent coplanar facets.\n");
+  }
+
+  // Initialize 'segspernodelist'.
+  segspernodelist = new int[pointpool->items + 1];
+  for (i = 0; i < pointpool->items + 1; i++) segspernodelist[i] = 0;
+
+  // Allocate a list for calculate an above point.
+  ptlist = new arraypool(sizeof(point *), 4);
+
+  // Loop all segments, counter the number of segments sharing each vertex.
+  subsegpool->traversalinit();
+  segloop.sh = shellfacetraverse(subsegpool);
+  while (segloop.sh != (shellface *) NULL) {
+    // Increment the number of sharing segments for each endpoint.
+    for (i = 0; i < 2; i++) {
+      j = pointmark((point) segloop.sh[3 + i]);
+      segspernodelist[j]++;
+    }
+    segloop.sh = shellfacetraverse(subsegpool);
+  }
+
+  // Loop all segments, merge adjacent coplanar facets.
+  subsegpool->traversalinit();
+  segloop.sh = shellfacetraverse(subsegpool);
+  while (segloop.sh != (shellface *) NULL) {
+    eorg = sorg(segloop);
+    edest = sdest(segloop);
+    spivot(segloop, parentsh);
+    spivot(parentsh, neighsh);
+    if (neighsh.sh != NULL) {
+      spivot(neighsh, neineighsh);
+      if (parentsh.sh == neineighsh.sh) {
+        // Exactly two subfaces at this segment.
+        fidx1 = getshellmark(parentsh) - 1;
+        fidx2 = getshellmark(neighsh) - 1;
+        // Possible to merge them if they are not in the same facet.
+        if (fidx1 != fidx2) {
+          // Test if they are coplanar wrt the tolerance.
+          ori = orient3d(eorg, edest, sapex(parentsh), sapex(neighsh));
+          if ((ori == 0) || iscoplanar(eorg, edest, sapex(parentsh),
+            sapex(neighsh), ori)) {
+            // Found two adjacent coplanar facets.
+            // Only can remove the segment if both apexes are on the 
+            //   different sides of the edge [eorg, edest].
+            ptlist->newindex((void **) &parypt);
+            *parypt = eorg;
+            ptlist->newindex((void **) &parypt);
+            *parypt = edest;
+            ptlist->newindex((void **) &parypt);
+            *parypt = sapex(parentsh);
+            ptlist->newindex((void **) &parypt);
+            *parypt = sapex(neighsh);
+            aboveflag = calculateabovepoint(ptlist, NULL, NULL, NULL);
+            if (aboveflag) {
+              ori1 = orient3d(eorg, edest, dummypoint, sapex(parentsh));
+              ori2 = orient3d(eorg, edest, dummypoint, sapex(neighsh));
+            } else {
+              ori1 = ori2 = 1.0; // Bad data.
+            }
+            if (ori1 * ori2 < 0) {
+              mergeflag = ((in->facetmarkerlist == NULL) || 
+                (in->facetmarkerlist[fidx1] == in->facetmarkerlist[fidx2]));
+              if (mergeflag) {
+                if (b->verbose > 1) {
+                  printf("  Removing segment (%d, %d).\n", pointmark(eorg),
+                         pointmark(edest));
+                }
+                ssdissolve(parentsh);
+                ssdissolve(neighsh);
+                shellfacedealloc(subsegpool, segloop.sh);
+                j = pointmark(eorg);
+                segspernodelist[j]--;
+                if (segspernodelist[j] == 0) {
+                  setpointtype(eorg, FACETVERTEX);
+                }
+                j = pointmark(edest);
+                segspernodelist[j]--;
+                if (segspernodelist[j] == 0) {
+                  setpointtype(edest, FACETVERTEX);
+                }
+                // Add the edge to flip stack.
+                futureflip = flipshpush(futureflip, &parentsh);
+              }
+            }
+            ptlist->restart(); // For the next test.
+          }
+        }
+      }
+    } // if (neighsh.sh != NULL)
+    segloop.sh = shellfacetraverse(subsegpool);
+  }
+
+  if (futureflip != NULL) {
+    // Do Delaunay flip.
+    lawsonflip();
+  }
+
+  delete ptlist;
+  delete [] segspernodelist;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// markacutevertices()    Classify vertices as ACUTEVERTEXs or RIDGEVERTEXs. //
+//                                                                           //
+// Initially, all segment vertices are marked as VOLVERTEX (after calling    //
+// incrementaldelaunay()).                                                   //
+//                                                                           //
+// A segment vertex is ACUTEVERTEX if it two segments incident it form an    //
+// interior angle less than 60 degree, otherwise, it is a RIDGEVERTEX.       //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::markacutevertices()
+{
+  point pa, pb, pc;
+  REAL anglimit, ang;
+  bool acuteflag;
+  int acutecount;
+  int idx, i, j;
+
+  face* segperverlist;
+  int* idx2seglist;
+
+  if (b->verbose) {
+    printf("  Marking acute vertices.\n");
+  }
+
+  // Construct a map from points to segments.
+  makepoint2submap(subsegpool, idx2seglist, segperverlist);
+
+  anglimit = PI / 3.0;  // 60 degree.
+  acutecount = 0;
+
+  // Loop over the set of vertices.
+  pointpool->traversalinit();
+  pa = pointtraverse();
+  while (pa != NULL) {
+    idx = pointmark(pa) - in->firstnumber;
+    // Mark it if it is an endpoint of some segments.
+    if (idx2seglist[idx + 1] > idx2seglist[idx]) {
+      acuteflag = false;
+      // Do a brute-force pair-pair check.
+      for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !acuteflag; i++) {
+        pb = sdest(segperverlist[i]);
+        for (j = i + 1; j < idx2seglist[idx + 1] && !acuteflag; j++) {
+          pc = sdest(segperverlist[j]);
+          ang = interiorangle(pa, pb, pc, NULL);
+          acuteflag = ang < anglimit;
+        }
+      }
+      // Now mark the vertex.
+      if (b->verbose > 1) {
+        printf("    Mark %d as %s.\n", pointmark(pa), acuteflag ?
+          "ACUTEVERTEX" : "RIDGEVERTEX");
+      }
+      setpointtype(pa, acuteflag ? ACUTEVERTEX : RIDGEVERTEX);
+      acutecount += (acuteflag ? 1 : 0);
+    }
+    pa = pointtraverse();
+  }
+
+  if (b->verbose) {
+    printf("  %d acute vertices.\n", acutecount);
+  }
+
+  delete [] idx2seglist;
+  delete [] segperverlist;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// meshsurface()    Create a surface mesh of the input PLC.                  //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::meshsurface()
+{
+  arraypool *ptlist, *conlist;
+  point *idx2verlist;
+  point tstart, tend, *pnewpt, *cons;
+  tetgenio::facet *f;
+  tetgenio::polygon *p;
+  int end1, end2;
+  int shmark, i, j;
+
+  if (!b->quiet) {
+    printf("Creating surface mesh.\n");
+  }
+
+  // Create a map from indices to points.
+  makeindex2pointmap(idx2verlist);
+
+  // Initialize arrays (block size: 2^8 = 256).
+  ptlist = new arraypool(sizeof(point *), 8);
+  conlist = new arraypool(2 * sizeof(point *), 8);
+
+  // Loop the facet list, triangulate each facet.
+  for (shmark = 1; shmark <= in->numberoffacets; shmark++) {
+
+    // Get a facet F.
+    f = &in->facetlist[shmark - 1];
+
+    // Process the duplicated points first, they are marked with type
+    //   DUPLICATEDVERTEX.  If p and q are duplicated, and p'index > q's,
+    //   then p is substituted by q.
+    if (dupverts > 0l) {
+      // Loop all polygons of this facet.
+      for (i = 0; i < f->numberofpolygons; i++) {
+        p = &(f->polygonlist[i]);
+        // Loop other vertices of this polygon.
+        for (j = 0; j < p->numberofvertices; j++) {
+          end1 = p->vertexlist[j];
+          tstart = idx2verlist[end1];
+          if (getpointtype(tstart) == DUPLICATEDVERTEX) {
+            // Reset the index of vertex-j.
+            tend = point2ppt(tstart);
+            end2 = pointmark(tend);
+            p->vertexlist[j] = end2;
+          }
+        }
+      }
+    }
+
+    // Loop polygons of F, get the set of vertices and segments.
+    for (i = 0; i < f->numberofpolygons; i++) {
+      // Get a polygon.
+      p = &(f->polygonlist[i]);
+      // Get the first vertex.
+      end1 = p->vertexlist[0];
+      if ((end1 < in->firstnumber) || 
+          (end1 >= in->firstnumber + in->numberofpoints)) {
+        if (!b->quiet) {
+          printf("Warning:  Invalid the 1st vertex %d of polygon", end1);
+          printf(" %d in facet %d.\n", i + 1, shmark);
+        }
+        continue; // Skip this polygon.
+      }
+      tstart = idx2verlist[end1];
+      // Add tstart to V if it haven't been added yet.
+      if (!pinfected(tstart)) {
+        pinfect(tstart);
+        ptlist->newindex((void **) &pnewpt);
+        *pnewpt = tstart;
+      }
+      // Loop other vertices of this polygon.
+      for (j = 1; j <= p->numberofvertices; j++) {
+        // get a vertex.
+        if (j < p->numberofvertices) {
+          end2 = p->vertexlist[j];
+        } else {
+          end2 = p->vertexlist[0];  // Form a loop from last to first.
+        }
+        if ((end2 < in->firstnumber) ||
+            (end2 >= in->firstnumber + in->numberofpoints)) {
+          if (!b->quiet) {
+            printf("Warning:  Invalid vertex %d in polygon %d", end2, i + 1);
+            printf(" in facet %d.\n", shmark);
+          }
+        } else {
+          if (end1 != end2) {
+            // 'end1' and 'end2' form a segment.
+            tend = idx2verlist[end2];
+            // Add tstart to V if it haven't been added yet.
+            if (!pinfected(tend)) {
+              pinfect(tend);
+              ptlist->newindex((void **) &pnewpt);
+              *pnewpt = tend;
+            }
+            // Save the segment in S (conlist).
+            conlist->newindex((void **) &cons);
+            cons[0] = tstart;
+            cons[1] = tend;
+            // Set the start for next continuous segment.
+            end1 = end2;
+            tstart = tend;
+          } else {
+            // Two identical vertices mean an isolated vertex of F.
+            if (p->numberofvertices > 2) {
+              // This may be an error in the input, anyway, we can continue
+              //   by simply skipping this segment.
+              if (!b->quiet) {
+                printf("Warning:  Polygon %d has two identical verts", i + 1);
+                printf(" in facet %d.\n", shmark);
+              }
+            } 
+            // Ignore this vertex.
+          }
+        }
+        // Is the polygon degenerate (a segment or a vertex)?
+        if (p->numberofvertices == 2) break;
+      }
+    }
+    // Unmark vertices.
+    for (i = 0; i < ptlist->objects; i++) {
+      pnewpt = (point *) fastlookup(ptlist, i);
+      puninfect(*pnewpt);
+    }
+
+    // Triangulate F into a CDT.
+    triangulate(shmark, ptlist, conlist, f->numberofholes, f->holelist);
+
+    // Clear working lists.
+    ptlist->restart();
+    conlist->restart();
+  }
+
+  delete ptlist;
+  delete conlist;
+  delete [] idx2verlist;
+
+  // Remove redundant segments and build the face links.
+  unifysegments();
+
+  if (b->object == tetgenbehavior::STL) {
+    // Remove redundant vertices (for .stl input mesh).
+    jettisonnodes();
+  }
+
+  if (!b->nomerge && !b->nobisect) {
+    // Merge adjacent coplanar facets.
+    mergefacets();
+  }
+
+  // Mark acutes vertices.
+  markacutevertices();
+
+  // The total number of iunput segments.
+  insegments = subsegpool->items;
+}
+
+#endif // #ifndef surfaceCXX
\ No newline at end of file
diff --git a/contrib/Tetgen/tetgen.cxx b/contrib/Tetgen/tetgen.cxx
deleted file mode 100644
index 91035a640485b3854577a9717d6ddf0f570a086c..0000000000000000000000000000000000000000
--- a/contrib/Tetgen/tetgen.cxx
+++ /dev/null
@@ -1,34961 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// TetGen                                                                    //
-//                                                                           //
-// A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
-//                                                                           //
-// Version 1.4                                                               //
-// April 16, 2007                                                            //
-//                                                                           //
-// Copyright (C) 2002--2007                                                  //
-// Hang Si                                                                   //
-// Research Group Numerical Mathematics and Scientific Computing             //
-// Weierstrass Institute for Applied Analysis and Stochastics                //
-// Mohrenstr. 39, 10117 Berlin, Germany                                      //
-// si@wias-berlin.de                                                         //
-//                                                                           //
-// TetGen is freely available through the website: http://tetgen.berlios.de. //
-//   It may be copied, modified, and redistributed for non-commercial use.   //
-//   Please consult the file LICENSE for the detailed copyright notices.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetgen.cxx                                                                //
-//                                                                           //
-// The TetGen library and program.                                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-#include "tetgen.h"
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// terminatetetgen()    Terminate TetGen with a given exit code.             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void terminatetetgen(int x)
-{
-#ifdef TETLIBRARY
-  throw x;
-#else
-  exit(x);
-#endif // #ifdef TETLIBRARY
-}
-
-//
-// Begin of class 'tetgenio' implementation
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// initialize()    Initialize all variables of 'tetgenio'.                   //
-//                                                                           //
-// It is called by the only class constructor 'tetgenio()' implicitly. Thus, //
-// all variables are guaranteed to be initialized. Each array is initialized //
-// to be a 'NULL' pointer, and its length is equal zero. Some variables have //
-// their default value, 'firstnumber' equals zero, 'mesh_dim' equals 3,  and //
-// 'numberofcorners' equals 4.  Another possible use of this routine is to   //
-// call it before to re-use an object.                                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenio::initialize()
-{
-  firstnumber = 0;              // Default item index is numbered from Zero.
-  mesh_dim = 3;                              // Default mesh dimension is 3.
-  useindex = true;
-
-  pointlist = (REAL *) NULL;
-  pointattributelist = (REAL *) NULL;
-  pointmtrlist = (REAL *) NULL;
-  pointmarkerlist = (int *) NULL;
-  numberofpoints = 0;
-  numberofpointattributes = 0;
-  numberofpointmtrs = 0;
-
-  tetrahedronlist = (int *) NULL;
-  tetrahedronattributelist = (REAL *) NULL;
-  tetrahedronvolumelist = (REAL *) NULL;
-  neighborlist = (int *) NULL;
-  numberoftetrahedra = 0;
-  numberofcorners = 4;                   // Default is 4 nodes per element.
-  numberoftetrahedronattributes = 0;
-
-  trifacelist = (int *) NULL;
-  adjtetlist = (int *) NULL;
-  trifacemarkerlist = (int *) NULL;
-  numberoftrifaces = 0; 
-
-  facetlist = (facet *) NULL;
-  facetmarkerlist = (int *) NULL;
-  numberoffacets = 0; 
-
-  edgelist = (int *) NULL;
-  edgemarkerlist = (int *) NULL;
-  numberofedges = 0;
-
-  holelist = (REAL *) NULL;
-  numberofholes = 0;
-
-  regionlist = (REAL *) NULL;
-  numberofregions = 0;
-
-  facetconstraintlist = (REAL *) NULL;
-  numberoffacetconstraints = 0;
-  segmentconstraintlist = (REAL *) NULL;
-  numberofsegmentconstraints = 0;
-
-  pbcgrouplist = (pbcgroup *) NULL;
-  numberofpbcgroups = 0;
-
-  vpointlist = (REAL *) NULL;
-  vedgelist = (voroedge *) NULL;
-  vfacetlist = (vorofacet *) NULL; 
-  vcelllist = (int **) NULL; 
-  numberofvpoints = 0;
-  numberofvedges = 0;
-  numberofvfacets = 0;
-  numberofvcells = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// deinitialize()    Free the memory allocated in 'tetgenio'.                //
-//                                                                           //
-// It is called by the class destructor '~tetgenio()' implicitly. Hence, the //
-// occupied memory by arrays of an object will be automatically released on  //
-// the deletion of the object. However, this routine assumes that the memory //
-// is allocated by C++ memory allocation operator 'new', thus it is freed by //
-// the C++ array deletor 'delete []'. If one uses the C/C++ library function //
-// 'malloc()' to allocate memory for arrays, one has to free them with the   //
-// 'free()' function, and call routine 'initialize()' once to disable this   //
-// routine on deletion of the object.                                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenio::deinitialize()
-{
-  facet *f;
-  polygon *p;
-  pbcgroup *pg;
-  int i, j;
-
-  if (pointlist != (REAL *) NULL) {
-    delete [] pointlist;
-  }
-  if (pointattributelist != (REAL *) NULL) {
-    delete [] pointattributelist;
-  }
-  if (pointmtrlist != (REAL *) NULL) {
-    delete [] pointmtrlist;
-  }
-  if (pointmarkerlist != (int *) NULL) {
-    delete [] pointmarkerlist;
-  }
-
-  if (tetrahedronlist != (int *) NULL) {
-    delete [] tetrahedronlist;
-  }
-  if (tetrahedronattributelist != (REAL *) NULL) {
-    delete [] tetrahedronattributelist;
-  }
-  if (tetrahedronvolumelist != (REAL *) NULL) {
-    delete [] tetrahedronvolumelist;
-  }
-  if (neighborlist != (int *) NULL) {
-    delete [] neighborlist;
-  }
-
-  if (trifacelist != (int *) NULL) {
-    delete [] trifacelist;
-  }
-  if (adjtetlist != (int *) NULL) {
-    delete [] adjtetlist;
-  }
-  if (trifacemarkerlist != (int *) NULL) {
-    delete [] trifacemarkerlist;
-  }
-
-  if (edgelist != (int *) NULL) {
-    delete [] edgelist;
-  }
-  if (edgemarkerlist != (int *) NULL) {
-    delete [] edgemarkerlist;
-  }
-
-  if (facetlist != (facet *) NULL) {
-    for (i = 0; i < numberoffacets; i++) {
-      f = &facetlist[i];
-      for (j = 0; j < f->numberofpolygons; j++) {
-        p = &f->polygonlist[j];
-        delete [] p->vertexlist;
-      }
-      delete [] f->polygonlist;
-      if (f->holelist != (REAL *) NULL) {
-        delete [] f->holelist;
-      }
-    }
-    delete [] facetlist;
-  }
-  if (facetmarkerlist != (int *) NULL) {
-    delete [] facetmarkerlist;
-  }
-
-  if (holelist != (REAL *) NULL) {
-    delete [] holelist;
-  }
-  if (regionlist != (REAL *) NULL) {
-    delete [] regionlist;
-  }
-  if (facetconstraintlist != (REAL *) NULL) {
-    delete [] facetconstraintlist;
-  }
-  if (segmentconstraintlist != (REAL *) NULL) {
-    delete [] segmentconstraintlist;
-  }
-  if (pbcgrouplist != (pbcgroup *) NULL) {
-    for (i = 0; i < numberofpbcgroups; i++) {
-      pg = &(pbcgrouplist[i]);
-      if (pg->pointpairlist != (int *) NULL) {
-        delete [] pg->pointpairlist;
-      }
-    }
-    delete [] pbcgrouplist;
-  }
-  if (vpointlist != (REAL *) NULL) {
-    delete [] vpointlist;
-  }
-  if (vedgelist != (voroedge *) NULL) {
-    delete [] vedgelist;
-  }
-  if (vfacetlist != (vorofacet *) NULL) {
-    for (i = 0; i < numberofvfacets; i++) {
-      delete [] vfacetlist[i].elist;
-    }
-    delete [] vfacetlist;
-  }
-  if (vcelllist != (int **) NULL) {
-    for (i = 0; i < numberofvcells; i++) {
-      delete [] vcelllist[i];
-    }
-    delete [] vcelllist;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_node_call()    Load a list of nodes.                                 //
-//                                                                           //
-// It is a support routine for routines: 'load_nodes()', 'load_poly()', and  //
-// 'load_tetmesh()'.  'infile' is the file handle contains the node list. It //
-// may point to a .node, or .poly or .smesh file.  'markers' indicates each  //
-// node contains an additional marker (integer) or not. 'infilename' is the  //
-// name of the file being read,  it is only appeared in error message.       //
-//                                                                           //
-// The 'firstnumber' (0 or 1) is automatically determined by the number of   //
-// the first index of the first point.                                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_node_call(FILE* infile, int markers, char* infilename)
-{
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-  REAL x, y, z, attrib;
-  int firstnode, currentmarker;
-  int index, attribindex;
-  int i, j;
-
-  // Initialize 'pointlist', 'pointattributelist', and 'pointmarkerlist'.
-  pointlist = new REAL[numberofpoints * 3];
-  if (pointlist == (REAL *) NULL) {
-    printf("Error:  Out of memory.\n");
-    terminatetetgen(1);
-  }
-  if (numberofpointattributes > 0) {
-    pointattributelist = new REAL[numberofpoints * numberofpointattributes];
-    if (pointattributelist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-  }
-  if (markers) {
-    pointmarkerlist = new int[numberofpoints];
-    if (pointmarkerlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-  }
-
-  // Read the point section.
-  index = 0;
-  attribindex = 0;
-  for (i = 0; i < numberofpoints; i++) {
-    stringptr = readnumberline(inputline, infile, infilename);
-    if (useindex) {
-      if (i == 0) {
-        firstnode = (int) strtol (stringptr, &stringptr, 0);
-        if ((firstnode == 0) || (firstnode == 1)) {
-          firstnumber = firstnode;
-        }
-      }
-      stringptr = findnextnumber(stringptr);
-    } // if (useindex)
-    if (*stringptr == '\0') {
-      printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
-      break;
-    }
-    x = (REAL) strtod(stringptr, &stringptr);
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr == '\0') {
-      printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
-      break;
-    }
-    y = (REAL) strtod(stringptr, &stringptr);
-    if (mesh_dim == 3) {
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
-        break;
-      }
-      z = (REAL) strtod(stringptr, &stringptr);
-    } else {
-      z = 0.0; // mesh_dim == 2;
-    }
-    pointlist[index++] = x;
-    pointlist[index++] = y;
-    pointlist[index++] = z;
-    // Read the point attributes.
-    for (j = 0; j < numberofpointattributes; j++) {
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        attrib = 0.0;
-      } else {
-        attrib = (REAL) strtod(stringptr, &stringptr);
-      }
-      pointattributelist[attribindex++] = attrib;
-    }
-    if (markers) {
-      // Read a point marker.
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        currentmarker = 0;
-      } else {
-        currentmarker = (int) strtol (stringptr, &stringptr, 0);
-      }
-      pointmarkerlist[i] = currentmarker;
-    }
-  }
-  if (i < numberofpoints) {
-    // Failed to read points due to some error.
-    delete [] pointlist;
-    pointlist = (REAL *) NULL;
-    if (markers) {
-      delete [] pointmarkerlist;
-      pointmarkerlist = (int *) NULL;
-    }
-    if (numberofpointattributes > 0) {
-      delete [] pointattributelist;
-      pointattributelist = (REAL *) NULL;
-    }
-    numberofpoints = 0;
-    return false;
-  }
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_node()    Load a list of nodes from a .node file.                    //
-//                                                                           //
-// 'filename' is the inputfile without suffix. The node list is in 'filename.//
-// node'. On completion, the node list is returned in 'pointlist'.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_node(char* filename)
-{
-  FILE *infile;
-  char innodefilename[FILENAMESIZE];
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-  int markers;
-
-  // Assembling the actual file names we want to open.
-  strcpy(innodefilename, filename);
-  strcat(innodefilename, ".node");
-
-  // Try to open a .node file.
-  infile = fopen(innodefilename, "r");
-  if (infile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
-    return false;
-  }
-  printf("Opening %s.\n", innodefilename);  
-  // Read the first line of the file.
-  stringptr = readnumberline(inputline, infile, innodefilename);
-  // Is this list of points generated from rbox?
-  stringptr = strstr(inputline, "rbox");
-  if (stringptr == NULL) {
-    // Read number of points, number of dimensions, number of point
-    //   attributes, and number of boundary markers. 
-    stringptr = inputline;
-    numberofpoints = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr == '\0') {
-      mesh_dim = 3;
-    } else {
-      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr == '\0') {
-      numberofpointattributes = 0;
-    } else {
-      numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr == '\0') {
-      markers = 0;
-    } else {
-      markers = (int) strtol (stringptr, &stringptr, 0);
-    }
-  } else {
-    // It is a rbox (qhull) input file.
-    stringptr = inputline;
-    // Get the dimension.
-    mesh_dim = (int) strtol (stringptr, &stringptr, 0);
-    // Get the number of points.
-    stringptr = readnumberline(inputline, infile, innodefilename);
-    numberofpoints = (int) strtol (stringptr, &stringptr, 0);
-    // There is no index column.
-    useindex = 0;
-  }
-
-  // if ((mesh_dim != 3) && (mesh_dim != 2)) {
-  //   printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
-  //   fclose(infile);
-  //   return false;
-  // }
-  if (numberofpoints < (mesh_dim + 1)) {
-    printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
-    fclose(infile);
-    return false;
-  }
-
-  // Load the list of nodes.
-  if (!load_node_call(infile, markers, innodefilename)) {
-    fclose(infile);
-    return false;
-  }
-  fclose(infile);
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_pbc()    Load a list of pbc groups into 'pbcgrouplist'.              //
-//                                                                           //
-// 'filename' is the filename of the original inputfile without suffix. The  //
-// pbc groups are found in file 'filename.pbc'.                              //
-//                                                                           //
-// This routine will be called both in load_poly() and load_tetmesh().       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_pbc(char* filename)
-{
-  FILE *infile;
-  char pbcfilename[FILENAMESIZE];
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-  pbcgroup *pg;
-  int index, p1, p2;
-  int i, j, k;
-
-  // Pbc groups are saved in file "filename.pbc".
-  strcpy(pbcfilename, filename);
-  strcat(pbcfilename, ".pbc");
-  infile = fopen(pbcfilename, "r");
-  if (infile != (FILE *) NULL) {
-    printf("Opening %s.\n", pbcfilename);
-  } else {
-    // No such file. Return.
-    return false;
-  }
-
-  // Read the number of pbc groups.
-  stringptr = readnumberline(inputline, infile, pbcfilename);
-  numberofpbcgroups = (int) strtol (stringptr, &stringptr, 0);
-  if (numberofpbcgroups == 0) {
-    // It looks this file contains no point.
-    fclose(infile);
-    return false; 
-  }
-  // Initialize 'pbcgrouplist';
-  pbcgrouplist = new pbcgroup[numberofpbcgroups];
-
-  // Read the list of pbc groups.
-  for (i = 0; i < numberofpbcgroups; i++) {
-    pg = &(pbcgrouplist[i]);
-    // Initialize pbcgroup i;
-    pg->numberofpointpairs = 0;
-    pg->pointpairlist = (int *) NULL;
-    // Read 'fmark1', 'fmark2'.
-    stringptr = readnumberline(inputline, infile, pbcfilename);
-    if (*stringptr == '\0') break;
-    pg->fmark1 = (int) strtol(stringptr, &stringptr, 0);
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr == '\0') break;
-    pg->fmark2 = (int) strtol(stringptr, &stringptr, 0);
-    // Read 'transmat'.
-    do {
-      stringptr = readline(inputline, infile, NULL);
-    } while ((*stringptr != '[') && (*stringptr != '\0'));
-    if (*stringptr == '\0') break;
-    for (j = 0; j < 4; j++) {
-      for (k = 0; k < 4; k++) {
-        // Read the entry of [j, k].
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          // Try to read another line.
-          stringptr = readnumberline(inputline, infile, pbcfilename);
-          if (*stringptr == '\0') break;
-        }
-        pg->transmat[j][k] = (REAL) strtod(stringptr, &stringptr);
-      }
-      if (k < 4) break; // Not complete!
-    }
-    if (j < 4) break; // Not complete!
-    // Read 'numberofpointpairs'.
-    stringptr = readnumberline(inputline, infile, pbcfilename);
-    if (*stringptr == '\0') break;
-    pg->numberofpointpairs = (int) strtol(stringptr, &stringptr, 0);
-    if (pg->numberofpointpairs > 0) {
-      pg->pointpairlist = new int[pg->numberofpointpairs * 2];
-      // Read the point pairs.
-      index = 0;
-      for (j = 0; j < pg->numberofpointpairs; j++) {
-        stringptr = readnumberline(inputline, infile, pbcfilename);
-        p1 = (int) strtol(stringptr, &stringptr, 0);
-        stringptr = findnextnumber(stringptr);
-        p2 = (int) strtol(stringptr, &stringptr, 0);
-        pg->pointpairlist[index++] = p1;
-        pg->pointpairlist[index++] = p2;
-      }
-    }
-  }
-  fclose(infile);
-
-  if (i < numberofpbcgroups) {
-    // Failed to read to additional points due to some error.
-    delete [] pbcgrouplist;
-    pbcgrouplist = (pbcgroup *) NULL;
-    numberofpbcgroups = 0;
-    return false;
-  }
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_var()    Load variant constraints applied on facets, segments, nodes.//
-//                                                                           //
-// 'filename' is the filename of the original inputfile without suffix. The  //
-// constraints are found in file 'filename.var'.                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_var(char* filename)
-{
-  FILE *infile;
-  char varfilename[FILENAMESIZE];
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-  int index;
-  int i;
-
-  // Variant constraints are saved in file "filename.var".
-  strcpy(varfilename, filename);
-  strcat(varfilename, ".var");
-  infile = fopen(varfilename, "r");
-  if (infile != (FILE *) NULL) {
-    printf("Opening %s.\n", varfilename);
-  } else {
-    // No such file. Return.
-    return false;
-  }
-
-  // Read the facet constraint section.
-  stringptr = readnumberline(inputline, infile, varfilename);
-  if (*stringptr != '\0') {
-    numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0);
-  } else {
-    numberoffacetconstraints = 0;
-  }
-  if (numberoffacetconstraints > 0) {
-    // Initialize 'facetconstraintlist'.
-    facetconstraintlist = new REAL[numberoffacetconstraints * 2];
-    index = 0;
-    for (i = 0; i < numberoffacetconstraints; i++) {
-      stringptr = readnumberline(inputline, infile, varfilename);
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  facet constraint %d has no facet marker.\n",
-               firstnumber + i);
-        break;
-      } else {
-        facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
-      }
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  facet constraint %d has no maximum area bound.\n",
-               firstnumber + i);
-        break;
-      } else {
-        facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
-      }
-    }
-    if (i < numberoffacetconstraints) {
-      // This must be caused by an error.
-      fclose(infile);
-      return false;
-    }
-  }
-
-  // Read the segment constraint section.
-  stringptr = readnumberline(inputline, infile, varfilename);
-  if (*stringptr != '\0') {
-    numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0);
-  } else {
-    numberofsegmentconstraints = 0;
-  }
-  if (numberofsegmentconstraints > 0) {
-    // Initialize 'segmentconstraintlist'.
-    segmentconstraintlist = new REAL[numberofsegmentconstraints * 3];
-    index = 0;
-    for (i = 0; i < numberofsegmentconstraints; i++) {
-      stringptr = readnumberline(inputline, infile, varfilename);
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  segment constraint %d has no frist endpoint.\n",
-               firstnumber + i);
-        break;
-      } else {
-        segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
-      }
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  segment constraint %d has no second endpoint.\n",
-               firstnumber + i);
-        break;
-      } else {
-        segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
-      }
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  segment constraint %d has no maximum length bound.\n",
-               firstnumber + i);
-        break;
-      } else {
-        segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
-      }
-    }
-    if (i < numberofsegmentconstraints) {
-      // This must be caused by an error.
-      fclose(infile);
-      return false;
-    }
-  }
-
-  fclose(infile);
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_mtr()    Load a size specification map from file.                    //
-//                                                                           //
-// 'filename' is the filename of the original inputfile without suffix. The  //
-// size map is found in file 'filename.mtr'.                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_mtr(char* filename)
-{
-  FILE *infile;
-  char mtrfilename[FILENAMESIZE];
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-  REAL mtr;
-  int mtrindex;
-  int i, j;
-
-  strcpy(mtrfilename, filename);
-  strcat(mtrfilename, ".mtr");
-  infile = fopen(mtrfilename, "r");
-  if (infile != (FILE *) NULL) {
-    printf("Opening %s.\n", mtrfilename);
-  } else {
-    // No such file. Return.
-    return false;
-  }
-
-  // Read number of points, number of columns (1, 3, or 6).
-  stringptr = readnumberline(inputline, infile, mtrfilename);
-  stringptr = findnextnumber(stringptr); // Skip number of points.
-  if (*stringptr != '\0') {
-    numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0);
-  }
-  if (numberofpointmtrs == 0) {
-    // Column number doesn't match. Set a default number (1).
-    numberofpointmtrs = 1;
-  }
-
-  // Allocate space for pointmtrlist.
-  pointmtrlist = new REAL[numberofpoints * numberofpointmtrs];
-  if (pointmtrlist == (REAL *) NULL) {
-    printf("Error:  Out of memory.\n");
-    terminatetetgen(1);
-  }
-  mtrindex = 0;
-  for (i = 0; i < numberofpoints; i++) {
-    // Read metrics.
-    stringptr = readnumberline(inputline, infile, mtrfilename);
-    for (j = 0; j < numberofpointmtrs; j++) {
-      if (*stringptr == '\0') {
-        printf("Error:  Metric %d is missing value #%d in %s.\n",
-               i + firstnumber, j + 1, mtrfilename);
-        terminatetetgen(1);
-      }
-      mtr = (REAL) strtod(stringptr, &stringptr);
-      pointmtrlist[mtrindex++] = mtr;
-      stringptr = findnextnumber(stringptr);
-    }
-  }
-
-  fclose(infile);
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_poly()    Load a piecewise linear complex from a .poly or .smesh.    //
-//                                                                           //
-// 'filename' is the inputfile without suffix. The PLC is in 'filename.poly' //
-// or 'filename.smesh', and possibly plus 'filename.node' (when the first    //
-// line of the file starts with a zero).                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_poly(char* filename)
-{
-  FILE *infile, *polyfile;
-  char innodefilename[FILENAMESIZE];
-  char inpolyfilename[FILENAMESIZE];
-  char insmeshfilename[FILENAMESIZE];
-  char inputline[INPUTLINESIZE];
-  char *stringptr, *infilename;
-  int smesh, markers, currentmarker;
-  int readnodefile, index;
-  int i, j, k;
-
-  // Assembling the actual file names we want to open.
-  strcpy(innodefilename, filename);
-  strcpy(inpolyfilename, filename);
-  strcpy(insmeshfilename, filename);
-  strcat(innodefilename, ".node");
-  strcat(inpolyfilename, ".poly");
-  strcat(insmeshfilename, ".smesh");
-
-  // First assume it is a .poly file.
-  smesh = 0;
-  // Try to open a .poly file.
-  polyfile = fopen(inpolyfilename, "r");
-  if (polyfile == (FILE *) NULL) {
-    // .poly doesn't exist! Try to open a .smesh file.
-    polyfile = fopen(insmeshfilename, "r");
-    if (polyfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot access file %s and %s.\n",
-             inpolyfilename, insmeshfilename);
-      return false;
-    } else {
-      printf("Opening %s.\n", insmeshfilename);
-    }
-    smesh = 1;
-  } else {
-    printf("Opening %s.\n", inpolyfilename);
-  }
-  // Initialize the default values.
-  mesh_dim = 3;  // Three-dimemsional accoordinates.
-  numberofpointattributes = 0;  // no point attribute.
-  markers = 0;  // no boundary marker.
-  // Read number of points, number of dimensions, number of point
-  //   attributes, and number of boundary markers.
-  stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-  numberofpoints = (int) strtol (stringptr, &stringptr, 0);
-  stringptr = findnextnumber(stringptr);
-  if (*stringptr != '\0') {
-    mesh_dim = (int) strtol (stringptr, &stringptr, 0);      
-  }
-  stringptr = findnextnumber(stringptr);
-  if (*stringptr != '\0') {
-    numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
-  }
-  stringptr = findnextnumber(stringptr);
-  if (*stringptr != '\0') {
-    markers = (int) strtol (stringptr, &stringptr, 0);
-  }
-  if (numberofpoints > 0) {
-    readnodefile = 0;
-    if (smesh) {
-      infilename = insmeshfilename;
-    } else {
-      infilename = inpolyfilename;
-    } 
-    infile = polyfile;
-  } else {
-    // If the .poly or .smesh file claims there are zero points, that
-    //   means the points should be read from a separate .node file.
-    readnodefile = 1;
-    infilename = innodefilename;
-  }
-
-  if (readnodefile) {
-    // Read the points from the .node file.
-    printf("Opening %s.\n", innodefilename);
-    infile = fopen(innodefilename, "r");
-    if (infile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
-      return false;
-    }
-    // Initialize the default values.
-    mesh_dim = 3;  // Three-dimemsional accoordinates.
-    numberofpointattributes = 0;  // no point attribute.
-    markers = 0;  // no boundary marker.
-    // Read number of points, number of dimensions, number of point
-    //   attributes, and number of boundary markers.
-    stringptr = readnumberline(inputline, infile, innodefilename);
-    numberofpoints = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr != '\0') {
-      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr != '\0') {
-      numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr != '\0') {
-      markers = (int) strtol (stringptr, &stringptr, 0);
-    }
-  }
-
-  if ((mesh_dim != 3) && (mesh_dim != 2)) {
-    printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
-    fclose(infile);
-    return false;
-  }
-  if (numberofpoints < (mesh_dim + 1)) {
-    printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
-    fclose(infile);
-    return false;
-  }
-
-  // Load the list of nodes.
-  if (!load_node_call(infile, markers, infilename)) {
-    fclose(infile);
-    return false;
-  }
-
-  if (readnodefile) {
-    fclose(infile);
-  }
-
-  facet *f;
-  polygon *p;
-
-  if (mesh_dim == 3) {
-
-    // Read number of facets and number of boundary markers.
-    stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-    numberoffacets = (int) strtol (stringptr, &stringptr, 0);
-    if (numberoffacets <= 0) {
-      // No facet list, return.
-      fclose(polyfile);
-      return true;
-    }
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr == '\0') {
-      markers = 0;  // no boundary marker.
-    } else {
-      markers = (int) strtol (stringptr, &stringptr, 0);
-    }
-
-    // Initialize the 'facetlist', 'facetmarkerlist'.
-    facetlist = new facet[numberoffacets];
-    if (markers == 1) {
-      facetmarkerlist = new int[numberoffacets];
-    }
-
-    // Read data into 'facetlist', 'facetmarkerlist'.
-    if (smesh == 0) {
-      // Facets are in .poly file format.
-      for (i = 1; i <= numberoffacets; i++) {
-        f = &(facetlist[i - 1]);
-        init(f);
-        f->numberofholes = 0;
-        currentmarker = 0;
-        // Read number of polygons, number of holes, and a boundary marker.
-        stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-        f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr != '\0') {
-          f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
-          if (markers == 1) {
-            stringptr = findnextnumber(stringptr);
-            if (*stringptr != '\0') {
-              currentmarker = (int) strtol(stringptr, &stringptr, 0);
-            }
-          }
-        }
-        // Initialize facetmarker if it needs.
-        if (markers == 1) {
-          facetmarkerlist[i - 1] = currentmarker; 
-        }
-        // Each facet should has at least one polygon.
-        if (f->numberofpolygons <= 0) {
-          printf("Error:  Wrong number of polygon in %d facet.\n", i);
-          break; 
-        }
-        // Initialize the 'f->polygonlist'.
-        f->polygonlist = new polygon[f->numberofpolygons];
-        // Go through all polygons, read in their vertices.
-        for (j = 1; j <= f->numberofpolygons; j++) {
-          p = &(f->polygonlist[j - 1]);
-          init(p);
-          // Read number of vertices of this polygon.
-          stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-          p->numberofvertices = (int) strtol(stringptr, &stringptr, 0);
-          if (p->numberofvertices < 1) {
-            printf("Error:  Wrong polygon %d in facet %d\n", j, i);
-            break;
-          }
-          // Initialize 'p->vertexlist'.
-          p->vertexlist = new int[p->numberofvertices];
-          // Read all vertices of this polygon.
-          for (k = 1; k <= p->numberofvertices; k++) {
-            stringptr = findnextnumber(stringptr);
-            if (*stringptr == '\0') {
-              // Try to load another non-empty line and continue to read the
-              //   rest of vertices.
-              stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-              if (*stringptr == '\0') {
-                printf("Error: Missing %d endpoints of polygon %d in facet %d",
-                       p->numberofvertices - k, j, i);
-                break;
-              }
-            }
-            p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
-          }
-        } 
-        if (j <= f->numberofpolygons) {
-          // This must be caused by an error. However, there're j - 1
-          //   polygons have been read. Reset the 'f->numberofpolygon'.
-          if (j == 1) {
-            // This is the first polygon.
-            delete [] f->polygonlist;
-          }
-          f->numberofpolygons = j - 1;
-          // No hole will be read even it exists.
-          f->numberofholes = 0;
-          break;
-        }
-        // If this facet has hole pints defined, read them.
-        if (f->numberofholes > 0) {
-          // Initialize 'f->holelist'.
-          f->holelist = new REAL[f->numberofholes * 3];
-          // Read the holes' coordinates.
-          index = 0;
-          for (j = 1; j <= f->numberofholes; j++) {
-            stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-            for (k = 1; k <= 3; k++) {
-              stringptr = findnextnumber(stringptr);
-              if (*stringptr == '\0') {
-                printf("Error:  Hole %d in facet %d has no coordinates", j, i);
-                break;
-              }
-              f->holelist[index++] = (REAL) strtod (stringptr, &stringptr);
-            }
-            if (k <= 3) {
-              // This must be caused by an error.
-              break;
-            }
-          }
-          if (j <= f->numberofholes) {
-            // This must be caused by an error.
-            break;
-          }
-        }
-      }
-      if (i <= numberoffacets) {
-        // This must be caused by an error.
-        numberoffacets = i - 1;
-        fclose(polyfile);
-        return false;
-      }
-    } else { // poly == 0
-      // Read the facets from a .smesh file.
-      for (i = 1; i <= numberoffacets; i++) {
-        f = &(facetlist[i - 1]);
-        init(f);
-        // Initialize 'f->facetlist'. In a .smesh file, each facetlist only
-        //   contains exactly one polygon, no hole.
-        f->numberofpolygons = 1;
-        f->polygonlist = new polygon[f->numberofpolygons];
-        p = &(f->polygonlist[0]);
-        init(p);
-        // Read number of vertices of this polygon.
-        stringptr = readnumberline(inputline, polyfile, insmeshfilename);
-        p->numberofvertices = (int) strtol (stringptr, &stringptr, 0);
-        if (p->numberofvertices < 1) {
-          printf("Error:  Wrong number of vertex in facet %d\n", i);
-          break;
-        }
-        // Initialize 'p->vertexlist'.
-        p->vertexlist = new int[p->numberofvertices];
-        for (k = 1; k <= p->numberofvertices; k++) {
-          stringptr = findnextnumber(stringptr);
-          if (*stringptr == '\0') {
-            // Try to load another non-empty line and continue to read the
-            //   rest of vertices.
-            stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-            if (*stringptr == '\0') {
-              printf("Error:  Missing %d endpoints in facet %d",
-                     p->numberofvertices - k, i);
-              break;
-            }
-          }
-          p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
-        }
-        if (k <= p->numberofvertices) {
-          // This must be caused by an error.
-          break;
-        }
-        // Read facet's boundary marker at last.
-        if (markers == 1) {
-          stringptr = findnextnumber(stringptr);
-          if (*stringptr == '\0') {
-            currentmarker = 0;
-          } else {
-            currentmarker = (int) strtol(stringptr, &stringptr, 0);
-          }
-          facetmarkerlist[i - 1] = currentmarker;
-        }
-      }
-      if (i <= numberoffacets) {
-        // This must be caused by an error.
-        numberoffacets = i - 1;
-        fclose(polyfile);
-        return false;
-      }
-    }
-
-    // Read the hole section.
-    stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-    if (*stringptr != '\0') {
-      numberofholes = (int) strtol (stringptr, &stringptr, 0);
-    } else {
-      numberofholes = 0;
-    }
-    if (numberofholes > 0) {
-      // Initialize 'holelist'.
-      holelist = new REAL[numberofholes * 3];
-      for (i = 0; i < 3 * numberofholes; i += 3) {
-        stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Hole %d has no x coord.\n", firstnumber + (i / 3));
-          break;
-        } else {
-          holelist[i] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Hole %d has no y coord.\n", firstnumber + (i / 3));
-          break;
-        } else {
-          holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Hole %d has no z coord.\n", firstnumber + (i / 3));
-          break;
-        } else {
-          holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
-        }
-      }
-      if (i < 3 * numberofholes) {
-        // This must be caused by an error.
-        fclose(polyfile);
-        return false;
-      }
-    }
-
-    // Read the region section.  The 'region' section is optional, if we
-    //   don't reach the end-of-file, try read it in.
-    stringptr = readnumberline(inputline, polyfile, NULL);
-    if (stringptr != (char *) NULL && *stringptr != '\0') {
-      numberofregions = (int) strtol (stringptr, &stringptr, 0);
-    } else {
-      numberofregions = 0;
-    }
-    if (numberofregions > 0) {
-      // Initialize 'regionlist'.
-      regionlist = new REAL[numberofregions * 5];
-      index = 0;
-      for (i = 0; i < numberofregions; i++) {
-        stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Region %d has no x coordinate.\n", firstnumber + i);
-          break;
-        } else {
-          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Region %d has no y coordinate.\n", firstnumber + i);
-          break;
-        } else {
-          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Region %d has no z coordinate.\n", firstnumber + i);
-          break;
-        } else {
-          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Region %d has no region attrib.\n", firstnumber + i);
-          break;
-        } else {
-          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          regionlist[index] = regionlist[index - 1];
-        } else {
-          regionlist[index] = (REAL) strtod(stringptr, &stringptr);
-        }
-        index++;
-      }
-      if (i < numberofregions) {
-        // This must be caused by an error.
-        fclose(polyfile);
-        return false;
-      }
-    }
-
-  } else {
-
-    // Read a PSLG from Triangle's poly file.
-    assert(mesh_dim == 2);
-    // A PSLG is a facet of a PLC.
-    numberoffacets = 1;
-    // Initialize the 'facetlist'.
-    facetlist = new facet[numberoffacets];
-    facetmarkerlist = (int *) NULL; // No facet markers.
-    f = &(facetlist[0]);
-    init(f);
-    // Read number of segments.
-    stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-    // Segments are degenerate polygons.
-    f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
-    if (f->numberofpolygons > 0) {
-      f->polygonlist = new polygon[f->numberofpolygons];
-    }
-    // Go through all segments, read in their vertices.
-    for (j = 0; j < f->numberofpolygons; j++) {
-      p = &(f->polygonlist[j]);
-      init(p);
-      // Read in a segment.
-      stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-      stringptr = findnextnumber(stringptr); // Skip its index.
-      p->numberofvertices = 2; // A segment always has two vertices.
-      p->vertexlist = new int[p->numberofvertices];
-      p->vertexlist[0] = (int) strtol (stringptr, &stringptr, 0);
-      stringptr = findnextnumber(stringptr);
-      p->vertexlist[1] = (int) strtol (stringptr, &stringptr, 0);
-    }
-    // Read number of holes.
-    stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-    f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
-    if (f->numberofholes > 0) {
-      // Initialize 'f->holelist'.
-      f->holelist = new REAL[f->numberofholes * 3];
-      // Read the holes' coordinates.
-      for (j = 0; j < f->numberofholes; j++) {
-        // Read a 2D hole point.
-        stringptr = readnumberline(inputline, polyfile, inpolyfilename);
-        stringptr = findnextnumber(stringptr); // Skip its index.
-        f->holelist[j * 3] = (REAL) strtod (stringptr, &stringptr);
-        stringptr = findnextnumber(stringptr);
-        f->holelist[j * 3 + 1] = (REAL) strtod (stringptr, &stringptr);
-        f->holelist[j * 3 + 2] = 0.0; // The z-coord.
-      }
-    }
-    // The regions are skipped.
-
-  }
-
-  // End of reading poly/smesh file.
-  fclose(polyfile);
-
-  // Try to load a .var file if it exists.
-  load_var(filename);
-  // Try to load a .mtr file if it exists.
-  load_mtr(filename);
-  // Try to read a .pbc file if it exists.
-  load_pbc(filename);
-
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_off()    Load a polyhedron described in a .off file.                 //
-//                                                                           //
-// The .off format is one of file formats of the Geomview, an interactive    //
-// program for viewing and manipulating geometric objects.  More information //
-// is available form: http://www.geomview.org.                               //
-//                                                                           //
-// 'filename' is a input filename with extension .off or without extension ( //
-// the .off will be added in this case). On completion, the polyhedron is    //
-// returned in 'pointlist' and 'facetlist'.                                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_off(char* filename)
-{
-  FILE *fp;
-  tetgenio::facet *f;
-  tetgenio::polygon *p;
-  char infilename[FILENAMESIZE];
-  char buffer[INPUTLINESIZE];
-  char *bufferp;
-  double *coord;
-  int nverts = 0, iverts = 0;
-  int nfaces = 0, ifaces = 0;
-  int nedges = 0;
-  int line_count = 0, i;
-
-  strncpy(infilename, filename, 1024 - 1);
-  infilename[FILENAMESIZE - 1] = '\0';
-  if (infilename[0] == '\0') {
-    printf("Error:  No filename.\n");
-    return false;
-  }
-  if (strcmp(&infilename[strlen(infilename) - 4], ".off") != 0) {
-    strcat(infilename, ".off");
-  }
-
-  if (!(fp = fopen(infilename, "r"))) {
-    printf("File I/O Error:  Unable to open file %s\n", infilename);
-    return false;
-  }
-  printf("Opening %s.\n", infilename);
-
-  // OFF requires the index starts from '0'.
-  firstnumber = 0;
-
-  while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
-    // Check section
-    if (nverts == 0) {
-      // Read header 
-      bufferp = strstr(bufferp, "OFF");
-      if (bufferp != NULL) {
-        // Read mesh counts
-        bufferp = findnextnumber(bufferp); // Skip field "OFF".
-        if (*bufferp == '\0') {
-          // Read a non-empty line.
-          bufferp = readline(buffer, fp, &line_count);
-        }
-        if ((sscanf(bufferp, "%d%d%d", &nverts, &nfaces, &nedges) != 3) 
-            || (nverts == 0)) {
-          printf("Syntax error reading header on line %d in file %s\n",
-                 line_count, infilename);
-          fclose(fp);
-          return false;
-        }
-        // Allocate memory for 'tetgenio'
-        if (nverts > 0) {
-          numberofpoints = nverts;
-          pointlist = new REAL[nverts * 3];
-        }
-        if (nfaces > 0) {        
-          numberoffacets = nfaces;
-          facetlist = new tetgenio::facet[nfaces];
-        }
-      }
-    } else if (iverts < nverts) {
-      // Read vertex coordinates
-      coord = &pointlist[iverts * 3];
-      for (i = 0; i < 3; i++) {
-        if (*bufferp == '\0') {
-          printf("Syntax error reading vertex coords on line %d in file %s\n",
-                 line_count, infilename);
-          fclose(fp);
-          return false;
-        }
-        coord[i] = (REAL) strtod(bufferp, &bufferp);
-        bufferp = findnextnumber(bufferp);
-      }
-      iverts++;
-    } else if (ifaces < nfaces) {
-      // Get next face
-      f = &facetlist[ifaces];
-      init(f);      
-      // In .off format, each facet has one polygon, no hole.
-      f->numberofpolygons = 1;
-      f->polygonlist = new tetgenio::polygon[1];
-      p = &f->polygonlist[0];
-      init(p);
-      // Read the number of vertices, it should be greater than 0.
-      p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
-      if (p->numberofvertices == 0) {
-        printf("Syntax error reading polygon on line %d in file %s\n",
-               line_count, infilename);
-        fclose(fp);
-        return false;
-      }
-      // Allocate memory for face vertices
-      p->vertexlist = new int[p->numberofvertices];
-      for (i = 0; i < p->numberofvertices; i++) {
-        bufferp = findnextnumber(bufferp);
-        if (*bufferp == '\0') {
-          printf("Syntax error reading polygon on line %d in file %s\n",
-                 line_count, infilename);
-          fclose(fp);
-          return false;
-        }
-        p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
-      }
-      ifaces++;
-    } else {
-      // Should never get here
-      printf("Found extra text starting at line %d in file %s\n", line_count,
-             infilename);
-      break;
-    }
-  }
-
-  // Close file
-  fclose(fp);
-
-  // Check whether read all points
-  if (iverts != nverts) {
-    printf("Expected %d vertices, but read only %d vertices in file %s\n",
-           nverts, iverts, infilename);
-    return false;
-  }
-
-  // Check whether read all faces
-  if (ifaces != nfaces) {
-    printf("Expected %d faces, but read only %d faces in file %s\n",
-           nfaces, ifaces, infilename);
-    return false;
-  }
-
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_ply()    Load a polyhedron described in a .ply file.                 //
-//                                                                           //
-// 'filename' is the file name with extension .ply or without extension (the //
-// .ply will be added in this case).                                         //
-//                                                                           //
-// This is a simplified version of reading .ply files, which only reads the  //
-// set of vertices and the set of faces. Other informations (such as color,  //
-// material, texture, etc) in .ply file are ignored. Complete routines for   //
-// reading and writing ,ply files are available from: http://www.cc.gatech.  //
-// edu/projects/large_models/ply.html.  Except the header section, ply file  //
-// format has exactly the same format for listing vertices and polygons as   //
-// off file format.                                                          //
-//                                                                           //
-// On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_ply(char* filename)
-{
-  FILE *fp;
-  tetgenio::facet *f;
-  tetgenio::polygon *p;
-  char infilename[FILENAMESIZE];
-  char buffer[INPUTLINESIZE];
-  char *bufferp, *str;
-  double *coord;
-  int endheader = 0, format = 0;
-  int nverts = 0, iverts = 0;
-  int nfaces = 0, ifaces = 0;
-  int line_count = 0, i;
-
-  strncpy(infilename, filename, FILENAMESIZE - 1);
-  infilename[FILENAMESIZE - 1] = '\0';
-  if (infilename[0] == '\0') {
-    printf("Error:  No filename.\n");
-    return false;
-  }
-  if (strcmp(&infilename[strlen(infilename) - 4], ".ply") != 0) {
-    strcat(infilename, ".ply");
-  }
-
-  if (!(fp = fopen(infilename, "r"))) {
-    printf("Error:  Unable to open file %s\n", infilename);
-    return false;
-  }
-  printf("Opening %s.\n", infilename);
-
-  // PLY requires the index starts from '0'.
-  firstnumber = 0;
-
-  while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
-    if (!endheader) {
-      // Find if it is the keyword "end_header".
-      str = strstr(bufferp, "end_header");
-      // strstr() is case sensitive.
-      if (!str) str = strstr(bufferp, "End_header");
-      if (!str) str = strstr(bufferp, "End_Header");
-      if (str) {
-        // This is the end of the header section.
-        endheader = 1; 
-        continue;
-      }
-      // Parse the number of vertices and the number of faces.
-      if (nverts == 0 || nfaces == 0) {
-        // Find if it si the keyword "element".
-        str = strstr(bufferp, "element");
-        if (!str) str = strstr(bufferp, "Element");
-        if (str) {
-          bufferp = findnextfield(str);
-          if (*bufferp == '\0') {
-            printf("Syntax error reading element type on line%d in file %s\n",
-                   line_count, infilename);
-            fclose(fp);
-            return false;
-          }
-          if (nverts == 0) {
-            // Find if it is the keyword "vertex".
-            str = strstr(bufferp, "vertex");
-            if (!str) str = strstr(bufferp, "Vertex");
-            if (str) {
-              bufferp = findnextnumber(str);
-              if (*bufferp == '\0') {
-                printf("Syntax error reading vertex number on line");
-                printf(" %d in file %s\n", line_count, infilename);
-                fclose(fp);
-                return false;
-              }
-              nverts = (int) strtol(bufferp, &bufferp, 0);
-              // Allocate memory for 'tetgenio'
-              if (nverts > 0) {
-                numberofpoints = nverts;
-                pointlist = new REAL[nverts * 3];
-              }
-            }
-          }
-          if (nfaces == 0) {
-            // Find if it is the keyword "face".
-            str = strstr(bufferp, "face");
-            if (!str) str = strstr(bufferp, "Face");
-            if (str) {
-              bufferp = findnextnumber(str);
-              if (*bufferp == '\0') {
-                printf("Syntax error reading face number on line");
-                printf(" %d in file %s\n", line_count, infilename);
-                fclose(fp);
-                return false;
-              }
-              nfaces = (int) strtol(bufferp, &bufferp, 0);
-              // Allocate memory for 'tetgenio'
-              if (nfaces > 0) {        
-                numberoffacets = nfaces;
-                facetlist = new tetgenio::facet[nfaces];
-              }
-            }
-          }
-        } // It is not the string "element". 
-      }
-      if (format == 0) {
-        // Find the keyword "format".
-        str = strstr(bufferp, "format");
-        if (!str) str = strstr(bufferp, "Format");
-        if (str) {
-          format = 1;
-          bufferp = findnextfield(str);
-          // Find if it is the string "ascii".
-          str = strstr(bufferp, "ascii");
-          if (!str) str = strstr(bufferp, "ASCII");
-          if (!str) {
-            printf("This routine only reads ascii format of ply files.\n");
-            printf("Hint: You can convert the binary to ascii format by\n");
-            printf("  using the provided ply tools:\n");
-            printf("  ply2ascii < %s > ascii_%s\n", infilename, infilename);
-            fclose(fp);
-            return false;
-          }
-        }
-      }
-    } else if (iverts < nverts) {
-      // Read vertex coordinates
-      coord = &pointlist[iverts * 3];
-      for (i = 0; i < 3; i++) {
-        if (*bufferp == '\0') {
-          printf("Syntax error reading vertex coords on line %d in file %s\n",
-                 line_count, infilename);
-          fclose(fp);
-          return false;
-        }
-        coord[i] = (REAL) strtod(bufferp, &bufferp);
-        bufferp = findnextnumber(bufferp);
-      }
-      iverts++;
-    } else if (ifaces < nfaces) {
-      // Get next face
-      f = &facetlist[ifaces];
-      init(f);      
-      // In .off format, each facet has one polygon, no hole.
-      f->numberofpolygons = 1;
-      f->polygonlist = new tetgenio::polygon[1];
-      p = &f->polygonlist[0];
-      init(p);
-      // Read the number of vertices, it should be greater than 0.
-      p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
-      if (p->numberofvertices == 0) {
-        printf("Syntax error reading polygon on line %d in file %s\n",
-               line_count, infilename);
-        fclose(fp);
-        return false;
-      }
-      // Allocate memory for face vertices
-      p->vertexlist = new int[p->numberofvertices];
-      for (i = 0; i < p->numberofvertices; i++) {
-        bufferp = findnextnumber(bufferp);
-        if (*bufferp == '\0') {
-          printf("Syntax error reading polygon on line %d in file %s\n",
-                 line_count, infilename);
-          fclose(fp);
-          return false;
-        }
-        p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
-      }
-      ifaces++;
-    } else {
-      // Should never get here
-      printf("Found extra text starting at line %d in file %s\n", line_count,
-             infilename);
-      break;
-    }
-  }
-
-  // Close file
-  fclose(fp);
-
-  // Check whether read all points
-  if (iverts != nverts) {
-    printf("Expected %d vertices, but read only %d vertices in file %s\n",
-           nverts, iverts, infilename);
-    return false;
-  }
-
-  // Check whether read all faces
-  if (ifaces != nfaces) {
-    printf("Expected %d faces, but read only %d faces in file %s\n",
-           nfaces, ifaces, infilename);
-    return false;
-  }
-
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_stl()    Load a surface mesh described in a .stl file.               //
-//                                                                           //
-// 'filename' is the file name with extension .stl or without extension (the //
-// .stl will be added in this case).                                         //
-//                                                                           //
-// The .stl or stereolithography format is an ASCII or binary file used in   //
-// manufacturing.  It is a list of the triangular surfaces that describe a   //
-// computer generated solid model. This is the standard input for most rapid //
-// prototyping machines.                                                     //
-//                                                                           //
-// On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
-// Note: After load_stl(), there exist many duplicated points in 'pointlist'.//
-// They will be unified during the Delaunay tetrahedralization process.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_stl(char* filename)
-{
-  FILE *fp;
-  tetgenmesh::list *plist;
-  tetgenio::facet *f;
-  tetgenio::polygon *p;
-  char infilename[FILENAMESIZE];
-  char buffer[INPUTLINESIZE];
-  char *bufferp, *str;
-  double *coord;
-  int solid = 0;
-  int nverts = 0, iverts = 0;
-  int nfaces = 0;
-  int line_count = 0, i;
-
-  strncpy(infilename, filename, FILENAMESIZE - 1);
-  infilename[FILENAMESIZE - 1] = '\0';
-  if (infilename[0] == '\0') {
-    printf("Error:  No filename.\n");
-    return false;
-  }
-  if (strcmp(&infilename[strlen(infilename) - 4], ".stl") != 0) {
-    strcat(infilename, ".stl");
-  }
-
-  if (!(fp = fopen(infilename, "r"))) {
-    printf("Error:  Unable to open file %s\n", infilename);
-    return false;
-  }
-  printf("Opening %s.\n", infilename);
-
-  // STL file has no number of points available. Use a list to read points.
-  plist = new tetgenmesh::list(sizeof(double) * 3, NULL, 1024); 
-
-  while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
-    // The ASCII .stl file must start with the lower case keyword solid and
-    //   end with endsolid.
-    if (solid == 0) {
-      // Read header 
-      bufferp = strstr(bufferp, "solid");
-      if (bufferp != NULL) {
-        solid = 1;
-      }
-    } else {
-      // We're inside the block of the solid.
-      str = bufferp;
-      // Is this the end of the solid.
-      bufferp = strstr(bufferp, "endsolid");
-      if (bufferp != NULL) {
-        solid = 0;
-      } else {
-        // Read the XYZ coordinates if it is a vertex.
-        bufferp = str;
-        bufferp = strstr(bufferp, "vertex");
-        if (bufferp != NULL) {
-          coord = (double *) plist->append(NULL);
-          for (i = 0; i < 3; i++) {
-            bufferp = findnextnumber(bufferp);
-            if (*bufferp == '\0') {
-              printf("Syntax error reading vertex coords on line %d\n",
-                   line_count);
-              delete plist;
-              fclose(fp);
-              return false;
-            }
-            coord[i] = (REAL) strtod(bufferp, &bufferp);
-          }
-        }
-      }
-    }
-  }
-  fclose(fp);
-
-  nverts = plist->len();
-  // nverts should be an integer times 3 (every 3 vertices denote a face).
-  if (nverts == 0 || (nverts % 3 != 0)) {
-    printf("Error:  Wrong number of vertices in file %s.\n", infilename);
-    delete plist;
-    return false;
-  }
-  numberofpoints = nverts;
-  pointlist = new REAL[nverts * 3];
-  for (i = 0; i < nverts; i++) {
-    coord = (double *) (* plist)[i];
-    iverts = i * 3;
-    pointlist[iverts] = (REAL) coord[0];
-    pointlist[iverts + 1] = (REAL) coord[1];
-    pointlist[iverts + 2] = (REAL) coord[2];
-  }
-
-  nfaces = (int) (nverts / 3);
-  numberoffacets = nfaces;
-  facetlist = new tetgenio::facet[nfaces];
-
-  // Default use '1' as the array starting index.
-  firstnumber = 1;
-  iverts = firstnumber;
-  for (i = 0; i < nfaces; i++) {
-    f = &facetlist[i];
-    init(f);      
-    // In .stl format, each facet has one polygon, no hole.
-    f->numberofpolygons = 1;
-    f->polygonlist = new tetgenio::polygon[1];
-    p = &f->polygonlist[0];
-    init(p);
-    // Each polygon has three vertices.
-    p->numberofvertices = 3;
-    p->vertexlist = new int[p->numberofvertices];
-    p->vertexlist[0] = iverts;
-    p->vertexlist[1] = iverts + 1;
-    p->vertexlist[2] = iverts + 2;
-    iverts += 3;
-  }
-
-  delete plist;
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_medit()    Load a surface mesh described in .mesh file.              //
-//                                                                           //
-// 'filename' is the file name with extension .mesh or without entension (   //
-// the .mesh will be added in this case). .mesh is the file format of Medit, //
-// a user-friendly interactive mesh viewing program.                         //
-//                                                                           //
-// This routine ONLY reads the sections containing vertices, triangles, and  //
-// quadrilaters. Other sections (such as tetrahedra, edges, ...) are ignored.//
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_medit(char* filename)
-{
-  FILE *fp;
-  tetgenio::facet *tmpflist, *f;
-  tetgenio::polygon *p;
-  char infilename[FILENAMESIZE];
-  char buffer[INPUTLINESIZE];
-  char *bufferp, *str;
-  double *coord;
-  int *tmpfmlist;
-  int dimension = 0;
-  int nverts = 0;
-  int nfaces = 0;
-  int line_count = 0;
-  int corners = 0; // 3 (triangle) or 4 (quad).
-  int i, j;
-
-  strncpy(infilename, filename, FILENAMESIZE - 1);
-  infilename[FILENAMESIZE - 1] = '\0';
-  if (infilename[0] == '\0') {
-    printf("Error:  No filename.\n");
-    return false;
-  }
-  if (strcmp(&infilename[strlen(infilename) - 5], ".mesh") != 0) {
-    strcat(infilename, ".mesh");
-  }
-  
-  if (!(fp = fopen(infilename, "r"))) {
-    printf("Error:  Unable to open file %s\n", infilename);
-    return false;
-  }
-  printf("Opening %s.\n", infilename);
-
-  // Default uses the index starts from '1'.
-  firstnumber = 1;
-
-  while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
-    if (*bufferp == '#') continue;  // A comment line is skipped.
-    if (dimension == 0) {
-      // Find if it is the keyword "Dimension".
-      str = strstr(bufferp, "Dimension");
-      if (!str) str = strstr(bufferp, "dimension");
-      if (!str) str = strstr(bufferp, "DIMENSION");
-      if (str) {
-        // Read the dimensions
-        bufferp = findnextnumber(str); // Skip field "Dimension".
-        if (*bufferp == '\0') {
-          // Read a non-empty line.
-          bufferp = readline(buffer, fp, &line_count);
-        }
-        dimension = (int) strtol(bufferp, &bufferp, 0);
-        if (dimension != 2 && dimension != 3) {
-          printf("Unknown dimension in file on line %d in file %s\n",
-                 line_count, infilename);
-          fclose(fp);
-          return false;
-        }
-        mesh_dim = dimension;
-      }
-    }
-    if (nverts == 0) {
-      // Find if it is the keyword "Vertices".
-      str = strstr(bufferp, "Vertices");
-      if (!str) str = strstr(bufferp, "vertices");
-      if (!str) str = strstr(bufferp, "VERTICES");
-      if (str) {
-        // Read the number of vertices.
-        bufferp = findnextnumber(str); // Skip field "Vertices".
-        if (*bufferp == '\0') {
-          // Read a non-empty line.
-          bufferp = readline(buffer, fp, &line_count);
-        }
-        nverts = (int) strtol(bufferp, &bufferp, 0);
-        // Allocate memory for 'tetgenio'
-        if (nverts > 0) {
-          numberofpoints = nverts;
-          pointlist = new REAL[nverts * 3];
-        }
-        // Read the follwoing node list.
-        for (i = 0; i < nverts; i++) {
-          bufferp = readline(buffer, fp, &line_count);
-          if (bufferp == NULL) {
-            printf("Unexpected end of file on line %d in file %s\n",
-                   line_count, infilename);
-            fclose(fp);
-            return false;
-          }
-          // Read vertex coordinates
-          coord = &pointlist[i * 3];
-          for (j = 0; j < 3; j++) {
-            if (*bufferp == '\0') {
-              printf("Syntax error reading vertex coords on line");
-              printf(" %d in file %s\n", line_count, infilename);
-              fclose(fp);
-              return false;
-            }
-            if ((j < 2) || (dimension == 3)) {
-              coord[j] = (REAL) strtod(bufferp, &bufferp);
-            } else {
-              assert((j == 2) && (dimension == 2));
-              coord[j] = 0.0;
-            }
-            bufferp = findnextnumber(bufferp);
-          }
-        }
-        continue;
-      }
-    } 
-    if (nfaces == 0) {
-      // Find if it is the keyword "Triangles" or "Quadrilaterals".
-      corners = 0;
-      str = strstr(bufferp, "Triangles");
-      if (!str) str = strstr(bufferp, "triangles");
-      if (!str) str = strstr(bufferp, "TRIANGLES");
-      if (str) {
-        corners = 3;
-      } else {
-        str = strstr(bufferp, "Quadrilaterals");
-        if (!str) str = strstr(bufferp, "quadrilaterals");
-        if (!str) str = strstr(bufferp, "QUADRILATERALS");
-        if (str) {
-          corners = 4;
-        }
-      }
-      if (corners == 3 || corners == 4) {
-        // Read the number of triangles (or quadrilaterals).
-        bufferp = findnextnumber(str); // Skip field "Triangles".
-        if (*bufferp == '\0') {
-          // Read a non-empty line.
-          bufferp = readline(buffer, fp, &line_count);
-        }
-        nfaces = strtol(bufferp, &bufferp, 0);
-        // Allocate memory for 'tetgenio'
-        if (nfaces > 0) {
-          if (numberoffacets > 0) {
-            // facetlist has already been allocated. Enlarge arrays.
-            tmpflist = new tetgenio::facet[numberoffacets + nfaces];
-            tmpfmlist = new int[numberoffacets + nfaces];
-            // Copy the data of old arrays into new arrays.
-            for (i = 0; i < numberoffacets; i++) {
-              f = &(tmpflist[i]);
-              tetgenio::init(f);
-              *f = facetlist[i];
-              tmpfmlist[i] = facetmarkerlist[i];
-            }
-            // Release old arrays.
-            delete [] facetlist;
-            delete [] facetmarkerlist;
-            // Remember the new arrays.
-            facetlist = tmpflist;
-            facetmarkerlist = tmpfmlist;
-          } else {
-            // This is the first time to allocate facetlist.
-            facetlist = new tetgenio::facet[nfaces];
-            facetmarkerlist = new int[nfaces];
-          }
-        }
-        // Read the following list of faces.
-        for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
-          bufferp = readline(buffer, fp, &line_count);
-          if (bufferp == NULL) {
-            printf("Unexpected end of file on line %d in file %s\n",
-                   line_count, infilename);
-            fclose(fp);
-            return false;
-          }
-          f = &facetlist[i];
-          tetgenio::init(f);
-          // In .mesh format, each facet has one polygon, no hole.
-          f->numberofpolygons = 1;
-          f->polygonlist = new tetgenio::polygon[1];
-          p = &f->polygonlist[0];
-          tetgenio::init(p);
-          p->numberofvertices = corners;
-          // Allocate memory for face vertices
-          p->vertexlist = new int[p->numberofvertices];
-          // Read the vertices of the face.
-          for (j = 0; j < corners; j++) {
-            if (*bufferp == '\0') {
-              printf("Syntax error reading face on line %d in file %s\n",
-                     line_count, infilename);
-              fclose(fp);
-              return false;
-            }
-            p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0);
-            if (firstnumber == 1) {
-              // Check if a '0' index appears.
-              if (p->vertexlist[j] == 0) {
-                // The first index is set to be 0.
-                firstnumber = 0;
-              }
-            }
-            bufferp = findnextnumber(bufferp);
-          }
-          // Read the marker of the face if it exists.
-          facetmarkerlist[i] = 0;
-          if (*bufferp != '\0') {
-            facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
-          }
-        }
-        // Have read in a list of triangles/quads.
-        numberoffacets += nfaces;
-        nfaces = 0;
-      }
-    }
-    // if (nverts > 0 && nfaces > 0) break; // Ignore other data.
-  }
-
-  // Close file
-  fclose(fp);
-
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_plc()    Load a piecewise linear complex from file.                  //
-//                                                                           //
-// This is main entrance for loading plcs from different file formats into   //
-// tetgenio.  'filename' is the input file name without extention. 'object'  //
-// indicates which file format is used to describ the plc.                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_plc(char* filename, int object)
-{
-  enum tetgenbehavior::objecttype type;
-
-  type = (enum tetgenbehavior::objecttype) object;
-  switch (type) {
-  case tetgenbehavior::NODES:
-    return load_node(filename);
-  case tetgenbehavior::POLY:
-    return load_poly(filename);
-  case tetgenbehavior::OFF:
-    return load_off(filename);
-  case tetgenbehavior::PLY:
-    return load_ply(filename);
-  case tetgenbehavior::STL:
-    return load_stl(filename);
-  case tetgenbehavior::MEDIT:
-    return load_medit(filename);
-  default:
-    return load_poly(filename);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_tetmesh()    Load a tetrahedral mesh from files.                     //
-//                                                                           //
-// 'filename' is the inputfile without suffix.  The nodes of the tetrahedral //
-// mesh is in "filename.node",  the elements is in "filename.ele", if the    //
-// "filename.face" and "filename.vol" exists, they will also be read.        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_tetmesh(char* filename)
-{
-  FILE *infile;
-  char innodefilename[FILENAMESIZE];
-  char inelefilename[FILENAMESIZE];
-  char infacefilename[FILENAMESIZE];
-  char inedgefilename[FILENAMESIZE];
-  char involfilename[FILENAMESIZE];
-  char inputline[INPUTLINESIZE];
-  char *stringptr, *infilename;
-  REAL attrib, volume;
-  int volelements;
-  int markers, corner;
-  int index, attribindex;
-  int i, j;
-
-  // Assembling the actual file names we want to open.
-  strcpy(innodefilename, filename);
-  strcpy(inelefilename, filename);
-  strcpy(infacefilename, filename);
-  strcpy(inedgefilename, filename);
-  strcpy(involfilename, filename);
-  strcat(innodefilename, ".node");
-  strcat(inelefilename, ".ele");
-  strcat(infacefilename, ".face");
-  strcat(inedgefilename, ".edge");
-  strcat(involfilename, ".vol");
-
-  // Read the points from a .node file.
-  infilename = innodefilename;
-  printf("Opening %s.\n", infilename);
-  infile = fopen(infilename, "r");
-  if (infile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot access file %s.\n", infilename);
-    return false;
-  }
-  // Read the first line of the file.
-  stringptr = readnumberline(inputline, infile, infilename); 
-  // Is this list of points generated from rbox?
-  stringptr = strstr(inputline, "rbox");
-  if (stringptr == NULL) {
-    // Read number of points, number of dimensions, number of point
-    //   attributes, and number of boundary markers.
-    stringptr = inputline;
-    numberofpoints = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr == '\0') {
-      mesh_dim = 3;
-    } else {
-      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr == '\0') {
-      numberofpointattributes = 0;
-    } else {
-      numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr == '\0') {
-      markers = 0;  // Default value.
-    } else {
-      markers = (int) strtol (stringptr, &stringptr, 0);
-    }
-  } else {
-    // It is a rbox (qhull) input file.
-    stringptr = inputline;
-    // Get the dimension.
-    mesh_dim = (int) strtol (stringptr, &stringptr, 0);
-    // Get the number of points.
-    stringptr = readnumberline(inputline, infile, infilename);
-    numberofpoints = (int) strtol (stringptr, &stringptr, 0);
-    // There is no index column.
-    useindex = 0;
-  }
-
-  // Load the list of nodes.
-  if (!load_node_call(infile, markers, infilename)) {
-    fclose(infile);
-    return false;
-  }
-  fclose(infile);
-
-  // Read the elements from an .ele file.
-  if (mesh_dim == 3) {
-    infilename = inelefilename;
-    infile = fopen(infilename, "r");
-    if (infile != (FILE *) NULL) {
-      printf("Opening %s.\n", infilename);
-      // Read number of elements, number of corners (4 or 10), number of
-      //   element attributes.
-      stringptr = readnumberline(inputline, infile, infilename);
-      numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0);
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        numberofcorners = 4;  // Default read 4 nodes per element.
-      } else {
-        numberofcorners = (int) strtol(stringptr, &stringptr, 0);
-      }
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        numberoftetrahedronattributes = 0; // Default no attribute.
-      } else {
-        numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0);
-      }
-      if (numberofcorners != 4 && numberofcorners != 10) {
-        printf("Error:  Wrong number of corners %d (should be 4 or 10).\n", 
-               numberofcorners);
-        fclose(infile);
-        return false;
-      }
-      // Allocate memory for tetrahedra.
-      if (numberoftetrahedra > 0) {
-        tetrahedronlist = new int[numberoftetrahedra * numberofcorners]; 
-        if (tetrahedronlist == (int *) NULL) {
-          printf("Error:  Out of memory.\n");
-          terminatetetgen(1);
-        }
-        // Allocate memory for output tetrahedron attributes if necessary.
-        if (numberoftetrahedronattributes > 0) {
-          tetrahedronattributelist = new REAL[numberoftetrahedra *
-                                          numberoftetrahedronattributes];
-          if (tetrahedronattributelist == (REAL *) NULL) {
-            printf("Error:  Out of memory.\n");
-            terminatetetgen(1);
-          }
-        }
-      }
-      // Read the list of tetrahedra.
-      index = 0;
-      attribindex = 0;
-      for (i = 0; i < numberoftetrahedra; i++) {
-        // Read tetrahedron index and the tetrahedron's corners.
-        stringptr = readnumberline(inputline, infile, infilename);
-        for (j = 0; j < numberofcorners; j++) {
-          stringptr = findnextnumber(stringptr);
-          if (*stringptr == '\0') {
-            printf("Error:  Tetrahedron %d is missing vertex %d in %s.\n",
-                   i + firstnumber, j + 1, infilename);
-            terminatetetgen(1);
-          }
-          corner = (int) strtol(stringptr, &stringptr, 0);
-          if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
-            printf("Error:  Tetrahedron %d has an invalid vertex index.\n",
-                   i + firstnumber);
-            terminatetetgen(1);
-          }
-          tetrahedronlist[index++] = corner;
-        }
-        // Read the tetrahedron's attributes.
-        for (j = 0; j < numberoftetrahedronattributes; j++) {
-          stringptr = findnextnumber(stringptr);
-          if (*stringptr == '\0') {
-            attrib = 0.0;
-          } else {
-            attrib = (REAL) strtod(stringptr, &stringptr);
-          }
-          tetrahedronattributelist[attribindex++] = attrib;
-        }
-      }
-      fclose(infile);
-    }
-  } // if (meshdim == 3)
-  
-  // Read the hullfaces or subfaces from a .face file if it exists.
-  if (mesh_dim == 3) {
-    infilename = infacefilename;
-  } else {
-    infilename = inelefilename;
-  }
-  infile = fopen(infilename, "r");
-  if (infile != (FILE *) NULL) {
-    printf("Opening %s.\n", infilename);
-    // Read number of faces, boundary markers.
-    stringptr = readnumberline(inputline, infile, infilename);
-    numberoftrifaces = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findnextnumber(stringptr);
-    if (mesh_dim == 2) {
-      // Skip a number.
-      stringptr = findnextnumber(stringptr);
-    }
-    if (*stringptr == '\0') {
-      markers = 0;  // Default there is no marker per face.
-    } else {
-      markers = (int) strtol (stringptr, &stringptr, 0);
-    }
-    if (numberoftrifaces > 0) {
-      trifacelist = new int[numberoftrifaces * 3];
-      if (trifacelist == (int *) NULL) {
-        printf("Error:  Out of memory.\n");
-        terminatetetgen(1);
-      }
-      if (markers) {
-        trifacemarkerlist = new int[numberoftrifaces * 3];
-        if (trifacemarkerlist == (int *) NULL) {
-          printf("Error:  Out of memory.\n");
-          terminatetetgen(1);
-        }
-      }
-    }
-    // Read the list of faces.
-    index = 0;
-    for (i = 0; i < numberoftrifaces; i++) {
-      // Read face index and the face's three corners.
-      stringptr = readnumberline(inputline, infile, infilename);
-      for (j = 0; j < 3; j++) {
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Face %d is missing vertex %d in %s.\n",
-                 i + firstnumber, j + 1, infilename);
-          terminatetetgen(1);
-        }
-        corner = (int) strtol(stringptr, &stringptr, 0);
-        if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
-          printf("Error:  Face %d has an invalid vertex index.\n",
-                 i + firstnumber);
-          terminatetetgen(1);
-        }
-        trifacelist[index++] = corner;
-      }
-      // Read the boundary marker if it exists.
-      if (markers) {
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          attrib = 0.0;
-        } else {
-          attrib = (REAL) strtod(stringptr, &stringptr);
-        }
-        trifacemarkerlist[i] = (int) attrib;
-      }
-    }
-    fclose(infile);
-  }
-
-  // Read the boundary edges from a .edge file if it exists.
-  infilename = inedgefilename;
-  infile = fopen(infilename, "r");
-  if (infile != (FILE *) NULL) {
-    printf("Opening %s.\n", infilename);
-    // Read number of boundary edges.
-    stringptr = readnumberline(inputline, infile, infilename);
-    numberofedges = (int) strtol (stringptr, &stringptr, 0);
-    if (numberofedges > 0) {
-      edgelist = new int[numberofedges * 2];
-      if (edgelist == (int *) NULL) {
-        printf("Error:  Out of memory.\n");
-        terminatetetgen(1);
-      }
-    }
-    // Read the list of faces.
-    index = 0;
-    for (i = 0; i < numberofedges; i++) {
-      // Read face index and the edge's two endpoints.
-      stringptr = readnumberline(inputline, infile, infilename);
-      for (j = 0; j < 2; j++) {
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Edge %d is missing vertex %d in %s.\n",
-                 i + firstnumber, j + 1, infilename);
-          terminatetetgen(1);
-        }
-        corner = (int) strtol(stringptr, &stringptr, 0);
-        if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
-          printf("Error:  Edge %d has an invalid vertex index.\n",
-                 i + firstnumber);
-          terminatetetgen(1);
-        }
-        edgelist[index++] = corner;
-      }
-    }
-    fclose(infile);
-  }
-
-  // Read the volume constraints from a .vol file if it exists.
-  infilename = involfilename;
-  infile = fopen(infilename, "r");
-  if (infile != (FILE *) NULL) {
-    printf("Opening %s.\n", infilename);
-    // Read number of tetrahedra.
-    stringptr = readnumberline(inputline, infile, infilename);
-    volelements = (int) strtol (stringptr, &stringptr, 0);
-    if (volelements != numberoftetrahedra) {
-      printf("Warning:  %s and %s disagree on number of tetrahedra.\n",
-             inelefilename, involfilename);
-      volelements = 0;
-    }
-    if (volelements > 0) {
-      tetrahedronvolumelist = new REAL[volelements];
-      if (tetrahedronvolumelist == (REAL *) NULL) {
-        printf("Error:  Out of memory.\n");
-        terminatetetgen(1);
-      }
-    }
-    // Read the list of volume constraints.
-    for (i = 0; i < volelements; i++) {
-      stringptr = readnumberline(inputline, infile, infilename);
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        volume = -1.0; // No constraint on this tetrahedron.
-      } else {
-        volume = (REAL) strtod(stringptr, &stringptr);
-      }
-      tetrahedronvolumelist[i] = volume;
-    }
-    fclose(infile);
-  }
-
-  // Try to load a .mtr file if it exists.
-  load_mtr(filename);
-  // Try to read a .pbc file if it exists.
-  load_pbc(filename);
-
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// load_voronoi()    Load a Voronoi diagram from files.                      //
-//                                                                           //
-// 'filename' is the inputfile without suffix.  The Voronoi diagram is read  //
-// from files: filename.v.node, filename.v.edge, and filename.v.face.        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenio::load_voronoi(char* filename)
-{
-  FILE *infile;
-  char innodefilename[FILENAMESIZE];
-  char inedgefilename[FILENAMESIZE];
-  char inputline[INPUTLINESIZE];
-  char *stringptr, *infilename;
-  voroedge *vedge;
-  REAL x, y, z;
-  int firstnode, corner;
-  int index;
-  int i, j;
-
-  // Assembling the actual file names we want to open.
-  strcpy(innodefilename, filename);
-  strcpy(inedgefilename, filename);
-  strcat(innodefilename, ".v.node");
-  strcat(inedgefilename, ".v.edge");
-
-  // Read the points from a .v.node file.
-  infilename = innodefilename;
-  printf("Opening %s.\n", infilename);
-  infile = fopen(infilename, "r");
-  if (infile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot access file %s.\n", infilename);
-    return false;
-  }
-  // Read the first line of the file.
-  stringptr = readnumberline(inputline, infile, infilename); 
-  // Is this list of points generated from rbox?
-  stringptr = strstr(inputline, "rbox");
-  if (stringptr == NULL) {
-    // Read number of points, number of dimensions, number of point
-    //   attributes, and number of boundary markers.
-    stringptr = inputline;
-    numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr == '\0') {
-      mesh_dim = 3;  // Default.
-    } else {
-      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
-    }
-    useindex = 1;  // There is an index column.
-  } else {
-    // It is a rbox (qhull) input file.
-    stringptr = inputline;
-    // Get the dimension.
-    mesh_dim = (int) strtol (stringptr, &stringptr, 0);
-    // Get the number of points.
-    stringptr = readnumberline(inputline, infile, infilename);
-    numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
-    useindex = 0;  // No index column.
-  }
-  // Initialize 'vpointlist'.
-  vpointlist = new REAL[numberofvpoints * 3];
-  if (vpointlist == (REAL *) NULL) {
-    printf("Error:  Out of memory.\n");
-    terminatetetgen(1);
-  }
-  // Read the point section.
-  index = 0;
-  for (i = 0; i < numberofvpoints; i++) {
-    stringptr = readnumberline(inputline, infile, infilename);
-    if (useindex) {
-      if (i == 0) {
-        firstnode = (int) strtol (stringptr, &stringptr, 0);
-        if ((firstnode == 0) || (firstnode == 1)) {
-          firstnumber = firstnode;
-        }
-      }
-      stringptr = findnextnumber(stringptr);
-    } // if (useindex)
-    if (*stringptr == '\0') {
-      printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
-      terminatetetgen(1);
-    }
-    x = (REAL) strtod(stringptr, &stringptr);
-    stringptr = findnextnumber(stringptr);
-    if (*stringptr == '\0') {
-      printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
-      terminatetetgen(1);
-    }
-    y = (REAL) strtod(stringptr, &stringptr);
-    if (mesh_dim == 3) {
-      stringptr = findnextnumber(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
-        terminatetetgen(1);
-      }
-      z = (REAL) strtod(stringptr, &stringptr);
-    } else {
-      z = 0.0; // mesh_dim == 2;
-    }
-    vpointlist[index++] = x;
-    vpointlist[index++] = y;
-    vpointlist[index++] = z;
-  }
-  fclose(infile);
-
-  // Read the Voronoi edges from a .v.edge file if it exists.
-  infilename = inedgefilename;
-  infile = fopen(infilename, "r");
-  if (infile != (FILE *) NULL) {
-    printf("Opening %s.\n", infilename);
-    // Read number of boundary edges.
-    stringptr = readnumberline(inputline, infile, infilename);
-    numberofvedges = (int) strtol (stringptr, &stringptr, 0);
-    if (numberofvedges > 0) {
-      vedgelist = new voroedge[numberofvedges];
-    }
-    // Read the list of faces.
-    index = 0;
-    for (i = 0; i < numberofvedges; i++) {
-      // Read edge index and the edge's two endpoints.
-      stringptr = readnumberline(inputline, infile, infilename);
-      vedge = &(vedgelist[i]);
-      for (j = 0; j < 2; j++) {
-        stringptr = findnextnumber(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Edge %d is missing vertex %d in %s.\n",
-                 i + firstnumber, j + 1, infilename);
-          terminatetetgen(1);
-        }
-        corner = (int) strtol(stringptr, &stringptr, 0);
-        j == 0 ? vedge->v1 = corner : vedge->v2 = corner;
-      }
-      if (vedge->v2 < 0) {
-        for (j = 0; j < mesh_dim; j++) {
-          stringptr = findnextnumber(stringptr);
-          if (*stringptr == '\0') {
-            printf("Error:  Edge %d is missing normal in %s.\n",
-                   i + firstnumber, infilename);
-            terminatetetgen(1);
-          }
-          vedge->vnormal[j] = (REAL) strtod(stringptr, &stringptr);
-        }
-        if (mesh_dim == 2) {
-          vedge->vnormal[2] = 0.0;
-        }
-      } else {
-        vedge->vnormal[0] = 0.0;
-        vedge->vnormal[1] = 0.0;
-        vedge->vnormal[2] = 0.0;
-      }
-    }
-    fclose(infile);
-  }
-
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// save_nodes()    Save points to a .node file.                              //
-//                                                                           //
-// 'filename' is a string containing the file name without suffix.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenio::save_nodes(char* filename)
-{
-  FILE *fout;
-  char outnodefilename[FILENAMESIZE];
-  char outmtrfilename[FILENAMESIZE];
-  int i, j;
-
-  sprintf(outnodefilename, "%s.node", filename);
-  printf("Saving nodes to %s\n", outnodefilename);
-  fout = fopen(outnodefilename, "w");
-  fprintf(fout, "%d  %d  %d  %d\n", numberofpoints, mesh_dim,
-          numberofpointattributes, pointmarkerlist != NULL ? 1 : 0);
-  for (i = 0; i < numberofpoints; i++) {
-    if (mesh_dim == 2) {
-      fprintf(fout, "%d  %.16g  %.16g", i + firstnumber, pointlist[i * 2],
-              pointlist[i * 2 + 1]);
-    } else {
-      fprintf(fout, "%d  %.16g  %.16g  %.16g", i + firstnumber,
-              pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
-    }
-    for (j = 0; j < numberofpointattributes; j++) {
-      fprintf(fout, "  %.16g", 
-              pointattributelist[i * numberofpointattributes + j]);
-    }
-    if (pointmarkerlist != NULL) {
-      fprintf(fout, "  %d", pointmarkerlist[i]);
-    }
-    fprintf(fout, "\n");
-  }
-  fclose(fout);
-
-  // If the point metrics exist, output them to a .mtr file.
-  if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
-    sprintf(outmtrfilename, "%s.mtr", filename);
-    printf("Saving metrics to %s\n", outmtrfilename);
-    fout = fopen(outmtrfilename, "w");
-    fprintf(fout, "%d  %d\n", numberofpoints, numberofpointmtrs);
-    for (i = 0; i < numberofpoints; i++) {
-      for (j = 0; j < numberofpointmtrs; j++) {
-        fprintf(fout, "%.16g ", pointmtrlist[i * numberofpointmtrs + j]);
-      }
-      fprintf(fout, "\n");
-    }
-    fclose(fout);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// save_elements()    Save elements to a .ele file.                          //
-//                                                                           //
-// 'filename' is a string containing the file name without suffix.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenio::save_elements(char* filename)
-{
-  FILE *fout;
-  char outelefilename[FILENAMESIZE];
-  int i, j;
-
-  sprintf(outelefilename, "%s.ele", filename);
-  printf("Saving elements to %s\n", outelefilename);
-  fout = fopen(outelefilename, "w");
-  fprintf(fout, "%d  %d  %d\n", numberoftetrahedra, numberofcorners,
-          numberoftetrahedronattributes);
-  for (i = 0; i < numberoftetrahedra; i++) {
-    fprintf(fout, "%d", i + firstnumber);
-    for (j = 0; j < numberofcorners; j++) {
-      fprintf(fout, "  %5d", tetrahedronlist[i * numberofcorners + j]);
-    }
-    for (j = 0; j < numberoftetrahedronattributes; j++) {
-      fprintf(fout, "  %g",
-        tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
-    }
-    fprintf(fout, "\n");
-  }
-
-  fclose(fout);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// save_faces()    Save faces to a .face file.                               //
-//                                                                           //
-// 'filename' is a string containing the file name without suffix.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenio::save_faces(char* filename)
-{
-  FILE *fout;
-  char outfacefilename[FILENAMESIZE];
-  int i;
-
-  sprintf(outfacefilename, "%s.face", filename);
-  printf("Saving faces to %s\n", outfacefilename);
-  fout = fopen(outfacefilename, "w");
-  fprintf(fout, "%d  %d\n", numberoftrifaces, 
-          trifacemarkerlist != NULL ? 1 : 0);
-  for (i = 0; i < numberoftrifaces; i++) {
-    fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber, trifacelist[i * 3],
-            trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
-    if (trifacemarkerlist != NULL) {
-      fprintf(fout, "  %d", trifacemarkerlist[i]);
-    }
-    fprintf(fout, "\n");
-  }
-
-  fclose(fout);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// save_edges()    Save egdes to a .edge file.                               //
-//                                                                           //
-// 'filename' is a string containing the file name without suffix.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenio::save_edges(char* filename)
-{
-  FILE *fout;
-  char outedgefilename[FILENAMESIZE];
-  int i;
-
-  sprintf(outedgefilename, "%s.edge", filename);
-  printf("Saving edges to %s\n", outedgefilename);
-  fout = fopen(outedgefilename, "w");
-  fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
-  for (i = 0; i < numberofedges; i++) {
-    fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
-            edgelist[i * 2 + 1]);
-    if (edgemarkerlist != NULL) {
-      fprintf(fout, "  %d", edgemarkerlist[i]);
-    }
-    fprintf(fout, "\n");
-  }
-
-  fclose(fout);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// save_neighbors()    Save egdes to a .neigh file.                          //
-//                                                                           //
-// 'filename' is a string containing the file name without suffix.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenio::save_neighbors(char* filename)
-{
-  FILE *fout;
-  char outneighborfilename[FILENAMESIZE];
-  int i;
-
-  sprintf(outneighborfilename, "%s.neigh", filename);
-  printf("Saving neighbors to %s\n", outneighborfilename);
-  fout = fopen(outneighborfilename, "w");
-  fprintf(fout, "%d  %d\n", numberoftetrahedra, mesh_dim + 1);
-  for (i = 0; i < numberoftetrahedra; i++) {
-    if (mesh_dim == 2) {
-      fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber,  neighborlist[i * 3],
-              neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]);
-    } else {
-      fprintf(fout, "%d  %5d  %5d  %5d  %5d", i + firstnumber,
-              neighborlist[i * 4], neighborlist[i * 4 + 1],
-              neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]);
-    }
-    fprintf(fout, "\n");
-  }
-
-  fclose(fout);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// save_poly()    Save segments or facets to a .poly file.                   //
-//                                                                           //
-// 'filename' is a string containing the file name without suffix.  It only  //
-// save the facets, holes and regions.  The nodes are saved in a .node file  //
-// by routine save_nodes().                                                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenio::save_poly(char* filename)
-{
-  FILE *fout;
-  facet *f;
-  polygon *p;
-  char outpolyfilename[FILENAMESIZE];
-  int i, j, k;
-
-  sprintf(outpolyfilename, "%s.poly", filename);
-  printf("Saving poly to %s\n", outpolyfilename);
-  fout = fopen(outpolyfilename, "w");
-
-  // The zero indicates that the vertices are in a separate .node file.
-  //   Followed by number of dimensions, number of vertex attributes,
-  //   and number of boundary markers (zero or one).
-  fprintf(fout, "%d  %d  %d  %d\n", 0, mesh_dim, numberofpointattributes,
-          pointmarkerlist != NULL ? 1 : 0);
-
-  // Save segments or facets.
-  if (mesh_dim == 2) {
-    // Number of segments, number of boundary markers (zero or one).
-    fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
-    for (i = 0; i < numberofedges; i++) {
-      fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
-              edgelist[i * 2 + 1]);
-      if (edgemarkerlist != NULL) {
-        fprintf(fout, "  %d", edgemarkerlist[i]);
-      }
-      fprintf(fout, "\n");
-    }
-  } else {
-    // Number of facets, number of boundary markers (zero or one).
-    fprintf(fout, "%d  %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0);
-    for (i = 0; i < numberoffacets; i++) {
-      f = &(facetlist[i]);
-      fprintf(fout, "%d  %d  %d  # %d\n", f->numberofpolygons,f->numberofholes,
-            facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber);
-      // Output polygons of this facet.
-      for (j = 0; j < f->numberofpolygons; j++) {
-        p = &(f->polygonlist[j]);
-        fprintf(fout, "%d  ", p->numberofvertices);
-        for (k = 0; k < p->numberofvertices; k++) {
-          if (((k + 1) % 10) == 0) {
-            fprintf(fout, "\n  ");
-          }
-          fprintf(fout, "  %d", p->vertexlist[k]);
-        }
-        fprintf(fout, "\n");
-      }
-      // Output holes of this facet.
-      for (j = 0; j < f->numberofholes; j++) {
-        fprintf(fout, "%d  %.12g  %.12g  %.12g\n", j + firstnumber,
-           f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]);
-      }
-    }
-  }
-
-  // Save holes.
-  fprintf(fout, "%d\n", numberofholes);
-  for (i = 0; i < numberofholes; i++) {
-    // Output x, y coordinates.
-    fprintf(fout, "%d  %.12g  %.12g", i + firstnumber, holelist[i * mesh_dim],
-            holelist[i * mesh_dim + 1]);
-    if (mesh_dim == 3) {
-      // Output z coordinate.
-      fprintf(fout, "  %.12g", holelist[i * mesh_dim + 2]);
-    }
-    fprintf(fout, "\n");
-  }
-
-  // Save regions.
-  fprintf(fout, "%d\n", numberofregions);
-  for (i = 0; i < numberofregions; i++) {
-    if (mesh_dim == 2) {
-      // Output the index, x, y coordinates, attribute (region number)
-      //   and maximum area constraint (maybe -1).
-      fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
-              regionlist[i * 4], regionlist[i * 4 + 1],
-              regionlist[i * 4 + 2], regionlist[i * 4 + 3]);
-    } else {
-      // Output the index, x, y, z coordinates, attribute (region number)
-      //   and maximum volume constraint (maybe -1).
-      fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
-              regionlist[i * 5], regionlist[i * 5 + 1],
-              regionlist[i * 5 + 2], regionlist[i * 5 + 3],
-              regionlist[i * 5 + 4]);
-    }
-  }
-
-  fclose(fout);  
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// readline()   Read a nonempty line from a file.                            //
-//                                                                           //
-// A line is considered "nonempty" if it contains something more than white  //
-// spaces.  If a line is considered empty, it will be dropped and the next   //
-// line will be read, this process ends until reaching the end-of-file or a  //
-// non-empty line.  Return NULL if it is the end-of-file, otherwise, return  //
-// a pointer to the first non-whitespace character of the line.              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-char* tetgenio::readline(char *string, FILE *infile, int *linenumber)
-{
-  char *result;
-
-  // Search for a non-empty line.
-  do {
-    result = fgets(string, INPUTLINESIZE - 1, infile);
-    if (linenumber) (*linenumber)++;
-    if (result == (char *) NULL) {
-      return (char *) NULL;
-    }
-    // Skip white spaces.
-    while ((*result == ' ') || (*result == '\t')) result++;
-    // If it's end of line, read another line and try again.
-  } while (*result == '\0');
-  return result;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// findnextfield()   Find the next field of a string.                        //
-//                                                                           //
-// Jumps past the current field by searching for whitespace or a comma, then //
-// jumps past the whitespace or the comma to find the next field.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-char* tetgenio::findnextfield(char *string)
-{
-  char *result;
-
-  result = string;
-  // Skip the current field.  Stop upon reaching whitespace or a comma.
-  while ((*result != '\0') && (*result != ' ') &&  (*result != '\t') && 
-         (*result != ',') && (*result != ';')) {
-    result++;
-  }
-  // Now skip the whitespace or the comma, stop at anything else that looks
-  //   like a character, or the end of a line. 
-  while ((*result == ' ') || (*result == '\t') || (*result == ',') ||
-         (*result == ';')) {
-    result++;
-  }
-  return result;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// readnumberline()   Read a nonempty number line from a file.               //
-//                                                                           //
-// A line is considered "nonempty" if it contains something that looks like  //
-// a number.  Comments (prefaced by `#') are ignored.                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-char* tetgenio::readnumberline(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) {
-      if (infilename != (char *) NULL) {
-        printf("  Error:  Unexpected end of file in %s.\n", infilename);
-        terminatetetgen(1);
-      }
-      return result;
-    }
-    // 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;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// findnextnumber()   Find the next field of a number string.                //
-//                                                                           //
-// Jumps past the current field by searching for whitespace or a comma, then //
-// jumps past the whitespace or the comma to find the next field that looks  //
-// like a number.                                                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-char* tetgenio::findnextnumber(char *string)
-{
-  char *result;
-
-  result = string;
-  // Skip the current field.  Stop upon reaching whitespace or a comma.
-  while ((*result != '\0') && (*result != '#') && (*result != ' ') && 
-         (*result != '\t') && (*result != ',')) {
-    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;
-}
-
-//
-// End of class 'tetgenio' implementation
-//
-
-static REAL PI = 3.14159265358979323846264338327950288419716939937510582;
-
-//
-// Begin of class 'tetgenbehavior' implementation
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetgenbehavior()    Initialize veriables of 'tetgenbehavior'.             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenbehavior::tetgenbehavior()
-{
-  // Initialize command line switches.
-  plc = 0;
-  quality = 0;
-  refine = 0;
-  coarse = 0;
-  metric = 0;
-  minratio = 2.0;
-  goodratio = 0.0;
-  minangle = 20.0;
-  goodangle = 0.0;
-  maxdihedral = 165.0;
-  mindihedral = 5.0;
-  varvolume = 0;
-  fixedvolume = 0;
-  maxvolume = -1.0;
-  regionattrib = 0;
-  insertaddpoints = 0;
-  diagnose = 0;
-  offcenter = 0;
-  conformdel = 0;
-  alpha1 = sqrt(2.0);
-  alpha2 = 1.0;
-  alpha3 = 0.6;
-  zeroindex = 0;
-  facesout = 0;
-  edgesout = 0;
-  neighout = 0;
-  voroout = 0;
-  meditview = 0;
-  gidview = 0;
-  geomview = 0;
-  optlevel = 3;
-  optpasses = 3;
-  order = 1;
-  nojettison = 0;
-  nobound = 0;
-  nonodewritten = 0;
-  noelewritten = 0;
-  nofacewritten = 0;
-  noiterationnum = 0;
-  nobisect = 0;
-  noflip = 0;
-  steiner = -1;
-  fliprepair = 1;
-  nomerge = 0;
-  docheck = 0;
-  quiet = 0;
-  verbose = 0;
-  useshelles = 0;
-  epsilon = 1.0e-8;
-  epsilon2 = 1.0e-5;
-  object = NONE;
-  // Initialize strings
-  commandline[0] = '\0';
-  infilename[0] = '\0';
-  outfilename[0] = '\0';
-  addinfilename[0] = '\0';
-  bgmeshfilename[0] = '\0';
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// versioninfo()    Print the version information of TetGen.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenbehavior::versioninfo()
-{
-  printf("Version 1.4.2 (April 16, 2007).\n");
-  printf("\n");
-  printf("Copyright (C) 2002 - 2007\n");
-  printf("Hang Si\n");
-  printf("Mohrenstr. 39, 10117 Berlin, Germany\n");
-  printf("si@wias-berlin.de\n");
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// syntax()    Print list of command line switches and exit the program.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenbehavior::syntax()
-{
-  printf("  tetgen [-prq_Ra_AiMYS_T_dzo_fenvgGOJBNEFICQVh] input_file\n");
-  printf("    -p  Tetrahedralizes a piecewise linear complex (PLC).\n");
-  printf("    -r  Reconstructs a previously generated mesh.\n");
-  printf("    -q  Quality mesh generation (adding new mesh points to ");
-  printf("improve mesh quality).\n");
-  printf("    -R  Mesh coarsening (deleting redundant mesh points).\n");
-  printf("    -a  Applies a maximum tetrahedron volume constraint.\n");
-  printf("    -A  Assigns attributes to identify tetrahedra in different ");
-  printf("regions.\n");
-  printf("    -i  Inserts a list of additional points into mesh.\n");
-  printf("    -M  Does not merge coplanar facets.\n");
-  printf("    -Y  Suppresses boundary facets/segments splitting.\n");
-  printf("    -S  Specifies maximum number of added points.\n");
-  printf("    -T  Sets a tolerance for coplanar test (default 1e-8).\n");
-  printf("    -d  Detects self-intersections of facets of the PLC.\n");
-  printf("    -z  Numbers all output items starting from zero.\n");
-  printf("    -o2 Generates second-order subparametric elements.\n");
-  printf("    -f  Outputs all faces to .face file.");
-  printf("file.\n");
-  printf("    -e  Outputs all edges to .edge file.\n");
-  printf("    -n  Outputs tetrahedra neighbors to .neigh file.\n");
-  printf("    -v  Outputs Voronoi diagram to files.\n");
-  printf("    -g  Outputs mesh to .mesh file for viewing by Medit.\n");
-  printf("    -G  Outputs mesh to .msh file for viewing by Gid.\n");
-  printf("    -O  Outputs mesh to .off file for viewing by Geomview.\n");
-  printf("    -J  No jettison of unused vertices from output .node file.\n");
-  printf("    -B  Suppresses output of boundary information.\n");
-  printf("    -N  Suppresses output of .node file.\n");
-  printf("    -E  Suppresses output of .ele file.\n");
-  printf("    -F  Suppresses output of .face file.\n");
-  printf("    -I  Suppresses mesh iteration numbers.\n");
-  printf("    -C  Checks the consistency of the final mesh.\n");
-  printf("    -Q  Quiet:  No terminal output except errors.\n");
-  printf("    -V  Verbose:  Detailed information, more terminal output.\n");
-  printf("    -h  Help:  A brief instruction for using TetGen.\n");
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// usage()    Print a brief instruction for using TetGen.                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenbehavior::usage()
-{
-  printf("TetGen\n");
-  printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
-  printf("Triangulator\n");
-  versioninfo();
-  printf("\n");
-  printf("What Can TetGen Do?\n");
-  printf("\n");
-  printf("  TetGen generates exact Delaunay tetrahedralizations, exact\n");
-  printf("  constrained Delaunay tetrahedralizations, and quality ");
-  printf("tetrahedral\n  meshes. The latter are nicely graded and whose ");
-  printf("tetrahedra have\n  radius-edge ratio bounded, thus are suitable ");
-  printf("for finite element and\n  finite volume analysis.\n"); 
-  printf("\n");
-  printf("Command Line Syntax:\n");
-  printf("\n");
-  printf("  Below is the command line syntax of TetGen with a list of ");
-  printf("short\n");
-  printf("  descriptions. Underscores indicate that numbers may optionally\n");
-  printf("  follow certain switches.  Do not leave any space between a ");
-  printf("switch\n");
-  printf("  and its numeric parameter.  \'input_file\' contains input data\n");
-  printf("  depending on the switches you supplied which may be a ");
-  printf("  piecewise\n");
-  printf("  linear complex or a list of nodes.  File formats and detailed\n");
-  printf("  description of command line switches are found in user's ");
-  printf("manual.\n");
-  printf("\n");
-  syntax();
-  printf("\n");
-  printf("Examples of How to Use TetGen:\n");
-  printf("\n");
-  printf("  \'tetgen object\' reads vertices from object.node, and writes ");
-  printf("their\n  Delaunay tetrahedralization to object.1.node and ");
-  printf("object.1.ele.\n");
-  printf("\n");
-  printf("  \'tetgen -p object\' reads a PLC from object.poly or object.");
-  printf("smesh (and\n  possibly object.node) and writes its constrained ");
-  printf("Delaunay\n  tetrahedralization to object.1.node, object.1.ele and ");
-  printf("object.1.face.\n");
-  printf("\n");
-  printf("  \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
-  printf("  object.smesh (and possibly object.node), generates a mesh ");
-  printf("whose\n  tetrahedra have radius-edge ratio smaller than 1.414 and ");
-  printf("have volume\n  of 0.1 or less, and writes the mesh to ");
-  printf("object.1.node, object.1.ele\n  and object.1.face.\n");
-  printf("\n");
-  printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// parse_commandline()    Read the command line, identify switches, and set  //
-//                        up options and file names.                         //
-//                                                                           //
-// 'argc' and 'argv' are the same parameters passed to the function main()   //
-// of a C/C++ program. They together represent the command line user invoked //
-// from an environment in which TetGen is running.                           //
-//                                                                           //
-// When TetGen is invoked from an environment. 'argc' is nonzero, switches   //
-// and input filename should be supplied as zero-terminated strings in       //
-// argv[0] through argv[argc - 1] and argv[0] shall be the name used to      //
-// invoke TetGen, i.e. "tetgen".  Switches are previously started with a     //
-// dash '-' to identify them from the input filename.                        //
-//                                                                           //
-// When TetGen is called from within another program. 'argc' is set to zero. //
-// switches are given in one zero-terminated string (no previous dash is     //
-// required.), and 'argv' is a pointer points to this string.  No input      //
-// filename is required (usually the input data has been directly created by //
-// user in the 'tetgenio' structure).  A default filename 'tetgen-tmpfile'   //
-// will be created for debugging output purpose.                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenbehavior::parse_commandline(int argc, char **argv)
-{
-  int startindex;
-  int increment;
-  int meshnumber;
-  int scount;
-  int i, j, k;
-  char workstring[1024];
-
-  // First determine the input style of the switches.
-  if (argc == 0) {
-    startindex = 0;                    // Switches are given without a dash.
-    argc = 1;                    // For running the following for-loop once.
-    commandline[0] = '\0';
-  } else {
-    startindex = 1;
-    strcpy(commandline, argv[0]);
-    strcat(commandline, " ");
-  }
-  
-  // Rcount used to count the number of '-R' be used.
-  scount = 0;
-
-  for (i = startindex; i < argc; i++) {
-    // Remember the command line switches.
-    strcat(commandline, argv[i]);
-    strcat(commandline, " ");
-    if (startindex == 1) {
-      // Is this string a filename?
-      if (argv[i][0] != '-') {
-        strncpy(infilename, argv[i], 1024 - 1);
-        infilename[1024 - 1] = '\0';
-        // Go to the next string directly.
-        continue;                     
-      }
-    }
-    // Parse the individual switch from the string.
-    for (j = startindex; argv[i][j] != '\0'; j++) {
-      if (argv[i][j] == 'p') {
-        plc = 1;
-      } else if (argv[i][j] == 'r') {
-        refine = 1;
-      } else if (argv[i][j] == 'R') {
-        coarse = 1;
-      } else if (argv[i][j] == 'q') {
-        quality++;
-        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';
-          if (quality == 1) {
-            minratio = (REAL) strtod(workstring, (char **) NULL);
-          } else if (quality == 2) {
-            mindihedral = (REAL) strtod(workstring, (char **) NULL);
-          } else if (quality == 3) {
-            maxdihedral = (REAL) strtod(workstring, (char **) NULL);
-          } else if (quality == 4) {
-            alpha2 = (REAL) strtod(workstring, (char **) NULL);
-          } else if (quality == 5) {
-            alpha1 = (REAL) strtod(workstring, (char **) NULL);
-          }
-        }
-      } else if (argv[i][j] == 'm') {
-        metric++;
-        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';
-          if (metric == 1) {
-            alpha1 = (REAL) strtod(workstring, (char **) NULL);
-          } else if (metric == 2) {
-            alpha2 = (REAL) strtod(workstring, (char **) NULL);
-          }
-        }
-      } else if (argv[i][j] == 'a') {
-        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] == '.') || (argv[i][j + 1] == 'e') ||
-                 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
-            j++;
-            workstring[k] = argv[i][j];
-            k++;
-          }
-          workstring[k] = '\0';
-          maxvolume = (REAL) strtod(workstring, (char **) NULL);
-        } else {
-          varvolume = 1;
-        }
-      } else if (argv[i][j] == 'A') {
-        regionattrib++;
-      } else if (argv[i][j] == 'i') {
-        insertaddpoints = 1;
-      } else if (argv[i][j] == 'd') {
-        diagnose = 1;
-      } else if (argv[i][j] == 'z') {
-        zeroindex = 1;
-      } else if (argv[i][j] == 'f') {
-        facesout = 1;
-      } else if (argv[i][j] == 'e') {
-        edgesout++;
-      } else if (argv[i][j] == 'n') {
-        neighout++;
-      } else if (argv[i][j] == 'v') {
-        voroout = 1;
-      } else if (argv[i][j] == 'g') {
-        meditview = 1;
-      } else if (argv[i][j] == 'G') {
-        gidview = 1;
-      } else if (argv[i][j] == 'O') {
-        geomview = 1;
-      } else if (argv[i][j] == 'M') {
-        nomerge = 1;
-      } else if (argv[i][j] == 'Y') {
-        nobisect++;
-      } else if (argv[i][j] == 'J') {
-        nojettison = 1;
-      } else if (argv[i][j] == 'B') {
-        nobound = 1;
-      } else if (argv[i][j] == 'N') {
-        nonodewritten = 1;
-      } else if (argv[i][j] == 'E') {
-        noelewritten = 1;
-      } else if (argv[i][j] == 'F') {
-        nofacewritten = 1;
-      } else if (argv[i][j] == 'I') {
-        noiterationnum = 1;
-      } else if (argv[i][j] == 'o') {
-        if (argv[i][j + 1] == '2') {
-          j++;
-          order = 2;
-        }
-      } else if (argv[i][j] == 'S') {
-        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';
-          steiner = (int) strtol(workstring, (char **) NULL, 0);
-        } 
-      } else if (argv[i][j] == 's') {
-        scount++;
-        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';
-          if (scount == 1) {
-            optlevel = (int) strtol(workstring, (char **) NULL, 0);
-          } else if (scount == 2) {
-            optpasses = (int) strtol(workstring, (char **) NULL, 0);
-          }
-        }
-      } else if (argv[i][j] == 'D') {
-        conformdel++;
-      } else 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';
-          epsilon = (REAL) strtod(workstring, (char **) NULL);
-        } 
-      } else if (argv[i][j] == 'C') {
-        docheck++;
-      } else if (argv[i][j] == 'X') {
-        fliprepair = 0;
-      } else if (argv[i][j] == 'Q') {
-        quiet = 1;
-      } else if (argv[i][j] == 'V') {
-        verbose++;
-      // } else if (argv[i][j] == 'v') {
-        // versioninfo();
-        // terminatetetgen(0);
-      } else if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
-                 (argv[i][j] == '?')) {
-        usage();
-        terminatetetgen(0);
-      } else {
-        printf("Warning:  Unknown switch -%c.\n", argv[i][j]);
-      }
-    }
-  }
-
-  if (startindex == 0) {
-    // Set a temporary filename for debugging output.
-    strcpy(infilename, "tetgen-tmpfile");
-  } else {
-    if (infilename[0] == '\0') {
-      // No input file name. Print the syntax and exit.
-      syntax();
-      terminatetetgen(0);
-    }
-    // Recognize the object from file extension if it is available.
-    if (!strcmp(&infilename[strlen(infilename) - 5], ".node")) {
-      infilename[strlen(infilename) - 5] = '\0';
-      object = NODES;
-    } else if (!strcmp(&infilename[strlen(infilename) - 5], ".poly")) {
-      infilename[strlen(infilename) - 5] = '\0';
-      object = POLY;
-      plc = 1;
-    } else if (!strcmp(&infilename[strlen(infilename) - 6], ".smesh")) {
-      infilename[strlen(infilename) - 6] = '\0';
-      object = POLY;
-      plc = 1;
-    } else if (!strcmp(&infilename[strlen(infilename) - 4], ".off")) {
-      infilename[strlen(infilename) - 4] = '\0';
-      object = OFF;
-      plc = 1;
-    } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ply")) {
-      infilename[strlen(infilename) - 4] = '\0';
-      object = PLY;
-      plc = 1;
-    } else if (!strcmp(&infilename[strlen(infilename) - 4], ".stl")) {
-      infilename[strlen(infilename) - 4] = '\0';
-      object = STL;
-      plc = 1;
-    } else if (!strcmp(&infilename[strlen(infilename) - 5], ".mesh")) {
-      infilename[strlen(infilename) - 5] = '\0';
-      object = MEDIT;
-      plc = 1;
-    } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ele")) {
-      infilename[strlen(infilename) - 4] = '\0';
-      object = MESH;
-      refine = 1;
-    }
-  }
-  plc = plc || diagnose;
-  useshelles = plc || refine || coarse || quality;
-  goodratio = minratio;
-  goodratio *= goodratio;
-
-  // Detect improper combinations of switches.
-  if (plc && refine) {
-    printf("Error:  Switch -r cannot use together with -p.\n");
-    return false;
-  }
-  if (refine && (plc || noiterationnum)) {
-    printf("Error:  Switches %s cannot use together with -r.\n",
-           "-p, -d, and -I");
-    return false;
-  }
-  if (diagnose && (quality || insertaddpoints || (order == 2) || neighout
-      || docheck)) {
-    printf("Error:  Switches %s cannot use together with -d.\n",
-           "-q, -i, -o2, -n, and -C");
-    return false;
-  }
-
-  // Be careful not to allocate space for element area constraints that 
-  //   will never be assigned any value (other than the default -1.0).
-  if (!refine && !plc) {
-    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 || !plc) {
-    regionattrib = 0;
-  }
-  // If '-a' or '-aa' is in use, enable '-q' option too.
-  if (fixedvolume || varvolume) {
-    if (quality == 0) {
-      quality = 1;
-    }
-  }
-  // Calculate the goodangle for testing bad subfaces.
-  goodangle = cos(minangle * PI / 180.0);
-  goodangle *= goodangle;
-
-  increment = 0;
-  strcpy(workstring, infilename);
-  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(outfilename, infilename);
-  } else if (increment == 0) {
-    strcpy(outfilename, infilename);
-    strcat(outfilename, ".1");
-  } else {
-    workstring[increment] = '%';
-    workstring[increment + 1] = 'd';
-    workstring[increment + 2] = '\0';
-    sprintf(outfilename, workstring, meshnumber + 1);
-  }
-  // Additional input file name has the end ".a".
-  strcpy(addinfilename, infilename);
-  strcat(addinfilename, ".a");
-  // Background filename has the form "*.b.ele", "*.b.node", ...
-  strcpy(bgmeshfilename, infilename);
-  strcat(bgmeshfilename, ".b");
-
-  return true;
-}
-
-//
-// End of class 'tetgenbehavior' implementation
-//
-
-//
-// Begin of class 'tetgenmesh' implementation
-//
-
-//
-// Begin of class 'list', 'memorypool' and 'link' implementation
-//
-
-// Following are predefined compare functions for primitive data types. 
-//   These functions take two pointers of the corresponding date type,
-//   perform the comparation. Return -1, 0 or 1 indicating the default
-//   linear order of two operators.
-
-// Compare two 'integers'.
-int tetgenmesh::compare_2_ints(const void* x, const void* y) {
-  if (* (int *) x < * (int *) y) {
-    return -1;
-  } else if (* (int *) x > * (int *) y) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-// Compare two 'longs'.  Note: in 64-bit machine the 'long' type is 64-bit
-//   (8-byte) where the 'int' only 32-bit (4-byte).
-int tetgenmesh::compare_2_longs(const void* x, const void* y) {
-  if (* (long *) x < * (long *) y) {
-    return -1;
-  } else if (* (long *) x > * (long *) y) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-// Compare two 'unsigned longs'.
-int tetgenmesh::compare_2_unsignedlongs(const void* x, const void* y) {
-  if (* (unsigned long *) x < * (unsigned long *) y) {
-    return -1;
-  } else if (* (unsigned long *) x > * (unsigned long *) y) {
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// set_compfunc()    Determine the size of primitive data types and set the  //
-//                   corresponding predefined linear order functions.        //
-//                                                                           //
-// 'str' is a zero-end string indicating a primitive data type, like 'int',  //
-// 'long' or 'unsigned long'.  Every string ending with a '*' is though as a //
-// type of pointer and the type 'unsign long' is used for it.                //
-//                                                                           //
-// When the type of 'str' is determined, the size of this type (in byte) is  //
-// returned in 'itbytes', and the pointer of corresponding predefined linear //
-// order functions is returned in 'pcomp'.                                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::set_compfunc(char* str, int* itbytes, compfunc* pcomp)
-{
-  // First figure out whether it is a pointer or not.
-  if (str[strlen(str) - 1] == '*') {
-    *itbytes = sizeof(unsigned long);
-    *pcomp = &compare_2_unsignedlongs;
-    return;
-  }
-  // Then determine other types.
-  if (strcmp(str, "int") == 0) {
-    *itbytes = sizeof(int);
-    *pcomp = &compare_2_ints;
-  } else if (strcmp(str, "long") == 0) {
-    *itbytes = sizeof(long);
-    *pcomp = &compare_2_longs;
-  } else if (strcmp(str, "unsigned long") == 0) {
-    *itbytes = sizeof(unsigned long);
-    *pcomp = &compare_2_unsignedlongs;
-  } else {
-    // It is an unknown type.
-    printf("Error in set_compfunc():  unknown type %s.\n", str);
-    terminatetetgen(1);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// listinit()    Initialize a list for storing a data type.                  //
-//                                                                           //
-// Determine the size of each item, set the maximum size allocated at onece, //
-// set the expand size in case the list is full, and set the linear order    //
-// function if it is provided (default is NULL).                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::list::
-listinit(int itbytes, compfunc pcomp, int mitems,int exsize)
-{
-#ifdef SELF_CHECK
-  assert(itbytes > 0 && mitems > 0 && exsize > 0);
-#endif
-  itembytes = itbytes;
-  comp = pcomp;
-  maxitems = mitems;
-  expandsize = exsize;
-  base = (char *) malloc(maxitems * itembytes); 
-  if (base == (char *) NULL) {
-    printf("Error:  Out of memory.\n");
-    terminatetetgen(1);
-  }
-  items = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// append()    Add a new item at the end of the list.                        //
-//                                                                           //
-// A new space at the end of this list will be allocated for storing the new //
-// item. If the memory is not sufficient, reallocation will be performed. If //
-// 'appitem' is not NULL, the contents of this pointer will be copied to the //
-// new allocated space.  Returns the pointer to the new allocated space.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* tetgenmesh::list::append(void *appitem)
-{
-  // Do we have enough space?
-  if (items == maxitems) {
-    char* newbase = (char *) realloc(base, (maxitems + expandsize) * 
-                                     itembytes);
-    if (newbase == (char *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-    base = newbase;
-    maxitems += expandsize;
-  }
-  if (appitem != (void *) NULL) {
-    memcpy(base + items * itembytes, appitem, itembytes);
-  }
-  items++;
-  return (void *) (base + (items - 1) * itembytes);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insert()    Insert an item before 'pos' (range from 0 to items - 1).      //
-//                                                                           //
-// A new space will be inserted at the position 'pos', that is, items lie    //
-// after pos (including the item at pos) will be moved one space downwords.  //
-// If 'insitem' is not NULL, its contents will be copied into the new        //
-// inserted space. Return a pointer to the new inserted space.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* tetgenmesh::list::insert(int pos, void* insitem)
-{
-  if (pos >= items) {
-    return append(insitem);
-  }
-  // Do we have enough space.
-  if (items == maxitems) {
-    char* newbase = (char *) realloc(base, (maxitems + expandsize) *
-                                     itembytes);
-    if (newbase == (char *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-    base = newbase;
-    maxitems += expandsize;
-  }
-  // Do block move.
-  memmove(base + (pos + 1) * itembytes,   // dest
-          base + pos * itembytes,         // src
-          (items - pos) * itembytes);     // size in bytes
-  // Insert the item.
-  if (insitem != (void *) NULL) {
-    memcpy(base + pos * itembytes, insitem, itembytes);
-  }
-  items++;
-  return (void *) (base + pos * itembytes);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// del()    Delete an item at 'pos' (range from 0 to items - 1).             //
-//                                                                           //
-// The space at 'pos' will be overlapped by other item. If 'order' is 1, the //
-// remaining items of the list have the same order as usual, i.e., items lie //
-// after pos will be moved one space upwords. If 'order' is 0, the last item //
-// of the list will be moved up to pos.                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::list::del(int pos, int order)
-{
-  // If 'pos' is the last item of the list, nothing need to do.
-  if (pos >= 0 && pos < items - 1) {
-    if (order == 1) {
-      // Do block move. 
-      memmove(base + pos * itembytes,       // dest
-              base + (pos + 1) * itembytes, // src
-              (items - pos - 1) * itembytes);
-    } else {
-      // Use the last item to overlap the del item.
-      memcpy(base + pos * itembytes, // item at pos
-             base + (items - 1) * itembytes, // item at last
-             itembytes);
-    }
-  }
-  if (items > 0) {
-    items--;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// hasitem()    Search in this list to find if 'checkitem' exists.           //
-//                                                                           //
-// This routine assumes that a linear order function has been set.  It loops //
-// through the entire list, compares each item to 'checkitem'. If it exists, //
-// return its position (between 0 to items - 1), otherwise, return -1.       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int tetgenmesh::list::hasitem(void* checkitem)
-{
-  int i;
-
-  for (i = 0; i < items; i++) {
-    if (comp != (compfunc) NULL) {
-      if ((* comp)((void *)(base + i * itembytes), checkitem) == 0) {
-        return i;
-      }
-    }
-  }
-  return -1;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// sort()    Sort the items with respect to a linear order function.         //
-//                                                                           //
-// Uses QuickSort routines (qsort) of the standard C/C++ library (stdlib.h). //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::list::sort()
-{
-  qsort((void *) base, (size_t) items, (size_t) itembytes, comp);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// memorypool()   The constructors of memorypool.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::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 = 0l;
-  unallocateditems = 0;
-  pathitemsleft = 0;
-}
-
-tetgenmesh::memorypool::
-memorypool(int bytecount, int itemcount, enum wordtype wtype, int alignment)
-{
-  poolinit(bytecount, itemcount, wtype, alignment);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// ~memorypool()   Free to the operating system all memory taken by a pool.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::memorypool::~memorypool()
-{
-  while (firstblock != (void **) NULL) {
-    nowblock = (void **) *(firstblock);
-    free(firstblock);
-    firstblock = nowblock;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// poolinit()    Initialize a pool of memory for allocation of items.        //
-//                                                                           //
-// A `pool' is created whose records have size at least `bytecount'.  Items  //
-// will be allocated 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 `alignment'-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.                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::memorypool::
-poolinit(int bytecount, int itemcount, enum wordtype wtype, int alignment)
-{
-  int wordsize;
-
-  // Initialize values in the pool.
-  itemwordtype = wtype;
-  wordsize = (itemwordtype == POINTER) ? sizeof(void *) : sizeof(REAL);
-  // 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 ((int) sizeof(void *) > alignbytes) {
-    alignbytes = (int) 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 **) malloc(itemsperblock * itembytes + sizeof(void *)
-                                + alignbytes); 
-  if (firstblock == (void **) NULL) {
-    printf("Error:  Out of memory.\n");
-    terminatetetgen(1);
-  }
-  // Set the next block pointer to NULL.
-  *(firstblock) = (void *) NULL;
-  restart();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// restart()   Deallocate all items in this 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 tetgenmesh::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;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// alloc()   Allocate space for an item.                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* tetgenmesh::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 **) malloc(itemsperblock * itembytes + sizeof(void *) 
-                                    + alignbytes);
-        if (newblock == (void **) NULL) {
-          printf("Error:  Out of memory.\n");
-          terminatetetgen(1);
-        }
-        *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 *) ((REAL *) 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 tetgenmesh::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 tetgenmesh::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.  It can usually be done more space-efficiently by //
-// a routine that knows something about the structure of the item.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* tetgenmesh::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 *) ((REAL *) pathitem + itemwords);
-  }
-  pathitemsleft--;
-  return newitem;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// linkinit()    Initialize a link for storing items.                        //
-//                                                                           //
-// The input parameters are the size of each item, a pointer of a linear     //
-// order function and the number of items allocating in one memory bulk.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::link::linkinit(int bytecount, compfunc pcomp, int itemcount)
-{
-#ifdef SELF_CHECK
-  assert(bytecount > 0 && itemcount > 0);
-#endif
-  // Remember the real size of each item.
-  linkitembytes = bytecount;
-  // Set the linear order function for this link.
-  comp = pcomp;
-
-  // Call the constructor of 'memorypool' to initialize its variables.
-  //   like: itembytes, itemwords, items, ... Each node has size
-  //   bytecount + 2 * sizeof(void **), and total 'itemcount + 2' (because
-  //   link has additional two nodes 'head' and 'tail').
-  poolinit(bytecount + 2 * sizeof(void **), itemcount + 2, POINTER, 0);
-  
-  // Initial state of this link.
-  head = (void **) alloc();
-  tail = (void **) alloc();
-  *head = (void *) tail;
-  *(head + 1) = NULL;
-  *tail = NULL;
-  *(tail + 1) = (void *) head;
-  nextlinkitem = *head;
-  curpos = 1;
-  linkitems = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// clear()   Deallocate all nodes in this link.                              //
-//                                                                           //
-// The link 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 tetgenmesh::link::clear()
-{
-  // Reset the pool.
-  restart();
-
-  // Initial state of this link.
-  head = (void **) alloc();
-  tail = (void **) alloc();
-  *head = (void *) tail;
-  *(head + 1) = NULL;
-  *tail = NULL;
-  *(tail + 1) = (void *) head;
-  nextlinkitem = *head;
-  curpos = 1;
-  linkitems = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// move()    Causes 'nextlinkitem' to traverse the specified number of nodes,//
-//           updates 'curpos' to be the node to which 'nextlinkitem' points. //
-//                                                                           //
-// 'numberofnodes' is a number indicating how many nodes need be traversed   //
-// (not counter the current node) need be traversed. It may be positive(move //
-// forward) or negative (move backward).  Return TRUE if it is successful.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::link::move(int numberofnodes)
-{
-  void **nownode;
-  int i;
-
-  nownode = (void **) nextlinkitem;
-  if (numberofnodes > 0) {
-    // Move forward.
-    i = 0;
-    while ((i < numberofnodes) && *nownode) {
-      nownode = (void **) *nownode;
-      i++;
-    }
-    if (*nownode == NULL) return false;
-    nextlinkitem = (void *) nownode;
-    curpos += numberofnodes;
-  } else if (numberofnodes < 0) {
-    // Move backward.
-    i = 0;
-    numberofnodes = -numberofnodes;
-    while ((i < numberofnodes) && *(nownode + 1)) {
-      nownode = (void **) *(nownode + 1);
-      i++;
-    }
-    if (*(nownode + 1) == NULL) return false;
-    nextlinkitem = (void *) nownode;
-    curpos -= numberofnodes;
-  }
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// locate()    Locates the node at the specified position.                   //
-//                                                                           //
-// The number 'pos' (between 1 and 'linkitems') indicates the location. This //
-// routine first decides the shortest path traversing from 'curpos' to 'pos',//
-// i.e., from head, tail or 'curpos'.   Routine 'move()' is called to really //
-// traverse the link. If success, 'nextlinkitem' points to the node, 'curpos'//
-// and 'pos' are equal. Otherwise, return FALSE.                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::link::locate(int pos)
-{
-  int headdist, taildist, curdist;
-  int abscurdist, mindist;
-
-  if (pos < 1 || pos > linkitems) return false;
-
-  headdist = pos - 1;
-  taildist = linkitems - pos;
-  curdist = pos - curpos;
-  abscurdist = curdist >= 0 ? curdist : -curdist;
-
-  if (headdist > taildist) {
-    if (taildist > abscurdist) {
-      mindist = curdist;
-    } else {
-      // taildist <= abs(curdist)
-      mindist = -taildist;
-      goend();
-    }
-  } else {
-    // headdist <= taildist
-    if (headdist > abscurdist) {
-      mindist = curdist;
-    } else {
-      // headdist <= abs(curdist)
-      mindist = headdist;
-      rewind();
-    }
-  }
-
-  return move(mindist);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// add()    Add a node at the end of this link.                              //
-//                                                                           //
-// A new node is appended to the end of the link.  If 'newitem' is not NULL, //
-// its conents will be copied to the data slot of the new node. Returns the  //
-// pointer to the newest added node.                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* tetgenmesh::link::add(void* newitem)
-{
-  void **newnode = tail;
-  if (newitem != (void *) NULL) {
-    memcpy((void *)(newnode + 2), newitem, linkitembytes);
-  }
-  tail = (void **) alloc();
-  *tail = NULL;
-  *newnode = (void*) tail;
-  *(tail + 1) = (void*) newnode;
-  linkitems++;
-  return (void *)(newnode + 2);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insert()    Inserts a node before the specified position.                 //
-//                                                                           //
-// 'pos' (between 1 and 'linkitems') indicates the inserting position.  This //
-// routine inserts a new node before the node of 'pos'.  If 'newitem' is not //
-// NULL,  its conents will be copied into the data slot of the new node.  If //
-// 'pos' is larger than 'linkitems', it is equal as 'add()'.  A pointer to   //
-// the newest inserted item is returned.                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* tetgenmesh::link::insert(int pos, void* insitem)
-{
-  if (!locate(pos)) {
-    return add(insitem);
-  }
-
-  void **nownode = (void **) nextlinkitem;
-
-  // Insert a node before 'nownode'.
-  void **newnode = (void **) alloc();
-  if (insitem != (void *) NULL) {
-    memcpy((void *)(newnode + 2), insitem, linkitembytes);
-  }
-
-  *(void **)(*(nownode + 1)) = (void *) newnode;
-  *newnode = (void *) nownode;
-  *(newnode + 1) = *(nownode + 1);
-  *(nownode + 1) = (void *) newnode;
-
-  linkitems++;
-
-  nextlinkitem = (void *) newnode;
-  return (void *)(newnode + 2);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// del()    Delete a node.                                                   //
-//                                                                           //
-// Returns a pointer of the deleted data. If you try to delete a non-existed //
-// node (e.g. link is empty or a wrong index is given) return NULL.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* tetgenmesh::link::deletenode(void** deadnode)
-{
-  void **nextnode = (void **) *deadnode;
-  void **prevnode = (void **) *(deadnode + 1);
-  *prevnode = (void *) nextnode;
-  *(nextnode + 1) = (void *) prevnode;
-
-  dealloc((void *) deadnode);
-  linkitems--;
-
-  nextlinkitem = (void *) nextnode;
-  return (void *)(deadnode + 2);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// del()    Delete a node at the specified position.                         //
-//                                                                           //
-// 'pos' between 1 and 'linkitems'.  Returns a pointer of the deleted data.  //
-// If you try to delete a non-existed node (e.g. link is empty or a wrong    //
-// index is given) return NULL.                                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* tetgenmesh::link::del(int pos)
-{
-  if (!locate(pos) || (linkitems == 0)) {
-    return (void *) NULL;
-  }
-  return deletenode((void **) nextlinkitem);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getitem()    The link traversal routine.                                  //
-//                                                                           //
-// Returns the node to which 'nextlinkitem' points. Returns a 'NULL' if the  //
-// end of the link is reaching.  Both 'nextlinkitem' and 'curpos' will be    //
-// updated after this operation.                                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* tetgenmesh::link::getitem()
-{
-  if (nextlinkitem == (void *) tail) return NULL;
-  void **nownode = (void **) nextlinkitem;
-  nextlinkitem = *nownode;
-  curpos += 1;
-  return (void *)(nownode + 2);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getnitem()    Returns the node at a specified position.                   //
-//                                                                           //
-// 'pos' between 1 and 'linkitems'. After this operation, 'nextlinkitem' and //
-// 'curpos' will be updated to indicate this node.                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void* tetgenmesh::link::getnitem(int pos)
-{
-  if (!locate(pos)) return NULL;
-  return (void *)((void **) nextlinkitem + 2);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// hasitem()    Search in this link to find if 'checkitem' exists.           //
-//                                                                           //
-// If 'checkitem' exists, return its position (between 1 to 'linkitems'),    //
-// otherwise, return -1. This routine requires the linear order function has //
-// been set.                                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int tetgenmesh::link::hasitem(void* checkitem)
-{
-  void *pathitem;
-  int count;
-
-  rewind();
-  pathitem = getitem();
-  count = 0;
-  while (pathitem) {
-    count ++;
-    if (comp) {
-      if ((* comp)(pathitem, checkitem) == 0) {
-        return count;
-      }
-    } 
-    pathitem = getitem();
-  }
-  return -1;
-}
-
-//
-// End of class 'list', 'memorypool' and 'link' implementation
-//
-
-//
-// Begin of mesh manipulation primitives
-//
-
-//
-// Begin of tables initialization.
-//
-
-// For enumerating three edges of a triangle.
-
-int tetgenmesh::plus1mod3[3] = {1, 2, 0};
-int tetgenmesh::minus1mod3[3] = {2, 0, 1};
-
-// Table 've' takes an edge version as input, returns the next edge version
-//   in the same edge ring.
-
-int tetgenmesh::ve[6] = { 2, 5, 4, 1, 0, 3 };
-
-// Tables 'vo', 'vd' and 'va' take an edge version, return the positions of
-//   the origin, destination and apex in the triangle.
-
-int tetgenmesh::vo[6] = { 0, 1, 1, 2, 2, 0 };
-int tetgenmesh::vd[6] = { 1, 0, 2, 1, 0, 2 };
-int tetgenmesh::va[6] = { 2, 2, 0, 0, 1, 1 };
-
-// The following tables are for tetrahedron primitives (operate on trifaces).
-
-// For 'org()', 'dest()' and 'apex()'.  Use 'loc' as the first index and
-//   'ver' as the second index.
-
-int tetgenmesh::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 tetgenmesh::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 tetgenmesh::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 the index.
-
-int tetgenmesh::loc2oppo[4] = { 3, 2, 0, 1 };
-
-// For fnext() primitive.  Use 'loc' as the first index and 'ver' as the
-//   second index. Returns a new 'loc' and new 'ver' in an array. (It is
-//   only valid for edge version equals one of {0, 2, 4}.)
-
-int tetgenmesh::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} }
-};
-
-// The edge number (from 0 to 5) of a tet is defined as follows:
-//   0 - (v0, v1), 1 - (v1, v2), 2 - (v2, v0)
-//   3 - (v3, v0), 4 - (v3, v1), 5 - (v3, v2).
-
-int tetgenmesh::locver2edge[4][6] = {
-  {0, 0, 1, 1, 2, 2},
-  {3, 3, 4, 4, 0, 0},
-  {4, 4, 5, 5, 1, 1},
-  {5, 5, 3, 3, 2, 2}
-};
-
-int tetgenmesh::edge2locver[6][2] = {
-  {0, 0}, // 0  v0 -> v1
-  {0, 2}, // 1  v1 -> v2
-  {0, 4}, // 2  v2 -> v1
-  {1, 0}, // 3  v0 -> v3
-  {1, 2}, // 4  v1 -> v3
-  {2, 2}  // 5  v2 -> v3
-};
-
-//
-// End of tables initialization.
-//
-
-// 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)
-
-//
-// Begin of primitives for tetrahedra
-// 
-
-// Each tetrahedron contains four pointers to its neighboring tetrahedra,
-//   with face indices.  To save memory, both information are kept in a
-//   single pointer. To make this possible, all tetrahedra are aligned to
-//   eight-byte boundaries, so that the last three bits of each pointer are
-//   zeros. A face index (in the range 0 to 3) is compressed into the last
-//   two bits of each pointer by the function 'encode()'.  The function
-//   'decode()' decodes a pointer, extracting a face index and a pointer to
-//   the beginning of a tetrahedron.
-
-inline void tetgenmesh::decode(tetrahedron ptr, triface& t) {
-  t.loc = (int) ((unsigned long) (ptr) & (unsigned long) 3l);
-  t.tet = (tetrahedron *) ((unsigned long) (ptr) & ~(unsigned long) 7l);
-}
-
-inline tetgenmesh::tetrahedron tetgenmesh::encode(triface& t) {
-  return (tetrahedron) ((unsigned long) t.tet | (unsigned long) t.loc);
-}
-
-// sym() finds the abutting tetrahedron on the same face.
-
-inline void tetgenmesh::sym(triface& t1, triface& t2) {
-  tetrahedron ptr = t1.tet[t1.loc];
-  decode(ptr, t2);
-}
-
-inline void tetgenmesh::symself(triface& t) {
-  tetrahedron ptr = t.tet[t.loc];
-  decode(ptr, t);
-}
-
-// Bond two tetrahedra together at their faces.
-
-inline void tetgenmesh::bond(triface& t1, triface& t2) {
-  t1.tet[t1.loc] = encode(t2);
-  t2.tet[t2.loc] = encode(t1);
-}
-
-// Dissolve a bond (from one side).  Note that the other tetrahedron will
-//   still think it is connected to this tetrahedron.  Usually, however,
-//   the other tetrahedron is being deleted entirely, or bonded to another
-//   tetrahedron, so it doesn't matter.
-
-inline void tetgenmesh::dissolve(triface& t) {
-  t.tet[t.loc] = (tetrahedron) dummytet;
-}
-
-// These primitives determine or set the origin, destination, apex or
-//   opposition of a tetrahedron with respect to 'loc' and 'ver'.
-
-inline tetgenmesh::point tetgenmesh::org(triface& t) {
-  return (point) t.tet[locver2org[t.loc][t.ver] + 4];
-}
-
-inline tetgenmesh::point tetgenmesh::dest(triface& t) {
-  return (point) t.tet[locver2dest[t.loc][t.ver] + 4];
-}
-
-inline tetgenmesh::point tetgenmesh::apex(triface& t) {
-  return (point) t.tet[locver2apex[t.loc][t.ver] + 4];
-}
-
-inline tetgenmesh::point tetgenmesh::oppo(triface& t) {
-  return (point) t.tet[loc2oppo[t.loc] + 4];
-}
-
-inline void tetgenmesh::setorg(triface& t, point pointptr) {
-  t.tet[locver2org[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
-}
-
-inline void tetgenmesh::setdest(triface& t, point pointptr) {
-  t.tet[locver2dest[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
-}
-
-inline void tetgenmesh::setapex(triface& t, point pointptr) {
-  t.tet[locver2apex[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
-}
-
-inline void tetgenmesh::setoppo(triface& t, point pointptr) {
-  t.tet[loc2oppo[t.loc] + 4] = (tetrahedron) pointptr;
-}
-
-// These primitives were drived from Mucke's triangle-edge 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 directions
-//   of the same undirected edge of a face. e0.sym() = e1 and vice versa.
-
-inline void tetgenmesh::esym(triface& t1, triface& t2) {
-  t2.tet = t1.tet;
-  t2.loc = t1.loc;
-  t2.ver = t1.ver + (EdgeRing(t1.ver) ? -1 : 1);
-}
-
-inline void tetgenmesh::esymself(triface& t) {
-  t.ver += (EdgeRing(t.ver) ? -1 : 1);
-}
-
-// If e0 and e1 are both in the same edge ring of a face, e1 = e0.enext().
-
-inline void tetgenmesh::enext(triface& t1, triface& t2) {
-  t2.tet = t1.tet;
-  t2.loc = t1.loc;
-  t2.ver = ve[t1.ver];
-}
-
-inline void tetgenmesh::enextself(triface& t) {
-  t.ver = ve[t.ver];
-}
-
-// enext2() is equal to e2 = e0.enext().enext()
-
-inline void tetgenmesh::enext2(triface& t1, triface& t2) {
-  t2.tet = t1.tet;
-  t2.loc = t1.loc;
-  t2.ver = ve[ve[t1.ver]];
-}
-
-inline void tetgenmesh::enext2self(triface& t) {
-  t.ver = ve[ve[t.ver]];
-}
-
-// If f0 and f1 are both in the same face ring of a face, f1 = f0.fnext().
-//   If f1 exists, return true. Otherwise, return false, i.e., f0 is a
-//   boundary or hull face.
-
-inline bool tetgenmesh::fnext(triface& t1, triface& t2) 
-{
-  // Get the next face.
-  t2.loc = locver2nextf[t1.loc][t1.ver][0];
-  // Is the next face in the same tet?
-  if (t2.loc != -1) {
-    // It's in the same tet. Get the edge version.
-    t2.ver = locver2nextf[t1.loc][t1.ver][1];
-    t2.tet = t1.tet;
-  } else {
-    // The next face is in the neigbhour of 't1'.
-    sym(t1, t2);
-    if (t2.tet != dummytet) {
-      // Find the corresponding edge in t2.
-      point torg;
-      int tloc, tver, i;
-      t2.ver = 0;
-      torg = org(t1);
-      for (i = 0; (i < 3) && (org(t2) != torg); i++) {
-        enextself(t2);
-      }
-      // Go to the next face in t2.
-      tloc = t2.loc;
-      tver = t2.ver;
-      t2.loc = locver2nextf[tloc][tver][0];
-      t2.ver = locver2nextf[tloc][tver][1];
-    }
-  }
-  return t2.tet != dummytet;
-}
-
-inline bool tetgenmesh::fnextself(triface& t1) 
-{
-  triface t2;
-
-  // Get the next face.
-  t2.loc = locver2nextf[t1.loc][t1.ver][0];
-  // Is the next face in the same tet?
-  if (t2.loc != -1) {
-    // It's in the same tet. Get the edge version.
-    t2.ver = locver2nextf[t1.loc][t1.ver][1];
-    t1.loc = t2.loc;
-    t1.ver = t2.ver;
-  } else {
-    // The next face is in the neigbhour of 't1'.
-    sym(t1, t2);
-    if (t2.tet != dummytet) {
-      // Find the corresponding edge in t2.
-      point torg;
-      int i;
-      t2.ver = 0;
-      torg = org(t1);
-      for (i = 0; (i < 3) && (org(t2) != torg); i++) {
-        enextself(t2);
-      }
-      t1.loc = locver2nextf[t2.loc][t2.ver][0];
-      t1.ver = locver2nextf[t2.loc][t2.ver][1];
-      t1.tet = t2.tet;
-    }
-  }
-  return t2.tet != dummytet;
-}
-
-// enextfnext() and enext2fnext() are combination primitives of enext(),
-//   enext2() and fnext().
-
-inline void tetgenmesh::enextfnext(triface& t1, triface& t2) {
-  enext(t1, t2);
-  fnextself(t2);
-}
-
-inline void tetgenmesh::enextfnextself(triface& t) {
-  enextself(t);
-  fnextself(t);
-}
-
-inline void tetgenmesh::enext2fnext(triface& t1, triface& t2) {
-  enext2(t1, t2);
-  fnextself(t2);
-}
-
-inline void tetgenmesh::enext2fnextself(triface& t) {
-  enext2self(t);
-  fnextself(t);
-}
-
-// Primitives to infect or cure a tetrahedron with the virus.   The last
-//   third bit of the pointer is marked for infection.  These rely on the
-//   assumption that all tetrahedron are aligned to eight-byte boundaries.
-
-inline void tetgenmesh::infect(triface& t) {
-  t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] | (unsigned long) 4l);
-}
-
-inline void tetgenmesh::uninfect(triface& t) {
-  t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] & ~ (unsigned long) 4l);
-}
-
-// Test a tetrahedron for viral infection.
-
-inline bool tetgenmesh::infected(triface& t) {
-  return (((unsigned long) t.tet[0] & (unsigned long) 4l) != 0);
-}
-
-// Check or set a tetrahedron's attributes.
-
-inline REAL tetgenmesh::elemattribute(tetrahedron* ptr, int attnum) {
-  return ((REAL *) (ptr))[elemattribindex + attnum];
-}
-
-inline void tetgenmesh::
-setelemattribute(tetrahedron* ptr, int attnum, REAL value){
-  ((REAL *) (ptr))[elemattribindex + attnum] = value;
-}
-
-// Check or set a tetrahedron's maximum volume bound.
-
-inline REAL tetgenmesh::volumebound(tetrahedron* ptr) {
-  return ((REAL *) (ptr))[volumeboundindex];
-}
-
-inline void tetgenmesh::setvolumebound(tetrahedron* ptr, REAL value) {
-  ((REAL *) (ptr))[volumeboundindex] = value;
-}
-
-//
-// End of primitives for tetrahedra
-//
-
-//
-// Begin of primitives for subfaces/subsegments
-//
-
-// Each subface contains three pointers to its neighboring subfaces, with
-//   edge versions.  To save memory, both information are kept in a single
-//   pointer. To make this possible, all subfaces are aligned to eight-byte
-//   boundaries, so that the last three bits of each pointer are zeros. An
-//   edge version (in the range 0 to 5) is compressed into the last three
-//   bits of each pointer by 'sencode()'.  'sdecode()' decodes a pointer,
-//   extracting an edge version and a pointer to the beginning of a subface.
-
-inline void tetgenmesh::sdecode(shellface sptr, face& s) {
-  s.shver = (int) ((unsigned long) (sptr) & (unsigned long) 7l);
-  s.sh = (shellface *) ((unsigned long) (sptr) & ~ (unsigned long) 7l);
-}
-
-inline tetgenmesh::shellface tetgenmesh::sencode(face& s) {
-  return (shellface) ((unsigned long) s.sh | (unsigned long) s.shver);
-}
-
-// spivot() finds the other subface (from this subface) that shares the
-//   same edge.
-
-inline void tetgenmesh::spivot(face& s1, face& s2) {
-  shellface sptr = s1.sh[Orient(s1.shver)];
-  sdecode(sptr, s2);
-}
-
-inline void tetgenmesh::spivotself(face& s) {
-  shellface sptr = s.sh[Orient(s.shver)];
-  sdecode(sptr, s);
-}
-
-// sbond() bonds two subfaces together, i.e., after bonding, both faces
-//   are pointing to each other.
-
-inline void tetgenmesh::sbond(face& s1, face& s2) {
-  s1.sh[Orient(s1.shver)] = sencode(s2);
-  s2.sh[Orient(s2.shver)] = sencode(s1);
-}
-
-// sbond1() only bonds s2 to s1, i.e., after bonding, s1 is pointing to s2,
-//   but s2 is not pointing to s1.
-
-inline void tetgenmesh::sbond1(face& s1, face& s2) {
-  s1.sh[Orient(s1.shver)] = sencode(s2);
-}
-
-// Dissolve a subface bond (from one side).  Note that the other subface
-//   will still think it's connected to this subface.
-
-inline void tetgenmesh::sdissolve(face& s) {
-  s.sh[Orient(s.shver)] = (shellface) dummysh;
-}
-
-// These primitives determine or set the origin, destination, or apex
-//   of a subface with respect to the edge version.
-
-inline tetgenmesh::point tetgenmesh::sorg(face& s) {
-  return (point) s.sh[3 + vo[s.shver]];
-}
-
-inline tetgenmesh::point tetgenmesh::sdest(face& s) {
-  return (point) s.sh[3 + vd[s.shver]];
-}
-
-inline tetgenmesh::point tetgenmesh::sapex(face& s) {
-  return (point) s.sh[3 + va[s.shver]];
-}
-
-inline void tetgenmesh::setsorg(face& s, point pointptr) {
-  s.sh[3 + vo[s.shver]] = (shellface) pointptr;
-}
-
-inline void tetgenmesh::setsdest(face& s, point pointptr) {
-  s.sh[3 + vd[s.shver]] = (shellface) pointptr;
-}
-
-inline void tetgenmesh::setsapex(face& s, point pointptr) {
-  s.sh[3 + va[s.shver]] = (shellface) pointptr;
-}
-
-// These primitives were drived from Mucke[2]'s triangle-edge data structure
-//   to change face-edge relation in a subface (sesym, senext and senext2).
-
-inline void tetgenmesh::sesym(face& s1, face& s2) {
-  s2.sh = s1.sh;
-  s2.shver = s1.shver + (EdgeRing(s1.shver) ? -1 : 1);
-}
-
-inline void tetgenmesh::sesymself(face& s) {
-  s.shver += (EdgeRing(s.shver) ? -1 : 1);
-}
-
-inline void tetgenmesh::senext(face& s1, face& s2) {
-  s2.sh = s1.sh;
-  s2.shver = ve[s1.shver];
-}
-
-inline void tetgenmesh::senextself(face& s) { 
-  s.shver = ve[s.shver]; 
-}
-
-inline void tetgenmesh::senext2(face& s1, face& s2) {
-  s2.sh = s1.sh;
-  s2.shver = ve[ve[s1.shver]];
-}
-
-inline void tetgenmesh::senext2self(face& s) {
-  s.shver = ve[ve[s.shver]];
-}
-
-// If f0 and f1 are both in the same face ring, then f1 = f0.fnext(),
-
-inline void tetgenmesh::sfnext(face& s1, face& s2) {
-  getnextsface(&s1, &s2);
-}
-
-inline void tetgenmesh::sfnextself(face& s) {
-  getnextsface(&s, NULL);
-}
-
-// These primitives read or set a pointer of the badface structure.  The
-//   pointer is stored sh[11].
-
-inline tetgenmesh::badface* tetgenmesh::shell2badface(face& s) {
-  return (badface*) s.sh[11];
-}
-
-inline void tetgenmesh::setshell2badface(face& s, badface* value) {
-  s.sh[11] = (shellface) value;
-}
-
-// Check or set a subface's maximum area bound.
-
-inline REAL tetgenmesh::areabound(face& s) {
-  return ((REAL *) (s.sh))[areaboundindex];
-}
-
-inline void tetgenmesh::setareabound(face& s, REAL value) {
-  ((REAL *) (s.sh))[areaboundindex] = value;
-}
-
-// These two primitives read or set a shell marker.  Shell markers are used
-//   to hold user boundary information.
-
-inline int tetgenmesh::shellmark(face& s) { 
-  return ((int *) (s.sh))[shmarkindex];
-}
-
-inline void tetgenmesh::setshellmark(face& s, int value) {
-  ((int *) (s.sh))[shmarkindex] = value;
-}
-
-// These two primitives set or read the type of the subface or subsegment.
-
-inline enum tetgenmesh::shestype tetgenmesh::shelltype(face& s) {
-  return (enum shestype) ((int *) (s.sh))[shmarkindex + 1];
-}
-
-inline void tetgenmesh::setshelltype(face& s, enum shestype value) {
-  ((int *) (s.sh))[shmarkindex + 1] = (int) value;
-}
-
-// These two primitives set or read the pbc group of the subface.
-
-inline int tetgenmesh::shellpbcgroup(face& s) {
-  return ((int *) (s.sh))[shmarkindex + 2];
-}
-
-inline void tetgenmesh::setshellpbcgroup(face& s, int value) {
-  ((int *) (s.sh))[shmarkindex + 2] = value;
-}
-
-// Primitives to infect or cure a subface with the virus. These rely on the
-//   assumption that all tetrahedra are aligned to eight-byte boundaries.
-
-inline void tetgenmesh::sinfect(face& s) {
-  s.sh[6] = (shellface) ((unsigned long) s.sh[6] | (unsigned long) 4l);
-}
-
-inline void tetgenmesh::suninfect(face& s) {
-  s.sh[6] = (shellface)((unsigned long) s.sh[6] & ~(unsigned long) 4l);
-}
-
-// Test a subface for viral infection.
-
-inline bool tetgenmesh::sinfected(face& s) {
-  return (((unsigned long) s.sh[6] & (unsigned long) 4l) != 0);
-}
-
-//
-// End of primitives for subfaces/subsegments
-//
-
-//
-// Begin of primitives for interacting between tetrahedra and subfaces
-//
-
-// tspivot() finds a subface abutting on this tetrahdera.
-
-inline void tetgenmesh::tspivot(triface& t, face& s) {
-  shellface sptr = (shellface) t.tet[8 + t.loc];
-  sdecode(sptr, s);
-}
-
-// stpivot() finds a tetrahedron abutting a subface.
-
-inline void tetgenmesh::stpivot(face& s, triface& t) {
-  tetrahedron ptr = (tetrahedron) s.sh[6 + EdgeRing(s.shver)];
-  decode(ptr, t);
-}
-
-// tsbond() bond a tetrahedron to a subface.
-
-inline void tetgenmesh::tsbond(triface& t, face& s) {
-  t.tet[8 + t.loc] = (tetrahedron) sencode(s);
-  s.sh[6 + EdgeRing(s.shver)] = (shellface) encode(t);
-}
-
-// tsdissolve() dissolve a bond (from the tetrahedron side).
-
-inline void tetgenmesh::tsdissolve(triface& t) {
-  t.tet[8 + t.loc] = (tetrahedron) dummysh;
-}
-
-// stdissolve() dissolve a bond (from the subface side).
-
-inline void tetgenmesh::stdissolve(face& s) {
-  s.sh[6 + EdgeRing(s.shver)] = (shellface) dummytet;
-}
-
-//
-// End of primitives for interacting between tetrahedra and subfaces
-//
-
-//
-// Begin of primitives for interacting between subfaces and subsegs
-//
-
-// sspivot() finds a subsegment abutting a subface.
-
-inline void tetgenmesh::sspivot(face& s, face& edge) {
-  shellface sptr = (shellface) s.sh[8 + Orient(s.shver)];
-  sdecode(sptr, edge);
-}
-
-// ssbond() bond a subface to a subsegment.
-
-inline void tetgenmesh::ssbond(face& s, face& edge) {
-  s.sh[8 + Orient(s.shver)] = sencode(edge);
-  edge.sh[0] = sencode(s);
-}
-
-// ssdisolve() dissolve a bond (from the subface side)
-
-inline void tetgenmesh::ssdissolve(face& s) {
-  s.sh[8 + Orient(s.shver)] = (shellface) dummysh;
-}
-
-//
-// End of primitives for interacting between subfaces and subsegs
-//
-
-//
-// Begin of primitives for interacting between tet and subsegs.
-//
-
-inline void tetgenmesh::tsspivot1(triface& t, face& seg)
-{
-  shellface sptr = (shellface) t.tet[8 + locver2edge[t.loc][t.ver]];
-  sdecode(sptr, seg);
-}
-
-// Only bond/dissolve at tet's side, but not vice versa.
-
-inline void tetgenmesh::tssbond1(triface& t, face& seg)
-{
-  t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) sencode(seg);
-}
-
-inline void tetgenmesh::tssdissolve1(triface& t)
-{
-  t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) dummysh;
-}
-
-//
-// End of primitives for interacting between tet and subsegs.
-//
-
-//
-// Begin of primitives for points
-//
-
-inline int tetgenmesh::pointmark(point pt) { 
-  return ((int *) (pt))[pointmarkindex]; 
-}
-
-inline void tetgenmesh::setpointmark(point pt, int value) {
-  ((int *) (pt))[pointmarkindex] = value;
-}
-
-// These two primitives set and read the type of the point.
-
-inline enum tetgenmesh::verttype tetgenmesh::pointtype(point pt) {
-  return (enum verttype) ((int *) (pt))[pointmarkindex + 1];
-}
-
-inline void tetgenmesh::setpointtype(point pt, enum verttype value) {
-  ((int *) (pt))[pointmarkindex + 1] = (int) value;
-}
-
-// These following primitives set and read a pointer to a tetrahedron
-//   a subface/subsegment, a point, or a tet of background mesh.
-
-inline tetgenmesh::tetrahedron tetgenmesh::point2tet(point pt) {
-  return ((tetrahedron *) (pt))[point2simindex];
-}
-
-inline void tetgenmesh::setpoint2tet(point pt, tetrahedron value) {
-  ((tetrahedron *) (pt))[point2simindex] = value;
-}
-
-inline tetgenmesh::shellface tetgenmesh::point2sh(point pt) {
-  return (shellface) ((tetrahedron *) (pt))[point2simindex + 1];
-}
-
-inline void tetgenmesh::setpoint2sh(point pt, shellface value) {
-  ((tetrahedron *) (pt))[point2simindex + 1] = (tetrahedron) value;
-}
-
-inline tetgenmesh::point tetgenmesh::point2ppt(point pt) {
-  return (point) ((tetrahedron *) (pt))[point2simindex + 2];
-}
-
-inline void tetgenmesh::setpoint2ppt(point pt, point value) {
-  ((tetrahedron *) (pt))[point2simindex + 2] = (tetrahedron) value;
-}
-
-inline tetgenmesh::tetrahedron tetgenmesh::point2bgmtet(point pt) {
-  return ((tetrahedron *) (pt))[point2simindex + 3];
-}
-
-inline void tetgenmesh::setpoint2bgmtet(point pt, tetrahedron value) {
-  ((tetrahedron *) (pt))[point2simindex + 3] = value;
-}
-
-// These primitives set and read a pointer to its pbc point.
-
-inline tetgenmesh::point tetgenmesh::point2pbcpt(point pt) {
-  return (point) ((tetrahedron *) (pt))[point2pbcptindex];
-}
-
-inline void tetgenmesh::setpoint2pbcpt(point pt, point value) {
-  ((tetrahedron *) (pt))[point2pbcptindex] = (tetrahedron) value;
-}
-
-//
-// End of primitives for points
-//
-
-//
-// Begin of advanced primitives
-//
-
-// adjustedgering() adjusts the edge version so that it belongs to the
-//   indicated edge ring.  The 'direction' only can be 0(CCW) or 1(CW).
-//   If the edge is not in the wanted edge ring, reverse it.
-
-inline void tetgenmesh::adjustedgering(triface& t, int direction) {
-  if (EdgeRing(t.ver) != direction) {
-    esymself(t);
-  }
-}
-
-inline void tetgenmesh::adjustedgering(face& s, int direction) {
-  if (EdgeRing(s.shver) != direction) {
-    sesymself(s);
-  }
-}
-
-// isdead() returns TRUE if the tetrahedron or subface has been dealloced.
-
-inline bool tetgenmesh::isdead(triface* t) {
-  if (t->tet == (tetrahedron *) NULL) return true;
-  else return t->tet[4] == (tetrahedron) NULL;
-}
-
-inline bool tetgenmesh::isdead(face* s) {
-  if (s->sh == (shellface *) NULL) return true;
-  else return s->sh[3] == (shellface) NULL;
-}
-
-// isfacehaspoint() returns TRUE if the 'testpoint' is one of the vertices
-//   of the tetface 't' subface 's'.
-
-inline bool tetgenmesh::isfacehaspoint(triface* t, point testpoint) {
-  return ((org(*t) == testpoint) || (dest(*t) == testpoint) ||
-          (apex(*t) == testpoint));
-}
-
-inline bool tetgenmesh::isfacehaspoint(face* s, point testpoint) {
-  return (s->sh[3] == (shellface) testpoint) || 
-         (s->sh[4] == (shellface) testpoint) ||
-         (s->sh[5] == (shellface) testpoint);
-}
-
-// isfacehasedge() returns TRUE if the edge (given by its two endpoints) is
-//   one of the three edges of the subface 's'.
-
-inline bool tetgenmesh::isfacehasedge(face* s, point tend1, point tend2) {
-  return (isfacehaspoint(s, tend1) && isfacehaspoint(s, tend2));
-}
-
-// issymexist() returns TRUE if the adjoining tetrahedron is not 'duumytet'.
-
-inline bool tetgenmesh::issymexist(triface* t) {
-  tetrahedron *ptr = (tetrahedron *) 
-    ((unsigned long)(t->tet[t->loc]) & ~(unsigned long)7l);
-  return ptr != dummytet;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getnextsface()    Finds the next subface in the face ring.                //
-//                                                                           //
-// For saving space in the data structure of subface, there only exists one  //
-// face ring around a segment (see programming manual).  This routine imple- //
-// ments the double face ring as desired in Muecke's data structure.         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::getnextsface(face* s1, face* s2)
-{
-  face neighsh, spinsh;
-  face testseg;
-
-  sspivot(*s1, testseg);
-  if (testseg.sh != dummysh) {
-    testseg.shver = 0;
-    if (sorg(testseg) == sorg(*s1)) {
-      spivot(*s1, neighsh);
-    } else {
-      spinsh = *s1;
-      do {
-        neighsh = spinsh;
-        spivotself(spinsh);
-      } while (spinsh.sh != s1->sh);
-    }
-  } else {
-    spivot(*s1, neighsh);
-  }
-  if (sorg(neighsh) != sorg(*s1)) {
-    sesymself(neighsh);
-  }
-  if (s2 != (face *) NULL) {
-    *s2 = neighsh;
-  } else {
-    *s1 = neighsh;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tsspivot()    Finds a subsegment abutting on a tetrahderon's edge.        //
-//                                                                           //
-// The edge is represented in the primary edge of 'checkedge'. If there is a //
-// subsegment bonded at this edge, it is returned in handle 'checkseg', the  //
-// edge direction of 'checkseg' is conformed to 'checkedge'. If there isn't, //
-// set 'checkseg.sh = dummysh' to indicate it is not a subsegment.           //
-//                                                                           //
-// To find whether an edge of a tetrahedron is a subsegment or not. First we //
-// need find a subface around this edge to see if it contains a subsegment.  //
-// The reason is there is no direct connection between a tetrahedron and its //
-// adjoining subsegments.                                                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::tsspivot(triface* checkedge, face* checkseg)
-{
-  triface spintet;
-  face parentsh;
-  point tapex;
-  int hitbdry;
-
-  spintet = *checkedge;
-  tapex = apex(*checkedge);
-  hitbdry = 0;
-  do {
-    tspivot(spintet, parentsh);
-    // Does spintet have a (non-fake) subface attached? 
-    if ((parentsh.sh != dummysh) && (sapex(parentsh) != NULL)) {
-      // Find a subface! Find the edge in it.      
-      findedge(&parentsh, org(*checkedge), dest(*checkedge));
-      sspivot(parentsh, *checkseg);
-      if (checkseg->sh != dummysh) {
-        // Find a subsegment! Correct its edge direction before return.
-        if (sorg(*checkseg) != org(*checkedge)) {
-          sesymself(*checkseg);
-        }
-      }
-      return;
-    }
-    if (!fnextself(spintet)) {
-      hitbdry++;
-      if (hitbdry < 2) {
-        esym(*checkedge, spintet);
-        if (!fnextself(spintet)) {
-          hitbdry++;
-        }
-      }
-    }
-  } while ((apex(spintet) != tapex) && (hitbdry < 2));
-  // Not find.
-  checkseg->sh = dummysh;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// sstpivot()    Finds a tetrahedron abutting a subsegment.                  //
-//                                                                           //
-// This is the inverse operation of 'tsspivot()'.  One subsegment shared by  //
-// arbitrary number of tetrahedron, the returned tetrahedron is not unique.  //
-// The edge direction of the returned tetrahedron is conformed to the given  //
-// subsegment.                                                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::sstpivot(face* checkseg, triface* retedge)
-{
-  face parentsh;
-
-  // Get the subface which holds the subsegment.
-  sdecode(checkseg->sh[0], parentsh);
-#ifdef SELF_CHECK
-  assert(parentsh.sh != dummysh);
-#endif
-  // Get a tetraheron to which the subface attches.
-  stpivot(parentsh, *retedge);
-  if (retedge->tet == dummytet) {
-    sesymself(parentsh);
-    stpivot(parentsh, *retedge);
-#ifdef SELF_CHECK
-    assert(retedge->tet != dummytet);
-#endif
-  }
-  // Correct the edge direction before return.
-  findedge(retedge, sorg(*checkseg), sdest(*checkseg));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// findorg()    Finds a point in the given handle (tetrahedron or subface).  //
-//                                                                           //
-// If 'dorg' is a one of vertices of the given handle,  set the origin of    //
-// this handle be that point and return TRUE.  Otherwise, return FALSE and   //
-// 'tface' remains unchanged.                                                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::findorg(triface* tface, point dorg)
-{
-  if (org(*tface) == dorg) {
-    return true;
-  } else { 
-    if (dest(*tface) == dorg) {
-      enextself(*tface);
-      return true;
-    } else {
-      if (apex(*tface) == dorg) {
-        enext2self(*tface);
-        return true;
-      } else {
-        if (oppo(*tface) == dorg) {
-          // Keep 'tface' referring to the same tet after fnext().
-          adjustedgering(*tface, CCW);
-          fnextself(*tface);
-          enext2self(*tface);
-          return true;
-        } 
-      }
-    }
-  }
-  return false;
-}
-
-bool tetgenmesh::findorg(face* sface, point dorg)
-{
-  if (sorg(*sface) == dorg) {
-    return true;
-  } else {
-    if (sdest(*sface) == dorg) {
-      senextself(*sface);
-      return true;
-    } else {
-      if (sapex(*sface) == dorg) {
-        senext2self(*sface);
-        return true;
-      } 
-    }
-  }
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// findedge()    Find an edge in the given handle (tetrahedron or subface).  //
-//                                                                           //
-// The edge is given in two points 'eorg' and 'edest'.  It is assumed that   //
-// the edge must exist in the given handle (tetrahedron or subface).  This   //
-// routine sets the right edge version for the input handle.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::findedge(triface* tface, point eorg, point edest)
-{
-  int i;
-
-  for (i = 0; i < 3; i++) {
-    if (org(*tface) == eorg) {
-      if (dest(*tface) == edest) {
-        // Edge is found, return.
-        return;
-      } 
-    } else {
-      if (org(*tface) == edest) {
-        if (dest(*tface) == eorg) {
-          // Edge is found, inverse the direction and return.
-          esymself(*tface);
-          return;
-        }
-      }
-    }
-    enextself(*tface);
-  }
-  // It should never be here.
-  printf("Internalerror in findedge():  Unable to find an edge in tet.\n");
-  internalerror();
-}
-
-void tetgenmesh::findedge(face* sface, point eorg, point edest)
-{
-  int i;
-
-  for (i = 0; i < 3; i++) {
-    if (sorg(*sface) == eorg) {
-      if (sdest(*sface) == edest) {
-        // Edge is found, return.
-        return;
-      } 
-    } else {
-      if (sorg(*sface) == edest) {
-        if (sdest(*sface) == eorg) {
-          // Edge is found, inverse the direction and return.
-          sesymself(*sface);
-          return;
-        }
-      }
-    }
-    senextself(*sface);
-  }
-  printf("Internalerror in findedge():  Unable to find an edge in subface.\n");
-  internalerror();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// findface()    Find the face has the given origin, destination and apex.   //
-//                                                                           //
-// On input, 'fface' is a handle which may contain the three corners or may  //
-// not or may be dead.  On return, it represents exactly the face with the   //
-// given origin, destination and apex.                                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::findface(triface *fface, point forg, point fdest, point fapex)
-{
-  triface spintet;
-  enum finddirectionresult collinear;
-  int hitbdry;
-
-  if (!isdead(fface)) {
-    // First check the easiest case, that 'fface' is just the right one.
-    if (org(*fface) == forg && dest(*fface) == fdest && 
-        apex(*fface) == fapex) return;
-  } else {
-    // The input handle is dead, use the 'recenttet' if it is alive.
-    if (!isdead(&recenttet)) *fface = recenttet;
-  }
-
-  if (!isdead(fface)) {
-    if (!findorg(fface, forg)) {
-      // 'forg' is not a corner of 'fface', locate it.
-      preciselocate(forg, fface, tetrahedrons->items);
-    }
-    // It is possible that forg is not found in a non-convex mesh.
-    if (org(*fface) == forg) {
-      collinear = finddirection(fface, fdest, tetrahedrons->items);
-      if (collinear == RIGHTCOLLINEAR) {
-        // fdest is just the destination.
-      } else if (collinear == LEFTCOLLINEAR) {
-        enext2self(*fface);
-        esymself(*fface);
-      } else if (collinear == TOPCOLLINEAR) {
-        fnextself(*fface);
-        enext2self(*fface);
-        esymself(*fface);
-      }
-    }
-    // It is possible taht fdest is not found in a non-convex mesh.
-    if ((org(*fface) == forg) && (dest(*fface) == fdest)) {
-      // Find the apex of 'fapex'.
-      spintet = *fface;
-      hitbdry = 0;
-      do {
-        if (apex(spintet) == fapex) {
-          // We have done. Be careful the edge direction of 'spintet',
-          //   it may reversed because of hitting boundary once.
-          if (org(spintet) != org(*fface)) {
-            esymself(spintet);
-          }
-          *fface = spintet;
-          return;
-        }
-        if (!fnextself(spintet)) {
-          hitbdry ++;
-          if (hitbdry < 2) {
-            esym(*fface, spintet);
-            if (!fnextself(spintet)) {
-              hitbdry ++;
-            }
-          }
-        }
-      } while (hitbdry < 2 && apex(spintet) != apex(*fface));
-      // It is possible that fapex is not found in a non-convex mesh.
-    }
-  }
-
-  if (isdead(fface) || (org(*fface) != forg) || (dest(*fface) != fdest) ||
-      (apex(*fface) != fapex)) {
-    // Too bad, the input handle is useless. We have to find a handle
-    //   for 'fface' contains the 'forg' and 'fdest'. Here a brute force
-    //   search is performed.
-    if (b->verbose > 1) {
-      printf("Warning in findface():  Perform a brute-force searching.\n");
-    }
-    enum verttype forgty, fdestty, fapexty;
-    int share, i;
-    forgty = pointtype(forg);
-    fdestty = pointtype(fdest);
-    fapexty = pointtype(fapex);
-    setpointtype(forg, DEADVERTEX);
-    setpointtype(fdest, DEADVERTEX);
-    setpointtype(fapex, DEADVERTEX);
-    tetrahedrons->traversalinit();
-    fface->tet = tetrahedrontraverse();
-    while (fface->tet != (tetrahedron *) NULL) {
-      share = 0;
-      for (i = 0; i < 4; i++) {
-        if (pointtype((point) fface->tet[4 + i]) == DEADVERTEX) share ++;
-      }
-      if (share == 3) {
-        // Found! Set the correct face and desired corners.
-        if (pointtype((point) fface->tet[4]) != DEADVERTEX) {
-          fface->loc = 2;
-        } else if (pointtype((point) fface->tet[5]) != DEADVERTEX) {
-          fface->loc = 3;
-        } else if (pointtype((point) fface->tet[6]) != DEADVERTEX) {
-          fface->loc = 1;
-        } else { // pointtype((point) fface->tet[7]) != DEADVERTEX
-          fface->loc = 0;
-        }
-        findedge(fface, forg, fdest);
-        break;
-      }
-      fface->tet = tetrahedrontraverse();
-    }
-    setpointtype(forg, forgty);
-    setpointtype(fdest, fdestty);
-    setpointtype(fapex, fapexty);
-    if (fface->tet == (tetrahedron *) NULL) {
-      // It is impossible to reach here.
-      printf("Internal error:  Fail to find the indicated face.\n");
-      internalerror();
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getonextseg()    Get the next SEGMENT counterclockwise with the same org. //
-//                                                                           //
-// 's' is a subface. This routine reteuns the segment which is counterclock- //
-// wise with the origin of s.                                                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::getonextseg(face* s, face* lseg)
-{
-  face checksh, checkseg;
-  point forg;
-
-  forg = sorg(*s);
-  checksh = *s;
-  do {
-    // Go to the edge at forg's left side.
-    senext2self(checksh);
-    // Check if there is a segment attaching this edge.
-    sspivot(checksh, checkseg);
-    if (checkseg.sh != dummysh) break;
-    // No segment! Go to the neighbor of this subface.
-    spivotself(checksh);
-#ifdef SELF_CHECK
-    // It should always meet a segment before come back.
-    assert(checksh.sh != s->sh);
-#endif
-    if (sorg(checksh) != forg) {
-      sesymself(checksh);
-#ifdef SELF_CHECK
-      assert(sorg(checksh) == forg);
-#endif
-    }
-  } while (true);
-  if (sorg(checkseg) != forg) sesymself(checkseg);
-  *lseg = checkseg;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getseghasorg()    Get the segment containing the given point.             //
-//                                                                           //
-// 'dorg' is an endpoint of a segment S. 'sseg' is a subsegment of S. This   //
-// routine search a subsegment (along sseg) of S containing dorg. On return, //
-// 'sseg' contains 'dorg' as its origin.                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::getseghasorg(face* sseg, point dorg)
-{
-  face nextseg;
-  point checkpt;
-
-  nextseg = *sseg;
-  checkpt = sorg(nextseg);
-  while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
-    // Search dorg along the original direction of sseg.
-    senext2self(nextseg);
-    spivotself(nextseg);
-    nextseg.shver = 0;
-    if (sdest(nextseg) != checkpt) sesymself(nextseg);
-    checkpt = sorg(nextseg);
-  }
-  if (checkpt == dorg) {
-    *sseg = nextseg;
-    return;
-  }
-  nextseg = *sseg;
-  checkpt = sdest(nextseg);
-  while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
-    // Search dorg along the destinational direction of sseg.
-    senextself(nextseg);
-    spivotself(nextseg);
-    nextseg.shver = 0;
-    if (sorg(nextseg) != checkpt) sesymself(nextseg);
-    checkpt = sdest(nextseg);
-  }
-  if (checkpt == dorg) {
-    sesym(nextseg, *sseg);
-    return;
-  }
-  // Should never be here.
-  printf("Internalerror in getseghasorg():  Unable to find the subseg.\n");
-  internalerror();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getsubsegfarorg()    Get the origin of the parent segment of a subseg.    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::point tetgenmesh::getsubsegfarorg(face* sseg)
-{
-  face prevseg;
-  point checkpt;
-
-  checkpt = sorg(*sseg);
-  senext2(*sseg, prevseg);
-  spivotself(prevseg);
-  // Search dorg along the original direction of sseg.
-  while (prevseg.sh != dummysh) {
-    prevseg.shver = 0;
-    if (sdest(prevseg) != checkpt) sesymself(prevseg);
-    checkpt = sorg(prevseg);
-    senext2self(prevseg);
-    spivotself(prevseg);
-  }
-  return checkpt;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getsubsegfardest()    Get the dest. of the parent segment of a subseg.    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::point tetgenmesh::getsubsegfardest(face* sseg)
-{
-  face nextseg;
-  point checkpt;
-
-  checkpt = sdest(*sseg);
-  senext(*sseg, nextseg);
-  spivotself(nextseg);
-  // Search dorg along the destinational direction of sseg.
-  while (nextseg.sh != dummysh) {
-    nextseg.shver = 0;
-    if (sorg(nextseg) != checkpt) sesymself(nextseg);
-    checkpt = sdest(nextseg);
-    senextself(nextseg);
-    spivotself(nextseg);
-  }
-  return checkpt;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// printtet()    Print out the details of a tetrahedron on screen.           //
-//                                                                           //
-// It's also used when the highest level of verbosity (`-VVV') is specified. //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::printtet(triface* tface)
-{
-  triface tmpface, prtface;
-  point tmppt;
-  face tmpsh;
-  int facecount;
-
-  printf("Tetra x%lx with loc(%i) and ver(%i):",
-         (unsigned long)(tface->tet), tface->loc, tface->ver);
-  if (infected(*tface)) {
-    printf(" (infected)");
-  }
-  printf("\n");
-
-  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).", facecount,
-             (unsigned long)(prtface.tet), prtface.loc);
-      if (infected(prtface)) {
-        printf(" (infected)");
-      }
-      printf("\n");
-    }
-    facecount ++;
-  }
-
-  tmppt = org(*tface);
-  if(tmppt == (point) 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));
-  }
-  tmppt = dest(*tface);
-  if(tmppt == (point) 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));
-  }
-  tmppt = apex(*tface);
-  if(tmppt == (point) 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));
-  }
-  tmppt = oppo(*tface);
-  if(tmppt == (point) 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 (b->useshelles) {
-    tmpface = *tface;
-    facecount = 0;
-    while(facecount < 6) {
-      tmpface.loc = facecount;
-      tspivot(tmpface, tmpsh);
-      if(tmpsh.sh != dummysh) {
-        printf("      [%i] x%lx  ID(%i) ", facecount,
-               (unsigned long)(tmpsh.sh), shellmark(tmpsh));
-        if (sorg(tmpsh) == (point) NULL) {
-          printf("(fake)");
-        }
-        printf("\n");
-      }
-      facecount ++;
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// printsh()    Print out the details of a subface or subsegment on screen.  //
-//                                                                           //
-// It's also used when the highest level of verbosity (`-VVV') is specified. //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::printsh(face* sface)
-{
-  face prtsh;
-  triface prttet;
-  point printpoint;
-
-  if (sapex(*sface) != NULL) {
-    printf("subface x%lx, ver %d, mark %d:",
-           (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
-  } else {
-    printf("Subsegment x%lx, ver %d, mark %d:",
-           (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
-  }
-  if (sinfected(*sface)) {
-    printf(" (infected)");
-  }
-  if (shell2badface(*sface)) {
-    printf(" (queued)");
-  }
-  if (sapex(*sface) != NULL) {
-    if (shelltype(*sface) == SHARP) {
-      printf(" (sharp)");
-    }
-  } else {
-    if (shelltype(*sface) == SHARP) {
-      printf(" (sharp)");
-    }
-  }
-  if (checkpbcs) {
-    if (shellpbcgroup(*sface) >= 0) {
-      printf(" (pbc %d)", shellpbcgroup(*sface));
-    }
-  }
-  printf("\n");
-
-  sdecode(sface->sh[0], prtsh);
-  if (prtsh.sh == dummysh) {
-    printf("      [0] = No shell\n");
-  } else {
-    printf("      [0] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
-  }
-  sdecode(sface->sh[1], prtsh);
-  if (prtsh.sh == dummysh) {
-    printf("      [1] = No shell\n");
-  } else {
-    printf("      [1] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
-  }
-  sdecode(sface->sh[2], prtsh);
-  if (prtsh.sh == dummysh) {
-    printf("      [2] = No shell\n");
-  } else {
-    printf("      [2] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
-  }
-
-  printpoint = sorg(*sface);
-  if (printpoint == (point) 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));
-  printpoint = sdest(*sface);
-  if (printpoint == (point) 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 (sapex(*sface) != NULL) {
-    printpoint = sapex(*sface);
-    if (printpoint == (point) 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], prttet);
-    if (prttet.tet == dummytet) {
-      printf("      [6] = Outer space\n");
-    } else {
-      printf("      [6] = x%lx  %d\n",
-             (unsigned long)(prttet.tet), prttet.loc);
-    }
-    decode(sface->sh[7], prttet);
-    if (prttet.tet == dummytet) {
-      printf("      [7] = Outer space\n");
-    } else {
-      printf("      [7] = x%lx  %d\n",
-             (unsigned long)(prttet.tet), prttet.loc);
-    }
-
-    sdecode(sface->sh[8], prtsh);
-    if (prtsh.sh == dummysh) {
-      printf("      [8] = No subsegment\n");
-    } else {
-      printf("      [8] = x%lx  %d\n",
-             (unsigned long)(prtsh.sh), prtsh.shver);
-    }
-    sdecode(sface->sh[9], prtsh);
-    if (prtsh.sh == dummysh) {
-      printf("      [9] = No subsegment\n");
-    } else {
-      printf("      [9] = x%lx  %d\n",
-             (unsigned long)(prtsh.sh), prtsh.shver);
-    }
-    sdecode(sface->sh[10], prtsh);
-    if (prtsh.sh == dummysh) {
-      printf("      [10]= No subsegment\n");
-    } else {
-      printf("      [10]= x%lx  %d\n",
-             (unsigned long)(prtsh.sh), prtsh.shver);
-    }
-  } 
-}
-
-//
-// End of advanced primitives
-//
-
-//
-// End of mesh manipulation primitives
-//
-
-//
-// Begin of mesh items searching routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// makepoint2tetmap()    Construct a mapping from points to tetrahedra.      //
-//                                                                           //
-// Traverses all the tetrahedra,  provides each corner of each tetrahedron   //
-// with a pointer to that tetrahedera.  Some pointers will be overwritten by //
-// other pointers because each point may be a corner of several tetrahedra,  //
-// but in the end every point will point to a tetrahedron that contains it.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::makepoint2tetmap()
-{
-  triface tetloop;
-  point pointptr;
-
-  if (b->verbose > 0) {
-    printf("  Constructing mapping from points to tetrahedra.\n");
-  }
-
-  // Initialize the point2tet field of each point.
-  points->traversalinit();
-  pointptr = pointtraverse();
-  while (pointptr != (point) NULL) {
-    setpoint2tet(pointptr, (tetrahedron) NULL);
-    pointptr = pointtraverse();
-  }
-
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    // Check all four points of the tetrahedron.
-    tetloop.loc = 0;
-    pointptr = org(tetloop);
-    setpoint2tet(pointptr, encode(tetloop));
-    pointptr = dest(tetloop);
-    setpoint2tet(pointptr, encode(tetloop));
-    pointptr = apex(tetloop);
-    setpoint2tet(pointptr, encode(tetloop));
-    pointptr = oppo(tetloop);
-    setpoint2tet(pointptr, encode(tetloop));
-    // Get the next tetrahedron in the list.
-    tetloop.tet = tetrahedrontraverse();
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// makeindex2pointmap()    Create a map from index to vertices.              //
-//                                                                           //
-// 'idx2verlist' returns the created map.  Traverse all vertices, a pointer  //
-// to each vertex is set into the array.  The pointer to the first vertex is //
-// saved in 'idx2verlist[0]'.  Don't forget to minus 'in->firstnumber' when  //
-// to get the vertex form its index.                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
-{
-  point pointloop;
-  int idx;
-
-  if (b->verbose > 0) {
-    printf("  Constructing mapping from indices to points.\n");
-  }
-
-  idx2verlist = new point[points->items];
-
-  points->traversalinit();
-  pointloop = pointtraverse();
-  idx = 0;
-  while (pointloop != (point) NULL) {
-    idx2verlist[idx] = pointloop;
-    idx++;
-    pointloop = pointtraverse();
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// makesegmentmap()    Create a map from vertices (their indices) to         //
-//                     segments incident at the same vertices.               //
-//                                                                           //
-// Two arrays 'idx2seglist' and 'segsperverlist' together return the map.    //
-// They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
-// number of segments.  idx2seglist contains row information and             //
-// segsperverlist contains all (non-zero) elements.  The i-th entry of       //
-// idx2seglist is the starting position of i-th row's (non-zero) elements in //
-// segsperverlist.  The number of elements of i-th row is calculated by the  //
-// (i+1)-th entry minus i-th entry of idx2seglist.                           //
-//                                                                           //
-// NOTE: These two arrays will be created inside this routine, don't forget  //
-// to free them after using.                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::makesegmentmap(int*& idx2seglist, shellface**& segsperverlist)
-{
-  shellface *shloop;
-  int i, j, k;
-
-  if (b->verbose > 0) {
-    printf("  Constructing mapping from points to segments.\n");
-  }
-
-  // Create and initialize 'idx2seglist'.
-  idx2seglist = new int[points->items + 1];
-  for (i = 0; i < points->items + 1; i++) idx2seglist[i] = 0;
-
-  // Loop the set of segments once, counter the number of segments sharing
-  //   each vertex.
-  subsegs->traversalinit();
-  shloop = shellfacetraverse(subsegs);
-  while (shloop != (shellface *) NULL) {
-    // Increment the number of sharing segments for each endpoint.
-    for (i = 0; i < 2; i++) {
-      j = pointmark((point) shloop[3 + i]) - in->firstnumber;
-      idx2seglist[j]++;
-    }
-    shloop = shellfacetraverse(subsegs);
-  }
-
-  // Calculate the total length of array 'facesperverlist'.
-  j = idx2seglist[0];
-  idx2seglist[0] = 0;  // Array starts from 0 element.
-  for (i = 0; i < points->items; i++) {
-    k = idx2seglist[i + 1];
-    idx2seglist[i + 1] = idx2seglist[i] + j;
-    j = k;
-  }
-  // The total length is in the last unit of idx2seglist.
-  segsperverlist = new shellface*[idx2seglist[i]];
-  // Loop the set of segments again, set the info. of segments per vertex.
-  subsegs->traversalinit();
-  shloop = shellfacetraverse(subsegs);
-  while (shloop != (shellface *) NULL) {
-    for (i = 0; i < 2; i++) {
-      j = pointmark((point) shloop[3 + i]) - in->firstnumber;
-      segsperverlist[idx2seglist[j]] = shloop;
-      idx2seglist[j]++;
-    }
-    shloop = shellfacetraverse(subsegs);
-  }
-  // Contents in 'idx2seglist' are shifted, now shift them back.
-  for (i = points->items - 1; i >= 0; i--) {
-    idx2seglist[i + 1] = idx2seglist[i];
-  }
-  idx2seglist[0] = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// makesubfacemap()    Create a map from vertices (their indices) to         //
-//                     subfaces incident at the same vertices.               //
-//                                                                           //
-// Two arrays 'idx2facelist' and 'facesperverlist' together return the map.  //
-// They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
-// number of subfaces.  idx2facelist contains row information and            //
-// facesperverlist contains all (non-zero) elements.  The i-th entry of      //
-// idx2facelist is the starting position of i-th row's(non-zero) elements in //
-// facesperverlist.  The number of elements of i-th row is calculated by the //
-// (i+1)-th entry minus i-th entry of idx2facelist.                          //
-//                                                                           //
-// NOTE: These two arrays will be created inside this routine, don't forget  //
-// to free them after using.                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::
-makesubfacemap(int*& idx2facelist, shellface**& facesperverlist)
-{
-  shellface *shloop;
-  int i, j, k;
-
-  if (b->verbose > 0) {
-    printf("  Constructing mapping from points to subfaces.\n");
-  }
-
-  // Create and initialize 'idx2facelist'.
-  idx2facelist = new int[points->items + 1];
-  for (i = 0; i < points->items + 1; i++) idx2facelist[i] = 0;
-
-  // Loop the set of subfaces once, counter the number of subfaces sharing
-  //   each vertex.
-  subfaces->traversalinit();
-  shloop = shellfacetraverse(subfaces);
-  while (shloop != (shellface *) NULL) {
-    // Increment the number of sharing segments for each endpoint.
-    for (i = 0; i < 3; i++) {
-      j = pointmark((point) shloop[3 + i]) - in->firstnumber;
-      idx2facelist[j]++;
-    }
-    shloop = shellfacetraverse(subfaces);
-  }
-
-  // Calculate the total length of array 'facesperverlist'.
-  j = idx2facelist[0];
-  idx2facelist[0] = 0;  // Array starts from 0 element.
-  for (i = 0; i < points->items; i++) {
-    k = idx2facelist[i + 1];
-    idx2facelist[i + 1] = idx2facelist[i] + j;
-    j = k;
-  }
-  // The total length is in the last unit of idx2facelist.
-  facesperverlist = new shellface*[idx2facelist[i]];
-  // Loop the set of segments again, set the info. of segments per vertex.
-  subfaces->traversalinit();
-  shloop = shellfacetraverse(subfaces);
-  while (shloop != (shellface *) NULL) {
-    for (i = 0; i < 3; i++) {
-      j = pointmark((point) shloop[3 + i]) - in->firstnumber;
-      facesperverlist[idx2facelist[j]] = shloop;
-      idx2facelist[j]++;
-    }
-    shloop = shellfacetraverse(subfaces);
-  }
-  // Contents in 'idx2facelist' are shifted, now shift them back.
-  for (i = points->items - 1; i >= 0; i--) {
-    idx2facelist[i + 1] = idx2facelist[i];
-  }
-  idx2facelist[0] = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// maketetrahedronmap()    Create a map from vertices (their indices) to     //
-//                         tetrahedra incident at the same vertices.         //
-//                                                                           //
-// Two arrays 'idx2tetlist' and 'tetsperverlist' together return the map.    //
-// They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
-// number of tetrahedra.  idx2tetlist contains row information and           //
-// tetsperverlist contains all (non-zero) elements.  The i-th entry of       //
-// idx2tetlist is the starting position of i-th row's (non-zero) elements in //
-// tetsperverlist.  The number of elements of i-th row is calculated by the  //
-// (i+1)-th entry minus i-th entry of idx2tetlist.                           //
-//                                                                           //
-// NOTE: These two arrays will be created inside this routine, don't forget  //
-// to free them after using.                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::
-maketetrahedronmap(int*& idx2tetlist, tetrahedron**& tetsperverlist)
-{
-  tetrahedron *tetloop;
-  int i, j, k;
-
-  if (b->verbose > 0) {
-    printf("  Constructing mapping from points to tetrahedra.\n");
-  }
-
-  // Create and initialize 'idx2tetlist'.
-  idx2tetlist = new int[points->items + 1];
-  for (i = 0; i < points->items + 1; i++) idx2tetlist[i] = 0;
-
-  // Loop the set of tetrahedra once, counter the number of tetrahedra
-  //   sharing each vertex.
-  tetrahedrons->traversalinit();
-  tetloop = tetrahedrontraverse();
-  while (tetloop != (tetrahedron *) NULL) {
-    // Increment the number of sharing tetrahedra for each endpoint.
-    for (i = 0; i < 4; i++) {
-      j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
-      idx2tetlist[j]++;
-    }
-    tetloop = tetrahedrontraverse();
-  }
-
-  // Calculate the total length of array 'tetsperverlist'.
-  j = idx2tetlist[0];
-  idx2tetlist[0] = 0;  // Array starts from 0 element.
-  for (i = 0; i < points->items; i++) {
-    k = idx2tetlist[i + 1];
-    idx2tetlist[i + 1] = idx2tetlist[i] + j;
-    j = k;
-  }
-  // The total length is in the last unit of idx2tetlist.
-  tetsperverlist = new tetrahedron*[idx2tetlist[i]];
-  // Loop the set of tetrahedra again, set the info. of tet. per vertex.
-  tetrahedrons->traversalinit();
-  tetloop = tetrahedrontraverse();
-  while (tetloop != (tetrahedron *) NULL) {
-    for (i = 0; i < 4; i++) {
-      j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
-      tetsperverlist[idx2tetlist[j]] = tetloop;
-      idx2tetlist[j]++;
-    }
-    tetloop = tetrahedrontraverse();
-  }
-  // Contents in 'idx2tetlist' are shifted, now shift them back.
-  for (i = points->items - 1; i >= 0; i--) {
-    idx2tetlist[i + 1] = idx2tetlist[i];
-  }
-  idx2tetlist[0] = 0;
-}
-
-//
-// End of mesh items searching routines
-//
-
-//
-// Begin of linear algebra functions
-//
-
-// dot() returns the dot product: v1 dot v2.
-
-inline REAL tetgenmesh::dot(REAL* v1, REAL* v2) 
-{
-  return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
-}
-
-// cross() computes the cross product: n = v1 cross v2.
-
-inline void tetgenmesh::cross(REAL* v1, REAL* v2, REAL* n) 
-{
-  n[0] =   v1[1] * v2[2] - v2[1] * v1[2];
-  n[1] = -(v1[0] * v2[2] - v2[0] * v1[2]);
-  n[2] =   v1[0] * v2[1] - v2[0] * v1[1];
-}
-
-// initm44() initializes a 4x4 matrix.
-static void initm44(REAL a00, REAL a01, REAL a02, REAL a03,
-                    REAL a10, REAL a11, REAL a12, REAL a13,
-                    REAL a20, REAL a21, REAL a22, REAL a23,
-                    REAL a30, REAL a31, REAL a32, REAL a33,
-                    REAL M[4][4])
-{
-  M[0][0] = a00; M[0][1] = a01; M[0][2] = a02; M[0][3] = a03;
-  M[1][0] = a10; M[1][1] = a11; M[1][2] = a12; M[1][3] = a13;
-  M[2][0] = a20; M[2][1] = a21; M[2][2] = a22; M[2][3] = a23;
-  M[3][0] = a30; M[3][1] = a31; M[3][2] = a32; M[3][3] = a33;
-}
-
-// m4xm4() multiplies 2 4x4 matrics:  m1 = m1 * m2.
-static void m4xm4(REAL m1[4][4], REAL m2[4][4])
-{
-  REAL tmp[4];
-  int i, j;
-
-  for (i = 0; i < 4; i++) {   // i-th row
-    for (j = 0; j < 4; j++) { // j-th col
-      tmp[j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j] 
-             + m1[i][2] * m2[2][j] + m1[i][3] * m2[3][j];
-    }
-    for (j = 0; j < 4; j++) 
-      m1[i][j] = tmp[j];
-  }
-}
-
-// m4xv4() multiplies a 4x4 matrix and 4x1 vector: v2 = m * v1
-static void m4xv4(REAL v2[4], REAL m[4][4], REAL v1[4])
-{
-  v2[0] = m[0][0]*v1[0] + m[0][1]*v1[1] + m[0][2]*v1[2] + m[0][3]*v1[3];
-  v2[1] = m[1][0]*v1[0] + m[1][1]*v1[1] + m[1][2]*v1[2] + m[1][3]*v1[3];
-  v2[2] = m[2][0]*v1[0] + m[2][1]*v1[1] + m[2][2]*v1[2] + m[2][3]*v1[3];
-  v2[3] = m[3][0]*v1[0] + m[3][1]*v1[1] + m[3][2]*v1[2] + m[3][3]*v1[3];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// lu_decmp()    Compute the LU decomposition of a matrix.                   //
-//                                                                           //
-// Compute the LU decomposition of a (non-singular) square matrix A using    //
-// partial pivoting and implicit row exchanges.  The result is:              //
-//     A = P * L * U,                                                        //
-// where P is a permutation matrix, L is unit lower triangular, and U is     //
-// upper triangular.  The factored form of A is used in combination with     //
-// 'lu_solve()' to solve linear equations: Ax = b, or invert a matrix.       //
-//                                                                           //
-// The inputs are a square matrix 'lu[N..n+N-1][N..n+N-1]', it's size is 'n'.//
-// On output, 'lu' is replaced by the LU decomposition of a rowwise permuta- //
-// tion of itself, 'ps[N..n+N-1]' is an output vector that records the row   //
-// permutation effected by the partial pivoting, effectively,  'ps' array    //
-// tells the user what the permutation matrix P is; 'd' is output as +1/-1   //
-// depending on whether the number of row interchanges was even or odd,      //
-// respectively.                                                             //
-//                                                                           //
-// Return true if the LU decomposition is successfully computed, otherwise,  //
-// return false in case that A is a singular matrix.                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N)
-{
-  REAL scales[4];
-  REAL pivot, biggest, mult, tempf;
-  int pivotindex = 0;
-  int i, j, k;
-
-  *d = 1.0;                                      // No row interchanges yet.
-
-  for (i = N; i < n + N; i++) {                             // For each row.
-    // Find the largest element in each row for row equilibration
-    biggest = 0.0;
-    for (j = N; j < n + N; j++)
-      if (biggest < (tempf = fabs(lu[i][j])))
-        biggest  = tempf;
-    if (biggest != 0.0)
-      scales[i] = 1.0 / biggest;
-    else {
-      scales[i] = 0.0;
-      return false;                            // Zero row: singular matrix.
-    }
-    ps[i] = i;                                 // Initialize pivot sequence.
-  }
-
-  for (k = N; k < n + N - 1; k++) {                      // For each column.
-    // Find the largest element in each column to pivot around.
-    biggest = 0.0;
-    for (i = k; i < n + N; i++) {
-      if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
-        biggest = tempf;
-        pivotindex = i;
-      }
-    }
-    if (biggest == 0.0) {
-      return false;                         // Zero column: singular matrix.
-    }
-    if (pivotindex != k) {                         // Update pivot sequence.
-      j = ps[k];
-      ps[k] = ps[pivotindex];
-      ps[pivotindex] = j;
-      *d = -(*d);                          // ...and change the parity of d.
-    }
-
-    // Pivot, eliminating an extra variable  each time
-    pivot = lu[ps[k]][k];
-    for (i = k + 1; i < n + N; i++) {
-      lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
-      if (mult != 0.0) {
-        for (j = k + 1; j < n + N; j++)
-          lu[ps[i]][j] -= mult * lu[ps[k]][j];
-      }
-    }
-  }
-
-  // (lu[ps[n + N - 1]][n + N - 1] == 0.0) ==> A is singular.
-  return lu[ps[n + N - 1]][n + N - 1] != 0.0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// lu_solve()    Solves the linear equation:  Ax = b,  after the matrix A    //
-//               has been decomposed into the lower and upper triangular     //
-//               matrices L and U, where A = LU.                             //
-//                                                                           //
-// 'lu[N..n+N-1][N..n+N-1]' is input, not as the matrix 'A' but rather as    //
-// its LU decomposition, computed by the routine 'lu_decmp'; 'ps[N..n+N-1]'  //
-// is input as the permutation vector returned by 'lu_decmp';  'b[N..n+N-1]' //
-// is input as the right-hand side vector, and returns with the solution     //
-// vector. 'lu', 'n', and 'ps' are not modified by this routine and can be   //
-// left in place for successive calls with different right-hand sides 'b'.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N)
-{
-  int i, j;
-  REAL X[4], dot;
-
-  for (i = N; i < n + N; i++) X[i] = 0.0;
-
-  // Vector reduction using U triangular matrix.
-  for (i = N; i < n + N; i++) {
-    dot = 0.0;
-    for (j = N; j < i + N; j++)
-      dot += lu[ps[i]][j] * X[j];
-    X[i] = b[ps[i]] - dot;
-  }
-
-  // Back substitution, in L triangular matrix.
-  for (i = n + N - 1; i >= N; i--) {
-    dot = 0.0;
-    for (j = i + 1; j < n + N; j++)
-      dot += lu[ps[i]][j] * X[j];
-    X[i] = (X[i] - dot) / lu[ps[i]][i];
-  }
-
-  for (i = N; i < n + N; i++) b[i] = X[i];
-}
-
-//
-// End of linear algebra functions
-//
-
-//
-// Begin of geometric tests
-//
-
-// All the following routines require the input objects are not degenerate.
-//   i.e., a triangle must has three non-collinear corners; an edge must
-//   has two identical endpoints.  Degenerate cases should have to detect
-//   first and then handled as special cases.
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// edge_vert_col_inter()    Test whether an edge (ab) and a collinear vertex //
-//                          (p) are intersecting or not.                     //
-//                                                                           //
-// Possible cases are p is coincident to a (p = a), or to b (p = b), or p is //
-// inside ab (a < p < b), or outside ab (p < a or p > b). These cases can be //
-// quickly determined by comparing the corresponding coords of a, b, and p   //
-// (which are not all equal).                                                //
-//                                                                           //
-// The return value indicates one of the three cases: DISJOINT, SHAREVERTEX  //
-// (p = a or p = b), and INTERSECT (a < p < b).                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::interresult tetgenmesh::edge_vert_col_inter(REAL* A, REAL* B,
-  REAL* P)
-{
-  int i = 0;
-  do {
-    if (A[i] < B[i]) {
-      if (P[i] < A[i]) {
-        return DISJOINT;
-      } else if (P[i] > A[i]) {
-        if (P[i] < B[i]) {
-          return INTERSECT;
-        } else if (P[i] > B[i]) {
-          return DISJOINT;
-        } else {
-          // assert(P[i] == B[i]);
-          return SHAREVERTEX;
-        }
-      } else {
-        // assert(P[i] == A[i]);
-        return SHAREVERTEX;
-      }
-    } else if (A[i] > B[i]) {
-      if (P[i] < B[i]) {
-        return DISJOINT;
-      } else if (P[i] > B[i]) {
-        if (P[i] < A[i]) {
-          return INTERSECT;
-        } else if (P[i] > A[i]) {
-          return DISJOINT;
-        } else {
-          // assert(P[i] == A[i]);
-          return SHAREVERTEX;
-        }
-      } else {
-        // assert(P[i] == B[i]);
-        return SHAREVERTEX;
-      }
-    }
-    // i-th coordinates are equal, try i+1-th;
-    i++;
-  } while (i < 3);
-  // Should never be here.
-  return DISJOINT;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// edge_edge_cop_inter()    Test whether two coplanar edges (ab, and pq) are //
-//                          intersecting or not.                             //
-//                                                                           //
-// Possible cases are ab and pq are disjointed, or proper intersecting (int- //
-// ersect at a point other than their endpoints), or both collinear and int- //
-// ersecting, or sharing at a common endpoint, or are coincident.            //
-//                                                                           //
-// A reference point R is required, which is exactly not coplanar with these //
-// two edges.  Since the caller knows these two edges are coplanar, it must  //
-// be able to provide (or calculate) such a point.                           //
-//                                                                           //
-// The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
-// SHAREEDGE, and INTERSECT.                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::interresult tetgenmesh:: edge_edge_cop_inter(REAL* A, REAL* B,
-  REAL* P, REAL* Q, REAL* R)
-{
-  REAL s1, s2, s3, s4;
-
-#ifdef SELF_CHECK
-  assert(R != NULL);
-#endif
-  s1 = orient3d(A, B, R, P);
-  s2 = orient3d(A, B, R, Q);
-  if (s1 * s2 > 0.0) {
-    // Both p and q are at the same side of ab.
-    return DISJOINT;
-  }
-  s3 = orient3d(P, Q, R, A);
-  s4 = orient3d(P, Q, R, B);
-  if (s3 * s4 > 0.0) {
-    // Both a and b are at the same side of pq.
-    return DISJOINT;
-  }
-
-  // Possible degenerate cases are:
-  //   (1) Only one of p and q is collinear with ab;
-  //   (2) Both p and q are collinear with ab;
-  //   (3) Only one of a and b is collinear with pq. 
-  enum interresult abp, abq;
-  enum interresult pqa, pqb;
-
-  if (s1 == 0.0) {
-    // p is collinear with ab.
-    abp = edge_vert_col_inter(A, B, P);
-    if (abp == INTERSECT) {
-      // p is inside ab.
-      return INTERSECT;
-    }
-    if (s2 == 0.0) {
-      // q is collinear with ab. Case (2).
-      abq = edge_vert_col_inter(A, B, Q);
-      if (abq == INTERSECT) {
-        // q is inside ab.
-        return INTERSECT;
-      }
-      if (abp == SHAREVERTEX && abq == SHAREVERTEX) {
-        // ab and pq are identical.
-        return SHAREEDGE;
-      }
-      pqa = edge_vert_col_inter(P, Q, A);
-      if (pqa == INTERSECT) {
-        // a is inside pq.
-        return INTERSECT;
-      }
-      pqb = edge_vert_col_inter(P, Q, B);
-      if (pqb == INTERSECT) {
-        // b is inside pq.
-        return INTERSECT;
-      }
-      if (abp == SHAREVERTEX || abq == SHAREVERTEX) {
-        // either p or q is coincident with a or b.
-#ifdef SELF_CHECK
-        // ONLY one case is possible, otherwise, shoule be SHAREEDGE.
-        assert(abp ^ abq);
-#endif
-        return SHAREVERTEX;
-      }
-      // The last case. They are disjointed.
-#ifdef SELF_CHECK
-      assert((abp == DISJOINT) && (abp == abq && abq == pqa && pqa == pqb));
-#endif
-      return DISJOINT;
-    } else {
-      // p is collinear with ab. Case (1).
-#ifdef SELF_CHECK
-      assert(abp == SHAREVERTEX || abp == DISJOINT);
-#endif
-      return abp;
-    }
-  }
-  // p is NOT collinear with ab.
-  if (s2 == 0.0) {
-    // q is collinear with ab. Case (1).
-    abq = edge_vert_col_inter(A, B, Q);
-#ifdef SELF_CHECK
-    assert(abq == SHAREVERTEX || abq == DISJOINT || abq == INTERSECT);
-#endif
-    return abq;
-  }
-
-  // We have found p and q are not collinear with ab. However, it is still
-  //   possible that a or b is collinear with pq (ONLY one of a and b).
-  if (s3 == 0.0) {
-    // a is collinear with pq. Case (3).
-#ifdef SELF_CHECK
-    assert(s4 != 0.0);
-#endif
-    pqa = edge_vert_col_inter(P, Q, A);
-#ifdef SELF_CHECK
-    // This case should have been detected in above.
-    assert(pqa != SHAREVERTEX);
-    assert(pqa == INTERSECT || pqa == DISJOINT);
-#endif
-    return pqa;
-  }
-  if (s4 == 0.0) {
-    // b is collinear with pq. Case (3).
-#ifdef SELF_CHECK
-    assert(s3 != 0.0);
-#endif
-    pqb = edge_vert_col_inter(P, Q, B);
-#ifdef SELF_CHECK
-    // This case should have been detected in above.
-    assert(pqb != SHAREVERTEX);
-    assert(pqb == INTERSECT || pqb == DISJOINT);
-#endif
-    return pqb;
-  }
-
-  // ab and pq are intersecting properly.
-  return INTERSECT;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Notations                                                                 //
-//                                                                           //
-// Let ABC be the plane passes through a, b, and c;  ABC+ be the halfspace   //
-// including the set of all points x, such that orient3d(a, b, c, x) > 0;    //
-// ABC- be the other halfspace, such that for each point x in ABC-,          //
-// orient3d(a, b, c, x) < 0.  For the set of x which are on ABC, orient3d(a, //
-// b, c, x) = 0.                                                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tri_vert_copl_inter()    Test whether a triangle (abc) and a coplanar     //
-//                          point (p) are intersecting or not.               //
-//                                                                           //
-// Possible cases are p is inside abc, or on an edge of, or coincident with  //
-// a vertex of, or outside abc.                                              //
-//                                                                           //
-// A reference point R is required. R is exactly not coplanar with abc and p.//
-// Since the caller knows they are coplanar, it must be able to provide (or  //
-// calculate) such a point.                                                  //
-//                                                                           //
-// The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
-// and INTERSECT.                                                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::interresult tetgenmesh::tri_vert_cop_inter(REAL* A, REAL* B,
-  REAL* C, REAL* P, REAL* R)
-{
-  REAL s1, s2, s3;
-  int sign;
-
-#ifdef SELF_CHECK
-  assert(R != (REAL *) NULL);
-#endif
-  // Adjust the orientation of a, b, c and r, so that we can assume that
-  //   r is strictly in ABC- (i.e., r is above ABC wrt. right-hand rule).
-  s1 = orient3d(A, B, C, R);
-#ifdef SELF_CHECK
-  assert(s1 != 0.0);
-#endif
-  sign = s1 < 0.0 ? 1 : -1;
-
-  // Test starts from here.
-  s1 = orient3d(A, B, R, P) * sign;
-  if (s1 < 0.0) {
-    // p is in ABR-.
-    return DISJOINT;
-  }
-  s2 = orient3d(B, C, R, P) * sign;
-  if (s2 < 0.0) {
-    // p is in BCR-.
-    return DISJOINT;
-  }
-  s3 = orient3d(C, A, R, P) * sign;
-  if (s3 < 0.0) {
-    // p is in CAR-.
-    return DISJOINT;
-  }
-  if (s1 == 0.0) {
-    // p is on ABR.
-    if (s2 == 0.0) {
-      // p is on BCR.
-#ifdef SELF_CHECK
-      assert(s3 > 0.0);
-#endif
-      // p is coincident with b.
-      return SHAREVERTEX;
-    }
-    if (s3 == 0.0) {
-      // p is on CAR.
-      // p is coincident with a.
-      return SHAREVERTEX;
-    }
-    // p is on edge ab.
-    return INTERSECT;
-  }
-  // p is in ABR+.
-  if (s2 == 0.0) {
-    // p is on BCR.
-    if (s3 == 0.0) {
-      // p is on CAR.
-      // p is coincident with c.
-      return SHAREVERTEX;
-    }
-    // p is on edge bc.
-    return INTERSECT;
-  }
-  if (s3 == 0.0) {
-    // p is on CAR.
-    // p is on edge ca.
-    return INTERSECT;
-  }
-
-  // p is strictly inside abc.
-  return INTERSECT;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tri_edge_cop_inter()    Test whether a triangle (abc) and a coplanar edge //
-//                         (pq) are intersecting or not.                     //
-//                                                                           //
-// A reference point R is required. R is exactly not coplanar with abc and   //
-// pq.  Since the caller knows they are coplanar, it must be able to provide //
-// (or calculate) such a point.                                              //
-//                                                                           //
-// The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
-// SHAREEDGE, and INTERSECT.                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::interresult tetgenmesh::tri_edge_cop_inter(REAL* A, REAL* B,
-  REAL* C, REAL* P, REAL* Q, REAL* R)
-{
-  enum interresult abpq, bcpq, capq;
-  enum interresult abcp, abcq;
-
-  // Test if pq is intersecting one of edges of abc.
-  abpq = edge_edge_cop_inter(A, B, P, Q, R);
-  if (abpq == INTERSECT || abpq == SHAREEDGE) {
-    return abpq;
-  }
-  bcpq = edge_edge_cop_inter(B, C, P, Q, R);
-  if (bcpq == INTERSECT || bcpq == SHAREEDGE) {
-    return bcpq;
-  }
-  capq = edge_edge_cop_inter(C, A, P, Q, R);
-  if (capq == INTERSECT || capq == SHAREEDGE) {
-    return capq;
-  }
-  
-  // Test if p and q is inside abc.
-  abcp = tri_vert_cop_inter(A, B, C, P, R);
-  if (abcp == INTERSECT) {
-    return INTERSECT;
-  }
-  abcq = tri_vert_cop_inter(A, B, C, Q, R);
-  if (abcq == INTERSECT) {
-    return INTERSECT;
-  }
-
-  // Combine the test results of edge intersectings and triangle insides
-  //   to detect whether abc and pq are sharing vertex or disjointed.
-  if (abpq == SHAREVERTEX) {
-    // p or q is coincident with a or b.
-#ifdef SELF_CHECK
-    assert(abcp ^ abcq);
-#endif
-    return SHAREVERTEX;
-  }
-  if (bcpq == SHAREVERTEX) {
-    // p or q is coincident with b or c.
-#ifdef SELF_CHECK
-    assert(abcp ^ abcq);
-#endif
-    return SHAREVERTEX;
-  }
-  if (capq == SHAREVERTEX) {
-    // p or q is coincident with c or a.
-#ifdef SELF_CHECK
-    assert(abcp ^ abcq);
-#endif
-    return SHAREVERTEX;
-  }
-
-  // They are disjointed.
-  return DISJOINT;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tri_edge_inter_tail()    Test whether a triangle (abc) and an edge (pq)   //
-//                          are intersecting or not.                         //
-//                                                                           //
-// s1 and s2 are results of pre-performed orientation tests. s1 = orient3d(  //
-// a, b, c, p); s2 = orient3d(a, b, c, q).  To separate this routine from    //
-// tri_edge_inter() can save two orientation tests in tri_tri_inter().       //
-//                                                                           //
-// The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
-// SHAREEDGE, and INTERSECT.                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::interresult tetgenmesh::tri_edge_inter_tail(REAL* A, REAL* B,
-  REAL* C, REAL* P, REAL* Q, REAL s1, REAL s2)
-{
-  REAL s3, s4, s5;
-  int sign;
-
-  if (s1 * s2 > 0.0) {
-    // p, q are at the same halfspace of ABC, no intersection.
-    return DISJOINT;
-  }
-
-  if (s1 * s2 < 0.0) {
-    // p, q are both not on ABC (and not sharing vertices, edges of abc).
-    // Adjust the orientation of a, b, c and p, so that we can assume that
-    //   p is strictly in ABC-, and q is strictly in ABC+.
-    sign = s1 < 0.0 ? 1 : -1;
-    s3 = orient3d(A, B, P, Q) * sign;
-    if (s3 < 0.0) {
-      // q is at ABP-.
-      return DISJOINT;
-    }
-    s4 = orient3d(B, C, P, Q) * sign;
-    if (s4 < 0.0) {
-      // q is at BCP-.
-      return DISJOINT;
-    }
-    s5 = orient3d(C, A, P, Q) * sign;
-    if (s5 < 0.0) {
-      // q is at CAP-.
-      return DISJOINT;
-    }
-    if (s3 == 0.0) {
-      // q is on ABP.
-      if (s4 == 0.0) {
-        // q is on BCP (and q must in CAP+).
-#ifdef SELF_CHECK
-        assert(s5 > 0.0); 
-#endif
-        // pq intersects abc at vertex b.
-        return SHAREVERTEX;
-      }
-      if (s5 == 0.0) {
-        // q is on CAP (and q must in BCP+).
-        // pq intersects abc at vertex a.
-        return SHAREVERTEX;
-      }
-      // q in both BCP+ and CAP+.
-      // pq crosses ab properly.
-      return INTERSECT;
-    }
-    // q is in ABP+;
-    if (s4 == 0.0) {
-      // q is on BCP.
-      if (s5 == 0.0) {
-        // q is on CAP.
-        // pq intersects abc at vertex c.
-        return SHAREVERTEX;
-      }
-      // pq crosses bc properly.
-      return INTERSECT;
-    }
-    // q is in BCP+;
-    if (s5 == 0.0) {
-      // q is on CAP.
-      // pq crosses ca properly.
-      return INTERSECT;
-    }
-    // q is in CAP+;
-    // pq crosses abc properly.
-    return INTERSECT;
-  }
-
-  if (s1 != 0.0 || s2 != 0.0) {
-    // Either p or q is coplanar with abc. ONLY one of them is possible.
-    if (s1 == 0.0) {
-      // p is coplanar with abc, q can be used as reference point.
-#ifdef SELF_CHECK
-      assert(s2 != 0.0);
-#endif
-      return tri_vert_cop_inter(A, B, C, P, Q);
-    } else {
-      // q is coplanar with abc, p can be used as reference point.
-#ifdef SELF_CHECK
-      assert(s2 == 0.0);
-#endif
-      return tri_vert_cop_inter(A, B, C, Q, P);
-    }
-  }
-
-  // pq is coplanar with abc.  Calculate a point which is exactly not
-  //   coplanar with a, b, and c.
-  REAL R[3], N[3];
-  REAL ax, ay, az, bx, by, bz;
-  
-  ax = A[0] - B[0];
-  ay = A[1] - B[1];
-  az = A[2] - B[2];
-  bx = A[0] - C[0];
-  by = A[1] - C[1];
-  bz = A[2] - C[2];
-  N[0] = ay * bz - by * az;
-  N[1] = az * bx - bz * ax;
-  N[2] = ax * by - bx * ay;
-  // The normal should not be a zero vector (otherwise, abc are collinear).
-#ifdef SELF_CHECK
-  assert((fabs(N[0]) + fabs(N[1]) + fabs(N[2])) > 0.0);
-#endif
-  // The reference point R is lifted from A to the normal direction with
-  //   a distance d = average edge length of the triangle abc.
-  R[0] = N[0] + A[0];
-  R[1] = N[1] + A[1];
-  R[2] = N[2] + A[2];
-  // Becareful the case: if the non-zero component(s) in N is smaller than
-  //   the machine epsilon (i.e., 2^(-16) for double), R will exactly equal
-  //   to A due to the round-off error.  Do check if it is.
-  if (R[0] == A[0] && R[1] == A[1] && R[2] == A[2]) {
-    int i, j;
-    for (i = 0; i < 3; i++) {
-#ifdef SELF_CHECK
-      assert (R[i] == A[i]);
-#endif
-      j = 2;
-      do {
-        if (N[i] > 0.0) {
-          N[i] += (j * macheps);
-        } else {
-          N[i] -= (j * macheps);
-        }
-        R[i] = N[i] + A[i];
-        j *= 2;
-      } while (R[i] == A[i]);
-    }
-  }
-
-  return tri_edge_cop_inter(A, B, C, P, Q, R);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tri_edge_inter()    Test whether a triangle (abc) and an edge (pq) are    //
-//                     intersecting or not.                                  //
-//                                                                           //
-// The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
-// SHAREEDGE, and INTERSECT.                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::interresult tetgenmesh::tri_edge_inter(REAL* A, REAL* B,
-  REAL* C, REAL* P, REAL* Q)
-{
-  REAL s1, s2;
-
-  // Test the locations of p and q with respect to ABC.
-  s1 = orient3d(A, B, C, P);
-  s2 = orient3d(A, B, C, Q);
-
-  return tri_edge_inter_tail(A, B, C, P, Q, s1, s2);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tri_tri_inter()    Test whether two triangle (abc) and (opq) are          //
-//                    intersecting or not.                                   //
-//                                                                           //
-// The return value indicates one of the five cases: DISJOINT, SHAREVERTEX,  //
-// SHAREEDGE, SHAREFACE, and INTERSECT.                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::interresult tetgenmesh::tri_tri_inter(REAL* A, REAL* B,
-  REAL* C, REAL* O, REAL* P, REAL* Q)
-{
-  REAL s_o, s_p, s_q;
-  REAL s_a, s_b, s_c;
-
-  s_o = orient3d(A, B, C, O);
-  s_p = orient3d(A, B, C, P);
-  s_q = orient3d(A, B, C, Q);
-  if ((s_o * s_p > 0.0) && (s_o * s_q > 0.0)) {
-    // o, p, q are all in the same halfspace of ABC.
-    return DISJOINT;
-  }
-
-  s_a = orient3d(O, P, Q, A);
-  s_b = orient3d(O, P, Q, B);
-  s_c = orient3d(O, P, Q, C);
-  if ((s_a * s_b > 0.0) && (s_a * s_c > 0.0)) {
-    // a, b, c are all in the same halfspace of OPQ.
-    return DISJOINT;
-  }
-
-  enum interresult abcop, abcpq, abcqo;
-  int shareedge = 0;
-
-  abcop = tri_edge_inter_tail(A, B, C, O, P, s_o, s_p);
-  if (abcop == INTERSECT) {
-    return INTERSECT;
-  } else if (abcop == SHAREEDGE) {
-    shareedge++;
-  }
-  abcpq = tri_edge_inter_tail(A, B, C, P, Q, s_p, s_q);
-  if (abcpq == INTERSECT) {
-    return INTERSECT;
-  } else if (abcpq == SHAREEDGE) {
-    shareedge++;
-  }
-  abcqo = tri_edge_inter_tail(A, B, C, Q, O, s_q, s_o);
-  if (abcqo == INTERSECT) {
-    return INTERSECT;
-  } else if (abcqo == SHAREEDGE) {
-    shareedge++;
-  }
-  if (shareedge == 3) {
-    // opq are coincident with abc.
-    return SHAREFACE;
-  }
-#ifdef SELF_CHECK
-  // It is only possible either no share edge or one.
-  assert(shareedge == 0 || shareedge == 1);
-#endif
-
-  // Continue to detect whether opq and abc are intersecting or not.
-  enum interresult opqab, opqbc, opqca;
-
-  opqab = tri_edge_inter_tail(O, P, Q, A, B, s_a, s_b);
-  if (opqab == INTERSECT) {
-    return INTERSECT;
-  }
-  opqbc = tri_edge_inter_tail(O, P, Q, B, C, s_b, s_c);
-  if (opqbc == INTERSECT) {
-    return INTERSECT;
-  }
-  opqca = tri_edge_inter_tail(O, P, Q, C, A, s_c, s_a);
-  if (opqca == INTERSECT) {
-    return INTERSECT;
-  }
-
-  // At this point, two triangles are not intersecting and not coincident.
-  //   They may be share an edge, or share a vertex, or disjoint.
-  if (abcop == SHAREEDGE) {
-#ifdef SELF_CHECK
-    assert(abcpq == SHAREVERTEX && abcqo == SHAREVERTEX);
-#endif
-    // op is coincident with an edge of abc.
-    return SHAREEDGE;
-  }
-  if (abcpq == SHAREEDGE) {
-#ifdef SELF_CHECK
-    assert(abcop == SHAREVERTEX && abcqo == SHAREVERTEX);
-#endif
-    // pq is coincident with an edge of abc.
-    return SHAREEDGE;
-  }
-  if (abcqo == SHAREEDGE) {
-#ifdef SELF_CHECK
-    assert(abcop == SHAREVERTEX && abcpq == SHAREVERTEX);
-#endif
-    // qo is coincident with an edge of abc.
-    return SHAREEDGE;
-  }
-
-  // They may share a vertex or disjoint.
-  if (abcop == SHAREVERTEX) {
-    // o or p is coincident with a vertex of abc.
-    if (abcpq == SHAREVERTEX) {
-      // p is the coincident vertex.
-#ifdef SELF_CHECK
-      assert(abcqo != SHAREVERTEX);
-#endif
-    } else {
-      // o is the coincident vertex.
-#ifdef SELF_CHECK
-      assert(abcqo == SHAREVERTEX);
-#endif
-    }
-    return SHAREVERTEX;
-  }
-  if (abcpq == SHAREVERTEX) {
-    // q is the coincident vertex.
-#ifdef SELF_CHECK
-    assert(abcqo == SHAREVERTEX);
-#endif
-    return SHAREVERTEX;
-  }
-
-  // They are disjoint.
-  return DISJOINT;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insphere_sos()    Insphere test with symbolic perturbation.               //
-//                                                                           //
-// The input points a, b, c, and d should be non-coplanar. They must be ord- //
-// ered so that they have a positive orientation (as defined by orient3d()), //
-// or the sign of the result will be reversed.                               //
-//                                                                           //
-// Return a positive value if the point e lies inside the circumsphere of a, //
-// b, c, and d; a negative value if it lies outside.                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL tetgenmesh::insphere_sos(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
-  int ia, int ib, int ic, int id, int ie)
-{
-  REAL det;
-
-  det = insphere(pa, pb, pc, pd, pe);
-  if (det != 0.0) {
-    return det;
-  }
-  
-  // det = 0.0, use symbolic perturbation.
-  REAL *p[5], *tmpp;
-  REAL sign, det_c, det_d;
-  int idx[5], perm, tmp; 
-  int n, i, j; 
-
-  p[0] = pa; idx[0] = ia;
-  p[1] = pb; idx[1] = ib;
-  p[2] = pc; idx[2] = ic;
-  p[3] = pd; idx[3] = id;
-  p[4] = pe; idx[4] = ie;
-
-  // Bubble sort the points by the increasing order of the indices.
-  n = 5;
-  perm = 0; // The number of total swaps.
-  for (i = 0; i < n - 1; i++) {
-    for (j = 0; j < n - 1 - i; j++) {
-      if (idx[j + 1] < idx[j]) {  // compare the two neighbors.
-        tmp = idx[j];         // swap idx[j] and idx[j + 1]
-        idx[j] = idx[j + 1];
-        idx[j + 1] = tmp;
-        tmpp = p[j];         // swap p[j] and p[j + 1]
-        p[j] = p[j + 1];
-        p[j + 1] = tmpp;
-        perm++;
-      }
-    }
-  }
-
-  sign = (perm % 2 == 0) ? 1.0 : -1.0; 
-  det_c = orient3d(p[1], p[2], p[3], p[4]); // orient3d(b, c, d, e)
-  if (det_c != 0.0) {
-    return sign * det_c;
-  }
-  det_d = orient3d(p[0], p[2], p[3], p[4]); // orient3d(a, c, d, e)
-  return -sign * det_d;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// iscollinear()    Check if three points are approximately collinear.       //
-//                                                                           //
-// 'eps' is a relative error tolerance.  The collinearity is determined by   //
-// the value q = cos(theta), where theta is the angle between two vectors    //
-// A->B and A->C.  They're collinear if 1.0 - q <= epspp.                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::iscollinear(REAL* A, REAL* B, REAL* C, REAL eps)
-{
-  REAL abx, aby, abz;
-  REAL acx, acy, acz;
-  REAL Lv, Lw, dd;
-  REAL d, q;
-
-  // Limit of two closed points.
-  q = longest * eps;
-  q *= q;
-
-  abx = A[0] - B[0];
-  aby = A[1] - B[1];
-  abz = A[2] - B[2];
-  acx = A[0] - C[0];
-  acy = A[1] - C[1];
-  acz = A[2] - C[2];
-  Lv = abx * abx + aby * aby + abz * abz;
-  // Is AB (nearly) indentical?
-  if (Lv < q) return true;
-  Lw = acx * acx + acy * acy + acz * acz;
-  // Is AC (nearly) indentical?
-  if (Lw < q) return true;
-  dd = abx * acx + aby * acy + abz * acz;
-  
-  d = (dd * dd) / (Lv * Lw);
-  if (d > 1.0) d = 1.0; // Rounding.
-  q = 1.0 - sqrt(d); // Notice 0 < q < 1.0.
-  
-  return q <= eps;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// iscoplanar()    Check if four points are approximately coplanar.          //
-//                                                                           //
-// 'vol6' is six times of the signed volume of the tetrahedron formed by the //
-// four points. 'eps' is the relative error tolerance.  The coplanarity is   //
-// determined by the value: q = fabs(vol6) / L^3,  where L is the average    //
-// edge length of the tet. They're coplanar if q <= eps.                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::
-iscoplanar(REAL* k, REAL* l, REAL* m, REAL* n, REAL vol6, REAL eps)
-{
-  REAL L, q;
-  REAL x, y, z;  
-
-  if (vol6 == 0.0) return true;
-
-  x = k[0] - l[0];
-  y = k[1] - l[1];
-  z = k[2] - l[2];
-  L = sqrt(x * x + y * y + z * z);
-  x = l[0] - m[0];
-  y = l[1] - m[1];
-  z = l[2] - m[2];
-  L += sqrt(x * x + y * y + z * z);
-  x = m[0] - k[0];
-  y = m[1] - k[1];
-  z = m[2] - k[2];
-  L += sqrt(x * x + y * y + z * z);
-  x = k[0] - n[0];
-  y = k[1] - n[1];
-  z = k[2] - n[2];
-  L += sqrt(x * x + y * y + z * z);
-  x = l[0] - n[0];
-  y = l[1] - n[1];
-  z = l[2] - n[2];
-  L += sqrt(x * x + y * y + z * z);
-  x = m[0] - n[0];
-  y = m[1] - n[1];
-  z = m[2] - n[2];
-  L += sqrt(x * x + y * y + z * z);
-#ifdef SELF_CHECK
-  assert(L > 0.0);
-#endif
-  L /= 6.0;
-  q = fabs(vol6) / (L * L * L);
-  
-  return q <= eps;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// iscospheric()    Check if five points are approximately coplanar.         //
-//                                                                           //
-// 'vol24' is the 24 times of the signed volume of the 4-dimensional simplex //
-// formed by the five points. 'eps' is the relative tolerance. The cosphere  //
-// case is determined by the value: q = fabs(vol24) / L^4,  where L is the   //
-// average edge length of the simplex. They're cosphere if q <= eps.         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::
-iscospheric(REAL* k, REAL* l, REAL* m, REAL* n, REAL* o, REAL vol24, REAL eps)
-{
-  REAL L, q;
-
-  // A 4D simplex has 10 edges.
-  L = distance(k, l);
-  L += distance(l, m);
-  L += distance(m, k);
-  L += distance(k, n);
-  L += distance(l, n);
-  L += distance(m, n);
-  L += distance(k, o);
-  L += distance(l, o);
-  L += distance(m, o);
-  L += distance(n, o);
-#ifdef SELF_CHECK
-  assert(L > 0.0);
-#endif
-  L /= 10.0;
-  q = fabs(vol24) / (L * L * L * L);
-
-  return q < eps;
-}
-
-//
-// End of geometric tests
-//
-
-//
-// Begin of Geometric quantities calculators
-//
-
-// distance() computs the Euclidean distance between two points.
-inline REAL tetgenmesh::distance(REAL* p1, REAL* p2)
-{
-  return sqrt((p2[0] - p1[0]) * (p2[0] - p1[0]) +
-              (p2[1] - p1[1]) * (p2[1] - p1[1]) +
-              (p2[2] - p1[2]) * (p2[2] - p1[2]));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// shortdistance()    Returns the shortest distance from point p to a line   //
-//                    defined by two points e1 and e2.                       //
-//                                                                           //
-// First compute the projection length l_p of the vector v1 = p - e1 along   //
-// the vector v2 = e2 - e1. Then Pythagoras' Theorem is used to compute the  //
-// shortest distance.                                                        //
-//                                                                           //
-// This routine allows that p is collinear with the line. In this case, the  //
-// return value is zero. The two points e1 and e2 should not be identical.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2)
-{
-  REAL v1[3], v2[3];
-  REAL len, l_p;
-
-  v1[0] = e2[0] - e1[0];
-  v1[1] = e2[1] - e1[1];
-  v1[2] = e2[2] - e1[2];
-  v2[0] = p[0] - e1[0];
-  v2[1] = p[1] - e1[1];
-  v2[2] = p[2] - e1[2];
-
-  len = sqrt(dot(v1, v1));
-#ifdef SELF_CHECK
-  assert(len != 0.0);
-#endif
-  v1[0] /= len;
-  v1[1] /= len;
-  v1[2] /= len;
-  l_p = dot(v1, v2);
-
-  return sqrt(dot(v2, v2) - l_p * l_p);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// shortdistance()    Returns the shortest distance from point p to a face.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2, REAL* e3)
-{
-  REAL prj[3];
-
-  projpt2face(p, e1, e2, e3, prj);
-  return distance(p, prj);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// interiorangle()    Return the interior angle (0 - 2 * PI) between vectors //
-//                    o->p1 and o->p2.                                       //
-//                                                                           //
-// 'n' is the normal of the plane containing face (o, p1, p2).  The interior //
-// angle is the total angle rotating from o->p1 around n to o->p2.  Exchange //
-// the position of p1 and p2 will get the complement angle of the other one. //
-// i.e., interiorangle(o, p1, p2) = 2 * PI - interiorangle(o, p2, p1).  Set  //
-// 'n' be NULL if you only want the interior angle between 0 - PI.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL tetgenmesh::interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n)
-{
-  REAL v1[3], v2[3], np[3];
-  REAL theta, costheta, lenlen;
-  REAL ori, len1, len2;
-
-  // Get the interior angle (0 - PI) between o->p1, and o->p2.
-  v1[0] = p1[0] - o[0];
-  v1[1] = p1[1] - o[1];
-  v1[2] = p1[2] - o[2];
-  v2[0] = p2[0] - o[0];
-  v2[1] = p2[1] - o[1];
-  v2[2] = p2[2] - o[2];
-  len1 = sqrt(dot(v1, v1));
-  len2 = sqrt(dot(v2, v2));
-  lenlen = len1 * len2;
-#ifdef SELF_CHECK
-  assert(lenlen != 0.0);
-#endif
-  costheta = dot(v1, v2) / lenlen;
-  if (costheta > 1.0) {
-    costheta = 1.0; // Roundoff. 
-  } else if (costheta < -1.0) {
-    costheta = -1.0; // Roundoff. 
-  }
-  theta = acos(costheta);
-  if (n != NULL) {
-    // Get a point above the face (o, p1, p2);
-    np[0] = o[0] + n[0];
-    np[1] = o[1] + n[1];
-    np[2] = o[2] + n[2];
-    // Adjust theta (0 - 2 * PI).
-    ori = orient3d(p1, o, np, p2);
-    if (ori > 0.0) {
-      theta = 2 * PI - theta;
-    }
-  }
-
-  return theta;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// projpt2edge()    Return the projection point from a point to an edge.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj)
-{
-  REAL v1[3], v2[3];
-  REAL len, l_p;
-
-  v1[0] = e2[0] - e1[0];
-  v1[1] = e2[1] - e1[1];
-  v1[2] = e2[2] - e1[2];
-  v2[0] = p[0] - e1[0];
-  v2[1] = p[1] - e1[1];
-  v2[2] = p[2] - e1[2];
-
-  len = sqrt(dot(v1, v1));
-#ifdef SELF_CHECK
-  assert(len != 0.0);
-#endif
-  v1[0] /= len;
-  v1[1] /= len;
-  v1[2] /= len;
-  l_p = dot(v1, v2);
-
-  prj[0] = e1[0] + l_p * v1[0];
-  prj[1] = e1[1] + l_p * v1[1];
-  prj[2] = e1[2] + l_p * v1[2];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// projpt2face()    Return the projection point from a point to a face.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj)
-{
-  REAL fnormal[3], v1[3];
-  REAL len, dist;
-
-  // Get the unit face normal.
-  facenormal(f1, f2, f3, fnormal, &len);
-#ifdef SELF_CHECK
-  assert(len > 0.0);
-#endif
-  fnormal[0] /= len;
-  fnormal[1] /= len;
-  fnormal[2] /= len;
-  // Get the vector v1 = |p - f1|.
-  v1[0] = p[0] - f1[0];
-  v1[1] = p[1] - f1[1];
-  v1[2] = p[2] - f1[2];
-  // Get the project distance.
-  dist = dot(fnormal, v1);
-  
-  // Get the project point.
-  prj[0] = p[0] - dist * fnormal[0];
-  prj[1] = p[1] - dist * fnormal[1];
-  prj[2] = p[2] - dist * fnormal[2];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// facenormal()    Calculate the normal of a face given by three points.     //
-//                                                                           //
-// In general, the face normal can be calculate by the cross product of any  //
-// pair of the three edge vectors.  However, if the three points are nearly  //
-// collinear, the rounding error may harm the result. To choose a good pair  //
-// of vectors is helpful to reduce the error.                                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::facenormal(REAL* pa, REAL* pb, REAL* pc, REAL* n, REAL* nlen)
-{
-  REAL v1[3], v2[3];
-
-  v1[0] = pb[0] - pa[0];
-  v1[1] = pb[1] - pa[1];
-  v1[2] = pb[2] - pa[2];
-  v2[0] = pc[0] - pa[0];
-  v2[1] = pc[1] - pa[1];
-  v2[2] = pc[2] - pa[2];
-
-  cross(v1, v2, n);
-  if (nlen != (REAL *) NULL) {
-    *nlen = sqrt(dot(n, n));
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// edgeorthonormal()    Return the unit normal of an edge in a given plane.  //
-//                                                                           //
-// The edge is from e1 to e2,  the plane is defined by given an additional   //
-// point op, which is non-collinear with the edge.  In addition, the side of //
-// the edge in which op lies defines the positive position of the normal.    //
-//                                                                           //
-// Let v1 be the unit vector from e1 to e2, v2 be the unit edge vector from  //
-// e1 to op, fn be the unit face normal calculated by fn = v1 x v2. Then the //
-// unit edge normal of e1e2 pointing to op is n = fn x v1.  Note, we should  //
-// not change the position of fn and v1, otherwise, we get the edge normal   //
-// pointing to the other side of op.                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::edgeorthonormal(REAL* e1, REAL* e2, REAL* op, REAL* n)
-{
-  REAL v1[3], v2[3], fn[3];
-  REAL len;
-
-  // Get the edge vector v1.
-  v1[0] = e2[0] - e1[0];
-  v1[1] = e2[1] - e1[1];
-  v1[2] = e2[2] - e1[2];
-  // Get the edge vector v2.
-  v2[0] = op[0] - e1[0];
-  v2[1] = op[1] - e1[1];
-  v2[2] = op[2] - e1[2];
-  // Get the face normal fn = v1 x v2.
-  cross(v1, v2, fn);
-  // Get the edge normal n pointing to op. n = fn x v1.
-  cross(fn, v1, n);
-  // Normalize the vector.
-  len = sqrt(dot(n, n));
-  n[0] /= len;
-  n[1] /= len;
-  n[2] /= len;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// facedihedral()    Return the dihedral angle (in radian) between two       //
-//                   adjoining faces.                                        //
-//                                                                           //
-// 'pa', 'pb' are the shared edge of these two faces, 'pc1', and 'pc2' are   //
-// apexes of these two faces.  Return the angle (between 0 to 2*pi) between  //
-// the normal of face (pa, pb, pc1) and normal of face (pa, pb, pc2).        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL tetgenmesh::facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2)
-{
-  REAL n1[3], n2[3];
-  REAL n1len, n2len;
-  REAL costheta, ori;
-  REAL theta;
-
-  facenormal(pa, pb, pc1, n1, &n1len);
-  facenormal(pa, pb, pc2, n2, &n2len);
-  costheta = dot(n1, n2) / (n1len * n2len);
-  // Be careful rounding error!
-  if (costheta > 1.0) {
-    costheta = 1.0;
-  } else if (costheta < -1.0) {
-    costheta = -1.0;
-  }
-  theta = acos(costheta);
-  ori = orient3d(pa, pb, pc1, pc2);
-  if (ori > 0.0) {
-    theta = 2 * PI - theta;
-  }
-
-  return theta;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetalldihedral()    Get all (six) dihedral angles of a tet.               //
-//                                                                           //
-// The tet is given by its four corners a, b, c, and d. If 'cosdd' is not    //
-// NULL, it returns the cosines of the 6 dihedral angles, the corresponding  //
-// edges are: ab, bc, ca, ad, bd, and cd. If 'cosmaxd' (or 'cosmind') is not //
-// NULL, it returns the cosine of the maximal (or minimal) dihedral angle.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::tetalldihedral(point pa, point pb, point pc, point pd,
-  REAL* cosdd, REAL* cosmaxd, REAL* cosmind)
-{
-  REAL N[4][3], cosd, len;
-  int f1, f2, i, j;
-
-  // Get four normals of faces of the tet.
-  tetallnormal(pa, pb, pc, pd, N, NULL);
-  // Normalize the normals.
-  for (i = 0; i < 4; i++) {
-    len = sqrt(dot(N[i], N[i]));
-    if (len != 0.0) {
-      for (j = 0; j < 3; j++) N[i][j] /= len;
-    }
-  }
-
-  for (i = 0; i < 6; i++) {
-    switch (i) {
-    case 0: f1 = 2; f2 = 3; break; // edge ab.
-    case 1: f1 = 0; f2 = 3; break; // edge bc.
-    case 2: f1 = 1; f2 = 3; break; // edge ca.
-    case 3: f1 = 1; f2 = 2; break; // edge ad.
-    case 4: f1 = 2; f2 = 0; break; // edge bd.
-    case 5: f1 = 0; f2 = 1; break; // edge cd.
-    }
-    cosd = -dot(N[f1], N[f2]);
-    if (cosdd) cosdd[i] = cosd;
-    if (i == 0) {
-      if (cosmaxd) *cosmaxd = cosd;
-      if (cosmind) *cosmind = cosd;
-    } else {
-      if (cosmaxd) *cosmaxd = cosd < *cosmaxd ? cosd : *cosmaxd;
-      if (cosmind) *cosmind = cosd > *cosmind ? cosd : *cosmind;
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetallnormal()    Get the in-noramls of the four faces of a given tet.    //
-//                                                                           //
-// Let tet be abcd. N[4][3] returns the four normals, which are: N[0] cbd,   //
-// N[1] acd, N[2] bad, N[3] abc. These normals are unnormalized.             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::tetallnormal(point pa, point pb, point pc, point pd,
-  REAL N[4][3], REAL* volume)
-{
-  REAL A[4][4], rhs[4], D;
-  int indx[4];
-  int i, j;
-
-  // get the entries of A[3][3].
-  for (i = 0; i < 3; i++) A[0][i] = pa[i] - pd[i];  // d->a vec
-  for (i = 0; i < 3; i++) A[1][i] = pb[i] - pd[i];  // d->b vec
-  for (i = 0; i < 3; i++) A[2][i] = pc[i] - pd[i];  // d->c vec
-  // Compute the inverse of matrix A, to get 3 normals of the 4 faces.
-  lu_decmp(A, 3, indx, &D, 0);     // Decompose the matrix just once.
-  if (volume != NULL) {
-    // Get the volume of the tet.
-    *volume = fabs((A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2])) / 6.0;
-  }
-  for (j = 0; j < 3; j++) {
-    for (i = 0; i < 3; i++) rhs[i] = 0.0;
-    rhs[j] = 1.0;  // Positive means the inside direction
-    lu_solve(A, 3, indx, rhs, 0);
-    for (i = 0; i < 3; i++) N[j][i] = rhs[i];
-  }
-  // Get the fourth normal by summing up the first three.
-  for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetaspectratio()    Calculate the aspect ratio of the tetrahedron.        //
-//                                                                           //
-// The aspect ratio of a tet is R/h, where R is the circumradius and h is    //
-// the shortest height of the tet.                                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL tetgenmesh::tetaspectratio(point pa, point pb, point pc, point pd)
-{
-  REAL vda[3], vdb[3], vdc[3];
-  REAL N[4][3], A[4][4], rhs[4], D;
-  REAL H[4], volume, radius2, minheightinv;
-  int indx[4];
-  int i, j; 
-
-  // Set the matrix A = [vda, vdb, vdc]^T.
-  for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
-  for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
-  for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
-  // Lu-decompose the matrix A.
-  lu_decmp(A, 3, indx, &D, 0);
-  // Get the volume of abcd.
-  volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
-  // Check if it is zero.
-  if (volume == 0.0) return 1.0e+200; // A degenerate tet.
-  // if (volume < 0.0) volume = -volume;
-  // Check the radiu-edge ratio of the tet.
-  rhs[0] = 0.5 * dot(vda, vda);
-  rhs[1] = 0.5 * dot(vdb, vdb);
-  rhs[2] = 0.5 * dot(vdc, vdc);
-  lu_solve(A, 3, indx, rhs, 0);
-  // Get the circumcenter.
-  // for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
-  // Get the square of the circumradius.
-  radius2 = dot(rhs, rhs);
-
-  // Compute the 4 face normals (N[0], ..., N[3]).
-  for (j = 0; j < 3; j++) {
-    for (i = 0; i < 3; i++) rhs[i] = 0.0;
-    rhs[j] = 1.0;  // Positive means the inside direction
-    lu_solve(A, 3, indx, rhs, 0);
-    for (i = 0; i < 3; i++) N[j][i] = rhs[i];
-  }
-  // Get the fourth normal by summing up the first three.
-  for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
-  // Normalized the normals.
-  for (i = 0; i < 4; i++) {
-    // H[i] is the inverse of the height of its corresponding face.
-    H[i] = sqrt(dot(N[i], N[i]));
-    // if (H[i] > 0.0) {
-    //   for (j = 0; j < 3; j++) N[i][j] /= H[i];
-    // }
-  }
-  // Get the radius of the inscribed sphere.
-  // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]);
-  // Get the biggest H[i] (corresponding to the smallest height).
-  minheightinv = H[0];
-  for (i = 1; i < 3; i++) {
-    if (H[i] > minheightinv) minheightinv = H[i];
-  }
-
-  return sqrt(radius2) * minheightinv;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// circumsphere()    Calculate the smallest circumsphere (center and radius) //
-//                   of the given three or four points.                      //
-//                                                                           //
-// The circumsphere of four points (a tetrahedron) is unique if they are not //
-// degenerate. If 'pd = NULL', the smallest circumsphere of three points is  //
-// the diametral sphere of the triangle if they are not degenerate.          //
-//                                                                           //
-// Return TRUE if the input points are not degenerate and the circumcenter   //
-// and circumradius are returned in 'cent' and 'radius' respectively if they //
-// are not NULLs. Otherwise, return FALSE indicated the points are degenrate.//
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::
-circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* cent, REAL* radius)
-{
-  REAL A[4][4], rhs[4], D;
-  int indx[4];
-
-  // Compute the coefficient matrix A (3x3).
-  A[0][0] = pb[0] - pa[0];
-  A[0][1] = pb[1] - pa[1];
-  A[0][2] = pb[2] - pa[2];
-  A[1][0] = pc[0] - pa[0];
-  A[1][1] = pc[1] - pa[1];
-  A[1][2] = pc[2] - pa[2];
-  if (pd != NULL) {
-    A[2][0] = pd[0] - pa[0];
-    A[2][1] = pd[1] - pa[1]; 
-    A[2][2] = pd[2] - pa[2];
-  } else {
-    cross(A[0], A[1], A[2]);
-  }
-
-  // Compute the right hand side vector b (3x1).
-  rhs[0] = 0.5 * dot(A[0], A[0]);
-  rhs[1] = 0.5 * dot(A[1], A[1]);
-  if (pd != NULL) {
-    rhs[2] = 0.5 * dot(A[2], A[2]);
-  } else {
-    rhs[2] = 0.0;
-  }
-
-  // Solve the 3 by 3 equations use LU decomposition with partial pivoting
-  //   and backward and forward substitute..
-  if (!lu_decmp(A, 3, indx, &D, 0)) {
-    if (radius != (REAL *) NULL) *radius = 0.0;
-    return false;
-  }    
-  lu_solve(A, 3, indx, rhs, 0);
-  if (cent != (REAL *) NULL) {
-    cent[0] = pa[0] + rhs[0];
-    cent[1] = pa[1] + rhs[1];
-    cent[2] = pa[2] + rhs[2];
-  }
-  if (radius != (REAL *) NULL) {
-    *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
-  }
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// inscribedsphere()    Compute the radius and center of the biggest         //
-//                      inscribed sphere of a given tetrahedron.             //
-//                                                                           //
-// The tetrahedron is given by its four points, it must not be degenerate.   //
-// The center and radius are returned in 'cent' and 'radius' respectively if //
-// they are not NULLs.                                                       //
-//                                                                           //
-// Geometrical fact. For any simplex in d dimension,                         //
-//   r/h1 + r/h2 + ... r/hn = 1 (n <= d + 1);                                //
-// where r is the radius of inscribed ball, and h is the height of each side //
-// of the simplex. The value of 'r/h' is just the barycenter coordinates of  //
-// each vertex of the simplex. Therefore, we can compute the radius and      //
-// center of the smallest inscribed ball as following equations:             //
-//   r = 1.0 / (1/h1 + 1/h2 + ... + 1/hn);          (1)                      //
-//   C = r/h1 * P1 + r/h2 * P2 + ... + r/hn * Pn;   (2)                      //
-// where C is the vector of center, P1, P2, .. Pn are vectors of vertices.   //
-// Here (2) contains n linear equations with n variables.  (h, P) must be a  //
-// pair, h is the height from P to its opposite face.                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::inscribedsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
-  REAL* cent, REAL* radius)
-{
-  REAL N[4][3], H[4]; // Normals (colume vectors) and heights of each face.
-  REAL rd;
-  int i;  
-
-  // Get the all normals of the tet.
-  tetallnormal(pa, pb, pc, pd, N, NULL);
-  for (i = 0; i < 4; i++) {
-    // H[i] is the inverse of height of its corresponding face.
-    H[i] = sqrt(dot(N[i], N[i]));
-  }
-  // Compute the radius use eq. (1).
-  rd = 1.0 / (H[0] + H[1] + H[2] + H[3]);
-  if (radius != (REAL*) NULL) *radius = rd;
-  if (cent != (REAL*) NULL) {
-    // Compute the center use eq. (2).
-    cent[0] = rd * (H[0] * pa[0] + H[1] * pb[0] + H[2] * pc[0] + H[3] * pd[0]);
-    cent[1] = rd * (H[0] * pa[1] + H[1] * pb[1] + H[2] * pc[1] + H[3] * pd[1]);
-    cent[2] = rd * (H[0] * pa[2] + H[1] * pb[2] + H[2] * pc[2] + H[3] * pd[2]);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// rotatepoint()    Create a point by rotating an existing point.            //
-//                                                                           //
-// Create a 3D point by rotating point 'p' with an angle 'rotangle' (in arc  //
-// degree) around a rotating axis given by a vector from point 'p1' to 'p2'. //
-// The rotation is according with right-hand rule, i.e., use your right-hand //
-// to grab the axis with your thumber pointing to its positive direction,    //
-// your fingers indicate the rotating direction.                             //
-//                                                                           //
-// The rotating steps are the following:                                     //
-//   1. Translate vector 'p1->p2' to origin, M1;                             //
-//   2. Rotate vector around the Y-axis until it lies in the YZ plane, M2;   //
-//   3. Rotate vector around the X-axis until it lies on the Z axis, M3;     //
-//   4. Perform the rotation of 'p' around the z-axis, M4;                   //
-//   5. Undo Step 3, M5;                                                     //
-//   6. Undo Step 2, M6;                                                     //
-//   7. Undo Step 1, M7;                                                     //
-// Use matrix multiplication to combine the above sequences, we get:         //
-//   p0' = T * p0, where T = M7 * M6 * M5 * M4 * M3 * M2 * M1                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::rotatepoint(REAL* p, REAL rotangle, REAL* p1, REAL* p2)
-{
-  REAL T[4][4], pp0[4], p0t[4], p2t[4];
-  REAL roty, rotx, alphaR, projlen;
-  REAL dx, dy, dz;
-
-  initm44(1, 0, 0, -p1[0],
-          0, 1, 0, -p1[1],
-          0, 0, 1, -p1[2],
-          0, 0, 0, 1, T);
-  pp0[0] = p[0]; pp0[1] = p[1]; pp0[2] = p[2]; pp0[3] = 1.0;
-  m4xv4(p0t, T, pp0); // Step 1
-  pp0[0] = p2[0]; pp0[1] = p2[1]; pp0[2] = p2[2]; pp0[3] = 1.0;
-  m4xv4(p2t, T, pp0); // Step 1
-
-  // Get the rotation angle around y-axis;
-  dx = p2t[0];
-  dz = p2t[2];
-  projlen = sqrt(dx * dx + dz * dz);
-  if (projlen <= (b->epsilon * 1e-2) * longest) {
-    roty = 0;
-  } else {
-    roty = acos(dz / projlen);
-    if (dx < 0) {
-      roty = -roty;
-    }
-  }
-
-  initm44(cos(-roty), 0, sin(-roty), 0,
-          0, 1, 0, 0,
-          -sin(-roty), 0, cos(-roty), 0,
-          0, 0, 0, 1, T);
-  pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
-  m4xv4(p0t, T, pp0); // Step 2
-  pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
-  m4xv4(p2t, T, pp0); // Step 2
-
-  // Get the rotation angle around x-axis
-  dy = p2t[1];
-  dz = p2t[2];
-  projlen = sqrt(dy * dy + dz * dz);
-  if (projlen <= (b->epsilon * 1e-2) * longest) {
-    rotx = 0;
-  } else {
-    rotx = acos(dz / projlen);
-    if (dy < 0) {
-      rotx = -rotx;
-    }
-  }
-    
-  initm44(1, 0, 0, 0,
-          0, cos(rotx), -sin(rotx), 0,
-          0, sin(rotx), cos(rotx), 0,
-          0, 0, 0, 1, T);
-  pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
-  m4xv4(p0t, T, pp0); // Step 3
-  // pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
-  // m4xv4(p2t, T, pp0); // Step 3
-
-  alphaR = rotangle;
-  initm44(cos(alphaR), -sin(alphaR), 0, 0,
-          sin(alphaR), cos(alphaR), 0, 0,
-          0, 0, 1, 0,
-          0, 0, 0, 1, T);
-  pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
-  m4xv4(p0t, T, pp0); // Step 4
-
-  initm44(1, 0, 0, 0,
-          0, cos(-rotx), -sin(-rotx), 0,
-          0, sin(-rotx), cos(-rotx), 0,
-          0, 0, 0, 1, T);
-  pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
-  m4xv4(p0t, T, pp0); // Step 5
-
-  initm44(cos(roty), 0, sin(roty), 0,
-          0, 1, 0, 0,
-          -sin(roty), 0, cos(roty), 0,
-          0, 0, 0, 1, T);
-  pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
-  m4xv4(p0t, T, pp0); // Step 6
-
-  initm44(1, 0, 0, p1[0],
-          0, 1, 0, p1[1],
-          0, 0, 1, p1[2],
-          0, 0, 0, 1, T);
-  pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
-  m4xv4(p0t, T, pp0); // Step 7  
-
-  p[0] = p0t[0];
-  p[1] = p0t[1];
-  p[2] = p0t[2];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// spherelineint()    3D line sphere (or circle) intersection.               //
-//                                                                           //
-// The line is given by two points p1, and p2, the sphere is centered at c   //
-// with radius r.  This function returns a pointer array p which first index //
-// indicates the number of intersection point, followed by coordinate pairs. //
-//                                                                           //
-// The following code are adapted from: http://astronomy.swin.edu.au/pbourke //
-// /geometry/sphereline. Paul Bourke pbourke@swin.edu.au                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::spherelineint(REAL* p1, REAL* p2, REAL* C, REAL R, REAL p[7])
-{
-  REAL x1, y1, z1; //  P1 coordinates (point of line)
-  REAL x2, y2, z2; //  P2 coordinates (point of line)
-  REAL x3, y3, z3, r; //  P3 coordinates and radius (sphere)
-  REAL a, b, c, mu, i ;
-
-  x1 = p1[0]; y1 = p1[1]; z1 = p1[2];
-  x2 = p2[0]; y2 = p2[1]; z2 = p2[2];
-  x3 = C[0];  y3 = C[1];  z3 = C[2];
-  r = R;
-  
-  a =   (x2 - x1) * (x2 - x1) 
-      + (y2 - y1) * (y2 - y1) 
-      + (z2 - z1) * (z2 - z1);
-  b = 2 * ( (x2 - x1) * (x1 - x3)
-          + (y2 - y1) * (y1 - y3)
-          + (z2 - z1) * (z1 - z3) ) ;
-  c =   (x3 * x3) + (y3 * y3) + (z3 * z3)
-      + (x1 * x1) + (y1 * y1) + (z1 * z1)
-      - 2 * (x3 * x1 + y3 * y1 + z3 * z1) - (r * r) ;
-  i = b * b - 4 * a * c ;
-
-  if (i < 0.0) {
-    // no intersection
-    p[0] = 0.0;
-  } else if (i == 0.0) {
-    // one intersection
-    p[0] = 1.0;
-    mu = -b / (2 * a) ;
-    p[1] = x1 + mu * (x2 - x1);
-    p[2] = y1 + mu * (y2 - y1);
-    p[3] = z1 + mu * (z2 - z1);
-  } else {
-    // two intersections
-    p[0] = 2.0;
-    // first intersection
-    mu = (-b + sqrt((b * b) - 4 * a * c)) / (2 * a);
-    p[1] = x1 + mu * (x2 - x1);
-    p[2] = y1 + mu * (y2 - y1);
-    p[3] = z1 + mu * (z2 - z1);
-    // second intersection
-    mu = (-b - sqrt((b * b) - 4 * a * c)) / (2 * a);
-    p[4] = x1 + mu * (x2 - x1);
-    p[5] = y1 + mu * (y2 - y1);
-    p[6] = z1 + mu * (z2 - z1);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// linelineint()    Calculate the shortest line between two lines in 3D.     //
-//                                                                           //
-// Two 3D lines generally don't intersect at a point, they may be parallel ( //
-// no intersections), or coincident (infinite intersections) but most often  //
-// only their projections onto a plane intersect. If they don't exactly int- //
-// ersect at a point they can be connected by a line segment, the shortest   //
-// segment is unique and is often considered to be their intersection in 3D. //
-//                                                                           //
-// The following code are adapted from: http://astronomy.swin.edu.au/pbourke //
-// /geometry/lineline3d. Paul Bourke pbourke@swin.edu.au                     //
-//                                                                           //
-// Calculate the line segment PaPb that is the shortest route between two    //
-// lines P1P2 and P3P4. This function returns a pointer array p which first  //
-// index indicates there exists solution or not, 0 means no solution, 1 meas //
-// has solution followed by two coordinate pairs.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::linelineint(REAL *p1,REAL *p2, REAL *p3, REAL *p4, REAL p[7])
-{
-  REAL p13[3], p43[3], p21[3];
-  REAL d1343, d4321, d1321, d4343, d2121;
-  REAL numer, denom;
-  REAL mua, mub;
-
-  p13[0] = p1[0] - p3[0];
-  p13[1] = p1[1] - p3[1];
-  p13[2] = p1[2] - p3[2];
-  p43[0] = p4[0] - p3[0];
-  p43[1] = p4[1] - p3[1];
-  p43[2] = p4[2] - p3[2];
-  if (p43[0] == 0.0 && p43[1] == 0.0 && p43[2] == 0.0) {
-    p[0] = 0.0;
-    return;
-  }
-
-  p21[0] = p2[0] - p1[0];
-  p21[1] = p2[1] - p1[1];
-  p21[2] = p2[2] - p1[2];
-  if (p21[0] == 0.0 && p21[1] == 0.0 && p21[2] == 0.0) {
-    p[0] = 0.0;
-    return;
-  }
-
-  d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
-  d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
-  d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
-  d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
-  d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
-
-  denom = d2121 * d4343 - d4321 * d4321;
-  if (denom == 0.0) {
-    p[0] = 0.0;
-    return;
-  }
-  numer = d1343 * d4321 - d1321 * d4343;
-  mua = numer / denom;
-  mub = (d1343 + d4321 * mua) / d4343;
-
-  p[0] = 1.0;
-  p[1] = p1[0] + mua * p21[0];
-  p[2] = p1[1] + mua * p21[1];
-  p[3] = p1[2] + mua * p21[2];
-  p[4] = p3[0] + mub * p43[0];
-  p[5] = p3[1] + mub * p43[1];
-  p[6] = p3[2] + mub * p43[2];
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// planelineint()    Calculate the intersection of a line and a plane.       //
-//                                                                           //
-// The equation of a plane (points P are on the plane with normal N and P3   //
-// on the plane) can be written as: N dot (P - P3) = 0. The equation of the  //
-// line (points P on the line passing through P1 and P2) can be written as:  //
-// P = P1 + u (P2 - P1). The intersection of these two occurs when:          //
-//   N dot (P1 + u (P2 - P1)) = N dot P3.                                    //
-// Solving for u gives:                                                      //
-//         N dot (P3 - P1)                                                   //
-//   u = ------------------.                                                 //
-//         N dot (P2 - P1)                                                   //
-// If the denominator is 0 then N (the normal to the plane) is perpendicular //
-// to the line.  Thus the line is either parallel to the plane and there are //
-// no solutions or the line is on the plane in which case there are an infi- //
-// nite number of solutions.                                                 //
-//                                                                           //
-// The plane is given by three points pa, pb, and pc, e1 and e2 defines the  //
-// line. If u is non-zero, The intersection point (if exists) returns in ip. //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
-  REAL* ip, REAL* u)
-{
-  REAL n[3], det, det1;
-
-  // Calculate N.
-  facenormal(pa, pb, pc, n, NULL);
-  // Calculate N dot (e2 - e1).
-  det = n[0] * (e2[0] - e1[0]) + n[1] * (e2[1] - e1[1])
-      + n[2] * (e2[2] - e1[2]);
-  if (det != 0.0) {
-    // Calculate N dot (pa - e1)
-    det1 = n[0] * (pa[0] - e1[0]) + n[1] * (pa[1] - e1[1])
-         + n[2] * (pa[2] - e1[2]);
-    *u = det1 / det;
-    ip[0] = e1[0] + *u * (e2[0] - e1[0]);
-    ip[1] = e1[1] + *u * (e2[1] - e1[1]);
-    ip[2] = e1[2] + *u * (e2[2] - e1[2]);
-  } else {
-    *u = 0.0;
-  }
-}
-
-//
-// End of Geometric quantities calculators
-//
-
-//
-// Begin of memory management routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// 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 tetgenmesh::dummyinit(int tetwords, int shwords)
-{
-  unsigned long alignptr;
-
-  // Set up 'dummytet', the 'tetrahedron' that occupies "outer space".
-  dummytetbase = (tetrahedron *) new char[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 tetrahedra 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 (b->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 char[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;
-    // Initialize the pointer to badface structure.
-    dummysh[11] = (shellface) NULL;
-    // 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;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// initializepools()    Calculate the sizes of the point, tetrahedron, and   //
-//                      subface. Initialize their memory pools.              //
-//                                                                           //
-// This routine also computes the indices 'pointmarkindex', 'point2simindex',//
-// and 'point2pbcptindex' used to find values within each point;  computes   //
-// indices 'highorderindex', 'elemattribindex', and 'volumeboundindex' used  //
-// to find values within each tetrahedron.                                   //
-//                                                                           //
-// There are two types of boundary elements, which are subfaces and subsegs, //
-// they are stored in seperate pools. However, the data structures of them   //
-// are the same.  A subsegment can be regarded as a degenerate subface, i.e.,//
-// one of its three corners is not used. We set the apex of it be 'NULL' to  //
-// distinguish it's a subsegment.                                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::initializepools()
-{
-  enum wordtype wtype;
-  int pointsize, elesize, shsize;
-
-  // Default checkpbc = 0;
-  if ((b->plc || b->refine) && (in->pbcgrouplist != NULL)) {
-    checkpbcs = 1;
-  }
-  // Default varconstraint = 0;
-  if (in->segmentconstraintlist || in->facetconstraintlist) {
-    varconstraint = 1;
-  }
-
-  // The index within each point at which its metric tensor is found. It is
-  //   saved directly after the list of point attributes.
-  pointmtrindex = 3 + in->numberofpointattributes;
-  // Decide the size (1, 3, or 6) of the metric tensor.
-  if (b->metric) {
-    // For '-m' option. A tensor field is provided (*.mtr or *.b.mtr file).
-    if (bgm != (tetgenmesh *) NULL) {
-      // A background mesh is allocated. It may not exist though.
-      sizeoftensor = (bgm->in != (tetgenio *) NULL) ? 
-        bgm->in->numberofpointmtrs : in->numberofpointmtrs;
-    } else {
-      // No given background mesh - Itself is a background mesh.
-      sizeoftensor = in->numberofpointmtrs;
-    }
-    // Make sure sizeoftensor is at least 1.
-    sizeoftensor = (sizeoftensor > 0) ? sizeoftensor : 1; 
-  } else {
-    // For '-q' option. Make sure to have space for saving a scalar value.
-    sizeoftensor = b->quality ? 1 : 0;
-  }
-  // The index within each point at which an element pointer is found, where
-  //   the index is measured in pointers. Ensure the index is aligned to a
-  //   sizeof(tetrahedron)-byte address.
-  point2simindex = ((pointmtrindex + sizeoftensor) * sizeof(REAL)
-                 + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
-  if (b->plc || b->refine) {
-    // Increase the point size by three pointers, which are:
-    //   - a pointer to a tet, read by point2tet();
-    //   - a pointer to a subface/subsegment , read by point2sh();
-    //   - a pointer to a parent point, read by point2ppt()).
-    if (b->metric) {
-      // Increase one pointer to a tet of the background mesh.
-      pointsize = (point2simindex + 4) * sizeof(tetrahedron);
-    } else {
-      pointsize = (point2simindex + 3) * sizeof(tetrahedron);
-    }
-    // The index within each point at which a pbc point is found.
-    point2pbcptindex = (pointsize + sizeof(tetrahedron) - 1)
-                     / sizeof(tetrahedron);
-    if (checkpbcs) {
-      // Increase the size by one pointer to a corresponding pbc point,
-      //   read by point2pbcpt().
-      pointsize = (point2pbcptindex + 1) * sizeof(tetrahedron);
-    }
-  } else {
-    pointsize = point2simindex * sizeof(tetrahedron);
-  }
-  // 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 = (pointsize + sizeof(int) - 1) / sizeof(int);
-  // Now point size is the ints (inidcated by pointmarkindex) plus:
-  //   - an integer for boundary marker;
-  //   - an integer for vertex type;
-  pointsize = (pointmarkindex + 2) * sizeof(int);
-  // Decide the wordtype used in vertex pool.
-  wtype = (sizeof(REAL) >= sizeof(tetrahedron)) ? FLOATINGPOINT : POINTER;
-  // Initialize the pool of vertices.
-  points = new memorypool(pointsize, VERPERBLOCK, wtype, 0);
-
-  // The number of bytes occupied by a tetrahedron.  There are four pointers
-  //   to other tetrahedra, four pointers to corners, and possibly four
-  //   pointers to subfaces.
-  elesize = (8 + b->useshelles * 6) * sizeof(tetrahedron);
-  // If Voronoi diagram is wanted, make sure we have additional space.
-  if (b->voroout && (b->useshelles == 0)) {
-    elesize = (8 + 4) * sizeof(tetrahedron);
-  }
-  // The index within each element at which its attributes are found, where
-  //   the index is measured in REALs. 
-  elemattribindex = (elesize + sizeof(REAL) - 1) / sizeof(REAL);
-  // The index within each element at which the maximum voulme bound is
-  //   found, where the index is measured in REALs.  Note that if the
-  //   `b->regionattrib' flag is set, an additional attribute will be added.
-  volumeboundindex = elemattribindex + in->numberoftetrahedronattributes
-                   + (b->regionattrib > 0);
-  // If element attributes or an constraint are needed, increase the number
-  //   of bytes occupied by an element.
-  if (b->varvolume) {
-    elesize = (volumeboundindex + 1) * sizeof(REAL);
-  } else if (in->numberoftetrahedronattributes + b->regionattrib > 0) {
-    elesize = volumeboundindex * sizeof(REAL);
-  }
-  // If element neighbor graph is requested (-n switch), an additional
-  //   integer is allocated for each element.
-  elemmarkerindex = (elesize + sizeof(int) - 1) / sizeof(int);
-  if (b->neighout || b->voroout) {
-    elesize = (elemmarkerindex + 1) * sizeof(int);
-  }
-  // If -o2 switch is used, an additional pointer pointed to the list of
-  //   higher order nodes is allocated for each element.
-  highorderindex = (elesize + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
-  if (b->order == 2) {
-    elesize = (highorderindex + 1) * sizeof(tetrahedron);
-  }
-  // Having determined the memory size of an element, initialize the pool.
-  tetrahedrons = new memorypool(elesize, ELEPERBLOCK, POINTER, 8);
-
-  if (b->useshelles) {
-    // The number of bytes occupied by a subface.  The list of pointers
-    //   stored in a subface are: three to other subfaces, three to corners,
-    //   three to subsegments, two to tetrahedra, and one to a badface.
-    shsize = 12 * sizeof(shellface);
-    // The index within each subface at which the maximum area bound is
-    //   found, where the index is measured in REALs.
-    areaboundindex = (shsize + sizeof(REAL) - 1) / sizeof(REAL);
-    // If -q switch is in use, increase the number of bytes occupied by
-    //   a subface for saving maximum area bound.
-    if (b->quality && varconstraint) {
-      shsize = (areaboundindex + 1) * sizeof(REAL);
-    } else {
-      shsize = areaboundindex * sizeof(REAL);
-    }
-    // The index within subface at which the facet marker is found. Ensure
-    //   the marker is aligned to a sizeof(int)-byte address.
-    shmarkindex = (shsize + sizeof(int) - 1) / sizeof(int);
-    // Increase the number of bytes by two or three integers, one for facet
-    //   marker, one for shellface type, and optionally one for pbc group.
-    shsize = (shmarkindex + 2 + checkpbcs) * sizeof(int);
-    // Initialize the pool of subfaces. Each subface record is eight-byte
-    //   aligned so it has room to store an edge version (from 0 to 5) in
-    //   the least three bits.
-    subfaces = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
-    // Initialize the pool of subsegments. The subsegment's record is same
-    //   with subface.
-    subsegs = new memorypool(shsize, SUBPERBLOCK, 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 tet., marking it dead.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::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.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse()
-{
-  tetrahedron *newtetrahedron;
-
-  do {
-    newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
-    if (newtetrahedron == (tetrahedron *) NULL) {
-      return (tetrahedron *) NULL;
-    }
-  } while (newtetrahedron[7] == (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 tetgenmesh::shellfacedealloc(memorypool *pool, shellface *dyingsh)
-{
-  // Set shellface's vertices to NULL. This makes it possible to detect dead
-  //   shellfaces when traversing the list of all shellfaces.
-  dyingsh[3] = (shellface) NULL;
-  dyingsh[4] = (shellface) NULL;
-  dyingsh[5] = (shellface) NULL;
-  pool->dealloc((void *) dyingsh);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// shellfacetraverse()    Traverse the subfaces, skipping dead ones. Used    //
-//                        for both subfaces and subsegments pool traverse.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::shellface* tetgenmesh::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;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// badfacedealloc()    Deallocate space for a badface, marking it dead.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::badfacedealloc(memorypool *pool, badface *dying)
-{
-  // Set badface's forg to NULL. This makes it possible to detect dead
-  //   ones when traversing the list of all items.
-  dying->forg = (point) NULL;
-  pool->dealloc((void *) dying);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// badfacetraverse()    Traverse the pools, skipping dead ones.              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::badface* tetgenmesh::badfacetraverse(memorypool *pool)
-{
-  badface *newsh;
-
-  do {
-    newsh = (badface *) pool->traverse();
-    if (newsh == (badface *) NULL) {
-      return (badface *) NULL;
-    }
-  } while (newsh->forg == (point) NULL);               // Skip dead ones.
-  return newsh;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// pointdealloc()    Deallocate space for a point, marking it dead.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::pointdealloc(point dyingpoint)
-{
-  // Mark the point as dead. This  makes it possible to detect dead points
-  //   when traversing the list of all points.
-  setpointtype(dyingpoint, DEADVERTEX);
-  points->dealloc((void *) dyingpoint);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// pointtraverse()    Traverse the points, skipping dead ones.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::point tetgenmesh::pointtraverse()
-{
-  point newpoint;
-
-  do {
-    newpoint = (point) points->traverse();
-    if (newpoint == (point) NULL) {
-      return (point) NULL;
-    }
-  } while (pointtype(newpoint) == DEADVERTEX);            // Skip dead ones.
-  return newpoint;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// maketetrahedron()    Create a new tetrahedron.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::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 vertices.
-  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 (b->useshelles) {
-    newtet->tet[8 ] = (tetrahedron) dummysh;
-    newtet->tet[9 ] = (tetrahedron) dummysh;
-    newtet->tet[10] = (tetrahedron) dummysh;
-    newtet->tet[11] = (tetrahedron) dummysh;
-    newtet->tet[12] = (tetrahedron) dummysh;
-    newtet->tet[13] = (tetrahedron) dummysh;
-  }
-  for (int i = 0; i < in->numberoftetrahedronattributes; i++) {
-    setelemattribute(newtet->tet, i, 0.0);
-  }
-  if (b->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 for     //
-//                    both subfaces and seusegments.                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::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 vertices.
-  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;
-  // Initialize the pointer to badface structure.
-  newface->sh[11] = (shellface) NULL;
-  if (b->quality && varconstraint) {
-    // Initialize the maximum area bound.
-    setareabound(*newface, 0.0);
-  }
-  // Set the boundary marker to zero.
-  setshellmark(*newface, 0);
-  // Set the type.
-  setshelltype(*newface, NSHARP);
-  if (checkpbcs) {
-    // Set the pbcgroup be ivalid.
-    setshellpbcgroup(*newface, -1);
-  }
-  // Initialize the version to be Zero.
-  newface->shver = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// makepoint()    Create a new point.                                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::makepoint(point* pnewpoint)
-{
-  int ptmark, i;
-
-  *pnewpoint = (point) points->alloc();
-  // Initialize three coordinates.
-  (*pnewpoint)[0] = 0.0;
-  (*pnewpoint)[1] = 0.0;
-  (*pnewpoint)[2] = 0.0;
-  // Initialize the list of user-defined attributes.
-  for (i = 0; i < in->numberofpointattributes; i++) {
-    (*pnewpoint)[3 + i] = 0.0;
-  }
-  // Initialize the metric tensor.
-  for (i = 0; i < sizeoftensor; i++) {
-    (*pnewpoint)[pointmtrindex + i] = 0.0;
-  }
-  if (b->plc || b->refine) {
-    // Initialize the point-to-simplex filed.
-    setpoint2tet(*pnewpoint, NULL);
-    setpoint2sh(*pnewpoint, NULL);
-    setpoint2ppt(*pnewpoint, NULL);
-    if (b->metric) {
-      setpoint2bgmtet(*pnewpoint, NULL);
-    }
-    if (checkpbcs) {
-      // Initialize the other pointer to its pbc point.
-      setpoint2pbcpt(*pnewpoint, NULL);
-    }
-  }
-  // Initialize the point marker (starting from in->firstnumber).
-  ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
-  setpointmark(*pnewpoint, ptmark);
-  // Initialize the point type.
-  setpointtype(*pnewpoint, UNUSEDVERTEX);
-}
-
-//
-// End of memory management routines
-//
-
-//
-// Begin of point location routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// randomnation()    Generate a random number between 0 and 'choices' - 1.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-unsigned long tetgenmesh::randomnation(unsigned int choices)
-{
-  unsigned long newrandom;
-
-  if (choices >= 714025l) {
-    newrandom = (randomseed * 1366l + 150889l) % 714025l;
-    randomseed = (newrandom * 1366l + 150889l) % 714025l;
-    newrandom = newrandom * (choices / 714025l) + randomseed;
-    if (newrandom >= choices) {
-      return newrandom - choices;
-    } else {
-      return newrandom;
-    }
-  } else {
-    randomseed = (randomseed * 1366l + 150889l) % 714025l;
-    return randomseed % choices;
-  }
-  // Old function.
-  // randomseed = (randomseed * 1366l + 150889l) % 714025l;
-  // return randomseed / (714025l / choices + 1);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// distance2()    Returns the square "distance" of a tetrahedron to point p. //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL tetgenmesh::distance2(tetrahedron* tetptr, point p)
-{
-  point p1, p2, p3, p4;
-  REAL dx, dy, dz;
-
-  p1 = (point) tetptr[4];
-  p2 = (point) tetptr[5];
-  p3 = (point) tetptr[6];
-  p4 = (point) tetptr[7];
-
-  dx = p[0] - 0.25 * (p1[0] + p2[0] + p3[0] + p4[0]);
-  dy = p[1] - 0.25 * (p1[1] + p2[1] + p3[1] + p4[1]);
-  dz = p[2] - 0.25 * (p1[2] + p2[2] + p3[2] + p4[2]);
-
-  return dx * dx + dy * dy + dz * dz;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// preciselocate()    Find a simplex containing a given point.               //
-//                                                                           //
-// This routine implements the simple Walk-through point location algorithm. //
-// Begins its search from 'searchtet', assume there is a line segment L from //
-// a vertex of 'searchtet' to the query point 'searchpt', and simply walk    //
-// towards 'searchpt' by traversing all faces intersected by L.              //
-//                                                                           //
-// On completion, 'searchtet' is a tetrahedron that contains 'searchpt'. The //
-// returned value indicates one of the following cases:                      //
-//   - 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 primary edge is the edge on which the point lies.        //
-//   - Returns ONFACE if the point lies strictly within a face. 'searchtet'  //
-//     is a handle whose primary face is the face on which the point lies.   //
-//   - Returns INTETRAHEDRON if the point lies strictly in 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.         //
-//                                                                           //
-// WARNING: This routine is designed for convex triangulations, and will not //
-// generally work after the holes and concavities have been carved.          //
-//                                                                           //
-// If 'maxtetnumber' > 0, stop the searching process if the number of passed //
-// tets is larger than it and return OUTSIDE.                                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::locateresult tetgenmesh::preciselocate(point searchpt,
-  triface* searchtet, long maxtetnumber)
-{
-  triface backtracetet;
-  triface walkthroface;
-  point forg, fdest, fapex, toppo;
-  REAL ori1, ori2, ori3, ori4;
-  long tetnumber;
-  int side;
-
-  if (isdead(searchtet)) searchtet->tet = dummytet;
-  if (searchtet->tet == dummytet) {
-    searchtet->loc = 0;
-    symself(*searchtet);
-  }
-  // 'searchtet' should be a valid tetrahedron now.
-#ifdef SELF_CHECK
-  // assert(!isdead(searchtet) && (searchtet->tet != dummytet));
-#endif
-  if (isdead(searchtet)) {
-    printf("Warning:  Point location failed.\n");
-    return OUTSIDE;
-  }
-
-  searchtet->ver = 0; // Keep in CCW edge ring.
-  // Find a face of 'searchtet' such that the 'searchpt' lies strictly
-  //   above it.  Such face should always exist.
-  for (searchtet->loc = 0; searchtet->loc < 4; searchtet->loc++) {
-    forg = org(*searchtet);
-    fdest = dest(*searchtet);
-    fapex = apex(*searchtet);
-    ori1 = orient3d(forg, fdest, fapex, searchpt);
-    if (ori1 < 0.0) break;
-  }
-#ifdef SELF_CHECK
-  assert(searchtet->loc < 4);
-#endif
-
-  // Define 'tetnumber' for exit the loop when it's running endless.
-  tetnumber = 0l;
-  while ((maxtetnumber > 0l) && (tetnumber <= maxtetnumber)) {
-    // Check if we are reaching the boundary of the triangulation.
-    if (searchtet->tet == dummytet) {
-      *searchtet = backtracetet;
-      return OUTSIDE;
-    }
-    // Initialize the face for returning the walk-through face.
-    walkthroface.tet = (tetrahedron *) NULL;
-    // Adjust the edge ring, so that 'ori1 < 0.0' holds.
-    searchtet->ver = 0;
-    // 'toppo' remains unchange for the following orientation tests.
-    toppo = oppo(*searchtet);
-    // Check the three sides of 'searchtet' to find the face through which
-    //   we can walk next.
-    for (side = 0; side < 3; side++) {
-      forg = org(*searchtet);
-      fdest = dest(*searchtet);
-      ori2 = orient3d(forg, fdest, toppo, searchpt);
-      if (ori2 == 0.0) {
-        // They are coplanar, check if 'searchpt' lies inside, or on an edge,
-        //   or coindice with a vertex of face (forg, fdest, toppo). 
-        fapex = apex(*searchtet);
-        ori3 = orient3d(fdest, fapex, toppo, searchpt);
-        if (ori3 < 0.0) {
-          // Outside the face (fdest, fapex, toppo), walk through it.
-          enextself(*searchtet);
-          fnext(*searchtet, walkthroface);
-          break;
-        }
-        ori4 = orient3d(fapex, forg, toppo, searchpt);
-        if (ori4 < 0.0) {
-          // Outside the face (fapex, forg, toppo), walk through it.
-          enext2self(*searchtet);
-          fnext(*searchtet, walkthroface);
-          break;
-        }
-        // Remember, ori1 < 0.0, which means 'searchpt' will not on edge
-        //   (forg, fdest) or on vertex forg or fdest.
-#ifdef SELF_CHECK
-        assert(ori1 < 0.0);
-#endif
-        // The rest possible cases are: 
-        //   (1) 'searchpt' lies on edge (fdest, toppo);
-        //   (2) 'searchpt' lies on edge (toppo, forg);
-        //   (3) 'searchpt' coincident with toppo;
-        //   (4) 'searchpt' lies inside face (forg, fdest, toppo).
-        fnextself(*searchtet);
-        if (ori3 == 0.0) {
-          if (ori4 == 0.0) {
-            // Case (4).
-            enext2self(*searchtet);
-            return ONVERTEX;
-          } else {
-            // Case (1).
-            enextself(*searchtet);
-            return ONEDGE;
-          }
-        }
-        if (ori4 == 0.0) {
-          // Case (2).
-          enext2self(*searchtet);
-          return ONEDGE;
-        }
-        // Case (4).
-        return ONFACE;
-      } else if (ori2 < 0.0) {
-        // Outside the face (forg, fdest, toppo), walk through it.
-        fnext(*searchtet, walkthroface);
-        break;
-      }
-      // Go to check next side.
-      enextself(*searchtet);
-    }
-    if (side >= 3) {
-      // Found! Inside tetrahedron.
-      return INTETRAHEDRON;
-    }
-    // We walk through the face 'walkthroface' and continue the searching.
-#ifdef SELF_CHECK
-    assert(walkthroface.tet != (tetrahedron *) NULL);
-#endif
-    // Store the face handle in 'backtracetet' before we take the real walk.
-    //   So we are able to restore the handle to 'searchtet' if we are
-    //   reaching the outer boundary.
-    backtracetet = walkthroface;
-    sym(walkthroface, *searchtet);    
-    tetnumber++;
-  }
-
-  // Should never be here.
-  // printf("Internal error in preciselocate(): Point location failed.\n");
-  // internalerror();
-  return OUTSIDE;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// locate()    Find a simplex containing a given point.                      //
-//                                                                           //
-// This routine implements Muecke's Jump-and-walk point location algorithm.  //
-// It improves the simple walk-through by "jumping" to a good starting point //
-// via random sampling.  Searching begins from one of handles:  the input    //
-// 'searchtet', a recently encountered tetrahedron 'recenttet',  or from one //
-// chosen from a random sample.  The choice is made by determining which one //
-// 's barycenter is closest to the point we are searcing for.  Having chosen //
-// the starting tetrahedron, the simple Walk-through algorithm is used to do //
-// the real walking.                                                         //
-//                                                                           //
-// The return value indicates the location of the 'searchpt' (INTETRAHEDRON, //
-// or ONFACE, ...). 'searchtet' is adjusted to a tetrahedron corresponding   //
-// to that value. See the introduction part of preciselocate() for detail.   //
-//                                                                           //
-// WARNING: This routine is designed for convex triangulations, and will not //
-// generally work after the holes and concavities have been carved.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::locateresult tetgenmesh::locate(point searchpt, 
-  triface *searchtet)
-{
-  tetrahedron *firsttet, *tetptr;
-  void **sampleblock;
-  long sampleblocks, samplesperblock, samplenum;
-  long tetblocks, i, j;
-  unsigned long alignptr;
-  REAL searchdist, dist;
-
-  // 'searchtet' should be a valid tetrahedron.
-  if (isdead(searchtet)) {
-    searchtet->tet = dummytet;
-  }
-  if (searchtet->tet == dummytet) {
-    // This is an 'Outer Space' handle, get a hull tetrahedron.
-    searchtet->loc = 0;
-    symself(*searchtet);
-  }
-#ifdef SELF_CHECK
-  // assert(!isdead(searchtet));
-#endif
-  if (isdead(searchtet)) {
-    printf("Warning:  Point location failed.\n");
-    return OUTSIDE;
-  }
-  
-  // Get the distance from the suggested starting tet to the point we seek.
-  searchdist = distance2(searchtet->tet, searchpt);
-
-  // If a recently encountered tetrahedron has been recorded and has not
-  //   been deallocated, test it as a good starting point.
-  if (!isdead(&recenttet) && (recenttet.tet != searchtet->tet)) {
-    dist = distance2(recenttet.tet, searchpt);
-    if (dist < searchdist) {
-      *searchtet = recenttet;
-      searchdist = dist;
-    }
-  }
-
-  // Select "good" candidate using k random samples, taking the closest one.
-  //   The number of random samples taken is proportional to the fourth 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 * samples <
-         tetrahedrons->items) {
-    samples++;
-  }
-  // Find how much blocks in current tet pool.
-  tetblocks = (tetrahedrons->maxitems + ELEPERBLOCK - 1) / ELEPERBLOCK;
-  // 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 * ELEPERBLOCK)));
-      } else {
-        samplenum = randomnation(ELEPERBLOCK);
-      }
-      tetptr = (tetrahedron *)
-               (firsttet + (samplenum * tetrahedrons->itemwords));
-      if (tetptr[4] != (tetrahedron) NULL) {
-        dist = distance2(tetptr, searchpt);
-        if (dist < searchdist) {
-          searchtet->tet = tetptr;
-          searchdist = dist;
-        }
-      }
-    }
-    sampleblock = (void **) *sampleblock;
-  }
-  
-  // Call simple walk-through to locate the point.
-  return preciselocate(searchpt, searchtet, tetrahedrons->items); 
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// adjustlocate()    Adjust the precise location of a vertex.                //
-//                                                                           //
-// 'precise' is the value returned from preciselocate().  It indicates the   //
-// exact location of the point 'searchpt' with respect to the tetrahedron    //
-// 'searchtet'.  'epspp' is a given relative tolerance.                      //
-//                                                                           //
-// This routine re-evaluates the orientations of searchpt with respect to    //
-// the four sides of searchtet. Detects the coplanarities by additinal tests //
-// which are based on the given tolerance. If 'precise' is ONFACE or ONEDGE, //
-// we can save one or two orientation tests.                                 //
-//                                                                           //
-// The return value indicates the location of the 'searchpt' (INTETRAHEDRON, //
-// or ONFACE, ...). 'searchtet' is adjusted to a tetrahedron corresponding   //
-// to that value. See the introduction part of preciselocate() for detail.   //
-//                                                                           //
-// WARNING:  This routine detect degenerate case using relative tolerance.   //
-// It is better used after locate() or preciselocate().  For general inputs, //
-// it may not able to tell the correct location.                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::locateresult tetgenmesh::adjustlocate(point searchpt,
-  triface* searchtet, enum locateresult precise, REAL epspp)
-{
-  point torg, tdest, tapex, toppo;
-  REAL s1, s2, s3, s4;
-
-  // For the given 'searchtet', the orientations tests are:
-  //  s1: (tdest, torg, tapex, searchpt);
-  //  s2: (torg, tdest, toppo, searchpt);
-  //  s3: (tdest, tapex, toppo, searchpt);
-  //  s4: (tapex, torg, toppo, searchpt);
-  adjustedgering(*searchtet, CCW);
-  torg = org(*searchtet);
-  tdest = dest(*searchtet);
-  tapex = apex(*searchtet);
-  toppo = oppo(*searchtet);
-
-  switch (precise) {
-  case ONVERTEX:
-    // This case we don't need do any further test.
-    return ONVERTEX;
-  case ONEDGE:
-    // (torg, tdest);
-    s1 = 0.0;
-    s2 = 0.0;
-    break;
-  case ONFACE:
-    // (tdest, torg, tapex);
-    s1 = 0.0;
-    s2 = orient3d(torg, tdest, toppo, searchpt);
-    break;
-  default: // INTETRAHEDRON or OUTSIDE
-    s1 = orient3d(tdest, torg, tapex, searchpt);
-    s2 = orient3d(torg, tdest, toppo, searchpt);
-  }
-  
-  if (s1 != 0.0) {
-    if (iscoplanar(tdest, torg, tapex, searchpt, s1, epspp)) {
-      s1 = 0.0;
-    }
-  }
-  if (s1 < 0.0) {
-    return OUTSIDE;
-  }
-
-  if (s2 != 0.0) {
-    if (iscoplanar(torg, tdest, toppo, searchpt, s2, epspp)) {
-      s2 = 0.0;
-    }
-  }
-  if (s2 < 0.0) {
-    fnextself(*searchtet);
-    return OUTSIDE;
-  }
-
-  s3 = orient3d(tdest, tapex, toppo, searchpt);
-  if (s3 != 0.0) {
-    if (iscoplanar(tdest, tapex, toppo, searchpt, s3, epspp)) {
-      s3 = 0.0;
-    }
-  }
-  if (s3 < 0.0) {
-    enextfnextself(*searchtet);
-    return OUTSIDE;
-  }
-
-  s4 = orient3d(tapex, torg, toppo, searchpt);
-  if (s4 != 0.0) {
-    if (iscoplanar(tapex, torg, toppo, searchpt, s4, epspp)) {
-      s4 = 0.0;
-    }
-  }
-  if (s4 < 0.0) {
-    enext2fnextself(*searchtet);
-    return OUTSIDE;
-  }
-
-  // Determine degenerate cases.
-  if (s1 == 0.0) {
-    if (s2 == 0.0) {
-      if (s3 == 0.0) {
-        // On tdest.
-        enextself(*searchtet);
-        return ONVERTEX;
-      }
-      if (s4 == 0.0) {
-        // On torg.
-        return ONVERTEX;
-      }
-      // On edge (torg, tdest).
-      return ONEDGE;
-    }
-    if (s3 == 0.0) {
-      if (s4 == 0.0) {
-        // On tapex.
-        enext2self(*searchtet);
-        return ONVERTEX;
-      }
-      // On edge (tdest, tapex).
-      enextself(*searchtet);
-      return ONEDGE;
-    }
-    if (s4 == 0.0) {
-      // On edge (tapex, torg).
-      enext2self(*searchtet);
-      return ONEDGE;
-    }
-    // On face (torg, tdest, tapex).
-    return ONFACE;
-  }
-  if (s2 == 0.0) {
-    fnextself(*searchtet);
-    if (s3 == 0.0) {
-      if (s4 == 0.0) {
-        // On toppo.
-        enext2self(*searchtet);
-        return ONVERTEX;
-      }
-      // On edge (tdest, toppo).
-      enextself(*searchtet);
-      return ONEDGE;
-    }
-    if (s4 == 0.0) {
-      // On edge (toppo, torg).
-      enext2self(*searchtet);
-      return ONEDGE;
-    }
-    // On face (torg, tdest, toppo).
-    return ONFACE;
-  }
-  if (s3 == 0.0) {
-    enextfnextself(*searchtet);
-    if (s4 == 0.0) {
-      // On edge (tapex, toppo).
-      enextself(*searchtet);
-      return ONEDGE;
-    }
-    // On face (tdest, tapex, toppo).
-    return ONFACE;
-  }
-  if (s4 == 0.0) {
-    enext2fnextself(*searchtet);
-    // On face (tapex, torg, toppo).
-    return ONFACE;
-  }
-
-  // Inside tetrahedron.
-  return INTETRAHEDRON;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// hullwalk()    Find a tetrahedron on the hull to continue search.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::locateresult tetgenmesh::hullwalk(point searchpt,
-  triface *hulltet)
-{
-  list* travtetlist;
-  triface travtet, neightet;
-  point pa, pb, pc;
-  enum locateresult loc;
-  REAL ori;
-  int i;
-
-  travtetlist = new list(sizeof(triface), NULL, 256);
-  travtet = *hulltet;
-  infect(travtet);
-  travtetlist->append(&travtet);
-
-  loc = OUTSIDE;
-  for (i = 0; i < travtetlist->len(); i++) {
-    travtet = * (triface *)(* travtetlist)[i];
-    // Choose the CCW-edgering in face.
-    travtet.ver = 0;
-    // Look for a side where pt lies below it.
-    for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
-      pa = org(travtet);
-      pb = dest(travtet);
-      pc = apex(travtet);
-      ori = orient3d(pa, pb, pc, searchpt);
-      if (ori > 0.0) break;
-    }
-    // Is pt above all (or coplanar with some of) the four sides?
-    if (travtet.loc == 4) {
-      hulltet->tet = travtet.tet;
-      loc = adjustlocate(searchpt, hulltet, INTETRAHEDRON, b->epsilon);
-      assert(loc != OUTSIDE);
-    } else { // ori > 0.0
-      // pt is below (behind) this side. We want to walk through it.
-      sym(travtet, neightet);
-      if (neightet.tet == dummytet) {
-        // This is a hull side. Is p approximately on this side.
-        loc = adjustlocate(searchpt, &travtet, OUTSIDE, b->epsilon);
-      }
-      if (loc == OUTSIDE) {
-        // Let's collect all the neighbors for next searching.
-        for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
-          sym(travtet, neightet);
-          if ((neightet.tet != dummytet) && !infected(neightet)) {
-            // Neighbor exists and not visited.
-            infect(neightet);
-            travtetlist->append(&neightet);
-          }
-        } // for (travtet.loc = 0; 
-      } // if (loc == OUTSIDE)
-    } // if (travtet.loc == 4)
-    if (loc != OUTSIDE) break;
-  } // for (i = 0; i < travtetlist->len(); i++)
-  
-  // Uninfect traversed tets.
-  for (i = 0; i < travtetlist->len(); i++) {
-    travtet = * (triface *)(* travtetlist)[i];
-    uninfect(travtet);
-  }
-
-  delete travtetlist;
-  return loc;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// locatesub()    Find a point in the surface mesh of a facet.               //
-//                                                                           //
-// Searching begins from the input 'searchsh', it should be a handle on the  //
-// convex hull of the facet triangulation.                                   //
-//                                                                           //
-// If 'stopatseg' is nonzero, the search will stop if it tries to walk       //
-// through a subsegment, and will return OUTSIDE.                            //
-//                                                                           //
-// On completion, 'searchsh' is a subface that contains 'searchpt'.          //
-//   - Returns ONVERTEX if the point lies on an existing vertex. 'searchsh'  //
-//     is a handle whose origin is the existing vertex.                      //
-//   - Returns ONEDGE if the point lies on a mesh edge.  'searchsh' is a     //
-//     handle whose primary edge is the edge on which the point lies.        //
-//   - Returns ONFACE if the point lies strictly within a subface.           //
-//     'searchsh' is a handle on which the point lies.                       //
-//   - Returns OUTSIDE if the point lies outside the triangulation.          //
-//                                                                           //
-// WARNING: This routine is designed for convex triangulations, and will not //
-// not generally work after the holes and concavities have been carved.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::locateresult tetgenmesh::locatesub(point searchpt,
-  face* searchsh, int stopatseg, REAL epspp)
-{
-  face backtracksh, spinsh, checkedge;
-  point forg, fdest, fapex;
-  REAL orgori, destori;
-  REAL ori, sign;
-  int moveleft, i;
-
-  if (searchsh->sh == dummysh) {
-    searchsh->shver = 0;
-    spivotself(*searchsh);
-#ifdef SELF_CHECK
-    assert(searchsh->sh != dummysh);
-#endif
-  }
-  // Find the sign to simulate that abovepoint is 'above' the facet.
-  adjustedgering(*searchsh, CCW);
-  forg = sorg(*searchsh);
-  fdest = sdest(*searchsh);
-  fapex = sapex(*searchsh);
-  ori = orient3d(forg, fdest, fapex, abovepoint);
-  sign = ori > 0.0 ? -1 : 1;
-
-  // Orient 'searchsh' so that 'searchpt' is below it (i.e., searchpt has
-  //   CCW orientation with respect to searchsh in plane).  Such edge
-  //   should always exist. Save it as (forg, fdest).
-  for (i = 0; i < 3; i++) {
-    forg = sorg(*searchsh);
-    fdest = sdest(*searchsh);
-    ori = orient3d(forg, fdest, abovepoint, searchpt) * sign;
-    if (ori > 0.0) break;
-    senextself(*searchsh);
-  }
-#ifdef SELF_CHECK
-  assert(i < 3);
-#endif
-  
-  while (1) {
-    fapex = sapex(*searchsh);
-    // Check whether the apex is the point we seek.
-    if (fapex[0] == searchpt[0] && fapex[1] == searchpt[1] &&
-        fapex[2] == searchpt[2]) {
-      senext2self(*searchsh);
-      return ONVERTEX;
-    }
-    // Does the point lie on the other side of the line defined by the
-    //   triangle edge opposite the triangle's destination?
-    destori = orient3d(forg, fapex, abovepoint, searchpt) * sign;
-    if (epspp > 0.0) {
-      if (iscoplanar(forg, fapex, abovepoint, searchpt, destori, epspp)) {
-        destori = 0.0;
-      }
-    }
-    // Does the point lie on the other side of the line defined by the
-    //   triangle edge opposite the triangle's origin? 
-    orgori = orient3d(fapex, fdest, abovepoint, searchpt) * sign;
-    if (epspp > 0.0) {
-      if (iscoplanar(fapex, fdest, abovepoint, searchpt, orgori, epspp)) {
-        orgori = 0.0;
-      }
-    }
-    if (destori > 0.0) {
-      moveleft = 1;
-    } else {
-      if (orgori > 0.0) {
-        moveleft = 0;
-      } else {
-        // The point must be on the boundary of or inside this triangle.
-        if (destori == 0.0) {
-          senext2self(*searchsh);
-          return ONEDGE;
-        } 
-        if (orgori == 0.0) {
-          senextself(*searchsh);
-          return ONEDGE;
-        }
-        return ONFACE;
-      }
-    }
-    // Move to another triangle.  Leave a trace `backtracksh' in case
-    //   walking off a boundary of the triangulation.
-    if (moveleft) {
-      senext2(*searchsh, backtracksh);
-      fdest = fapex;
-    } else {
-      senext(*searchsh, backtracksh);
-      forg = fapex;
-    }
-    // Check if we meet a segment.
-    sspivot(backtracksh, checkedge);
-    if (checkedge.sh != dummysh) {
-      if (stopatseg) {
-        // The flag indicates we should not cross a segment. Stop.
-        *searchsh = backtracksh;
-        return OUTSIDE;
-      }
-      // Try to walk through a segment. We need to find a coplanar subface
-      //   sharing this segment to get into.
-      spinsh = backtracksh;
-      do {
-        spivotself(spinsh);
-        if (spinsh.sh == backtracksh.sh) {
-          // Turn back, no coplanar subface is found.
-          break;
-        }
-        // Are they belong to the same facet.
-        if (shellmark(spinsh) == shellmark(backtracksh)) {
-          // Find a coplanar subface. Walk into it.
-          *searchsh = spinsh;
-          break;
-        }
-        // Are they (nearly) coplanar?
-        ori = orient3d(forg, fdest, sapex(backtracksh), sapex(spinsh));
-        if (iscoplanar(forg, fdest, sapex(backtracksh), sapex(spinsh), ori,
-                       b->epsilon)) {
-          // Find a coplanar subface. Walk into it.
-          *searchsh = spinsh;
-          break;
-        }
-      } while (spinsh.sh != backtracksh.sh);
-    } else {
-      spivot(backtracksh, *searchsh);
-    }
-    // Check for walking right out of the triangulation.
-    if ((searchsh->sh == dummysh) || (searchsh->sh == backtracksh.sh)) {
-      // Go back to the last triangle.
-      *searchsh = backtracksh;
-      return OUTSIDE;
-    }
-    // To keep the same orientation wrt abovepoint.
-    if (sorg(*searchsh) != forg) sesymself(*searchsh);
-#ifdef SELF_CHECK
-    assert((sorg(*searchsh) == forg) && (sdest(*searchsh) == fdest));
-#endif
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// adjustlocatesub()    Adjust the precise location of a vertex.             //
-//                                                                           //
-// 'precise' is the precise location (returned from locatesub()) of 'searcht'//
-// with respect to 'searchsh'. 'epspp' is the given relative tolerance.      //
-//                                                                           //
-// This routine re-evaluates the orientations of 'searchpt' with respect to  //
-// the three edges of 'searchsh'. Detects the collinearities by additinal    //
-// tests based on the given tolerance. If 'precise' is ONEDGE, one can save  //
-// one orientation test for the current edge of 'searchsh'.                  //
-//                                                                           //
-// On completion, 'searchsh' is a subface contains 'searchpt'. The returned  //
-// value indicates one of the following cases:                               //
-//   - Returns ONVERTEX if the point lies on an existing vertex. 'searchsh'  //
-//     is a handle whose origin is the existing vertex.                      //
-//   - Returns ONEDGE if the point lies on a mesh edge.  'searchsh' is a     //
-//     handle whose primary edge is the edge on which the point lies.        //
-//   - Returns ONFACE if the point lies strictly within a subface.           //
-//     'searchsh' is a handle on which the point lies.                       //
-//   - Returns OUTSIDE if the point lies outside 'searchsh'.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::locateresult tetgenmesh::
-adjustlocatesub(point searchpt, face* searchsh, enum locateresult precise,
-                REAL epspp)
-{
-  point pa, pb, pc;
-  bool s1, s2, s3;
-
-  pa = sorg(*searchsh);
-  pb = sdest(*searchsh);
-  pc = sapex(*searchsh);
-
-  if (precise == ONEDGE) {
-    s1 = true;
-  } else {
-    s1 = iscollinear(pa, pb, searchpt, epspp);
-  }
-  s2 = iscollinear(pb, pc, searchpt, epspp);
-  s3 = iscollinear(pc, pa, searchpt, epspp);
-  if (s1) {
-    if (s2) {
-      // on vertex pb.
-#ifdef SELF_CHECK
-      assert(!s3);
-#endif
-      senextself(*searchsh);
-      return ONVERTEX;
-    } else if (s3) {
-      // on vertex pa.
-      return ONVERTEX;
-    } else {
-      // on edge pa->pb.
-      return ONEDGE;
-    }
-  } else if (s2) {
-    if (s3) {
-      // on vertex pc.
-      senext2self(*searchsh);
-      return ONVERTEX;
-    } else {
-      // on edge pb->pc.
-      senextself(*searchsh);
-      return ONEDGE;
-    }
-  } else if (s3) {
-    // on edge pc->pa.
-    senext2self(*searchsh);
-    return ONEDGE;
-  } else {
-    return precise;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// locateseg()    Find a point in subsegments.                               //
-//                                                                           //
-// Searching begins from the input 'searchseg', it should be a subsegment of //
-// the whole segment.                                                        //
-//                                                                           //
-// On completion, 'searchseg' is a subsegment that contains 'searchpt'.      //
-//   - Returns ONVERTEX if the point lies on an existing vertex. 'searchseg' //
-//     is a handle whose origin is the existing vertex.                      //
-//   - Returns ONEDGE if the point lies inside 'searchseg'.                  //
-//   - Returns OUTSIDE if the point lies outside the segment.                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::locateresult tetgenmesh::
-locateseg(point searchpt, face* searchseg)
-{
-  face backtraceseg;
-  point pa, pb;
-  REAL dx, dy, dz;
-  int moveleft;
-  int i;
-
-  moveleft = 0;
-  while (1) {
-    searchseg->shver = 0;
-    pa = sorg(*searchseg);
-    pb = sdest(*searchseg);
-    // Find the biggest difference in x, y, and z coordinates of a and b.
-    dx = fabs(pb[0] - pa[0]);
-    dy = fabs(pb[1] - pa[1]);
-    dz = fabs(pb[2] - pa[2]);
-    if (dx > dy) {
-      if (dx > dz) {
-        i = 0;
-      } else {
-        i = 2;
-      }
-    } else {
-      if (dy > dz) {
-        i = 1;
-      } else {
-        i = 2;
-      }
-    }
-    if (pa[i] < pb[i]) {
-      if (searchpt[i] < pa[i]) {
-        moveleft = 1;
-      } else if (searchpt[i] > pa[i]) {
-        if (searchpt[i] < pb[i]) {
-          return ONEDGE;
-        } else if (searchpt[i] > pb[i]) {
-          moveleft = 0;
-        } else {
-#ifdef SELF_CHECK
-          assert(searchpt[i] == pb[i]);
-#endif
-          sesymself(*searchseg);
-          return ONVERTEX;
-        }
-      } else {
-#ifdef SELF_CHECK
-        assert(searchpt[i] == pa[i]);
-#endif
-        return ONVERTEX;
-      }
-    } else if (pa[i] > pb[i]) {
-      if (searchpt[i] < pb[i]) {
-        moveleft = 0;
-      } else if (searchpt[i] > pb[i]) {
-        if (searchpt[i] < pa[i]) {
-          return ONEDGE;
-        } else if (searchpt[i] > pa[i]) {
-          moveleft = 1;
-        } else {
-#ifdef SELF_CHECK
-          assert(searchpt[i] == pa[i]);
-#endif
-          return ONVERTEX;
-        }
-      } else {
-#ifdef SELF_CHECK
-        assert(searchpt[i] == pb[i]);
-#endif
-        sesymself(*searchseg);
-        return ONVERTEX;
-      }
-    }
-    backtraceseg = *searchseg;
-    if (moveleft) {
-      senext2self(*searchseg);
-    } else {
-      senextself(*searchseg);
-    }
-    spivotself(*searchseg);
-    if (searchseg->sh == dummysh) {
-      *searchseg = backtraceseg;
-      break;
-    }
-  }
-
-  return OUTSIDE;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// adjustlocateseg()    Adjust the precise location of a vertex on segment.  //
-//                                                                           //
-// 'searchpt' is either inside or ouside the segment 'searchseg'. It will be //
-// adjusted to on vertex if it is very close to an endpoint of 'searchseg'.  //
-// 'epspp' is the given relative tolerance.                                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::locateresult tetgenmesh::
-adjustlocateseg(point searchpt, face* searchseg, enum locateresult precise,
-                REAL epspp)
-{
-  point pa, pb;
-  REAL L, d, r;
-
-  pa = sorg(*searchseg);
-  pb = sdest(*searchseg);
-  L = distance(pa, pb);
-
-  // Is searchpt approximate to pa?
-  d = distance(pa, searchpt);
-  r = d / L;
-  if (r <= epspp) {
-    return ONVERTEX;
-  }
-  // Is searchpt approximate to pb?
-  d = distance(pb, searchpt);
-  r = d / L;
-  if (r <= epspp) {
-    sesymself(*searchseg);
-    return ONVERTEX;
-  }
-
-  return precise;
-}
-
-//
-// End of point location routines
-//
-
-//
-// Begin of mesh transformation routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Flip operations                                                           //
-//                                                                           //
-// If abc is a hull face, it is unflipable, and is locally Delaunay.  In the //
-// following, we assume abc is an interior face, and the other tetrahedron   //
-// adjoining at abc is bace.                                                 //
-//                                                                           //
-// If the convex hull CH of the set {a, b, c, d, e} only has four vertices,  //
-// i.e., one vertex lies inside CH, then abc is unflipable, and is locally   //
-// Delaunay. If CH is the vertex set itself, we have the following cases to  //
-// determine whether abc is flipable or not.                                 //
-//                                                                           //
-// If no four points of {a, b, c, d, e} are coplanar, a 2-to-3 flip can be   //
-// applied to abc if the edge de crosses the triangle abc; a 3-to-2 flip can //
-// be applied to abc if ab crosses cde, and abde exists, otherwise, face abc //
-// is unflipable, i.e., the tetrahedron abde is not present.                 //
-//                                                                           //
-// If four points of {a, b, c, d, e} are coplanar (two faces are coplanar).  //
-// Assume faces abd and abe are coplanar (it is impossible be abc). If a, b, //
-// d, e form a non-convex quadrilateral, then abc is unflipable, furthermore,//
-// it is locally Delaunay.  Assume they are convex quadrilateral, if abd and //
-// abe are hull faces, a 2-to-2 flip can be applied to abc;  if abd and abe  //
-// are interior faces,  assume two tetrahedra adjoining abd and abe at the   //
-// opposite sides are abdg and abef, respectively.  If g = f, a 4-to-4 flip  //
-// can be applied to abc, otherwise, abc is unflipable.                      //
-//                                                                           //
-// There are other cases which can cause abc unflipable. If abc is a subface,//
-// a 2-to-3 flip is forbidden;  if ab is a subsegment, flips 3-to-2, 2-to-2, //
-// and 4-to-4 are forbidden.                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// categorizeface()    Determine the flip type of a given face.              //
-//                                                                           //
-// On input, 'horiz' represents the face abc we want to flip (imagine it is  //
-// parallel to the horizon).  Let the tet above it be abcd.                  //
-//                                                                           //
-// This routine determines the suitable type of flip operation for 'horiz'.  //
-//   - Returns T23 if a 2-to-3 flip is applicable. 'horiz' is same as input. //
-//   - Returns T32 if a 3-to-2 flip is applicable. 'horiz' returns the edge  //
-//     of abc which is the flipable.                                         //
-//   - Returns T22 if a 2-to-2 or 4-to-4 flip is applicable. 'horiz' returns //
-//     the edge of abc which is flipable.                                    //
-//   - Returns N32 indicates it is unflipable due to the absence of a tet.   //
-//     'horize' returns the unflipable edge.                                 //
-//   - Returns N40 indicates it is unflipable and is locally Delaunay.       //
-//   - Returns FORBIDDENFACE indicates abc is a subface.                     //
-//   - Returns FORBIDDENEDGE indicates the flipable edge of abc is a segment.//
-//     'horize' returns the flipable edge.                                   //
-//                                                                           //
-// Given a face abc, with two adjoining tetrahedra abcd and bace.  If abc is //
-// flipable, i.e., T23, T32, T22 or T44, its flip type can be determined by  //
-// doing five orientation tests: two tests for determining that d, e lie on  //
-// the different sides of abc, three tests for determining if the edge de    //
-// intersects the face abc.  However, if we use the neighbor information of  //
-// the mesh data structure, we can reduce the five orientation tests to at   //
-// most three tests, that is, the two tests for determining whether d and e  //
-// lie on the different sides of abc can be saved.                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::fliptype tetgenmesh::categorizeface(triface& horiz)
-{
-  triface symhoriz, casing;
-  face checksh, checkseg;
-  face cassh1, cassh2;
-  point pa, pb, pc, pd, pe, pf, pg;
-  point abdoppo, bcdoppo, cadoppo;
-  REAL ori1, ori2, ori3;
-  int adjtet;
-
-  sym(horiz, symhoriz);
-  if (symhoriz.tet == dummytet) {
-    // A hull face is unflipable and locally Delaunay.
-    return N40;
-  }
-  
-  adjustedgering(horiz, CCW);
-  findedge(&symhoriz, dest(horiz), org(horiz));
-  pa = org(horiz);
-  pb = dest(horiz);
-  pc = apex(horiz);
-  pd = oppo(horiz);
-  pe = oppo(symhoriz);
-
-  // Find the number of adjacent tetrahedra of abc, which have d, e, and one
-  //   of corners of abc as their corners. This number can be 0, 1 and 2.
-  abdoppo = bcdoppo = cadoppo = (point) NULL;
-  adjtet = 0;
-  fnext(horiz, casing); // at edge 'ab'.
-  symself(casing);
-  if (casing.tet != dummytet) {
-    abdoppo = oppo(casing);
-    if (abdoppo == pe) adjtet++;
-  }
-  enextfnext(horiz, casing); // at edge 'bc'.
-  symself(casing);
-  if (casing.tet != dummytet) {
-    bcdoppo = oppo(casing);
-    if (bcdoppo == pe) adjtet++;
-  }
-  enext2fnext(horiz, casing); // at edge 'ca'.
-  symself(casing);
-  if (casing.tet != dummytet) {
-    cadoppo = oppo(casing);
-    if (cadoppo == pe) adjtet++;
-  }
-  
-  if (adjtet == 0) {
-    // No adjacent tetrahedron. Types T23, T22 and T44 are possible. 
-    ori1 = orient3d(pa, pb, pd, pe);
-    if (checksubfaces && ori1 != 0.0) {
-      // Check if abd and abe are both boundary faces?
-      fnext(horiz, casing);
-      tspivot(casing, cassh1);
-      fnext(symhoriz, casing);
-      tspivot(casing, cassh2);
-      if ((cassh1.sh != dummysh) && (cassh2.sh != dummysh)) {
-        // abd and abe are both boundary faces. Check if ab is a segment.
-        findedge(&cassh1, pa, pb);
-        sspivot(cassh1, checkseg);
-        if (checkseg.sh == dummysh) {
-          // ab is not a segment - abd and abe belong to the same facet.
-          //   The four points are forced to be coplanar.
-          ori1 = 0.0;
-        } else {
-          // ab is a segment - abd and abe belong to two different facets.
-          //   In principle, a, b, c and d can form a tetrahedron (since
-          //   ori1 != 0.0).  However, we should avoid to create a very
-          //   flat one which may form a sequence of extremely badly-shaped
-          //   or even wrong orientational tets. Test with a larger epsilon.
-          if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
-        }
-      } else {
-        // abd and abe are not both boundary faces. Check if abd and bae
-        //   are approximately coplanar with respect to the epsilon.
-        if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon)) ori1 = 0.0;
-      }
-    }
-    if (ori1 < 0.0) {
-      // e lies above abd, unflipable, tet abde is not present.
-#ifdef SELF_CHECK
-      if (!nonconvex) {
-        // abd and abe should not be hull faces, check it.
-        fnext(horiz, casing);
-        symself(casing);
-        assert(casing.tet != dummytet);
-        fnext(symhoriz, casing);
-        symself(casing);
-        assert(casing.tet != dummytet);
-      }
-#endif
-      if (checksubfaces) {
-        // The nonconvexbility may be casued by existing an subsegment.
-        tsspivot(&horiz, &checkseg);
-        if (checkseg.sh != dummysh) {
-          return FORBIDDENEDGE;
-        }
-      }
-      return N32;
-    }
-    ori2 = orient3d(pb, pc, pd, pe);
-    if (checksubfaces && ori2 != 0.0) {
-      // Check if bcd and cbe are both boundary faces.
-      enextfnext(horiz, casing);
-      tspivot(casing, cassh1);
-      enext2fnext(symhoriz, casing);
-      tspivot(casing, cassh2);
-      if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
-        // bcd and cbe are both boundary faces. Check if bc is a segment.
-        findedge(&cassh1, pb, pc);
-        sspivot(cassh1, checkseg);
-        if (checkseg.sh == dummysh) {
-          // bc is not a segment - bcd and cbe belong to the same facet.
-          //   The four points are forced to be coplanar.
-          ori2 = 0.0;
-        } else {
-          if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
-        } 
-      } else {
-        //  bcd and cbe are not both boundary faces. Check if bcd and cbe
-        //   are approximately coplanar with respect to the epsilon.
-        if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon)) ori2 = 0.0;
-      }
-    }
-    if (ori2 < 0.0) {
-      // e lies above bcd, unflipable, tet bcde is not present.
-#ifdef SELF_CHECK
-      if (!nonconvex) {
-        // bcd and cbe should not be hull faces, check it.
-        enextfnext(horiz, casing);
-        symself(casing);
-        assert(casing.tet != dummytet);
-        enext2fnext(symhoriz, casing);
-        symself(casing);
-        assert(casing.tet != dummytet);
-      }
-#endif
-      enextself(horiz);
-      if (checksubfaces) {
-        // The nonconvexbility may be casued by existing an subsegment.
-        tsspivot(&horiz, &checkseg);
-        if (checkseg.sh != dummysh) {
-          return FORBIDDENEDGE;
-        }
-      }
-      return N32;
-    } 
-    ori3 = orient3d(pc, pa, pd, pe);
-    if (checksubfaces && ori3 != 0.0) {
-      // Check if cad and ace are both boundary faces.
-      enext2fnext(horiz, casing);
-      tspivot(casing, cassh1);
-      enextfnext(symhoriz, casing);
-      tspivot(casing, cassh2);
-      if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
-        // cad and ace are both boundary faces. Check if ca is a segment.
-        findedge(&cassh1, pc, pa);
-        sspivot(cassh1, checkseg);
-        if (checkseg.sh == dummysh) {
-          // ca is not a segment - cad and ace belong to the same facet.
-          //   The four points are forced to be coplanar.
-          ori3 = 0.0;
-        } else {
-          // ca is a segment - cad and ace belong to two different facets.
-          //   In principle, c, a, d and e can form a tetrahedron (since
-          //   ori3 != 0.0). Use a larger eps to test if they're coplanar.
-          if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon * 1e+2)) ori3 = 0.0;
-        } 
-      } else {
-        // cad and ace are not both boundary faces. Check if cad and ace
-        //   are approximately coplanar with respect to the epsilon.
-        if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon)) ori3 = 0.0;
-      }
-    }
-    if (ori3 < 0.0) {
-      // e lies above cad, unflipable, tet cade is not present.
-#ifdef SELF_CHECK
-      if (!nonconvex) {
-        // cad and ace should not be hull faces, check it.
-        enext2fnext(horiz, casing);
-        symself(casing);
-        assert(casing.tet != dummytet);
-        enextfnext(symhoriz, casing);
-        symself(casing);
-        assert(casing.tet != dummytet);
-      }
-#endif
-      enext2self(horiz);
-      if (checksubfaces) {
-        // The nonconvexbility may be casued by existing an subsegment.
-        tsspivot(&horiz, &checkseg);
-        if (checkseg.sh != dummysh) {
-          return FORBIDDENEDGE;
-        }
-      }
-      return N32;
-    }
-    if (ori1 == 0.0) {
-      // e is coplanar with abd.
-      if (ori2 * ori3 == 0.0) {
-        // only one zero is possible.
-        // assert(!(ori2 == 0.0 && ori3 == 0.0));
-        // Three points (d, e, and a or b) are collinear, abc is unflipable
-        //   and locally Delaunay.
-        return N40;
-      }
-    } else if (ori2 == 0.0) {
-      // e is coplanar with bcd.
-      if (ori1 * ori3 == 0.0) {
-        // only one zero is possible.
-        // assert(!(ori1 == 0.0 && ori3 == 0.0));
-        // Three points (d, e, and b or c) are collinear, abc is unflipable
-        //   and locally Delaunay.
-        return N40;
-      }
-      // Adjust 'horiz' and 'symhoriz' be the edge bc.
-      enextself(horiz);
-      enext2self(symhoriz);
-    } else if (ori3 == 0.0) {
-      // e is coplanar with cad.
-      if (ori1 * ori2 == 0.0) {
-        // only one zero is possible.
-        // assert(!(ori1 == 0.0 && ori2 == 0.0));
-        // Three points (d, e, and c or a) are collinear, abc is unflipable
-        //   and locally Delaunay.
-        return N40;
-      }
-      // Adjust 'horiz' and 'symhoriz' be the edge ca.
-      enext2self(horiz);
-      enextself(symhoriz);
-    } else {
-      // e lies below all three faces, flipable.
-      if (checksubfaces) {
-        tspivot(horiz, checksh);
-        if (checksh.sh != dummysh) {
-          // To flip a subface is forbidden.
-          return FORBIDDENFACE;
-        }
-      }
-      return T23;
-    }
-    // Four points are coplanar, T22 or T44 is possible.
-    if (checksubfaces) {
-      tsspivot(&horiz, &checkseg);
-      if (checkseg.sh != dummysh) {
-        // To flip a subsegment is forbidden.
-        return FORBIDDENEDGE;
-      }
-      tspivot(horiz, checksh);
-      if (checksh.sh != dummysh) {
-        // To flip a subface is forbidden.
-        return FORBIDDENFACE;
-      }
-    }
-    // Assume the four coplanar points are a, b, d, e, abd and abe are two
-    //   coplanar faces. If both abd and abe are hull faces, flipable(T22).
-    //   If they are interior faces, get the opposite tetrahedra abdf and
-    //   abeg, if f = g, flipable (T44). Otherwise, unflipable.
-    pf = pg = (point) NULL;
-    fnext(horiz, casing);
-    symself(casing);
-    if (casing.tet != dummytet) {
-      pf = oppo(casing);
-    }
-    fnext(symhoriz, casing);
-    symself(casing);
-    if (casing.tet != dummytet) {
-      pg = oppo(casing);
-    }
-    if (pf == pg) {
-      // Either T22 (pf == pg == NULL) or T44 (pf and pg) is possible.
-      if (checksubfaces) {
-        // Retreat the corner points a, b, and c.
-        pa = org(horiz);
-        pb = dest(horiz);
-        pc = apex(horiz);
-        // Be careful not to create an inverted tetrahedron. Check the case.
-        ori1 = orient3d(pc, pd, pe, pa);
-        if (ori1 <= 0) return N40;
-        ori1 = orient3d(pd, pc, pe, pb);
-        if (ori1 <= 0) return N40;
-        if (pf != (point) NULL) {
-          ori1 = orient3d(pd, pf, pe, pa);
-          if (ori1 <= 0) return N40;
-          ori1 = orient3d(pf, pd, pe, pb);
-          if (ori1 <= 0) return N40;
-        }
-      }
-      if (pf == (point) NULL) {
-        // abd and abe are hull faces, flipable.
-        return T22;
-      } else {
-        // abd and abe are interior faces, flipable.
-#ifdef SELF_CHECK
-        assert(pf != (point) NULL);
-#endif
-        return T44;
-      }
-    } else {
-      // ab has more than four faces around it, unflipable.
-      return N32;
-    }
-  } else if (adjtet == 1) {
-    // One of its three edges is locally non-convex. Type T32 is possible.
-    // Adjust current configuration so that edge ab is non-convex.
-    if (bcdoppo == pe) {
-      // Edge bc is non-convex. Adjust 'horiz' and 'symhoriz' be edge bc.
-      enextself(horiz);
-      enext2self(symhoriz);
-      pa = org(horiz);
-      pb = dest(horiz);
-      pc = apex(horiz);
-    } else if (cadoppo == pe) {
-      // Edge ca is non-convex. Adjust 'horiz' and 'symhoriz' be edge ca.
-      enext2self(horiz);
-      enextself(symhoriz);
-      pa = org(horiz);
-      pb = dest(horiz);
-      pc = apex(horiz);
-    } else {
-      // Edge ab is non-convex.
-#ifdef SELF_CHECK
-      assert(abdoppo == pe);
-#endif
-    } // Now ab is the non-convex edge.
-    // In order to be flipable, ab should cross face cde. Check it.
-    ori1 = orient3d(pc, pd, pe, pa);
-    if (checksubfaces && ori1 != 0.0) {
-      // Check if cad and ace are both boundary faces.
-      enext2fnext(horiz, casing);
-      tspivot(casing, cassh1);
-      enextfnext(symhoriz, casing);
-      tspivot(casing, cassh2);
-      if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
-        // cad and ace are both boundary faces. Check if ca is a segment.
-        findedge(&cassh1, pc, pa);
-        sspivot(cassh1, checkseg);
-        if (checkseg.sh == dummysh) {
-          // ca is not a segment. cad and ace belong to the same facet.
-          //   The four points are forced to be coplanar.
-          ori1 = 0.0;
-        } else {
-          // ca is a segment. cad and ace belong to different facets.
-          //   In principle, c, d, e, and a can form a tetrahedron (since
-          //   ori1 != 0.0).  However, we should avoid to create a very
-          //   flat tet. Use a larger epsilon to test if they're coplanar.
-          if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
-        }
-      } else {
-        // Check if c, d, e, and a are approximately coplanar.
-        if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon)) ori1 = 0.0;
-      }
-    }
-    if (ori1 <= 0.0) {
-      // a lies above or is coplanar cde, abc is locally Delaunay.
-      return N40;
-    }
-    ori2 = orient3d(pd, pc, pe, pb);
-    if (checksubfaces && ori2 != 0.0) {
-      // Check if bcd and cbe are both boundary faces.
-      enextfnext(horiz, casing);
-      tspivot(casing, cassh1);
-      enext2fnext(symhoriz, casing);
-      tspivot(casing, cassh2);
-      if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
-        // bcd and cbe are both boundary faces. Check if bc is a segment.
-        findedge(&cassh1, pb, pc);
-        sspivot(cassh1, checkseg);
-        if (checkseg.sh == dummysh) {
-          // bc is not a segment. bcd and cbe belong to the same facet.
-          //   The four points are forced to be coplanar.
-          ori2 = 0.0;
-        } else {
-          // bc is a segment. bcd and cbe belong to different facets.
-          //   In principle, d, c, e, and b can form a tetrahedron (since
-          //   ori2 != 0.0).  However, we should avoid to create a very
-          //   flat tet. Use a larger epsilon to test if they're coplanar.
-          if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
-        }
-      } else {
-        // Check if d, c, e, and b are approximately coplanar.
-        if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon)) ori2 = 0.0;
-      }
-    }
-    if (ori2 <= 0.0) {
-      // b lies above dce, unflipable, and abc is locally Delaunay.
-      return N40;
-    }
-    // Edge ab crosses face cde properly.
-    if (checksubfaces) {
-      // If abc is subface, then ab must be a subsegment (because abde is
-      //   a tetrahedron and ab crosses cde properly). 
-      tsspivot(&horiz, &checkseg);
-      if (checkseg.sh != dummysh) {
-        // To flip a subsegment is forbidden.
-        return FORBIDDENEDGE;
-      }
-      // Both abd and bae should not be subfaces (because they're not
-      //   coplanar and ab is not a subsegment). However, they may be
-      //   subfaces and belong to a facet (created during facet recovery),
-      //   that is, abde is an invalid tetrahedron. Find this case out.
-      fnext(horiz, casing);
-      tspivot(casing, cassh1);
-      fnext(symhoriz, casing);
-      tspivot(casing, cassh2); 
-      if (cassh1.sh != dummysh || cassh2.sh != dummysh) {
-        if (!b->quiet) {
-          // Unfortunately, they're subfaces. Corrections need be done here.
-          printf("Warning:  A tetrahedron spans two subfaces of a facet.\n");
-        }
-        // Temporarily, let it be there.
-        return N32;
-      }
-    }
-    return T32;
-  } else {
-    // The convex hull of {a, b, c, d, e} has only four vertices, abc is
-    //   unflipable, furthermore, it is locally Delaunay.
-    return N40;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// enqueueflipface(), enqueueflipedge()    Queue a face (or an edge).        //
-//                                                                           //
-// The face (or edge) may be non-locally Delaunay. It is queued for process- //
-// ing in flip() (or flipsub()). The vertices of the face (edge) are stored  //
-// seperatly to ensure the face (or edge) is still the same one when we save //
-// it since other flips will cause this face (or edge) be changed or dead.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::enqueueflipface(triface& checkface, queue* flipqueue)
-{
-  badface *queface;
-  triface symface;
-
-  sym(checkface, symface);
-  if (symface.tet != dummytet) {
-    queface = (badface *) flipqueue->push((void *) NULL);
-    queface->tt = checkface;
-    queface->foppo = oppo(symface);
-  }
-}
-
-void tetgenmesh::enqueueflipedge(face& checkedge, queue* flipqueue)
-{
-  badface *queface;
-
-  queface = (badface *) flipqueue->push((void *) NULL);
-  queface->ss = checkedge;
-  queface->forg = sorg(checkedge);
-  queface->fdest = sdest(checkedge);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flip23()    Perform a 2-to-3 flip.                                        //
-//                                                                           //
-// On input, 'flipface' represents the face will be flipped.  Let it is abc, //
-// the two tetrahedra sharing abc are abcd, bace. abc is not a subface.      //
-//                                                                           //
-// A 2-to-3 flip is to change two tetrahedra abcd, bace to three tetrahedra  //
-// edab, edbc, and edca.  As a result, face abc has been removed and three   //
-// new faces eda, edb and edc have been created.                             //
-//                                                                           //
-// On completion, 'flipface' returns edab.  If 'flipqueue' is not NULL, all  //
-// possibly non-Delaunay faces are added into it.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::flip23(triface* flipface, queue* flipqueue)
-{
-  triface abcd, bace;                                  // Old configuration.
-  triface oldabd, oldbcd, oldcad;
-  triface abdcasing, bcdcasing, cadcasing;
-  triface oldbae, oldcbe, oldace;
-  triface baecasing, cbecasing, acecasing;
-  triface worktet;
-  face abdsh, bcdsh, cadsh;                   // The six subfaces on the CH.
-  face baesh, cbesh, acesh;
-  face abseg, bcseg, caseg;                      // The nine segs on the CH.
-  face adseg, bdseg, cdseg;
-  face aeseg, beseg, ceseg;
-  triface edab, edbc, edca;                            // New configuration.
-  point pa, pb, pc, pd, pe;
-  REAL attrib, volume;
-  int i;
-
-  abcd = *flipface;
-  adjustedgering(abcd, CCW); // abcd represents edge ab.
-  pa = org(abcd);
-  pb = dest(abcd);
-  pc = apex(abcd);
-  pd = oppo(abcd);
-  // sym(abcd, bace);
-  // findedge(&bace, dest(abcd), org(abcd)); // bace represents edge ba.
-  sym(abcd, bace);
-  bace.ver = 0; // CCW.
-  for (i = 0; (i < 3) && (org(bace) != pb); i++) {
-    enextself(bace);
-  }
-  pe = oppo(bace);
-
-  if (b->verbose > 2) {
-    printf("    Do T23 on face (%d, %d, %d) %d, %d.\n", pointmark(pa),
-           pointmark(pb), pointmark(pc), pointmark(pd), pointmark(pe));
-  }
-  flip23s++;
-
-  // Storing the old configuration outside the convex hull.
-  fnext(abcd, oldabd);
-  enextfnext(abcd, oldbcd);
-  enext2fnext(abcd, oldcad);
-  fnext(bace, oldbae);
-  enext2fnext(bace, oldcbe);
-  enextfnext(bace, oldace);
-  sym(oldabd, abdcasing);
-  sym(oldbcd, bcdcasing);
-  sym(oldcad, cadcasing);
-  sym(oldbae, baecasing);
-  sym(oldcbe, cbecasing);
-  sym(oldace, acecasing);
-  if (checksubfaces) {
-    tspivot(oldabd, abdsh);
-    tspivot(oldbcd, bcdsh);
-    tspivot(oldcad, cadsh);
-    tspivot(oldbae, baesh);
-    tspivot(oldcbe, cbesh);
-    tspivot(oldace, acesh);
-  } else if (checksubsegs) {
-    tsspivot1(abcd, abseg);
-    enext(abcd, worktet);
-    tsspivot1(worktet, bcseg);
-    enext2(abcd, worktet);
-    tsspivot1(worktet, caseg);
-    enext2(oldabd, worktet);
-    tsspivot1(worktet, adseg);
-    enext2(oldbcd, worktet);
-    tsspivot1(worktet, bdseg);
-    enext2(oldcad, worktet);
-    tsspivot1(worktet, cdseg);
-    enext(oldbae, worktet);
-    tsspivot1(worktet, aeseg);
-    enext(oldcbe, worktet);
-    tsspivot1(worktet, beseg);
-    enext(oldace, worktet);
-    tsspivot1(worktet, ceseg);
-  }
-
-  // Creating the new configuration inside the convex hull.
-  edab.tet = abcd.tet; // Update abcd to be edab.
-  setorg (edab, pe);
-  setdest(edab, pd);
-  setapex(edab, pa);
-  setoppo(edab, pb);
-  edbc.tet = bace.tet; // Update bace to be edbc.
-  setorg (edbc, pe);
-  setdest(edbc, pd);
-  setapex(edbc, pb);
-  setoppo(edbc, pc);
-  maketetrahedron(&edca); // Create edca.
-  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 < in->numberoftetrahedronattributes; i++) {
-    attrib = elemattribute(abcd.tet, i);
-    setelemattribute(edca.tet, i, attrib);
-  }
-  // Set the volume constraint of the new tetrahedron 'edca' if the -ra
-  //   switches are not used together. In -ra case, the various volume
-  //   constraints can be spreaded very far.
-  if (b->varvolume && !b->refine) {
-    volume = volumebound(abcd.tet);
-    setvolumebound(edca.tet, volume);
-  }
-
-  // Clear old bonds in edab(was abcd) and edbc(was bace).
-  for (i = 0; i < 4; i ++) {
-    edab.tet[i] = (tetrahedron) dummytet;
-  }
-  for (i = 0; i < 4; i ++) {
-    edbc.tet[i] = (tetrahedron) dummytet;
-  }
-  // Bond the faces inside the convex hull.
-  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 the faces on the convex hull.
-  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);
-  // There may exist subfaces that need to be bonded to new configuarton.
-  if (checksubfaces) {
-    // Clear old flags in edab(was abcd) and edbc(was bace).
-    for (i = 0; i < 4; i ++) {
-      edab.loc = i;
-      tsdissolve(edab);
-      edbc.loc = i;
-      tsdissolve(edbc);
-    }
-    if (abdsh.sh != dummysh) {
-      edab.loc = 2; 
-      tsbond(edab, abdsh);
-    }
-    if (baesh.sh != dummysh) {
-      edab.loc = 3; 
-      tsbond(edab, baesh);
-    }
-    if (bcdsh.sh != dummysh) {
-      edbc.loc = 2; 
-      tsbond(edbc, bcdsh);
-    }
-    if (cbesh.sh != dummysh) {
-      edbc.loc = 3; 
-      tsbond(edbc, cbesh);
-    }
-    if (cadsh.sh != dummysh) {
-      edca.loc = 2; 
-      tsbond(edca, cadsh);
-    }
-    if (acesh.sh != dummysh) {
-      edca.loc = 3; 
-      tsbond(edca, acesh);
-    }
-  } else if (checksubsegs) {
-    for (i = 0; i < 6; i++) {
-      edab.tet[8 + i] = (tetrahedron) dummysh;
-    }
-    for (i = 0; i < 6; i++) {
-      edbc.tet[8 + i] = (tetrahedron) dummysh;
-    }
-    edab.loc = edab.ver = 0;
-    edbc.loc = edab.ver = 0;
-    edca.loc = edab.ver = 0;
-    // Operate in tet edab (5 edges).
-    enext(edab, worktet);
-    tssbond1(worktet, adseg);
-    enext2(edab, worktet);
-    tssbond1(worktet, aeseg);
-    fnext(edab, worktet);
-    enextself(worktet);
-    tssbond1(worktet, bdseg);
-    enextself(worktet);
-    tssbond1(worktet, beseg);
-    enextfnext(edab, worktet);
-    enextself(worktet);
-    tssbond1(worktet, abseg);
-    // Operate in tet edbc (5 edges)
-    enext(edbc, worktet);
-    tssbond1(worktet, bdseg);
-    enext2(edbc, worktet);
-    tssbond1(worktet, beseg);
-    fnext(edbc, worktet);
-    enextself(worktet);
-    tssbond1(worktet, cdseg);
-    enextself(worktet);
-    tssbond1(worktet, ceseg);
-    enextfnext(edbc, worktet);
-    enextself(worktet);
-    tssbond1(worktet, bcseg);
-    // Operate in tet edca (5 edges)
-    enext(edca, worktet);
-    tssbond1(worktet, cdseg);
-    enext2(edca, worktet);
-    tssbond1(worktet, ceseg);
-    fnext(edca, worktet);
-    enextself(worktet);
-    tssbond1(worktet, adseg);
-    enextself(worktet);
-    tssbond1(worktet, aeseg);
-    enextfnext(edca, worktet);
-    enextself(worktet);
-    tssbond1(worktet, caseg);
-  }
-
-  edab.loc = 0;
-  edbc.loc = 0;
-  edca.loc = 0;
-  if (b->verbose > 3) {
-    printf("    Updating edab ");
-    printtet(&edab);
-    printf("    Updating edbc ");
-    printtet(&edbc);
-    printf("    Creating edca ");
-    printtet(&edca);
-  }
-
-  if (flipqueue != (queue *) NULL) {
-    enextfnext(edab, abdcasing);
-    enqueueflipface(abdcasing, flipqueue);
-    enext2fnext(edab, baecasing);
-    enqueueflipface(baecasing, flipqueue);
-    enextfnext(edbc, bcdcasing);
-    enqueueflipface(bcdcasing, flipqueue);
-    enext2fnext(edbc, cbecasing);
-    enqueueflipface(cbecasing, flipqueue);
-    enextfnext(edca, cadcasing);
-    enqueueflipface(cadcasing, flipqueue);
-    enext2fnext(edca, acecasing);
-    enqueueflipface(acecasing, flipqueue);  
-  }
-
-  // Save a live handle in 'recenttet'.
-  recenttet = edbc;
-  // Set the return handle be edab.
-  *flipface = edab;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flip32()    Perform a 3-to-2 flip.                                        //
-//                                                                           //
-// On input, 'flipface' represents the face will be flipped.  Let it is eda, //
-// where edge ed is locally non-convex. Three tetrahedra sharing ed are edab,//
-// edbc, and edca.  ed is not a subsegment.                                  //
-//                                                                           //
-// A 3-to-2 flip is to change the three tetrahedra edab, edbc, and edca into //
-// another two tetrahedra abcd and bace.  As a result, the edge ed has been  //
-// removed and the face abc has been created.                                //
-//                                                                           //
-// On completion, 'flipface' returns abcd.  If 'flipqueue' is not NULL, all  //
-// possibly non-Delaunay faces are added into it.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::flip32(triface* flipface, queue* flipqueue)
-{
-  triface edab, edbc, edca;                            // Old configuration.
-  triface oldabd, oldbcd, oldcad;
-  triface abdcasing, bcdcasing, cadcasing;
-  triface oldbae, oldcbe, oldace;
-  triface baecasing, cbecasing, acecasing;
-  triface worktet;
-  face abdsh, bcdsh, cadsh;
-  face baesh, cbesh, acesh;
-  face abseg, bcseg, caseg;                      // The nine segs on the CH.
-  face adseg, bdseg, cdseg;
-  face aeseg, beseg, ceseg;
-  triface abcd, bace;                                  // New configuration.
-  point pa, pb, pc, pd, pe;
-  int i;
-
-  edab = *flipface;
-  adjustedgering(edab, CCW);
-  pa = apex(edab);
-  pb = oppo(edab);
-  pd = dest(edab);
-  pe = org(edab);
-  fnext(edab, edbc);
-  symself(edbc);
-  edbc.ver = 0;
-  for (i = 0; (i < 3) && (org(edbc) != pe); i++) {
-    enextself(edbc);
-  }
-  pc = oppo(edbc);
-  fnext(edbc, edca);
-  symself(edca);
-  edca.ver = 0;
-  for (i = 0; (i < 3) && (org(edca) != pe); i++) {
-    enextself(edca);
-  }
-
-  if (b->verbose > 2) {
-    printf("    Do T32 on edge (%d, %d) %d, %d, %d.\n", pointmark(pe),
-           pointmark(pd), pointmark(pa), pointmark(pb), pointmark(pc));
-  }
-  flip32s++;
-
-  // Storing the old configuration outside the convex hull.
-  enextfnext(edab, oldabd);
-  enext2fnext(edab, oldbae);
-  enextfnext(edbc, oldbcd);
-  enext2fnext(edbc, oldcbe);
-  enextfnext(edca, oldcad);
-  enext2fnext(edca, oldace);
-  sym(oldabd, abdcasing);
-  sym(oldbcd, bcdcasing);
-  sym(oldcad, cadcasing);
-  sym(oldbae, baecasing);
-  sym(oldcbe, cbecasing);
-  sym(oldace, acecasing);
-  if (checksubfaces) {
-    tspivot(oldabd, abdsh);
-    tspivot(oldbcd, bcdsh);
-    tspivot(oldcad, cadsh);
-    tspivot(oldbae, baesh);
-    tspivot(oldcbe, cbesh);
-    tspivot(oldace, acesh);
-  } else if (checksubsegs) {
-    enext(edab, worktet);
-    tsspivot1(worktet, adseg);
-    enext2(edab, worktet);
-    tsspivot1(worktet, aeseg);
-    enext(edbc, worktet);
-    tsspivot1(worktet, bdseg);
-    enext2(edbc, worktet);
-    tsspivot1(worktet, beseg);
-    enext(edca, worktet);
-    tsspivot1(worktet, cdseg);
-    enext2(edca, worktet);
-    tsspivot1(worktet, ceseg);
-    enextfnext(edab, worktet);
-    enextself(worktet);
-    tsspivot1(worktet, abseg);
-    enextfnext(edbc, worktet);
-    enextself(worktet);
-    tsspivot1(worktet, bcseg);
-    enextfnext(edca, worktet);
-    enextself(worktet);
-    tsspivot1(worktet, caseg);
-  }
-
-  // Creating the new configuration inside the convex hull.
-  abcd.tet = edab.tet; // Update edab to be abcd.
-  setorg (abcd, pa);
-  setdest(abcd, pb);
-  setapex(abcd, pc);
-  setoppo(abcd, pd);
-  bace.tet = edbc.tet; // Update edbc to be bace.
-  setorg (bace, pb);
-  setdest(bace, pa);
-  setapex(bace, pc);
-  setoppo(bace, pe);
-  // Dealloc a redundant tetrahedron (edca).
-  tetrahedrondealloc(edca.tet); 
-
-  // Clear the old bonds in abcd (was edab) and bace (was edbc).
-  for (i = 0; i < 4; i ++) {
-    abcd.tet[i] = (tetrahedron) dummytet;
-  }
-  for (i = 0; i < 4; i ++) {
-    bace.tet[i] = (tetrahedron) dummytet;
-  }
-  // Bond the inside face of the convex hull.
-  abcd.loc = 0;
-  bace.loc = 0;
-  bond(abcd, bace);
-  // Bond the outside faces of the convex hull.
-  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);
-  if (checksubfaces) {
-    // Clear old bonds in abcd(was edab) and bace(was edbc).
-    for (i = 0; i < 4; i ++) {
-      abcd.tet[8 + i] = (tetrahedron) dummysh;
-    }
-    for (i = 0; i < 4; i ++) {
-      bace.tet[8 + i] = (tetrahedron) dummysh;
-    }
-    if (abdsh.sh != dummysh) {
-      abcd.loc = 1;
-      tsbond(abcd, abdsh);
-    }
-    if (bcdsh.sh != dummysh) {
-      abcd.loc = 2;
-      tsbond(abcd, bcdsh);
-    }
-    if (cadsh.sh != dummysh) {
-      abcd.loc = 3;
-      tsbond(abcd, cadsh);
-    }
-    if (baesh.sh != dummysh) {
-      bace.loc = 1;
-      tsbond(bace, baesh);
-    }
-    if (cbesh.sh != dummysh) {
-      bace.loc = 3;
-      tsbond(bace, cbesh);
-    }
-    if (acesh.sh != dummysh) {
-      bace.loc = 2;
-      tsbond(bace, acesh);
-    }
-  } else if (checksubsegs) {
-    for (i = 0; i < 6; i++) {
-      abcd.tet[8 + i] = (tetrahedron) dummysh;
-    }
-    for (i = 0; i < 6; i++) {
-      bace.tet[8 + i] = (tetrahedron) dummysh;
-    }
-    abcd.loc = abcd.ver = 0;
-    bace.loc = bace.ver = 0;
-    tssbond1(abcd, abseg);     // 1
-    enext(abcd, worktet);
-    tssbond1(worktet, bcseg);  // 2
-    enext2(abcd, worktet);
-    tssbond1(worktet, caseg);  // 3
-    fnext(abcd, worktet);
-    enext2self(worktet);
-    tssbond1(worktet, adseg);  // 4
-    enextfnext(abcd, worktet);
-    enext2self(worktet);
-    tssbond1(worktet, bdseg);  // 5
-    enext2fnext(abcd, worktet);
-    enext2self(worktet);
-    tssbond1(worktet, cdseg);  // 6
-    tssbond1(bace, abseg);
-    enext2(bace, worktet);
-    tssbond1(worktet, bcseg);
-    enext(bace, worktet);
-    tssbond1(worktet, caseg);
-    fnext(bace, worktet);
-    enextself(worktet);
-    tssbond1(worktet, aeseg);  // 7
-    enext2fnext(bace, worktet);
-    enextself(worktet);
-    tssbond1(worktet, beseg);  // 8
-    enextfnext(bace, worktet);
-    enextself(worktet);
-    tssbond1(worktet, ceseg);  // 9
-  }
-
-  abcd.loc = 0;
-  bace.loc = 0;
-  if (b->verbose > 3) {
-    printf("    Updating abcd ");
-    printtet(&abcd);
-    printf("    Updating bace ");
-    printtet(&bace);
-    printf("    Deleting edca ");
-    // printtet(&edca);
-  }
-
-  if (flipqueue != (queue *) NULL) { 
-    fnext(abcd, abdcasing);
-    enqueueflipface(abdcasing, flipqueue);
-    fnext(bace, baecasing);
-    enqueueflipface(baecasing, flipqueue);
-    enextfnext(abcd, bcdcasing);
-    enqueueflipface(bcdcasing, flipqueue);
-    enextfnext(bace, cbecasing);
-    enqueueflipface(cbecasing, flipqueue);
-    enext2fnext(abcd, cadcasing);
-    enqueueflipface(cadcasing, flipqueue);
-    enext2fnext(bace, acecasing);
-    enqueueflipface(acecasing, flipqueue);  
-  }
-
-  // Save a live handle in 'recenttet'.
-  recenttet = abcd;
-  // Set the return handle be abcd.
-  *flipface = abcd;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flip22()    Perform a 2-to-2 (or 4-to-4) flip.                            //
-//                                                                           //
-// On input, 'flipface' represents the face will be flipped.  Let it is abe, //
-// ab is the flipable edge, the two tetrahedra sharing abe are abce and bade,//
-// hence a, b, c and d are coplanar. If abc, bad are interior faces, the two //
-// tetrahedra opposite to e are bacf and abdf.  ab is not a subsegment.      //
-//                                                                           //
-// A 2-to-2 flip is to change two tetrahedra abce and bade into another two  //
-// tetrahedra dcae and cdbe. If bacf and abdf exist, they're changed to cdaf //
-// and dcbf, thus a 4-to-4 flip.  As a result, two or four tetrahedra have   //
-// rotated counterclockwise (using right-hand rule with thumb points to e):  //
-// abce->dcae, bade->cdbe, and bacf->cdaf, abdf->dcbf.                       //
-//                                                                           //
-// If abc and bad are subfaces, a 2-to-2 flip is performed simultaneously by //
-// calling routine flip22sub(), hence abc->dca, bad->cdb.  The edge rings of //
-// the flipped subfaces dca and cdb have the same orientation as abc and bad.//
-// Hence, they have the same orientation as other subfaces of the facet with //
-// respect to the lift point of this facet.                                  //
-//                                                                           //
-// On completion, 'flipface' holds edge dc of tetrahedron dcae. 'flipqueue'  //
-// contains all possibly non-Delaunay faces if it is not NULL.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::flip22(triface* flipface, queue* flipqueue)
-{
-  triface abce, bade;
-  triface oldbce, oldcae, oldade, olddbe;
-  triface bcecasing, caecasing, adecasing, dbecasing;
-  face bcesh, caesh, adesh, dbesh;
-  triface bacf, abdf;
-  triface oldacf, oldcbf, oldbdf, olddaf;
-  triface acfcasing, cbfcasing, bdfcasing, dafcasing;
-  triface worktet;
-  face acfsh, cbfsh, bdfsh, dafsh;
-  face abc, bad;
-  face adseg, dbseg, bcseg, caseg;  // Coplanar segs.
-  face aeseg, deseg, beseg, ceseg;  // Above segs.
-  face afseg, dfseg, bfseg, cfseg;  // Below segs.
-  point pa, pb, pc, pd, pe, pf;
-  int mirrorflag, i;
-
-  adjustedgering(*flipface, CCW); // 'flipface' is bae.
-  fnext(*flipface, abce);
-  esymself(abce);
-  adjustedgering(*flipface, CW); // 'flipface' is abe.
-  fnext(*flipface, bade);
-#ifdef SELF_CHECK
-  assert(bade.tet != dummytet);
-#endif
-  esymself(bade);
-  pa = org(abce);
-  pb = dest(abce);
-  pc = apex(abce);
-  pd = apex(bade);
-  pe = oppo(bade);
-#ifdef SELF_CHECK
-  assert(oppo(abce) == pe);
-#endif
-  sym(abce, bacf);
-  mirrorflag = bacf.tet != dummytet;
-  if (mirrorflag) {
-    // findedge(&bacf, pb, pa);
-    bacf.ver = 0;
-    for (i = 0; (i < 3) && (org(bacf) != pb); i++) {
-      enextself(bacf);
-    }
-    sym(bade, abdf);
-#ifdef SELF_CHECK
-    assert(abdf.tet != dummytet);
-#endif
-    // findedge(&abdf, pa, pb);
-    abdf.ver = 0;
-    for (i = 0; (i < 3) && (org(abdf) != pa); i++) {
-      enextself(abdf);
-    }
-    pf = oppo(bacf);
-#ifdef SELF_CHECK
-    assert(oppo(abdf) == pf);
-#endif
-  } 
-
-  if (b->verbose > 2) {
-    printf("    Do %s on edge (%d, %d).\n", mirrorflag ? "T44" : "T22",
-           pointmark(pa), pointmark(pb));
-  }
-  mirrorflag ? flip44s++ : flip22s++;
-
-  // Save the old configuration at the convex hull.
-  enextfnext(abce, oldbce);
-  enext2fnext(abce, oldcae);
-  enextfnext(bade, oldade);
-  enext2fnext(bade, olddbe);
-  sym(oldbce, bcecasing);
-  sym(oldcae, caecasing);
-  sym(oldade, adecasing);
-  sym(olddbe, dbecasing);
-  if (checksubfaces) {
-    tspivot(oldbce, bcesh);
-    tspivot(oldcae, caesh);
-    tspivot(oldade, adesh);
-    tspivot(olddbe, dbesh);
-    tspivot(abce, abc);
-    tspivot(bade, bad);
-  } else if (checksubsegs) {
-    // Coplanar segs: a->d->b->c.
-    enext(bade, worktet); 
-    tsspivot1(worktet, adseg);
-    enext2(bade, worktet);
-    tsspivot1(worktet, dbseg);
-    enext(abce, worktet);
-    tsspivot1(worktet, bcseg);
-    enext2(abce, worktet);
-    tsspivot1(worktet, caseg);
-    // Above segs: a->e, d->e, b->e, c->e.
-    fnext(bade, worktet);
-    enextself(worktet);
-    tsspivot1(worktet, aeseg);
-    enextfnext(bade, worktet);
-    enextself(worktet);
-    tsspivot1(worktet, deseg);
-    enext2fnext(bade, worktet);
-    enextself(worktet);
-    tsspivot1(worktet, beseg);
-    enextfnext(abce, worktet);
-    enextself(worktet);
-    tsspivot1(worktet, ceseg);
-  }
-  if (mirrorflag) {
-    enextfnext(bacf, oldacf);
-    enext2fnext(bacf, oldcbf);
-    enextfnext(abdf, oldbdf);
-    enext2fnext(abdf, olddaf);
-    sym(oldacf, acfcasing);
-    sym(oldcbf, cbfcasing);
-    sym(oldbdf, bdfcasing);
-    sym(olddaf, dafcasing);
-    if (checksubfaces) {
-      tspivot(oldacf, acfsh);
-      tspivot(oldcbf, cbfsh);
-      tspivot(oldbdf, bdfsh);
-      tspivot(olddaf, dafsh);
-    } else if (checksubsegs) {
-      // Below segs: a->f, d->f, b->f, c->f.
-      fnext(abdf, worktet);
-      enext2self(worktet);
-      tsspivot1(worktet, afseg);
-      enext2fnext(abdf, worktet);
-      enext2self(worktet);
-      tsspivot1(worktet, dfseg);
-      enextfnext(abdf, worktet);
-      enext2self(worktet);
-      tsspivot1(worktet, bfseg);
-      enextfnext(bacf, worktet);
-      enextself(worktet);
-      tsspivot1(worktet, cfseg);
-    }
-  }
-
-  // Rotate abce, bade one-quarter turn counterclockwise.
-  bond(oldbce, caecasing);
-  bond(oldcae, adecasing);
-  bond(oldade, dbecasing);
-  bond(olddbe, bcecasing);
-  if (checksubfaces) {
-    // Check for subfaces and rebond them to the rotated tets.
-    if (caesh.sh == dummysh) {
-      tsdissolve(oldbce);
-    } else {
-      tsbond(oldbce, caesh);
-    }
-    if (adesh.sh == dummysh) {
-      tsdissolve(oldcae);
-    } else {
-      tsbond(oldcae, adesh);
-    }
-    if (dbesh.sh == dummysh) {
-      tsdissolve(oldade);
-    } else {
-      tsbond(oldade, dbesh);
-    }
-    if (bcesh.sh == dummysh) {
-      tsdissolve(olddbe);
-    } else {
-      tsbond(olddbe, bcesh);
-    }
-  } else if (checksubsegs) {
-    // 5 edges in abce are changed.
-    enext(abce, worktet);  // fit b->c into c->a.
-    if (caseg.sh == dummysh) {
-      tssdissolve1(worktet);
-    } else {
-      tssbond1(worktet, caseg);
-    }
-    enext2(abce, worktet); // fit c->a into a->d.
-    if (adseg.sh == dummysh) {
-      tssdissolve1(worktet);
-    } else {
-      tssbond1(worktet, adseg);
-    }
-    fnext(abce, worktet); // fit b->e into c->e.
-    enextself(worktet);
-    if (ceseg.sh == dummysh) {
-      tssdissolve1(worktet);
-    } else {
-      tssbond1(worktet, ceseg);
-    }
-    enextfnext(abce, worktet); // fit c->e into a->e.
-    enextself(worktet);
-    if (aeseg.sh == dummysh) {
-      tssdissolve1(worktet);
-    } else {
-      tssbond1(worktet, aeseg);
-    }
-    enext2fnext(abce, worktet); // fit a->e into d->e.
-    enextself(worktet);
-    if (deseg.sh == dummysh) {
-      tssdissolve1(worktet);
-    } else {
-      tssbond1(worktet, deseg);
-    }
-    // 5 edges in bade are changed.
-    enext(bade, worktet); // fit a->d into d->b.
-    if (dbseg.sh == dummysh) {
-      tssdissolve1(worktet);
-    } else {
-      tssbond1(worktet, dbseg);
-    }
-    enext2(bade, worktet); // fit d->b into b->c.
-    if (bcseg.sh == dummysh) {
-      tssdissolve1(worktet);
-    } else {
-      tssbond1(worktet, bcseg);
-    }
-    fnext(bade, worktet); // fit a->e into d->e.
-    enextself(worktet);
-    if (deseg.sh == dummysh) {
-      tssdissolve1(worktet);
-    } else {
-      tssbond1(worktet, deseg);
-    }
-    enextfnext(bade, worktet); // fit d->e into b->e.
-    enextself(worktet);
-    if (beseg.sh == dummysh) {
-      tssdissolve1(worktet);
-    } else {
-      tssbond1(worktet, beseg);
-    }
-    enext2fnext(bade, worktet); // fit b->e into c->e.
-    enextself(worktet);
-    if (ceseg.sh == dummysh) {
-      tssdissolve1(worktet);
-    } else {
-      tssbond1(worktet, ceseg);
-    }
-  }
-  if (mirrorflag) {
-    // Rotate bacf, abdf one-quarter turn counterclockwise.
-    bond(oldcbf, acfcasing);
-    bond(oldacf, dafcasing);
-    bond(olddaf, bdfcasing);
-    bond(oldbdf, cbfcasing);
-    if (checksubfaces) {
-      // Check for subfaces and rebond them to the rotated tets.
-      if (acfsh.sh == dummysh) {
-        tsdissolve(oldcbf);
-      } else {
-        tsbond(oldcbf, acfsh);
-      }
-      if (dafsh.sh == dummysh) {
-        tsdissolve(oldacf);
-      } else {
-        tsbond(oldacf, dafsh);
-      }
-      if (bdfsh.sh == dummysh) {
-        tsdissolve(olddaf);
-      } else {
-        tsbond(olddaf, bdfsh);
-      }
-      if (cbfsh.sh == dummysh) {
-        tsdissolve(oldbdf);
-      } else {
-        tsbond(oldbdf, cbfsh);
-      }
-    } else if (checksubsegs) {
-      // 5 edges in bacf are changed.
-      enext2(bacf, worktet); // fit b->c into c->a.
-      if (caseg.sh == dummysh) {
-        tssdissolve1(worktet);
-      } else {
-        tssbond1(worktet, caseg);
-      }
-      enext(bacf, worktet); // fit c->a into a->d.
-      if (adseg.sh == dummysh) {
-        tssdissolve1(worktet);
-      } else {
-        tssbond1(worktet, adseg);
-      }
-      fnext(bacf, worktet); // fit b->f into c->f.
-      enext2self(worktet);
-      if (cfseg.sh == dummysh) {
-        tssdissolve1(worktet);
-      } else {
-        tssbond1(worktet, cfseg);
-      }
-      enext2fnext(bacf, worktet); // fit c->f into a->f.
-      enext2self(worktet);
-      if (afseg.sh == dummysh) {
-        tssdissolve1(worktet);
-      } else {
-        tssbond1(worktet, afseg);
-      }
-      enextfnext(bacf, worktet); // fit a->f into d->f.
-      enext2self(worktet);
-      if (dfseg.sh == dummysh) {
-        tssdissolve1(worktet);
-      } else {
-        tssbond1(worktet, dfseg);
-      }
-      // 5 edges in abdf are changed.
-      enext2(abdf, worktet); // fit a->d into d->b.
-      if (dbseg.sh == dummysh) {
-        tssdissolve1(worktet);
-      } else {
-        tssbond1(worktet, dbseg);
-      }
-      enext(abdf, worktet); // fit d->b into b->c.
-      if (bcseg.sh == dummysh) {
-        tssdissolve1(worktet);
-      } else {
-        tssbond1(worktet, bcseg);
-      }
-      fnext(abdf, worktet); // fit a->f into d->f.
-      enext2self(worktet);
-      if (dfseg.sh == dummysh) {
-        tssdissolve1(worktet);
-      } else {
-        tssbond1(worktet, dfseg);
-      }
-      enext2fnext(abdf, worktet); // fit d->f into b->f.
-      enext2self(worktet);
-      if (bfseg.sh == dummysh) {
-        tssdissolve1(worktet);
-      } else {
-        tssbond1(worktet, bfseg);
-      }
-      enextfnext(abdf, worktet); // fit b->f into c->f.
-      enext2self(worktet);
-      if (cfseg.sh == dummysh) {
-        tssdissolve1(worktet);
-      } else {
-        tssbond1(worktet, cfseg);
-      }
-    }
-  }
-
-  // New vertex assignments for the rotated tetrahedra.
-  setorg(abce, pd); // Update abce to dcae
-  setdest(abce, pc);
-  setapex(abce, pa);
-  setorg(bade, pc); // Update bade to cdbe
-  setdest(bade, pd);
-  setapex(bade, pb);
-  if (mirrorflag) {
-    setorg(bacf, pc); // Update bacf to cdaf
-    setdest(bacf, pd);
-    setapex(bacf, pa);
-    setorg(abdf, pd); // Update abdf to dcbf
-    setdest(abdf, pc);
-    setapex(abdf, pb);
-  }
-
-  // Are there subfaces need to be flipped?
-  if (checksubfaces && abc.sh != dummysh) {
-#ifdef SELF_CHECK
-    assert(bad.sh != dummysh);
-#endif
-    // Adjust the edge be ab, so the rotation of subfaces is according with
-    //   the rotation of tetrahedra.
-    findedge(&abc, pa, pb);
-    // Flip an edge of two subfaces, ignore non-Delaunay edges.
-    flip22sub(&abc, NULL);
-  }
-
-  if (b->verbose > 3) {
-    printf("    Updating abce ");
-    printtet(&abce);
-    printf("    Updating bade ");
-    printtet(&bade);
-    if (mirrorflag) {
-      printf("    Updating bacf ");
-      printtet(&bacf);
-      printf("    Updating abdf ");
-      printtet(&abdf);
-    }
-  }
-
-  if (flipqueue != (queue *) NULL) { 
-    enextfnext(abce, bcecasing);
-    enqueueflipface(bcecasing, flipqueue);
-    enext2fnext(abce, caecasing);
-    enqueueflipface(caecasing, flipqueue);
-    enextfnext(bade, adecasing);
-    enqueueflipface(adecasing, flipqueue);
-    enext2fnext(bade, dbecasing);
-    enqueueflipface(dbecasing, flipqueue);
-    if (mirrorflag) {
-      enextfnext(bacf, acfcasing);
-      enqueueflipface(acfcasing, flipqueue);
-      enext2fnext(bacf, cbfcasing);
-      enqueueflipface(cbfcasing, flipqueue);
-      enextfnext(abdf, bdfcasing);
-      enqueueflipface(bdfcasing, flipqueue);
-      enext2fnext(abdf, dafcasing);
-      enqueueflipface(dafcasing, flipqueue);
-    }
-    // The two new faces dcae (abce), cdbe (bade) may still not be locally
-    //   Delaunay, and may need be flipped (flip23).  On the other hand, in
-    //   conforming Delaunay algorithm, two new subfaces dca (abc), and cdb
-    //   (bad) may be non-conforming Delaunay, they need be queued if they
-    //   are locally Delaunay but non-conforming Delaunay.
-    enqueueflipface(abce, flipqueue);
-    enqueueflipface(bade, flipqueue);
-  }
-
-  // Save a live handle in 'recenttet'.
-  recenttet = abce;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flip22sub()    Perform a 2-to-2 flip on a subface edge.                   //
-//                                                                           //
-// The flip edge is given by subface 'flipedge'.  Let it is abc, where ab is //
-// the flipping edge.  The other subface is bad,  where a, b, c, d form a    //
-// convex quadrilateral.  ab is not a subsegment.                            //
-//                                                                           //
-// A 2-to-2 subface flip is to change two subfaces abc and bad to another    //
-// two subfaces dca and cdb.  Hence, edge ab has been removed and dc becomes //
-// an edge. If a point e is above abc, this flip is equal to rotate abc and  //
-// bad counterclockwise using right-hand rule with thumb points to e. It is  //
-// important to know that the edge rings of the flipped subfaces dca and cdb //
-// are keeping the same orientation as their original subfaces. So they have //
-// the same orientation with respect to the lift point of this facet.        //
-//                                                                           //
-// During rotating, the face rings of the four edges bc, ca, ad, and de need //
-// be re-connected. If the edge is not a subsegment, then its face ring has  //
-// only two faces, a sbond() will bond them together. If it is a subsegment, //
-// one should use sbond1() twice to bond two different handles to the rotat- //
-// ing subface, one is predecssor (-casin), another is successor (-casout).  //
-//                                                                           //
-// If 'flipqueue' is not NULL, it returns four edges bc, ca, ad, de, which   //
-// may be non-Delaunay.                                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::flip22sub(face* flipedge, queue* flipqueue)
-{
-  face abc, bad;
-  face oldbc, oldca, oldad, olddb;
-  face bccasin, bccasout, cacasin, cacasout;
-  face adcasin, adcasout, dbcasin, dbcasout;
-  face bc, ca, ad, db;
-  face spinsh;
-  point pa, pb, pc, pd;
-
-  abc = *flipedge;
-  spivot(abc, bad);
-  if (sorg(bad) != sdest(abc)) {
-    sesymself(bad);
-  }
-  pa = sorg(abc);
-  pb = sdest(abc);
-  pc = sapex(abc);
-  pd = sapex(bad);
-
-  if (b->verbose > 2) {
-    printf("    Flip sub edge (%d, %d).\n", pointmark(pa), pointmark(pb));
-  }
-
-  // Save the old configuration outside the quadrilateral.  
-  senext(abc, oldbc);
-  senext2(abc, oldca);
-  senext(bad, oldad);
-  senext2(bad, olddb);
-  // Get the outside connection. Becareful if there is a subsegment on the
-  //   quadrilateral, two casings (casin and casout) are needed to save for
-  //   keeping the face link.
-  spivot(oldbc, bccasout);
-  sspivot(oldbc, bc);
-  if (bc.sh != dummysh) {
-    // 'bc' is a subsegment.
-    if (bccasout.sh != dummysh) {
-      if (oldbc.sh != bccasout.sh) {
-        // 'oldbc' is not self-bonded.
-        spinsh = bccasout;
-        do {
-          bccasin = spinsh;
-          spivotself(spinsh);
-        } while (spinsh.sh != oldbc.sh);
-      } else {
-        bccasout.sh = dummysh;
-      }
-    }
-    ssdissolve(oldbc);
-  }
-  spivot(oldca, cacasout);
-  sspivot(oldca, ca);
-  if (ca.sh != dummysh) {
-    // 'ca' is a subsegment.
-    if (cacasout.sh != dummysh) {
-      if (oldca.sh != cacasout.sh) {
-        // 'oldca' is not self-bonded.
-        spinsh = cacasout;
-        do {
-          cacasin = spinsh;
-          spivotself(spinsh);
-        } while (spinsh.sh != oldca.sh);
-      } else {
-        cacasout.sh = dummysh;
-      }
-    }
-    ssdissolve(oldca);
-  }
-  spivot(oldad, adcasout);
-  sspivot(oldad, ad);
-  if (ad.sh != dummysh) {
-    // 'ad' is a subsegment. 
-    if (adcasout.sh != dummysh) {
-      if (oldad.sh != adcasout.sh) {
-        // 'adcasout' is not self-bonded.
-        spinsh = adcasout;
-        do {
-          adcasin = spinsh;
-          spivotself(spinsh);
-        } while (spinsh.sh != oldad.sh);
-      } else {
-        adcasout.sh = dummysh;
-      }
-    }
-    ssdissolve(oldad);
-  }
-  spivot(olddb, dbcasout);
-  sspivot(olddb, db);
-  if (db.sh != dummysh) {
-    // 'db' is a subsegment.
-    if (dbcasout.sh != dummysh) {
-      if (olddb.sh != dbcasout.sh) {
-        // 'dbcasout' is not self-bonded.
-        spinsh = dbcasout;
-        do {
-          dbcasin = spinsh;
-          spivotself(spinsh);
-        } while (spinsh.sh != olddb.sh);
-      } else {
-        dbcasout.sh = dummysh;
-      }
-    }
-    ssdissolve(olddb);
-  }
-
-  // Rotate abc and bad one-quarter turn counterclockwise.
-  if (ca.sh != dummysh) {
-    if (cacasout.sh != dummysh) {
-      sbond1(cacasin, oldbc);
-      sbond1(oldbc, cacasout);
-    } else {
-      // Bond 'oldbc' to itself.
-      sbond(oldbc, oldbc);
-      // Make sure that dummysh always correctly bonded.
-      dummysh[0] = sencode(oldbc);
-    }
-    ssbond(oldbc, ca);
-  } else {
-    sbond(oldbc, cacasout);
-  }
-  if (ad.sh != dummysh) {
-    if (adcasout.sh != dummysh) {
-      sbond1(adcasin, oldca);
-      sbond1(oldca, adcasout);
-    } else {
-      // Bond 'oldca' to itself.
-      sbond(oldca, oldca);
-      // Make sure that dummysh always correctly bonded.
-      dummysh[0] = sencode(oldca);
-    }
-    ssbond(oldca, ad);
-  } else {
-    sbond(oldca, adcasout);
-  }
-  if (db.sh != dummysh) {
-    if (dbcasout.sh != dummysh) {
-      sbond1(dbcasin, oldad);
-      sbond1(oldad, dbcasout);
-    } else {
-      // Bond 'oldad' to itself.
-      sbond(oldad, oldad);
-      // Make sure that dummysh always correctly bonded.
-      dummysh[0] = sencode(oldad);
-    }
-    ssbond(oldad, db);
-  } else {
-    sbond(oldad, dbcasout);
-  }
-  if (bc.sh != dummysh) {
-    if (bccasout.sh != dummysh) {
-      sbond1(bccasin, olddb);
-      sbond1(olddb, bccasout);
-    } else {
-      // Bond 'olddb' to itself.
-      sbond(olddb, olddb);
-      // Make sure that dummysh always correctly bonded.
-      dummysh[0] = sencode(olddb);
-    }
-    ssbond(olddb, bc);
-  } else {
-    sbond(olddb, bccasout);
-  }
-
-  // New vertex assignments for the rotated subfaces.
-  setsorg(abc, pd);  // Update abc to dca.
-  setsdest(abc, pc);
-  setsapex(abc, pa);
-  setsorg(bad, pc);  // Update bad to cdb.
-  setsdest(bad, pd);
-  setsapex(bad, pb);
-
-  if (flipqueue != (queue *) NULL) {
-    enqueueflipedge(bccasout, flipqueue);
-    enqueueflipedge(cacasout, flipqueue);
-    enqueueflipedge(adcasout, flipqueue);
-    enqueueflipedge(dbcasout, flipqueue);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flip()    Flips non-locally Delaunay faces in flipqueue until it is empty.//
-//                                                                           //
-// Assumpation:  Current tetrahedralization is non-Delaunay after inserting  //
-// a point or performing a flip operation, all possibly non-Delaunay faces   //
-// are in 'flipqueue'.                                                       //
-//                                                                           //
-// If 'plastflip' is not NULL,  it is used to return a stack of recently     //
-// flipped faces.  This stack will be used to reverse the flips done in this //
-// routine later for removing a newly inserted point because it encroaches   //
-// any subfaces or subsegments.                                              //
-//                                                                           //
-// The return value is the total number of flips done during this invocation.//
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-long tetgenmesh::flip(queue* flipqueue, badface **plastflip)
-{
-  badface *qface, *newflip;
-  triface flipface, symface;
-  point pa, pb, pc, pd, pe;
-  enum fliptype fc;
-  REAL sign, bakepsilon;
-  long flipcount, maxfaces;
-  int epscount, fcount;
-  int ia, ib, ic, id, ie;
-
-  if (b->verbose > 1) {
-    printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
-  }
-
-  flipcount = flip23s + flip32s + flip22s + flip44s;
-  if (checksubfaces) {
-    maxfaces = (4l * tetrahedrons->items + hullsize) / 2l;
-    fcount = 0;
-  }
-
-  if (plastflip != (badface **) NULL) {
-    // Initialize the stack of the flip sequence.
-    flipstackers->restart();
-    *plastflip = (badface *) NULL;
-  }
-
-  // Loop until the queue is empty.
-  while (!flipqueue->empty()) {
-    qface = (badface *) flipqueue->pop();
-    flipface = qface->tt;
-    if (isdead(&flipface)) continue;
-    sym(flipface, symface);
-    // Only do check when the adjacent tet exists and it's not a "fake" tet.
-    if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
-      // For positive orientation that insphere() test requires.
-      adjustedgering(flipface, CW);
-      pa = org(flipface);
-      pb = dest(flipface);
-      pc = apex(flipface);
-      pd = oppo(flipface);
-      pe = oppo(symface);
-      if (symbolic) {
-        ia = pointmark(pa);
-        ib = pointmark(pb);
-        ic = pointmark(pc);
-        id = pointmark(pd);
-        ie = pointmark(pe);
-        sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
-        assert(sign != 0.0);
-      } else {  
-        sign = insphere(pa, pb, pc, pd, pe);
-      }
-    } else {
-      sign = -1.0; // A hull face is locally Delaunay.
-    }
-    if (sign > 0.0) {
-      // 'flipface' is non-locally Delaunay, try to flip it.     
-      if (checksubfaces) {
-        fcount++;
-        bakepsilon = b->epsilon;
-        epscount = 0;
-        while (epscount < 32) {
-          fc = categorizeface(flipface);
-          if (fc == N40) {
-            b->epsilon *= 1e-1;
-            epscount++;
-            continue;
-          }
-          break;
-        }
-        b->epsilon = bakepsilon;
-        if (epscount >= 32) {
-          if (b->verbose > 0) {
-            printf("Warning:  Can't flip a degenerate tetrahedron.\n");
-          }
-          fc = N40;
-        }
-      } else {
-        fc = categorizeface(flipface);
-#ifdef SELF_CHECK
-        assert(fc != N40);
-#endif
-      }
-      switch (fc) {
-      // The following face types are flipable.
-      case T44:
-      case T22:
-        flip22(&flipface, flipqueue); 
-        break;
-      case T23:
-        flip23(&flipface, flipqueue); 
-        break;
-      case T32:
-        flip32(&flipface, flipqueue); 
-        break;
-      // The following face types are unflipable.
-      case N32:
-        break;
-      case FORBIDDENFACE:
-        break;
-      case FORBIDDENEDGE:
-        break;
-      // This case is only possible when the domain is nonconvex.
-      case N40:
-        // assert(nonconvex);
-        break;
-      }
-      if (plastflip != (badface **) NULL) {
-        if ((fc == T44) || (fc == T22) || (fc == T23) || (fc == T32)) { 
-          // Push the flipped face into stack.
-          newflip = (badface *) flipstackers->alloc();
-          newflip->tt = flipface;
-          newflip->key = (REAL) fc;
-          newflip->forg = org(flipface);
-          newflip->fdest = dest(flipface);
-          newflip->fapex = apex(flipface);
-          newflip->previtem = *plastflip;
-          *plastflip = newflip; 
-        }
-      }
-    }
-  }
-
-  flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
-  if (b->verbose > 1) {
-    printf("    %ld flips.\n", flipcount);
-  }
-
-  return flipcount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// lawson()    Flip locally non-Delaunay faces by Lawson's algorithm.        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-long tetgenmesh::lawson(list *misseglist, queue* flipqueue)
-{
-  badface *qface, *misseg;
-  triface flipface, symface;
-  triface starttet, spintet;
-  face checksh, checkseg;
-  point pa, pb, pc, pd, pe;
-  point swappt;
-  REAL sign, ori;
-  long flipcount;
-  int ia, ib, ic, id, ie;  
-  int hitbdry, i;
-
-  if (b->verbose > 1) {
-    printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
-  }
-  flipcount = flip23s + flip32s + flip22s + flip44s;
-
-  // Go through the stack of possible flips and decide whether to do them.
-  //   Note that during the loop new possible flips will be pushed onto
-  //   this stack, while they popped in this loop.
-  while (!flipqueue->empty()) {
-    qface = (badface *) flipqueue->pop();
-    flipface = qface->tt;
-    // Check if tet has already been flipped out of existence.
-    if (!isdead(&flipface)) {
-      sym(flipface, symface);
-      // Check if this tet is the same as the one which was stacked.
-      if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
-        flipface.ver = 0; // Select the CCW ring.
-        pa = org(flipface);
-        pb = dest(flipface);
-        pc = apex(flipface);
-        pd = oppo(flipface);
-        pe = oppo(symface);
-        if (symbolic) {
-          ia = pointmark(pa);
-          ib = pointmark(pb);
-          ic = pointmark(pc);
-          id = pointmark(pd);
-          ie = pointmark(pe);
-          sign = insphere_sos(pb, pa, pc, pd, pe, ib, ia, ic, id, ie);
-        } else {
-          sign = insphere(pb, pa, pc, pd, pe);
-        }
-        if (sign > 0.0) {
-          for (i = 0; i < 3; i++) {
-            ori = orient3d(pa, pb, pd, pe);
-            if (ori > 0.0) {
-              // Goto and check the next edge.
-              swappt = pa;
-              pa = pb;
-              pb = pc;
-              pc = swappt;
-              enextself(flipface);
-            } else {
-              break; // either (ori < 0.0) or (ori == 0.0)
-            }
-          } // for (i = 0; ....)
-          if (ori > 0.0) {
-            // All three edges are convex, a 2-3 flip is possible.
-            if (checksubfaces) {
-              tspivot(flipface, checksh);
-              if (checksh.sh != dummysh) {
-                // A subface is not flipable.
-                continue;
-              }
-            }
-            flip23(&flipface, flipqueue);
-          } else if (ori < 0.0) {
-            // The edge (a, b) is non-convex, check for a 3-2 flip.
-            fnext(flipface, symface);
-            symself(symface);
-            if (oppo(symface) == pe) {
-              // Only three tets adjoining this edge.
-              if (checksubfaces) {
-                tsspivot(&flipface, &checkseg);
-                if (checkseg.sh != dummysh) {
-                  // A subsegment is not flipable.
-                  continue;
-                }
-              } else if (checksubsegs) {
-                tsspivot1(flipface, checkseg);
-                if (checkseg.sh != dummysh) {
-                  if (b->verbose > 2) {
-                    printf("    Queuing missing segment (%d, %d).\n",
-                      pointmark(org(flipface)), pointmark(dest(flipface)));
-                  }
-                  misseg = (badface *) misseglist->append(NULL);
-                  misseg->ss = checkseg;
-                  misseg->forg = sorg(checkseg);
-                  misseg->fdest = sdest(checkseg);
-                  // Detach all tets having this seg.
-                  starttet = flipface;
-                  adjustedgering(starttet, CCW);
-                  fnextself(starttet);
-                  spintet = starttet;
-                  hitbdry = 0;
-                  do {
-                    tssdissolve1(spintet);
-                    if (!fnextself(spintet)) {
-                      hitbdry++;
-                      if (hitbdry < 2) {
-                        esym(starttet, spintet);
-                        if (!fnextself(spintet)) {
-                          hitbdry++;
-                        }
-                      }
-                    }
-                  } while ((apex(spintet) != apex(starttet)) && (hitbdry < 2));
-                }
-              } // if (checksubfaces)
-              flip32(&flipface, flipqueue);
-            }
-          } else {
-            // Four points (a, b, d, e) are coplanar.
-            fnext(flipface, symface);
-            if (fnextself(symface)) {
-              // Check for a 4-4 flip.
-              fnextself(symface);
-              if (apex(symface) == pe) {
-                if (checksubfaces) {
-                  tsspivot(&flipface, &checkseg);
-                  if (checkseg.sh != dummysh) {
-                    // A subsegment is not flippable.
-                    continue;
-                  }
-                } else if (checksubsegs) {
-                  tsspivot1(flipface, checkseg);
-                  if (checkseg.sh != dummysh) {
-                    if (b->verbose > 2) {
-                      printf("    Queuing missing segment (%d, %d).\n",
-                        pointmark(org(flipface)), pointmark(dest(flipface)));
-                    }
-                    misseg = (badface *) misseglist->append(NULL);
-                    misseg->ss = checkseg;
-                    misseg->forg = sorg(checkseg);
-                    misseg->fdest = sdest(checkseg);
-                    // Detach all tets having this seg.
-                    starttet = flipface;
-                    adjustedgering(starttet, CCW);
-                    fnextself(starttet);
-                    spintet = starttet;
-                    hitbdry = 0;
-                    do {
-                      tssdissolve1(spintet);
-                      if (!fnextself(spintet)) {
-                        hitbdry++;
-                        if (hitbdry < 2) {
-                          esym(starttet, spintet);
-                          if (!fnextself(spintet)) {
-                            hitbdry++;
-                          }
-                        }
-                      }
-                    } while ((apex(spintet) != apex(starttet)) && 
-                             (hitbdry < 2));
-                  }
-                } // if (checksubfaces) 
-                flip22(&flipface, flipqueue);
-              }
-            } else {
-              // Check for a 2-2 flip.
-              esym(flipface, symface);
-              fnextself(symface);
-              symself(symface);
-              if (symface.tet == dummytet) {
-                if (checksubfaces) {
-                  tsspivot(&flipface, &checkseg);
-                  if (checkseg.sh != dummysh) {
-                    // A subsegment is not flipable.
-                    continue;
-                  }
-                } else if (checksubsegs) {
-                  tsspivot1(flipface, checkseg);
-                  if (checkseg.sh != dummysh) {
-                    if (b->verbose > 2) {
-                      printf("    Queuing missing segment (%d, %d).\n",
-                        pointmark(org(flipface)), pointmark(dest(flipface)));
-                    }
-                    misseg = (badface *) misseglist->append(NULL);
-                    misseg->ss = checkseg;
-                    misseg->forg = sorg(checkseg);
-                    misseg->fdest = sdest(checkseg);
-                    // Detach all tets having this seg.
-                    starttet = flipface;
-                    adjustedgering(starttet, CCW);
-                    fnextself(starttet);
-                    spintet = starttet;
-                    hitbdry = 0;
-                    do {
-                      tssdissolve1(spintet);
-                      if (!fnextself(spintet)) {
-                        hitbdry++;
-                        if (hitbdry < 2) {
-                          esym(starttet, spintet);
-                          if (!fnextself(spintet)) {
-                            hitbdry++;
-                          }
-                        }
-                      }
-                    } while ((apex(spintet) != apex(starttet)) && 
-                             (hitbdry < 2));
-                  }
-                } // if (checksubfaces)
-                flip22(&flipface, flipqueue);
-              }
-            }
-          } // if (ori > 0.0)
-        } // if (sign > 0.0)
-      }
-    } // !isdead(&qface->tt)
-  } // while (!flipqueue->empty())
-
-  flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
-  if (b->verbose > 1) {
-    printf("    %ld flips.\n", flipcount);
-  }
-  return flipcount;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// undoflip()    Undo the most recent flip sequence induced by flip().       //
-//                                                                           //
-// 'lastflip' is the stack of recently flipped faces. Walks through the list //
-// of flips, in the reverse of the order in which they were done, and undoes //
-// them.                                                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::undoflip(badface *lastflip)
-{
-  enum fliptype fc;
-
-  while (lastflip != (badface *) NULL) {
-    // Get the right flipped face.
-    findface(&lastflip->tt, lastflip->forg, lastflip->fdest, lastflip->fapex);
-    fc = (enum fliptype) (int) lastflip->key;
-    switch (fc) {
-    case T23:
-      // The reverse operation of T23 is T32.
-      flip32(&lastflip->tt, NULL);
-      break;
-    case T32:
-      // The reverse operation of T32 is T23.
-      flip23(&lastflip->tt, NULL);
-      break;
-    case T22:
-    case T44:
-      // The reverse operation of T22 or T44 is again T22 or T44.
-      flip22(&lastflip->tt, NULL);
-      break;
-    default: // To omit compile warnings.
-      break;
-    }
-    // Go on and process the next transformation.
-    lastflip = lastflip->previtem;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flipsub()    Flip non-Delaunay edges in a queue of (coplanar) subfaces.   //
-//                                                                           //
-// Assumpation:  Current triangulation T contains non-Delaunay edges (after  //
-// inserting a point or performing a flip). Non-Delaunay edges are queued in //
-// 'facequeue'. Returns the total number of flips done during this call.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-long tetgenmesh::flipsub(queue* flipqueue)
-{
-  badface *qedge;
-  face flipedge, symedge;
-  face checkseg;
-  point pa, pb, pc, pd;
-  REAL vab[3], vac[3], vad[3];
-  REAL dot1, dot2, lac, lad; 
-  REAL sign, ori;
-  int edgeflips;
-  int i;
-
-  if (b->verbose > 1) {
-    printf("  Start do edge queue: %ld edges.\n", flipqueue->len());
-  }
-
-  edgeflips = 0;
-
-  while (!flipqueue->empty()) {
-    qedge = (badface *) flipqueue->pop();
-    flipedge = qedge->ss;
-    if (flipedge.sh == dummysh) continue;
-    if ((sorg(flipedge) != qedge->forg) || 
-        (sdest(flipedge) != qedge->fdest)) continue; 
-    sspivot(flipedge, checkseg);
-    if (checkseg.sh != dummysh) continue;  // Can't flip a subsegment.
-    spivot(flipedge, symedge);
-    if (symedge.sh == dummysh) continue; // Can't flip a hull edge.
-    pa = sorg(flipedge);
-    pb = sdest(flipedge);
-    pc = sapex(flipedge);
-    pd = sapex(symedge);
-    // Choose the triangle abc or abd as the base depending on the angle1
-    //   (Vac, Vab) and angle2 (Vad, Vab).
-    for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
-    for (i = 0; i < 3; i++) vac[i] = pc[i] - pa[i];
-    for (i = 0; i < 3; i++) vad[i] = pd[i] - pa[i];
-    dot1 = dot(vac, vab);
-    dot2 = dot(vad, vab);
-    dot1 *= dot1;
-    dot2 *= dot2;
-    lac = dot(vac, vac);
-    lad = dot(vad, vad);
-    if (lad * dot1 <= lac * dot2) {
-      // angle1 is closer to 90 than angle2, choose abc (flipedge).
-      abovepoint = facetabovepointarray[shellmark(flipedge)];
-      if (abovepoint == (point) NULL) {
-        getfacetabovepoint(&flipedge);
-      }
-      sign = insphere(pa, pb, pc, abovepoint, pd);
-      ori = orient3d(pa, pb, pc, abovepoint);
-    } else {
-      // angle2 is closer to 90 than angle1, choose abd (symedge).
-      abovepoint = facetabovepointarray[shellmark(symedge)];
-      if (abovepoint == (point) NULL) {
-        getfacetabovepoint(&symedge);
-      }
-      sign = insphere(pa, pb, pd, abovepoint, pc);
-      ori = orient3d(pa, pb, pd, abovepoint);
-    }
-    // Correct the sign.
-    sign = ori > 0.0 ? sign : -sign;
-    if (sign > 0.0) {
-      // Flip the non-Delaunay edge.
-      flip22sub(&flipedge, flipqueue);
-      edgeflips++;
-    }
-  }
-
-  if (b->verbose > 1) {
-    printf("  Total %d flips.\n", edgeflips);
-  }
-
-  return edgeflips;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// removetetbypeeloff()    Remove a boundary tet by peeling it off.          //
-//                                                                           //
-// 'striptet' (abcd) is on boundary and can be removed by stripping it off.  //
-// Let abc and bad are the external boundary faces.                          //
-//                                                                           //
-// To strip 'abcd' from the mesh is to detach its two interal faces (dca and //
-// cdb) from their adjoining tets together with a 2-to-2 flip to transform   //
-// two subfaces (abc and bad) into another two (dca and cdb).                //
-//                                                                           //
-// In mesh optimization. It is possible that ab is a segment and abcd is a   //
-// sliver on the hull. Strip abcd will also delete the segment ab.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::removetetbypeeloff(triface *striptet)
-{
-  triface abcd, badc;
-  triface dcacasing, cdbcasing;
-  face abc, bad;
-  face abseg;
-  REAL ang;
-  
-  abcd = *striptet;
-  adjustedgering(abcd, CCW);
-  // Get the casing tets at the internal sides.
-  enextfnext(abcd, cdbcasing);
-  enext2fnext(abcd, dcacasing);
-  symself(cdbcasing);
-  symself(dcacasing);  
-  // Do the neighboring tets exist?  During optimization. It is possible
-  //   that the neighboring tets are already dead.
-  if ((cdbcasing.tet == dummytet) || (dcacasing.tet == dummytet)) {
-    // Do not strip this tet.
-    return false;
-  }
-
-  // Are there subfaces?
-  if (checksubfaces) {
-    // Get the external subfaces abc, bad.
-    fnext(abcd, badc);
-    esymself(badc);
-    tspivot(abcd, abc);
-    tspivot(badc, bad);
-    if (abc.sh != dummysh) { 
-      assert(bad.sh != dummysh);
-      findedge(&abc, org(abcd), dest(abcd));
-      findedge(&bad, org(badc), dest(badc));
-      // Is ab a segment?
-      sspivot(abc, abseg);
-      if (abseg.sh != dummysh) {
-        // Does a segment allow to be removed?
-        if ((b->optlevel > 3) && (b->nobisect == 0)) {
-          // Only remove this segment if the dihedal angle at ab is between
-          //   [b->maxdihedral-9, 180] (deg).  This avoids mistakely fliping
-          //   ab when it has actually no big dihedral angle while cd has.
-          ang = facedihedral(org(abcd), dest(abcd), apex(abcd), oppo(abcd));
-          ang = ang * 180.0 / PI;
-          if ((ang + 9.0) > b->maxdihedral) {
-            if (b->verbose > 1) {
-              printf("    Remove a segment during peeling.\n");
-            }
-            face prevseg, nextseg;
-            // It is only shared by abc and bad (abcd is a tet).
-            ssdissolve(abc);
-            ssdissolve(bad);
-            abseg.shver = 0;
-            senext(abseg, nextseg);
-            spivotself(nextseg);
-            if (nextseg.sh != dummysh) {
-              ssdissolve(nextseg);
-            }
-            senext2(abseg, prevseg);
-            spivotself(prevseg);
-            if (prevseg.sh != dummysh) {
-              ssdissolve(prevseg);
-            }
-            shellfacedealloc(subsegs, abseg.sh);
-            optcount[1]++;
-          } else {
-            return false;
-          }
-        } else {
-          return false;
-        }
-      }
-      // Do a 2-to-2 flip on abc and bad, transform abc->dca, bad->cdb.
-      flip22sub(&abc, NULL);
-      // The two internal faces become boundary faces.
-      tsbond(cdbcasing, bad);
-      tsbond(dcacasing, abc);
-    }
-  }
-  
-  // Detach abcd from the two internal faces.
-  dissolve(cdbcasing);
-  dissolve(dcacasing);
-  // Delete abcd.
-  tetrahedrondealloc(abcd.tet);
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// removeedgebyflip22()    Remove an edge by a 2-to-2 (or 4-to-4) flip.      //
-//                                                                           //
-// 'abtetlist' contains n tets (n is 2 or 4) sharing edge ab,  abtetlist[0]  //
-// and abtetlist[1] are tets abec and abde, respectively (NOTE, both are in  //
-// CW edge ring), where a, b, c, and d are coplanar.  If n = 4, abtetlist[2] //
-// and abtetlist[3] are tets abfd and abcf, respectively.  This routine uses //
-// flip22() to replace edge ab with cd, the surrounding tets are rotated.    //
-//                                                                           //
-// If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
-// local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
-// is the maximum dihedral angle in the old tets.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::removeedgebyflip22(REAL *key, int n, triface *abtetlist,
-  queue *flipque)
-{
-  point pa, pb, pc, pd, pe, pf;
-  REAL cosmaxd, d1, d2, d3;
-  bool doflip;
-
-  doflip = true;
-  adjustedgering(abtetlist[0], CW);
-  pa = org(abtetlist[0]);
-  pb = dest(abtetlist[0]);
-  pe = apex(abtetlist[0]);
-  pc = oppo(abtetlist[0]);
-  pd = apex(abtetlist[1]);
-  if (n == 4) {
-    pf = apex(abtetlist[2]);
-  }
-  if (key && (*key > -1.0)) {
-    tetalldihedral(pc, pd, pe, pa, NULL, &d1, NULL);
-    tetalldihedral(pd, pc, pe, pb, NULL, &d2, NULL);
-    cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
-    if (n == 4) {
-      tetalldihedral(pd, pc, pf, pa, NULL, &d1, NULL);
-      tetalldihedral(pc, pd, pf, pb, NULL, &d2, NULL);
-      d3 = d1 < d2 ? d1 : d2; // Choose the bigger angle.
-      cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
-    }
-    doflip = (*key < cosmaxd); // Can local quality be improved?
-  }
-
-  if (doflip) {
-    flip22(&abtetlist[0], NULL);
-    // Return the improved quality value.
-    if (key) *key = cosmaxd;
-  }
-
-  return doflip;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// removefacebyflip23()    Remove a face by a 2-to-3 flip.                   //
-//                                                                           //
-// 'abctetlist' contains 2 tets sharing abc, which are [0]abcd and [1]bace.  //
-// This routine forms three new tets that abc is not a face anymore. Save    //
-// them in 'newtetlist': [0]edab, [1]edbc, and [2]edca.  Note that the new   //
-// tets may not valid if one of them get inverted. return false if so.       //
-//                                                                           //
-// If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
-// local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
-// is the maximum dihedral angle in the old tets.                            //
-//                                                                           //
-// If the face is flipped, 'newtetlist' returns the three new tets. The two  //
-// tets in 'abctetlist' are NOT deleted.  The caller has the right to either //
-// delete them or reverse the operation.                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::removefacebyflip23(REAL *key, triface *abctetlist,
-  triface *newtetlist, queue *flipque)
-{
-  triface edab, edbc, edca; // new configuration.
-  triface newfront, oldfront, adjfront;
-  face checksh;
-  point pa, pb, pc, pd, pe;
-  REAL ori, cosmaxd, d1, d2, d3;
-  REAL attrib, volume;
-  bool doflip;
-  int i;
-
-  adjustedgering(abctetlist[0], CCW);
-  pa = org(abctetlist[0]);
-  pb = dest(abctetlist[0]);
-  pc = apex(abctetlist[0]);
-  pd = oppo(abctetlist[0]);  
-  pe = oppo(abctetlist[1]);
-
-  // Check if the flip creates valid new tets.
-  ori = orient3d(pe, pd, pa, pb);
-  if (ori < 0.0) {
-    ori = orient3d(pe, pd, pb, pc);
-    if (ori < 0.0) {
-      ori = orient3d(pe, pd, pc, pa);
-    }
-  }
-  doflip = (ori < 0.0); // Can abc be flipped away?
-  if (doflip && (key != (REAL *) NULL)) {
-    if (*key > -1.0) {
-      // Test if the new tets reduce the maximal dihedral angle.
-      tetalldihedral(pe, pd, pa, pb, NULL, &d1, NULL);
-      tetalldihedral(pe, pd, pb, pc, NULL, &d2, NULL);
-      tetalldihedral(pe, pd, pc, pa, NULL, &d3, NULL);
-      cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
-      cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
-      doflip = (*key < cosmaxd); // Can local quality be improved?
-    }
-  }
-
-  if (doflip) {
-    // A valid (2-to-3) flip is found.
-    flip23s++;
-    // Create the new tets.
-    maketetrahedron(&edab);
-    setorg(edab, pe);
-    setdest(edab, pd);
-    setapex(edab, pa);
-    setoppo(edab, pb);
-    maketetrahedron(&edbc);
-    setorg(edbc, pe);
-    setdest(edbc, pd);
-    setapex(edbc, pb);
-    setoppo(edbc, pc);
-    maketetrahedron(&edca);
-    setorg(edca, pe);
-    setdest(edca, pd);
-    setapex(edca, pc);
-    setoppo(edca, pa);
-    // Transfer the element attributes.
-    for (i = 0; i < in->numberoftetrahedronattributes; i++) {
-      attrib = elemattribute(abctetlist[0].tet, i);
-      setelemattribute(edab.tet, i, attrib);
-      setelemattribute(edbc.tet, i, attrib);
-      setelemattribute(edca.tet, i, attrib);
-    }
-    // Transfer the volume constraints.
-    if (b->varvolume && !b->refine) {
-      volume = volumebound(abctetlist[0].tet);
-      setvolumebound(edab.tet, volume);
-      setvolumebound(edbc.tet, volume);
-      setvolumebound(edca.tet, volume);
-    }
-    // Return two new tets.
-    newtetlist[0] = edab;
-    newtetlist[1] = edbc;
-    newtetlist[2] = edca;
-    // Glue the three new tets.
-    for (i = 0; i < 3; i++) {
-      fnext(newtetlist[i], newfront);
-      bond(newfront, newtetlist[(i + 1) % 3]);
-    }
-    // Substitute the three new tets into the old cavity.
-    for (i = 0; i < 3; i++) {
-      fnext(abctetlist[0], oldfront);
-      sym(oldfront, adjfront); // may be outside.
-      enextfnext(newtetlist[i], newfront);
-      bond(newfront, adjfront);
-      if (checksubfaces) {
-        tspivot(oldfront, checksh);
-        if (checksh.sh != dummysh) {
-          tsbond(newfront, checksh);
-        }
-      }
-      if (flipque != (queue *) NULL) {
-        enqueueflipface(newfront, flipque);
-      }
-      enextself(abctetlist[0]);
-    }
-    findedge(&(abctetlist[1]), pb, pa);
-    for (i = 0; i < 3; i++) {
-      fnext(abctetlist[1], oldfront);
-      sym(oldfront, adjfront); // may be outside.
-      enext2fnext(newtetlist[i], newfront);
-      bond(newfront, adjfront);
-      if (checksubfaces) {
-        tspivot(oldfront, checksh);
-        if (checksh.sh != dummysh) {
-          tsbond(newfront, checksh);
-        }
-      }
-      if (flipque != (queue *) NULL) {
-        enqueueflipface(newfront, flipque);
-      }
-      enext2self(abctetlist[1]);
-    }
-    // Do not delete the old tets.
-    // for (i = 0; i < 2; i++) {
-    //   tetrahedrondealloc(abctetlist[i].tet);
-    // }
-    // Return the improved quality value.
-    if (key != (REAL *) NULL) *key = cosmaxd;
-    return true;
-  }
-
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// removeedgebyflip32()    Remove an edge by a 3-to-2 flip.                  //
-//                                                                           //
-// 'abtetlist' contains 3 tets sharing ab. Imaging that ab is perpendicular  //
-// to the screen, where a lies in front of and b lies behind it. The 3 tets  //
-// of the list are: [0]abce, [1]abdc, and [2]abed, respectively.             //
-//                                                                           //
-// This routine forms two new tets that ab is not an edge of them. Save them //
-// in 'newtetlist', [0]dcea, [1]cdeb. Note that the new tets may not valid   //
-// if one of them get inverted. return false if so.                          //
-//                                                                           //
-// If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
-// local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
-// is the maximum dihedral angle in the old tets.                            //
-//                                                                           //
-// If the edge is flipped, 'newtetlist' returns the two new tets. The three  //
-// tets in 'abtetlist' are NOT deleted.  The caller has the right to either  //
-// delete them or reverse the operation.                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::removeedgebyflip32(REAL *key, triface *abtetlist,
-  triface *newtetlist, queue *flipque)
-{
-  triface dcea, cdeb; // new configuration.
-  triface newfront, oldfront, adjfront;
-  face checksh;
-  point pa, pb, pc, pd, pe;
-  REAL ori, cosmaxd, d1, d2;
-  REAL attrib, volume;
-  bool doflip;
-  int i;
-
-  pa = org(abtetlist[0]);
-  pb = dest(abtetlist[0]);
-  pc = apex(abtetlist[0]);
-  pd = apex(abtetlist[1]);
-  pe = apex(abtetlist[2]);
-
-  ori = orient3d(pd, pc, pe, pa);
-  if (ori < 0.0) {
-    ori = orient3d(pc, pd, pe, pb);
-  }
-  doflip = (ori < 0.0); // Can ab be flipped away?
-
-  // Does the caller ensure a valid configuration?
-  if (doflip && (key != (REAL *) NULL)) {    
-    if (*key > -1.0) {
-      // Test if the new tets reduce the maximal dihedral angle.
-      tetalldihedral(pd, pc, pe, pa, NULL, &d1, NULL);
-      tetalldihedral(pc, pd, pe, pb, NULL, &d2, NULL);
-      cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
-      doflip = (*key < cosmaxd); // Can local quality be improved?
-      // Return the key
-      *key = cosmaxd;
-    }
-  }
-
-  if (doflip) {
-    // Create the new tets.
-    maketetrahedron(&dcea);
-    setorg(dcea, pd);
-    setdest(dcea, pc);
-    setapex(dcea, pe);
-    setoppo(dcea, pa);
-    maketetrahedron(&cdeb);
-    setorg(cdeb, pc);
-    setdest(cdeb, pd);
-    setapex(cdeb, pe);
-    setoppo(cdeb, pb);
-    // Transfer the element attributes.
-    for (i = 0; i < in->numberoftetrahedronattributes; i++) {
-      attrib = elemattribute(abtetlist[0].tet, i);
-      setelemattribute(dcea.tet, i, attrib);
-      setelemattribute(cdeb.tet, i, attrib);
-    }
-    // Transfer the volume constraints.
-    if (b->varvolume && !b->refine) {
-      volume = volumebound(abtetlist[0].tet);
-      setvolumebound(dcea.tet, volume);
-      setvolumebound(cdeb.tet, volume);
-    }
-    // Return two new tets.
-    newtetlist[0] = dcea;
-    newtetlist[1] = cdeb;
-    // Glue the two new tets.
-    bond(dcea, cdeb);
-    // Substitute the two new tets into the old three-tets cavity.
-    for (i = 0; i < 3; i++) {
-      fnext(dcea, newfront); // face dca, cea, eda.
-      esym(abtetlist[(i + 1) % 3], oldfront);
-      enextfnextself(oldfront);
-      // Get the adjacent tet at the face (may be a dummytet).
-      sym(oldfront, adjfront);
-      bond(newfront, adjfront);
-      if (checksubfaces) {
-        tspivot(oldfront, checksh);
-        if (checksh.sh != dummysh) {
-          tsbond(newfront, checksh);
-        }
-      }
-      if (flipque != (queue *) NULL) {
-        enqueueflipface(newfront, flipque);
-      }
-      enext2self(dcea);
-    }
-    for (i = 0; i < 3; i++) {
-      fnext(cdeb, newfront); // face cdb, deb, ecb.
-      esym(abtetlist[(i + 1) % 3], oldfront);
-      enext2fnextself(oldfront);
-      // Get the adjacent tet at the face (may be a dummytet).
-      sym(oldfront, adjfront);
-      bond(newfront, adjfront);
-      if (checksubfaces) {
-        tspivot(oldfront, checksh);
-        if (checksh.sh != dummysh) {
-          tsbond(newfront, checksh);
-        }
-      }
-      if (flipque != (queue *) NULL) {
-        enqueueflipface(newfront, flipque);
-      }
-      enextself(cdeb);
-    }
-    // Do not delete the old tets.
-    // for (i = 0; i < 3; i++) {
-    //   tetrahedrondealloc(abtetlist[i].tet);
-    // }
-    return true;
-  } // if (doflip)
-
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// removeedgebytranNM()    Remove an edge by transforming n-to-m tets.       //
-//                                                                           //
-// This routine attempts to remove a given edge (ab) by transforming the set //
-// T of tets surrounding ab into another set T' of tets.  T and T' have the  //
-// same outer faces and ab is not an edge of T' anymore. Let |T|=n, and |T'| //
-// =m, it is actually a n-to-m flip for n > 3.  The relation between n and m //
-// depends on the method, ours is found below.                               //
-//                                                                           //
-// 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
-// to the screen, where a lies in front of and b lies behind it.  Let the    //
-// projections of the n apexes onto screen in clockwise order are: p_0, ...  //
-// p_n-1, respectively. The tets in the list are: [0]abp_0p_n-1,[1]abp_1p_0, //
-// ..., [n-1]abp_n-1p_n-2, respectively.                                     //
-//                                                                           //
-// The principle of the approach is: Recursively reduce the link of ab by    //
-// using flip23 until only three faces remain, hence a flip32 can be applied //
-// to remove ab. For a given face a.b.p_0, check a flip23 can be applied on  //
-// it, i.e, edge p_1.p_n-1 crosses it. NOTE*** We do the flip even p_1.p_n-1 //
-// intersects with a.b (they are coplanar). If so, a degenerate tet (a.b.p_1.//
-// p_n-1) is temporarily created, but it will be eventually removed by the   //
-// final flip32. This relaxation splits a flip44 into flip23 + flip32. *NOTE //
-// Now suppose a.b.p_0 gets flipped, p_0 is not on the link of ab anymore.   //
-// The link is then reduced (by 1). 2 of the 3 new tets, p_n-1.p_1.p_0.a and //
-// p_1.p_n-1.p_0.b, will be part of the new configuration.  The left new tet,//
-// a.b.p_1.p_n-1, goes into the new link of ab. A recurrence can be applied. //
-//                                                                           //
-// If 'e1' and 'e2' are not NULLs, they specify an wanted edge to appear in  //
-// the new tet configuration. In such case, only do flip23 if edge e1<->e2   //
-// can be recovered. It is used in removeedgebycombNM().                     //
-//                                                                           //
-// If ab gets removed. 'newtetlist' contains m new tets.  By using the above //
-// approach, the pairs (n, m) can be easily enumerated.  For example, (3, 2),//
-// (4, 4), (5, 6), (6, 8), (7, 10), (8, 12), (9, 14), (10, 16),  and so on.  //
-// It is easy to deduce, that m = (n - 2) * 2, when n >= 3.  The n tets in   //
-// 'abtetlist' are NOT deleted in this routine. The caller has the right to  //
-// either delete them or reverse this operation.                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::removeedgebytranNM(REAL *key, int n, triface *abtetlist,
-  triface *newtetlist, point e1, point e2, queue *flipque)
-{
-  triface tmpabtetlist[9]; // Temporary max 9 tets configuration.
-  triface newfront, oldfront, adjfront;
-  face checksh;
-  point pa, pb, p[10];
-  REAL ori, cosmaxd, d1, d2;
-  REAL tmpkey;
-  REAL attrib, volume;
-  bool doflip, copflag, success;
-  int i, j, k;
-
-  // Maximum 10 tets.
-  assert(n <= 10);
-  // Two points a and b are fixed.
-  pa = org(abtetlist[0]);
-  pb = dest(abtetlist[0]);
-  // The points p_0, p_1, ..., p_n-1 are permuted in each new configuration.
-  //   These permutations can be easily done in the following loop.
-  // Loop through all the possible new tets configurations. Stop on finding
-  //   a valid new tet configuration which also immproves the quality value.
-  for (i = 0; i < n; i++) {
-    // Get other n points for the current configuration.
-    for (j = 0; j < n; j++) {
-      p[j] = apex(abtetlist[(i + j) % n]);
-    }
-    // Is there a wanted edge?
-    if ((e1 != (point) NULL) && (e2 != (point) NULL)) {
-      // Yes. Skip this face if p[1]<->p[n-1] is not the edge.
-      if (!(((p[1] == e1) && (p[n - 1] == e2)) ||
-	    ((p[1] == e2) && (p[n - 1] == e1)))) continue;
-    }
-    // Test if face a.b.p_0 can be flipped (by flip23), ie, to check if the
-    //   edge p_n-1.p_1 crosses face a.b.p_0 properly.
-    // Note. It is possible that face a.b.p_0 has type flip44, ie, a,b,p_1,
-    //   and p_n-1 are coplanar. A trick is to split the flip44 into two
-    //   steps: frist a flip23, then a flip32. The first step creates a
-    //   degenerate tet (vol=0) which will be removed by the second flip.
-    ori = orient3d(pa, pb, p[1], p[n - 1]);
-    copflag = (ori == 0.0); // Are they coplanar?
-    if (ori >= 0.0) {
-      // Accept the coplanar case which supports flip44.
-      ori = orient3d(pb, p[0], p[1], p[n - 1]);
-      if (ori > 0.0) {
-        ori = orient3d(p[0], pa, p[1], p[n - 1]);
-      }
-    }
-    // Is face abc flipable?
-    if (ori > 0.0) {
-      // A valid (2-to-3) flip (or 4-to-4 flip) is found.
-      copflag ? flip44s++ : flip23s++;
-      doflip = true;
-      if (key != (REAL *) NULL) {
-        if (*key > -1.0) {
-          // Test if the new tets reduce the maximal dihedral angle. Only 2
-          //   tets, p_n-1.p_1.p_0.a and p_1.p_n-1.p_0.b, need to be tested
-          //   The left one a.b.p_n-1.p_1 goes into the new link of ab.
-          tetalldihedral(p[n - 1], p[1], p[0], pa, NULL, &d1, NULL);
-          tetalldihedral(p[1], p[n - 1], p[0], pb, NULL, &d2, NULL);
-          cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
-          doflip = *key < cosmaxd; // Can the local quality be improved?
-        }
-      }
-      if (doflip) {
-        tmpkey = key != NULL ? *key : -1.0;
-        // Create the two new tets.
-        maketetrahedron(&(newtetlist[0]));
-        setorg(newtetlist[0], p[n - 1]);
-        setdest(newtetlist[0], p[1]);
-        setapex(newtetlist[0], p[0]);
-        setoppo(newtetlist[0], pa);
-        maketetrahedron(&(newtetlist[1]));
-        setorg(newtetlist[1], p[1]);
-        setdest(newtetlist[1], p[n - 1]);
-        setapex(newtetlist[1], p[0]);
-        setoppo(newtetlist[1], pb);
-        // Create the n - 1 temporary new tets (the new Star(ab)).
-        maketetrahedron(&(tmpabtetlist[0]));
-        setorg(tmpabtetlist[0], pa);
-        setdest(tmpabtetlist[0], pb);
-        setapex(tmpabtetlist[0], p[n - 1]);
-        setoppo(tmpabtetlist[0], p[1]);
-        for (j = 1; j < n - 1; j++) {
-          maketetrahedron(&(tmpabtetlist[j]));
-          setorg(tmpabtetlist[j], pa);
-          setdest(tmpabtetlist[j], pb);
-          setapex(tmpabtetlist[j], p[j]);
-          setoppo(tmpabtetlist[j], p[j + 1]);
-        }
-        // Transfer the element attributes.
-        for (j = 0; j < in->numberoftetrahedronattributes; j++) {
-          attrib = elemattribute(abtetlist[0].tet, j);
-          setelemattribute(newtetlist[0].tet, j, attrib);
-          setelemattribute(newtetlist[1].tet, j, attrib);
-          for (k = 0; k < n - 1; k++) {
-            setelemattribute(tmpabtetlist[k].tet, j, attrib);
-          }
-        }
-        // Transfer the volume constraints.
-        if (b->varvolume && !b->refine) {
-          volume = volumebound(abtetlist[0].tet);
-          setvolumebound(newtetlist[0].tet, volume);
-          setvolumebound(newtetlist[1].tet, volume);
-          for (k = 0; k < n - 1; k++) {
-            setvolumebound(tmpabtetlist[k].tet, volume);
-          }
-        }
-        // Glue the new tets at their internal faces: 2 + (n - 1).
-        bond(newtetlist[0], newtetlist[1]); // p_n-1.p_1.p_0.
-        fnext(newtetlist[0], newfront);
-        enext2fnext(tmpabtetlist[0], adjfront);
-        bond(newfront, adjfront); // p_n-1.p_1.a.
-        fnext(newtetlist[1], newfront);
-        enextfnext(tmpabtetlist[0], adjfront);
-        bond(newfront, adjfront); // p_n-1.p_1.b.
-        // Glue n - 1 internal faces around ab.
-        for (j = 0; j < n - 1; j++) {
-          fnext(tmpabtetlist[j], newfront);
-          bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
-        }
-        // Substitute the old tets with the new tets by connecting the new
-        //   tets to the adjacent tets in the mesh. There are n * 2 (outer)
-        //   faces of the new tets need to be operated.
-        // Note, after the substitution, the old tets still have pointers to
-        //   their adjacent tets in the mesh.  These pointers can be re-used
-        //   to inverse the substitution.
-        for (j = 0; j < n; j++) {
-          // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
-          oldfront = abtetlist[(i + j) % n];
-          esymself(oldfront);
-          enextfnextself(oldfront);
-          // Get an adjacent tet at face: [0]a.p_0.p_n-1 or [j]a.p_j.p_j-1.
-          sym(oldfront, adjfront); // adjfront may be dummy.
-          // Get the corresponding face from the new tets.
-          if (j == 0) {
-            enext2fnext(newtetlist[0], newfront); // a.p_0.n_n-1
-          } else if (j == 1) {
-            enextfnext(newtetlist[0], newfront); // a.p_1.p_0
-          } else { // j >= 2.
-            enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
-          }
-          bond(newfront, adjfront);
-          if (checksubfaces) {
-            tspivot(oldfront, checksh); 
-            if (checksh.sh != dummysh) {
-              tsbond(newfront, checksh);
-            }
-          }
-          if (flipque != (queue *) NULL) {
-            // Only queue the faces of the two new tets.
-            if (j < 2) enqueueflipface(newfront, flipque);
-          }
-        }
-        for (j = 0; j < n; j++) {
-          // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
-          oldfront = abtetlist[(i + j) % n];
-          esymself(oldfront);
-          enext2fnextself(oldfront);
-          // Get an adjacent tet at face: [0]b.p_0.p_n-1 or [j]b.p_j.p_j-1.
-          sym(oldfront, adjfront); // adjfront may be dummy.
-          // Get the corresponding face from the new tets.
-          if (j == 0) {
-            enextfnext(newtetlist[1], newfront); // b.p_0.n_n-1
-          } else if (j == 1) {
-            enext2fnext(newtetlist[1], newfront); // b.p_1.p_0
-          } else { // j >= 2.
-            enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
-          }
-          bond(newfront, adjfront);
-          if (checksubfaces) {
-            tspivot(oldfront, checksh); 
-            if (checksh.sh != dummysh) {
-              tsbond(newfront, checksh);
-            }
-          }
-          if (flipque != (queue *) NULL) {
-            // Only queue the faces of the two new tets.
-            if (j < 2) enqueueflipface(newfront, flipque);
-          }
-        }
-        // Adjust the faces in the temporary new tets at ab for recursively
-        //   processing on the n-1 tets.(See the description at beginning)
-        for (j = 0; j < n - 1; j++) {
-          fnextself(tmpabtetlist[j]);
-        }
-        if (n > 4) {
-          success = removeedgebytranNM(&tmpkey, n-1, tmpabtetlist,
-            &(newtetlist[2]), NULL, NULL, flipque);
-        } else { // assert(n == 4);
-          success = removeedgebyflip32(&tmpkey, tmpabtetlist,
-            &(newtetlist[2]), flipque);
-        }
-        // No matter it was success or not, delete the temporary tets.
-        for (j = 0; j < n - 1; j++) {
-          tetrahedrondealloc(tmpabtetlist[j].tet);
-        }
-        if (success) {
-          // The new configuration is good. 
-          // Do not delete the old tets.
-          // for (j = 0; j < n; j++) {
-          //   tetrahedrondealloc(abtetlist[j].tet);
-          // }
-          // Save the minimal improved quality value.
-          if (key != (REAL *) NULL) {
-            *key = (tmpkey < cosmaxd ? tmpkey : cosmaxd);
-          }
-          return true;
-        } else {
-          // The new configuration is bad, substitue back the old tets.
-          for (j = 0; j < n; j++) {
-            oldfront = abtetlist[(i + j) % n];
-            esymself(oldfront);
-            enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
-            sym(oldfront, adjfront); // adjfront may be dummy.
-            bond(oldfront, adjfront);
-            if (checksubfaces) {
-              tspivot(oldfront, checksh);
-              if (checksh.sh != dummysh) {
-                tsbond(oldfront, checksh);
-              }
-            }
-          }
-          for (j = 0; j < n; j++) {
-            oldfront = abtetlist[(i + j) % n];
-            esymself(oldfront);
-            enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
-            sym(oldfront, adjfront); // adjfront may be dummy
-            bond(oldfront, adjfront);
-            if (checksubfaces) {
-              tspivot(oldfront, checksh);
-              if (checksh.sh != dummysh) {
-                tsbond(oldfront, checksh);
-              }
-            }
-          }
-          // Delete the new tets.
-          tetrahedrondealloc(newtetlist[0].tet);
-          tetrahedrondealloc(newtetlist[1].tet);
-          // If tmpkey has been modified, then the failure was not due to
-          //   unflipable configuration, but the non-improvement.
-          if (key && (tmpkey < *key)) {
-            *key = tmpkey;
-            return false;
-          }
-        } // if (success)
-      } // if (doflip)
-    } // if (ori > 0.0)
-  } // for (i = 0; i < n; i++)
-
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// removeedgebycombNM()    Remove an edge by combining two flipNMs.          //
-//                                                                           //
-// Given a set T of tets surrounding edge ab. The premise is that ab can not //
-// be removed by a flipNM. This routine attempts to remove ab by two flipNMs,//
-// i.e., first find and flip an edge af (or bf) by flipNM, then flip ab by   //
-// flipNM. If it succeeds, two sets T(ab) and T(af) of tets are replaced by  //
-// a new set T' and both ab and af are not edges in T' anymore.              //
-//                                                                           //
-// 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
-// to the screen, such that a lies in front of and b lies behind it. Let the //
-// projections of the n apexes on the screen in clockwise order are: p_0,...,//
-// p_n-1, respectively. So the list of tets are: [0]abp_0p_n-1, [1]abp_1p_0, //
-// ..., [n-1]abp_n-1p_n-2, respectively.                                     //
-//                                                                           //
-// The principle of the approach is: for a face a.b.p_0, check if edge b.p_0 //
-// is of type N32 (or N44). If it is, then try to do a flipNM on it. If the  //
-// flip is successful, then try to do another flipNM on a.b.  If one of the  //
-// two flipNMs fails, restore the old tets as they have never been flipped.  //
-// Then try the next face a.b.p_1.  The process can be looped for all faces  //
-// having ab. Stop if ab is removed or all faces have been visited. Note in  //
-// the above description only b.p_0 is considered, a.p_0 is done by swapping //
-// the position of a and b.                                                  //
-//                                                                           //
-// Similar operations have been described in [Joe,1995].  My approach checks //
-// more cases for finding flips than Joe's.  For instance, the cases (1)-(7) //
-// of Joe only consider abf for finding a flip (T23/T32).  My approach looks //
-// all faces at ab for finding flips. Moreover, the flipNM can flip an edge  //
-// whose star may have more than 3 tets while Joe's only works on 3-tet case.//
-//                                                                           //
-// If ab is removed, 'newtetlist' contains the new tets. Two sets 'abtetlist'//
-// (n tets) and 'bftetlist' (n1 tets) have been replaced.  The number of new //
-// tets can be calculated by follows: the 1st flip transforms n1 tets into   //
-// (n1 - 2) * 2 new tets, however,one of the new tets goes into the new link //
-// of ab, i.e., the reduced tet number in Star(ab) is n - 1;  the 2nd flip   //
-// transforms n - 1 tets into (n - 3) * 2 new tets. Hence the number of new  //
-// tets are: m = ((n1 - 2) * 2 - 1) + (n - 3) * 2.  The old tets are NOT del-//
-// eted. The caller has the right to delete them or reverse the operation.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::removeedgebycombNM(REAL *key, int n, triface *abtetlist,
-  int *n1, triface *bftetlist, triface *newtetlist, queue *flipque)
-{
-  triface tmpabtetlist[11];
-  triface newfront, oldfront, adjfront;
-  face checksh;
-  point pa, pb, p[10];
-  REAL ori, tmpkey, tmpkey2;
-  REAL attrib, volume;
-  bool doflip, success;
-  int twice, count;
-  int i, j, k, m;
-
-  // Maximal 10 tets in Star(ab).
-  assert(n <= 10);
-
-  // Do the following procedure twice, one for flipping edge b.p_0 and the
-  //   other for p_0.a which is symmetric to the first.
-  twice = 0;
-  do {
-    // Two points a and b are fixed.
-    pa = org(abtetlist[0]);
-    pb = dest(abtetlist[0]);
-    // The points p_0, ..., p_n-1 are permuted in the following loop.
-    for (i = 0; i < n; i++) {
-      // Get the n points for the current configuration.
-      for (j = 0; j < n; j++) {
-        p[j] = apex(abtetlist[(i + j) % n]);
-      }
-      // Check if b.p_0 is of type N32 or N44.
-      ori = orient3d(pb, p[0], p[1], p[n - 1]);
-      if ((ori > 0) && (key != (REAL *) NULL)) {
-        // b.p_0 is not N32. However, it is possible that the tet b.p_0.p_1.
-        //   p_n-1 has worse quality value than the key. In such case, also
-        //   try to flip b.p_0.
-        tetalldihedral(pb, p[0], p[n - 1], p[1], NULL, &tmpkey, NULL);
-        if (tmpkey < *key) ori = 0.0;
-      }
-      if (ori <= 0.0) {
-        // b.p_0 is either N32 or N44. Try the 1st flipNM.
-        bftetlist[0] = abtetlist[i];
-        enextself(bftetlist[0]);// go to edge b.p_0.
-        adjustedgering(bftetlist[0], CW); // edge p_0.b.
-        assert(apex(bftetlist[0]) == pa);
-        // Form Star(b.p_0).
-        doflip = true;
-        *n1 = 0;
-        do {
-          // Is the list full?
-          if (*n1 == 10) break;
-          if (checksubfaces) {
-            // Stop if a subface appears.
-            tspivot(bftetlist[*n1], checksh);
-            if (checksh.sh != dummysh) {
-              doflip = false; break;
-            }
-          }
-          // Get the next tet at p_0.b.
-          fnext(bftetlist[*n1], bftetlist[(*n1) + 1]);
-          (*n1)++;
-        } while (apex(bftetlist[*n1]) != pa);
-        // 2 <= n1 <= 10.
-        if (doflip) {
-          success = false;
-          tmpkey = -1.0;  // = acos(pi).
-          if (key != (REAL *) NULL) tmpkey = *key;
-          m = 0;
-          if (*n1 == 3) {
-            // Three tets case. Try flip32.
-            success = removeedgebyflip32(&tmpkey,bftetlist,newtetlist,flipque);
-            m = 2;
-          } else if ((*n1 > 3) && (*n1 < 7)) {
-            // Four or more tets case. Try flipNM.
-            success = removeedgebytranNM(&tmpkey, *n1, bftetlist, newtetlist,
-                                         p[1], p[n - 1], flipque);
-            // If success, the number of new tets.
-            m = ((*n1) - 2) * 2;
-          } else {
-            if (b->verbose > 1) {
-              printf("  !! Unhandled case: n1 = %d.\n", *n1);
-            }
-          }
-          if (success) {
-            // b.p_0 is flipped. The link of ab is reduced (by 1), i.e., p_0
-            //   is not on the link of ab. Two old tets a.b.p_0.p_n-1 and
-            //   a.b.p_1.p_0 have been removed from the Star(ab) and one new
-            //   tet t = a.b.p_1.p_n-1 belongs to Star(ab). 
-            // Find t in the 'newtetlist' and remove it from the list.
-            setpointmark(pa, -pointmark(pa) - 1);
-            setpointmark(pb, -pointmark(pb) - 1);
-            assert(m > 0);
-            for (j = 0; j < m; j++) {
-              tmpabtetlist[0] = newtetlist[j];
-              // Does it has ab?
-              count = 0;
-              for (k = 0; k < 4; k++) {
-                if (pointmark((point)(tmpabtetlist[0].tet[4+k])) < 0) count++;
-              }
-              if (count == 2) {
-                // It is. Adjust t to be the edge ab.
-                for (tmpabtetlist[0].loc = 0; tmpabtetlist[0].loc < 4;
-                     tmpabtetlist[0].loc++) {
-                  if ((oppo(tmpabtetlist[0]) != pa) &&
-                      (oppo(tmpabtetlist[0]) != pb)) break;
-                }
-                // The face of t must contain ab.
-                assert(tmpabtetlist[0].loc < 4);
-                findedge(&(tmpabtetlist[0]), pa, pb);
-                break;
-              }
-            }
-            assert(j < m); // The tet must exist.
-            // Remove t from list. Fill t's position by the last tet.
-            newtetlist[j] = newtetlist[m - 1];
-            setpointmark(pa, -(pointmark(pa) + 1));
-            setpointmark(pb, -(pointmark(pb) + 1));
-            // Create the temporary Star(ab) for the next flipNM.
-            adjustedgering(tmpabtetlist[0], CCW);
-            if (org(tmpabtetlist[0]) != pa) {
-              fnextself(tmpabtetlist[0]);
-              esymself(tmpabtetlist[0]);
-            }
-#ifdef SELF_CHECK
-            // Make sure current edge is a->b.
-            assert(org(tmpabtetlist[0]) == pa);
-            assert(dest(tmpabtetlist[0]) == pb);
-            assert(apex(tmpabtetlist[0]) == p[n - 1]);
-            assert(oppo(tmpabtetlist[0]) == p[1]);
-#endif // SELF_CHECK
-            // There are n - 2 left temporary tets.
-            for (j = 1; j < n - 1; j++) {
-              maketetrahedron(&(tmpabtetlist[j]));
-              setorg(tmpabtetlist[j], pa);
-              setdest(tmpabtetlist[j], pb);
-              setapex(tmpabtetlist[j], p[j]);
-              setoppo(tmpabtetlist[j], p[j + 1]);
-            }
-            // Transfer the element attributes.
-            for (j = 0; j < in->numberoftetrahedronattributes; j++) {
-              attrib = elemattribute(abtetlist[0].tet, j);
-              for (k = 0; k < n - 1; k++) {
-                setelemattribute(tmpabtetlist[k].tet, j, attrib);
-              }
-            }
-            // Transfer the volume constraints.
-            if (b->varvolume && !b->refine) {
-              volume = volumebound(abtetlist[0].tet);
-              for (k = 0; k < n - 1; k++) {
-                setvolumebound(tmpabtetlist[k].tet, volume);
-              }
-            }
-            // Glue n - 1 internal faces of Star(ab).
-            for (j = 0; j < n - 1; j++) {
-              fnext(tmpabtetlist[j], newfront);
-              bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
-            }
-            // Substitute the old tets with the new tets by connecting the
-            //   new tets to the adjacent tets in the mesh. There are (n-2)
-            //   * 2 (outer) faces of the new tets need to be operated.
-            // Note that the old tets still have the pointers to their
-            //   adjacent tets in the mesh.  These pointers can be re-used
-            //   to inverse the substitution.
-            for (j = 2; j < n; j++) {
-              // Get an old tet: [j]a.b.p_j.p_j-1, (j > 1).
-              oldfront = abtetlist[(i + j) % n];
-              esymself(oldfront);
-              enextfnextself(oldfront);
-              // Get an adjacent tet at face: [j]a.p_j.p_j-1.
-              sym(oldfront, adjfront); // adjfront may be dummy.
-              // Get the corresponding face from the new tets.
-              // j >= 2.
-              enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
-              bond(newfront, adjfront);
-              if (checksubfaces) {
-                tspivot(oldfront, checksh); 
-                if (checksh.sh != dummysh) {
-                  tsbond(newfront, checksh);
-                }
-              }
-            }
-            for (j = 2; j < n; j++) {
-              // Get an old tet: [j]a.b.p_j.p_j-1, (j > 2).
-              oldfront = abtetlist[(i + j) % n];
-              esymself(oldfront);
-              enext2fnextself(oldfront);
-              // Get an adjacent tet at face: [j]b.p_j.p_j-1.
-              sym(oldfront, adjfront); // adjfront may be dummy.
-              // Get the corresponding face from the new tets.
-              // j >= 2.
-              enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
-              bond(newfront, adjfront);
-              if (checksubfaces) {
-                tspivot(oldfront, checksh); 
-                if (checksh.sh != dummysh) {
-                  tsbond(newfront, checksh);
-                }
-              }
-            }
-            // Adjust the faces in the temporary new tets at ab for
-            //   recursively processing on the n-1 tets.
-            for (j = 0; j < n - 1; j++) {
-              fnextself(tmpabtetlist[j]);
-            }
-            tmpkey2 = -1;
-            if (key) tmpkey2 = *key;
-            if ((n - 1) == 3) {
-              success = removeedgebyflip32(&tmpkey2, tmpabtetlist,
-                &(newtetlist[m - 1]), flipque);
-            } else { // assert((n - 1) >= 4);
-              success = removeedgebytranNM(&tmpkey2, n - 1, tmpabtetlist,
-                &(newtetlist[m - 1]), NULL, NULL, flipque);
-            }
-            // No matter it was success or not, delete the temporary tets.
-            for (j = 0; j < n - 1; j++) {
-              tetrahedrondealloc(tmpabtetlist[j].tet);
-            }
-            if (success) {
-              // The new configuration is good. 
-              // Do not delete the old tets.
-              // for (j = 0; j < n; j++) {
-              //   tetrahedrondealloc(abtetlist[j].tet);
-              // }
-              // Return the bigger dihedral in the two sets of new tets.
-              if (key != (REAL *) NULL) {
-                *key = tmpkey2 < tmpkey ? tmpkey2 : tmpkey;
-              }
-              return true;
-            } else {
-              // The new configuration is bad, substitue back the old tets.
-              for (j = 0; j < n; j++) {
-                oldfront = abtetlist[(i + j) % n];
-                esymself(oldfront);
-                enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
-                sym(oldfront, adjfront); // adjfront may be dummy.
-                bond(oldfront, adjfront);
-                if (checksubfaces) {
-                  tspivot(oldfront, checksh);
-                  if (checksh.sh != dummysh) {
-                    tsbond(oldfront, checksh);
-                  }
-                }
-              }
-              for (j = 0; j < n; j++) {
-                oldfront = abtetlist[(i + j) % n];
-                esymself(oldfront);
-                enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
-                sym(oldfront, adjfront); // adjfront may be dummy
-                bond(oldfront, adjfront);
-                if (checksubfaces) {
-                  tspivot(oldfront, checksh);
-                  if (checksh.sh != dummysh) {
-                    tsbond(oldfront, checksh);
-                  }
-                }
-              }
-              // Substitute back the old tets of the first flip.
-              for (j = 0; j < *n1; j++) {
-                oldfront = bftetlist[j];
-                esymself(oldfront);
-                enextfnextself(oldfront);
-                sym(oldfront, adjfront); // adjfront may be dummy.
-                bond(oldfront, adjfront);
-                if (checksubfaces) {
-                  tspivot(oldfront, checksh);
-                  if (checksh.sh != dummysh) {
-                    tsbond(oldfront, checksh);
-                  }
-                }
-              }
-              for (j = 0; j < *n1; j++) {
-                oldfront = bftetlist[j];
-                esymself(oldfront);
-                enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
-                sym(oldfront, adjfront); // adjfront may be dummy
-                bond(oldfront, adjfront);
-                if (checksubfaces) {
-                  tspivot(oldfront, checksh);
-                  if (checksh.sh != dummysh) {
-                    tsbond(oldfront, checksh);
-                  }
-                }
-              }
-              // Delete the new tets of the first flip. Note that one new
-              //   tet has already been removed from the list.
-              for (j = 0; j < m - 1; j++) {
-                tetrahedrondealloc(newtetlist[j].tet);
-              }
-            } // if (success)
-          } // if (success)
-        } // if (doflip)
-      } // if (ori <= 0.0)
-    } // for (i = 0; i < n; i++)
-    // Inverse a and b and the tets configuration.
-    for (i = 0; i < n; i++) newtetlist[i] = abtetlist[i];
-    for (i = 0; i < n; i++) {
-      oldfront = newtetlist[n - i - 1];
-      esymself(oldfront);
-      fnextself(oldfront);
-      abtetlist[i] = oldfront;
-    }
-    twice++;
-  } while (twice < 2);
-
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// splittetrahedron()    Insert a point into a tetrahedron, split it into    //
-//                       four tetrahedra.                                    //
-//                                                                           //
-// The tetrahedron is given by 'splittet'.  Let it is abcd.  The inserting   //
-// point 'newpoint' v should lie strictly inside abcd.                       //
-//                                                                           //
-// Splitting a tetrahedron is to shrink abcd to abcv,  and create three new  //
-// tetrahedra badv, cbdv, and acdv.                                          //
-//                                                                           //
-// On completion, 'splittet' returns abcv.  If 'flipqueue' is not NULL, it   //
-// contains all possibly non-locally Delaunay faces.                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::splittetrahedron(point newpoint, triface* splittet,
-  queue* flipqueue)
-{
-  triface oldabd, oldbcd, oldcad;                      // Old configuration.
-  triface abdcasing, bcdcasing, cadcasing;
-  face abdsh, bcdsh, cadsh;
-  triface abcv, badv, cbdv, acdv;                      // New configuration.
-  triface worktet;
-  face abseg, bcseg, caseg;
-  face adseg, bdseg, cdseg;
-  point pa, pb, pc, pd;
-  REAL attrib, volume;
-  int i;
-
-  abcv = *splittet;
-  abcv.ver = 0;
-  // Set the changed vertices and new tetrahedron.
-  pa = org(abcv);
-  pb = dest(abcv);
-  pc = apex(abcv);
-  pd = oppo(abcv);
-
-  if (b->verbose > 1) {
-    printf("  Inserting point %d in tetrahedron (%d, %d, %d, %d).\n",
-           pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc),
-           pointmark(pd));
-  }
-
-  fnext(abcv, oldabd);
-  enextfnext(abcv, oldbcd);
-  enext2fnext(abcv, oldcad);
-  sym(oldabd, abdcasing);
-  sym(oldbcd, bcdcasing);
-  sym(oldcad, cadcasing);
-  maketetrahedron(&badv);
-  maketetrahedron(&cbdv);
-  maketetrahedron(&acdv);
-
-  // Set 'badv' vertices.
-  setorg (badv, pb);
-  setdest(badv, pa);
-  setapex(badv, pd);
-  setoppo(badv, newpoint);
-  // Set 'cbdv' vertices.
-  setorg (cbdv, pc);
-  setdest(cbdv, pb);
-  setapex(cbdv, pd);
-  setoppo(cbdv, newpoint);
-  // Set 'acdv' vertices.
-  setorg (acdv, pa);
-  setdest(acdv, pc);
-  setapex(acdv, pd);
-  setoppo(acdv, newpoint);
-  // Set 'abcv' vertices
-  setoppo(abcv, newpoint);
-
-  // Set the element attributes of the new tetrahedra.
-  for (i = 0; i < in->numberoftetrahedronattributes; 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 tetrahedra.
-  if (b->varvolume) {
-    volume = volumebound(abcv.tet);
-    setvolumebound(badv.tet, volume);
-    setvolumebound(cbdv.tet, volume);
-    setvolumebound(acdv.tet, volume);
-  }
-
-  // Bond the new triangles to the surrounding tetrahedron.
-  bond(badv, abdcasing);
-  bond(cbdv, bcdcasing);
-  bond(acdv, cadcasing);
-  // There may exist subfaces need to be bonded to the new tetrahedra.
-  if (checksubfaces) {
-    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);
-    }
-  } else if (checksubsegs) {
-    tsspivot1(abcv, abseg);
-    if (abseg.sh != dummysh) {
-      tssbond1(badv, abseg);
-    }
-    enext(abcv, worktet);
-    tsspivot1(worktet, bcseg);
-    if (bcseg.sh != dummysh) {
-      tssbond1(cbdv, bcseg);
-    }
-    enext2(abcv, worktet);
-    tsspivot1(worktet, caseg);
-    if (caseg.sh != dummysh) {
-      tssbond1(acdv, caseg);
-    }
-    fnext(abcv, worktet);
-    enext2self(worktet);
-    tsspivot1(worktet, adseg);
-    if (adseg.sh != dummysh) {
-      tssdissolve1(worktet);
-      enext(badv, worktet);
-      tssbond1(worktet, adseg);
-      enext2(acdv, worktet);
-      tssbond1(worktet, adseg);
-    }
-    enextfnext(abcv, worktet);
-    enext2self(worktet);
-    tsspivot1(worktet, bdseg);
-    if (bdseg.sh != dummysh) {
-      tssdissolve1(worktet);
-      enext(cbdv, worktet);
-      tssbond1(worktet, bdseg);
-      enext2(badv, worktet);
-      tssbond1(worktet, bdseg);
-    }
-    enext2fnext(abcv, worktet);
-    enext2self(worktet);
-    tsspivot1(worktet, cdseg);
-    if (cdseg.sh != dummysh) {
-      tssdissolve1(worktet);
-      enext(acdv, worktet);
-      tssbond1(worktet, cdseg);
-      enext2(cbdv, worktet);
-      tssbond1(worktet, cdseg);
-    }
-  }
-  badv.loc = 3; 
-  cbdv.loc = 2;
-  bond(badv, cbdv);
-  cbdv.loc = 3; 
-  acdv.loc = 2;
-  bond(cbdv, acdv);
-  acdv.loc = 3; 
-  badv.loc = 2;
-  bond(acdv, badv);
-  badv.loc = 1; 
-  bond(badv, oldabd);
-  cbdv.loc = 1; 
-  bond(cbdv, oldbcd);
-  acdv.loc = 1; 
-  bond(acdv, oldcad);
-  
-  badv.loc = 0;
-  cbdv.loc = 0;
-  acdv.loc = 0;
-  if (b->verbose > 3) {
-    printf("    Updating abcv ");
-    printtet(&abcv);
-    printf("    Creating badv ");
-    printtet(&badv);
-    printf("    Creating cbdv ");
-    printtet(&cbdv);
-    printf("    Creating acdv ");
-    printtet(&acdv);
-  }
-
-  if (flipqueue != (queue *) NULL) {
-    enqueueflipface(abcv, flipqueue);
-    enqueueflipface(badv, flipqueue);
-    enqueueflipface(cbdv, flipqueue);
-    enqueueflipface(acdv, flipqueue);
-  }
-
-  // Save a handle for quick point location.
-  recenttet = abcv;
-  // Set the return handle be abcv.
-  *splittet = abcv;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// unsplittetrahedron()    Reverse the operation of inserting a point into a //
-//                         tetrahedron, so as to remove the newly inserted   //
-//                         point from the mesh.                              //
-//                                                                           //
-// Assume the origional tetrahedron is abcd, it was split by v into four     //
-// tetrahedra abcv, badv, cbdv, and acdv. 'splittet' represents face abc of  //
-// abcv (i.e., its opposite is v).                                           //
-//                                                                           //
-// Point v is removed by expanding abcv to abcd, deleting three tetrahedra   //
-// badv, cbdv and acdv.  On return, point v is not deleted in this routine.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::unsplittetrahedron(triface* splittet)
-{
-  triface abcv, badv, cbdv, acdv;
-  triface oldabv, oldbcv, oldcav;
-  triface badcasing, cbdcasing, acdcasing;
-  face badsh, cbdsh, acdsh;
-
-  abcv = *splittet;
-  adjustedgering(abcv, CCW);  // for sure.
-  fnext(abcv, oldabv);
-  fnext(oldabv, badv);
-  esymself(badv);
-  enextfnext(abcv, oldbcv);
-  fnext(oldbcv, cbdv);
-  esymself(cbdv);
-  enext2fnext(abcv, oldcav);
-  fnext(oldcav, acdv);
-  esymself(acdv);
-
-  if (b->verbose > 1) {
-    printf("  Removing point %d in tetrahedron (%d, %d, %d, %d).\n",
-           pointmark(oppo(abcv)), pointmark(org(abcv)), pointmark(dest(abcv)),
-           pointmark(apex(abcv)), pointmark(apex(badv)));
-  }
-
-  sym(badv, badcasing);
-  tspivot(badv, badsh);
-  sym(cbdv, cbdcasing);
-  tspivot(cbdv, cbdsh);
-  sym(acdv, acdcasing);
-  tspivot(acdv, acdsh);
-
-  // Expanding abcv to abcd.
-  setoppo(abcv, apex(badv));
-  bond(oldabv, badcasing);
-  if (badsh.sh != dummysh) {
-    tsbond(oldabv, badsh);
-  }
-  bond(oldbcv, cbdcasing);
-  if (cbdsh.sh != dummysh) {
-    tsbond(oldbcv, cbdsh);
-  }
-  bond(oldcav, acdcasing);
-  if (acdsh.sh != dummysh) {
-    tsbond(oldcav, acdsh);
-  }
-
-  // Delete the three split-out tetrahedra.
-  tetrahedrondealloc(badv.tet);
-  tetrahedrondealloc(cbdv.tet);
-  tetrahedrondealloc(acdv.tet);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// splittetface()    Insert a point on a face of a mesh.                     //
-//                                                                           //
-// 'splittet' is the splitting face.  Let it is abcd, where abc is the face  //
-// will be split. If abc is not a hull face, abce is the tetrahedron at the  //
-// opposite of d.                                                            //
-//                                                                           //
-// To split face abc by a point v is to shrink the tetrahedra abcd to abvd,  //
-// create two new tetrahedra bcvd, cavd.  If abc is not a hull face, shrink  //
-// the tetrahedra bace to bave, create two new tetrahedra cbve, acve.        //
-//                                                                           //
-// If abc is a subface, it is split into three subfaces simultaneously by    //
-// calling routine splitsubface(), hence, abv, bcv, cav.  The edge rings of  //
-// the split subfaces have the same orientation as abc's.                    //
-//                                                                           //
-// On completion, 'splittet' returns abvd.  If 'flipqueue' is not NULL, it   //
-// contains all possibly non-locally Delaunay faces.                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::splittetface(point newpoint, triface* splittet,
-  queue* flipqueue)
-{
-  triface abcd, bace;                                  // Old configuration.
-  triface oldbcd, oldcad, oldace, oldcbe; 
-  triface bcdcasing, cadcasing, acecasing, cbecasing;
-  face abcsh, bcdsh, cadsh, acesh, cbesh;
-  triface abvd, bcvd, cavd, bave, cbve, acve;          // New configuration.
-  triface worktet;
-  face bcseg, caseg;
-  face adseg, bdseg, cdseg;
-  face aeseg, beseg, ceseg;
-  point pa, pb, pc, pd, pe;
-  REAL attrib, volume;
-  bool mirrorflag;
-  int i;
-
-  abcd = *splittet;
-  // abcd.ver = 0; // Adjust to be CCW edge ring.
-  adjustedgering(abcd, CCW);
-  pa = org(abcd);
-  pb = dest(abcd);
-  pc = apex(abcd);
-  pd = oppo(abcd);
-  pe = (point) NULL; // avoid a compile warning.
-  // Is there a second tetrahderon?
-  mirrorflag = issymexist(&abcd);
-  if (mirrorflag) {
-    // This is an interior face.
-    sym(abcd, bace);
-    findedge(&bace, dest(abcd), org(abcd));
-    pe = oppo(bace);
-  }
-  if (checksubfaces) {
-    // Is there a subface need to be split together?
-    tspivot(abcd, abcsh);
-    if (abcsh.sh != dummysh) {
-      // Exists! Keep the edge ab of both handles be the same.
-      findedge(&abcsh, org(abcd), dest(abcd));
-    }
-  }
-
-  if (b->verbose > 1) {
-    printf("  Inserting point %d on face (%d, %d, %d).\n", pointmark(newpoint),
-           pointmark(pa), pointmark(pb), pointmark(pc));
-  }
-
-  // Save the old configuration at faces bcd and cad.
-  enextfnext(abcd, oldbcd);
-  enext2fnext(abcd, oldcad);
-  sym(oldbcd, bcdcasing);
-  sym(oldcad, cadcasing);
-  // Create two new tetrahedra.
-  maketetrahedron(&bcvd);
-  maketetrahedron(&cavd);
-  if (mirrorflag) {
-    // Save the old configuration at faces bce and cae.
-    enextfnext(bace, oldace);
-    enext2fnext(bace, oldcbe);
-    sym(oldace, acecasing);
-    sym(oldcbe, cbecasing);
-    // Create two new tetrahedra.
-    maketetrahedron(&acve);
-    maketetrahedron(&cbve);
-  } else {
-    // Splitting a boundary face increases the number of boundary faces.
-    hullsize += 2;
-  }
-
-  // Set vertices to the changed tetrahedron and new tetrahedra.
-  abvd = abcd;  // Update 'abcd' to 'abvd'.
-  setapex(abvd, newpoint);
-  setorg (bcvd, pb);  // Set 'bcvd'.
-  setdest(bcvd, pc);
-  setapex(bcvd, newpoint);
-  setoppo(bcvd, pd);
-  setorg (cavd, pc);  // Set 'cavd'.
-  setdest(cavd, pa);
-  setapex(cavd, newpoint);
-  setoppo(cavd, pd);
-  // Set the element attributes of the new tetrahedra.
-  for (i = 0; i < in->numberoftetrahedronattributes; i++) {
-    attrib = elemattribute(abvd.tet, i);
-    setelemattribute(bcvd.tet, i, attrib);
-    setelemattribute(cavd.tet, i, attrib);
-  }
-  if (b->varvolume) {
-    // Set the area constraint of the new tetrahedra.
-    volume = volumebound(abvd.tet);
-    setvolumebound(bcvd.tet, volume);
-    setvolumebound(cavd.tet, volume);
-  }
-  if (mirrorflag) {
-    bave = bace;  // Update 'bace' to 'bave'.
-    setapex(bave, newpoint);
-    setorg (acve, pa);  // Set 'acve'.
-    setdest(acve, pc);
-    setapex(acve, newpoint);
-    setoppo(acve, pe);
-    setorg (cbve, pc);  // Set 'cbve'.
-    setdest(cbve, pb);
-    setapex(cbve, newpoint);
-    setoppo(cbve, pe);
-    // Set the element attributes of the new tetrahedra.
-    for (i = 0; i < in->numberoftetrahedronattributes; i++) {
-      attrib = elemattribute(bave.tet, i);
-      setelemattribute(acve.tet, i, attrib);
-      setelemattribute(cbve.tet, i, attrib);
-    }
-    if (b->varvolume) {
-      // Set the area constraint of the new tetrahedra.
-      volume = volumebound(bave.tet);
-      setvolumebound(acve.tet, volume);
-      setvolumebound(cbve.tet, volume);
-    }
-  }
-
-  // Bond the new tetrahedra to the surrounding tetrahedra.
-  bcvd.loc = 1;
-  bond(bcvd, bcdcasing); 
-  cavd.loc = 1;
-  bond(cavd, cadcasing); 
-  bcvd.loc = 3;
-  bond(bcvd, oldbcd);
-  cavd.loc = 2;
-  bond(cavd, oldcad);
-  bcvd.loc = 2;
-  cavd.loc = 3;
-  bond(bcvd, cavd);  
-  if (mirrorflag) {
-    acve.loc = 1;
-    bond(acve, acecasing);
-    cbve.loc = 1;
-    bond(cbve, cbecasing);
-    acve.loc = 3;
-    bond(acve, oldace);
-    cbve.loc = 2;
-    bond(cbve, oldcbe);
-    acve.loc = 2;
-    cbve.loc = 3;
-    bond(acve, cbve);
-    // Bond two new coplanar facets.
-    bcvd.loc = 0;
-    cbve.loc = 0;
-    bond(bcvd, cbve);
-    cavd.loc = 0;
-    acve.loc = 0;
-    bond(cavd, acve);
-  }
-
-  // There may exist subface needed to be bonded to the new tetrahedra.
-  if (checksubfaces) {
-    tspivot(oldbcd, bcdsh);
-    if (bcdsh.sh != dummysh) {
-      tsdissolve(oldbcd);
-      bcvd.loc = 1;
-      tsbond(bcvd, bcdsh);
-    }
-    tspivot(oldcad, cadsh);
-    if (cadsh.sh != dummysh) {
-      tsdissolve(oldcad);
-      cavd.loc = 1;
-      tsbond(cavd, cadsh);
-    }
-    if (mirrorflag) {
-      tspivot(oldace, acesh);
-      if (acesh.sh != dummysh) {
-        tsdissolve(oldace);
-        acve.loc = 1;
-        tsbond(acve, acesh);
-      }
-      tspivot(oldcbe, cbesh);
-      if (cbesh.sh != dummysh) {
-        tsdissolve(oldcbe);
-        cbve.loc = 1;
-        tsbond(cbve, cbesh);
-      }
-    }
-    // Is there a subface needs to be split together?
-    if (abcsh.sh != dummysh) {
-      // Split this subface 'abc' into three i.e, abv, bcv, cav.
-      splitsubface(newpoint, &abcsh, (queue *) NULL);
-    }  
-  } else if (checksubsegs) {
-    // abvd.loc = abvd.ver = 0;
-    bcvd.loc = bcvd.ver = 0;
-    cavd.loc = cavd.ver = 0;
-    if (mirrorflag) {
-      // bave.loc = bave.ver = 0;
-      cbve.loc = cbve.ver = 0;
-      acve.loc = acve.ver = 0;
-    }
-    enext(abvd, worktet);
-    tsspivot1(worktet, bcseg);
-    if (bcseg.sh != dummysh) {
-      tssdissolve1(worktet);
-      tssbond1(bcvd, bcseg);
-      if (mirrorflag) {
-        enext2(bave, worktet);
-        tssdissolve1(worktet);
-        tssbond1(cbve, bcseg);
-      }
-    }
-    enext2(abvd, worktet);
-    tsspivot1(worktet, caseg);
-    if (caseg.sh != dummysh) {
-      tssdissolve1(worktet);
-      tssbond1(cavd, caseg);
-      if (mirrorflag) {
-        enext(bave, worktet);
-        tssdissolve1(worktet);
-        tssbond1(acve, caseg);
-      }
-    }
-    fnext(abvd, worktet);
-    enext2self(worktet);
-    tsspivot1(worktet, adseg);
-    if (adseg.sh != dummysh) {
-      fnext(cavd, worktet);
-      enextself(worktet);
-      tssbond1(worktet, adseg);
-    }
-    fnext(abvd, worktet);
-    enextself(worktet);
-    tsspivot1(worktet, bdseg);
-    if (bdseg.sh != dummysh) {
-      fnext(bcvd, worktet);
-      enext2self(worktet);
-      tssbond1(worktet, bdseg);
-    }
-    enextfnext(abvd, worktet);
-    enextself(worktet);
-    tsspivot1(worktet, cdseg);
-    if (cdseg.sh != dummysh) {
-      tssdissolve1(worktet);
-      fnext(bcvd, worktet);
-      enextself(worktet);
-      tssbond1(worktet, cdseg);
-      fnext(cavd, worktet);
-      enext2self(worktet);
-      tssbond1(worktet, cdseg);
-    }
-    if (mirrorflag) {
-      fnext(bave, worktet);
-      enextself(worktet);
-      tsspivot1(worktet, aeseg);
-      if (aeseg.sh != dummysh) {
-        fnext(acve, worktet);
-        enext2self(worktet);
-        tssbond1(worktet, aeseg);
-      }
-      fnext(bave, worktet);
-      enext2self(worktet);
-      tsspivot1(worktet, beseg);
-      if (beseg.sh != dummysh) {
-        fnext(cbve, worktet);
-        enextself(worktet);
-        tssbond1(worktet, beseg);
-      }
-      enextfnext(bave, worktet);
-      enextself(worktet);
-      tsspivot1(worktet, ceseg);
-      if (ceseg.sh != dummysh) {
-        tssdissolve1(worktet);
-        fnext(cbve, worktet);
-        enext2self(worktet);
-        tssbond1(worktet, ceseg);
-        fnext(acve, worktet);
-        enextself(worktet);
-        tssbond1(worktet, ceseg);
-      }
-    }
-  }
-
-  // Save a handle for quick point location.
-  recenttet = abvd;
-  // Set the return handle be abvd.
-  *splittet = abvd;
-
-  bcvd.loc = 0;
-  cavd.loc = 0;
-  if (mirrorflag) {
-    cbve.loc = 0;
-    acve.loc = 0;
-  }
-  if (b->verbose > 3) {
-    printf("    Updating abvd ");
-    printtet(&abvd);
-    printf("    Creating bcvd ");
-    printtet(&bcvd);
-    printf("    Creating cavd ");
-    printtet(&cavd);
-    if (mirrorflag) {
-      printf("    Updating bave ");
-      printtet(&bave);
-      printf("    Creating cbve ");
-      printtet(&cbve);
-      printf("    Creating acve ");
-      printtet(&acve);
-    }
-  }
-
-  if (flipqueue != (queue *) NULL) {
-    fnextself(abvd);
-    enqueueflipface(abvd, flipqueue);
-    fnextself(bcvd);
-    enqueueflipface(bcvd, flipqueue);
-    fnextself(cavd);
-    enqueueflipface(cavd, flipqueue);
-    if (mirrorflag) {
-      fnextself(bave);
-      enqueueflipface(bave, flipqueue);
-      fnextself(cbve);
-      enqueueflipface(cbve, flipqueue);
-      fnextself(acve);
-      enqueueflipface(acve, flipqueue);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// unsplittetface()    Reverse the operation of inserting a point on a face, //
-//                     so as to remove the newly inserted point.             //
-//                                                                           //
-// Assume the original face is abc, the tetrahedron containing abc is abcd.  //
-// If abc is not a hull face, bace is the tetrahedron at the opposite of d.  //
-// After face abc was split by a point v, tetrahedron abcd had been split    //
-// into three tetrahedra, abvd, bcvd, cavd, and bace (if it exists) had been //
-// split into bave, cbve, acve. 'splittet' represents abvd (its apex is v).  //
-//                                                                           //
-// Point v is removed by expanding abvd to abcd, deleting two tetrahedra     //
-// bcvd, cavd. Expanding bave(if it exists) to bace, deleting two tetrahedra //
-// cbve, acve.  If abv is a subface, routine unsplitsubface() will be called //
-// to reverse the operation of splitting a subface. On completion, point v   //
-// is not deleted in this routine.                                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::unsplittetface(triface* splittet)
-{
-  triface abvd, bcvd, cavd, bave, cbve, acve;
-  triface oldbvd, oldvad, oldvbe, oldave;
-  triface bcdcasing, cadcasing, cbecasing, acecasing;
-  face bcdsh, cadsh, cbesh, acesh;
-  face abvsh;
-  bool mirrorflag;
-
-  abvd = *splittet;
-  adjustedgering(abvd, CCW); // for sure.
-  enextfnext(abvd, oldbvd);
-  fnext(oldbvd, bcvd);
-  esymself(bcvd);
-  enextself(bcvd);
-  enext2fnext(abvd, oldvad);
-  fnext(oldvad, cavd);
-  esymself(cavd);
-  enext2self(cavd);
-  // Is there a second tetrahedron?
-  sym(abvd, bave);
-  mirrorflag = bave.tet != dummytet;
-  if (mirrorflag) {
-    findedge(&bave, dest(abvd), org(abvd));
-    enextfnext(bave, oldave);  
-    fnext(oldave, acve);
-    esymself(acve);
-    enextself(acve);
-    enext2fnext(bave, oldvbe);  
-    fnext(oldvbe, cbve);
-    esymself(cbve);
-    enext2self(cbve);
-  } else {
-    // Unsplit a hull face decrease the number of boundary faces.
-    hullsize -= 2;
-  }
-  // Is there a subface at abv.
-  tspivot(abvd, abvsh);
-  if (abvsh.sh != dummysh) {
-    // Exists! Keep the edge ab of both handles be the same.
-    findedge(&abvsh, org(abvd), dest(abvd));
-  }
-
-  if (b->verbose > 1) {
-    printf("  Removing point %d on face (%d, %d, %d).\n",
-           pointmark(apex(abvd)), pointmark(org(abvd)), pointmark(dest(abvd)),
-           pointmark(dest(bcvd)));
-  }
-
-  fnextself(bcvd); // bcvd has changed to bcdv.
-  sym(bcvd, bcdcasing);
-  tspivot(bcvd, bcdsh);
-  fnextself(cavd); // cavd has changed to cadv.
-  sym(cavd, cadcasing);
-  tspivot(cavd, cadsh);
-  if (mirrorflag) {
-    fnextself(acve); // acve has changed to acev.
-    sym(acve, acecasing);
-    tspivot(acve, acesh);
-    fnextself(cbve); // cbve has changed to cbev.
-    sym(cbve, cbecasing);
-    tspivot(cbve, cbesh);
-  }
-
-  // Expand abvd to abcd.
-  setapex(abvd, dest(bcvd));
-  bond(oldbvd, bcdcasing);
-  if (bcdsh.sh != dummysh) {
-    tsbond(oldbvd, bcdsh);
-  }
-  bond(oldvad, cadcasing);
-  if (cadsh.sh != dummysh) {
-    tsbond(oldvad, cadsh);
-  }
-  if (mirrorflag) {
-    // Expanding bave to bace.
-    setapex(bave, dest(acve));
-    bond(oldave, acecasing);
-    if (acesh.sh != dummysh) {
-      tsbond(oldave, acesh);
-    }
-    bond(oldvbe, cbecasing);
-    if (cbesh.sh != dummysh) {
-      tsbond(oldvbe, cbesh);
-    }
-  }
-
-  // Unsplit a subface if there exists.
-  if (abvsh.sh != dummysh) {
-    unsplitsubface(&abvsh);
-  }
-
-  // Delete the split-out tetrahedra.
-  tetrahedrondealloc(bcvd.tet);
-  tetrahedrondealloc(cavd.tet);
-  if (mirrorflag) {
-    tetrahedrondealloc(acve.tet);
-    tetrahedrondealloc(cbve.tet);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// splitsubface()    Insert a point on a subface, split it into three.       //
-//                                                                           //
-// The subface is 'splitface'.  Let it is abc. The inserting point 'newpoint'//
-// v should lie inside abc.  If the neighbor tetrahedra of abc exist, i.e.,  //
-// abcd and bace, they should have been split by routine splittetface()      //
-// before calling this routine, so the connection between the new tetrahedra //
-// and new subfaces can be correctly set.                                    //
-//                                                                           //
-// To split subface abc by point v is to shrink abc to abv, create two new   //
-// subfaces bcv and cav.  Set the connection between updated and new created //
-// subfaces. If there is a subsegment at edge bc or ca, connection of new    //
-// subface (bcv or cav) to its casing subfaces is a face link, 'casingin' is //
-// the predecessor and 'casingout' is the successor. It is important to keep //
-// the orientations of the edge rings of the updated and created subfaces be //
-// the same as abc's. So they have the same orientation as other subfaces of //
-// this facet with respect to the lift point of this facet.                  //
-//                                                                           //
-// On completion, 'splitface' returns abv.  If 'flipqueue' is not NULL, it   //
-// returns all possibly non-Delaunay edges.                                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::splitsubface(point newpoint, face* splitface,
-  queue* flipqueue)
-{
-  triface abvd, bcvd, cavd, bave, cbve, acve;
-  face abc, oldbc, oldca, bc, ca, spinsh;
-  face bccasin, bccasout, cacasin, cacasout;
-  face abv, bcv, cav;
-  point pa, pb, pc;
-  
-  abc = *splitface;
-  // The newly created subfaces will have the same edge ring as abc.
-  adjustedgering(abc, CCW);
-  pa = sorg(abc);
-  pb = sdest(abc);
-  pc = sapex(abc);
-
-  if (b->verbose > 1) {
-    printf("  Inserting point %d on subface (%d, %d, %d).\n",
-           pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc));
-  }
-
-  // Save the old configuration at edge bc and ca.  Subsegments may appear
-  //   at both sides, save the face links and dissolve them.
-  senext(abc, oldbc);
-  senext2(abc, oldca);
-  spivot(oldbc, bccasout);
-  sspivot(oldbc, bc);
-  if (bc.sh != dummysh) {
-    if (oldbc.sh != bccasout.sh) {
-      // 'oldbc' is not self-bonded.
-      spinsh = bccasout;
-      do {
-        bccasin = spinsh;
-        spivotself(spinsh);
-      } while (spinsh.sh != oldbc.sh);
-    } else {
-      bccasout.sh = dummysh;
-    }
-    ssdissolve(oldbc);
-  } 
-  spivot(oldca, cacasout);
-  sspivot(oldca, ca);
-  if (ca.sh != dummysh) {
-    if (oldca.sh != cacasout.sh) {
-      // 'oldca' is not self-bonded.
-      spinsh = cacasout;
-      do {
-        cacasin = spinsh;
-        spivotself(spinsh);
-      } while (spinsh.sh != oldca.sh);
-    } else {
-      cacasout.sh = dummysh;
-    }
-    ssdissolve(oldca);
-  }
-  // Create two new subfaces.
-  makeshellface(subfaces, &bcv);
-  makeshellface(subfaces, &cav);
-
-  // Set the vertices of changed and new subfaces.
-  abv = abc;  // Update 'abc' to 'abv'.
-  setsapex(abv, newpoint);
-  setsorg(bcv, pb);  // Set 'bcv'.
-  setsdest(bcv, pc);
-  setsapex(bcv, newpoint);
-  setsorg(cav, pc);  // Set 'cav'.
-  setsdest(cav, pa);
-  setsapex(cav, newpoint);
-  if (b->quality && varconstraint) {
-    // Copy yhr area bound into the new subfaces.
-    setareabound(bcv, areabound(abv));
-    setareabound(cav, areabound(abv));
-  }
-  // Copy the boundary mark into the new subfaces.
-  setshellmark(bcv, shellmark(abv));
-  setshellmark(cav, shellmark(abv));  
-  // Copy the subface type into the new subfaces.
-  setshelltype(bcv, shelltype(abv));
-  setshelltype(cav, shelltype(abv));
-  if (checkpbcs) {
-    // Copy the pbcgroup into the new subfaces.
-    setshellpbcgroup(bcv, shellpbcgroup(abv));
-    setshellpbcgroup(cav, shellpbcgroup(abv));
-  }
-  // Bond the new subfaces to the surrounding subfaces.
-  if (bc.sh != dummysh) {
-    if (bccasout.sh != dummysh) {
-      sbond1(bccasin, bcv);
-      sbond1(bcv, bccasout);
-    } else {
-      // Bond 'bcv' to itsself.
-      sbond(bcv, bcv);
-    }
-    ssbond(bcv, bc);
-  } else {
-    sbond(bcv, bccasout);
-  }
-  if (ca.sh != dummysh) {
-    if (cacasout.sh != dummysh) {
-      sbond1(cacasin, cav);
-      sbond1(cav, cacasout);
-    } else {
-      // Bond 'cav' to itself.
-      sbond(cav, cav);
-    }
-    ssbond(cav, ca);
-  } else {
-    sbond(cav, cacasout);
-  }
-  senext2self(bcv);
-  sbond(bcv, oldbc);
-  senextself(cav);
-  sbond(cav, oldca);
-  senext2self(bcv);
-  senextself(cav);
-  sbond(bcv, cav);
-
-  // Bond the new subfaces to the new tetrahedra if they exist.
-  stpivot(abv, abvd);
-  if (abvd.tet != dummytet) {
-    // Get two new tetrahedra and their syms.
-    findedge(&abvd, sorg(abv), sdest(abv));
-    enextfnext(abvd, bcvd);
-#ifdef SELF_CHECK
-    assert(bcvd.tet != dummytet);
-#endif
-    fnextself(bcvd);
-    enext2fnext(abvd, cavd);
-#ifdef SELF_CHECK
-    assert(cavd.tet != dummytet);
-#endif
-    fnextself(cavd);
-    // Bond two new subfaces to the two new tetrahedra.
-    tsbond(bcvd, bcv);
-    tsbond(cavd, cav);
-  }
-  // Set the connection at the other sides if the tetrahedra exist.
-  sesymself(abv);  // bav
-  stpivot(abv, bave);
-  if (bave.tet != dummytet) {
-    sesymself(bcv);  // cbv
-    sesymself(cav);  // acv
-    // Get two new tetrahedra and their syms.
-    findedge(&bave, sorg(abv), sdest(abv));
-    enextfnext(bave, acve);
-#ifdef SELF_CHECK
-    assert(acve.tet != dummytet);
-#endif
-    fnextself(acve);
-    enext2fnext(bave, cbve);
-#ifdef SELF_CHECK
-    assert(cbve.tet != dummytet);
-#endif
-    fnextself(cbve);
-    // Bond two new subfaces to the two new tetrahedra.
-    tsbond(acve, cav);
-    tsbond(cbve, bcv);
-  }
-
-  bcv.shver = 0;
-  cav.shver = 0;
-  if (b->verbose > 3) {
-    printf("    Updating abv ");
-    printsh(&abv);
-    printf("    Creating bcv ");
-    printsh(&bcv);
-    printf("    Creating cav ");
-    printsh(&cav);
-  }
-
-  if (flipqueue != (queue *) NULL) {
-    enqueueflipedge(abv, flipqueue);
-    enqueueflipedge(bcv, flipqueue);
-    enqueueflipedge(cav, flipqueue);
-  }
-
-  // Set the return handle be abv.
-  *splitface = abv;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// unsplitsubface()    Reverse the operation of inserting a point on a       //
-//                     subface, so as to remove the newly inserted point.    //
-//                                                                           //
-// Assume the original subface is abc, it was split by a point v into three  //
-// subfaces abv, bcv and cav.  'splitsh' represents abv.                     //
-//                                                                           //
-// To remove point v is to expand abv to abc, delete bcv and cav. If edge bc //
-// or ca is a subsegment,  the connection at a subsegment is a subface link, //
-// '-casin' and '-casout' are used to save the predecessor and successor of  //
-// bcv or cav.  On completion, point v is not deleted in this routine.       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::unsplitsubface(face* splitsh)
-{
-  face abv, bcv, cav;
-  face oldbv, oldva, bc, ca, spinsh;
-  face bccasin, bccasout, cacasin, cacasout;
-
-  abv = *splitsh;
-  senext(abv, oldbv);
-  spivot(oldbv, bcv);
-  if (sorg(bcv) != sdest(oldbv)) {
-    sesymself(bcv);
-  }
-  senextself(bcv);
-  senext2(abv, oldva);
-  spivot(oldva, cav);
-  if (sorg(cav) != sdest(oldva)) {
-    sesymself(cav);
-  }
-  senext2self(cav);
-
-  if (b->verbose > 1) {
-    printf("  Removing point %d on subface (%d, %d, %d).\n",
-           pointmark(sapex(abv)), pointmark(sorg(abv)), pointmark(sdest(abv)),
-           pointmark(sdest(bcv)));
-  }
-
-  spivot(bcv, bccasout);
-  sspivot(bcv, bc);
-  if (bc.sh != dummysh) {
-    if (bcv.sh != bccasout.sh) {
-      // 'bcv' is not self-bonded.
-      spinsh = bccasout;
-      do {
-        bccasin = spinsh;
-        spivotself(spinsh);
-      } while (spinsh.sh != bcv.sh);
-    } else {
-      bccasout.sh = dummysh;
-    }
-  }
-  spivot(cav, cacasout);
-  sspivot(cav, ca);
-  if (ca.sh != dummysh) {
-    if (cav.sh != cacasout.sh) {
-      // 'cav' is not self-bonded.
-      spinsh = cacasout;
-      do {
-       cacasin = spinsh;
-       spivotself(spinsh);
-      } while (spinsh.sh != cav.sh);
-    } else {
-      cacasout.sh = dummysh;
-    }
-  }
-
-  // Expand abv to abc.
-  setsapex(abv, sdest(bcv));
-  if (bc.sh != dummysh) {
-    if (bccasout.sh != dummysh) {
-      sbond1(bccasin, oldbv);
-      sbond1(oldbv, bccasout);
-    } else {
-      // Bond 'oldbv' to itself.
-      sbond(oldbv, oldbv);
-    }
-    ssbond(oldbv, bc);
-  } else {
-    sbond(oldbv, bccasout);
-  } 
-  if (ca.sh != dummysh) {
-    if (cacasout.sh != dummysh) {
-      sbond1(cacasin, oldva);
-      sbond1(oldva, cacasout);
-    } else {
-      // Bond 'oldva' to itself.
-      sbond(oldva, oldva);
-    }
-    ssbond(oldva, ca);
-  } else {
-    sbond(oldva, cacasout);
-  }
-
-  // Delete two split-out subfaces.
-  shellfacedealloc(subfaces, bcv.sh);
-  shellfacedealloc(subfaces, cav.sh);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// splittetedge()    Insert a point on an edge of the mesh.                  //
-//                                                                           //
-// The edge is given by 'splittet'. Assume its four corners are a, b, n1 and //
-// n2, where ab is the edge will be split. Around ab may exist any number of //
-// tetrahedra. For convenience, they're ordered in a sequence following the  //
-// right-hand rule with your thumb points from a to b. Let the vertex set of //
-// these tetrahedra be {a, b, n1, n2, ..., n(i)}. NOTE the tetrahedra around //
-// ab may not connect to each other (can only happen when ab is a subsegment,//
-// hence some faces abn(i) are subfaces).  If ab is a subsegment, abn1 must  //
-// be a subface.                                                             //
-//                                                                           //
-// To split edge ab by a point v is to split all tetrahedra containing ab by //
-// v.  More specifically, for each such tetrahedron, an1n2b, it is shrunk to //
-// an1n2v, and a new tetrahedra bn2n1v is created. If ab is a subsegment, or //
-// some faces of the splitting tetrahedra are subfaces, they must be split   //
-// either by calling routine 'splitsubedge()'.                               //
-//                                                                           //
-// On completion, 'splittet' returns avn1n2.  If 'flipqueue' is not NULL, it //
-// returns all faces which may become non-Delaunay after this operation.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::splittetedge(point newpoint, triface* splittet,
-  queue* flipqueue)
-{
-  triface *bots, *newtops;
-  triface oldtop, topcasing;
-  triface spintet, tmpbond0, tmpbond1;
-  face abseg, splitsh, topsh, spinsh;
-  triface worktet;
-  face n1n2seg, n2vseg, n1vseg;
-  point pa, pb, n1, n2;
-  REAL attrib, volume;
-  int wrapcount, hitbdry;
-  int i, j;
-
-  if (checksubfaces) {
-    // Is there a subsegment need to be split together?
-    tsspivot(splittet, &abseg);
-    if (abseg.sh != dummysh) {
-      abseg.shver = 0;
-      // Orient the edge direction of 'splittet' be abseg.
-      if (org(*splittet) != sorg(abseg)) {
-        esymself(*splittet);
-      }
-    }
-  } 
-  spintet = *splittet;
-  pa = org(spintet);
-  pb = dest(spintet);
-
-  if (b->verbose > 1) {
-    printf("  Inserting point %d on edge (%d, %d).\n", 
-           pointmark(newpoint), pointmark(pa), pointmark(pb));
-  }
-
-  // Collect the tetrahedra containing the splitting edge (ab).
-  n1 = apex(spintet);
-  hitbdry = 0;
-  wrapcount = 1;
-  if (checksubfaces && abseg.sh != dummysh) {
-    // It may happen that some tetrahedra containing ab (a subsegment) are
-    //   completely disconnected with others. If it happens, use the face
-    //   link of ab to cross the boundary. 
-    while (true) {
-      if (!fnextself(spintet)) {
-        // Meet a boundary, walk through it.
-        hitbdry ++;
-        tspivot(spintet, spinsh);
-#ifdef SELF_CHECK
-        assert(spinsh.sh != dummysh);
-#endif
-        findedge(&spinsh, pa, pb);
-        sfnextself(spinsh);
-        stpivot(spinsh, spintet);
-#ifdef SELF_CHECK
-        assert(spintet.tet != dummytet);
-#endif
-        findedge(&spintet, pa, pb);
-        // Remember this position (hull face) in 'splittet'.
-        *splittet = spintet;
-        // Split two hull faces increase the hull size;
-        hullsize += 2;
-      }
-      if (apex(spintet) == n1) break;
-      wrapcount ++;
-    }
-    if (hitbdry > 0) {
-      wrapcount -= hitbdry;
-    }
-  } else {
-    // All the tetrahedra containing ab are connected together. If there
-    //   are subfaces, 'splitsh' keeps one of them.
-    splitsh.sh = dummysh;
-    while (hitbdry < 2) {
-      if (checksubfaces && splitsh.sh == dummysh) {
-        tspivot(spintet, splitsh);
-      }
-      if (fnextself(spintet)) {
-        if (apex(spintet) == n1) break;
-        wrapcount++;
-      } else {
-        hitbdry ++;
-        if (hitbdry < 2) {
-          esym(*splittet, spintet);
-        }
-      }
-    }
-    if (hitbdry > 0) {
-      // ab is on the hull.
-      wrapcount -= 1;
-      // 'spintet' now is a hull face, inverse its edge direction.
-      esym(spintet, *splittet);
-      // Split two hull faces increases the number of hull faces.
-      hullsize += 2;
-    }
-  }
-  
-  // Make arrays of updating (bot, oldtop) and new (newtop) tetrahedra.
-  bots = new triface[wrapcount];
-  newtops = new triface[wrapcount];
-  // Spin around ab, gather tetrahedra and set up new tetrahedra. 
-  spintet = *splittet;
-  for (i = 0; i < wrapcount; i++) {
-    // Get 'bots[i] = an1n2b'.
-    enext2fnext(spintet, bots[i]);
-    esymself(bots[i]);
-    // Create 'newtops[i]'.
-    maketetrahedron(&(newtops[i]));
-    // Go to the next.
-    fnextself(spintet);
-    if (checksubfaces && abseg.sh != dummysh) {
-      if (!issymexist(&spintet)) {
-        // We meet a hull face, walk through it.
-        tspivot(spintet, spinsh);
-#ifdef SELF_CHECK
-        assert(spinsh.sh != dummysh);
-#endif
-        findedge(&spinsh, pa, pb);
-        sfnextself(spinsh);
-        stpivot(spinsh, spintet);
-#ifdef SELF_CHECK
-        assert(spintet.tet != dummytet);
-#endif
-        findedge(&spintet, pa, pb);
-      }
-    }
-  }
-  
-  // Set the vertices of updated and new tetrahedra.
-  for (i = 0; i < wrapcount; i++) {
-    // Update 'bots[i] = an1n2v'.
-    setoppo(bots[i], newpoint);
-    // Set 'newtops[i] = bn2n1v'.
-    n1 = dest(bots[i]);
-    n2 = apex(bots[i]);
-    // Set 'newtops[i]'.
-    setorg(newtops[i], pb);
-    setdest(newtops[i], n2);
-    setapex(newtops[i], n1);
-    setoppo(newtops[i], newpoint);
-    // Set the element attributes of a new tetrahedron.
-    for (j = 0; j < in->numberoftetrahedronattributes; j++) {
-      attrib = elemattribute(bots[i].tet, j);
-      setelemattribute(newtops[i].tet, j, attrib);
-    }
-    if (b->varvolume) {
-      // Set the area constraint of a new tetrahedron.
-      volume = volumebound(bots[i].tet);
-      setvolumebound(newtops[i].tet, volume);
-    }
-#ifdef SELF_CHECK
-    // Make sure no inversed tetrahedron has been created.
-    // volume = orient3d(pa, n1, n2, newpoint);
-    // if (volume >= 0.0) {
-    //   printf("Internal error in splittetedge(): volume = %.12g.\n", volume);
-    // }
-    // volume = orient3d(pb, n2, n1, newpoint);
-    // if (volume >= 0.0) {
-    //   printf("Internal error in splittetedge(): volume = %.12g.\n", volume);
-    // }
-#endif
-  }
-
-  // Bond newtops to topcasings and bots.
-  for (i = 0; i < wrapcount; i++) {
-    // Get 'oldtop = n1n2va' from 'bots[i]'.
-    enextfnext(bots[i], oldtop);
-    sym(oldtop, topcasing);
-    bond(newtops[i], topcasing);
-    if (checksubfaces) {
-      tspivot(oldtop, topsh);
-      if (topsh.sh != dummysh) {
-        tsdissolve(oldtop);
-        tsbond(newtops[i], topsh);
-      }
-    }
-    enextfnext(newtops[i], tmpbond0);
-    bond(oldtop, tmpbond0);
-  }
-  // Bond between newtops.
-  fnext(newtops[0], tmpbond0);
-  enext2fnext(bots[0], spintet); 
-  for (i = 1; i < wrapcount; i ++) {
-    if (issymexist(&spintet)) {
-      enext2fnext(newtops[i], tmpbond1);
-      bond(tmpbond0, tmpbond1);
-    }
-    fnext(newtops[i], tmpbond0);
-    enext2fnext(bots[i], spintet); 
-  }
-  // Bond the last to the first if no boundary.
-  if (issymexist(&spintet)) {
-    enext2fnext(newtops[0], tmpbond1);
-    bond(tmpbond0, tmpbond1);
-  }
-  if (checksubsegs) {
-    for (i = 0; i < wrapcount; i++) {
-      enextfnext(bots[i], worktet); // edge n1->n2.
-      tsspivot1(worktet, n1n2seg);
-      if (n1n2seg.sh != dummysh) {
-        enext(newtops[i], tmpbond0);
-        tssbond1(tmpbond0, n1n2seg);
-      }
-      enextself(worktet); // edge n2->v ==> n2->b
-      tsspivot1(worktet, n2vseg);
-      if (n2vseg.sh != dummysh) {
-        tssdissolve1(worktet);
-        tssbond1(newtops[i], n2vseg);
-      }
-      enextself(worktet); // edge v->n1 ==> b->n1
-      tsspivot1(worktet, n1vseg);
-      if (n1vseg.sh != dummysh) {
-        tssdissolve1(worktet);
-        enext2(newtops[i], tmpbond0);
-        tssbond1(tmpbond0, n1vseg);
-      }
-    }
-  }
-
-  // Is there exist subfaces and subsegment need to be split?
-  if (checksubfaces) {
-    if (abseg.sh != dummysh) {
-      // A subsegment needs be split.
-      spivot(abseg, splitsh);
-#ifdef SELF_CHECK
-      assert(splitsh.sh != dummysh);
-#endif
-    }
-    if (splitsh.sh != dummysh) {
-      // Split subfaces (and subsegment).
-      findedge(&splitsh, pa, pb);
-      splitsubedge(newpoint, &splitsh, (queue *) NULL);
-    }
-  }
-
-  if (b->verbose > 3) {
-    for (i = 0; i < wrapcount; i++) {
-      printf("    Updating bots[%i] ", i);
-      printtet(&(bots[i]));
-      printf("    Creating newtops[%i] ", i);
-      printtet(&(newtops[i]));
-    }
-  }
-
-  if (flipqueue != (queue *) NULL) {
-    for (i = 0; i < wrapcount; i++) {
-      enqueueflipface(bots[i], flipqueue);
-      enqueueflipface(newtops[i], flipqueue);
-    }
-  }
-
-  // Set the return handle be avn1n2.  It is got by transforming from
-  //   'bots[0]' (which is an1n2v).
-  fnext(bots[0], spintet); // spintet is an1vn2.
-  esymself(spintet); // spintet is n1avn2.
-  enextself(spintet); // spintet is avn1n2.
-  *splittet = spintet;
-
-  delete [] bots;
-  delete [] newtops;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// unsplittetedge()    Reverse the operation of splitting an edge, so as to  //
-//                     remove the newly inserted point.                      //
-//                                                                           //
-// Assume the original edge is ab, the tetrahedron containing ab is abn1n2.  //
-// After ab was split by a point v, every tetrahedron containing ab (e.g.,   //
-// abn1n2) has been split into two (e.g., an1n2v and bn2n1v). 'splittet'     //
-// represents avn1n2 (i.e., its destination is v).                           //
-//                                                                           //
-// To remove point v is to expand each split tetrahedron containing ab (e.g.,//
-// (avn1n2 to abn1n2), then delete the redundant one(e.g., vbn1n2). If there //
-// exists any subface around ab, routine unsplitsubedge() will be called to  //
-// reverse the operation of splitting a edge (or a subsegment) of subfaces.  //
-// On completion, point v is not deleted in this routine.                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::unsplittetedge(triface* splittet)
-{
-  triface *bots, *newtops;
-  triface oldtop, topcasing;
-  triface spintet;
-  face avseg, splitsh, topsh, spinsh;
-  point pa, pv, n1;
-  int wrapcount, hitbdry;
-  int i;
-
-  spintet = *splittet;
-  pa = org(spintet);
-  pv = dest(spintet);
-  if (checksubfaces) {
-    // Is there a subsegment need to be unsplit together?
-    tsspivot(splittet, &avseg);
-    if (avseg.sh != dummysh) {
-      // The subsegment's direction should conform to 'splittet'.
-      if (sorg(avseg) != pa) {
-        sesymself(avseg);
-      }
-    }
-  } 
-
-  n1 = apex(spintet);
-  hitbdry = 0;
-  wrapcount = 1;
-  if (checksubfaces && avseg.sh != dummysh) {
-    // It may happen that some tetrahedra containing ab (a subsegment) are
-    //   completely disconnected with others. If it happens, use the face
-    //   link of ab to cross the boundary. 
-    while (true) {    
-      if (!fnextself(spintet)) {
-        // Meet a boundary, walk through it.
-        hitbdry ++;
-        tspivot(spintet, spinsh);
-#ifdef SELF_CHECK
-        assert(spinsh.sh != dummysh);
-#endif
-        findedge(&spinsh, pa, pv);
-        sfnextself(spinsh);
-        stpivot(spinsh, spintet);
-#ifdef SELF_CHECK
-        assert(spintet.tet != dummytet);
-#endif
-        findedge(&spintet, pa, pv);
-        // Remember this position (hull face) in 'splittet'.
-        *splittet = spintet;
-        // Split two hull faces increase the hull size;
-        hullsize += 2;
-      }
-      if (apex(spintet) == n1) break;
-      wrapcount ++;
-    }
-    if (hitbdry > 0) {
-      wrapcount -= hitbdry;
-    }
-  } else {
-    // All the tetrahedra containing ab are connected together. If there
-    //   are subfaces, 'splitsh' keeps one of them.
-    splitsh.sh = dummysh;
-    while (hitbdry < 2) {
-      if (checksubfaces && splitsh.sh == dummysh) {
-        tspivot(spintet, splitsh);
-      }
-      if (fnextself(spintet)) {
-        if (apex(spintet) == n1) break;
-        wrapcount++;
-      } else {
-        hitbdry ++;
-        if (hitbdry < 2) {
-          esym(*splittet, spintet);
-        }
-      }
-    }
-    if (hitbdry > 0) {
-      // ab is on the hull.
-      wrapcount -= 1;
-      // 'spintet' now is a hull face, inverse its edge direction.
-      esym(spintet, *splittet);
-      // Split two hull faces increases the number of hull faces.
-      hullsize += 2;
-    }
-  }
-  
-  // Make arrays of updating (bot, oldtop) and new (newtop) tetrahedra.
-  bots = new triface[wrapcount];
-  newtops = new triface[wrapcount];
-  // Spin around av, gather tetrahedra and set up new tetrahedra. 
-  spintet = *splittet;
-  for (i = 0; i < wrapcount; i++) {
-    // Get 'bots[i] = an1n2v'.
-    enext2fnext(spintet, bots[i]);
-    esymself(bots[i]);
-    // Get 'oldtop = n1n2va'.
-    enextfnext(bots[i], oldtop);
-    // Get 'newtops[i] = 'bn1n2v'
-    fnext(oldtop, newtops[i]); // newtop = n1n2bv
-    esymself(newtops[i]); // newtop = n2n1bv
-    enext2self(newtops[i]); // newtop = bn2n1v
-    // Go to the next.
-    fnextself(spintet);
-    if (checksubfaces && avseg.sh != dummysh) {
-      if (!issymexist(&spintet)) {
-        // We meet a hull face, walk through it.
-        tspivot(spintet, spinsh);
-#ifdef SELF_CHECK
-        assert(spinsh.sh != dummysh);
-#endif
-        findedge(&spinsh, pa, pv);
-        sfnextself(spinsh);
-        stpivot(spinsh, spintet);
-#ifdef SELF_CHECK
-        assert(spintet.tet != dummytet);
-#endif
-        findedge(&spintet, pa, pv);
-      }
-    }
-  }
-
-  if (b->verbose > 1) {
-    printf("  Removing point %d from edge (%d, %d).\n", 
-           pointmark(oppo(bots[0])), pointmark(org(bots[0])),
-           pointmark(org(newtops[0])));
-  }
-
-  for (i = 0; i < wrapcount; i++) {
-    // Expand an1n2v to an1n2b.
-    setoppo(bots[i], org(newtops[i]));
-    // Get 'oldtop = n1n2va' from 'bot[i]'.
-    enextfnext(bots[i], oldtop);
-    // Get 'topcasing' from 'newtop[i]'
-    sym(newtops[i], topcasing);
-    // Bond them.
-    bond(oldtop, topcasing);
-    if (checksubfaces) {
-      tspivot(newtops[i], topsh);
-      if (topsh.sh != dummysh) {
-        tsbond(oldtop, topsh);
-      }
-    }
-    // Delete the tetrahedron above an1n2v.
-    tetrahedrondealloc(newtops[i].tet);
-  }
-
-  // If there exists any subface, unsplit them.
-  if (checksubfaces) {
-    if (avseg.sh != dummysh) {
-      spivot(avseg, splitsh);
-#ifdef SELF_CHECK
-      assert(splitsh.sh != dummysh);
-#endif
-    }
-    if (splitsh.sh != dummysh) {
-      findedge(&splitsh, pa, pv);
-      unsplitsubedge(&splitsh);
-    }
-  }
-
-  delete [] bots;
-  delete [] newtops;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// splitsubedge()    Insert a point on an edge of the surface mesh.          //
-//                                                                           //
-// The splitting edge is given by 'splitsh'. Assume its three corners are a, //
-// b, c, where ab is the edge will be split. ab may be a subsegment.         //
-//                                                                           //
-// To split edge ab is to split all subfaces conatining ab. If ab is not a   //
-// subsegment, there are only two subfaces need be split, otherwise, there   //
-// may have any number of subfaces need be split. Each splitting subface abc //
-// is shrunk to avc, a new subface vbc is created.  It is important to keep  //
-// the orientations of edge rings of avc and vbc be the same as abc's. If ab //
-// is a subsegment, it is shrunk to av and a new subsegment vb is created.   //
-//                                                                           //
-// If there are tetrahedra adjoining to the splitting subfaces, they should  //
-// be split before calling this routine, so the connection between the new   //
-// tetrahedra and the new subfaces can be correctly set.                     //
-//                                                                           //
-// On completion, 'splitsh' returns avc.  If 'flipqueue' is not NULL, it     //
-// returns all edges which may be non-Delaunay.                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::splitsubedge(point newpoint, face* splitsh, queue* flipqueue)
-{
-  triface abcd, bace, vbcd, bvce;
-  face startabc, spinabc, spinsh;
-  face oldbc, bccasin, bccasout;
-  face ab, bc;
-  face avc, vbc, vbc1;
-  face av, vb;
-  point pa, pb;
-
-  startabc = *splitsh;
-  // Is there a subsegment?
-  sspivot(startabc, ab);
-  if (ab.sh != dummysh) {
-    ab.shver = 0; 
-    if (sorg(startabc) != sorg(ab)) {
-      sesymself(startabc);
-    }
-  }
-  pa = sorg(startabc);
-  pb = sdest(startabc);
-  
-  if (b->verbose > 1) {
-    printf("  Inserting point %d on subedge (%d, %d) %s.\n",
-           pointmark(newpoint), pointmark(pa), pointmark(pb),
-           (ab.sh != dummysh ? "(seg)" : " "));
-  }
-  
-  // Spin arround ab, split every subface containing ab.
-  spinabc = startabc;
-  do {
-    // Adjust spinabc be edge ab.
-    if (sorg(spinabc) != pa) {
-      sesymself(spinabc);
-    }
-    // Save old configuration at edge bc, if bc has a subsegment, save the
-    //   face link of it and dissolve it from bc.
-    senext(spinabc, oldbc);
-    spivot(oldbc, bccasout);    
-    sspivot(oldbc, bc);
-    if (bc.sh != dummysh) {
-      if (spinabc.sh != bccasout.sh) {
-        // 'spinabc' is not self-bonded.
-        spinsh = bccasout;
-        do {
-          bccasin = spinsh;
-          spivotself(spinsh);
-        } while (spinsh.sh != oldbc.sh);
-      } else {
-        bccasout.sh = dummysh;
-      }
-      ssdissolve(oldbc);
-    }
-    // Create a new subface.
-    makeshellface(subfaces, &vbc);
-    // Split abc.
-    avc = spinabc;  // Update 'abc' to 'avc'.
-    setsdest(avc, newpoint);
-    // Make 'vbc' be in the same edge ring as 'avc'. 
-    vbc.shver = avc.shver; 
-    setsorg(vbc, newpoint); // Set 'vbc'.
-    setsdest(vbc, pb);
-    setsapex(vbc, sapex(avc));
-    if (b->quality && varconstraint) {
-      // Copy the area bound into the new subface.
-      setareabound(vbc, areabound(avc));
-    }
-    // Copy the shell marker and shell type into the new subface.
-    setshellmark(vbc, shellmark(avc));
-    setshelltype(vbc, shelltype(avc));
-    if (checkpbcs) {
-      // Copy the pbcgroup into the new subface.
-      setshellpbcgroup(vbc, shellpbcgroup(avc));
-    }
-    // Set the connection between updated and new subfaces.
-    senext2self(vbc);
-    sbond(vbc, oldbc);
-    // Set the connection between new subface and casings.
-    senext2self(vbc);
-    if (bc.sh != dummysh) {
-      if (bccasout.sh != dummysh) {
-        // Insert 'vbc' into face link.
-        sbond1(bccasin, vbc);
-        sbond1(vbc, bccasout);
-      } else {
-        // Bond 'vbc' to itself.
-        sbond(vbc, vbc);
-      }
-      ssbond(vbc, bc);
-    } else {
-      sbond(vbc, bccasout);
-    }
-    // Go to next subface at edge ab.
-    spivotself(spinabc);
-    if (spinabc.sh == dummysh) {
-      break; // 'ab' is a hull edge.
-    }
-  } while (spinabc.sh != startabc.sh);
-
-  // Get the new subface vbc above the updated subface avc (= startabc).
-  senext(startabc, oldbc);
-  spivot(oldbc, vbc);
-  if (sorg(vbc) == newpoint) {
-    sesymself(vbc);
-  }
-#ifdef SELF_CHECK
-  assert(sorg(vbc) == sdest(oldbc) && sdest(vbc) == sorg(oldbc));
-#endif
-  senextself(vbc);
-  // Set the face link for the new created subfaces around edge vb.
-  spinabc = startabc;
-  do {
-    // Go to the next subface at edge av.
-    spivotself(spinabc);
-    if (spinabc.sh == dummysh) {
-      break; // 'ab' is a hull edge.
-    }
-    if (sorg(spinabc) != pa) {
-      sesymself(spinabc);
-    }
-    // Get the new subface vbc1 above the updated subface avc (= spinabc).
-    senext(spinabc, oldbc);
-    spivot(oldbc, vbc1);
-    if (sorg(vbc1) == newpoint) {
-      sesymself(vbc1);
-    }
-#ifdef SELF_CHECK
-    assert(sorg(vbc1) == sdest(oldbc) && sdest(vbc1) == sorg(oldbc));
-#endif
-    senextself(vbc1);
-    // Set the connection: vbc->vbc1.
-    sbond1(vbc, vbc1);
-    // For the next connection.
-    vbc = vbc1;
-  } while (spinabc.sh != startabc.sh);
-
-  // Split ab if it is a subsegment.
-  if (ab.sh != dummysh) {
-    // Update subsegment ab to av.
-    av = ab;
-    setsdest(av, newpoint);
-    // Create a new subsegment vb.
-    makeshellface(subsegs, &vb);
-    setsorg(vb, newpoint);
-    setsdest(vb, pb);
-    // vb gets the same mark and segment type as av.
-    setshellmark(vb, shellmark(av));
-    setshelltype(vb, shelltype(av));
-    if (b->quality && varconstraint) {
-      // Copy the area bound into the new subsegment.
-      setareabound(vb, areabound(av));
-    }
-    // Save the old connection at ab (re-use the handles oldbc, bccasout).
-    senext(av, oldbc);
-    spivot(oldbc, bccasout);
-    // Bond av and vb (bonded at their "fake" edges).
-    senext2(vb, bccasin);
-    sbond(bccasin, oldbc);
-    if (bccasout.sh != dummysh) {
-      // There is a subsegment connecting with ab at b. It will connect
-      //   to vb at b after splitting.
-      bccasout.shver = 0;
-      if (sorg(bccasout) != pb) sesymself(bccasout);
-#ifdef SELF_CHECK
-      assert(sorg(bccasout) == pb); 
-#endif
-      senext2self(bccasout);
-      senext(vb, bccasin);
-      sbond(bccasin, bccasout);
-    }
-    // Bond all new subfaces (vbc) to vb. 
-    spinabc = startabc;
-    do {
-      // Adjust spinabc be edge av.
-      if (sorg(spinabc) != pa) {
-        sesymself(spinabc);
-      }
-      // Get new subface vbc above the updated subface avc (= spinabc).
-      senext(spinabc, oldbc);
-      spivot(oldbc, vbc);
-      if (sorg(vbc) == newpoint) {
-        sesymself(vbc);
-      }
-      senextself(vbc);
-      // Bond the new subface and the new subsegment.
-      ssbond(vbc, vb);
-      // Go to the next.
-      spivotself(spinabc);
-#ifdef SELF_CHECK
-      assert(spinabc.sh != dummysh);
-#endif
-    } while (spinabc.sh != startabc.sh);
-  }
-
-  // Bond the new subfaces to new tetrahedra if they exist.  New tetrahedra
-  //   should have been created before calling this routine.
-  spinabc = startabc;
-  do {
-    // Adjust spinabc be edge av.
-    if (sorg(spinabc) != pa) {
-      sesymself(spinabc);
-    }
-    // Get new subface vbc above the updated subface avc (= spinabc).
-    senext(spinabc, oldbc);
-    spivot(oldbc, vbc);
-    if (sorg(vbc) == newpoint) {
-      sesymself(vbc);
-    }
-    senextself(vbc);
-    // Get the adjacent tetrahedra at 'spinabc'.
-    stpivot(spinabc, abcd);
-    if (abcd.tet != dummytet) {
-      findedge(&abcd, sorg(spinabc), sdest(spinabc));
-      enextfnext(abcd, vbcd);
-      fnextself(vbcd);
-#ifdef SELF_CHECK
-      assert(vbcd.tet != dummytet);
-#endif
-      tsbond(vbcd, vbc);
-      sym(vbcd, bvce);
-      sesymself(vbc);
-      tsbond(bvce, vbc);
-    } else {
-      // One side is empty, check the other side.
-      sesymself(spinabc);
-      stpivot(spinabc, bace);
-      if (bace.tet != dummytet) {
-        findedge(&bace, sorg(spinabc), sdest(spinabc));
-        enext2fnext(bace, bvce);
-        fnextself(bvce);
-#ifdef SELF_CHECK
-        assert(bvce.tet != dummytet);
-#endif
-        sesymself(vbc); 
-        tsbond(bvce, vbc);
-      }
-    }
-    // Go to the next.
-    spivotself(spinabc);
-    if (spinabc.sh == dummysh) {
-      break; // 'ab' is a hull edge.
-    }
-  } while (spinabc.sh != startabc.sh);
-  
-  if (b->verbose > 3) {
-    spinabc = startabc;
-    do {
-      // Adjust spinabc be edge av.
-      if (sorg(spinabc) != pa) {
-        sesymself(spinabc);
-      }
-      printf("    Updating abc:\n");
-      printsh(&spinabc);
-      // Get new subface vbc above the updated subface avc (= spinabc).
-      senext(spinabc, oldbc);
-      spivot(oldbc, vbc);
-      if (sorg(vbc) == newpoint) {
-        sesymself(vbc);
-      }
-      senextself(vbc);
-      printf("    Creating vbc:\n");
-      printsh(&vbc);
-      // Go to the next.
-      spivotself(spinabc);
-      if (spinabc.sh == dummysh) {
-        break; // 'ab' is a hull edge.
-      }
-    } while (spinabc.sh != startabc.sh);
-  }
-
-  if (flipqueue != (queue *) NULL) {
-    spinabc = startabc;
-    do {
-      // Adjust spinabc be edge av.
-      if (sorg(spinabc) != pa) {
-        sesymself(spinabc);
-      }
-      senext2(spinabc, oldbc); // Re-use oldbc.
-      enqueueflipedge(oldbc, flipqueue);
-      // Get new subface vbc above the updated subface avc (= spinabc).
-      senext(spinabc, oldbc);
-      spivot(oldbc, vbc);
-      if (sorg(vbc) == newpoint) {
-        sesymself(vbc);
-      }
-      senextself(vbc);
-      senext(vbc, oldbc); // Re-use oldbc.
-      enqueueflipedge(oldbc, flipqueue);
-      // Go to the next.
-      spivotself(spinabc);
-      if (spinabc.sh == dummysh) {
-        break; // 'ab' is a hull edge.
-      }
-    } while (spinabc.sh != startabc.sh);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// unsplitsubedge()    Reverse the operation of splitting an edge of subface,//
-//                     so as to remove a point from the edge.                //
-//                                                                           //
-// Assume the original edge is ab, the subface containing it is abc. It was  //
-// split by a point v into avc, and vbc.  'splitsh' represents avc, further- //
-// more, if av is a subsegment, av should be the zero version of the split   //
-// subsegment (i.e., av.shver = 0), so we are sure that the destination (v)  //
-// of both avc and av is the deleting point.                                 //
-//                                                                           //
-// To remove point v is to expand avc to abc, delete vbc, do the same for    //
-// other subfaces containing av and vb. If av and vb are subsegments, expand //
-// av to ab, delete vb.  On completion, point v is not deleted.              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::unsplitsubedge(face* splitsh)
-{
-  face startavc, spinavc, spinbcv;
-  face oldvc, bccasin, bccasout, spinsh;
-  face av, vb, bc;
-  point pa, pv, pb;
-
-  startavc = *splitsh;
-  sspivot(startavc, av);
-  if (av.sh != dummysh) {
-    // Orient the direction of subsegment to conform the subface. 
-    if (sorg(av) != sorg(startavc)) {
-      sesymself(av);
-    }
-#ifdef SELF_CHECK
-    assert(av.shver == 0);
-#endif
-  }
-  senext(startavc, oldvc);
-  spivot(oldvc, vb);  // vb is subface vbc
-  if (sorg(vb) != sdest(oldvc)) {
-    sesymself(vb);
-  }
-  senextself(vb);
-  pa = sorg(startavc);
-  pv = sdest(startavc);
-  pb = sdest(vb);
-
-  if (b->verbose > 1) {
-    printf("  Removing point %d from subedge (%d, %d).\n",
-           pointmark(pv), pointmark(pa), pointmark(pb));
-  }
-
-  // Spin arround av, unsplit every subface containing av.
-  spinavc = startavc;
-  do {
-    // Adjust spinavc be edge av.
-    if (sorg(spinavc) != pa) {
-      sesymself(spinavc);
-    }
-    // Save old configuration at edge bc, if bc has a subsegment, save the
-    //   face link of it.
-    senext(spinavc, oldvc);
-    spivot(oldvc, spinbcv);
-    if (sorg(spinbcv) != sdest(oldvc)) {
-      sesymself(spinbcv);
-    }
-    senext2self(spinbcv);
-    spivot(spinbcv, bccasout);
-    sspivot(spinbcv, bc);
-    if (bc.sh != dummysh) {
-      if (spinbcv.sh != bccasout.sh) {
-        // 'spinbcv' is not self-bonded.
-        spinsh = bccasout;
-        do {
-          bccasin = spinsh;
-          spivotself(spinsh);
-        } while (spinsh.sh != spinbcv.sh);
-      } else {
-        bccasout.sh = dummysh;
-      }
-    }
-    // Expand avc to abc.
-    setsdest(spinavc, pb);
-    if (bc.sh != dummysh) {
-      if (bccasout.sh != dummysh) {
-        sbond1(bccasin, oldvc);
-        sbond1(oldvc, bccasout);
-      } else {
-        // Bond 'oldbc' to itself.
-        sbond(oldvc, oldvc);
-      }
-      ssbond(oldvc, bc);
-    } else {
-      sbond(oldvc, bccasout);
-    }
-    // Delete bcv.
-    shellfacedealloc(subfaces, spinbcv.sh);
-    // Go to next subface at edge av.
-    spivotself(spinavc);
-    if (spinavc.sh == dummysh) {
-      break; // 'av' is a hull edge.
-    }
-  } while (spinavc.sh != startavc.sh);
-
-  // Is there a subsegment need to be unsplit?
-  if (av.sh != dummysh) {
-    senext(av, oldvc);  // Re-use oldvc.
-    spivot(oldvc, vb);
-    vb.shver = 0;
-#ifdef SELF_CHECK
-    assert(sdest(av) == sorg(vb));
-#endif
-    senext(vb, spinbcv); // Re-use spinbcv.
-    spivot(spinbcv, bccasout);
-    // Expand av to ab.
-    setsdest(av, pb);
-    sbond(oldvc, bccasout);
-    // Delete vb.
-    shellfacedealloc(subsegs, vb.sh);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertsite()    Insert a point into the mesh.                             //
-//                                                                           //
-// The 'newpoint' is located.  If 'searchtet->tet' is not NULL, the search   //
-// for the containing tetrahedron begins from 'searchtet', otherwise, a full //
-// point location procedure is called.  If 'newpoint' is found inside a      //
-// tetrahedron, the tetrahedron is split into four (by splittetrahedron());  //
-// if 'newpoint' lies on a face, the face is split into three, thereby       //
-// splitting the two adjacent tetrahedra into six (by splittetface()); if    //
-// 'newpoint' lies on an edge, the edge is split into two, thereby, every    //
-// tetrahedron containing this edge is split into two. If 'newpoint' lies on //
-// an existing vertex, no action is taken, and the value DUPLICATEPOINT  is  //
-// returned and 'searchtet' is set to a handle whose origin is the vertex.   //
-//                                                                           //
-// If 'flipqueue' is not NULL, after 'newpoint' is inserted, it returns all  //
-// faces which may become non-Delaunay due to the newly inserted point. Flip //
-// operations can be performed as necessary on them to maintain the Delaunay //
-// property.                                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::insertsiteresult tetgenmesh::insertsite(point newpoint,
-  triface* searchtet, bool approx, queue* flipqueue)
-{
-  enum locateresult intersect, exactloc;
-  point checkpt;
-  REAL epspp, checklen;
-  int count;
-
-  if (b->verbose > 1) {
-    printf("  Insert point to mesh: (%.12g, %.12g, %.12g) %d.\n",
-           newpoint[0], newpoint[1], newpoint[2], pointmark(newpoint));
-  }
-
-  if (searchtet->tet == (tetrahedron *) NULL) {
-    // Search for a tetrahedron containing 'newpoint'.
-    searchtet->tet = dummytet;
-    exactloc = locate(newpoint, searchtet);
-  } else {
-    // Start searching from the tetrahedron provided by the caller. 
-    exactloc = preciselocate(newpoint, searchtet, tetrahedrons->items);
-  }
-  intersect = exactloc;
-  if (approx && (exactloc != ONVERTEX)) {
-    // Adjust the exact location to an approx. location wrt. epsilon.
-    epspp = b->epsilon;
-    count = 0;
-    while (count < 16) {
-      intersect = adjustlocate(newpoint, searchtet, exactloc, epspp);
-      if (intersect == ONVERTEX) {
-        checkpt = org(*searchtet);
-        checklen = distance(checkpt, newpoint);
-        if (checklen / longest > b->epsilon) {
-          epspp *= 1e-2;
-          count++;
-          continue;
-        }
-      }
-      break;
-    }
-  }
-  // Keep current search state for next searching.
-  recenttet = *searchtet; 
-
-  // Insert the point using the right routine
-  switch (intersect) {
-  case ONVERTEX:
-    // There's already a vertex there. Return in 'searchtet' a tetrahedron
-    //   whose origin is the existing vertex.
-    if (b->verbose > 1) {
-      printf("  Not insert for duplicating point.\n");
-    }
-    return DUPLICATEPOINT;
-
-  case OUTSIDE:
-    if (b->verbose > 1) {
-      printf("  Not insert for locating outside the mesh.\n");
-    }
-    return OUTSIDEPOINT;
-
-  case ONEDGE:
-    // 'newpoint' falls on an edge.
-    splittetedge(newpoint, searchtet, flipqueue);
-    return SUCCESSONEDGE;
-
-  case ONFACE:
-    // 'newpoint' falls on a face.
-    splittetface(newpoint, searchtet, flipqueue);
-    return SUCCESSONFACE;
-
-  case INTETRAHEDRON:
-    // 'newpoint' falls inside a tetrahedron.
-    splittetrahedron(newpoint, searchtet, flipqueue);
-    return SUCCESSINTET;
-  
-  default:
-    // Impossible case.
-    return OUTSIDEPOINT;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// undosite()    Undo the most recently point insertion.                     //
-//                                                                           //
-// 'insresult' indicates in where the newpoint has been inserted, i.e., in a //
-// tetrahedron, on a face, or on an edge.  A correspoding routine will be    //
-// called to undo the point insertion.  'splittet' is a handle represent one //
-// of the resulting tetrahedra, but it may be changed after transformation,  //
-// even may be dead.  Four points 'torg', ... 'toppo' are the corners which  //
-// 'splittet' should have. On finish, 'newpoint' is not removed.             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::undosite(enum insertsiteresult insresult, triface* splittet,
-  point torg, point tdest, point tapex, point toppo)
-{
-  // Set the four corners of 'splittet' exactly be 'torg', ... 'toppo'.
-  findface(splittet, torg, tdest, tapex);
-  if (oppo(*splittet) != toppo) {
-    symself(*splittet);
-#ifdef SELF_CHECK
-    assert(oppo(*splittet) == toppo);
-#endif
-    // The sym() operation may inverse the edge, correct it if so.
-    findedge(splittet, torg, tdest);
-  }
-  
-  // Unsplit the tetrahedron according to 'insresult'.  
-  switch (insresult) {
-  case SUCCESSINTET:
-    // 'splittet' should be the face with 'newpoint' as its opposite.
-    unsplittetrahedron(splittet);
-    break;
-  case SUCCESSONFACE:
-    // 'splittet' should be the one of three splitted face with 'newpoint'
-    //   as its apex.
-    unsplittetface(splittet);
-    break;
-  case SUCCESSONEDGE:
-    // 'splittet' should be the tet with destination is 'newpoint'.
-    unsplittetedge(splittet);
-    break;
-  default: // To omit compile warnings.
-    break;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// closeopenface()    Close "open" faces recursively.                        //
-//                                                                           //
-// This is the support routine of inserthullsite(). A point p which lies out-//
-// side of CH(T). p is inserted to T by forming a tet t from p and a visible //
-// CH face f. The three sides of f which have p as a vertex is called "open" //
-// face. Each open face will be closed by either creating a tet on top of it //
-// or become a new CH face.                                                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::closeopenface(triface* openface, queue* flipque)
-{
-  triface newtet, oldhull;
-  triface newopenface, closeface;
-  point inspoint, pa, pb, pc;
-  REAL attrib, volume;
-  int i;
-
-  // Get the new point p.
-  inspoint = apex(*openface);
-  // Find the old CH face f_o (f and f_o share the same edge). 
-  esym(*openface, oldhull);
-  while (fnextself(oldhull)) ;
-  if (apex(oldhull) != inspoint) {
-    // Is f_o visible by p?
-    pa = org(oldhull);
-    pb = dest(oldhull);
-    pc = apex(oldhull);
-    if (orient3d(pa, pb, pc, inspoint) < 0.0) {
-      // Yes. Create a new tet t above f_o.
-      maketetrahedron(&newtet);
-      setorg(newtet, pa);
-      setdest(newtet, pb);
-      setapex(newtet, pc);
-      setoppo(newtet, inspoint); 
-      for (i = 0; i < in->numberoftetrahedronattributes; i++) {
-        attrib = elemattribute(oldhull.tet, i);
-        setelemattribute(newtet.tet, i, attrib);
-      }
-      if (b->varvolume) {
-        volume = volumebound(oldhull.tet);
-        setvolumebound(newtet.tet, volume);
-      }
-      // Connect t to T.
-      bond(newtet, oldhull);
-      // Close f.
-      fnext(newtet, newopenface);
-      bond(newopenface, *openface);
-      // f_o becomes an interior face.
-      enqueueflipface(oldhull, flipque);
-      // Hull face number decreases.
-      hullsize--; 
-      // Two faces of t become open face.
-      enextself(newtet);
-      for (i = 0; i < 2; i++) {
-        fnext(newtet, newopenface);
-        sym(newopenface, closeface);
-        if (closeface.tet == dummytet) {
-          closeopenface(&newopenface, flipque);
-        }
-        enextself(newtet);
-      }
-    } else {
-      // Inivisible. f becomes a new CH face.
-      hullsize++;
-      // Let 'dummytet' holds f for the next point location.
-      dummytet[0] = encode(*openface);
-    }
-  } else {
-    // f_o is co-incident with f --> f is closed by f_o.
-    bond(*openface, oldhull);
-    // f is an interior face.
-    enqueueflipface(*openface, flipque);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// inserthullsite()    Insert a point which lies outside the convex hull.    //
-//                                                                           //
-// The 'inspoint' p lies outside the tetrahedralization T.  The 'horiz' f is //
-// on the convex hull of T, CH(T), which is visible by p (Imagine f is para- //
-// llel to the horizon). To insert p into T we have to enlarge the CH(T) and //
-// update T so that p is on the new CH(T).                                   //
-//                                                                           //
-// To enlarge the CH(T).  We need to find the set F of faces which are on CH //
-// (T) and visible by p (F can be formed by a depth-first search from f).  p //
-// is then inserted into T by mounting new tets formed by p and these faces. //
-// Faces of F become interior faces and may non-locally Delaunay.  They are  //
-// queued in 'flipqueue' for flip tests.                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::inserthullsite(point inspoint, triface* horiz, queue* flipque)
-{
-  triface firstnewtet;
-  triface openface, closeface;
-  REAL attrib, volume;
-  int i;
-
-  // Let f face to p.
-  adjustedgering(*horiz, CW);
-  // Create the first tet t (from f and p).
-  maketetrahedron(&firstnewtet);
-  setorg (firstnewtet, org(*horiz));
-  setdest(firstnewtet, dest(*horiz));
-  setapex(firstnewtet, apex(*horiz));
-  setoppo(firstnewtet, inspoint);
-  for (i = 0; i < in->numberoftetrahedronattributes; i++) {
-    attrib = elemattribute(horiz->tet, i);
-    setelemattribute(firstnewtet.tet, i, attrib);
-  }
-  if (b->varvolume) {
-    volume = volumebound(horiz->tet);
-    setvolumebound(firstnewtet.tet, volume);
-  }
-  // Connect t to T.
-  bond(firstnewtet, *horiz);
-  // f is not on CH(T) anymore.
-  enqueueflipface(*horiz, flipque);
-  // Hull face number decreases.
-  hullsize--;
-
-  // Call the faces of t which have p as a vertex "open" face.
-  for (i = 0; i < 3; i++) {
-    // Get an open face f_i of t.
-    fnext(firstnewtet, openface);
-    // Close f_i if it is still open.
-    sym(openface, closeface);
-    if (closeface.tet == dummytet) {
-      closeopenface(&openface, flipque);
-    }
-    // Go to the next open face of t.
-    enextself(firstnewtet);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Terminology: BC(p) and CBC(p), B(p) and C(p).                             //
-//                                                                           //
-// Given an arbitrary point p,  the Bowyer-Watson cavity BC(p) is formed by  //
-// tets whose circumspheres containing p.  The outer faces of BC(p) form a   //
-// polyhedron B(p).                                                          //
-//                                                                           //
-// If p is on a facet F, the constrained Bowyer-Watson cavity CBC(p) on F is //
-// formed by subfaces of F whose circumspheres containing p. The outer edges //
-// of CBC(p) form a polygon C(p).  B(p) is separated into two parts by C(p), //
-// denoted as B_1(p) and B_2(p), one of them may be empty (F is on the hull).//
-//                                                                           //
-// If p is on a segment S which is shared by n facets.  There exist n C(p)s, //
-// each one is a non-closed polygon (without S). B(p) is split into n parts, //
-// each of them is denoted as B_i(p), some B_i(p) may be empty.              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// formbowatcavitysub()    Form CBC(p) and C(p) on a facet F.                //
-//                                                                           //
-// Parameters: bp = p, bpseg = S, sublist = CBC(p), subceillist = C(p).      //
-//                                                                           //
-// CBC(p) contains at least one subface on input; S may be NULL which means  //
-// that p is inside a facet. On output, all subfaces of CBC(p) are infected, //
-// and the edge rings are oriented to the same halfspace.                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::formbowatcavitysub(point bp, face* bpseg, list* sublist,
-  list* subceillist)
-{
-  triface adjtet;
-  face startsh, neighsh;
-  face checkseg;
-  point pa, pb, pc, pd;
-  REAL sign;
-  int i, j;  
-
-  // Form CBC(p) and C(p) by a broadth-first searching.
-  for (i = 0; i < sublist->len(); i++) {
-    startsh = * (face *)(* sublist)[i]; // startsh = f.
-    // Look for three neighbors of f.
-    for (j = 0; j < 3; j++) {
-      sspivot(startsh, checkseg);
-      if (checkseg.sh == dummysh) {
-        // Get its neighbor n.
-        spivot(startsh, neighsh);
-        // Is n already in CBC(p)?
-        if (!sinfected(neighsh)) {
-          stpivot(neighsh, adjtet);
-          if (adjtet.tet == dummytet) {
-            sesymself(neighsh);
-            stpivot(neighsh, adjtet);
-          }
-          // For positive orientation that insphere() test requires.
-          adjustedgering(adjtet, CW);
-          pa = org(adjtet);
-          pb = dest(adjtet);
-          pc = apex(adjtet);
-          pd = oppo(adjtet);
-          sign = insphere(pa, pb, pc, pd, bp);
-          if (sign >= 0.0) {
-            // Orient edge ring of n according to that of f.
-            if (sorg(neighsh) != sdest(startsh)) sesymself(neighsh);
-            // Collect it into CBC(p).
-            sinfect(neighsh);
-            sublist->append(&neighsh);
-          } else {
-            subceillist->append(&startsh); // Found an edge of C(p).
-          }
-        }
-      } else {
-        // Do not cross a segment.
-        if (bpseg != (face *) NULL) {
-          if (checkseg.sh != bpseg->sh) {
-            subceillist->append(&startsh); // Found an edge of C(p).
-          }
-        } else {
-          subceillist->append(&startsh); // Found an edge of C(p).
-        }
-      }
-      senextself(startsh);
-    }
-  }
-
-  if (b->verbose > 2) {
-    printf("    Collect CBC(%d): %d subfaces, %d edges.\n", pointmark(bp),
-           sublist->len(), subceillist->len());
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// formbowatcavityquad()    Form BC_i(p) and B_i(p) in a quadrant.           //
-//                                                                           //
-// Parameters: bp = p, tetlist = BC_i(p), ceillist = B_i(p).                 //
-//                                                                           //
-// BC_i(p) contains at least one tet on input. On finish, all tets collected //
-// in BC_i(p) are infected. B_i(p) may not closed when p is on segment or in //
-// facet. C(p) must be formed before this routine.  Check the infect flag of //
-// a subface to identify the unclosed side of B_i(p).  These sides will be   //
-// closed by new subfaces of C(p)s.                                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::formbowatcavityquad(point bp, list* tetlist, list* ceillist)
-{
-  triface starttet, neightet;
-  face checksh;
-  point pa, pb, pc, pd;
-  REAL sign;
-  int i;
-
-  // Form BC_i(p) and B_i(p) by a broadth-first searching.
-  for (i = 0; i < tetlist->len(); i++) {
-    starttet = * (triface *)(* tetlist)[i];
-    for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
-      // Try to collect the neighbor of the face (f).
-      tspivot(starttet, checksh);
-      if (checksh.sh == dummysh) {
-        // Get its neighbor n.
-        sym(starttet, neightet);
-        // Is n already in BC_i(p)?
-        if (!infected(neightet)) {
-          // For positive orientation that insphere() test requires.
-          adjustedgering(neightet, CW);
-          pa = org(neightet);
-          pb = dest(neightet);
-          pc = apex(neightet);
-          pd = oppo(neightet);
-          sign = insphere(pa, pb, pc, pd, bp);
-          if (sign >= 0.0) {
-            // Collect it into BC_i(p).
-            infect(neightet);
-            tetlist->append(&neightet);
-          } else {
-            ceillist->append(&starttet); // Found a face of B_i(p).
-          }
-        }
-      } else {
-        // Do not cross a boundary face.
-        if (!sinfected(checksh)) {
-          ceillist->append(&starttet); // Found a face of B_i(p).
-        }
-      }
-    }
-  }
-
-  if (b->verbose > 2) {
-    printf("    Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
-           tetlist->len(), ceillist->len());
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// formbowatcavitysegquad()    Form BC_i(p) and B_i(p) in a segment quadrant.//
-//                                                                           //
-// Parameters: bp = p, tetlist = BC_i(p), ceillist = B_i(p).                 //
-//                                                                           //
-// BC_i(p) contains at least one tet on input. On finish, all tets collected //
-// in BC_i(p) are infected. B_i(p) is not closed. C(p) must be formed before //
-// this routine. Check the infect flag of a subface to identify the unclosed //
-// sides of B_i(p).  These sides will be closed by new subfaces of C(p)s.    //
-//                                                                           //
-// During the repair of encroaching subsegments, there may exist locally non-//
-// Delaunay faces. These faces are collected in BC_i(p) either.  B_i(p) has  //
-// to be formed later than BC_i(p).                                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::formbowatcavitysegquad(point bp, list* tetlist,list* ceillist)
-{
-  triface starttet, neightet, cavtet;
-  face checksh;
-  point pa, pb, pc, pd, pe;
-  REAL sign;
-  int i;
-
-  // Form BC_i(p) by a broadth-first searching.
-  for (i = 0; i < tetlist->len(); i++) {
-    starttet = * (triface *)(* tetlist)[i];
-    for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
-      // Try to collect the neighbor of the face f.
-      tspivot(starttet, checksh);
-      if (checksh.sh == dummysh) {
-        // Get its neighbor n.
-        sym(starttet, neightet);
-        // Is n already in BC_i(p)?
-        if (!infected(neightet)) {
-          // For positive orientation that insphere() test requires.
-          adjustedgering(neightet, CW);
-          pa = org(neightet);
-          pb = dest(neightet);
-          pc = apex(neightet);
-          pd = oppo(neightet);
-          sign = insphere(pa, pb, pc, pd, bp);
-          if (sign >= 0.0) {
-            // Collect it into BC_i(p).
-            infect(neightet);
-            tetlist->append(&neightet);
-          } else {
-            // Check if the face is locally non-Delaunay.
-            pe = oppo(starttet);
-            sign = insphere(pa, pb, pc, pd, pe);
-            if (sign >= 0.0) {
-              // Collect it into BC_i(p).
-              infect(neightet);
-              tetlist->append(&neightet);
-            }
-          }
-        }
-      }
-    }
-  }
-
-  // Generate B_i(p).
-  for (i = 0; i < tetlist->len(); i++) {
-    cavtet = * (triface *)(* tetlist)[i];
-    for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
-      tspivot(cavtet, checksh);
-      if (checksh.sh == dummysh) {
-        sym(cavtet, neightet);
-        if (!infected(neightet)) {
-          ceillist->append(&cavtet); // Found a face of B(p).
-        }
-      } else {
-        // Do not cross a boundary face.
-        if (!sinfected(checksh)) {
-          ceillist->append(&cavtet); // Found a face of B(p).
-        }
-      }
-    }
-  }
-
-  if (b->verbose > 2) {
-    printf("    Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
-           tetlist->len(), ceillist->len());
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// formbowatcavity()    Form BC(p), B(p), CBC(p)s, and C(p)s.                //
-//                                                                           //
-// If 'bpseg'(S) != NULL, p is on segment S, else, p is on facet containing  //
-// 'bpsh' (F).  'n' returns the number of quadrants in BC(p). 'nmax' is the  //
-// maximum pre-allocated array length for the lists.                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::formbowatcavity(point bp, face* bpseg, face* bpsh, int* n,
-  int* nmax, list** sublists, list** subceillists, list** tetlists,
-  list** ceillists)
-{
-  list *sublist;
-  triface adjtet;
-  face startsh, spinsh;
-  point pa, pb;
-  int i, j;
-
-  *n = 0;
-  if (bpseg != (face *) NULL) {
-    // p is on segment S.
-    bpseg->shver = 0;
-    pa = sorg(*bpseg);
-    pb = sdest(*bpseg);
-    // Count the number of facets sharing at S.
-    spivot(*bpseg, startsh);
-    spinsh = startsh;
-    do {
-      (*n)++; // spinshlist->append(&spinsh);
-      spivotself(spinsh);
-    } while (spinsh.sh != startsh.sh);
-    // *n is the number of quadrants around S.
-    if (*n > *nmax) {
-      // Reallocate arrays. Should not happen very often.
-      delete [] tetlists;
-      delete [] ceillists;
-      delete [] sublists;
-      delete [] subceillists;
-      tetlists = new list*[*n];
-      ceillists = new list*[*n];
-      sublists = new list*[*n];
-      subceillists = new list*[*n];
-      *nmax = *n;
-    }
-    // Form CBC(p)s and C(p)s.
-    spinsh = startsh;
-    for (i = 0; i < *n; i++) {
-      sublists[i] = new list(sizeof(face), NULL, 256);
-      subceillists[i] = new list(sizeof(face), NULL, 256);
-      // Set a subface f to start search.
-      startsh = spinsh;
-      // Let f face to the quadrant of interest (used in forming BC(p)).
-      findedge(&startsh, pa, pb);
-      sinfect(startsh);
-      sublists[i]->append(&startsh);
-      formbowatcavitysub(bp, bpseg, sublists[i], subceillists[i]);
-      // Go to the next facet.
-      spivotself(spinsh);
-    }
-  } else if (sublists != (list **) NULL) {
-    // p is on a facet.
-    *n = 2;
-    // Form CBC(p) and C(p).
-    sublists[0] = new list(sizeof(face), NULL, 256);
-    subceillists[0] = new list(sizeof(face), NULL, 256);
-    sinfect(*bpsh);
-    sublists[0]->append(bpsh);
-    formbowatcavitysub(bp, NULL, sublists[0], subceillists[0]);
-  } else {
-    // p is inside a tet.
-    *n = 1;
-  }
-
-  // Form BC_i(p) and B_i(p).
-  for (i = 0; i < *n; i++) {
-    tetlists[i] = new list(sizeof(triface), NULL, 256);
-    ceillists[i] = new list(sizeof(triface), NULL, 256);
-    if (sublists != (list **) NULL) {
-      // There are C(p)s.
-      sublist = ((bpseg == (face *) NULL) ? sublists[0] : sublists[i]);
-      // Add all adjacent tets of C_i(p) into BC_i(p).
-      for (j = 0; j < sublist->len(); j++) {    
-        startsh = * (face *)(* sublist)[j];
-        // Adjust the side facing to the right quadrant for C(p).
-        if ((bpseg == (face *) NULL) && (i == 1)) sesymself(startsh);
-        stpivot(startsh, adjtet);
-        if (adjtet.tet != dummytet) {
-          if (!infected(adjtet)) {
-            infect(adjtet);
-            tetlists[i]->append(&adjtet);
-          }
-        }
-      }
-      if (bpseg != (face *) NULL) {
-        // The quadrant is bounded by another facet.
-        sublist = ((i < *n - 1) ? sublists[i + 1] : sublists[0]);
-        for (j = 0; j < sublist->len(); j++) {    
-          startsh = * (face *)(* sublist)[j];
-          // Adjust the side facing to the right quadrant for C(p).
-          sesymself(startsh);
-          stpivot(startsh, adjtet);
-          if (adjtet.tet != dummytet) {
-            if (!infected(adjtet)) {
-              infect(adjtet);
-              tetlists[i]->append(&adjtet);
-            }
-          }
-        }
-      }
-    }
-    // It is possible that BC_i(p) is empty.
-    if (tetlists[i]->len() == 0) continue;
-    // Collect the rest of tets of BC_i(p) and form B_i(p).
-    // if (b->conformdel) {
-      // formbowatcavitysegquad(bp, tetlists[i], ceillists[i]);
-    // } else {
-      formbowatcavityquad(bp, tetlists[i], ceillists[i]);
-    // }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// releasebowatcavity()    Undo and free the memory allocated in routine     //
-//                         formbowatcavity().                                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::releasebowatcavity(face* bpseg, int n, list** sublists,
-  list** subceillist, list** tetlists, list** ceillists)
-{
-  triface oldtet;
-  face oldsh;
-  int i, j;
-
-  if (sublists != (list **) NULL) {
-    // Release CBC(p)s.
-    for (i = 0; i < n; i++) {
-      // Uninfect subfaces of CBC(p).
-      for (j = 0; j < sublists[i]->len(); j++) {
-        oldsh = * (face *)(* (sublists[i]))[j];
-#ifdef SELF_CHECK
-        assert(sinfected(oldsh));
-#endif
-        suninfect(oldsh);
-      }
-      delete sublists[i];
-      delete subceillist[i];
-      sublists[i] = (list *) NULL;
-      subceillist[i] = (list *) NULL;
-      if (bpseg == (face *) NULL) break;
-    }
-  }
-  // Release BC(p).
-  for (i = 0; i < n; i++) {
-    // Uninfect tets of BC_i(p).
-    for (j = 0; j < tetlists[i]->len(); j++) {
-      oldtet = * (triface *)(* (tetlists[i]))[j];
-#ifdef SELF_CHECK
-      assert(infected(oldtet));
-#endif
-      uninfect(oldtet);
-    }
-    delete tetlists[i];
-    delete ceillists[i];
-    tetlists[i] = (list *) NULL;
-    ceillists[i] = (list *) NULL;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// validatebowatcavityquad()    Valid B_i(p).                                //
-//                                                                           //
-// B_i(p) is valid if all faces of B_i(p) are visible by p, else B_i(p) is   //
-// invalid.  Each tet of BC_i(p) which has such a face is marked (uninfect). //
-// They will be removed in updatebowatcavityquad().                          //
-//                                                                           //
-// Return TRUE if B(p) is valid, else, return FALSE.                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::validatebowatcavityquad(point bp,list* ceillist,REAL maxcosd)
-{
-  triface ceiltet;
-  point pa, pb, pc;
-  REAL ori, cosd;
-  int remcount, i;
-
-  // Check the validate of B(p), cut tets having invisible faces.
-  remcount = 0;
-  for (i = 0; i < ceillist->len(); i++) {
-    ceiltet = * (triface *)(* ceillist)[i];
-    if (infected(ceiltet)) {
-      adjustedgering(ceiltet, CCW);
-      pa = org(ceiltet);
-      pb = dest(ceiltet);
-      pc = apex(ceiltet);
-      ori = orient3d(pa, pb, pc, bp);
-      if (ori >= 0.0) {
-        // Found an invisible face.
-        uninfect(ceiltet);
-        remcount++;
-        continue;
-      }
-      // If a non-trival 'maxcosd' is given.
-      if (maxcosd > -1.0) {
-        // Get the maximal dihedral angle of tet abcp.
-        tetalldihedral(pa, pb, pc, bp, NULL, &cosd, NULL);
-        // Do not form the tet if the maximal dihedral angle is not reduced.
-        if (cosd < maxcosd) {
-          uninfect(ceiltet);
-          remcount++;
-        }
-      }
-    }
-  }
-  return remcount == 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// updatebowatcavityquad()    Update BC_i(p) and reform B_i(p).              //
-//                                                                           //
-// B_i(p) is invalid and some tets in BC_i(p) have been marked to be removed //
-// in validatebowatcavityquad().  This routine actually remove the cut tets  //
-// of BC_i(p) and re-form the B_i(p).                                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::updatebowatcavityquad(list* tetlist, list* ceillist)
-{
-  triface cavtet, neightet;
-  face checksh;
-  int remcount, i;
-
-  remcount = 0;
-  for (i = 0; i < tetlist->len(); i++) {
-    cavtet = * (triface *)(* tetlist)[i];
-    if (!infected(cavtet)) {
-      tetlist->del(i, 1);
-      remcount++;
-      i--;
-    }
-  }
-
-  // Are there tets have been cut in BC_i(p)?
-  if (remcount > 0) {
-    // Re-form B_i(p).
-    ceillist->clear();
-    for (i = 0; i < tetlist->len(); i++) {
-      cavtet = * (triface *)(* tetlist)[i];
-      for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
-        tspivot(cavtet, checksh);
-        if (checksh.sh == dummysh) {
-          sym(cavtet, neightet);
-          if (!infected(neightet)) {
-            ceillist->append(&cavtet); // Found a face of B_i(p).
-          }
-        } else {
-          // Do not cross a boundary face.
-          if (!sinfected(checksh)) {
-            ceillist->append(&cavtet); // Found a face of B_i(p).
-          }
-        }
-      }
-    }
-    if (b->verbose > 2) {
-      printf("    Update BC_i(p): %d tets, %d faces.\n", tetlist->len(),
-             ceillist->len());
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// updatebowatcavitysub()    Check and update CBC(p) and C(p).               //
-//                                                                           //
-// A CBC(p) is valid if all its subfaces are inside or on the hull of BC(p). //
-// A subface s of CBC(p) is invalid if it is in one of the two cases:        //
-//   (1) s is completely outside BC(p);                                      //
-//   (2) s has two adjacent tets but only one of them is in BC(p);           //
-// s is removed from CBC(p) if it is invalid. If there is an adjacent tet of //
-// s which is in BC(p), it gets removed from BC(p) too. If CBC(p) is updated,//
-// C(p) is re-formed.                                                        //
-//                                                                           //
-// A C(p) is valid if all its edges are on the hull of BC(p).  An edge e of  //
-// C(p) may be inside BC(p) if e is a segment and belongs to only one facet. //
-// To correct C(p), a tet of BC(p) which shields e gets removed.             //
-//                                                                           //
-// If BC(p) is formed with locally non-Delaunay check (b->conformdel > 0).   //
-// A boundary-consistent check is needed for non-segment edges of C(p). Let  //
-// e be such an edge, the subface f contains e and outside C(p) may belong   //
-// to B(p) due to the non-coplanarity of the facet definition.  The tet of   //
-// BC(p) containing f gets removed to avoid creating a degenerate new tet.   //
-//                                                                           //
-// 'cutcount' accumulates the total number of cuttets(not only by this call).//
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::updatebowatcavitysub(list* sublist, list* subceillist,
-  int* cutcount)
-{
-  triface adjtet, rotface;
-  face checksh, neighsh;
-  face checkseg;
-  point pa, pb, pc;
-  REAL ori1, ori2;
-  int remcount;
-  int i, j;
-
-  remcount = 0;
-  // Check the validity of CBC(p).
-  for (i = 0; i < sublist->len(); i++) {
-    checksh = * (face *)(* sublist)[i];
-    // Check two adjacent tets of s.
-    for (j = 0; j < 2; j++) {
-      stpivot(checksh, adjtet);
-      if (adjtet.tet != dummytet) {
-        if (!infected(adjtet)) {
-          // Could be either case (1) or (2).
-          suninfect(checksh); // s survives.
-          // If the sym. adjtet exists, it should remove from BC(p) too.
-          sesymself(checksh);
-          stpivot(checksh, adjtet);
-          if (adjtet.tet != dummytet) {
-            if (infected(adjtet)) {
-              // Found an adj. tet in BC(p), remove it.
-              uninfect(adjtet);
-              (*cutcount)++;
-            }
-          }
-          // Remove s from C(p).
-          sublist->del(i, 1);
-          i--;
-          remcount++;
-          break;
-        }
-      }
-      sesymself(checksh);
-    }
-  }
-  if (remcount > 0) {
-    if (b->verbose > 2) {
-      printf("    Removed %d subfaces from CBC(p).\n", remcount);
-    }
-    // Re-generate C(p).
-    subceillist->clear();
-    for (i = 0; i < sublist->len(); i++) {
-      checksh = * (face *)(* sublist)[i];
-      for (j = 0; j < 3; j++) {
-        spivot(checksh, neighsh);
-        if (!sinfected(neighsh)) {
-          subceillist->append(&checksh);
-        }
-        senextself(checksh);
-      }
-    }
-    if (b->verbose > 2) {
-      printf("    Update CBC(p): %d subs, %d edges.\n", sublist->len(),
-             subceillist->len());
-    }
-  }
-
-  // Check the validity of C(p).
-  for (i = 0; i < subceillist->len(); i++) {
-    checksh = * (face *)(* subceillist)[i];
-    sspivot(checksh, checkseg);
-    if (checkseg.sh != dummysh) {
-      // A segment. Check if it is inside BC(p).
-      stpivot(checksh, adjtet);
-      if (adjtet.tet == dummytet) {
-        sesym(checksh, neighsh);
-        stpivot(neighsh, adjtet);
-      }
-      findedge(&adjtet, sorg(checkseg), sdest(checkseg));
-      adjustedgering(adjtet, CCW);
-      fnext(adjtet, rotface); // It's the same tet.
-      // Rotate rotface (f), stop on either of the following cases:
-      //   (a) meet a subface, or
-      //   (b) enter an uninfected tet, or
-      //   (c) rewind back to adjtet.
-      do {
-        if (!infected(rotface)) break; // case (b)
-        tspivot(rotface, neighsh);
-        if (neighsh.sh != dummysh) break; // case (a)
-        // Go to the next tet of the facing ring.
-        fnextself(rotface);
-      } while (apex(rotface) != apex(adjtet));
-      // Is it case (c)?
-      if (apex(rotface) == apex(adjtet)) {
-        // The segment is enclosed by BC(p), invalid cavity.
-        pa = org(adjtet);
-        pb = dest(adjtet);
-        pc = apex(adjtet);
-        // Find the shield tet and cut it. Notice that the shield tet may
-        //   not be unique when there are four coplanar points, ie.,
-        //   ori1 * ori2 == 0.0. In such case, choose either of them.
-        fnext(adjtet, rotface);
-        do {
-          fnextself(rotface);
-          assert(infected(rotface));
-          ori1 = orient3d(pa, pb, pc, apex(rotface));
-          ori2 = orient3d(pa, pb, pc, oppo(rotface));
-        } while (ori1 * ori2 > 0.0);
-        // Cut this tet from BC(p).
-        uninfect(rotface);
-        (*cutcount)++;
-      }
-    } else {
-      /*// An edge. Check if boundary-consistency should be enforced.
-      if (b->conformdel > 0) {
-        // Get the adj-sub n at e, it must be outside C(p).
-        spivot(checksh, neighsh);
-        assert(!sinfected(neighsh));
-        // Check if n is on B(p).
-        for (j = 0; j < 2; j++) {
-          stpivot(neighsh, adjtet);
-          if (adjtet.tet != dummytet) {
-            if (infected(adjtet)) {
-              uninfect(adjtet);
-              (*cutcount)++;
-            }
-          }
-          sesymself(neighsh);
-        }
-      } */
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// trimbowatcavity()    Validate B(p), CBC(p)s and C(p)s, update BC(p).      //
-//                                                                           //
-// A B(p) is valid if all its faces are visible by p. If a face f of B(p) is //
-// found invisible by p, the tet of BC(p) containing f gets removed and B(p) //
-// is refromed. The new B(p) may still contain invisible faces by p. Iterat- //
-// ively do the above procedure until B(p) is satisfied.                     //
-//                                                                           //
-// A CBC(p) is valid if each subface of CBC(p) is either on the hull of BC(p)//
-// or completely inside BC(p). If a subface s of CBC(p) is not valid, it is  //
-// removed from CBC(p) and C(p) is reformed. If there exists a tet t of BC(p)//
-// containg s, t is removed from BC(p). The process for validating BC(p) and //
-// B(p) is re-excuted.                                                       //
-//                                                                           //
-// A C(p) is valid if each edge of C(p) is on the hull of BC(p). If an edge  //
-// e of C(p) is invalid (e should be a subsegment which only belong to one   //
-// facet), a tet of BC(p) which contains e and has two other faces shielding //
-// e is removed. The process for validating BC(p) and B(p) is re-excuted.    //
-//                                                                           //
-// If either BC(p) or CBC(p) becomes empty. No valid BC(p) is found, return  //
-// FALSE. else, return TRUE.                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::trimbowatcavity(point bp, face* bpseg, int n, list** sublists,
-  list** subceillists, list** tetlists, list** ceillists, REAL maxcosd)
-{
-  bool valflag;
-  int oldnum, cutnum, cutcount;
-  int i;
-
-  cutnum = 0; // Count the total number of cut-off tets of BC(p).
-  valflag = true;
-
-  do {
-    // Validate BC(p), B(p).
-    for (i = 0; i < n && valflag; i++) {
-      oldnum = tetlists[i]->len();
-      // Iteratively validate BC_i(p) and B_i(p).
-      while (!validatebowatcavityquad(bp, ceillists[i], maxcosd)) {
-        // Update BC_i(p) and B_i(p).
-        updatebowatcavityquad(tetlists[i], ceillists[i]);
-        valflag = tetlists[i]->len() > 0;
-      }
-      cutnum += (oldnum - tetlists[i]->len());
-    }
-    if (valflag && (sublists != (list **) NULL)) {
-      // Validate CBC(p), C(p).
-      cutcount = 0;
-      for (i = 0; i < n; i++) {
-        updatebowatcavitysub(sublists[i], subceillists[i], &cutcount);
-        // Only do once if p is on a facet.
-        if (bpseg == (face *) NULL) break; 
-      }
-      // Are there cut tets?
-      if (cutcount > 0) {
-        // Squeeze all cut tets in BC(p), keep valflag once it gets FLASE.
-        for (i = 0; i < n; i++) {
-          if (tetlists[i]->len() > 0) {
-            updatebowatcavityquad(tetlists[i], ceillists[i]);
-            if (valflag) {
-              valflag = tetlists[i]->len() > 0;
-            }
-          }
-        }
-        cutnum += cutcount;
-        // Go back to valid the updated BC(p).
-        continue;
-      }
-    }
-    break; // Leave the while-loop.
-  } while (true);
-
-  // Check if any CBC(p) becomes non-empty.
-  if (valflag && (sublists != (list **) NULL)) {
-    for (i = 0; i < n && valflag; i++) {
-      valflag = (sublists[i]->len() > 0);
-      if (bpseg == (face *) NULL) break; 
-    }
-  }
-
-  if (valflag && (cutnum > 0)) {
-    // Accumulate counters.
-    if (bpseg != (face *) NULL) {
-      updsegcount++;
-    } else if (sublists != (list **) NULL) {
-      updsubcount++;
-    } else {
-      updvolcount++;
-    }
-  }
-
-  if (!valflag) {
-    // Accumulate counters.
-    if (bpseg != (face *) NULL) {
-      failsegcount++;
-    } else if (sublists != (list **) NULL) {
-      failsubcount++;
-    } else {
-      failvolcount++;
-    }
-  }
-
-  return valflag;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// bowatinsertsite()    Insert a point using the Bowyer-Watson method.       //
-//                                                                           //
-// Parameters: 'bp' = p, 'splitseg' = S, 'n' = the number of quadrants,      //
-// 'sublists', an array of CBC_i(p)s, 'subceillists', an array of C_i(p)s,   //
-// 'tetlists', an array of BC_i(p)s, 'ceillists', an array of B_i(p)s.       //
-//                                                                           //
-// If p is inside the mesh domain, then S = NULL, n = 1, CBC(p) and C(p) are //
-//   NULLs. 'tetlists[0]' = BC(p), 'ceillists[0]' = B(p).                    //
-// If p is on a facet F, then S = NULL, n = 2, and 'subceillists[0]' = C(p), //
-//  'subceillists[1]' is not needed (set it to NULL). B_1(p) and B_2(p) are  //
-//  in 'ceillists[0]' and 'ceillists[1]'.                                    //
-// If p is on a segment S, then F(S) is a list of subfaces around S, and n = //
-//   len(F(S)), there are n C_i(p)s and B_i(p)s supplied in 'subceillists[i]'//
-//   and 'ceillists[i]'.                                                     //
-//                                                                           //
-// If 'verlist' != NULL, it returns a list of vertices which connect to p.   //
-//   This vertices are used for interpolating size of p.                     //
-//                                                                           //
-// If 'flipque' != NULL, it returns a list of internal faces of new tets in  //
-//   BC(p), faces on C(p)s are excluded. These faces may be locally non-     //
-//   Delaunay and will be flipped if they are flippable. Such non-Delaunay   //
-//   faces may exist when p is inserted to split an encroaching segment.     //
-//                                                                           //
-// 'chkencseg', 'chkencsub', and 'chkbadtet' are flags that indicate whether //
-// or not there should be checks for the creation of encroached subsegments, //
-// subfaces, or bad quality tets. If 'chkencseg' = TRUE, the encroached sub- //
-// segments are added to the list of subsegments to be split.                //
-//                                                                           //
-// On return, 'ceillists' returns Star(p).                                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::bowatinsertsite(point bp,face* splitseg,int n,list** sublists,
-  list** subceillists, list** tetlists, list** ceillists, list* verlist,
-  queue* flipque, bool chkencseg, bool chkencsub, bool chkbadtet)
-{
-  list *ceillist, *subceillist; 
-  triface oldtet, newtet, newface, rotface, neightet; 
-  face oldsh, newsh, newedge, checksh;
-  face spinsh, casingin, casingout;
-  face *apsegshs, *pbsegshs;
-  face apseg, pbseg, checkseg;
-  point pa, pb, pc;
-  REAL attrib, volume;
-  int idx, i, j, k;
-
-  if (b->verbose > 1) {
-    printf("    Insert point %d (%.12g, %.12g, %.12g)", pointmark(bp), bp[0],
-           bp[1], bp[2]);
-  }
-  if (splitseg != (face *) NULL) {
-    if (b->verbose > 1) {
-      printf(" on segment.\n");
-    }
-    bowatsegcount++;
-  } else {
-    if (subceillists != (list **) NULL) {
-      if (b->verbose > 1) {
-        printf(" on facet.\n");
-      }
-      bowatsubcount++;
-    } else {
-      if (b->verbose > 1) {
-        printf(" in volume.\n");
-      }
-      bowatvolcount++;
-    }
-  }
-
-  // Create new tets to fill B(p).
-  for (k = 0; k < n; k++) {
-    // Create new tets from each B_i(p).
-    ceillist = ceillists[k];
-    for (i = 0; i < ceillist->len(); i++) {
-      oldtet = * (triface *)(* ceillist)[i];
-      adjustedgering(oldtet, CCW);
-      pa = org(oldtet);
-      pb = dest(oldtet);
-      pc = apex(oldtet);
-      maketetrahedron(&newtet);
-      setorg(newtet, pa);
-      setdest(newtet, pb);
-      setapex(newtet, pc);
-      setoppo(newtet, bp);
-      for (j = 0; j < in->numberoftetrahedronattributes; j++) {
-        attrib = elemattribute(oldtet.tet, j);
-        setelemattribute(newtet.tet, j, attrib);
-      }
-      if (b->varvolume) {
-        volume = volumebound(oldtet.tet);
-        if (volume > 0.0) {
-          if (!b->fixedvolume && b->refine) {
-            // '-r -a' switches and a .vol file case. Enlarge the maximum
-            //   volume constraint for the new tets. Hence the new points
-            //   only spread near the original constrained tet.
-            volume *= 1.2;
-          }
-        }
-        setvolumebound(newtet.tet, volume);
-      }
-      sym(oldtet, neightet);
-      tspivot(oldtet, checksh);
-      if (neightet.tet != dummytet) {
-        bond(newtet, neightet);
-      }
-      if (checksh.sh != dummysh) {
-        tsbond(newtet, checksh);
-      }
-      if (verlist != (list *) NULL) {
-        // Collect vertices connecting to p.
-        idx = pointmark(pa);
-        if (idx >= 0) {
-          setpointmark(pa, -idx - 1);
-          verlist->append(&pa);
-        }
-        idx = pointmark(pb);
-        if (idx >= 0) {
-          setpointmark(pb, -idx - 1);
-          verlist->append(&pb);
-        }
-        idx = pointmark(pc);
-        if (idx >= 0) {
-          setpointmark(pc, -idx - 1);
-          verlist->append(&pc);
-        }
-      }
-      // Replace the tet by the newtet for checking the quality.
-      * (triface *)(* ceillist)[i] = newtet;
-    }
-  }
-  if (verlist != (list *) NULL) {
-    // Uninfect collected vertices.
-    for (i = 0; i < verlist->len(); i++) {
-      pa = * (point *)(* verlist)[i];
-      idx = pointmark(pa);
-      setpointmark(pa, -(idx + 1));
-    }
-  }
-
-  // Connect new tets of B(p). Not all faces of new tets can be connected,
-  //   e.g., if there are empty B_i(p)s.
-  for (k = 0; k < n; k++) {
-    ceillist = ceillists[k];
-    for (i = 0; i < ceillist->len(); i++) {
-      newtet = * (triface *)(* ceillist)[i];
-      newtet.ver = 0;
-      for (j = 0; j < 3; j++) {
-        fnext(newtet, newface);
-        sym(newface, neightet);
-        if (neightet.tet == dummytet) {
-          // Find the neighbor face by rotating the faces at edge ab.
-          esym(newtet, rotface);
-          pa = org(rotface);
-          pb = dest(rotface);
-          while (fnextself(rotface));
-          // Do we meet a boundary face?
-          tspivot(rotface, checksh);
-          if (checksh.sh != dummysh) {
-            // Walk through the boundary and continue to rotate faces.
-            do {
-              findedge(&checksh, pa, pb);
-              sfnextself(checksh);
-              assert((sorg(checksh) == pa) && (sdest(checksh) == pb));
-              stpivot(checksh, rotface);
-              if (infected(rotface)) {
-                // Meet an old tet of B_i(p). This side is on the hull and
-                //   will be connected to a new subface created in C(p).
-                break;
-              }
-              findedge(&rotface, pa, pb);
-              while (fnextself(rotface));
-              tspivot(rotface, checksh);
-            } while (checksh.sh != dummysh);
-          }
-          // The rotface has edge ab, but it may not have newpt.
-          if (apex(rotface) == apex(newface)) { 
-            // Bond the two tets together.
-            bond(newface, rotface);
-            // Queue (uniquely) this face if 'flipque' is given.
-            if (flipque != (queue *) NULL) {
-              enqueueflipface(newface, flipque);
-            }
-          }
-        }
-        enextself(newtet);
-      }
-    }
-  }
-
-  if (subceillists != (list **) NULL) {
-    // There are C(p)s.
-    if (splitseg != (face *) NULL) {
-      // S (ab) is split by p.
-      splitseg->shver = 0;
-      pa = sorg(*splitseg);
-      pb = sdest(*splitseg);
-      // Allcate two arrays for saving the subface rings of the two new
-      //   segments a->p and p->b.
-      apsegshs = new face[n];
-      pbsegshs = new face[n];
-    }
-
-    // For each C_k(p), do the following:
-    //   (1) Create new subfaces to fill C_k(p), insert them into B(p);
-    //   (2) Connect new subfaces to each other;
-    for (k = 0; k < n; k++) {      
-      subceillist = subceillists[k];
-
-      // Check if 'hullsize' should be updated.
-      oldsh = * (face *)(* subceillist)[0];
-      stpivot(oldsh, neightet);
-      if (neightet.tet != dummytet) {
-        sesymself(oldsh);
-        stpivot(oldsh, neightet);
-      }
-      if (neightet.tet == dummytet) {
-        // The hull size changes.
-        hullsize += (subceillist->len() - sublists[k]->len());
-      }
-
-      // (1) Create new subfaces to fill C_k(p), insert them into B(p).
-      for (i = 0; i < subceillist->len(); i++) {
-        oldsh = * (face *)(* subceillist)[i];
-        makeshellface(subfaces, &newsh);
-        setsorg(newsh, sorg(oldsh));
-        setsdest(newsh, sdest(oldsh));
-        setsapex(newsh, bp);
-        if (b->quality && varconstraint) {
-          setareabound(newsh, areabound(oldsh));
-        }
-        setshellmark(newsh, shellmark(oldsh));
-        setshelltype(newsh, shelltype(oldsh));
-        if (checkpbcs) {
-          setshellpbcgroup(newsh, shellpbcgroup(oldsh));
-        }
-        // Replace oldsh by newsh at the edge.
-        spivot(oldsh, casingout);
-        sspivot(oldsh, checkseg);
-        if (checkseg.sh != dummysh) {
-          // A segment. Insert s into the face ring, ie, s_in -> s -> s_out.
-          if (oldsh.sh != casingout.sh) {
-            // s is not bonded to itself.
-            spinsh = casingout;
-            do {
-              casingin = spinsh;
-              spivotself(spinsh);
-            } while (sapex(spinsh) != sapex(oldsh));
-            assert(casingin.sh != oldsh.sh); 
-            // Bond s_in -> s -> s_out (and dissolve s_in -> s_old -> s_out).
-            sbond1(casingin, newsh);
-            sbond1(newsh, casingout);
-          } else {
-            // Bond newsh -> newsh.
-            sbond(newsh, newsh);
-          }
-          // Bond the segment.
-          ssbond(newsh, checkseg);
-        } else {
-          // Bond s <-> s_out (and dissolve s_out -> s_old).
-          sbond(newsh, casingout);
-        }
-
-        // Insert newsh into B(p). Use the coonections of oldsh.
-        stpivot(oldsh, neightet);
-        if (neightet.tet == dummytet) {
-          sesymself(oldsh);
-          sesymself(newsh); // Keep the same orientation as oldsh.
-          stpivot(oldsh, neightet);
-        }
-        assert(infected(neightet));
-        // Set on the rotating edge.
-        findedge(&neightet, sorg(oldsh), sdest(oldsh));
-        // Choose the rotating direction (to the inside of B(p)).
-        adjustedgering(neightet, CCW);
-        rotface = neightet;
-        // Rotate face. Stop at a non-infected tet t (not in B(p)) or a
-        //   hull face f (on B(p)). Get the neighbor n of t or f.  n is
-        //   a new tet that has just been created to fill B(p).
-        do {
-          fnextself(rotface);
-          sym(rotface, neightet);
-          if (neightet.tet == dummytet) {
-            tspivot(rotface, checksh);
-            assert(checksh.sh != dummysh);
-            stpivot(checksh, newtet);
-            break;
-          } else if (!infected(neightet)) {
-            sym(neightet, newtet);
-            break;
-          }
-        } while (true);
-        assert(newtet.tet != rotface.tet);
-        // Set the rotating edge of n.
-        findedge(&newtet, sorg(oldsh), sdest(oldsh));
-        // Choose the rotating direction (to the inside of B(p)).
-        adjustedgering(newtet, CCW);
-        fnext(newtet, newface);
-        assert(apex(newface) == bp);
-        // newsh has already been oriented toward n.
-        tsbond(newface, newsh);
-        sym(newface, neightet); // 'neightet' maybe outside.
-        sesymself(newsh);
-        tsbond(neightet, newsh); // Bond them anyway.
-
-        // Replace oldsh by newsh in list.
-        * (face *)(* subceillist)[i] = newsh;
-      }
-
-      // (2) Connect new subfaces to each other.
-      for (i = 0; i < subceillist->len(); i++) {
-        // Get a face cdp.
-        newsh = * (face *)(* subceillist)[i];
-        // Get a new tet containing cdp.
-        stpivot(newsh, newtet);
-        if (newtet.tet == dummytet) {
-          sesymself(newsh);
-          stpivot(newsh, newtet);
-        }
-        for (j = 0; j < 2; j++) {
-          if (j == 0) {
-            senext(newsh, newedge); // edge dp.
-          } else {
-            senext2(newsh, newedge); // edge pc.
-            sesymself(newedge); // edge cp.
-          }
-          if (splitseg != (face *) NULL) {
-            // Don not operate on newedge if it is ap or pb.
-            if (sorg(newedge) == pa) {
-              apsegshs[k] = newedge;
-              continue;
-            } else if (sorg(newedge) == pb) {
-              pbsegshs[k] = newedge;
-              continue;
-            }
-          }
-          // There should no segment inside the cavity. Check it.
-          sspivot(newedge, checkseg);
-          assert(checkseg.sh == dummysh);
-          spivot(newedge, casingout);
-          if (casingout.sh == dummysh) {
-            rotface = newtet;
-            findedge(&rotface, sorg(newedge), sdest(newedge));
-            // Rotate newtet until meeting a new subface which contains
-            //   newedge. It must exist since newedge is not a seg.
-            adjustedgering(rotface, CCW);
-            do {
-              fnextself(rotface);
-              tspivot(rotface, checksh);
-              if (checksh.sh != dummysh) break;
-            } while (true);
-            findedge(&checksh, sorg(newedge), sdest(newedge));
-            sbond(newedge, checksh);
-          }
-        }
-      }
-      // Only do once if p is on a facet.
-      if (splitseg == (face *) NULL) break;
-    } // for (k = 0; k < n; k++)
-
-    if (splitseg != (face *) NULL) {
-      // Update a->b to be a->p.
-      apseg = *splitseg;
-      setsdest(apseg, bp);
-      // Create a new subsegment p->b.
-      makeshellface(subsegs, &pbseg);
-      setsorg(pbseg, bp);
-      setsdest(pbseg, pb);
-      // p->b gets the same mark and segment type as a->p.
-      setshellmark(pbseg, shellmark(apseg));
-      setshelltype(pbseg, shelltype(apseg));
-      if (b->quality && varconstraint) {
-        // Copy the area bound into the new subsegment.
-        setareabound(pbseg, areabound(apseg));
-      }
-      senext(apseg, checkseg);
-      // Get the old connection at b of a->b.
-      spivot(checkseg, casingout);
-      // Bond a->p and p->b together.
-      senext2(pbseg, casingin);
-      sbond(casingin, checkseg);
-      if (casingout.sh != dummysh) {
-        // There is a subsegment connect at b of p->b.
-        casingout.shver = 0;
-#ifdef SELF_CHECK
-        assert(sorg(casingout) == pb); 
-#endif
-        senext2self(casingout);
-        senext(pbseg, casingin);
-        sbond(casingin, casingout);
-      }
-
-      // Bond all new subfaces to a->p and p->b.
-      for (i = 0; i < n; i++) {
-        spinsh = apsegshs[i];
-        findedge(&spinsh, pa, bp);
-        ssbond(spinsh, apseg);
-        spinsh = pbsegshs[i];
-        findedge(&spinsh, bp, pb);
-        ssbond(spinsh, pbseg);
-      }
-      // Bond all subfaces share at a->p together.
-      for (i = 0; i < n; i++) {
-        spinsh = apsegshs[i];
-        if (i < (n - 1)) {
-          casingout = apsegshs[i + 1];
-        } else {
-          casingout = apsegshs[0];
-        }
-        sbond1(spinsh, casingout);
-      }
-      // Bond all subfaces share at p->b together.
-      for (i = 0; i < n; i++) {
-        spinsh = pbsegshs[i];
-        if (i < (n - 1)) {
-          casingout = pbsegshs[i + 1];
-        } else {
-          casingout = pbsegshs[0];
-        }
-        sbond1(spinsh, casingout);
-      }
-      delete [] apsegshs;
-      delete [] pbsegshs;
-
-      // Check for newly encroached subsegments if the flag is set.
-      if (chkencseg) {
-        // Check if a->p and p->b are encroached by other vertices.
-        checkseg4encroach(&apseg, NULL, NULL, true);
-        checkseg4encroach(&pbseg, NULL, NULL, true);
-        // Check if the adjacent segments are encroached by p.
-        tallencsegs(bp, n, ceillists);
-      }
-    } // if (splitseg != (face *) NULL) 
-
-    // Delete subfaces of old CBC_i(p)s.
-    for (k = 0; k < n; k++) {
-      for (i = 0; i < sublists[k]->len(); i++) {
-        oldsh = * (face *)(* (sublists[k]))[i];
-        shellfacedealloc(subfaces, oldsh.sh);
-      }
-      // Clear the list so that the subs will not get unmarked later in
-      //   routine releasebowatcavity() which only frees the memory.
-      sublists[k]->clear();
-      // Only do once if p is on a facet.
-      if (splitseg == (face *) NULL) break; 
-    }
-
-    // Check for newly encroached subfaces if the flag is set.
-    if (chkencsub) {
-      // Check if new subfaces of C_i(p) are encroached by other vertices.
-      for (k = 0; k < n; k++) {
-        subceillist = subceillists[k];
-        for (i = 0; i < subceillist->len(); i++) {
-          newsh = * (face *)(* subceillist)[i];
-          checksub4encroach(&newsh, NULL, true);
-        }
-        // Only do once if p is on a facet.
-        if (splitseg == (face *) NULL) break; 
-      }
-      // Check if the adjacent subfaces are encroached by p.
-      tallencsubs(bp, n, ceillists);
-    }
-  } // if (subceillists != (list **) NULL)
-
-  // Delete tets of old BC_i(p)s.
-  for (k = 0; k < n; k++) {
-    for (i = 0; i < tetlists[k]->len(); i++) {
-      oldtet = * (triface *)(* (tetlists[k]))[i];
-      tetrahedrondealloc(oldtet.tet);
-    }
-    // Clear the list so that the tets will not get unmarked later in
-    //   routine releasebowatcavity() which only frees the memory.
-    tetlists[k]->clear();
-  }
-
-  // check for bad quality tets if the flags is set.
-  if (chkbadtet) {
-    for (k = 0; k < n; k++) {
-      ceillist = ceillists[k];
-      for (i = 0; i < ceillist->len(); i++) {
-        newtet = * (triface *)(* ceillist)[i];
-        checktet4badqual(&newtet, true);
-      }
-    }
-  }
-
-  if (flipque != (queue *) NULL) {
-    // Newly created internal faces of BC(p) (excluding faces on C(p)s) are
-    //   in 'flipque'.  Some of these faces may be locally non-Delaunay due,
-    //   to the existence of non-constrained tets. check and fix them.
-    repairflipcount += flip(flipque, NULL);
-  }
-}
-
-//
-// End of mesh transformation routines
-//
-
-//
-// Begin Delaunay tetrahedralization routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// formstarpolyhedron()    Get the star ployhedron of a point 'pt'.          //
-//                                                                           //
-// The polyhedron P is formed by faces of tets having 'pt' as a vertex.  If  //
-// 'complete' is TRUE, P is the complete star of 'pt'. Otherwise, P is boun- //
-// ded by subfaces, i.e. P is only part of the star of 'pt'.                 //
-//                                                                           //
-// 'tetlist' T returns the tets, it has one of such tets on input. Moreover, //
-// if t is in T, then oppo(t) = p.  Topologically, T is the star of p;  and  //
-// the faces of T is the link of p. 'verlist' V returns the vertices of T.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::formstarpolyhedron(point pt, list* tetlist, list* verlist,
-  bool complete)
-{
-  triface starttet, neightet;
-  face checksh;
-  point ver[3];
-  int idx, i, j;
-
-  // Get a tet t containing p.
-  starttet = * (triface *)(* tetlist)[0];
-  // Let oppo(t) = p.
-  for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
-    if (oppo(starttet) == pt) break;
-  }
-  assert(starttet.loc < 4);
-  // Add t into T.
-  * (triface *)(* tetlist)[0] = starttet;
-  infect(starttet);
-  if (verlist != (list *) NULL) {
-    // Add three verts of t into V.
-    ver[0] = org(starttet);
-    ver[1] = dest(starttet);
-    ver[2] = apex(starttet);
-    for (i = 0; i < 3; i++) {
-      // Mark the vert by inversing the index of the vert.
-      idx = pointmark(ver[i]);
-      setpointmark(ver[i], -idx - 1); // -1 to distinguish the zero.
-      verlist->append(&(ver[i]));
-    }
-  }
-
-  // Find other tets by a broadth-first search.
-  for (i = 0; i < tetlist->len(); i++) {
-    starttet = * (triface *)(* tetlist)[i];
-    starttet.ver = 0;
-    for (j = 0; j < 3; j++) {
-      fnext(starttet, neightet);
-      tspivot(neightet, checksh);
-      // Should we cross a subface.
-      if ((checksh.sh == dummysh) || complete) {
-        // Get the neighbor n.
-        symself(neightet);
-        if ((neightet.tet != dummytet) && !infected(neightet)) {
-          // Let oppo(n) = p.
-          for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
-            if (oppo(neightet) == pt) break;
-          }
-          assert(neightet.loc < 4);
-          // Add n into T.
-          infect(neightet);
-          tetlist->append(&neightet);
-          if (verlist != (list *) NULL) {
-            // Add the apex vertex in n into V.
-            ver[0] = org(starttet);
-            ver[1] = dest(starttet);
-            findedge(&neightet, ver[0], ver[1]);
-            ver[2] = apex(neightet);
-            idx = pointmark(ver[2]);
-            if (idx >= 0) {
-              setpointmark(ver[2], -idx - 1);
-              verlist->append(&(ver[2]));
-            }
-          }
-        }
-      }
-      enextself(starttet);
-    }
-  }
-
-  // Uninfect tets.
-  for (i = 0; i < tetlist->len(); i++) {
-    starttet = * (triface *)(* tetlist)[i];
-    uninfect(starttet);
-  }
-  if (verlist != (list *) NULL) {
-    // Uninfect vertices.
-    for (i = 0; i < verlist->len(); i++) {
-      ver[0] = * (point *)(* verlist)[i];
-      idx = pointmark(ver[0]);
-      setpointmark(ver[0], -(idx + 1));
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// unifypoint()    Unify two distinct points if they're very close.          //
-//                                                                           //
-// This function is used for dealing with inputs from CAD tools.  Two points //
-// p and q are unified if: dist(p, q) / longest < eps.  Where dist() is the  //
-// Euclidean distance between p and q, longest is the maximum edge size of   //
-// the input point set, eps is the tolerrence specified by user, default is  //
-// 1e-6, it can be adjusted by '-T' switch.                                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::unifypoint(point testpt, triface *starttet, enum locateresult
-  loc, REAL eps)
-{
-  triface symtet, spintet;
-  point checkpt, tapex;
-  REAL tol;
-  bool merged;
-  int hitbdry;
-  int i;
-
-  merged = false;
-  tol = longest * eps;
-  if ((loc == OUTSIDE) || (loc == INTETRAHEDRON) || (loc == ONFACE)) {
-    // Check p is close to the four corners of the tet.
-    for (i = 0; i < 4; i++) {
-      checkpt = (point) starttet->tet[4 + i];
-      if (distance(testpt, checkpt) < tol) {
-        merged = true; // Found a merge point p'.
-        break;
-      }
-    }
-    if (!merged && (loc == ONFACE)) {
-      // Check the opposite point of the neighbor tet if it exists.
-      sym(*starttet, symtet);
-      if (symtet.tet != dummytet) {
-        checkpt = oppo(symtet);
-        if (distance(testpt, checkpt) < tol) {
-          merged = true; // Found a merge point p'.
-        }
-      }
-    }
-  } else if (loc == ONEDGE) {
-    // Check two endpoints of the edge.
-    checkpt = org(*starttet);
-    if (distance(testpt, checkpt) < tol) {
-      merged = true; // Found a merge point p'.
-    }
-    if (!merged) {
-      checkpt = dest(*starttet);
-      if (distance(testpt, checkpt) < tol) {
-        merged = true; // Found a merge point p'.
-      }
-    }
-    if (!merged) {
-      // Check apexes of the faces having the edge.
-      spintet = *starttet;
-      tapex = apex(*starttet);
-      hitbdry = 0;
-      do {
-        checkpt = apex(spintet);
-        if (distance(testpt, checkpt) < tol) {
-          merged = true; // Found a merge point p'.
-          break;
-        }
-        if (!fnextself(spintet)) {
-          hitbdry++;
-          if (hitbdry < 2) {
-            esym(*starttet, spintet);
-            if (!fnextself(spintet)) {
-              hitbdry++;
-            }
-          }
-        }
-      } while ((apex(spintet) != tapex) && (hitbdry < 2));
-    }
-  }
-  if (merged) {
-    if (b->object != tetgenbehavior::STL) {
-      if (!b->quiet) {
-        printf("Warning:  Point %d is unified to point %d.\n",
-               pointmark(testpt), pointmark(checkpt));
-      }
-      // Count the number of duplicated points.
-      dupverts++;
-    }
-    // Remember it is a duplicated point.
-    setpointtype(testpt, DUPLICATEDVERTEX);
-    // Set a pointer to the point it duplicates.
-    setpoint2ppt(testpt, checkpt);
-  }
-  return merged;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// incrflipdelaunay()   Construct a delaunay tetrahedrization from a set of  //
-//                      3D points by the incremental flip algorithm.         //
-//                                                                           //
-// The incremental flip algorithm (by Edelsbrunner and Shah) can be describ- //
-// ed as follows:                                                            //
-//                                                                           //
-//   S be a set of points in 3D, Let 4 <= i <= n and assume that the         //
-//   Delaunay tetrahedralization of the first i-1 points in S is already     //
-//   constructed; call it D(i-1). Add the i-th point p_i (belong to S) to    //
-//   D(i-1), and restore Delaunayhood by flipping; this result in D(i).      //
-//   Repeat this procedure until i = n.                                      //
-//                                                                           //
-// This strategy always leads to the Delaunay triangulation of a point set.  //
-// The return value is the number of convex hull faces of D.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::incrflipdelaunay(triface* oldtet, point* insertarray, 
-  long arraysize, bool jump, bool merge, REAL eps, queue* flipque)
-{
-  triface newtet, searchtet;
-  point swappt, lastpt;
-  enum locateresult loc;
-  REAL det, n[3];
-  REAL attrib, volume;
-  int i, j;
-  clock_t loc_start, loc_end;
-
-  if (b->verbose > 0) {
-    printf("  Creating initial tetrahedralization.\n");
-  }
-
-  // The initial tetrahedralization T only has one tet formed by 4 affinely
-  //   linear independent vertices of the point set V = 'insertarray'. The
-  //   first point a = insertarray[0].
- 
-  // Get the second point b, that is not identical or very close to a.
-  for (i = 1; i < arraysize; i++) {
-    det = distance(insertarray[0], insertarray[i]);
-    if (det > (longest * eps)) break;
-  }
-  if (i == arraysize) {
-    printf("\nAll points seem to be identical.\n");
-    return;
-  } else {
-    // Swap to move b from index i to index 1.
-    swappt = insertarray[i];
-    insertarray[i] = insertarray[1];
-    insertarray[1] = swappt;  
-  }
-  // Get the third point c, that is not collinear with a and b.
-  for (i++; i < arraysize; i++) {
-    if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps)) 
-      break;
-  }
-  if (i == arraysize) {
-    printf("\nAll points seem to be collinear.\n");
-    return;
-  } else {
-    // Swap to move c from index i to index 2.
-    swappt = insertarray[i];
-    insertarray[i] = insertarray[2];
-    insertarray[2] = swappt;
-  }
-  // Get the fourth point d, that is not coplanar with a, b, and c.
-  for (i++; i < arraysize; i++) {
-    det = orient3d(insertarray[0], insertarray[1], insertarray[2],
-                   insertarray[i]);
-    if (det == 0.0) continue;
-    if (!iscoplanar(insertarray[0], insertarray[1], insertarray[2],
-                    insertarray[i], det, eps)) break;
-  }
-  if (i == arraysize) {
-    // It's a 2D problem.
-    in->mesh_dim = 2;
-    // All points are coplanar.
-    if (b->plc) {
-      // Create an abovepoint. Maybe a surface triangulation can be formed.
-      facenormal(insertarray[0], insertarray[1], insertarray[2], n, &det);
-      if (det != 0.0) for (j = 0; j < 3; j++) n[j] /= det;
-      // Take the average edge length of the bounding box.
-      det = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
-      // Temporarily create a point. It will be removed by jettison();
-      makepoint(&lastpt);
-      for (j = 0; j < 3; j++) lastpt[j] = insertarray[0][j] + det * n[j];
-      abovepoint = lastpt;
-      det = orient3d(insertarray[0], insertarray[1], insertarray[2], lastpt);
-      // The index of the next inserting point is 3.
-      i = 3;
-    } else {
-      printf("\nAll points seem to be coplanar.\n");
-      return;
-    }
-  } else {
-    // Swap to move d from index i to index 3.
-    swappt = insertarray[i];
-    insertarray[i] = insertarray[3];
-    insertarray[3] = swappt;
-    lastpt = insertarray[3];
-    // The index of the next inserting point is 4.
-    i = 4;
-  }
-  
-  // Create the initial tet.
-  maketetrahedron(&newtet);
-  if (det > 0.0) {
-    // For keeping the positive orientation.
-    swappt = insertarray[0];
-    insertarray[0] = insertarray[1];
-    insertarray[1] = swappt;
-  }
-  if (b->verbose > 2) {
-    printf("  Create the first tet (%d, %d, %d, %d).\n",
-           pointmark(insertarray[0]), pointmark(insertarray[1]),
-           pointmark(insertarray[2]), pointmark(lastpt));
-  }
-  setorg(newtet, insertarray[0]);
-  setdest(newtet, insertarray[1]);
-  setapex(newtet, insertarray[2]);
-  setoppo(newtet, lastpt);
-  if (oldtet != (triface *) NULL) {
-    for (j = 0; j < in->numberoftetrahedronattributes; j++) {
-      attrib = elemattribute(oldtet->tet, j);
-      setelemattribute(newtet.tet, j, attrib);
-    }
-    if (b->varvolume) {
-      volume = volumebound(oldtet->tet);
-      setvolumebound(newtet.tet, volume);
-    }
-  }
-  // Set vertex type be FREEVOLVERTEX if it has no type yet.
-  if (pointtype(insertarray[0]) == UNUSEDVERTEX) {
-    setpointtype(insertarray[0], FREEVOLVERTEX);
-  }
-  if (pointtype(insertarray[1]) == UNUSEDVERTEX) {
-    setpointtype(insertarray[1], FREEVOLVERTEX);
-  }
-  if (pointtype(insertarray[2]) == UNUSEDVERTEX) {
-    setpointtype(insertarray[2], FREEVOLVERTEX);
-  }
-  if (pointtype(lastpt) == UNUSEDVERTEX) {
-    setpointtype(lastpt, FREEVOLVERTEX);
-  }
-  // Bond to 'dummytet' for point location.
-  dummytet[0] = encode(newtet);
-  if (b->verbose > 3) {
-    printf("    Creating tetra ");
-    printtet(&newtet);
-  }
-  // At init, all faces of this tet are hull faces.
-  hullsize = 4;
-
-  if (b->verbose > 0) {
-    printf("  Incrementally inserting points.\n");
-  }
-
-  flip23s = flip32s = flip22s = flip44s = 0;
-  searchtet.tet = (tetrahedron *) NULL;
-
-  // Insert the rest of points, one by one.
-  for (; i < arraysize; i++) {
-    // Locate p_i in T.
-#ifdef SELF_CHECK
-    loc_start = clock();
-#endif
-    if (jump) {
-      loc = locate(insertarray[i], &searchtet);
-    } else {
-      loc = preciselocate(insertarray[i], &searchtet, tetrahedrons->items);
-    }
-#ifdef SELF_CHECK
-    loc_end = clock();
-    tloctime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
-#endif
-    // Keep current search state for next searching.
-    recenttet = searchtet;
-    if (loc == ONVERTEX) {
-      if (b->object != tetgenbehavior::STL) {
-        if (!b->quiet) {
-          printf("Warning:  Point %d is identical with point %d.\n",
-                 pointmark(insertarray[i]), pointmark(org(searchtet)));
-        }
-      }
-      // Count the number of duplicated points.
-      dupverts++;
-      // Remember it is a duplicated point.
-      setpointtype(insertarray[i], DUPLICATEDVERTEX);
-      if (b->plc || b->refine) {
-        // Set a pointer to the point it duplicates.
-        setpoint2ppt(insertarray[i], org(searchtet));
-      }
-      continue; // p_i is not inserted.
-    }
-    if (merge) {
-      // Unify p_i if it is too close to a point of T.
-      if (unifypoint(insertarray[i], &searchtet, loc, eps)) {
-        continue; // p_i is not inserted.
-      }
-    }
-    // Insert p_i in T.
-    if (loc != OUTSIDE) {
-      if (b->verbose > 1) {
-        printf("  Insert point %d in tetrahedralization.\n",
-               pointmark(insertarray[i]));
-      }
-      if (loc == INTETRAHEDRON) {
-        splittetrahedron(insertarray[i], &searchtet, flipque);
-      } else if (loc == ONFACE) {
-        splittetface(insertarray[i], &searchtet, flipque);
-      } else if (loc == ONEDGE) {
-        splittetedge(insertarray[i], &searchtet, flipque);
-      }
-    } else {
-      if (b->verbose > 1) {
-        printf("  Insert point %d on convex hull.\n",
-               pointmark(insertarray[i]));
-      }
-      inserthullsite(insertarray[i], &searchtet, flipque);
-    }
-    if (pointtype(insertarray[i]) == UNUSEDVERTEX) {
-      // p_i becomes a (volume) vertex of T.
-      setpointtype(insertarray[i], FREEVOLVERTEX);
-    }
-#ifdef SELF_CHECK
-    loc_start = clock();
-#endif
-    if (!b->noflip) {
-      // Recover Delaunayness of T by flipping.
-      flip(flipque, NULL); 
-    } else {
-      lawson(NULL, flipque);
-      // T remains regular.
-      // flipque->clear();
-    }
-#ifdef SELF_CHECK
-    loc_end = clock();
-    tfliptime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
-#endif
-  }
-
-  if (b->verbose > 0) {
-    printf("  %ld Flips (T23 %ld, T32 %ld, T22 %ld, T44 %ld)\n",
-      flip23s+flip32s+flip22s+flip44s, flip23s, flip32s, flip22s, flip44s);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// delaunizevertices()    Form a Delaunay tetrahedralization.                //
-//                                                                           //
-// Given a point set V (saved in 'points').  The Delaunay tetrahedralization //
-// D of V is created by incrementally inserting vertices. Returns the number //
-// of triangular faces bounding the convex hull of D.                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-long tetgenmesh::delaunizevertices()
-{
-  queue *flipque;
-  point *insertarray;
-  long arraysize;
-  int i, j;
-
-  if (!b->quiet) {
-    if (!b->noflip) {
-      printf("Constructing Delaunay tetrahedralization.\n");
-    } else {
-      printf("Constructing regular tetrahedralization.\n");
-    }
-  }
-
-  flipque = new queue(sizeof(badface));
-  // Prepare the array of points for inserting.
-  arraysize = points->items;
-  insertarray = new point[arraysize];  
-  points->traversalinit();
-
-  // Randomize the point order.
-  // randomseed = b->srandseed;
-  for (i = 0; i < arraysize; i++) {
-    j = (int) randomnation(i + 1); // 0 <= j <= i;
-    insertarray[i] = insertarray[j];
-    insertarray[j] = pointtraverse();
-  }
-
-  // Use lawson flip.
-  b->noflip = 1;
-
-  // Form the DT by incremental flip Delaunay algorithm.
-  incrflipdelaunay(NULL, insertarray, arraysize, true, b->plc, b->epsilon,
-                   flipque);
-
-  b->noflip = 0;
-
-  delete [] insertarray;
-  delete flipque;
-  return hullsize;
-}
-
-//
-// End Delaunay tetrahedralization routines
-//
-
-//
-// Begin of surface triangulation routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// formstarpolygon()    Form the star polygon of a point in facet.           //
-//                                                                           //
-// The polygon P is formed by all coplanar subfaces having 'pt' as a vertex. //
-// P is bounded by segments, e.g, if no segments, P is the full star of pt.  //
-//                                                                           //
-// 'trilist' T returns the subfaces, it has one of such subfaces on input.   //
-// In addition, if f is in T, then sapex(f) = p. 'vertlist' V are verts of P.//
-// Topologically, T is the star of p; V and the edges of T are the link of p.//
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::formstarpolygon(point pt, list* trilist, list* vertlist)
-{
-  face steinsh, lnextsh, rnextsh;
-  face checkseg;
-  point pa, pb, pc, pd;
-  int i;
-
-  // Get a subface f containing p.
-  steinsh = * (face *)(* trilist)[0];
-  steinsh.shver = 0; // CCW
-  // Let sapex(f) be p.
-  for (i = 0; i < 3; i++) {
-    if (sapex(steinsh) == pt) break;
-    senextself(steinsh);
-  }
-  assert(i < 3);
-  // Add the edge f into list.
-  * (face *)(* trilist)[0] = steinsh;
-  pa = sorg(steinsh);
-  pb = sdest(steinsh);
-  if (vertlist != (list *) NULL) {
-    // Add two verts a, b into V,
-    vertlist->append(&pa);
-    vertlist->append(&pb);
-  }
-
-  // Rotate edge pa to the left (CW) until meet pb or a segment.
-  lnextsh = steinsh;
-  pc = pa;
-  do {
-    senext2self(lnextsh);
-    assert(sorg(lnextsh) == pt);
-    sspivot(lnextsh, checkseg);
-    if (checkseg.sh != dummysh) break; // Do not cross a segment.
-    // Get neighbor subface n (must exist).
-    spivotself(lnextsh);
-    if (lnextsh.sh == dummysh) break; // It's a hull edge.
-    // Go to the edge ca opposite to p.
-    if (sdest(lnextsh) != pt) sesymself(lnextsh);
-    assert(sdest(lnextsh) == pt);
-    senext2self(lnextsh);
-    // Add n (at edge ca) to T.
-    trilist->append(&lnextsh);
-    // Add edge ca to E.
-    pc = sorg(lnextsh);
-    if (pc == pb) break; // Rotate back.
-    if (vertlist != (list *) NULL) {
-      // Add vert c into V.
-      vertlist->append(&pc);
-    }
-  } while (true);
-
-  if (pc != pb) {
-    // Rotate edge bp to the right (CCW) until meet a segment.
-    rnextsh = steinsh;
-    do {
-      senextself(rnextsh);
-      assert(sdest(rnextsh) == pt);
-      sspivot(rnextsh, checkseg);
-      if (checkseg.sh != dummysh) break; // Do not cross a segment.
-      // Get neighbor subface n (must exist).
-      spivotself(rnextsh);
-      if (rnextsh.sh == dummysh) break; // It's a hull edge.
-      // Go to the edge bd opposite to p.
-      if (sorg(rnextsh) != pt) sesymself(rnextsh);
-      assert(sorg(rnextsh) == pt);
-      senextself(rnextsh);
-      // Add n (at edge bd) to T.
-      trilist->append(&rnextsh);
-      // Add edge bd to E.
-      pd = sdest(rnextsh);
-      if (pd == pa) break; // Rotate back.
-      if (vertlist != (list *) NULL) {
-        // Add vert d into V.
-        vertlist->append(&pd);
-      }
-    } while (true);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// About the 'abovepoint'                                                    //
-//                                                                           //
-// The 'abovepoint' of a facet is a point which is exactly non-coplanar with //
-// the plane containing that facet.  With such an point, the 3D predicates:  //
-// orient3d(), and insphere() can be used to substitute the corresponding 2D //
-// siblings, e.g. orient2d(), and incircle().  Its location is not critical, //
-// but floating-point accuracy is improved if it is nicely placed over the   //
-// facet, not too close or too far away.                                     //
-//                                                                           //
-// We take the convention that the abovepoint of a facet always lies above   //
-// the facet. By this convention, given three points a, b, and c in a facet, //
-// we say c has the counterclockwise order with ab is corresponding to say   //
-// that c is below the plane abp, where p is the lift point.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getfacetabovepoint()    Get a point above a plane pass through a facet.   //
-//                                                                           //
-// The calculcated point is saved in 'facetabovepointarray'. The 'abovepoint'//
-// is set on return.                                                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::getfacetabovepoint(face* facetsh)
-{
-  list *verlist, *trilist, *tetlist;
-  triface adjtet;
-  face symsh;
-  point p1, p2, p3, pa;
-  enum locateresult loc;
-  REAL smallcos, cosa;
-  REAL largevol, volume;
-  REAL v1[3], v2[3], len;
-  int smallidx, largeidx;
-  int shmark;
-  int i, j;
-
-  abovecount++;
-  // Initialize working lists.
-  verlist = new list(sizeof(point *), NULL);
-  trilist = new list(sizeof(face), NULL);
-  tetlist = new list(sizeof(triface), NULL);
-
-  // Get three pivotal points p1, p2, and p3 in the facet as a base triangle
-  //   which is non-trivil and has good base angle (close to 90 degree).
-
-  // p1 is chosen as the one which has the smallest index in pa, pb, pc.
-  p1 = sorg(*facetsh);
-  pa = sdest(*facetsh);
-  if (pointmark(pa) < pointmark(p1)) p1 = pa;
-  pa = sapex(*facetsh);
-  if (pointmark(pa) < pointmark(p1)) p1 = pa;
-  // Form the star polygon of p1.
-  trilist->append(facetsh);
-  formstarpolygon(p1, trilist, verlist);
-
-  // Get the second pivotal point p2.
-  p2 = * (point *)(* verlist)[0];
-  // Get vector v1 = p1->p2.
-  for (i = 0; i < 3; i++) v1[i] = p2[i] - p1[i];
-  len = sqrt(dot(v1, v1));
-  assert(len > 0.0);  // p2 != p1.
-  for (i = 0; i < 3; i++) v1[i] /= len;
-
-  // Get the third pivotal point p3. p3 is chosen as the one in 'verlist'
-  //   which forms an angle with v1 closer to 90 degree than others do.
-  smallcos = 1.0; // The cosine value of 0 degree.
-  smallidx = 1;   // Default value.
-  for (i = 1; i < verlist->len(); i++) {
-    p3 = * (point *)(* verlist)[i];
-    for (j = 0; j < 3; j++) v2[j] = p3[j] - p1[j];
-    len = sqrt(dot(v2, v2));
-    if (len > 0.0) { // v2 is not too small.
-      cosa = fabs(dot(v1, v2)) / len;
-      if (cosa < smallcos) {
-        smallidx = i;
-        smallcos = cosa;
-      }
-    }
-  }
-  assert(smallcos < 1.0); // p1->p3 != p1->p2.
-  p3 = * (point *)(* verlist)[smallidx];
-  verlist->clear();
-
-  if (tetrahedrons->items > 0l) {
-    // Get a tet having p1 as a vertex.
-    stpivot(*facetsh, adjtet);
-    if (adjtet.tet == dummytet) {
-      sesym(*facetsh, symsh);
-      stpivot(symsh, adjtet);
-    }
-    if (adjtet.tet == dummytet) {
-      decode(point2tet(p1), adjtet);
-      if (isdead(&adjtet)) {
-        adjtet.tet = dummytet;
-      } else {
-        if (!findorg(&adjtet, p1)) {
-          adjtet.tet = dummytet;
-        }
-      }
-    }
-    if (adjtet.tet == dummytet) {
-      loc = locate(p1, &adjtet);
-      if (loc == ONVERTEX) {
-        setpoint2tet(p1, encode(adjtet));
-      } else {
-        adjtet.tet = dummytet;
-      }
-    }
-    if (adjtet.tet != dummytet) {
-      // Get the star polyhedron of p1.
-      tetlist->append(&adjtet);
-      formstarpolyhedron(p1, tetlist, verlist, false);
-    }
-  }
-
-  // Get the abovepoint in 'verlist'. It is the one form the largest valid
-  //   volumw with the base triangle over other points in 'verlist.
-  largevol = 0.0;
-  largeidx = 0;
-  for (i = 0; i < verlist->len(); i++) {
-    pa = * (point *)(* verlist)[i];
-    volume = orient3d(p1, p2, p3, pa);
-    if (!iscoplanar(p1, p2, p3, pa, volume, b->epsilon * 1e+2)) {
-      if (fabs(volume) > largevol) {
-        largevol = fabs(volume);
-        largeidx = i;
-      }
-    }
-  }
-
-  // Do we have the abovepoint?
-  if (largevol > 0.0) {
-    abovepoint = * (point *)(* verlist)[largeidx];
-    if (b->verbose > 1) {
-      printf("    Chosen abovepoint %d for facet %d.\n", pointmark(abovepoint),
-             shellmark(*facetsh));
-    }
-  } else {
-    // Calculate an abovepoint for this facet.
-    facenormal(p1, p2, p3, v1, &len);
-    if (len != 0.0) for (i = 0; i < 3; i++) v1[i] /= len;
-    // Take the average edge length of the bounding box.
-    len = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
-    // Temporarily create a point. It will be removed by jettison();
-    makepoint(&abovepoint);
-    setpointtype(abovepoint, UNUSEDVERTEX);
-    unuverts++;
-    for (i = 0; i < 3; i++) abovepoint[i] = p1[i] + len * v1[i];
-    if (b->verbose > 1) {
-      printf("    Calculated abovepoint %d for facet %d.\n",
-             pointmark(abovepoint), shellmark(*facetsh));
-    }
-  }
-  // Save the abovepoint in 'facetabovepointarray'.
-  shmark = shellmark(*facetsh);
-  facetabovepointarray[shmark] = abovepoint;
-  
-  delete trilist;
-  delete tetlist;
-  delete verlist;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// collectcavsubs()    Collect non-locally Delaunay subfaces wrt a point.    //
-//                                                                           //
-// 'cavsublist' returns the list of subfaces. On input, it conatins at least //
-// one subface.                                                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::collectcavsubs(point newpoint, list* cavsublist)
-{
-  face startsub, neighsub;
-  face checkseg;
-  point pa, pb, pc;
-  REAL sign, ori;
-  int i, j;
-
-  // First infect subfaces in 'cavsublist'.
-  for (i = 0; i < cavsublist->len(); i++) {
-    startsub = * (face *)(* cavsublist)[i];
-    sinfect(startsub);
-  }
-  // Find the other subfaces by a broadth-first searching.
-  for (i = 0; i < cavsublist->len(); i++) {
-    startsub = * (face *)(* cavsublist)[i];
-    for (j = 0; j < 3; j++) {
-      sspivot(startsub, checkseg);
-      // Is there a segment?
-      if (checkseg.sh == dummysh) {
-        // No segment. Get the neighbor.
-        spivot(startsub, neighsub);
-        if (!sinfected(neighsub)) {
-          pa = sorg(neighsub);
-          pb = sdest(neighsub);
-          pc = sapex(neighsub);
-          sign = insphere(pa, pb, pc, abovepoint, newpoint);
-          ori = orient3d(pa, pb, pc, abovepoint);
-          if (sign != 0.0) {
-            // Correct the sign.
-            sign = ori > 0.0 ? sign : -sign;
-          }
-          if (sign > 0.0) {
-            // neighsub is encroached by newpoint.
-            sinfect(neighsub);
-            cavsublist->append(&neighsub);
-          }
-        }
-      }
-      senextself(startsub);
-    }
-  }
-  // Having found all subfaces, uninfect them before return.
-  for (i = 0; i < cavsublist->len(); i++) {
-    startsub = * (face *)(* cavsublist)[i];
-    suninfect(startsub);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// collectvisiblesubs()    Collect convex hull edges which are visible from  //
-//                         the inserting point. Construct new subfaces from  //
-//                         these edges and the point.                        //
-//                                                                           //
-// Let T be the current Delaunay triangulation (of vertices of a facet F).   //
-// 'shmark', the index of F in 'in->facetlist' (starts from 1);  'inspoint'  //
-// lies outside of T; 'horiz' is a hull edge of T which is visible by it.    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::collectvisiblesubs(int shmark, point inspoint, face* horiz,
-  queue* flipqueue)
-{
-  face newsh, hullsh;
-  face rightsh, leftsh, spinedge;
-  point horg, hdest;
-  bool aboveflag;
-  REAL ori, sign;
-
-  // Get the sign of abovepoint (so we can assume it is above the plane).  
-  adjustedgering(*horiz, CCW);
-  horg = sorg(*horiz);
-  hdest = sdest(*horiz);
-  ori = orient3d(horg, hdest, sapex(*horiz), abovepoint);
-  sign = ori > 0.0 ? -1 : 1;
-
-  // Create a new subface above 'horiz'.
-  makeshellface(subfaces, &newsh);
-  setsorg(newsh, hdest);
-  setsdest(newsh, horg);
-  setsapex(newsh, inspoint);
-  setshellmark(newsh, shmark);
-  if (b->quality && varconstraint) {
-    setareabound(newsh, areabound(*horiz));
-  }
-  if (checkpbcs) {
-    setshellpbcgroup(newsh, shellpbcgroup(*horiz));
-  }
-  // Make the connection.
-  sbond(newsh, *horiz);
-  // 'horiz' becomes interior edge.
-  enqueueflipedge(*horiz, flipqueue);
-  
-  // Finish the hull edges at the right side of the newsh.
-  hullsh = *horiz;
-  while (1) {
-    senext(newsh, rightsh);
-    // Get the right hull edge of 'horiz' by spinning inside edges around
-    //   'horg' until reaching the 'dummysh'.
-    spinedge = hullsh;
-    do {
-      hullsh = spinedge;
-      senext2self(hullsh);
-      spivot(hullsh, spinedge);
-      if (spinedge.sh == dummysh) break;
-      if (sorg(spinedge) != horg) sesymself(spinedge);
-      assert(sorg(spinedge) == horg);
-    } while (true);
-    horg = sorg(hullsh);
-    // Test whether 'inspoint' is visible by 'hullsh'.
-    ori = orient3d(horg, sdest(hullsh), abovepoint, inspoint);
-    ori *= sign;
-    aboveflag = ori < 0.0;
-    if (aboveflag) {
-      // It's visible.
-      makeshellface(subfaces, &newsh);
-      setsorg(newsh, sdest(hullsh));
-      setsdest(newsh, horg);
-      setsapex(newsh, inspoint);
-      setshellmark(newsh, shmark);
-      if (b->quality && varconstraint) {
-        setareabound(newsh, areabound(hullsh));
-      }
-      if (checkpbcs) {
-        setshellpbcgroup(newsh, shellpbcgroup(hullsh));
-      }
-      // Make the connection.
-      sbond(newsh, hullsh);
-      senext2(newsh, leftsh);
-      sbond(leftsh, rightsh);
-      // 'hullsh' becomes interior edge.
-      enqueueflipedge(hullsh, flipqueue); 
-    } else {
-      // 'rightsh' is a new hull edge.
-      dummysh[0] = sencode(rightsh);
-      break;
-    }
-  }
-
-  // Finish the hull edges at the left side of the newsh.
-  hullsh = *horiz;
-  spivot(*horiz, newsh);
-  while (1) {
-    senext2(newsh, leftsh);
-    // Get the left hull edge of 'horiz' by spinning edges around 'hdest'.
-    spinedge = hullsh;
-    do {
-      hullsh = spinedge;
-      senextself(hullsh);
-      spivot(hullsh, spinedge);
-      if (spinedge.sh == dummysh) break;
-      if (sdest(spinedge) != hdest) sesymself(spinedge);
-      assert(sdest(spinedge) == hdest);
-    } while (true);
-    // Update 'hdest'.
-    hdest = sdest(hullsh);
-    // Test whether 'inspoint' is visible from 'hullsh'.
-    ori = orient3d(sorg(hullsh), hdest, abovepoint, inspoint);
-    ori *= sign;
-    aboveflag = ori < 0.0;
-    if (aboveflag) {
-      // It's a visible hull edge.
-      makeshellface(subfaces, &newsh);
-      setsorg(newsh, hdest);
-      setsdest(newsh, sorg(hullsh));
-      setsapex(newsh, inspoint);
-      setshellmark(newsh, shmark);
-      if (b->quality && varconstraint) {
-        setareabound(newsh, areabound(hullsh));
-      }
-      if (checkpbcs) {
-        setshellpbcgroup(newsh, shellpbcgroup(hullsh));
-      }
-      // Make the connection.
-      sbond(newsh, hullsh);
-      senext(newsh, rightsh);
-      sbond(rightsh, leftsh);
-      // 'horiz' becomes interior edge.
-      enqueueflipedge(hullsh, flipqueue); 
-    } else {
-      // 'leftsh' is a new hull edge.
-      dummysh[0] = sencode(leftsh);
-      break;
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// incrflipdelaunaysub()    Create a DT from a 3D coplanar point set using   //
-//                          the incremental flip algorithm.                  //
-//                                                                           //
-// Let T be the current Delaunay triangulation (of vertices of a facet F).   //
-// 'shmark', the index of F in 'in->facetlist' (starts from 1).              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::incrflipdelaunaysub(int shmark, REAL eps, list* ptlist,
-  int holes, REAL* holelist, queue* flipque)
-{
-  face newsh, startsh;
-  point *insertarray;
-  point swappt;
-  pbcdata *pd;
-  enum locateresult loc;
-  REAL det, area;
-  bool aboveflag;
-  int arraysize;
-  int epscount;
-  int fmarker;
-  int idx, i, j, k;  
-
-  // Get the point array (saved in 'ptlist').
-  insertarray = (point *) ptlist->base;
-  arraysize = ptlist->len();
-  if (arraysize < 3) return;
-
-  // Do calculation of 'abovepoint' if number of points > 3.
-  aboveflag = (arraysize > 3);
-
-  // The initial triangulation T only has one triangle formed by 3 not
-  //   cillinear points of the set V = 'insertarray'. The first point:
-  //   a = insertarray[0].
-
-  epscount = 0;
-  while (true) {
-  for (i = 1; i < arraysize; i++) {
-    det = distance(insertarray[0], insertarray[i]);
-    if (det > (longest * eps)) break;
-  }
-  if (i < arraysize) {
-    // Swap to move b from index i to index 1.
-    swappt = insertarray[i];
-    insertarray[i] = insertarray[1];
-    insertarray[1] = swappt;  
-  }
-  // Get the third point c, that is not collinear with a and b.
-  for (i++; i < arraysize; i++) {
-    if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
-      break;
-  }
-  if (i < arraysize) {
-    // Swap to move c from index i to index 2.
-    swappt = insertarray[i];
-    insertarray[i] = insertarray[2];
-    insertarray[2] = swappt;
-    i = 3; // The next inserting point.
-  } else {
-    // The set of vertices is not good (or nearly degenerate).  However,
-    //   a trivial triangulation can be formed (using 3 vertices). It may
-    //   be corrected (or deleted) by mergefacet().
-    if ((eps == 0.0) || (epscount > 16)) {
-      printf("Error:  Invalid PLC.\n");
-      printf("  Facet (%d, %d, %d", pointmark(insertarray[0]),
-             pointmark(insertarray[1]), pointmark(insertarray[2]));
-      if (ptlist->len() > 3) {
-        printf(", ...");
-      }
-      printf(") (%d) is not a valid polygon.\n", shmark);
-      terminatetetgen(1);
-    }
-    // Decrease the eps, and continue to try.
-    eps *= 1e-2;
-    epscount++;
-    continue;
-  }
-  break;
-  } // while (true);
-
-  // Create the initial triangle.
-  makeshellface(subfaces, &newsh);
-  setsorg(newsh, insertarray[0]);
-  setsdest(newsh, insertarray[1]);
-  setsapex(newsh, insertarray[2]);
-  // Remeber the facet it belongs to.
-  setshellmark(newsh, shmark);
-  // Set vertex type be FREESUBVERTEX if it has no type yet.
-  if (pointtype(insertarray[0]) == FREEVOLVERTEX) {
-    setpointtype(insertarray[0], FREESUBVERTEX);
-  }
-  if (pointtype(insertarray[1]) == FREEVOLVERTEX) {
-    setpointtype(insertarray[1], FREESUBVERTEX);
-  }
-  if (pointtype(insertarray[2]) == FREEVOLVERTEX) {
-    setpointtype(insertarray[2], FREESUBVERTEX);
-  }
-  // Let 'dummysh' point to it (for point location).
-  dummysh[0] = sencode(newsh);
-
-  // Are there area constraints?
-  if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
-    idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker.
-    for (k = 0; k < in->numberoffacetconstraints; k++) {
-      fmarker = (int) in->facetconstraintlist[k * 2];
-      if (fmarker == idx) {
-        area = in->facetconstraintlist[k * 2 + 1];
-        setareabound(newsh, area);
-        break;
-      }
-    }
-  }
-
-  // Are there pbc conditions?
-  if (checkpbcs) {
-    idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker.
-    for (k = 0; k < in->numberofpbcgroups; k++) {
-      pd = &subpbcgrouptable[k];
-      for (j = 0; j < 2; j++) {
-        if (pd->fmark[j] == idx) {
-          setshellpbcgroup(newsh, k);
-          pd->ss[j] = newsh;
-        }
-      }
-    }
-  }
-
-  if (aboveflag) {
-    // Compute the 'abovepoint' for orient3d().
-    abovepoint = facetabovepointarray[shmark];
-    if (abovepoint == (point) NULL) {
-      getfacetabovepoint(&newsh);
-    }
-  }
-
-  if (holes > 0) {
-    // Project hole points onto the plane containing the facet.
-    REAL prj[3];
-    for (k = 0; k < holes; k++) {
-      projpt2face(&(holelist[k * 3]), insertarray[0], insertarray[1],
-                  insertarray[2], prj);
-      for (j = 0; j < 3; j++) holelist[k * 3 + j] = prj[j];
-    }
-  }
-
-  // Incrementally insert the rest of points into T.
-  for (; i < arraysize; i++) {
-    // Insert p_i.
-    startsh.sh = dummysh;
-    loc = locatesub(insertarray[i], &startsh, 0, 0.0);
-    if (loc == ONFACE) {
-      splitsubface(insertarray[i], &startsh, flipque);
-    } else if (loc == ONEDGE) {
-      splitsubedge(insertarray[i], &startsh, flipque);
-    } else if (loc == OUTSIDE) {
-      collectvisiblesubs(shmark, insertarray[i], &startsh, flipque);
-    } else if (loc == ONVERTEX) {
-      // !should not happen!
-    }
-    // Set p_i's type FREESUBVERTEX if it has no type yet.
-    if (pointtype(insertarray[i]) == FREEVOLVERTEX) {
-      setpointtype(insertarray[i], FREESUBVERTEX);
-    }
-    flipsub(flipque);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// finddirectionsub()    Find the first subface in a facet on the path from  //
-//                       one point to another.                               //
-//                                                                           //
-// Finds the subface in the facet that intersects a line segment drawn from  //
-// the origin of `searchsh' to the point `tend', and returns the result in   //
-// `searchsh'.  The origin of `searchsh' does not change,  even though the   //
-// subface returned may differ from the one passed in.                       //
-//                                                                           //
-// The return value notes whether the destination or apex of the found face  //
-// is collinear with the two points in question.                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::finddirectionresult tetgenmesh::finddirectionsub(
-  face* searchsh, point tend)
-{
-  face checksh;
-  point startpoint, leftpoint, rightpoint;
-  REAL leftccw, rightccw;
-  REAL ori, sign;
-  int leftflag, rightflag;
-
-  startpoint = sorg(*searchsh);
-  // Find the sign to simulate that abovepoint is 'above' the facet.
-  adjustedgering(*searchsh, CCW);
-  // Make sure 'startpoint' is the origin.
-  if (sorg(*searchsh) != startpoint) senextself(*searchsh);
-  rightpoint = sdest(*searchsh);
-  leftpoint = sapex(*searchsh);
-  ori = orient3d(startpoint, rightpoint, leftpoint, abovepoint);
-  sign = ori > 0.0 ? -1 : 1;
-
-  // Is `tend' to the left?
-  ori = orient3d(tend, startpoint, abovepoint, leftpoint);
-  leftccw = ori * sign;
-  leftflag = leftccw > 0.0;
-  // Is `tend' to the right?
-  ori = orient3d(startpoint, tend, abovepoint, rightpoint);
-  rightccw = ori * sign;
-  rightflag = rightccw > 0.0;
-  if (leftflag && rightflag) {
-    // `searchsh' faces directly away from `tend'.  We could go left or
-    //   right.  Ask whether it's a triangle or a boundary on the left.
-    senext2(*searchsh, checksh);
-    spivotself(checksh);
-    if (checksh.sh == dummysh) {
-      leftflag = 0;
-    } else {
-      rightflag = 0;
-    }
-  }
-  while (leftflag) {
-    // Turn left until satisfied.
-    senext2self(*searchsh);
-    spivotself(*searchsh);
-    if (searchsh->sh == dummysh) {
-      printf("Internal error in finddirectionsub():  Unable to find a\n");
-      printf("  subface leading from %d to %d.\n", pointmark(startpoint),
-             pointmark(tend));
-      internalerror();
-    }
-    if (sorg(*searchsh) != startpoint) sesymself(*searchsh);
-    assert(sorg(*searchsh) == startpoint);
-    leftpoint = sapex(*searchsh);
-    rightccw = leftccw;
-    ori = orient3d(tend, startpoint, abovepoint, leftpoint);
-    leftccw = ori * sign;
-    leftflag = leftccw > 0.0;
-  }
-  while (rightflag) {
-    // Turn right until satisfied.
-    spivotself(*searchsh);
-    if (searchsh->sh == dummysh) {
-      printf("Internal error in finddirectionsub():  Unable to find a\n");
-      printf("  subface leading from %d to %d.\n", pointmark(startpoint),
-             pointmark(tend));
-      internalerror();
-    }
-    if (sdest(*searchsh) != startpoint) sesymself(*searchsh);
-    assert(sdest(*searchsh) == startpoint);
-    senextself(*searchsh);
-    rightpoint = sdest(*searchsh);
-    leftccw = rightccw;
-    ori = orient3d(startpoint, tend, abovepoint, rightpoint);
-    rightccw = ori * sign;
-    rightflag = rightccw > 0.0;
-  }
-  if (leftccw == 0.0) {
-    return LEFTCOLLINEAR;
-  } else if (rightccw == 0.0) {
-    return RIGHTCOLLINEAR;
-  } else {
-    return ACROSSEDGE;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertsubseg()    Create a subsegment and insert it between two subfaces. //
-//                                                                           //
-// The new subsegment ab is inserted at the edge of subface 'tri'.  If ab is //
-// not a hull edge, it is inserted between two subfaces.  If 'tri' is a hull //
-// face, the initial face ring of ab will be set only one face which is self-//
-// bonded.  The final face ring will be constructed in 'unifysegments()'.    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::insertsubseg(face* tri)
-{
-  face oppotri;
-  face newsubseg;
-  point pa, pb;
-  REAL len;
-  int e1, e2;
-  int i;
-
-  // Check if there's already a subsegment here.
-  sspivot(*tri, newsubseg);
-  if (newsubseg.sh == dummysh) {
-    // Make new subsegment and initialize its vertices.
-    makeshellface(subsegs, &newsubseg);
-    pa = sorg(*tri);
-    pb = sdest(*tri);
-    setsorg(newsubseg, pa);
-    setsdest(newsubseg, pb);
-    // Are there length constraints?
-    if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
-      for (i = 0; i < in->numberofsegmentconstraints; i++) {
-        e1 = (int) in->segmentconstraintlist[i * 3];
-        e2 = (int) in->segmentconstraintlist[i * 3 + 1];
-        if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
-            ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
-          len = in->segmentconstraintlist[i * 3 + 2];
-          setareabound(newsubseg, len);
-          break;
-        }
-      }
-    }
-    // Bond new subsegment to the two subfaces it is sandwiched between.
-    ssbond(*tri, newsubseg);
-    spivot(*tri, oppotri);
-    // 'oppotri' might be "out space".
-    if (oppotri.sh != dummysh) {
-      ssbond(oppotri, newsubseg);
-    } /* else {
-      // Outside! Bond '*tri' to itself.
-      sbond(*tri, *tri);
-    } */
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// scoutsegmentsub()    Scout the first triangle on the path from one point  //
-//                      to another, and check for completion (reaching the   //
-//                      second point), a collinear point,or the intersection //
-//                      of two segments.                                     //
-//                                                                           //
-// Returns true if the entire segment is successfully inserted, and false if //
-// the job must be finished by constrainededge().                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::scoutsegmentsub(face* searchsh, point tend)
-{
-  face newsubseg;
-  face crosssub, crosssubseg;
-  point leftpoint, rightpoint;
-  enum finddirectionresult collinear;
-
-  collinear = finddirectionsub(searchsh, tend);
-  rightpoint = sdest(*searchsh);
-  leftpoint = sapex(*searchsh);
-  if (rightpoint == tend || leftpoint == tend) {
-    // The segment is already an edge.
-    if (leftpoint == tend) {
-      senext2self(*searchsh);
-    }
-    // Insert a subsegment.
-    insertsubseg(searchsh);
-    return true;
-  } else if (collinear == LEFTCOLLINEAR) {
-    // We've collided with a vertex between the segment's endpoints.
-    // Make the collinear vertex be the triangle's origin.
-    senextself(*searchsh); // lprevself(*searchtri);
-    // Insert a subsegment.
-    insertsubseg(searchsh);
-    // Insert the remainder of the segment.
-    return scoutsegmentsub(searchsh, tend);
-  } else if (collinear == RIGHTCOLLINEAR) {
-    // We've collided with a vertex between the segment's endpoints.
-    // Insert a subsegment.
-    insertsubseg(searchsh);
-    // Make the collinear vertex be the triangle's origin.
-    senextself(*searchsh); // lnextself(*searchtri);
-    // Insert the remainder of the segment.
-    return scoutsegmentsub(searchsh, tend);
-  } else {
-    senext(*searchsh, crosssub); // lnext(*searchtri, crosstri);
-    // Check for a crossing segment.
-    sspivot(crosssub, crosssubseg);
-#ifdef SELF_CHECK
-    assert(crosssubseg.sh == dummysh);
-#endif
-    return false;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// flipedgerecursive()    Flip an edge.                                      //
-//                                                                           //
-// This is a support routine for inserting segments into a CDT.              //
-//                                                                           //
-// Let 'flipedge' be ab, and two triangles abc, abd share at it.  ab may not //
-// flipable if the four vertices a, b, c, and d are non-convex. If it is the //
-// case, recursively flip ad or bd. Return when ab is flipped.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::flipedgerecursive(face* flipedge, queue* flipqueue)
-{
-  face fixupsh;
-  point pa, pb, pc, pd;
-  REAL oria, orib;
-  bool doflip;
-
-  pa = sorg(*flipedge);
-  pb = sdest(*flipedge);
-  pc = sapex(*flipedge);
-  do {
-    spivot(*flipedge, fixupsh);    
-    pd = sapex(fixupsh);
-    oria = orient3d(pc, pd, abovepoint, pa);
-    orib = orient3d(pc, pd, abovepoint, pb);
-    doflip = (oria * orib < 0.0);
-    if (doflip) {
-      // Flip the edge (a, b) away.      
-      flip22sub(flipedge, flipqueue);
-      // Fix flipedge on edge e (c, d).
-      findedge(flipedge, pc, pd);
-    } else {
-      // ab is unflipable. Get the next edge (bd, or da) to flip.
-      if (sorg(fixupsh) != pb) sesymself(fixupsh);
-      assert(sdest(fixupsh) == pa);
-      if (fabs(oria) > fabs(orib)) {
-        // acd has larger area. Choose da.
-        senextself(fixupsh);
-      } else {
-        // bcd has larger area. Choose bd.
-        senext2self(fixupsh);
-      }
-      // Flip the edge.
-      flipedgerecursive(&fixupsh, flipqueue);
-    }
-  } while (!doflip);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// constrainededge()    Force a segment into a CDT.                          //
-//                                                                           //
-// The segment s is recovered by flipping away the edges it intersects, and  //
-// triangulating the polygons that form on each side of it.                  //
-//                                                                           //
-// Generates a single subsegment connecting `tstart' to `tend'. The triangle //
-// `startsh' has `tstart' as its origin.                                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::constrainededge(face* startsh, point tend, queue* flipqueue)
-{
-  point tstart, tright, tleft;
-  REAL rori, lori;
-  bool collision;
-
-  tstart = sorg(*startsh);
-  do {
-    // Loop edges oppo to tstart until find one crosses the segment.
-    do {
-      tright = sdest(*startsh);
-      tleft = sapex(*startsh);
-      // Is edge (tright, tleft) corss the segment.
-      rori = orient3d(tstart, tright, abovepoint, tend);
-      collision = (rori == 0.0);
-      if (collision) break; // tright is on the segment.
-      lori = orient3d(tstart, tleft, abovepoint, tend);
-      collision = (lori == 0.0);
-      if (collision) { //  tleft is on the segment.
-        senext2self(*startsh);
-        break;
-      }
-      if (rori * lori < 0.0) break; // Find the crossing edge.
-      // Both points are at one side of the segment. 
-      finddirectionsub(startsh, tend);
-    } while (true);
-    if (collision) break;
-    // Get the neighbor face at edge e (tright, tleft).
-    senextself(*startsh);
-    // Flip the crossing edge.
-    flipedgerecursive(startsh, flipqueue);
-    // After flip, sorg(*startsh) == tstart.
-    assert(sorg(*startsh) == tstart);
-  } while (sdest(*startsh) != tend);
-
-  // Insert a subsegment to make the segment permanent.
-  insertsubseg(startsh);
-  // 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 (!scoutsegmentsub(startsh, tend)) {
-      constrainededge(startsh, tend, flipqueue);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// recoversegment()    Recover a segment in the surface triangulation.       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::recoversegment(point tstart, point tend, queue* flipqueue)
-{
-  face searchsh;
-
-  if (b->verbose > 2) {
-    printf("    Insert seg (%d, %d).\n", pointmark(tstart), pointmark(tend));
-  }
-
-  // Find a triangle whose origin is the segment's first endpoint.
-  searchsh.sh = dummysh;
-  // Search for the segment's first endpoint by point location.
-  if (locatesub(tstart, &searchsh, 0, 0.0) != ONVERTEX) {
-    // Possibly caused by a degenerate subface. Do a brute-force search.
-    list *newshlist;
-    int i, j;
-    newshlist = new list(sizeof(face), NULL, 256);
-    // Get new subfaces, do not remove protected segments.
-    retrievenewsubs(newshlist, false);
-    // Search for a sub contain tstart.
-    for (i = 0; i < newshlist->len(); i++) {
-      searchsh = * (face *)(* newshlist)[i];
-      for (j = 0; j < 3; j++) {
-        if (sorg(searchsh) == tstart) break;
-        senextself(searchsh);
-      }
-      if (j < 3) break;
-    }
-    delete newshlist;
-    if (sorg(searchsh) != tstart) {
-      printf("Internal error in recoversegment():  Vertex location failed.\n");
-      internalerror();
-    }
-  }
-  // Scout the segment and insert it if it is found.
-  if (scoutsegmentsub(&searchsh, tend)) {
-    // The segment was easily inserted.
-    return;
-  }  
-  // Insert the segment into the triangulation by flips.
-  constrainededge(&searchsh, tend, flipqueue);
-  // Some edges may need flipping.
-  flipsub(flipqueue);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// infecthullsub()    Virally infect all of the triangles of the convex hull //
-//                    that are not protected by subsegments.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::infecthullsub(memorypool* viri)
-{
-  face hulltri, nexttri, starttri;
-  face hullsubseg;
-  shellface **deadshellface;
-
-  // Find a triangle handle on the hull.
-  hulltri.sh = dummysh;
-  hulltri.shver = 0;
-  spivotself(hulltri);
-  adjustedgering(hulltri, CCW);
-  // Remember where we started so we know when to stop.
-  starttri = hulltri;
-  // Go once counterclockwise around the convex hull.
-  do {
-    // Ignore triangles that are already infected.
-    if (!sinfected(hulltri)) {
-      // Is the triangle protected by a subsegment?
-      sspivot(hulltri, hullsubseg);
-      if (hullsubseg.sh == dummysh) {
-        // The triangle is not protected; infect it.
-        if (!sinfected(hulltri)) {
-          sinfect(hulltri);
-          deadshellface = (shellface **) viri->alloc();
-          *deadshellface = hulltri.sh;
-        }
-      } 
-    }
-    // To find the next hull edge, go clockwise around the next vertex.
-    senextself(hulltri); // lnextself(hulltri);
-    spivot(hulltri, nexttri); // oprev(hulltri, nexttri);
-    if (nexttri.sh == hulltri.sh) {
-      nexttri.sh = dummysh;  // 'hulltri' is self-bonded.
-    } else {
-      adjustedgering(nexttri, CCW);
-      senextself(nexttri);
-    }
-    while (nexttri.sh != dummysh) {
-      hulltri = nexttri;
-      spivot(hulltri, nexttri); // oprev(hulltri, nexttri);
-      if (nexttri.sh == hulltri.sh) {
-        nexttri.sh = dummysh;  // 'hulltri' is self-bonded.
-      } else {
-        adjustedgering(nexttri, CCW);
-        senextself(nexttri);
-      }
-    }
-  } while (hulltri != starttri);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// plaguesub()    Spread the virus from all infected triangles to any        //
-//                neighbors not protected by subsegments.  Delete all        //
-//                infected triangles.                                        //
-//                                                                           //
-// This is the procedure that actually creates holes and concavities.        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::plaguesub(memorypool* viri)
-{
-  face testtri, neighbor, ghostsh;
-  face neighborsubseg;
-  shellface **virusloop;
-  shellface **deadshellface;
-  int i;
-
-  // Loop through all the infected triangles, spreading the virus to
-  //   their neighbors, then to their neighbors' neighbors.
-  viri->traversalinit();
-  virusloop = (shellface **) viri->traverse();
-  while (virusloop != (shellface **) NULL) {
-    testtri.sh = *virusloop;
-    // Check each of the triangle's three neighbors.
-    for (i = 0; i < 3; i++) {
-      // Find the neighbor.
-      spivot(testtri, neighbor);
-      // Check for a subsegment between the triangle and its neighbor.
-      sspivot(testtri, neighborsubseg);
-      // Check if the neighbor is nonexistent or already infected.
-      if ((neighbor.sh == dummysh) || sinfected(neighbor)) {
-        if (neighborsubseg.sh != dummysh) {
-          // There is a subsegment separating the triangle from its
-          //   neighbor, but both triangles are dying, so the subsegment
-          //   dies too.
-          shellfacedealloc(subsegs, neighborsubseg.sh);
-          if (neighbor.sh != dummysh) {
-            // Make sure the subsegment doesn't get deallocated again
-            //   later when the infected neighbor is visited.
-            ssdissolve(neighbor);
-          }
-        }
-      } else {                   // The neighbor exists and is not infected.
-        if (neighborsubseg.sh == dummysh) {
-          // There is no subsegment protecting the neighbor, so the
-          //   neighbor becomes infected.
-          sinfect(neighbor);
-          // Ensure that the neighbor's neighbors will be infected.
-          deadshellface = (shellface **) viri->alloc();
-          *deadshellface = neighbor.sh;
-        } else {               // The neighbor is protected by a subsegment.
-          // Remove this triangle from the subsegment.
-          ssbond(neighbor, neighborsubseg);
-        }
-      }
-      senextself(testtri);
-    }
-    virusloop = (shellface **) viri->traverse();
-  }
-
-  ghostsh.sh = dummysh; // A handle of outer space.
-  viri->traversalinit();
-  virusloop = (shellface **) viri->traverse();
-  while (virusloop != (shellface **) NULL) {
-    testtri.sh = *virusloop;
-    // Record changes in the number of boundary edges, and disconnect
-    //   dead triangles from their neighbors. 
-    for (i = 0; i < 3; i++) {
-      spivot(testtri, neighbor);
-      if (neighbor.sh != dummysh) {
-        // Disconnect the triangle from its neighbor.
-        // sdissolve(neighbor);
-        sbond(neighbor, ghostsh); 
-      }
-      senextself(testtri);
-    }
-    // Return the dead triangle to the pool of triangles.
-    shellfacedealloc(subfaces, testtri.sh);
-    virusloop = (shellface **) viri->traverse();
-  }
-  // Empty the virus pool.
-  viri->restart();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// carveholessub()    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 tetgenmesh::carveholessub(int holes, REAL* holelist, memorypool *viri)
-{
-  face searchtri, triangleloop;
-  shellface **holetri;
-  enum locateresult intersect;
-  int i;
-
-  // Mark as infected any unprotected triangles on the boundary.
-  //   This is one way by which concavities are created.
-  infecthullsub(viri);
-
-  if (holes > 0) {
-    // Infect each triangle 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 triangle on the outer boundary.
-        searchtri.sh = dummysh;
-        // Find a triangle that contains the hole.
-        intersect = locatesub(&holelist[i], &searchtri, 0, 0.0);
-        if ((intersect != OUTSIDE) && (!sinfected(searchtri))) {
-          // Infect the triangle.  This is done by marking the triangle
-          //   as infected and including the triangle in the virus pool.
-          sinfect(searchtri);
-          holetri = (shellface **) viri->alloc();
-          *holetri = searchtri.sh;
-        }
-      }
-    }
-  }
-
-  if (viri->items > 0) {
-    // Carve the holes and concavities.
-    plaguesub(viri);
-  }
-  // The virus pool should be empty now.
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// triangulate()    Triangulate a PSLG into a CDT.                           //
-//                                                                           //
-// A Planar Straight Line Graph (PSLG) P is actually a 2D polygonal region,  //
-// possibly contains holes, segments and vertices in its interior. P is tri- //
-// angulated into a set of _subfaces_ forming a CDT of P.                    //
-//                                                                           //
-// The vertices and segments of P are found in 'ptlist' and 'conlist', resp- //
-// ectively. 'holelist' contains a list of hole points. 'shmark' will be set //
-// to all subfaces of P.                                                     //
-//                                                                           //
-// The CDT is created directly in the pools 'subfaces' and 'subsegs'. It can //
-// be retrived by a broadth-first searching starting from 'dummysh[0]'(debug //
-// function 'outsurfmesh()' does it).                                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::triangulate(int shmark, REAL eps, list* ptlist, list* conlist,
-  int holes, REAL* holelist, memorypool* viri, queue* flipqueue)
-{
-  face newsh;
-  point *cons;
-  int i;
-
-  if (b->verbose > 1) {
-    printf("    %d vertices, %d segments", ptlist->len(), conlist->len());
-    if (holes > 0) {
-      printf(", %d holes", holes);
-    }
-    printf(", shmark: %d.\n", shmark);
-  }
-
-  // Create the DT of V by the 2D incremental flip algorithm.
-  incrflipdelaunaysub(shmark, eps, ptlist, holes, holelist, flipqueue);
-  // Recover boundary edges.
-  if (ptlist->len() > 3) {
-    // Insert segments into the DT.
-    for (i = 0; i < conlist->len(); i++) {
-      cons = (point *)(* conlist)[i];
-      recoversegment(cons[0], cons[1], flipqueue);        
-    }
-    // Carve holes and concavities.
-    carveholessub(holes, holelist, viri);
-  } else if (ptlist->len() == 3) {
-    // Insert 3 segments directly.
-    newsh.sh = dummysh;
-    newsh.shver = 0;
-    spivotself(newsh);
-    for (i = 0; i < 3; i++) {
-      insertsubseg(&newsh);
-      senextself(newsh);
-    }
-  } else if (ptlist->len() == 2) {
-    // This facet is actually a segment. It is not support by the mesh data
-    //   strcuture. Hence the segment will not be maintained in the mesh.
-    //   However, during segment recovery, the segment can be processed.
-    cons = (point *)(* conlist)[0];
-    makeshellface(subsegs, &newsh);
-    setsorg(newsh, cons[0]);
-    setsdest(newsh, cons[1]);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// retrievenewsubs()    Retrieve newly created subfaces.                     //
-//                                                                           //
-// The new subfaces created by triangulate() can be found by a broadth-first //
-// searching starting from 'dummysh[0]'.                                     //
-//                                                                           //
-// 'newshlist' (empty on input) returns the retrieved subfaces. Each edge on //
-// the hull is bound to 'dummysh' and protected by a segment. If 'removeseg' //
-// is TRUE, the segment is removed.                                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::retrievenewsubs(list* newshlist, bool removeseg)
-{
-  face startsh, neighsh;
-  face deadseg;
-  int i, j;
-
-  // The first new subface is found at dummysh[0].
-  startsh.sh = dummysh;
-  startsh.shver = 0;
-  spivotself(startsh);
-  assert(startsh.sh != dummysh);
-  sinfect(startsh);
-  newshlist->append(&startsh);
-
-  // Find the rest of new subfaces by a broadth-first searching.
-  for (i = 0; i < newshlist->len(); i++) {
-    // Get a new subface s.
-    startsh = * (face *)(* newshlist)[i];
-    for (j = 0; j < 3; j++) {
-      spivot(startsh, neighsh);
-      if (neighsh.sh != dummysh) {
-        if (!sinfected(neighsh)) {
-          // Discovered a new subface.
-          sinfect(neighsh);
-          newshlist->append(&neighsh);
-        }
-      } else {
-        // Found a boundary edge. 
-        if (removeseg) {
-          // This side of s may be protected by a segment.
-          sspivot(startsh, deadseg);
-          if (deadseg.sh != dummysh) {
-            // Detach it from s.
-            ssdissolve(startsh);
-            // Delete the segment.
-            shellfacedealloc(subsegs, deadseg.sh);
-          }
-        }
-      }
-      senextself(startsh);
-    }
-  }
-  for (i = 0; i < newshlist->len(); i++) {
-    startsh = * (face *)(* newshlist)[i];
-    suninfect(startsh);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// unifysegments()    Unify identical segments and build facet connections.  //
-//                                                                           //
-// After creating the surface mesh. Each facet has its own segments.  There  //
-// are duplicated segments between adjacent facets.  This routine has three  //
-// purposes:                                                                 //
-//   (1) identify the set of segments which have the same endpoints and      //
-//       unify them into one segment, remove redundant ones;                 //
-//   (2) create the face rings of the unified segments, hence setup the      //
-//       connections between facets; and                                     //
-//   (3) set a unique marker (1-based) for each segment.                     //
-// On finish, each segment is unique and the face ring around it (right-hand //
-// rule) is constructed. The connections between facets-facets are setup.    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::unifysegments()
-{
-  list *sfacelist;
-  shellface **facesperverlist;
-  face subsegloop, testseg;
-  face sface, sface1, sface2;
-  point torg, tdest;
-  REAL da1, da2;
-  int *idx2facelist;
-  int segmarker;
-  int idx, k, m;
-
-  if (b->verbose > 0) {
-    printf("  Unifying segments.\n");
-  }
-
-  // Compute a mapping from indices of vertices to subfaces.
-  makesubfacemap(idx2facelist, facesperverlist);
-  // Initialize 'sfacelist' for constructing the face link of each segment.
-  sfacelist = new list(sizeof(face), NULL); 
-  
-  segmarker = 1;
-  subsegs->traversalinit();
-  subsegloop.sh = shellfacetraverse(subsegs);
-  while (subsegloop.sh != (shellface *) NULL) {
-    subsegloop.shver = 0; // For sure.
-    torg = sorg(subsegloop);
-    tdest = sdest(subsegloop);
-    idx = pointmark(torg) - in->firstnumber;
-    // Loop through the set of subfaces containing 'torg'.  Get all the
-    //   subfaces containing the edge (torg, tdest). Save and order them
-    //   in 'sfacelist', the ordering is defined by the right-hand rule
-    //   with thumb points from torg to tdest.
-    for (k = idx2facelist[idx]; k < idx2facelist[idx + 1]; k++) {
-      sface.sh = facesperverlist[k];
-      sface.shver = 0;
-      // sface may be died due to the removing of duplicated subfaces.
-      if (!isdead(&sface) && isfacehasedge(&sface, torg, tdest)) {
-        // 'sface' contains this segment.
-        findedge(&sface, torg, tdest);
-        // Save it in 'sfacelist'.
-        if (sfacelist->len() < 2) {
-          sfacelist->append(&sface);
-        } else {
-          for (m = 0; m < sfacelist->len() - 1; m++) {
-            sface1 = * (face *)(* sfacelist)[m];
-            sface2 = * (face *)(* sfacelist)[m + 1];
-            da1 = facedihedral(torg, tdest, sapex(sface1), sapex(sface));
-            da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
-            if (da1 < da2) {
-              break;  // Insert it after m.
-            }
-          }
-          sfacelist->insert(m + 1, &sface);
-        }
-      }
-    }
-    if (b->verbose > 1) {
-      printf("    Identifying %d segments of (%d  %d).\n", sfacelist->len(),
-             pointmark(torg), pointmark(tdest));
-    }
-    // Set the connection between this segment and faces containing it,
-    //   at the same time, remove redundant segments.
-    for (k = 0; k < sfacelist->len(); k++) {
-      sface = *(face *)(* sfacelist)[k];
-      sspivot(sface, testseg);
-      // If 'testseg' is not 'subsegloop', it is a redundant segment that
-      //   needs be removed. BE CAREFUL it may already be removed. Do not
-      //   remove it twice, i.e., do test 'isdead()' together.
-      if ((testseg.sh != subsegloop.sh) && !isdead(&testseg)) {
-        shellfacedealloc(subsegs, testseg.sh);
-      }
-      // 'ssbond' bonds the subface and the segment together, and dissloves
-      //   the old bond as well.
-      ssbond(sface, subsegloop);
-    }
-    // Set connection between these faces.
-    sface = *(face *)(* sfacelist)[0];
-    for (k = 1; k <= sfacelist->len(); k++) {
-      if (k < sfacelist->len()) {
-        sface1 = *(face *)(* sfacelist)[k];
-      } else {
-        sface1 = *(face *)(* sfacelist)[0];    // Form a face loop.
-      }
-      /*
-      // Check if these two subfaces are the same. It is possible when user
-      //   defines one facet (or polygon) two or more times. If they are,
-      //   they should not be bonded together, instead of that, one of them
-      //   should be delete from the surface mesh.
-      if ((sfacelist->len() > 1) && sapex(sface) == sapex(sface1)) {
-        // They are duplicated faces.
-        if (b->verbose > 0) {
-          printf("  A duplicated subface (%d, %d, %d) is removed.\n",
-                 pointmark(torg), pointmark(tdest), pointmark(sapex(sface)));
-        }
-        if (k == sfacelist->len()) {
-          // 'sface' is the last face, however, it is same as the first one.
-          //   In order to form the ring, we have to let the second last
-          //   face bond to the first one 'sface1'.
-          shellfacedealloc(subfaces, sface.sh);
-          assert(sfacelist->len() >= 2);
-          assert(k == sfacelist->len());
-          sface = *(face *)(* sfacelist)[k - 2];
-        } else {
-          // 'sface1' is in the middle and may be the last one. 
-          shellfacedealloc(subfaces, sface1.sh);
-          // Skip this face and go to the next one.
-          continue;
-        }
-      }
-      */ 
-      if (b->verbose > 2) {
-        printf("    Bond subfaces (%d, %d, %d) and (%d, %d, %d).\n",
-               pointmark(torg), pointmark(tdest), pointmark(sapex(sface)),
-               pointmark(torg), pointmark(tdest), pointmark(sapex(sface1)));
-      }
-      sbond1(sface, sface1);
-      sface = sface1;
-    }
-    // Set the unique segment marker into the unified segment.
-    setshellmark(subsegloop, segmarker);
-    // Increase the marker.
-    segmarker++;
-    // Clear the working list.
-    sfacelist->clear(); 
-    subsegloop.sh = shellfacetraverse(subsegs);
-  }
-
-  delete [] idx2facelist;
-  delete [] facesperverlist;
-  delete sfacelist;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// mergefacets()    Merge adjacent facets to be one facet if they are        //
-//                  coplanar and have the same boundary marker.              //
-//                                                                           //
-// Segments between two merged facets will be removed from the mesh.  If all //
-// segments around a vertex have been removed, change its vertex type to be  //
-// FREESUBVERTEX. Edge flips will be performed to ensure the Delaunayness of //
-// the triangulation of merged facets.                                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::mergefacets(queue* flipqueue)
-{
-  face parentsh, neighsh, neineighsh;
-  face segloop;
-  point eorg, edest;
-  REAL ori;
-  bool mergeflag, pbcflag;
-  int* segspernodelist;
-  int fidx1, fidx2;
-  int i, j;
-
-  if (b->verbose > 0) {
-    printf("  Merging coplanar facets.\n");
-  }
-  // Create and initialize 'segspernodelist'.
-  segspernodelist = new int[points->items + 1];
-  for (i = 0; i < points->items + 1; i++) segspernodelist[i] = 0;
-
-  // Loop the segments, counter the number of segments sharing each vertex.
-  subsegs->traversalinit();
-  segloop.sh = shellfacetraverse(subsegs);
-  while (segloop.sh != (shellface *) NULL) {
-    // Increment the number of sharing segments for each endpoint.
-    for (i = 0; i < 2; i++) {
-      j = pointmark((point) segloop.sh[3 + i]);
-      segspernodelist[j]++;
-    }
-    segloop.sh = shellfacetraverse(subsegs);
-  }
-
-  // Loop the segments, find out dead segments.
-  subsegs->traversalinit();
-  segloop.sh = shellfacetraverse(subsegs);
-  while (segloop.sh != (shellface *) NULL) {
-    eorg = sorg(segloop);
-    edest = sdest(segloop);
-    spivot(segloop, parentsh);
-    spivot(parentsh, neighsh);
-    spivot(neighsh, neineighsh);
-    if (parentsh.sh != neighsh.sh && parentsh.sh == neineighsh.sh) {
-      // Exactly two subfaces at this segment.
-      fidx1 = shellmark(parentsh) - 1;
-      fidx2 = shellmark(neighsh) - 1;
-      pbcflag = false;
-      if (checkpbcs) {
-        pbcflag = (shellpbcgroup(parentsh) >= 0)
-          || (shellpbcgroup(neighsh) >= 0);
-      }
-      // Possibly merge them if they are not in the same facet.
-      if ((fidx1 != fidx2) && !pbcflag) {
-        // Test if they are coplanar.
-        ori = orient3d(eorg, edest, sapex(parentsh), sapex(neighsh));
-        if (ori != 0.0) {
-          if (iscoplanar(eorg, edest, sapex(parentsh), sapex(neighsh), ori,
-                         b->epsilon)) {
-            ori = 0.0; // They are assumed as coplanar.
-          }
-        }
-        if (ori == 0.0) {
-          mergeflag = (in->facetmarkerlist == (int *) NULL || 
-          in->facetmarkerlist[fidx1] == in->facetmarkerlist[fidx2]);
-          if (mergeflag) {
-            // This segment becomes dead.
-            if (b->verbose > 1) {
-              printf("  Removing segment (%d, %d).\n", pointmark(eorg),
-                     pointmark(edest));
-            }
-            ssdissolve(parentsh);
-            ssdissolve(neighsh);
-            shellfacedealloc(subsegs, segloop.sh);
-            j = pointmark(eorg);
-            segspernodelist[j]--;
-            if (segspernodelist[j] == 0) {
-              setpointtype(eorg, FREESUBVERTEX);
-            }
-            j = pointmark(edest);
-            segspernodelist[j]--;
-            if (segspernodelist[j] == 0) {
-              setpointtype(edest, FREESUBVERTEX);
-            }
-            // Add 'parentsh' to queue checking for flip.
-            enqueueflipedge(parentsh, flipqueue);
-          }
-        }
-      }
-    }
-    segloop.sh = shellfacetraverse(subsegs);
-  }
-
-  if (!flipqueue->empty()) {
-    // Restore the Delaunay property in the facet triangulation.
-    flipsub(flipqueue);
-  }
-
-  delete [] segspernodelist;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// meshsurface()    Create the surface mesh of a PLC.                        //
-//                                                                           //
-// Let X be the PLC, the surface mesh S of X consists of triangulated facets.//
-// S is created mainly in the following steps:                               //
-//                                                                           //
-// (1) Form the CDT of each facet of X separately (by routine triangulate()).//
-// After it is done, the subfaces of each facet are connected to each other, //
-// however there is no connection between facets yet.  Notice each facet has //
-// its own segments, some of them are duplicated.                            //
-//                                                                           //
-// (2) Remove the redundant segments created in step (1) (by routine unify-  //
-// segment()). The subface ring of each segment is created,  the connection  //
-// between facets are established as well.                                   //
-//                                                                           //
-// The return value indicates the number of segments of X.                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-long tetgenmesh::meshsurface()
-{
-  list *ptlist, *conlist;
-  queue *flipqueue;
-  tetgenio::facet *f;
-  tetgenio::polygon *p;
-  memorypool *viri;
-  point *idx2verlist;
-  point tstart, tend, *cons;
-  int *worklist;
-  int end1, end2;
-  int shmark, i, j;
-
-  if (!b->quiet) {
-    printf("Creating surface mesh.\n");
-  }
-
-  // Compute a mapping from indices to points.
-  makeindex2pointmap(idx2verlist);
-  // Compute a mapping from points to tets for computing abovepoints.
-  makepoint2tetmap();
-  // Initialize 'facetabovepointarray'.
-  facetabovepointarray = new point[in->numberoffacets + 1];
-  for (i = 0; i < in->numberoffacets + 1; i++) {
-    facetabovepointarray[i] = (point) NULL;
-  }
-  if (checkpbcs) {
-    // Initialize the global array 'subpbcgrouptable'.
-    createsubpbcgrouptable();
-  }
-
-  // Initialize working lists.
-  viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
-  flipqueue = new queue(sizeof(badface));
-  ptlist = new list(sizeof(point *), NULL, 256);
-  conlist = new list(sizeof(point *) * 2, NULL, 256);
-  worklist = new int[points->items + 1];
-  for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
-  
-  // Loop the facet list, triangulate each facet. On finish, all subfaces
-  //   are in 'subfaces', all segments are in 'subsegs'. Notice: there're
-  //   redundant segments.  Remember: All facet indices count from 1.
-  for (shmark = 1; shmark <= in->numberoffacets; shmark++) {    
-    // Get a facet F.
-    f = &in->facetlist[shmark - 1];
-
-    // Process the duplicated points first, they are marked with type
-    //   DUPLICATEDVERTEX by incrflipdelaunay().  Let p and q are dup.
-    //   and the index of p is larger than q's, p is substituted by q.
-    //   In a STL mesh, duplicated points are implicitly included.
-    if ((b->object == tetgenbehavior::STL) || dupverts) {
-      // Loop all polygons of this facet.
-      for (i = 0; i < f->numberofpolygons; i++) {
-        p = &(f->polygonlist[i]);
-        // Loop other vertices of this polygon.
-        for (j = 0; j < p->numberofvertices; j++) {
-          end1 = p->vertexlist[j];
-          tstart = idx2verlist[end1 - in->firstnumber];
-          if (pointtype(tstart) == DUPLICATEDVERTEX) {
-            // Reset the index of vertex-j.
-            tend = point2ppt(tstart);
-            end2 = pointmark(tend);
-            p->vertexlist[j] = end2;
-          }
-        }
-      }
-    }
-
-    // Loop polygons of F, get the set V of vertices and S of segments.
-    for (i = 0; i < f->numberofpolygons; i++) {
-      // Get a polygon.
-      p = &(f->polygonlist[i]);
-      // Get the first vertex.
-      end1 = p->vertexlist[0];
-      if ((end1 < in->firstnumber) || 
-          (end1 >= in->firstnumber + in->numberofpoints)) {
-        if (!b->quiet) {
-          printf("Warning:  Invalid the 1st vertex %d of polygon", end1);
-          printf(" %d in facet %d.\n", i + 1, shmark);
-        }
-        continue; // Skip this polygon.
-      }
-      tstart = idx2verlist[end1 - in->firstnumber];
-      // Add tstart to V if it haven't been added yet.
-      if (worklist[end1] == 0) {
-        ptlist->append(&tstart);
-        worklist[end1] = 1;
-      }
-      // Loop other vertices of this polygon.
-      for (j = 1; j <= p->numberofvertices; j++) {
-        // get a vertex.
-        if (j < p->numberofvertices) {
-          end2 = p->vertexlist[j];
-        } else {
-          end2 = p->vertexlist[0];  // Form a loop from last to first.
-        }
-        if ((end2 < in->firstnumber) ||
-            (end2 >= in->firstnumber + in->numberofpoints)) {
-          if (!b->quiet) {
-            printf("Warning:  Invalid vertex %d in polygon %d", end2, i + 1);
-            printf(" in facet %d.\n", shmark);
-          }
-        } else {
-          if (end1 != end2) {
-            // 'end1' and 'end2' form a segment.
-            tend = idx2verlist[end2 - in->firstnumber];
-            // Add tstart to V if it haven't been added yet.
-            if (worklist[end2] == 0) {
-              ptlist->append(&tend);
-              worklist[end2] = 1;
-            }
-            // Save the segment in S (conlist).
-            cons = (point *) conlist->append(NULL);
-            cons[0] = tstart;
-            cons[1] = tend;
-            // Set the start for next continuous segment.
-            end1 = end2;
-            tstart = tend;
-          } else {
-            // Two identical vertices represent an isolated vertex of F.
-            if (p->numberofvertices > 2) {
-              // This may be an error in the input, anyway, we can continue
-              //   by simply skipping this segment.
-              if (!b->quiet) {
-                printf("Warning:  Polygon %d has two identical verts", i + 1);
-                printf(" in facet %d.\n", shmark);
-              }
-            } 
-            // Ignore this vertex.
-          } 
-        }
-        // Is the polygon degenerate (a segment or a vertex)?
-        if (p->numberofvertices == 2) break;
-      } 
-    }
-    // Unmark vertices.
-    for (i = 0; i < ptlist->len(); i++) {
-      tstart = * (point *)(* ptlist)[i];
-      end1 = pointmark(tstart);
-      assert(worklist[end1] == 1);
-      worklist[end1] = 0;
-    }
-
-    // Create a CDT of F.
-    triangulate(shmark, b->epsilon * 1e+2, ptlist, conlist, f->numberofholes,
-                f->holelist, viri, flipqueue);
-    // Clear working lists.
-    ptlist->clear();
-    conlist->clear();
-    viri->restart();
-  }
-
-  // Unify segments in 'subsegs', remove redundant segments.  Face links
-  //   of segments are also built.
-  unifysegments();
-  // Remember the number of input segments (for output).
-  insegments = subsegs->items;
-
-  if (checkpbcs) {
-    // Create the global array 'segpbcgrouptable'.
-    createsegpbcgrouptable();
-  }
-
-  if (b->object == tetgenbehavior::STL) {
-    // Remove redundant vertices (for .stl input mesh).
-    jettisonnodes();
-  }
-
-  if (!b->nomerge && !b->nobisect && !checkpbcs) {
-    // No '-M' switch - merge adjacent facets if they are coplanar.
-    mergefacets(flipqueue);
-  }
-
-  delete [] idx2verlist;
-  delete [] worklist;
-  delete ptlist;
-  delete conlist;
-  delete flipqueue;
-  delete viri;
-
-  return subsegs->items;
-}
-
-//
-// End of surface triangulation routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// interecursive()    Recursively do intersection test on a set of triangles.//
-//                                                                           //
-// Recursively split the set 'subfacearray' of subfaces into two sets using  //
-// a cut plane parallel to x-, or, y-, or z-axies.  The split criteria are   //
-// follows. Assume the cut plane is H, and H+ denotes the left halfspace of  //
-// H, and H- denotes the right halfspace of H; and s be a subface:           //
-//                                                                           //
-//    (1) If all points of s lie at H+, put it into left array;              //
-//    (2) If all points of s lie at H-, put it into right array;             //
-//    (3) If some points of s lie at H+ and some of lie at H-, or some       //
-//        points lie on H, put it into both arraies.                         //
-//                                                                           //
-// Partitions by x-axis if axis == '0'; by y-axis if axis == '1'; by z-axis  //
-// if axis == '2'. If current cut plane is parallel to the x-axis, the next  //
-// one will be parallel to y-axis, and the next one after the next is z-axis,//
-// and then alternately return back to x-axis.                               //
-//                                                                           //
-// Stop splitting when the number of triangles of the input array is not     //
-// decreased anymore. Do tests on the current set.                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::
-interecursive(shellface** subfacearray, int arraysize, int axis, REAL bxmin,
-              REAL bxmax, REAL bymin, REAL bymax, REAL bzmin, REAL bzmax,
-              int* internum)
-{
-  shellface **leftarray, **rightarray;
-  face sface1, sface2;
-  point p1, p2, p3;
-  point p4, p5, p6;
-  enum interresult intersect;
-  REAL split;
-  bool toleft, toright;
-  int leftsize, rightsize;
-  int i, j;
-
-  if (b->verbose > 1) {
-    printf("  Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
-           arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
-           axis == 0 ? "x" : (axis == 1 ? "y" : "z"));
-  }
-    
-  leftarray = new shellface*[arraysize];
-  if (leftarray == NULL) {
-    printf("Error in interecursive():  Insufficient memory.\n");
-    terminatetetgen(1);
-  }
-  rightarray = new shellface*[arraysize];
-  if (rightarray == NULL) {
-    printf("Error in interecursive():  Insufficient memory.\n");
-    terminatetetgen(1);
-  }
-  leftsize = rightsize = 0;
-
-  if (axis == 0) {
-    // Split along x-axis.
-    split = 0.5 * (bxmin + bxmax);
-  } else if (axis == 1) {
-    // Split along y-axis.
-    split = 0.5 * (bymin + bymax);
-  } else {
-    // Split along z-axis.
-    split = 0.5 * (bzmin + bzmax);
-  }
-
-  for (i = 0; i < arraysize; i++) {
-    sface1.sh = subfacearray[i];
-    p1 = (point) sface1.sh[3];
-    p2 = (point) sface1.sh[4];
-    p3 = (point) sface1.sh[5];
-    toleft = toright = false;
-    if (p1[axis] < split) {
-      toleft = true;
-      if (p2[axis] >= split || p3[axis] >= split) {
-        toright = true;
-      } 
-    } else if (p1[axis] > split) {
-      toright = true;
-      if (p2[axis] <= split || p3[axis] <= split) {
-        toleft = true;
-      } 
-    } else {
-      // p1[axis] == split;
-      toleft = true;
-      toright = true;
-    }
-    // At least one is true;
-#ifdef SELF_CHECK
-    assert(!(toleft == false && toright == false));
-#endif
-    if (toleft) {
-      leftarray[leftsize] = sface1.sh;
-      leftsize++;
-    }
-    if (toright) {
-      rightarray[rightsize] = sface1.sh;
-      rightsize++;
-    }
-  }
-
-  if (leftsize < arraysize && rightsize < arraysize) {
-    // Continue to partition the input set. Now 'subfacearray' has been
-    //   split into two sets, it's memory can be freed. 'leftarray' and
-    //   'rightarray' will be freed in the next recursive (after they're
-    //   partitioned again or performing tests).
-    delete [] subfacearray;
-    // Continue to split these two sets.
-    if (axis == 0) {
-      interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax,
-                    bzmin, bzmax, internum);
-      interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax,
-                    bzmin, bzmax, internum);
-    } else if (axis == 1) {
-      interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split,
-                    bzmin, bzmax, internum);
-      interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax,
-                    bzmin, bzmax, internum);
-    } else {
-      interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax,
-                    bzmin, split, internum);
-      interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax,
-                    split, bzmax, internum);
-    }
-  } else {
-    if (b->verbose > 1) {
-      printf("  Checking intersecting faces.\n");
-    }
-    // Perform a brute-force compare on the set.
-    for (i = 0; i < arraysize; i++) {
-      sface1.sh = subfacearray[i];
-      p1 = (point) sface1.sh[3];
-      p2 = (point) sface1.sh[4];
-      p3 = (point) sface1.sh[5];
-      for (j = i + 1; j < arraysize; j++) {
-        sface2.sh = subfacearray[j];
-        p4 = (point) sface2.sh[3];
-        p5 = (point) sface2.sh[4];
-        p6 = (point) sface2.sh[5];
-        intersect = tri_tri_inter(p1, p2, p3, p4, p5, p6);
-        if (intersect == INTERSECT || intersect == SHAREFACE) {
-          if (!b->quiet) {
-            if (intersect == INTERSECT) {
-              printf("  Facet #%d intersects facet #%d at triangles:\n",
-                     shellmark(sface1), shellmark(sface2));
-              printf("    (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
-                     pointmark(p1), pointmark(p2), pointmark(p3),
-                     pointmark(p4), pointmark(p5), pointmark(p6));
-            } else {
-              printf("  Facet #%d duplicates facet #%d at triangle:\n",
-                     shellmark(sface1), shellmark(sface2));
-              printf("    (%4d, %4d, %4d)\n", pointmark(p1), pointmark(p2),
-                     pointmark(p3));
-            }
-          }
-          // Increase the number of intersecting pairs.
-          (*internum)++; 
-          // Infect these two faces (although they may already be infected).
-          sinfect(sface1);
-          sinfect(sface2);
-        }
-      }
-    }
-    // Don't forget to free all three arrays. No further partition.
-    delete [] leftarray;
-    delete [] rightarray;  
-    delete [] subfacearray;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// detectinterfaces()    Detect intersecting triangles.                      //
-//                                                                           //
-// Given a set of triangles,  find the pairs of intersecting triangles from  //
-// them.  Here the set of triangles is in 'subfaces' which is a surface mesh //
-// of a PLC (.poly or .smesh).                                               //
-//                                                                           //
-// To detect whether two triangles are intersecting is done by the routine   //
-// 'tri_tri_inter()'.  The algorithm for the test is very simple and stable. //
-// It is based on geometric orientation test which uses exact arithmetics.   //
-//                                                                           //
-// Use divide-and-conquer algorithm for reducing the number of intersection  //
-// tests.  Start from the bounding box of the input point set, recursively   //
-// partition the box into smaller boxes, until the number of triangles in a  //
-// box is not decreased anymore. Then perform triangle-triangle tests on the //
-// remaining set of triangles.  The memory allocated in the input set is     //
-// freed immediately after it has been partitioned into two arrays.  So it   //
-// can be re-used for the consequent partitions.                             //
-//                                                                           //
-// On return, the pool 'subfaces' will be cleared, and only the intersecting //
-// triangles remain for output (to a .face file).                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::detectinterfaces()
-{
-  shellface **subfacearray;
-  face shloop;
-  int internum;
-  int i;
-
-  if (!b->quiet) {
-    printf("Detecting intersecting facets.\n");
-  }
-
-  // Construct a map from indices to subfaces;
-  subfacearray = new shellface*[subfaces->items];
-  subfaces->traversalinit();
-  shloop.sh = shellfacetraverse(subfaces);
-  i = 0;
-  while (shloop.sh != (shellface *) NULL) {
-    subfacearray[i] = shloop.sh;
-    shloop.sh = shellfacetraverse(subfaces);
-    i++;
-  }
-
-  internum = 0;
-  // Recursively split the set of triangles into two sets using a cut plane
-  //   parallel to x-, or, y-, or z-axies.  Stop splitting when the number
-  //   of subfaces is not decreasing anymore. Do tests on the current set.
-  interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax,
-                zmin, zmax, &internum);
-
-  if (!b->quiet) {
-    if (internum > 0) {
-      printf("\n!! Found %d pairs of faces are intersecting.\n\n", internum);
-    } else {
-      printf("\nNo faces are intersecting.\n\n");
-    }
-  }
-
-  if (internum > 0) {
-    // Traverse all subfaces, deallocate those have not been infected (they
-    //   are not intersecting faces). Uninfect those have been infected.
-    //   After this loop, only intersecting faces remain.
-    subfaces->traversalinit();
-    shloop.sh = shellfacetraverse(subfaces);
-    while (shloop.sh != (shellface *) NULL) {
-      if (sinfected(shloop)) {
-        suninfect(shloop);
-      } else {
-        shellfacedealloc(subfaces, shloop.sh);
-      }
-      shloop.sh = shellfacetraverse(subfaces);
-    }
-  } else {
-    // Deallocate all subfaces.
-    subfaces->restart();
-  }
-}
-
-//
-// Begin of periodic boundary condition routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// createsubpbcgrouptable()    Create the 'subpbcgrouptable'.                //
-//                                                                           //
-// Allocate the memory for 'subpbcgrouptable'.  Each entry i (a pbcdata) of  //
-// the table represents a pbcgroup.  Most of the fields of a group-i are set //
-// in this routine. 'fmark[0]', 'fmark[1]', and 'transmat[0]' are directly   //
-// copied from the corresponding data of 'in->numberofpbcgroups'. 'transmat  //
-// [1]' is calculated as the inverse matrix of 'transmat[0]'.  'ss[0]' and   //
-// 'ss[1]' are initilized be 'dummysh'. They are set in 'trangulatefacet()'  //
-// (when -p is in use) or 'reconstructmesh()' (when -r is in use).           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::createsubpbcgrouptable()
-{
-  tetgenio::pbcgroup *pg;
-  pbcdata *pd;
-  REAL A[4][4], rhs[4], D;
-  int indx[4];
-  int i, j, k;
-
-  subpbcgrouptable = new pbcdata[in->numberofpbcgroups];
-  for (i = 0; i < in->numberofpbcgroups; i++) {
-    pg = &(in->pbcgrouplist[i]);
-    pd = &(subpbcgrouptable[i]);
-    // Copy data from pg to pd.
-    pd->fmark[0] = pg->fmark1;
-    pd->fmark[1] = pg->fmark2;
-    // Initialize array 'pd->ss'.
-    pd->ss[0].sh = dummysh;
-    pd->ss[1].sh = dummysh;
-    // Copy the transform matrix from pg to pd->transmat[0].
-    for (j = 0; j < 4; j++) {
-      for (k = 0; k < 4; k++) {
-        pd->transmat[0][j][k] = pg->transmat[j][k];
-        // Prepare for inverting the matrix.
-        A[j][k] = pg->transmat[j][k];
-      }
-    }
-    // Calculate the inverse matrix (pd->transmat[1]) of pd->transmat[0].
-    lu_decmp(A, 4, indx, &D, 0);
-    for (j = 0; j < 4; j++) {
-      for (k = 0; k < 4; k++) rhs[k] = 0.0;
-      rhs[j] = 1.0;
-      lu_solve(A, 4, indx, rhs, 0);
-      for (k = 0; k < 4; k++) pd->transmat[1][k][j] = rhs[k];
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getsubpbcgroup()    Get the pbcgroup of a subface.                        //
-//                                                                           //
-// 'pbcsub' has pbc defined. Its pbcgroup is returned in 'pd'. In addition,  //
-// 'f1' (0 or 1) indicates the position of 'pbcsub' in 'pd'; 'f2' (= 1 - f1) //
-// is the position where the symmetric subface of 'pbcsub' is found.         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::getsubpbcgroup(face* pbcsub, pbcdata** pd, int *f1, int *f2)
-{
-  int groupid, fmark, idx;
-
-  groupid = shellpbcgroup(*pbcsub);
-  *pd = &subpbcgrouptable[groupid];
-  
-  // Get the facet index (1 - based).
-  idx = shellmark(*pbcsub);
-  // Get the facet marker from array (0 - based).
-  fmark = in->facetmarkerlist[idx - 1];
-  if ((*pd)->fmark[0] == fmark) {
-    *f1 = 0;
-  } else {
-#ifdef SELF_CHECK
-    assert((*pd)->fmark[1] == fmark);
-#endif
-    *f1 = 1;
-  }
-  *f2 = 1 - (*f1);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getsubpbcsympoint()    Compute the symmetric point for a subface point.   //
-//                                                                           //
-// 'newpoint' lies on 'splitsub'. This routine calculates a 'sympoint' which //
-// locates on 'symsplitsub' and symmtric to 'newpoint'.  Return the location //
-// of sympoint wrt. symsplitsub.                                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::locateresult tetgenmesh:: getsubpbcsympoint(point newpoint,
-  face* splitsub, point sympoint, face* symsplitsub)
-{
-  pbcdata *pd;
-  face subloop;
-  point pa, pb, pc;
-  enum locateresult symloc;
-  REAL ori;
-  int f1, f2, i;
-
-  // Get the pbcgroup of 'splitsub'.
-  getsubpbcgroup(splitsub, &pd, &f1, &f2);
-      
-  // Transform newpoint from f1 -> f2.
-  for (i = 0; i < 3; i++) {
-    sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
-                + pd->transmat[f1][i][1] * newpoint[1]
-                + pd->transmat[f1][i][2] * newpoint[2]
-                + pd->transmat[f1][i][3] * 1.0;
-  }
-  // Locate sympoint in f2.
-  symloc = OUTSIDE;
-  *symsplitsub = pd->ss[f2];
-  // Is the stored subface valid? Hole removal may delete the subface.  
-  if ((symsplitsub->sh != dummysh) && !isdead(symsplitsub)) {
-    // 'symsplitsub' should lie on the symmetric facet. Check it.
-    i = shellmark(*symsplitsub);
-    if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
-      // 'symsplitsub' has the symmetric boundary marker.
-      pa = sorg(*symsplitsub);
-      pb = sdest(*symsplitsub);
-      pc = sapex(*symsplitsub);
-      // Test if they are (nearly) coplanar. Some facets may have the
-      //   same boundary marker but not coplanar with this point.
-      ori = orient3d(pa, pb, pc, sympoint);
-      if (iscoplanar(pa, pb, pc, sympoint, ori, b->epsilon * 1e+2)) {
-        // Locate sympoint in facet. Don't stop at subsegment.
-        abovepoint = facetabovepointarray[shellmark(*symsplitsub)];
-        if (abovepoint == (point) NULL) {
-          getfacetabovepoint(symsplitsub);
-        }
-        symloc = locatesub(sympoint, symsplitsub, 0, b->epsilon * 1e+2);
-      }
-    }
-  }
-  if (symloc == OUTSIDE) {
-    // Do a brute-force searching for the symmetric subface.
-    REAL epspp = b->epsilon * 1e+2;
-    int lcount = 0;
-    do {
-      // Locate sympoint in the pool of subfaces (with fmark pd->fmark[f2]).
-      subfaces->traversalinit();
-      subloop.sh = shellfacetraverse(subfaces);
-      while (subloop.sh != (shellface *) NULL) {
-        i = shellmark(subloop);
-        if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
-          // Found a facet have the symmetric boundary marker.
-          pa = sorg(subloop);
-          pb = sdest(subloop);
-          pc = sapex(subloop);
-          // Test if they are (nearly) coplanar. Some facets may have the
-          //   same boundary marker but not coplanar with this point.
-          ori = orient3d(pa, pb, pc, sympoint);
-          if (iscoplanar(pa, pb, pc, sympoint, ori, epspp)) {
-            // Test if sympoint is (nearly) inside this facet. 
-            // Get the abovepoint of the facet.
-            abovepoint = facetabovepointarray[shellmark(subloop)];
-            // Do we need to calculate the abovepoint?
-            if (abovepoint == (point) NULL) {
-              getfacetabovepoint(&subloop);
-            }
-            // subloop is on the facet, search sympoint.
-            symloc = locatesub(sympoint, &subloop, 0, epspp);
-            if (symloc != OUTSIDE) break;
-          }
-        }
-        subloop.sh = shellfacetraverse(subfaces);
-      }
-      lcount++;
-      epspp *= 10.0;
-    } while ((symloc == OUTSIDE) && (lcount < 3));
-#ifdef SELF_CHECK
-    // sympoint should be inside the facet.
-    assert(symloc != OUTSIDE);
-#endif
-    // Set the returning subface.
-    *symsplitsub = subloop;
-    // Update the stored subface for next searching.
-    pd->ss[f2] = *symsplitsub;
-  }
-
-  return adjustlocatesub(sympoint, symsplitsub, symloc, b->epsilon);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// createsegpbcgrouptable()    Create the 'segpbcgrouptable'.                //
-//                                                                           //
-// Each segment may belong to more than one pbcgroups.  For example, segment //
-// ab may need to be symmteric to both segments cd, and ef, then  ab and cd, //
-// cd and ef, ef and ab form three pbcgroups.                                //
-//                                                                           //
-// 'segpbcgrouptable' is  implemented as a list of pbcdatas. Each item i is  //
-// a pbcgroup.                                                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::createsegpbcgrouptable()
-{
-  shellface** segsperverlist;
-  pbcdata *pd, *ppd, pd1, pd2;
-  face segloop, symseg;
-  face startsh, spinsh, symsh;
-  point pa, pb, syma, symb;
-  enum locateresult symloc;
-  REAL testpt[3], sympt[3];
-  bool inflag;
-  int *idx2seglist;
-  int segid1, segid2;
-  int f1, f2;
-  int i, j, k, l;
-
-  // Allocate memory for 'subpbcgrouptable'.
-  segpbcgrouptable = new list(sizeof(pbcdata), NULL, 256);
-
-  if (b->refine) {
-    // Create a point-to-seg map for quickly finding PBC seg pairs.
-    makesegmentmap(idx2seglist, segsperverlist);
-  }
-
-  // Loop through the segment list.
-  subsegs->traversalinit();
-  segloop.sh = shellfacetraverse(subsegs);
-  while (segloop.sh != (shellface *) NULL) {
-    // Loop the subface ring of segloop ab.
-    pa = sorg(segloop);
-    pb = sdest(segloop);
-    segid1 = shellmark(segloop);
-    spivot(segloop, startsh);
-    spinsh = startsh;
-    do {
-      // Adjust spinsh be edge ab.
-      if (sorg(spinsh) != pa) {
-        sesymself(spinsh);
-      }
-      // Does spinsh belong to a pbcgroup?
-      if (shellpbcgroup(spinsh) != -1) {
-        // Yes! There exists a segment cd. ab and cd form a pbcgroup.
-        if (b->refine) {
-          getsubpbcgroup(&spinsh, &pd, &f1, &f2);
-          // Transform pa from f1 -> f2.
-          for (i = 0; i < 3; i++) {
-            sympt[i] = pd->transmat[f1][i][0] * pa[0]
-                     + pd->transmat[f1][i][1] * pa[1]
-                     + pd->transmat[f1][i][2] * pa[2]
-                     + pd->transmat[f1][i][3] * 1.0;
-          }
-          syma = point2pbcpt(pa);
-          // Is 'sympt == syma'?
-          if (distance(sympt, syma) > (longest * b->epsilon)) {
-            // No. Search the symmetric vertex of pa.
-            symloc = getsubpbcsympoint(pa, &spinsh, sympt, &symsh);
-            syma = sorg(symsh);
-            if (symloc != ONVERTEX) {
-              // Do a brute force search. Not done yet.
-              assert(0);
-            }
-          }
-          // Transform pb from f1 -> f2.
-          for (i = 0; i < 3; i++) {
-            sympt[i] = pd->transmat[f1][i][0] * pb[0]
-                     + pd->transmat[f1][i][1] * pb[1]
-                     + pd->transmat[f1][i][2] * pb[2]
-                     + pd->transmat[f1][i][3] * 1.0;
-          }
-          // Search sym subface from the point-to-subface map.
-          symseg.shver = 0;
-          j = pointmark(syma) - in->firstnumber;
-          for (i = idx2seglist[j]; i < idx2seglist[j + 1]; i++) {
-            symseg.sh = segsperverlist[i];
-            if (sorg(symseg) == syma) symb = sdest(symseg);
-            else symb = sorg(symseg);
-            if (distance(sympt, symb) <= (longest * b->epsilon)) break;
-          }
-          assert(i < idx2seglist[j + 1]);
-        } else {
-          //   'testpt' is the midpoint of ab used to find cd.
-          for (i = 0; i < 3; i++) testpt[i] = 0.5 * (pa[i] + pb[i]);
-          symloc = getsubpbcsympoint(testpt, &spinsh, sympt, &symsh);
-#ifdef SELF_CHECK
-          assert(symloc == ONEDGE);
-#endif
-          sspivot(symsh, symseg);
-        }
-#ifdef SELF_CHECK
-        assert(symseg.sh != dummysh);
-#endif
-        // Check whether this group has already been created in list.
-        segid2 = shellmark(symseg);
-        inflag = false;
-        for (i = 0; i < segpbcgrouptable->len() && !inflag; i++) {
-          pd = (pbcdata *)(* segpbcgrouptable)[i];
-          if (pd->segid[0] == segid1) {
-            if (pd->segid[1] == segid2) inflag = true;
-          } else if (pd->segid[0] == segid2) {
-            if (pd->segid[1] == segid1) inflag = true;
-          }
-        }
-        if (!inflag) {
-          // Create a segment pbcgroup in list for ab and cd.
-          pd = (pbcdata *) segpbcgrouptable->append(NULL);
-          // Save the markers of ab and cd.
-          pd->segid[0] = segid1;
-          pd->segid[1] = segid2;
-          // Save the handles of ab and cd.
-          pd->ss[0] = segloop;
-          pd->ss[1] = symseg;
-          // Find the map from ab to cd.
-          getsubpbcgroup(&spinsh, &ppd, &f1, &f2);
-          pd->fmark[0] = ppd->fmark[f1];
-          pd->fmark[1] = ppd->fmark[f2];
-          // Set the map from ab to cd.
-          for (i = 0; i < 4; i++) {
-            for (j = 0; j < 4; j++) {
-              pd->transmat[0][i][j] = ppd->transmat[f1][i][j];
-            }
-          }
-          // Set the map from cd to ab.
-          for (i = 0; i < 4; i++) {
-            for (j = 0; j < 4; j++) {
-              pd->transmat[1][i][j] = ppd->transmat[f2][i][j];
-            }
-          }
-        }
-      }
-      // Go to the next subface in the ring of ab.
-      spivotself(spinsh);
-    } while (spinsh.sh != startsh.sh);
-    segloop.sh = shellfacetraverse(subsegs);
-  }
-  
-  if (b->refine) {
-    delete [] segsperverlist;
-    delete [] idx2seglist;
-  }
-
-  // Create the indirect segment pbcgroups.
-  // Bug-fixed (08 Sept. 2006). The total size of 'segpbcgrouptable' may get
-  //   increased. Do not use pointers for 'pd1' and 'pd2'. The addresses may
-  //   be invaild after realloc().
-  for (i = 0; i < segpbcgrouptable->len(); i++) {
-    pd1 = * (pbcdata *)(* segpbcgrouptable)[i];
-    for (f1 = 0; f1 < 2; f1++) {
-      // Search for a group (except i) contains pd1.segid[f1].
-      for (j = 0; j < segpbcgrouptable->len(); j++) {
-        if (j == i) continue;
-        pd2 = * (pbcdata *)(* segpbcgrouptable)[j];
-        f2 = -1;
-        if (pd1.segid[f1] == pd2.segid[0]) {
-          f2 = 0;
-        } else if (pd1.segid[f1] == pd2.segid[1]) {
-          f2 = 1;
-        }
-        if (f2 != -1) {
-#ifdef SELF_CHECK
-          assert(pd1.segid[f1] == pd2.segid[f2]);
-#endif
-          segid1 = pd1.segid[1 - f1];
-          segid2 = pd2.segid[1 - f2];
-          // Search for the existence of segment pbcgroup (segid1, segid2).
-          inflag = false;
-          for (k = 0; k < segpbcgrouptable->len() && !inflag; k++) {
-            pd = (pbcdata *)(* segpbcgrouptable)[k];
-            if (pd->segid[0] == segid1) {
-              if (pd->segid[1] == segid2) inflag = true;
-            } else if (pd->segid[0] == segid2) {
-              if (pd->segid[1] == segid1) inflag = true;
-            }
-          }
-          if (!inflag) {
-            pd = (pbcdata *) segpbcgrouptable->append(NULL);
-            pd->segid[0] = pd1.segid[1 - f1];
-            pd->segid[1] = pd2.segid[1 - f2];
-            pd->ss[0] = pd1.ss[1 - f1];
-            pd->ss[1] = pd2.ss[1 - f2];
-            // Invalid the fmark[0] == fmark[1].
-            pd->fmark[0] = pd->fmark[1] = 0;
-            // Translate matrix pd->transmat[0] = m2 * m1, where m1 =
-            //   pd1.transmat[1 - f1], m2 = pd2.transmat[f2].
-            for (k = 0; k < 4; k++) {
-              for (l = 0; l < 4; l++) { 
-                pd->transmat[0][k][l] = pd2.transmat[f2][k][l];
-              }
-            }
-            m4xm4(pd->transmat[0], pd1.transmat[1 - f1]);
-            // Translate matrix pd->transmat[1] = m4 * m3, where m3 =
-            //   pd2.transmat[1 - f2], m4 = pd1.transmat[f1].
-            for (k = 0; k < 4; k++) {
-              for (l = 0; l < 4; l++) { 
-                pd->transmat[1][k][l] = pd1.transmat[f1][k][l];
-              }
-            }
-            m4xm4(pd->transmat[1], pd2.transmat[1 - f2]);
-          }
-        }
-      }
-    }
-  }
-
-  // Form a map from segment index to pbcgroup list of this segment.
-  idx2segpglist = new int[subsegs->items + 1];
-  for (i = 0; i < subsegs->items + 1; i++) idx2segpglist[i] = 0;
-  // Loop through 'segpbcgrouptable', counter the number of pbcgroups of
-  //   each segment.
-  for (i = 0; i < segpbcgrouptable->len(); i++) {
-    pd = (pbcdata *)(* segpbcgrouptable)[i];
-    for (j = 0; j < 2; j++) {
-      k = pd->segid[j] - 1;
-      idx2segpglist[k]++;
-    }
-  }
-  // Calculate the total length of array 'segpglist'.
-  j = idx2segpglist[0];
-  idx2segpglist[0] = 0;  // Array starts from 0 element.
-  for (i = 0; i < subsegs->items; i++) {
-    k = idx2segpglist[i + 1];
-    idx2segpglist[i + 1] = idx2segpglist[i] + j;
-    j = k;
-  }
-  // The total length is in the last unit of idx2segpglist.
-  segpglist = new int[idx2segpglist[i]];
-  // Loop the set of pbcgroups again, set the data into segpglist.
-  for (i = 0; i < segpbcgrouptable->len(); i++) {
-    pd = (pbcdata *)(* segpbcgrouptable)[i];
-    for (j = 0; j < 2; j++) {
-      k = pd->segid[j] - 1;
-      segpglist[idx2segpglist[k]] = i;
-      idx2segpglist[k]++;
-    }
-  }
-  // Contents in 'idx2segpglist' are shifted, now shift them back.
-  for (i = subsegs->items - 1; i >= 0; i--) {
-    idx2segpglist[i + 1] = idx2segpglist[i];
-  }
-  idx2segpglist[0] = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getsegpbcsympoint()    Compute the symmetric point for a segment point.   //
-//                                                                           //
-// 'newpoint' lies on 'splitseg'. This routine calculates a 'sympoint' which //
-// locates on 'symsplitseg' and symmtric to 'newpoint'.  Return the location //
-// of sympoint wrt. symsplitseg.                                             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::locateresult tetgenmesh::
-getsegpbcsympoint(point newpoint, face* splitseg, point sympoint,
-                  face* symsplitseg, int groupid)
-{
-  pbcdata *pd;
-  enum locateresult symloc;
-  int segid, f1, f2, i;
-
-  pd = (pbcdata *)(* segpbcgrouptable)[groupid];
-  segid = shellmark(*splitseg);
-  if (pd->segid[0] == segid) {
-    f1 = 0;
-  } else {
-#ifdef SELF_CHECK
-    assert(pd->segid[1] == segid);
-#endif
-    f1 = 1;
-  }
-  f2 = 1 - f1;
-
-  // Transform newpoint from f1 -> f2.
-  for (i = 0; i < 3; i++) {
-    sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
-                + pd->transmat[f1][i][1] * newpoint[1]
-                + pd->transmat[f1][i][2] * newpoint[2]
-                + pd->transmat[f1][i][3] * 1.0;
-  }
-  // Locate sympoint in f2.
-  *symsplitseg = pd->ss[f2];
-#ifdef SELF_CHECK
-  assert(symsplitseg->sh != dummysh);
-#endif
-  // Locate sympoint in facet. Stop at subsegment.
-  symloc = locateseg(sympoint, symsplitseg);
-  symloc = adjustlocateseg(sympoint, symsplitseg, symloc, b->epsilon * 1e+2);
-  return symloc;
-}
-
-//
-// End of periodic boundary condition routines
-//
-
-//
-// Begin of vertex perturbation routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// randgenerator()    Generate a random REAL number between (0, |range|).    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-REAL tetgenmesh::randgenerator(REAL range)
-{
-  REAL worknumber, result;
-  int expo;
-
-  if (range == 0.0) return 0.0;
-
-  expo = 0;
-  worknumber = fabs(range);
-  // Normalize worknumber (i.e., 1.xxxExx)
-  if (worknumber > 10.0) {
-    while (worknumber > 10.0) {
-      worknumber /= 10.0;
-      expo++;
-    }
-  } else if (worknumber < 1.0) {
-    while (worknumber < 1.0) {
-      worknumber *= 10.0;
-      expo--;
-    }
-  }
-#ifdef SELF_CHECK
-  assert(worknumber >= 1.0 && worknumber <= 10.0);
-#endif
-
-  // Enlarge worknumber 1000 times.
-  worknumber *= 1e+3;
-  expo -= 3;
-  // Generate a randome number between (0, worknumber).
-  result = (double) randomnation((int) worknumber);
-  
-  // Scale result back into the original size.
-  if (expo > 0) {
-    while (expo != 0) {
-      result *= 10.0;
-      expo--;
-    }
-  } else if (expo < 0) {
-    while (expo != 0) {
-      result /= 10.0;
-      expo++;
-    }
-  }
-#ifdef SELF_CHECK
-  assert((result >= 0.0) && (result <= fabs(range)));
-#endif
-
-  return result;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checksub4cocir()    Test a subface to find co-circular pair of subfaces.  //
-//                                                                           //
-// 'eps' is a relative tolerance for testing approximately cospherical case. //
-// Set it to zero if only exact test is desired.                             //
-//                                                                           //
-// An edge(not a segment) of 'testsub' is locally degenerate if the opposite //
-// vertex of the adjacent subface is cocircular with the vertices of testsub.//
-// If 'once' is TRUE, operate on the edge only if the pointer 'testsub->sh'  //
-// is smaller than its neighbor (for each edge is considered only once).     //
-//                                                                           //
-// Return TRUE if find an edge of testsub is locally degenerate.             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::checksub4cocir(face* testsub, REAL eps, bool once,
-  bool enqflag)
-{
-  badface *cocirsub;
-  face subloop, neighsub;
-  face checkseg;
-  point pa, pb, pc, pd;
-  REAL sign;
-  int i;
-  
-  subloop = *testsub;
-  subloop.shver = 0; // Keep the CCW orientation.
-  // Get the abovepoint of the facet.
-  abovepoint = facetabovepointarray[shellmark(subloop)];
-  // Do we need to calculate the abovepoint?
-  if (abovepoint == (point) NULL) {
-    getfacetabovepoint(&subloop);
-  }
-  // Check the three edges of subloop.
-  for (i = 0; i < 3; i++) {
-    sspivot(subloop, checkseg);
-    if (checkseg.sh == dummysh) {
-      // It is not a segment, get the adjacent subface.
-      spivot(subloop, neighsub);
-      // assert(neighsub.sh != dummysh);
-      if (!once || (once && (neighsub.sh > subloop.sh))) {
-        pa = sorg(subloop);
-        pb = sdest(subloop);
-        pc = sapex(subloop);
-        pd = sapex(neighsub);
-        sign = insphere(pa, pb, pc, abovepoint, pd);
-        if ((sign != 0.0) && (eps > 0.0)) {
-          if (iscospheric(pa, pb, pc, abovepoint, pd, sign, eps)) sign = 0.0;
-        }
-        if (sign == 0.0) {
-          // It's locally degenerate!
-          if (enqflag && badsubfaces != (memorypool *) NULL) {
-            // Save it.
-            cocirsub = (badface *) badsubfaces->alloc();
-            cocirsub->ss = subloop;
-            cocirsub->forg = pa;
-            cocirsub->fdest = pb;
-            cocirsub->fapex = pc;
-            cocirsub->foppo = pd;
-            setshell2badface(cocirsub->ss, cocirsub);
-          }
-          if (b->verbose > 1) {
-            printf("    Found set (%d, %d, %d, %d).\n", pointmark(pa),
-                   pointmark(pb), pointmark(pc), pointmark(pd));
-          }
-          return true;
-        }
-      }
-    }
-    senextself(subloop);
-  }
-
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tallcocirsubs()    Find all co-circular subfaces and save them in list.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::tallcocirsubs(REAL eps, bool enqflag)
-{
-  face subloop;
-
-  // Loop over all subfaces.
-  subfaces->traversalinit();
-  subloop.sh = shellfacetraverse(subfaces);
-  while (subloop.sh != (shellface *) NULL) {
-    checksub4cocir(&subloop, eps, true, enqflag);
-    subloop.sh = shellfacetraverse(subfaces);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tallencsegsfsubs()    Check for encroached segs from a list of subfaces.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::tallencsegsfsubs(point testpt, list* cavsublist)
-{
-  face startsub, checkseg;
-  long oldencnum;
-  int i, j;
-
-  // Remember the current number of encroached segments.
-  oldencnum = badsubsegs->items;
-
-  // Check segments in the list of subfaces.
-  for (i = 0; i < cavsublist->len(); i++) {
-    startsub = * (face *)(* cavsublist)[i];
-    // Test all three edges of startsub.
-    for (j = 0; j < 3; j++) {
-      sspivot(startsub, checkseg);
-      if (checkseg.sh != dummysh) {
-        if (!shell2badface(checkseg)) {
-          checkseg4encroach(&checkseg, testpt, NULL, true);
-        }
-      }
-      senextself(startsub);
-    }
-  }
-
-  return (badsubsegs->items > oldencnum);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// collectflipedges()    Collect edges of split subfaces for flip checking.  //
-//                                                                           //
-// 'inspoint' is a newly inserted segment point (inserted by insertsite()).  //
-// 'splitseg' is one of the two split subsegments. Some subfaces may be non- //
-// Delaunay since they're still not bonded to CDT. This routine collect all  //
-// such possible subfaces in 'flipqueue'.                                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::
-collectflipedges(point inspoint, face* splitseg, queue* flipqueue)
-{
-  face startsh, spinsh, checksh;
-  face nextseg;
-  point pa, pb;
-
-  // Let the dest of splitseg be inspoint.
-  splitseg->shver = 0;
-  if (sdest(*splitseg) != inspoint) {
-    sesymself(*splitseg);
-  }
-#ifdef SELF_CHECK
-  assert(sdest(*splitseg) == inspoint);
-#endif
-  pa = sorg(*splitseg);
-  spivot(*splitseg, startsh);
-  spinsh = startsh;
-  do {
-    findedge(&spinsh, pa, inspoint);
-    senext2(spinsh, checksh);
-    enqueueflipedge(checksh, flipqueue);
-    spivotself(spinsh);
-  } while (spinsh.sh != startsh.sh);
-
-  // Get the next subsegment.
-  senext(*splitseg, nextseg);
-  spivotself(nextseg);
-#ifdef SELF_CHECK
-  assert(nextseg.sh != (shellface *) NULL);
-#endif
-  
-  // Let the org of nextseg be inspoint.
-  nextseg.shver = 0;
-  if (sorg(nextseg) != inspoint) {
-    sesymself(nextseg);
-  }
-#ifdef SELF_CHECK
-  assert(sorg(nextseg) == inspoint);
-#endif
-  pb = sdest(nextseg);
-  spivot(nextseg, startsh);
-  spinsh = startsh;
-  do {
-    findedge(&spinsh, inspoint, pb);
-    senext(spinsh, checksh);
-    enqueueflipedge(checksh, flipqueue);
-    spivotself(spinsh);
-  } while (spinsh.sh != startsh.sh);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// perturbrepairencsegs()    Repair all encroached segments.                 //
-//                                                                           //
-// All encroached segments are stored in 'badsubsegs'.  Each segment will be //
-// split by adding a perturbed point near its circumcenter.                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::perturbrepairencsegs(queue* flipqueue)
-{
-  badface *encloop;
-  tetrahedron encodedtet;
-  triface splittet;
-  face splitsub, symsplitsub;
-  face splitseg, symsplitseg;
-  point newpoint, sympoint;
-  point pa, pb, pc;
-  enum insertsiteresult success;
-  enum locateresult loc, symloc;
-  REAL cent[3], d1, ps, rs;
-  int i, j;
-
-  // Note that steinerleft == -1 if an unlimited number of Steiner points 
-  //   is allowed.  Loop until 'badsubsegs' is empty.
-  badsubsegs->traversalinit();
-  encloop = badfacetraverse(badsubsegs);
-  while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
-    splitseg = encloop->ss;
-#ifdef SELF_CHECK
-    assert(shell2badface(splitseg) == encloop);
-#endif
-    setshell2badface(splitseg, NULL);
-    pa = sorg(splitseg);
-    pb = sdest(splitseg);
-    if ((pa == encloop->forg) && (pb == encloop->fdest)) {
-      if (b->verbose > 1) {
-        printf("  Get seg (%d, %d).\n", pointmark(pa), pointmark(pb));
-      }
-      // Create the newpoint.
-      makepoint(&newpoint);
-      // Get the circumcenter and radius of ab.
-      for (i = 0; i < 3; i++) cent[i] = 0.5 * (pa[i] + pb[i]);
-      d1 = 0.5 * distance(pa, pb);
-      // Add a random perturbation to newpoint along the vector ab.
-      ps = randgenerator(d1 * 1.0e-3);
-      rs = ps / d1;
-      // Set newpoint (be at the perturbed circumcenter of ab).
-      for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
-      setpointtype(newpoint, FREESEGVERTEX);
-      // Set splitseg into the newpoint.
-      setpoint2sh(newpoint, sencode(splitseg));        
-
-      // Is there periodic boundary condition?
-      if (checkpbcs) {
-        // Insert points on other segments of incident pbcgroups.
-        i = shellmark(splitseg) - 1;
-        for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
-          makepoint(&sympoint);
-          symloc = getsegpbcsympoint(newpoint, &splitseg, sympoint,
-                                     &symsplitseg, segpglist[j]);
-#ifdef SELF_CHECK
-          assert(symloc != OUTSIDE);
-#endif
-          // Note: the symsplitseg and splitseg may be identical, in case
-          //   when the the splitseg is the axis of the rotational sym.
-          if ((symloc == ONEDGE) && (symsplitseg.sh != splitseg.sh)) {
-            setpointtype(sympoint, FREESEGVERTEX);
-            setpoint2sh(sympoint, sencode(symsplitseg));
-            // Insert sympoint into DT.
-            pc = sorg(symsplitseg);
-            splittet.tet = dummytet;
-            // Find a good start point to search.
-            encodedtet = point2tet(pc);
-            if (encodedtet != (tetrahedron) NULL) {
-              decode(encodedtet, splittet);
-              if (isdead(&splittet)) {
-                splittet.tet = dummytet; 
-              }
-            }
-            // Locate sympoint in DT.  Do exact location.
-            success = insertsite(sympoint, &splittet, false, flipqueue);
-#ifdef SELF_CHECK
-            assert(success != DUPLICATEPOINT);
-#endif
-            if (success == OUTSIDEPOINT) {
-              inserthullsite(sympoint, &splittet, flipqueue);
-            }
-            if (steinerleft > 0) steinerleft--;
-            // Let sympoint remember splittet.
-            setpoint2tet(sympoint, encode(splittet));
-            // Do flip in DT.
-            flip(flipqueue, NULL);
-            // Insert sympoint into F.
-            symloc = locateseg(sympoint, &symsplitseg);
-            if (symloc == ONEDGE) {
-              symsplitseg.shver = 0;
-              spivot(symsplitseg, symsplitsub);
-              // sympoint should on the edge of symsplitsub.
-              splitsubedge(sympoint, &symsplitsub, flipqueue);
-            } else {
-              // insertsite() has done the whole job.
-#ifdef SELF_CHECK
-              assert(symloc == ONVERTEX);
-              assert(checksubfaces);
-#endif
-              // Some edges may need to be flipped.
-              collectflipedges(sympoint, &symsplitseg, flipqueue);
-            }
-            // Do flip in facet.
-            flipsub(flipqueue);
-          } else { // if (symloc == ONVERTEX) {
-            // The symmtric point already exists. It is possible when two
-            //   pbc group are idebtical. Omit sympoint.
-            pointdealloc(sympoint);
-          }
-        }
-      }
-
-      // Insert newpoint into DT.
-      splittet.tet = dummytet;
-      // Find a good start point to search.
-      encodedtet = point2tet(pa);
-      if (encodedtet != (tetrahedron) NULL) {
-        decode(encodedtet, splittet);
-        if (isdead(&splittet)) {
-          splittet.tet = dummytet; 
-        }
-      }
-      if (splittet.tet == dummytet) { // Try pb.
-        encodedtet = point2tet(pb);
-        if (encodedtet != (tetrahedron) NULL) {
-          decode(encodedtet, splittet);
-          if (isdead(&splittet)) {
-            splittet.tet = dummytet;
-          }
-        }
-      }
-      // Locate the newpoint in DT.  Do exact location.
-      success = insertsite(newpoint, &splittet, false, flipqueue);
-#ifdef SELF_CHECK
-      assert(success != DUPLICATEPOINT);
-#endif
-      if (success == OUTSIDEPOINT) {
-        // A convex hull edge is mssing, and the inserting point lies
-        //   (slightly) outside the convex hull due to the significant
-        //   digits lost in the calculation. Enlarge the convex hull.
-        inserthullsite(newpoint, &splittet, flipqueue);
-      }
-      if (steinerleft > 0) steinerleft--;
-      // Let newpoint remember splittet.
-      setpoint2tet(newpoint, encode(splittet));
-      // Do flip in DT.
-      flip(flipqueue, NULL);
-      // Insert newpoint into F.
-      loc = locateseg(newpoint, &splitseg);
-      if (loc == ONEDGE) {
-        splitseg.shver = 0;
-        spivot(splitseg, splitsub);
-        // newpoint should on the edge of splitsub.
-        splitsubedge(newpoint, &splitsub, flipqueue);
-      } else {
-        // insertsite() has done the whole job.
-#ifdef SELF_CHECK
-        assert(loc == ONVERTEX);
-        assert(checksubfaces);
-#endif
-        // Some edges may need to be flipped.
-        collectflipedges(newpoint, &splitseg, flipqueue);
-      }
-      // Do flip in facet.
-      flipsub(flipqueue);
-    }
-    // Remove this entry from list.
-    badfacedealloc(badsubsegs, encloop);  
-    // Get the next encroached segments.
-    encloop = badfacetraverse(badsubsegs);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// perturbrepairencsubs()    Repair all encroached subfaces.                 //
-//                                                                           //
-// All encroached subfaces are stored in 'badsubfaces'. Each subface will be //
-// split by adding a perturbed point near its circumcenter. However, if the  //
-// point encroaches some segments, it will not be inserted.  Instead, the    //
-// encroached segments are split.                                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::perturbrepairencsubs(list* cavsublist, queue* flipqueue)
-{
-  badface *encloop, *encsubseg;
-  tetrahedron encodedtet;
-  triface splittet;
-  face splitsub, symsplitsub;
-  face checkseg, symsplitseg;
-  point newpoint, sympoint;
-  point pa, pb, pc, pd;
-  enum insertsiteresult success;
-  enum locateresult loc, symloc;
-  REAL cent[3], d1, ps, rs;
-  bool reject;
-  int i;
-
-  // Note that steinerleft == -1 if an unlimited number of Steiner points
-  //   is allowed.  Loop until the list 'badsubfaces' is empty.
-  while ((badsubfaces->items > 0) && (steinerleft != 0)) {
-    badsubfaces->traversalinit();
-    encloop = badfacetraverse(badsubfaces);
-    while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
-      splitsub = encloop->ss;
-#ifdef SELF_CHECK
-      assert(shell2badface(splitsub) == encloop);
-#endif
-      setshell2badface(splitsub, NULL);
-      pa = sorg(splitsub);
-      pb = sdest(splitsub);
-      pc = sapex(splitsub);
-      // The subface may be not the same one when it was determined to be
-      //   encroached.  If its adjacent encroached subface was split, the
-      //   consequent flips may change it into another subface.
-      if ((pa == encloop->forg) && (pb == encloop->fdest) &&
-          (pc == encloop->fapex)) {
-        if (b->verbose > 1) {
-          printf("  Get subface (%d, %d, %d).\n", pointmark(pa),
-                 pointmark(pb), pointmark(pc));
-        }
-        // Create the newpoint.
-        makepoint(&newpoint);
-        // Get the circumcenter of abc.
-        circumsphere(pa, pb, pc, NULL, cent, &d1);
-#ifdef SELF_CHECK
-        assert(d1 > 0.0);
-#endif
-        // Add a random perturbation to newpoint along the vector a->cent.
-        //   This way, the perturbed point still lies in the plane of abc.
-        ps = randgenerator(d1 * 1.0e-3);
-        rs = ps / d1;
-        // Set newpoint (be at the perturbed circumcenter of abc).
-        for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
-        // Get the abovepoint of the facet.
-        abovepoint = facetabovepointarray[shellmark(splitsub)];
-        // Do we need to calculate the abovepoint?
-        if (abovepoint == (point) NULL) {
-          getfacetabovepoint(&splitsub);
-        }
-        loc = locatesub(newpoint, &splitsub, 1, 0.0);
-#ifdef SELF_CHECK
-        assert(loc != ONVERTEX);
-#endif
-        if (loc != OUTSIDE) {
-          // Add 'splitsub' into 'cavsublist'.
-          cavsublist->append(&splitsub);
-          // Collect all subfaces that encroached by newpoint.
-          collectcavsubs(newpoint, cavsublist);
-          // Find if there are encroached segments.
-          reject = tallencsegsfsubs(newpoint, cavsublist);
-          // Clear cavsublist for the next use.
-          cavsublist->clear();
-        } else {
-          // newpoint lies outside. splitsub contains the boundary segment.
-          sspivot(splitsub, checkseg);
-#ifdef SELF_CHECK
-          assert(checkseg.sh != dummysh);
-#endif
-          // Add this segment into list for splitting.
-          if (b->verbose > 2) {
-            printf("    Queuing boundary segment (%d, %d).\n",
-                   pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
-          }
-          encsubseg = (badface *) badsubsegs->alloc();
-          encsubseg->ss = checkseg;
-          encsubseg->forg = sorg(checkseg);
-          encsubseg->fdest = sdest(checkseg);
-          encsubseg->foppo = (point) NULL;
-          setshell2badface(encsubseg->ss, encsubseg);
-          // Reject newpoint.
-          reject = true;
-        }
-
-        if (!reject) {
-          // newpoint is going to be inserted.
-          
-          // Is there periodic boundary condition?
-          if (checkpbcs) {
-            if (shellpbcgroup(splitsub) >= 0) {
-              // Insert a point on another facet of the pbcgroup.
-              makepoint(&sympoint);
-              // Note: 'abovepoint' will be changed.
-              symloc = getsubpbcsympoint(newpoint, &splitsub, sympoint,
-                                         &symsplitsub);
-#ifdef SELF_CHECK
-              assert(symloc != ONVERTEX);
-#endif
-              setpoint2pbcpt(newpoint, sympoint);
-              setpoint2pbcpt(sympoint, newpoint);
-              setpointtype(sympoint, FREESUBVERTEX);
-              // setpoint2sh(sympoint, sencode(symsplitsub));
-              // Insert sympoint into DT.
-              pd = sorg(symsplitsub);
-              splittet.tet = dummytet;
-              // Find a good start point to search.
-              encodedtet = point2tet(pd);
-              if (encodedtet != (tetrahedron) NULL) {
-                decode(encodedtet, splittet);
-                if (isdead(&splittet)) {
-                  splittet.tet = dummytet; 
-                }
-              }
-              // Locate sympoint in DT.  Do exact location.
-              success = insertsite(sympoint, &splittet, false, flipqueue);
-#ifdef SELF_CHECK
-              assert(success != DUPLICATEPOINT);
-#endif
-              if (success == OUTSIDEPOINT) {
-                inserthullsite(sympoint, &splittet, flipqueue);
-              }
-              if (steinerleft > 0) steinerleft--;
-              // Let sympoint remember splittet.
-              setpoint2tet(sympoint, encode(splittet));
-              // Do flip in DT.
-              flip(flipqueue, NULL);
-              // Insert sympoint into F.
-              // getabovepoint(&symsplitsub);
-              // symloc = locatesub(sympoint, &symsplitsub, 1, 0.0);
-              if (symloc == ONFACE) {
-                splitsubface(sympoint, &symsplitsub, flipqueue);
-              } else if (symloc == ONEDGE) {
-                splitsubedge(sympoint, &symsplitsub, flipqueue);
-              } else {
-                // 'insertsite()' has done the whole job.
-#ifdef SELF_CHECK
-                assert(symloc == ONVERTEX);
-                assert(checksubfaces);
-#endif
-                // Split subfaces have been flipped.
-                flipqueue->clear();
-              }
-              // Do flip in facet.
-              flipsub(flipqueue);
-            }
-          }
-
-          // Insert newpoint into DT.
-          splittet.tet = dummytet;
-          // Find a good start point to search.
-          encodedtet = point2tet(pa);
-          if (encodedtet != (tetrahedron) NULL) {
-            decode(encodedtet, splittet);
-            if (isdead(&splittet)) {
-              splittet.tet = dummytet; 
-            }
-          }
-          if (splittet.tet == dummytet) { // Try pb.
-            encodedtet = point2tet(pb);
-            if (encodedtet != (tetrahedron) NULL) {
-              decode(encodedtet, splittet);
-              if (isdead(&splittet)) {
-                splittet.tet = dummytet;
-              }
-            }
-          }
-          // Locate the newpoint in DT.  Do exact location.
-          success = insertsite(newpoint, &splittet, false, flipqueue);
-#ifdef SELF_CHECK
-          assert(success != DUPLICATEPOINT);
-#endif
-          if (success == OUTSIDEPOINT) {
-            inserthullsite(newpoint, &splittet, flipqueue);
-          }
-          if (steinerleft > 0) steinerleft--;
-          // Let newpoint remember splittet.
-          setpoint2tet(newpoint, encode(splittet));
-          // Do flip in DT.
-          flip(flipqueue, NULL);
-          // Insert newpoint into F.
-          // if (checkpbcs) {
-            // 'abovepoint' has been changed.
-            // getabovepoint(&splitsub);
-            // loc = locatesub(newpoint, &splitsub, 1, 0.0);
-          // }
-          if (loc == ONFACE) {
-            // Insert the newpoint in facet.
-            splitsubface(newpoint, &splitsub, flipqueue);
-          } else if (loc == ONEDGE) {
-            // Insert the newpoint in facet.
-            splitsubedge(newpoint, &splitsub, flipqueue);
-          } else {
-            // 'insertsite()' has done the whole job.
-#ifdef SELF_CHECK
-            assert(loc == ONVERTEX);
-            assert(checksubfaces);
-#endif
-            // Split subfaces have been flipped.
-            flipqueue->clear();
-          }
-          // Set the type of the newpoint.
-          setpointtype(newpoint, FREESUBVERTEX);
-          // Set splitsub into the newpoint.
-          // setpoint2sh(newpoint, sencode(splitsub));
-          // Do flip in the facet.
-          flipsub(flipqueue);
-
-          // Remove this entry from list.
-          badfacedealloc(badsubfaces, encloop);
-        } else {
-          // newpoint is rejected. Remove it from points.
-          pointdealloc(newpoint);
-          // Repair all encroached segments.
-          perturbrepairencsegs(flipqueue);
-          // Do not remove 'encloop'. Later it will be tested again.
-          setshell2badface(encloop->ss, encloop);
-        }
-      } else {
-        // This subface has been changed. Remove this entry from list.
-        badfacedealloc(badsubfaces, encloop);
-        // It may be co-circular with its neighbors.
-        // checksub4cocir(&splitsub, eps, false, true); 
-      }
-      // Get the next encroached subfaces.
-      encloop = badfacetraverse(badsubfaces);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// incrperturbvertices()    Remove the local degeneracies in DT.             //
-//                                                                           //
-// A local degeneracy of a DT D is a set of 5 or more vertices which share a //
-// common sphere S and no other vertex of D in S.  D is not unique if it has //
-// local degeneracies. This routine removes the local degeneracies from D by //
-// inserting break points (as described in reference [2]).                   //
-//                                                                           //
-// 'eps' is a user-provided error tolerance. It is used to detect whether or //
-// not five points are approximate cospherical (evaluated in iscospheric()). //
-// Set it to 0.0 to disable it, i.e., only test pure degenerate point set.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::incrperturbvertices(REAL eps)
-{
-  queue *flipqueue;
-  list *cavsublist;
-  long vertcount;
-
-  if (!b->quiet) {
-    printf("Perturbing vertices.\n");
-  }
-
-  vertcount = points->items;
-  // Create a map from points to tets for fastening search.
-  // makepoint2tetmap();  // This has been done in meshsurface().
-
-  // Initialize working queues, lists.
-  flipqueue = new queue(sizeof(badface));
-  cavsublist = new list(sizeof(face), NULL, 256);
-  // Initialize the pool of encroached subfaces and subsegments.
-  badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
-  badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
-  // Find all pairs of co-circular subfaces.
-  tallcocirsubs(eps, true);
-  if (b->verbose && badsubfaces->items > 0) {
-    printf("  Removing degenerate subfaces.\n");
-  }
-  perturbrepairencsubs(cavsublist, flipqueue);
-
-  if (b->verbose > 0) {
-    printf("  %ld break points.\n", points->items - vertcount);
-  }
-  
-  delete cavsublist;
-  delete flipqueue;
-  delete badsubfaces;
-  delete badsubsegs; 
-  badsubsegs = (memorypool *) NULL;
-  badsubfaces = (memorypool *) NULL;
-}
-
-//
-// End of vertex perturbation routines
-//
-
-//
-// Begin of segment recovery routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// markacutevertices()    Mark acute vertices.                               //
-//                                                                           //
-// A vertex v is called acute if there are two segments sharing at v forming //
-// an acute angle (i.e. smaller than 90 degree).                             //
-//                                                                           //
-// This routine finds all acute vertices in the PLC and marks them as point- //
-// type ACUTEVERTEX. The other vertices of segments which are non-acute will //
-// be marked as NACUTEVERTEX.  Vertices which are not endpoints of segments  //
-// (such as DUPLICATEDVERTEX, UNUSEDVERTEX, etc) are not infected.           //
-//                                                                           //
-// NOTE: This routine should be called before Steiner points are introduced. //
-// That is, no point has type like FREESEGVERTEX, etc.                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::markacutevertices(REAL acuteangle)
-{
-  shellface **segsperverlist;
-  face segloop, nextseg;
-  point pointloop, edest, eapex;
-  REAL cosbound, anglearc;
-  REAL v1[3], v2[3], L, D;
-  bool isacute;
-  int *idx2seglist;
-  int acutecount;
-  int idx, i, j, k;
-
-  if (b->verbose > 0) {
-    printf("  Marking acute vertices.\n");
-  }
-
-  anglearc = acuteangle * PI / 180.0;
-  cosbound = cos(anglearc);
-  acutecount = 0;
-  // Constructing a map from vertex to segments.
-  makesegmentmap(idx2seglist, segsperverlist);
-
-  // Loop over the set of vertices.
-  points->traversalinit();
-  pointloop = pointtraverse();
-  while (pointloop != (point) NULL) {
-    idx = pointmark(pointloop) - in->firstnumber;
-    // Only do test if p is an endpoint of some segments.
-    if (idx2seglist[idx + 1] > idx2seglist[idx]) {
-      // Init p to be non-acute.
-      setpointtype(pointloop, NACUTEVERTEX);
-      isacute = false;
-      // Loop through all segments sharing at p.
-      for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isacute; i++) {
-        segloop.sh = segsperverlist[i];
-        // segloop.shver = 0;
-        if (sorg(segloop) != pointloop) sesymself(segloop);
-        edest = sdest(segloop);
-        for (j = i + 1; j < idx2seglist[idx + 1] && !isacute; j++) {
-          nextseg.sh = segsperverlist[j];
-          // nextseg.shver = 0;
-          if (sorg(nextseg) != pointloop) sesymself(nextseg);
-          eapex = sdest(nextseg);
-          // Check the angle formed by segs (p, edest) and (p, eapex).
-          for (k = 0; k < 3; k++) {
-            v1[k] = edest[k] - pointloop[k];
-            v2[k] = eapex[k] - pointloop[k];
-          }
-          L = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
-          for (k = 0; k < 3; k++) v1[k] /= L;
-          L = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
-          for (k = 0; k < 3; k++) v2[k] /= L;
-          D = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
-          // Is D acute?
-          isacute = (D >= cosbound);
-        }
-      }
-      if (isacute) {
-        // Mark p to be acute.
-        setpointtype(pointloop, ACUTEVERTEX);
-        acutecount++;
-      }
-    }
-    pointloop = pointtraverse();
-  }
-
-  delete [] idx2seglist;
-  delete [] segsperverlist;
-
-  if ((b->verbose > 0) && (acutecount > 0)) {
-    printf("  %d acute vertices.\n", acutecount);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// finddirection()    Find the first tetrahedron on the path from one point  //
-//                    to another.                                            //
-//                                                                           //
-// Find the tetrahedron that intersects a line segment L (from the origin of //
-// 'searchtet' to the point 'tend'), 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 the location of the line segment L with respect to //
-// 'searchtet':                                                              //
-//   - Returns RIGHTCOLLINEAR indicates L is collinear with the line segment //
-//     from the origin to the destination of 'searchtet'.                    //
-//   - Returns LEFTCOLLINEAR indicates L is collinear with the line segment  //
-//     from the origin to the apex of 'searchtet'.                           //
-//   - Returns TOPCOLLINEAR indicates L is collinear with the line segment   //
-//     from the origin to the opposite of 'searchtet'.                       //
-//   - Returns ACROSSEDGE indicates L intersects with the line segment from  //
-//     the destination to the apex of 'searchtet'.                           //
-//   - Returns ACROSSFACE indicates L intersects with the face opposite to   //
-//     the origin of 'searchtet'.                                            //
-//   - Returns BELOWHULL indicates L crosses outside the mesh domain. This   //
-//     can only happen when the domain is non-convex.                        //
-//                                                                           //
-// NOTE: This routine only works correctly when the mesh is exactly Delaunay.//
-//                                                                           //
-// If 'maxtetnumber' > 0, stop the searching process if the number of passed //
-// tets is larger than it. Return BELOWHULL.                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-enum tetgenmesh::finddirectionresult tetgenmesh::
-finddirection(triface *searchtet, point tend, long maxtetnumber)
-{
-  triface neightet;
-  point tstart, tdest, tapex, toppo;
-  REAL ori1, ori2, ori3;
-  long tetnumber;
-
-  tstart = org(*searchtet);
-#ifdef SELF_CHECK
-  assert(tstart != tend);
-#endif
-  adjustedgering(*searchtet, CCW);
-  if (tstart != org(*searchtet)) {
-    enextself(*searchtet); // For keeping the same origin.
-  }
-  tdest = dest(*searchtet);
-  if (tdest == tend) {
-    return RIGHTCOLLINEAR;
-  }
-  tapex = apex(*searchtet); 
-  if (tapex == tend) {
-    return LEFTCOLLINEAR;
-  } 
-
-  ori1 = orient3d(tstart, tdest, tapex, tend);
-  if (ori1 > 0.0) {
-    // 'tend' is below the face, get the neighbor of this side.
-    sym(*searchtet, neightet);
-    if (neightet.tet != dummytet) {
-      findorg(&neightet, tstart); 
-      adjustedgering(neightet, CCW);
-      if (org(neightet) != tstart) {
-        enextself(neightet); // keep the same origin.
-      }
-      // Set the changed configuratiuon.
-      *searchtet = neightet; 
-      ori1 = -1.0; 
-      tdest = dest(*searchtet);
-      tapex = apex(*searchtet);
-    } else {
-      // A hull face. Only possible for a nonconvex mesh.
-#ifdef SELF_CHECK
-      assert(nonconvex);
-#endif
-      return BELOWHULL; 
-    }
-  }
-
-  // Repeatedly change the 'searchtet', remain 'tstart' be its origin, until
-  //   find a tetrahedron contains 'tend' or is crossed by the line segment
-  //   from 'tstart' to 'tend'.
-  tetnumber = 0l;
-  while ((maxtetnumber > 0) && (tetnumber <= maxtetnumber)) {
-    tetnumber++;
-    toppo = oppo(*searchtet);
-    if (toppo == tend) {
-      return TOPCOLLINEAR;
-    }
-    ori2 = orient3d(tstart, toppo, tdest, tend);
-    if (ori2 > 0.0) {
-      // 'tend' is below the face, get the neighbor at this side.
-      fnext(*searchtet, neightet);
-      symself(neightet);
-      if (neightet.tet != dummytet) {
-        findorg(&neightet, tstart); 
-        adjustedgering(neightet, CCW);
-        if (org(neightet) != tstart) {
-          enextself(neightet); // keep the same origin.
-        }
-        // Set the changed configuration.
-        *searchtet = neightet; 
-        ori1 = -1.0; 
-        tdest = dest(*searchtet);
-        tapex = apex(*searchtet);
-        // Continue the search from the changed 'searchtet'.
-        continue;
-      } else {
-        // A hull face. Only possible for a nonconvex mesh.
-#ifdef SELF_CHECK
-        assert(nonconvex);
-#endif
-        return BELOWHULL; 
-      }
-    }
-    ori3 = orient3d(tapex, toppo, tstart, tend);
-    if (ori3 > 0.0) {
-      // 'tend' is below the face, get the neighbor at this side.
-      enext2fnext(*searchtet, neightet);
-      symself(neightet);
-      if (neightet.tet != dummytet) {
-        findorg(&neightet, tstart); 
-        adjustedgering(neightet, CCW);
-        if (org(neightet) != tstart) {
-          enextself(neightet); // keep the same origin.
-        }
-        // Set the changed configuration.
-        *searchtet = neightet; 
-        ori1 = -1.0; 
-        tdest = dest(*searchtet);
-        tapex = apex(*searchtet);
-        // Continue the search from the changed 'searchtet'.
-        continue;
-      } else {
-        // A hull face. Only possible for a nonconvex mesh.
-#ifdef SELF_CHECK
-        assert(nonconvex);
-#endif
-        return BELOWHULL; 
-      }
-    }
-    // Now 'ori1', 'ori2' and 'ori3' are possible be 0.0 or all < 0.0;
-    if (ori1 < 0.0) {
-      // Possible cases are: ACROSSFACE, ACROSSEDGE, TOPCOLLINEAR.
-      if (ori2 < 0.0) {
-        if (ori3 < 0.0) {
-          return ACROSSFACE;
-        } else { // ori3 == 0.0;
-          // Cross edge (apex, oppo)
-          enext2fnextself(*searchtet);
-          esymself(*searchtet); // org(*searchtet) == tstart;
-          return ACROSSEDGE;
-        }
-      } else { // ori2 == 0.0; 
-        if (ori3 < 0.0) {
-          // Cross edge (dest, oppo)
-          fnextself(*searchtet);
-          esymself(*searchtet);
-          enextself(*searchtet); // org(*searchtet) == tstart;
-          return ACROSSEDGE;
-        } else { // ori3 == 0.0;
-          // Collinear with edge (org, oppo)
-          return TOPCOLLINEAR;
-        }
-      }
-    } else { // ori1 == 0.0;
-      // Possible cases are: RIGHTCOLLINEAR, LEFTCOLLINEAR, ACROSSEDGE.
-      if (ori2 < 0.0) {
-        if (ori3 < 0.0) {
-          // Cross edge (tdest, tapex)
-          return ACROSSEDGE;
-        } else { // ori3 == 0.0
-          // Collinear with edge (torg, tapex)
-          return LEFTCOLLINEAR;
-        }
-      } else { // ori2 == 0.0;
-#ifdef SELF_CHECK
-        assert(ori3 != 0.0);
-#endif
-        // Collinear with edge (torg, tdest)
-        return RIGHTCOLLINEAR;
-      }
-    }
-  }
-  // Loop breakout. It may happen when the mesh is non-Delaunay.
-  return BELOWHULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getsearchtet()    Find a tetrahedron whose origin is either 'p1' or 'p2'. //
-//                                                                           //
-// On return, the origin of 'searchtet' is either 'p1' or 'p2',  and 'tend'  //
-// returns the other point.  'searchtet' serves as the starting tetrahedron  //
-// for searching of the line segment from 'p1' to 'p2' or vice versa.        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::getsearchtet(point p1, point p2, triface* searchtet,
-  point* tend)
-{
-  tetrahedron encodedtet1, encodedtet2;
-
-  // Is there a valid handle provided by the user?
-  if ((searchtet->tet != (tetrahedron *) NULL) && !isdead(searchtet)) {
-    // Find which endpoint the handle holds.
-    if (findorg(searchtet, p1)) {
-      *tend = p2;
-      return;
-    } else {
-      if (findorg(searchtet, p2)) {
-        *tend = p1;
-        return;
-      }
-    }
-  }
-  // If not, search the tet handle stored in 'p1' or 'p2'.
-  *tend = (point) NULL;
-  encodedtet1 = point2tet(p1);
-  encodedtet2 = point2tet(p2);
-  if (encodedtet1 != (tetrahedron) NULL) {
-    decode(encodedtet1, *searchtet);
-    // Be careful, here 'searchtet' may be dead.
-    if (findorg(searchtet, p1)) {
-      *tend = p2;
-    }
-  } else if (encodedtet2 != (tetrahedron) NULL) {
-    decode(encodedtet2, *searchtet);
-    // Be careful, here 'searchtet' may be dead.
-    if (findorg(searchtet, p2)) {
-      *tend = p1;
-    }
-  }
-  // If still not, perform a full point location.  The starting tet is
-  //   chosen as follows: Use the handle stored in 'p1' or 'p2' if it is
-  //   alive; otherwise, start from a tet on the convex hull.
-  if (*tend == (point) NULL) {
-    if (encodedtet1 != (tetrahedron) NULL) {
-      decode(encodedtet1, *searchtet);
-      // Be careful, here 'searchtet' may be dead.
-    }
-    if (isdead(searchtet)) {
-      if (encodedtet2 != (tetrahedron) NULL) {
-        decode(encodedtet2, *searchtet);
-        // Be careful, here 'searchtet' may be dead.
-      }
-      if (isdead(searchtet)) {
-        searchtet->tet = dummytet;
-        searchtet->loc = 0;
-        symself(*searchtet);
-      }
-#ifdef SELF_CHECK
-      assert(!isdead(searchtet));
-#endif
-    }
-    if (locate(p1, searchtet) != ONVERTEX) {
-      printf("Internal error in getsearchtet():  Failed to locate point\n");
-      internalerror();
-    }
-    // Remember this handle in 'p1' to enhance the search speed.
-    setpoint2tet(p1, encode(*searchtet));
-    *tend = p2;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// isedgeencroached()    Check whether or not a subsegment is encroached.    //
-//                                                                           //
-// A segment with endpoints 'p1' and 'p2' is encroached by the point 'testpt'//
-// if it lies in the diametral sphere of this segment.  The degenerate case  //
-// that 'testpt' lies on the sphere is treated as encroached if 'degflag' is //
-// set to be TRUE.                                                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::isedgeencroached(point p1, point p2, point testpt,
-  bool degflag)
-{
-  REAL dotproduct;
-
-  // Check if the segment is facing an angle larger than 90 degree?
-  dotproduct = (p1[0] - testpt[0]) * (p2[0] - testpt[0])
-             + (p1[1] - testpt[1]) * (p2[1] - testpt[1])
-             + (p1[2] - testpt[2]) * (p2[2] - testpt[2]);
-  if (dotproduct < 0) {
-    return true;
-  } else if (dotproduct == 0 && degflag) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// scoutrefpoint()    Search the reference point of a missing segment.       //
-//                                                                           //
-// A segment S is missing in current Delaunay tetrahedralization DT and will //
-// be split by inserting a point V in it.  The two end points of S are the   //
-// origin of 'searchtet' and 'tend'. And we know that S is crossing the face //
-// of 'searchtet' opposite to its origin (may be intersecting with the edge  //
-// from the destination to the apex of the 'searchtet').  The search of P is //
-// completed by walking through all faces of DT across by S.                 //
-//                                                                           //
-// Warning:  This routine is correct when the tetrahedralization is Delaunay //
-// and convex. Otherwise, the search loop may not terminate.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::point tetgenmesh::scoutrefpoint(triface* searchtet, point tend)
-{
-  triface checkface;
-  point tstart, testpt, refpoint;
-  REAL cent[3], radius, largest;
-  REAL ahead;
-  bool ncollinear;
-  int sides;
-
-  if (b->verbose > 2) {
-    printf("  Scout the reference point of segment (%d, %d).\n",
-           pointmark(org(*searchtet)), pointmark(tend));
-  }
-
-  tstart = org(*searchtet);
-  refpoint = (point) NULL;
-  largest = 0; // avoid compile warning.
-  
-  // Check the three vertices of the crossing face.
-  testpt = apex(*searchtet);
-  if (isedgeencroached(tstart, tend, testpt, true)) {
-    ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
-#ifdef SELF_CHECK
-    assert(ncollinear);
-#endif
-    refpoint = testpt;
-    largest = radius;
-  }
-  testpt = dest(*searchtet);
-  if (isedgeencroached(tstart, tend, testpt, true)) {
-    ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
-#ifdef SELF_CHECK
-    assert(ncollinear);
-#endif
-    if (refpoint == (point) NULL) {
-      refpoint = testpt;
-      largest = radius;
-    } else {
-      if (radius > largest) {
-        refpoint = testpt;
-        largest = radius;
-      }
-    }
-  }
-  testpt = oppo(*searchtet);
-  if (isedgeencroached(tstart, tend, testpt, true)) {
-    ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
-#ifdef SELF_CHECK
-    assert(ncollinear);
-#endif
-    if (refpoint == (point) NULL) {
-      refpoint = testpt;
-      largest = radius;
-    } else {
-      if (radius > largest) {
-        refpoint = testpt;
-        largest = radius;
-      }
-    }
-  }
-  // Check the opposite vertex of the neighboring tet in case the segment
-  //   crosses the edge (leftpoint, rightpoint) of the crossing face.
-  sym(*searchtet, checkface);
-  if (checkface.tet != dummytet) {
-    testpt = oppo(checkface);
-    if (isedgeencroached(tstart, tend, testpt, true)) {
-      ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
-#ifdef SELF_CHECK
-      assert(ncollinear);
-#endif
-      if (refpoint == (point) NULL) {
-        refpoint = testpt;
-        largest = radius;
-      } else {
-        if (radius > largest) {
-          refpoint = testpt;
-          largest = radius;
-        }
-      }
-    }
-  }
-
-  // Walk through all crossing faces.
-  enextfnext(*searchtet, checkface);
-  sym(checkface, *searchtet);
-  while (true) {
-    // Check if we are reaching the boundary of the triangulation.
-#ifdef SELF_CHECK
-    assert(searchtet->tet != dummytet);
-#endif
-    // Search for an adjoining tetrahedron we can walk through.
-    searchtet->ver = 0;
-    // 'testpt' is the shared vertex for the following orientation tests.
-    testpt = oppo(*searchtet);
-    if (testpt == tend) {
-      // The searching is finished.
-      break; 
-    } else {
-      // 'testpt' may encroach the segment.
-      if ((testpt != tstart) && (testpt != refpoint)) {
-        if (isedgeencroached(tstart, tend, testpt, true)) {
-          ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
-          if (!ncollinear) {
-            // 'testpt' is collinear with the segment. It may happen when a
-            //   set of collinear and continuous segments is defined by two
-            //   extreme endpoints.  In this case, we should choose 'testpt'
-            //   as the splitting point immediately.  No new point should be
-            //   created.
-            refpoint = testpt;
-            break;
-          }
-          if (refpoint == (point) NULL) {
-            refpoint = testpt;
-            largest = radius;
-          } else {
-            if (radius > largest) {
-              refpoint = testpt;
-              largest = radius;
-            }
-          }
-        }
-      }
-    }
-    // Check three side-faces of 'searchtet' to find the one through
-    //   which we can walk next.
-    for (sides = 0; sides < 3; sides++) {
-      fnext(*searchtet, checkface);
-      ahead = orient3d(org(checkface), dest(checkface), testpt, tend);
-      if (ahead < 0.0) {
-        // We can walk through this face and continue the searching. 
-        sym(checkface, *searchtet);
-        break;
-      }
-      enextself(*searchtet);
-    }
-#ifdef SELF_CHECK
-    assert (sides < 3);
-#endif
-  }
-
-#ifdef SELF_CHECK
-  assert(refpoint != (point) NULL);
-#endif
-  return refpoint;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getsegmentorigin()    Return the origin of the (unsplit) segment.         //
-//                                                                           //
-// After a segment (or a subsegment) is split. Two resulting subsegments are //
-// connecting each other through the pointers saved in their data fields.    //
-// With these pointers, the whole (unsplit) segment can be found. 'splitseg' //
-// may be a split subsegment.  Returns the origin of the unsplit segment.    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::point tetgenmesh::getsegmentorigin(face* splitseg)
-{
-  face workseg;
-  point farorg;
-
-  farorg = sorg(*splitseg);
-  if ((pointtype(farorg) != ACUTEVERTEX) &&
-      (pointtype(farorg) != NACUTEVERTEX)) {
-    workseg = *splitseg;
-    do {
-      senext2self(workseg);
-      spivotself(workseg);
-      if (workseg.sh != dummysh) {
-        workseg.shver = 0;  // It's a subsegment.
-        if (sdest(workseg) != farorg) {
-          sesymself(workseg);
-#ifdef SELF_CHECK
-          assert(sdest(workseg) == farorg);
-#endif
-        }
-        farorg = sorg(workseg);
-        if ((pointtype(farorg) == ACUTEVERTEX) ||
-            (pointtype(farorg) == NACUTEVERTEX)) break;
-      }
-    } while (workseg.sh != dummysh);
-  }
-#ifdef SELF_CHECK
-  assert((pointtype(farorg) == ACUTEVERTEX) ||
-         (pointtype(farorg) == NACUTEVERTEX));
-#endif
-  return farorg;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getsplitpoint()    Get a point for splitting a segment.                   //
-//                                                                           //
-// 'splitseg' is the segment will be split. 'refpoint' is a reference point  //
-// for splitting this segment. Moreover, it should not collinear with the    //
-// splitting segment. (The collinear case will be detected by iscollinear()  //
-// before entering this routine.)  The calculation of the splitting point is //
-// governed by three rules introduced in my paper.                           //
-//                                                                           //
-// After the position is calculated, a new point is created at this location.//
-// The new point has one of the two pointtypes: FREESEGVERTEX indicating it  //
-// is an inserting vertex on segment, and NACUTEVERTEX indicating it is an   //
-// endpoint of a segment which original has type-3 now becomes type-2.       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::point tetgenmesh::getsplitpoint(face* splitseg, point refpoint)
-{
-  point splitpoint;
-  point farorg, fardest;
-  point ei, ej, ek, c;
-  REAL v[3], r, split;
-  REAL d1, d2, ps, rs;
-  bool acuteorg, acutedest;
-  int stype, rule;
-  int i;   
-
-  // First determine the type of the segment (type-1, type-2, or type-3).
-  farorg = getsegmentorigin(splitseg);
-  acuteorg = (pointtype(farorg) == ACUTEVERTEX);
-  sesymself(*splitseg);
-  fardest = getsegmentorigin(splitseg);
-  acutedest = (pointtype(fardest) == ACUTEVERTEX);
-  sesymself(*splitseg);
-
-  ek = (point) NULL; // avoid a compilation warning.
-
-  if (acuteorg) {
-    if (acutedest) {
-      stype = 3;
-    } else {
-      stype = 2;
-      ek = farorg;
-    }
-  } else {
-    if (acutedest) {
-      stype = 2;
-      // Adjust splitseg, so that its origin is acute.
-      sesymself(*splitseg);
-      ek = fardest;
-    } else {
-      stype = 1;
-    }
-  }
-  ei = sorg(*splitseg);
-  ej = sdest(*splitseg);
-
-  if (b->verbose > 1) {
-    printf("  Splitting segment (%d, %d) type-%d with refpoint %d.\n",
-           pointmark(ei), pointmark(ej), stype, pointmark(refpoint));
-  }
-
-  if (stype == 1 || stype == 3) {
-    // Use rule-1.
-    REAL eij, eip, ejp;
-    eij = distance(ei, ej);
-    eip = distance(ei, refpoint);
-    ejp = distance(ej, refpoint);
-    if ((eip < ejp) && (eip < 0.5 * eij)) {
-      c = ei;
-      r = eip;
-    } else if ((eip > ejp) && (ejp < 0.5 * eij)) {
-      c = ej;
-      ej = ei;
-      r = ejp;
-    } else {
-      c = ei;
-      r = 0.5 * eij;
-    }
-    split = r / eij;
-    for (i = 0; i < 3; i++) {
-      v[i] = c[i] + split * (ej[i] - c[i]);
-    }
-    rule = 1;
-  } else {
-    // Use rule-2 or rule-3.
-    REAL eki, ekj, ekp, evj, evp, eiv;
-    c = ek;
-    eki = distance(ek, ei);  // eki may equal zero.
-    ekj = distance(ek, ej);
-    ekp = distance(ek, refpoint);
-    // Calculate v (the going to split position between ei, ej).
-    r = ekp;
-    // Check the validity of the position.
-    if (!(eki < r && r < ekj)) {
-      printf("Error:  Invalid PLC.\n");
-      printf("  Hint:  Use -d switch to check it.\n");
-      terminatetetgen(1);
-    }
-    split = r / ekj;
-    for (i = 0; i < 3; i++) {
-      v[i] = c[i] + split * (ej[i] - c[i]);
-    }
-    rule = 2;
-    evj = ekj - r; // distance(v, ej);
-    evp = distance(v, refpoint);
-    if (evj < evp) {
-      // v is rejected, use rule-3.
-      eiv = distance(ei, v);
-      if (evp <= 0.5 * eiv) {
-        r = eki + eiv - evp;
-      } else {
-        r = eki + 0.5 * eiv;
-      }
-#ifdef SELF_CHECK
-      assert(eki < r && r < ekj);
-#endif
-      split = r / ekj;
-      for (i = 0; i < 3; i++) {
-        v[i] = c[i] + split * (ej[i] - c[i]);
-      }
-      if (b->verbose > 1) {
-        printf("    Using rule-3.\n");
-      }
-      rule = 3;
-    }
-  }
-
-  // Accumulate the corresponding counters.
-  if (rule == 1) r1count++;
-  else if (rule == 2) r2count++;
-  else if (rule == 3) r3count++;
-
-  if (b->verbose > 1) {
-    if (stype == 2) {
-      printf("    Split = %.12g.\n", distance(ei, v) / distance(ei, ej));
-    } else {
-      printf("    Split = %.12g.\n", distance(c, v) / distance(c, ej));
-    }
-  }
-
-  // Create the newpoint.
-  makepoint(&splitpoint);
-  // Add a random perturbation on splitpoint.
-  d1 = distance(c, v);
-  d2 = distance(refpoint, v);
-  if (stype == 1 || stype == 3) {
-    ps = randgenerator(d1 * 1.0e-3);
-  } else {
-    // For type-2 segment, add a smaller perturbation.
-    // ps = randgenerator(d1 * 1.0e-5);
-    // REAL d2 = distance(refpoint, v);
-    ps = randgenerator(d2 * 1.0e-5);
-  }
-  rs = ps / d1;
-  // Perturb splitpoint away from c.
-  for (i = 0; i < 3; i++) {
-    splitpoint[i] = c[i] + (1.0 + rs) * (v[i] - c[i]);
-  }
-  // for (i = 0; i < in->numberofpointattributes; i++) {
-  //   splitpoint[i + 3] = c[i + 3] + (split + rs) * (ej[i + 3] - c[i + 3]);
-  // }
-  if (stype == 3) {
-    // Change a type-3 segment into two type-2 segments. 
-    setpointtype(splitpoint, NACUTEVERTEX);
-  } else {
-    // Set it's type be FREESEGVERTEX.
-    setpointtype(splitpoint, FREESEGVERTEX);
-  }
-  setpoint2sh(splitpoint, sencode(*splitseg));
-
-  return splitpoint;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertsegment()    Insert segment into DT. Queue it if it does not exist. //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::insertsegment(face *insseg, list *misseglist)
-{
-  badface *misseg;
-  triface searchtet, spintet;
-  point tend, checkpoint;
-  point p1, p2;
-  enum finddirectionresult collinear;
-  int hitbdry;
-
-  // Search segment ab in DT.
-  p1 = (point) insseg->sh[3]; 
-  p2 = (point) insseg->sh[4];
-  getsearchtet(p1, p2, &searchtet, &tend);
-  collinear = finddirection(&searchtet, tend, tetrahedrons->items);
-  if (collinear == LEFTCOLLINEAR) {
-    checkpoint = apex(searchtet);
-    enext2self(searchtet);
-    esymself(searchtet);
-  } else if (collinear == RIGHTCOLLINEAR) {
-    checkpoint = dest(searchtet);
-  } else if (collinear == TOPCOLLINEAR) {
-    checkpoint = oppo(searchtet);
-    fnextself(searchtet);
-    enext2self(searchtet);
-    esymself(searchtet);
-  } else {
-    // assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
-    checkpoint = (point) NULL;
-  }
-  if (checkpoint == tend) {
-    // Segment exist. Bond it to all tets containing it.
-    hitbdry = 0;
-    adjustedgering(searchtet, CCW);
-    fnextself(searchtet);
-    spintet = searchtet;
-    do {
-      tssbond1(spintet, *insseg);
-      if (!fnextself(spintet)) {
-        hitbdry++;
-        if (hitbdry < 2) {
-          esym(searchtet, spintet);
-          if (!fnextself(spintet)) {
-            hitbdry++;
-          }
-        }
-      }
-    } while ((apex(spintet) != apex(searchtet)) && (hitbdry < 2));
-    return true;
-  } else {
-    // Segment is missing.
-    if (misseglist != (list *) NULL) {
-      if (b->verbose > 2) {
-        printf("    Queuing missing segment (%d, %d).\n", pointmark(p1),
-               pointmark(p2));
-      }
-      misseg = (badface *) misseglist->append(NULL);
-      misseg->ss = *insseg;
-      misseg->forg = p1;
-      misseg->fdest = p2;
-      misseg->foppo = (point) NULL; // Not used.
-      // setshell2badface(misseg->ss, misseg);
-    }
-    return false;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tallmissegs()    Find and queue all missing segments in DT.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::tallmissegs(list *misseglist)
-{
-  face segloop;
-
-  if (b->verbose) {
-    printf("  Queuing missing segments.\n");
-  }
-
-  subsegs->traversalinit();
-  segloop.sh = shellfacetraverse(subsegs);
-  while (segloop.sh != (shellface *) NULL) {
-    insertsegment(&segloop, misseglist);  
-    segloop.sh = shellfacetraverse(subsegs);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// delaunizesegments()    Split segments repeatedly until they appear in a   //
-//                        Delaunay tetrahedralization.                       //
-//                                                                           //
-// Given a PLC X, which has a set V of vertices and a set of segments. Start //
-// from a Delaunay tetrahedralization D of V, this routine recovers segments //
-// of X in D by incrementally inserting points on missing segments, updating //
-// D with the newly inserted points into D', which remains to be a Delaunay  //
-// tetrahedralization and respects the segments of X. Hence, each segment of //
-// X appears as a union of edges in D'.                                      //
-//                                                                           //
-// This routine dynamically maintains two meshes, one is DT, another is the  //
-// surface mesh F of X.  DT and F have exactly the same vertices.  They are  //
-// updated simultaneously with the newly inserted points.                    //
-//                                                                           //
-// Missing segments are found by looping the set S of segments, checking the //
-// existence of each segment in DT.  Once a segment is found missing in DT,  //
-// it is split into two subsegments by inserting a point into both DT and F, //
-// and S is updated accordingly.  However, the inserted point may cause some //
-// other existing segments be non-Delaunay,  hence are missing from the DT.  //
-// In order to force all segments to appear in DT, we have to loop S again   //
-// after some segments are split. (A little ugly method)  Use a handle to    //
-// remember the last segment be split in one loop, hence all segments after  //
-// it are existing and need not be checked.                                  //
-//                                                                           //
-// In priciple, a segment on the convex hull should exist in DT. However, if //
-// there are four coplanar points on the convex hull, and the DT only can    //
-// contain one diagonal edge which is unfortunately not the segment, then it //
-// is missing. During the recovery of the segment, it is possible that the   //
-// calculated inserting point for recovering this convex hull segment is not //
-// exact enough and lies (slightly) outside the DT. In order to insert the   //
-// point, we enlarge the convex hull of the DT, so it can contain the point  //
-// and remains convex.  'inserthullsite()' is called for this case.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::delaunizesegments()
-{
-  list *misseglist;
-  queue *flipqueue;
-  badface *misloop;
-  tetrahedron encodedtet;
-  triface searchtet, splittet;
-  face splitsh, symsplitsub;
-  face segloop, symsplitseg;
-  point refpoint, splitpoint, sympoint;
-  point tend, checkpoint;
-  point p1, p2, pa;
-  enum finddirectionresult collinear;
-  enum insertsiteresult success;
-  enum locateresult symloc;
-  bool coll;
-  long vertcount;
-  int i, j;
-
-  if (!b->quiet) {
-    printf("Delaunizing segments.\n");
-  }
-
-  // Construct a map from points to tets for speeding point location.
-  makepoint2tetmap();
-  // Initialize a flipqueue.
-  flipqueue = new queue(sizeof(badface));
-  // Initialize the pool of missing segments.
-  misseglist = new list(sizeof(badface), NULL, SUBPERBLOCK);
-  // Looking for missing segments.
-  tallmissegs(misseglist);
-  // The DT contains segments now.
-  checksubsegs = 1;
-  // Remember the current number of points.
-  vertcount = points->items;
-  // Initialize the counters.
-  r1count = r2count = r3count = 0l;
-
-  // Loop until 'misseglist' is empty.
-  while (misseglist->items > 0) {
-    // Randomly pick a missing segment to recover.
-    i = randomnation(misseglist->items);
-    misloop = (badface *)(* misseglist)[i];
-    segloop = misloop->ss;
-    // Fill the "hole" in the list by filling the last one.
-    *misloop = *(badface *)(* misseglist)[misseglist->items - 1];
-    misseglist->items--;
-    // Now recover the segment.
-      p1 = (point) segloop.sh[3];
-      p2 = (point) segloop.sh[4];
-      if (b->verbose > 1) {
-        printf("  Recover segment (%d, %d).\n", pointmark(p1), pointmark(p2));
-      }
-      getsearchtet(p1, p2, &searchtet, &tend);
-      collinear = finddirection(&searchtet, tend, tetrahedrons->items);
-      if (collinear == LEFTCOLLINEAR) {
-        checkpoint = apex(searchtet);
-      } else if (collinear == RIGHTCOLLINEAR) {
-        checkpoint = dest(searchtet);
-      } else if (collinear == TOPCOLLINEAR) {
-        checkpoint = oppo(searchtet);
-      } else {
-#ifdef SELF_CHECK
-        assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
-#endif
-        checkpoint = (point) NULL;
-      }
-      if (checkpoint != tend) {
-        // ab is missing.
-        splitpoint = (point) NULL;
-        if (checkpoint != (point) NULL) {
-          // An existing point c is found on the segment. It can happen when
-          //   ab is defined by a long segment with c inside it. Use c to
-          //   split ab. No new point is created.
-          splitpoint = checkpoint;
-          if (pointtype(checkpoint) == FREEVOLVERTEX) {
-            // c is not a segment vertex yet. It becomes NACUTEVERTEX.
-            setpointtype(splitpoint, NACUTEVERTEX);  
-          } else if (pointtype(checkpoint) == ACUTEVERTEX) {
-            // c is an acute vertex. The definition of PLC is wrong.
-          } else if (pointtype(checkpoint) == NACUTEVERTEX) {
-            // c is an nonacute vertex. The definition of PLC is wrong.
-          } else {
-            // assert(0);
-          }
-        } else {
-          // Find a reference point p of ab.
-          refpoint = scoutrefpoint(&searchtet, tend);
-          if (pointtype(refpoint) == FREEVOLVERTEX) {
-            // p is an input point, check if it is nearly collinear with ab.
-            coll = iscollinear(p1, p2, refpoint, b->epsilon);
-            if (coll) {
-              // a, b, and p are collinear. We insert p into ab. p becomes
-              //   a segment vertex with type NACUTEVERTEX.
-              splitpoint = refpoint;
-              setpointtype(splitpoint, NACUTEVERTEX);
-            }
-          }
-          if (splitpoint == (point) NULL) {
-            // Calculate a split point v using rule 1, or 2, or 3.
-            splitpoint = getsplitpoint(&segloop, refpoint);
-            
-            // Is there periodic boundary conditions?
-            if (checkpbcs) {
-              // Yes! Insert points on other segments of incident pbcgroups.
-              i = shellmark(segloop) - 1;
-              for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
-                makepoint(&sympoint);
-                symloc = getsegpbcsympoint(splitpoint, &segloop, sympoint,
-                                           &symsplitseg, segpglist[j]);
-#ifdef SELF_CHECK
-                assert(symloc != OUTSIDE);
-#endif
-                if ((symloc == ONEDGE) && (symsplitseg.sh != segloop.sh)) {
-#ifdef SELF_CHECK
-                  assert(symsplitseg.sh != dummysh);
-#endif
-                  setpointtype(sympoint, FREESEGVERTEX);
-                  setpoint2sh(sympoint, sencode(symsplitseg));
-                  // Insert sympoint into DT.
-                  pa = sorg(symsplitseg);
-                  splittet.tet = dummytet;
-                  // Find a good start point to search.
-                  encodedtet = point2tet(pa);
-                  if (encodedtet != (tetrahedron) NULL) {
-                    decode(encodedtet, splittet);
-                    if (isdead(&splittet)) {
-                      splittet.tet = dummytet; 
-                    }
-                  }
-                  // Locate sympoint in DT.  Do exact location.
-                  success = insertsite(sympoint, &splittet, false, flipqueue);
-#ifdef SELF_CHECK
-                  assert(success != DUPLICATEPOINT);
-#endif
-                  if (success == OUTSIDEPOINT) {
-                    inserthullsite(sympoint, &splittet, flipqueue);
-                  }
-                  if (steinerleft > 0) steinerleft--;
-                  // Let sympoint remember splittet.
-                  setpoint2tet(sympoint, encode(splittet));
-                  // Do flip in DT.
-                  lawson(misseglist, flipqueue);
-                  // Insert sympoint into F.
-                  symsplitseg.shver = 0;
-                  spivot(symsplitseg, symsplitsub);
-                  // sympoint should on the edge of symsplitsub.
-                  splitsubedge(sympoint, &symsplitsub, flipqueue);
-                  // Do flip in facet.
-                  flipsub(flipqueue);
-                  // Insert the two subsegments.
-                  symsplitseg.shver = 0;
-                  insertsegment(&symsplitseg, misseglist);
-                  senextself(symsplitseg);
-                  spivotself(symsplitseg);
-                  symsplitseg.shver = 0;
-                  insertsegment(&symsplitseg, misseglist);
-                } else { // if (symloc == ONVERTEX) {
-                  // The sympoint already exists. It is possible when two
-                  //   pbc groups are exactly the same. Omit this point.
-                  pointdealloc(sympoint);
-                }
-              }
-            }
-
-            // Insert 'splitpoint' into DT.
-            if (isdead(&searchtet)) searchtet.tet = dummytet;
-            success = insertsite(splitpoint, &searchtet, false, flipqueue);
-            if (success == OUTSIDEPOINT) {
-              // A convex hull edge is missing, and the inserting point lies
-              //   (slightly) outside the convex hull due to the significant
-              //   digits lost in the calculation. Enlarge the convex hull.
-              inserthullsite(splitpoint, &searchtet, flipqueue);
-            }
-            if (steinerleft > 0) steinerleft--;
-            // Remember a handle in 'splitpoint' to enhance the speed of
-            //   consequent point location.
-            setpoint2tet(splitpoint, encode(searchtet));
-            // Maintain Delaunayness in DT.
-            lawson(misseglist, flipqueue);
-          }
-        }
-        // Insert 'splitpoint' into F.
-        spivot(segloop, splitsh);
-        splitsubedge(splitpoint, &splitsh, flipqueue);
-        flipsub(flipqueue);
-        // Insert the two subsegments.
-        segloop.shver = 0;
-        insertsegment(&segloop, misseglist);
-        senextself(segloop);
-        spivotself(segloop);
-        segloop.shver = 0;
-        insertsegment(&segloop, misseglist);
-      }
-  }
-
-  // Detach all segments from tets.
-  tetrahedrons->traversalinit();
-  searchtet.tet = tetrahedrontraverse();
-  while (searchtet.tet != (tetrahedron *) NULL) {
-    for (i = 0; i < 6; i++) {
-      searchtet.tet[8 + i] = (tetrahedron) dummysh;
-    }
-    searchtet.tet = tetrahedrontraverse();
-  }
-  // No segments now.
-  checksubsegs = 0;
-
-  if (b->verbose > 0) {
-    printf("  %ld protect points.\n", points->items - vertcount);
-    printf("  R1: %ld,  R2: %ld,  R3: %ld.\n", r1count, r2count, r3count);
-  }
-
-  delete flipqueue;
-  delete misseglist;
-}
-
-//
-// End of segments recovery routines
-//
-
-//
-// Begin of facet recovery routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertsubface()    Fix a subface in place.                                //
-//                                                                           //
-// Search a subface s in current tetrahedralization T.  If s is found a face //
-// face of T, it is inserted into T.  Return FALSE if s is not found in T.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::insertsubface(face* insertsh, triface* searchtet)
-{
-  triface spintet, symtet;
-  face testsh, testseg;
-  face spinsh, casin, casout;
-  point tapex, checkpoint;
-  enum finddirectionresult collinear;
-  int hitbdry;
-
-  // Search an edge of s.
-  getsearchtet(sorg(*insertsh), sdest(*insertsh), searchtet, &checkpoint);
-  collinear = finddirection(searchtet, checkpoint, tetrahedrons->items);
-  if (collinear == LEFTCOLLINEAR) {
-    enext2self(*searchtet);
-    esymself(*searchtet);
-  } else if (collinear == TOPCOLLINEAR) {
-    fnextself(*searchtet);
-    enext2self(*searchtet);
-    esymself(*searchtet);
-  }
-  if (dest(*searchtet) != checkpoint) {
-    // The edge doesn't exist => s is missing.
-    return false;
-  }
-
-  // Search s by spinning faces around the edge.
-  tapex = sapex(*insertsh);
-  spintet = *searchtet;
-  hitbdry = 0;
-  do {
-    if (apex(spintet) == tapex) {
-      // Found s in T. Check if s has already been inserted.
-      tspivot(spintet, testsh);
-      if (testsh.sh == dummysh) {
-        adjustedgering(spintet, CCW);
-        findedge(insertsh, org(spintet), dest(spintet));
-        tsbond(spintet, *insertsh);
-        sym(spintet, symtet); // 'symtet' maybe outside, use it anyway.
-        sesymself(*insertsh);
-        tsbond(symtet, *insertsh);
-      } else {
-        // Found a duplicated subface (due to the redundant input).
-        if (!b->quiet) {
-          printf("Warning:  Two subfaces are found duplicated at ");
-          printf("(%d, %d, %d)\n", pointmark(sorg(testsh)),
-                 pointmark(sdest(testsh)), pointmark(sapex(testsh)));
-          printf("  Subface of facet #%d is deleted.\n", shellmark(*insertsh));
-          // printf("  Hint: -d switch can find all duplicated facets.\n");
-        }
-        shellfacedealloc(subfaces, insertsh->sh);
-      }
-      return true;
-    }
-    if (!fnextself(spintet)) {
-      hitbdry ++;
-      if (hitbdry < 2) {
-        esym(*searchtet, spintet);
-        if (!fnextself(spintet)) {
-          hitbdry ++;
-        }
-      }
-    }
-  } while (hitbdry < 2 && apex(spintet) != apex(*searchtet));
-
-  // s is missing.
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tritritest()    Test if two triangles are intersecting in their interior. //
-//                                                                           //
-// One triangle t1 is the face of 'checktet', the other t2 is given by three //
-// corners 'p1', 'p2' and 'p3'. This routine calls tri_tri_inter() to detect //
-// whether t1 and t2 exactly intersect in their interior. Cases like share a //
-// vertex, share an edge, or coincidence are considered not intersect.       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::tritritest(triface* checktet, point p1, point p2, point p3)
-{
-  point forg, fdest, fapex;
-  enum interresult intersect;
-
-  forg = org(*checktet);
-  fdest = dest(*checktet);
-  fapex = apex(*checktet);
-
-#ifdef SELF_CHECK
-  REAL ax, ay, az, bx, by, bz;
-  REAL n[3];
-  // face (torg, tdest, tapex) should not be degenerate. However p1, p2,
-  //   and p3 may be collinear. Check it.
-  ax = forg[0] - fdest[0];
-  ay = forg[1] - fdest[1];
-  az = forg[2] - fdest[2];
-  bx = forg[0] - fapex[0];
-  by = forg[1] - fapex[1];
-  bz = forg[2] - fapex[2];
-  n[0] = ay * bz - by * az;
-  n[1] = az * bx - bz * ax;
-  n[2] = ax * by - bx * ay;
-  assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
-  // The components of n should not smaller than the machine epsilon.
-
-  ax = p1[0] - p2[0];
-  ay = p1[1] - p2[1];
-  az = p1[2] - p2[2];
-  bx = p1[0] - p3[0];
-  by = p1[1] - p3[1];
-  bz = p1[2] - p3[2];
-  n[0] = ay * bz - by * az;
-  n[1] = az * bx - bz * ax;
-  n[2] = ax * by - bx * ay;
-  assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
-  // The components of n should not smaller than the machine epsilon.
-#endif
-
-  intersect = tri_tri_inter(forg, fdest, fapex, p1, p2, p3);
-  return intersect == INTERSECT;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// initializecavity()    Initialize the cavity.                              //
-//                                                                           //
-// A cavity C is bounded by a list of faces, called fronts.  Each front f is //
-// hold by a tet t adjacent to C, t is not in C (uninfected). If f is a hull //
-// face, t does't exist, a fake tet t' is created to hold f. t' has the same //
-// vertices as f but no opposite.  t' will be removed automatically after C  //
-// is filled with new tets (by carvecavity()).                               //
-//                                                                           //
-// The faces of C are given in two lists. 'floorlist' is a set of subfaces,  //
-// each subface has been oriented to face to the inside of C.  'ceillist' is //
-// a set of tetrahedral faces. 'frontlist' returns the initialized fronts.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::initializecavity(list* floorlist, list* ceillist,
-  list* frontlist)
-{
-  triface neightet, casingtet;
-  triface faketet;
-  face worksh;
-  int i;
-
-  // Initialize subfaces of C.
-  for (i = 0; i < floorlist->len(); i++) {
-    // Get a subface s.
-    worksh = * (face *)(* floorlist)[i];
-#ifdef SELF_CHECK
-    // Current side of s should be empty.
-    stpivot(worksh, neightet);
-    assert(neightet.tet == dummytet);
-#endif
-    // Get the adjacent tet t.
-    sesymself(worksh);
-    stpivot(worksh, casingtet);
-    // Does t exist?
-    if (casingtet.tet == dummytet) {
-      // Create a fake tet t' to hold f temporarily.
-      maketetrahedron(&faketet);
-      setorg(faketet, sorg(worksh));
-      setdest(faketet, sdest(worksh));
-      setapex(faketet, sapex(worksh));
-      setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
-      tsbond(faketet, worksh);
-      frontlist->append(&faketet);
-    } else {
-      frontlist->append(&casingtet);
-    }
-  }
-  // Initialize tet faces of C.
-  for (i = 0; i < ceillist->len(); i++) {
-    // Get a tet face c.
-    neightet = * (triface *) (* ceillist)[i];
-#ifdef SELF_CHECK
-    // The tet of c must be inside C (going to be deleted).
-    assert(infected(neightet));
-#endif
-    // Get the adjacent tet t.
-    sym(neightet, casingtet);
-    // Does t exist?
-    if (casingtet.tet == dummytet) {
-      // No. Create a fake tet t' to hold f temporarily.
-      maketetrahedron(&faketet);
-      // Be sure that the vertices of t' are CCW oriented.
-      adjustedgering(neightet, CW); // CW edge ring.
-      setorg(faketet, org(neightet));
-      setdest(faketet, dest(neightet));
-      setapex(faketet, apex(neightet));
-      setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
-      // Bond t' to a subface if it exists.
-      tspivot(neightet, worksh);
-      if (worksh.sh != dummysh) {
-        sesymself(worksh);
-        tsbond(faketet, worksh);
-      } 
-      // Bond c <--> t'. So we're able to find t' and remove it.
-      bond(faketet, neightet);
-      // c may become uninfected due to the bond().
-      infect(neightet);
-      frontlist->append(&faketet);
-    } else {
-      frontlist->append(&casingtet);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// retrievenewtets()    Retrieve the newly created tets.                     //
-//                                                                           //
-// On input, 'newtetlist' contains at least one alive new tet. From this tet,//
-// other new tets can be found by a broadth-first searching.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::retrievenewtets(list* newtetlist)
-{
-  triface searchtet, casingtet;
-  int i;
-
-  // There may be dead tets due to flip32(). Delete them first.
-  for (i = 0; i < newtetlist->len(); i++) {
-    searchtet = * (triface *)(* newtetlist)[i];
-    if (isdead(&searchtet)) {
-      newtetlist->del(i, 0); i--;
-      continue;
-    }
-    infect(searchtet);
-  }
-  // Find all new tets.
-  for (i = 0; i < newtetlist->len(); i++) {
-    searchtet = * (triface *)(* newtetlist)[i];
-    for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
-      sym(searchtet, casingtet);
-      if ((casingtet.tet != dummytet) && !infected(casingtet)) {
-        infect(casingtet);
-        newtetlist->append(&casingtet);
-      }
-    }
-  }
-  // Uninfect new tets.
-  for (i = 0; i < newtetlist->len(); i++) {
-    searchtet = * (triface *)(* newtetlist)[i];
-    uninfect(searchtet);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// delaunizecavvertices()    Form a DT of the vertices of a cavity.          //
-//                                                                           //
-// 'floorptlist' and 'ceilptlist' are the vertices of the cavity.            //
-//                                                                           //
-// The tets of the DT are created directly in the pool 'tetrahedrons', i.e., //
-// no auxiliary data structure and memory are required.  The trick is at the //
-// time they're created, there are no connections between them to the other  //
-// tets in the pool. You can imagine they form an ioslated island.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::delaunizecavvertices(triface* oldtet, list* floorptlist,
-  list* ceilptlist, list* newtetlist, queue* flipque)
-{
-  point *insertarray;
-  triface bakhulltet, newtet;
-  long bakhullsize;
-  long arraysize;
-  int bakchksub;
-  int i, j;
-
-  // Prepare the array of points for inserting.
-  arraysize = floorptlist->len();
-  if (ceilptlist != (list *) NULL) {
-    arraysize += ceilptlist->len();
-  }
-  insertarray = new point[arraysize];
-  for (i = 0; i < floorptlist->len(); i++) {
-    insertarray[i] = * (point *)(* floorptlist)[i];
-  }
-  if (ceilptlist != (list *) NULL) {
-    for (j = 0; j < ceilptlist->len(); j++) {
-      insertarray[i + j] = * (point *)(* ceilptlist)[j];
-    }
-  }
-
-  // The incrflipdelaunay() is re-used. Backup global variables.
-  decode(dummytet[0], bakhulltet);
-  bakhullsize = hullsize;
-  bakchksub = checksubfaces;
-  checksubfaces = 0;
-  b->verbose--;
-
-  // Form the DT by incremental flip Delaunay algorithm. Do not jump for
-  //   point location, do not merge points.
-  incrflipdelaunay(oldtet, insertarray, arraysize, false, false, 0.0, flipque);
-  
-  // Get a tet in D.
-  decode(dummytet[0], newtet);
-  newtetlist->append(&newtet);
-  // Get all tets of D.
-  retrievenewtets(newtetlist);
-
-  // Restore global variables.
-  dummytet[0] = encode(bakhulltet);
-  hullsize = bakhullsize;
-  checksubfaces = bakchksub;
-  b->verbose++;
-  
-  delete [] insertarray;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertauxsubface()    Fix an auxilary subface in place.                   //
-//                                                                           //
-// An auxilary subface s is fixed in D as it is a real subface, but s has no //
-// vertices and neighbors. It has two uses: (1) it protects an identfied     //
-// front f in D; (2) it serves the link to bond a tet in C and f later. The  //
-// first neighbor of s (s->sh[0]) stores a pointer to f.                     //
-//                                                                           //
-// 'front' is a front f of C. idfront' t is a tet in D where f is identified //
-// be a face of it. s will be fixed between t and its neighbor.              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::insertauxsubface(triface* front, triface* idfront)
-{
-  triface neightet;
-  face auxsh;
-
-  // Create the aux subface s.
-  makeshellface(subfaces, &auxsh);
-  // Bond s <--> t.
-  tsbond(*idfront, auxsh);
-  // Does t's neighbor n exist?
-  sym(*idfront, neightet);
-  if (neightet.tet != dummytet) {
-    // Bond s <--> n.
-    sesymself(auxsh);
-    tsbond(neightet, auxsh);
-  }
-  // Let s remember f.
-  auxsh.sh[0] = (shellface) encode(*front);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// scoutfront()    Scout a face in D.                                        //
-//                                                                           //
-// Search a 'front' f in D. If f is found, return TRUE and the face of D is  //
-// returned in 'idfront'. Otherwise, return FALSE.                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::scoutfront(triface* front, triface* idfront, list* newtetlist)
-{
-  triface spintet;
-  point pa, pb, pc;
-  enum locateresult loc;
-  enum finddirectionresult col;
-  int hitbdry;
-  int i;
-
-  // Let the front we're searching is abc.
-  pa = org(*front);
-  pb = dest(*front);
-  // Get a tet in D for searching.
-  *idfront = recenttet;
-  // Make sure the tet is valid (it may be killed by flips).
-  if (isdead(idfront)) {
-    // The tet is dead. Search a live tet in D. !!!
-    for (i = 0; i < newtetlist->len(); i++) {
-      recenttet = * (triface *)(* newtetlist)[i];
-      if (!isdead(&recenttet)) break;
-    }
-    assert(i < newtetlist->len());
-  }
-
-  // Search a tet having vertex a.
-  loc = preciselocate(pa, idfront, (long) newtetlist->len());
-  assert(loc == ONVERTEX);
-  recenttet = *idfront;
-  // Search a tet having edge ab.
-  col = finddirection(idfront, pb, (long) newtetlist->len());
-  if (col == RIGHTCOLLINEAR) {
-    // b is just the destination.
-  } else if (col == LEFTCOLLINEAR) {
-    enext2self(*idfront);
-    esymself(*idfront);
-  } else if (col == TOPCOLLINEAR) {
-    fnextself(*idfront);
-    enext2self(*idfront);
-    esymself(*idfront);
-  }
-
-  if (dest(*idfront) == pb) {
-    // Search a tet having face abc
-    pc = apex(*front);
-    spintet = *idfront;
-    hitbdry = 0;
-    do {
-      if (apex(spintet) == pc) {
-        // Found abc. Insert an auxilary subface s at idfront.
-        // insertauxsubface(front, &spintet);
-        *idfront = spintet;
-        return true;
-      }
-      if (!fnextself(spintet)) {
-        hitbdry ++;
-        if (hitbdry < 2) {
-          esym(*idfront, spintet);
-          if (!fnextself(spintet)) {
-            hitbdry ++;
-          }
-        }
-      }
-      if (apex(spintet) == apex(*idfront)) break;
-    } while (hitbdry < 2);  
-  }
-
-  // f is missing in D.
-  if (b->verbose > 2) {
-    printf("    Front (%d, %d, %d) is missing.\n", pointmark(pa),
-           pointmark(pb), pointmark(apex(*front)));
-  }
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// gluefronts()    Glue two fronts together.                                 //
-//                                                                           //
-// This is a support routine for identifyfront().  Two fronts f and f1 are   //
-// found indentical. This is caused by the non-coplanarity of vertices of a  //
-// facet. Hence f and f1 are a subface and a tet. They are not fronts of the //
-// cavity anymore. This routine glues f and f1 together.                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::gluefronts(triface* front, triface* front1)
-{
-  face consh;
-
-  // Glue f and f1 together. There're four cases:
-  //   (1) both f and f1 are not fake;
-  //   (2) f is not fake, f1 is fake;
-  //   (3) f is fake and f1 is not fake;
-  //   (4) both f and f1 are fake.
-  // Case (4) should be not possible. 
-
-  // Is there a concrete subface c at f.
-  tspivot(*front, consh);
-  if (consh.sh != dummysh) {
-    sesymself(consh);
-    tsbond(*front1, consh); // Bond: f1 <--> c.
-    sesymself(consh);
-  }
-  // Does f hold by a fake tet.
-  if (oppo(*front) == (point) NULL) {
-    // f is fake. Case (3) or (4).
-    assert(oppo(*front1) != (point) NULL); // Eliminate (4).
-    // Case (3).
-    if (consh.sh != dummysh) {
-      stdissolve(consh);  // Dissolve: c -x-> f.
-    }
-    // Dealloc f.
-    tetrahedrondealloc(front->tet);
-    // f1 becomes a hull. let 'dummytet' bond to it.
-    dummytet[0] = encode(*front1);
-  } else {
-    // Case (1) or (2).
-    bond(*front, *front1); // Bond f1 <--> f. 
-  }
-  // Is f a fake tet?
-  if (!isdead(front)) {
-    // No. Check for case (2).
-    tspivot(*front1, consh);
-    // Is f1 fake?
-    if (oppo(*front1) == (point) NULL) {
-      // Case (2) or (4)
-      assert(oppo(*front) != (point) NULL); // Eliminate (4).
-      // Case (2).
-      if (consh.sh != dummysh) {
-        stdissolve(consh);  // Dissolve: c -x-> f1.
-        sesymself(consh); // Bond: f <--> c.
-        tsbond(*front, consh);
-      }
-      // Dissolve: f -x->f1.
-      dissolve(*front);
-      // Dealloc f1.
-      tetrahedrondealloc(front1->tet);
-      // f becomes a hull. let 'dummytet' bond to it.
-      dummytet[0] = encode(*front);
-    } else {
-      // Case (1).
-      if (consh.sh != dummysh) {
-        sesymself(consh);
-        tsbond(*front, consh); // Bond: f <--> c.
-      } 
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// identifyfronts()    Identify cavity faces in D.                           //
-//                                                                           //
-// 'frontlist' are fronts of C need indentfying.  This routine searches each //
-// front f in D. Once f is found, an auxilary subface s is inserted in D at  //
-// the face. If f is not found in D, remove it from frontlist and save it in //
-// 'misfrontlist'.                                                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::identifyfronts(list* frontlist, list* misfrontlist,
-  list* newtetlist)
-{
-  triface front, front1, tfront;
-  triface idfront, neightet;
-  face auxsh;
-  int len, i, j;
-
-  misfrontlist->clear();
-  // Set a new tet in D for searching.
-  recenttet = * (triface *)(* newtetlist)[0];
-
-  // Identify all fronts in D.
-  for (i = 0; i < frontlist->len(); i++) {
-    // Get a front f.
-    front = * (triface *)( *frontlist)[i];
-    if (scoutfront(&front, &idfront, newtetlist)) {
-      // Found f. Insert an aux subface s.
-      assert((idfront.tet != dummytet) && !isdead(&idfront));
-      // Does s already exist?
-      tspivot(idfront, auxsh);
-      if (auxsh.sh != dummysh) {
-        // There're two identical fronts, f (front) and f1 (s.sh[0])!
-        decode((tetrahedron) auxsh.sh[0], front1);
-        assert((front1.tet != dummytet) && !infected(front1));
-        // Detach s in D.
-        tsdissolve(idfront);
-        sym(idfront, neightet);
-        if (neightet.tet != dummytet) {
-          tsdissolve(neightet);
-        }
-        // s has fulfilled its duty. Can be deleted.
-        shellfacedealloc(subfaces, auxsh.sh);
-        // Remove f from frontlist.
-        frontlist->del(i, 1); i--;
-        // Remove f1 from frontlist.
-        len = frontlist->len();
-        for (j = 0; j < frontlist->len(); j++) {
-          tfront = * (triface *)(* frontlist)[j];
-          if ((tfront.tet == front1.tet) && (tfront.loc == front1.loc)) {
-            // Found f1 in list.  Check f1 != f.
-            assert((tfront.tet != front.tet) || (tfront.loc != front.loc));
-            frontlist->del(j, 1); i--;
-            break;
-          }
-        }
-        assert((frontlist->len() + 1) == len);
-        // Glue f and f1 together.
-        gluefronts(&front, &front1);        
-      } else {
-        // Insert an aux subface to protect f in D.
-        insertauxsubface(&front, &idfront);
-      }
-    } else {
-      // f is missing.
-      frontlist->del(i, 1); i--;
-      // Are there two identical fronts, f (front) and f1 (front1)?
-      for (j = 0; j < misfrontlist->len(); j++) {
-        front1 = * (triface *)(* misfrontlist)[j];
-        if (isfacehaspoint(&front1, org(front)) &&
-            isfacehaspoint(&front1, dest(front)) &&
-            isfacehaspoint(&front1, apex(front))) break;
-      }
-      if (j < misfrontlist->len()) {
-        // Found an identical front f1. Remove f1 from the list.
-        misfrontlist->del(j, 1);
-        // Glue f and f1 together.
-        gluefronts(&front, &front1); 
-      } else {
-        // Add f into misfrontlist.
-        misfrontlist->append(&front);
-      }
-    }
-  }
-  return misfrontlist->len() == 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// detachauxsubfaces()    Detach auxilary subfaces in D.                     //
-//                                                                           //
-// This is a reverse routine of identifyfronts(). Some fronts are missing in //
-// D. C can not be easily tetrahedralized. It needs remediation (expansion,  //
-// or constrained flips, or adding a Steiner point).  This routine detaches  //
-// the auxilary subfaces have been inserted in D and delete them.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::detachauxsubfaces(list* newtetlist)
-{
-  triface newtet, neightet;
-  face auxsh;
-  int i;
-
-  for (i = 0; i < newtetlist->len(); i++) {
-    // Get a new tet t.
-    newtet = * (triface *)(* newtetlist)[i];
-    // t may e dead due to flips.
-    if (isdead(&newtet)) continue;
-    assert(!infected(newtet));
-    // Check the four faces of t.
-    for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
-      tspivot(newtet, auxsh);
-      if (auxsh.sh != dummysh) {
-        // An auxilary subface s.
-        assert(sorg(auxsh) == (point) NULL);
-        tsdissolve(newtet);  // t -x-> s.
-        sym(newtet, neightet);
-        if (neightet.tet != dummytet) {
-          assert(!isdead(&neightet));
-          tsdissolve(neightet); // n -x-> s.
-        }
-        // Delete s.
-        shellfacedealloc(subfaces, auxsh.sh);
-      }
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// expandcavity()    Expand the cavity by adding new fronts.                 //
-//                                                                           //
-// This is the support routine for delaunizecavity().  Some fronts of C are  //
-// missing in D since they're not strongly Delaunay. Such fronts are removed //
-// and the faces of the tets abutting to them are added. C is then expanded. //
-// Some removed faces may be subfaces, they're queued to recover later. D is //
-// expanded simultaneously with the new vertices of the new fronts.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::expandcavity(list* frontlist, list* misfrontlist,
-  list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
-{
-  triface misfront, newfront, casingtet, crosstet;
-  triface searchtet, faketet, bakhulltet;
-  face checksh;
-  point pd;
-  enum insertsiteresult success;
-  long bakhullsize;
-  int bakchksub;
-  int i, j, k;
-
-  if (b->verbose > 1) {
-    printf("    Expand cavity (%d missing fronts).\n", misfrontlist->len());
-  }
-  // Increase the number of expanded times.
-  expcavcount++;
-  // The incrflipdelaunay() is re-used. Backup global variables.
-  decode(dummytet[0], bakhulltet);
-  bakhullsize = hullsize;
-  bakchksub = checksubfaces;
-  checksubfaces = 0;
-  b->verbose--;
-
-  // Choose a tet in D for searching.
-  recenttet = * (triface *)(* newtetlist)[0];
-  assert((recenttet.tet != dummytet) && !isdead(&recenttet));
-
-  // Loop through 'misfrontlist'.
-  for (i = 0; i < misfrontlist->len(); i++) {
-    // Get a missing front f.
-    misfront = * (triface *)(* misfrontlist)[i];
-    // C will be expanded at f.
-    if (b->verbose > 1) {
-      printf("    Get misfront (%d, %d, %d).\n", pointmark(org(misfront)),
-             pointmark(dest(misfront)), pointmark(apex(misfront)));
-    }
-    // Is f has a subface s?
-    tspivot(misfront, checksh);
-    if (checksh.sh != dummysh) {
-      // A subface s is found. Check whether f is expandable at s.
-      sym(misfront, crosstet);
-      if (!infected(crosstet)) {
-        // f is not expandable. In principle is should not happen. However,
-        //   it can happen when PBC is in use.
-        assert(checkpbcs);
-        // Skip expanding f. It will be processed later.
-        continue;
-      }
-      // Temporarily remove s. Queue and recover it later.
-      if (b->verbose > 1) {
-        printf("    Queuing subface (%d, %d, %d).\n",
-               pointmark(sorg(checksh)), pointmark(sdest(checksh)),
-               pointmark(sapex(checksh)));
-      }
-      // Detach s from tets at its both sides.
-      tsdissolve(misfront);
-      tsdissolve(crosstet);
-      // Detach tets at from s.
-      stdissolve(checksh);
-      sesymself(checksh);
-      stdissolve(checksh);
-      // Mark and queue it.
-      sinfect(checksh);
-      missingshqueue->push(&checksh);
-    }
-    // f may already be processed (become a cross tet of C).
-    if (infected(misfront)) continue;
-    // Get the point p = oppo(t), t is the tet holds f.
-    pd = oppo(misfront);
-#ifdef SELF_CHECK
-    // t must not be fake.
-    assert(pd != (point) NULL);
-#endif
-    // Insert p in D. p may not be inserted if it is one of the two cases:
-    //   (1) p is already a vertex of D;
-    //   (2) p lies outside the CH of D;
-    searchtet = recenttet;
-    // Make sure the tet is valid (it may be killed by flips).
-    if (isdead(&searchtet)) {
-      // The tet is dead. Get a live tet in D. !!!
-      for (j = 0; j < newtetlist->len(); j++) {
-        recenttet = * (triface *)(* newtetlist)[j];
-        if (!isdead(&recenttet)) break;
-      }
-      assert(j < newtetlist->len());
-      searchtet = recenttet;
-    }
-    success = insertsite(pd, &searchtet, false, flipque);
-    if (success == OUTSIDEPOINT) {
-      // case (2). Insert p onto CH of D.
-      inserthullsite(pd, &searchtet, flipque);
-    }
-    if (success != DUPLICATEPOINT) {
-      // p is inserted. Recover Delaunness of D by flips.
-      flip(flipque, NULL);
-    }
-    // Expand C by adding new fronts. The three faces of t which have p as a
-    //   vertex become new fronts. However, if a new front is coincident with
-    //   an old front of C, it is not added and the old front is removed. 
-    adjustedgering(misfront, CCW);
-    for (j = 0; j < 3; j++) {
-      // Notice: Below I mis-used the names. 'newfront' is not exactly a new
-      //   front, instead the 'casingtet' should be called new front. 
-      // Get a new front f_n.
-      fnext(misfront, newfront);
-      // Get the neighbor tet n at f_n.
-      sym(newfront, casingtet);
-      // Is n a cross tet?
-      if (!infected(casingtet)) {
-        // f_n becomes a new front of C.
-        // Does n exist?
-        if (casingtet.tet == dummytet) {
-          // Create a fake tet n' to hold f_n temporarily.
-          maketetrahedron(&faketet);
-          // Be sure that the vertices of fake tet are CCW oriented.
-          adjustedgering(newfront, CW); // CW edge ring.
-          setorg(faketet, org(newfront));
-          setdest(faketet, dest(newfront));
-          setapex(faketet, apex(newfront));
-          setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
-          // Bond n' to a subface if it exists.
-          tspivot(newfront, checksh);
-          if (checksh.sh != dummysh) {
-            sesymself(checksh);
-            tsbond(faketet, checksh);
-          } 
-          // Bond f_n <--> n'. So we're able to find n' and remove it.
-          bond(faketet, newfront);
-          frontlist->append(&faketet);
-        } else {
-          // Add n to frontlist.
-          frontlist->append(&casingtet);
-        }
-      } else {
-        // f_n is coincident with an existing front f' of C. f' is no longer
-        //   a front, remove it from frontlist.  Use the inverse order to
-        //   search f' (most likely, a newly added front may be f').
-        for (k = frontlist->len() - 1; k >= 0; k--) {
-          searchtet = * (triface *)(* frontlist)[k];
-          if ((newfront.tet == searchtet.tet) &&
-              (newfront.loc == searchtet.loc)) {
-            frontlist->del(k, 0);
-            break;
-          }
-        }
-        // Is f_n a subface?
-        tspivot(newfront, checksh);
-        if (checksh.sh != dummysh) {
-          // Temporarily remove checksh. Make it missing. recover it later.
-          if (b->verbose > 2) {
-            printf("    Queuing subface (%d, %d, %d).\n",
-                   pointmark(sorg(checksh)), pointmark(sdest(checksh)),
-                   pointmark(sapex(checksh)));
-          }
-          tsdissolve(newfront);
-          tsdissolve(casingtet);
-          // Detach tets at the both sides of checksh.
-          stdissolve(checksh);
-          sesymself(checksh);
-          stdissolve(checksh);
-          sinfect(checksh);
-          missingshqueue->push(&checksh);
-        }
-      }
-      enextself(misfront);
-    }
-    // C has been expanded at f. t becomes a cross tet.
-    if (!infected(misfront)) {
-      // t will be deleted, queue it.
-      infect(misfront);
-      crosstetlist->append(&misfront);
-    }
-  }
-
-  // Loop through misfrontlist, remove infected misfronts.
-  for (i = 0; i < misfrontlist->len(); i++) {
-    misfront = * (triface *)(* misfrontlist)[i];
-    if (infected(misfront)) {
-      // Remove f, keep original list order.
-      misfrontlist->del(i, 1);
-      i--;
-    }
-  }
-
-  // Are we done?
-  if (misfrontlist->len() > 0) {
-    // No. There are unexpandable fronts.
-    // expandcavity_sos(misfrontlist);
-    assert(0); // Not done yet.
-  }
-
-  // D has been updated (by added new tets or dead tets) (due to flips).
-  retrievenewtets(newtetlist);
-
-  // Restore global variables.
-  dummytet[0] = encode(bakhulltet);
-  hullsize = bakhullsize;
-  checksubfaces = bakchksub;
-  b->verbose++;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// carvecavity()    Remove redundant (outside) tetrahedra from D.            //
-//                                                                           //
-// The fronts of C have been identified in D. Hence C can be tetrahedralized //
-// by removing the tets outside C. The CDT is then updated by filling C with //
-// the remaining tets (inside C) of D.                                       //
-//                                                                           //
-// Each front is protected by an auxilary subface s in D. s has a pointer to //
-// f (s.sh[0]). f can be used to classified the in- and out- tets of C (the  //
-// CW orientation of f faces to the inside of C). The classified out-tets of //
-// C are marked (infected) for removing.                                     //
-//                                                                           //
-// Notice that the out-tets may not only the tets on the CH of C,  but also  //
-// tets completely inside D, eg., there is a "hole" in D.  Such tets must be //
-// marked during classification. The hole tets are poped up and removed too. //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::carvecavity(list* newtetlist, list* outtetlist,
-  queue* flipque)
-{
-  triface newtet, neightet, front, outtet;
-  face auxsh, consh;
-  point pointptr;
-  REAL ori;
-  int i;
-
-  // Clear work list.
-  outtetlist->clear();
-
-  // Classify in- and out- tets in D. Mark and queue classified out-tets.
-  for (i = 0; i < newtetlist->len(); i++) {
-    // Get a new tet t.
-    newtet = * (triface *)(* newtetlist)[i];
-    assert(!isdead(&newtet));
-    // Look for aux subfaces attached at t.
-    for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
-      tspivot(newtet, auxsh);
-      if (auxsh.sh != dummysh) {
-        // Has this side a neighbor n? 
-        sym(newtet, neightet);
-        if (neightet.tet != dummytet) {
-          // Classify t and n (one is "in" and another is "out").
-          // Get the front f.
-          decode((tetrahedron) auxsh.sh[0], front);
-          // Let f face to the inside of C.
-          adjustedgering(front, CW);
-          ori = orient3d(org(front), dest(front), apex(front), oppo(newtet));
-          assert(ori != 0.0);
-          if (ori < 0.0) {
-            // t is in-tet. n is out-tet.
-            outtet = neightet;
-          } else {
-            // n is in-tet. t is out-tet.
-            outtet = newtet;
-          }
-          // Add the out-tet into list.
-          if (!infected(outtet)) {
-            infect(outtet);
-            outtetlist->append(&outtet);
-          }
-        }
-      }
-    }
-  }
-
-  // Find and mark all out-tets.
-  for (i = 0; i < outtetlist->len(); i++) {
-    outtet = * (triface *)(* outtetlist)[i];
-    for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
-      sym(outtet, neightet);
-      // Does the neighbor exist and unmarked?
-      if ((neightet.tet != dummytet) && !infected(neightet)) {
-        // Is it protected by an aux subface?
-        tspivot(outtet, auxsh);
-        if (auxsh.sh == dummysh) {
-          // It's an out-tet.
-          infect(neightet);
-          outtetlist->append(&neightet);
-        }
-      }
-    }
-  }
-
-  // Remove the out- (and hole) tets.
-  for (i = 0; i < outtetlist->len(); i++) {
-    // Get an out-tet t.
-    outtet = * (triface *)(* outtetlist)[i];
-    // Detach t from the in-tets.
-    for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
-      // Is there an aux subface s?
-      tspivot(outtet, auxsh);
-      if (auxsh.sh != dummysh) {
-        // Get the neighbor n.
-        sym(outtet, neightet);
-        assert(!infected(neightet)); // t must be in-tet.
-        // Detach n -x-> t.
-        dissolve(neightet);
-      }
-    }
-    // Dealloc the tet.
-    tetrahedrondealloc(outtet.tet);
-  }
-
-  // Connect the in-tets of C to fronts. Remove aux subfaces and fake tets.
-  for (i = 0; i < newtetlist->len(); i++) {
-    // Get a new tet t.
-    newtet = * (triface *)(* newtetlist)[i];
-    // t may be an out-tet and has got deleted.
-    if (isdead(&newtet)) continue;
-    // t is an in-tet. Look for aux subfaces attached at t.
-    for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
-      // Is there an aux subface s?
-      tspivot(newtet, auxsh);
-      if (auxsh.sh != dummysh) {
-        // Get the front f.
-        decode((tetrahedron) auxsh.sh[0], front);
-        assert((front.tet != dummytet) && !infected(front));
-        // s has fulfilled its duty. Can be deleted.
-        tsdissolve(newtet); // dissolve: t -x-> s.
-        // Delete s.
-        shellfacedealloc(subfaces, auxsh.sh);
-        // Connect the newtet t and front f.
-        // Is there a concrete subface c at f.
-        tspivot(front, consh);
-        if (consh.sh != dummysh) {
-          sesymself(consh);
-          // Bond: t <--> c.
-          tsbond(newtet, consh);
-        }
-        // Does f hold by a fake tet.
-        if (oppo(front) == (point) NULL) {
-          // f is fake.
-          if (consh.sh != dummysh) {
-            sesymself(consh);
-            // Dissolve: c -x-> f.
-            stdissolve(consh);
-          }
-          // Dealloc f.
-          tetrahedrondealloc(front.tet);
-          // f becomes a hull. let 'dummytet' bond to it.
-          dummytet[0] = encode(newtet);
-        } else {
-          // Bond t <--> f.
-          bond(newtet, front);
-        }
-        // t may be non-locally Delaunay and flipable.
-        if (flipque != (queue *) NULL) {
-          enqueueflipface(newtet, flipque);
-        }
-      }
-    }
-    // Let the corners of t2 point to it for fast searching.
-    pointptr = org(newtet);
-    setpoint2tet(pointptr, encode(newtet));
-    pointptr = dest(newtet);
-    setpoint2tet(pointptr, encode(newtet));
-    pointptr = apex(newtet);
-    setpoint2tet(pointptr, encode(newtet));
-    pointptr = oppo(newtet);
-    setpoint2tet(pointptr, encode(newtet));
-  }
-  // The cavity has been re-tetrahedralized.
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// delaunizecavity()    Tetrahedralize a cavity by Delaunay tetrahedra.      //
-//                                                                           //
-// The cavity C is bounded by a set of triangles in 'floorlist' (a list of   //
-// coplanar subfaces) and 'ceillist' (a list of tetrahedral faces lie above  //
-// the subfaces). 'floorptlist' and 'ceilptlist' are the vertices of C.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::delaunizecavity(list* floorlist, list* ceillist,
-  list* ceilptlist, list* floorptlist, list* frontlist, list* misfrontlist,
-  list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
-{
-  int vertnum;
-
-  vertnum = floorptlist->len();
-  vertnum += (ceilptlist != (list *) NULL ? ceilptlist->len() : 0);
-  if (b->verbose > 1) {
-    printf("    Delaunizing cavity (%d floors, %d ceilings, %d vertices).\n",
-           floorlist->len(), ceillist->len(), vertnum);
-  }
-  // Save the size of the largest cavity.
-  if ((floorlist->len() + ceillist->len()) > maxcavfaces) {
-    maxcavfaces = floorlist->len() + ceillist->len();
-  }
-  if (vertnum > maxcavverts) {
-    maxcavverts = vertnum;
-  }
-
-  // Clear these lists.
-  frontlist->clear();
-  misfrontlist->clear();
-  newtetlist->clear();
-
-  // Initialize the cavity C.
-  initializecavity(floorlist, ceillist, frontlist);
-  // Form the D of the vertices of C.
-  delaunizecavvertices(NULL, floorptlist, ceilptlist, newtetlist, flipque);    
-  // Identify faces of C in D.
-  while (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
-    // Remove protecting subfaces, keep new tets.
-    detachauxsubfaces(newtetlist);
-    // Expand C and updateing D.
-    expandcavity(frontlist, misfrontlist, newtetlist, crosstetlist,
-                 missingshqueue, flipque);
-  }
-  // All fronts have identified in D. Get the shape of C by removing out
-  //   tets of C. 'misfrontlist' is reused for removing out tets.
-  carvecavity(newtetlist, misfrontlist, NULL);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// formmissingregion()    Form the missing region.                           //
-//                                                                           //
-// 'missingsh' is a missing subface.  Start from it we can form the missing  //
-// region R (a set of connected missing subfaces).  Because all missing sub- //
-// faces have been marked (infected) before. R can be formed by checking the //
-// neighbors of 'missingsh', and the neighbors of the neighbors, and so on.  //
-// Stop checking further at either a segment or an unmarked subface.         //
-//                                                                           //
-// 'missingshlist' returns R. The edge ring of subfaces of R are oriented in //
-// the same direction. 'equatptlist' returns the vertices of R, each vertex  //
-// is marked with '1' (in 'worklist').                                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::formmissingregion(face* missingsh, list* missingshlist,
-  list* equatptlist, int* worklist)
-{
-  face neighsh, worksh, workseg;
-  point workpt[3];
-  int idx, i, j;
-
-  // Add 'missingsh' into 'missingshlist'.
-  missingshlist->append(missingsh);
-  // Save and mark its three vertices.
-  workpt[0] = sorg(*missingsh);
-  workpt[1] = sdest(*missingsh);
-  workpt[2] = sapex(*missingsh);
-  for (i = 0; i < 3; i++) {
-    idx = pointmark(workpt[i]) - in->firstnumber;
-    worklist[idx] = 1;
-    equatptlist->append(&workpt[i]);
-  }
-  // Temporarily uninfect it (avoid to save it again).
-  suninfect(*missingsh);
-  
-  // Find the other missing subfaces.
-  for (i = 0; i < missingshlist->len(); i++) {
-    // Get a missing subface.
-    worksh = * (face *)(* missingshlist)[i];
-    // Check three neighbors of this face.
-    for (j = 0; j < 3; j++) {
-      sspivot(worksh, workseg);
-      if (workseg.sh == dummysh) {
-        spivot(worksh, neighsh);
-        if (sinfected(neighsh)) {
-          // Find a missing subface, adjust the face orientation.
-          if (sorg(neighsh) != sdest(worksh)) {
-            sesymself(neighsh);
-          }
-          if (b->verbose > 2) {
-            printf("    Add missing subface (%d, %d, %d).\n", 
-                   pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
-                   pointmark(sapex(neighsh)));
-          }
-          missingshlist->append(&neighsh);
-          // Save and mark its apex.
-          workpt[0] = sapex(neighsh);
-          idx = pointmark(workpt[0]) - in->firstnumber;
-          // Has workpt[0] been added?
-          if (worklist[idx] == 0) {
-            worklist[idx] = 1;
-            equatptlist->append(&workpt[0]);
-          }
-          // Temporarily uninfect it (avoid to save it again).
-          suninfect(neighsh);
-        } 
-      } 
-      senextself(worksh);
-    }
-  }
-
-  // R has been formed. Infect missing subfaces again.
-  for (i = 0; i < missingshlist->len(); i++) {
-    worksh = * (face *)(* missingshlist)[i];
-    sinfect(worksh);
-  } 
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// rearrangesubfaces()    Rearrange the set of subfaces of a missing region  //
-//                        so that they conform to the faces of DT.           //
-//                                                                           //
-// The missing region formed by subfaces of 'missingshlist' contains a set   //
-// of degenerate vertices, hence the set of subfaces don't match the set of  //
-// faces in DT.  Instead of forcing them to present in DT, we re-arrange the //
-// connection of them so that the new subfaces conform to the faces of DT.   //
-// 'boundedgelist' is a set of boundary edges of the region, these edges(may //
-// be subsegments) must exist in DT.                                         //
-//                                                                           //
-// On completion, we have created and inserted a set of new subfaces which   //
-// conform to faces of DT. The set of old subfaces in 'missingshlist' are    //
-// deleted. The region vertices in 'equatptlist' are unmarked.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::rearrangesubfaces(list* missingshlist, list* boundedgelist,
-  list* equatptlist, int* worklist)
-{
-  link *boundedgelink;
-  link *newshlink;
-  triface starttet, spintet, neightet, worktet;
-  face shloop, newsh, neighsh, spinsh, worksh;
-  face workseg, casingin, casingout;
-  point torg, tdest, workpt;
-  point spt1, spt2, spt3;
-  enum finddirectionresult collinear;
-  enum shestype shtype;
-  REAL area;
-  bool matchflag, finishflag;
-  int shmark, pbcgp, idx, hitbdry;
-  int i, j;
-
-  // Initialize the boundary edge link.
-  boundedgelink = new link(sizeof(face), NULL, 256);
-  // Initialize the new subface link.
-  newshlink = new link(sizeof(face), NULL, 256);
-  // Remember the type (skinny or not) of replaced subfaces.  They should
-  //   all have the same type since there is no segment inside the region.
-  worksh = * (face *)(* missingshlist)[0];
-  shtype = shelltype(worksh);
-  // The following loop is only for checking purpose.
-  for (i = 1; i < missingshlist->len(); i++) {
-    worksh = * (face *)(* missingshlist)[i];
-    assert(shelltype(worksh) == shtype);
-  }
-  // To avoid compilation warnings.
-  shmark = pbcgp = 0;
-  area = 0.0; 
-
-  // Create an initial boundary link.
-  for (i = 0; i < boundedgelist->len(); i++) {
-    shloop = * (face *)(* boundedgelist)[i];
-    if (i == 0) {
-      // 'shmark' will be set to all new created subfaces.
-      shmark = shellmark(shloop);
-      if (b->quality && varconstraint) {
-        // area will be copied to all new created subfaces.
-        area = areabound(shloop);
-      }
-      if (checkpbcs) {
-        // pbcgp will be copied to all new created subfaces.
-        pbcgp = shellpbcgroup(shloop);
-      }
-      // Get the abovepoint of this facet.
-      abovepoint = facetabovepointarray[shellmark(shloop)];
-      if (abovepoint == (point) NULL) {
-        getfacetabovepoint(&shloop);
-      }
-    }
-    sspivot(shloop, workseg);
-    if (workseg.sh == dummysh) {
-      // This edge is an interior edge.
-      spivot(shloop, neighsh);
-      boundedgelink->add(&neighsh);
-    } else {
-      // This side has a segment, the edge exists. 
-      boundedgelink->add(&shloop);
-    }
-  }
-
-  // Each edge ab of boundedgelink will be finished by finding a vertex c
-  //   which is a vertex of the missing region, such that:
-  //   (1) abc is inside the missing region, i.e., abc intersects at least
-  //       one of missing subfaces (saved in missingshlist);
-  //   (2) abc is not intersect with any previously created new subfaces
-  //       in the missing region (saved in newshlink).
-  //   After abc is created, it will be inserted into both the surface mesh
-  //   and the DT. The boundedgelink will be updated, ab is removed, bc and
-  //   ca will be added if they are open.
-
-  while (boundedgelink->len() > 0) {
-    // Remove an edge (ab) from the link.
-    shloop = * (face *) boundedgelink->del(1);
-    // 'workseg' indicates it is a segment or not.
-    sspivot(shloop, workseg);
-    torg = sorg(shloop);  // torg = a;
-    tdest = sdest(shloop);  // tdest = b; 
-    // Find a tetrahedron containing ab.
-    getsearchtet(torg, tdest, &starttet, &workpt);
-    collinear = finddirection(&starttet, workpt, tetrahedrons->items);
-    if (collinear == LEFTCOLLINEAR) {
-      enext2self(starttet);
-      esymself(starttet);
-    } else if (collinear == TOPCOLLINEAR) {
-      fnextself(starttet);
-      enext2self(starttet);
-      esymself(starttet);
-    }
-    assert(dest(starttet) == workpt);
-    // Checking faces around ab until a valid face is found.
-    matchflag = false;
-    spintet = starttet;
-    hitbdry = 0;
-    do {
-      workpt = apex(spintet);
-      idx = pointmark(workpt) - in->firstnumber;
-      if (worklist[idx] == 1) {
-        // (trog, tdest, workpt) is on the facet. Check if it satisfies (1).
-        finishflag = false;
-        for (i = 0; i < missingshlist->len(); i++) {
-          worksh = * (face *)(* missingshlist)[i];
-          spt1 = sorg(worksh);
-          spt2 = sdest(worksh);
-          spt3 = sapex(worksh);
-          // Does bc intersect the face?
-          if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
-              == INTERSECT) {
-            finishflag = true; break;
-          }
-          // Does ca intersect the face?
-          if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
-              == INTERSECT) {
-            finishflag = true; break;
-          }
-          // Does c inside the face?
-          if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
-              == INTERSECT) {
-            finishflag = true; break;
-          }
-        }
-        if (finishflag) {
-          // Satisfying (1). Check if it satisfies (2).
-          matchflag = true;
-          for (i = 0; i < newshlink->len() && matchflag; i++) {
-            worksh = * (face *) newshlink->getnitem(i + 1);
-            spt1 = sorg(worksh);
-            spt2 = sdest(worksh);
-            spt3 = sapex(worksh);
-            // Does bc intersect the face?
-            if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
-                == INTERSECT) {
-              matchflag = false; break;
-            }
-            // Does ca intersect the face?
-            if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
-                == INTERSECT) {
-              matchflag = false; break;
-            }
-            // Does c inside the face?
-            if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
-                == INTERSECT) {
-              matchflag = false; break;
-            }
-          }
-        }
-        if (matchflag == true) {
-          // Satisfying both (1) and (2). Find abc.
-          break;
-        }
-      }
-      if (!fnextself(spintet)) {
-        hitbdry ++;
-        if (hitbdry < 2) {
-          esym(starttet, spintet);
-          if (!fnextself(spintet)) {
-            hitbdry ++;
-          }
-        }
-      }
-    } while (hitbdry < 2 && apex(spintet) != apex(starttet));
-    assert(matchflag == true);
-    tspivot(spintet, neighsh);
-    if (neighsh.sh != dummysh) {
-      printf("Error:  Invalid PLC.\n");
-      printf("  Facet #%d and facet #%d overlap each other.\n",
-             shellmark(neighsh), shellmark(shloop));
-      printf("  It might be caused by a facet is defined more than once.\n");
-      printf("  Hint:  Use -d switch to find all overlapping facets.\n");
-      exit(1);
-    }
-    // The side of 'spintet' is at which a new subface will be attached.
-    adjustedgering(spintet, CCW);
-    // Create the new subface.
-    makeshellface(subfaces, &newsh);
-    setsorg(newsh, org(spintet));
-    setsdest(newsh, dest(spintet));
-    setsapex(newsh, apex(spintet));
-    if (b->quality && varconstraint) {
-      setareabound(newsh, area);
-    }
-    if (checkpbcs) {
-      setshellpbcgroup(newsh, pbcgp);
-    }
-    setshellmark(newsh, shmark);
-    setshelltype(newsh, shtype);  // It may be a skinny subface.
-    // Add newsh into newshlink for intersecting checking.
-    newshlink->add(&newsh);
-    // Insert it into the current mesh.
-    tsbond(spintet, newsh);
-    sym(spintet, neightet);
-    if (neightet.tet != dummytet) {
-      sesym(newsh, neighsh);
-      tsbond(neightet, neighsh);
-    }
-    // Insert it into the surface mesh.
-    sspivot(shloop, workseg);
-    if (workseg.sh == dummysh) {
-      sbond(shloop, newsh);
-    } else {
-      // There is a subsegment, 'shloop' is the subface which is going to
-      //   die. Insert the 'newsh' at the place of 'shloop' into its face
-      //   link, so as to dettach 'shloop'.   The original connection is:
-      //   -> casingin -> shloop -> casingout ->, it will be changed with:
-      //   -> casingin ->  newsh -> casingout ->.  Pay attention to the
-      //   case when this subsegment is dangling in the mesh, i.e., 'shloop'
-      //   is bonded to itself.
-      spivot(shloop, casingout);
-      if (shloop.sh != casingout.sh) {
-        // 'shloop' is not bonded to itself.
-        spinsh = casingout;
-        do {
-          casingin = spinsh;
-          spivotself(spinsh);
-        } while (sapex(spinsh) != sapex(shloop));
-        assert(casingin.sh != shloop.sh); 
-        // Bond casingin -> newsh -> casingout.
-        sbond1(casingin, newsh);
-        sbond1(newsh, casingout);
-      } else {
-        // Bond newsh -> newsh.
-        sbond(newsh, newsh);
-      }
-      // Bond the segment.
-      ssbond(newsh, workseg);
-    }
-    // Check other two sides of this new subface.  If a side is not bonded
-    //   to any edge in the link, it will be added to the link.
-    for (i = 0; i < 2; i++) {
-      if (i == 0) {
-        senext(newsh, worksh);
-      } else {
-        senext2(newsh, worksh);
-      }
-      torg = sorg(worksh);
-      tdest = sdest(worksh);
-      finishflag = false;
-      for (j = 0; j < boundedgelink->len() && !finishflag; j++) {
-        neighsh = * (face *) boundedgelink->getnitem(j + 1);
-        if ((sorg(neighsh) == torg && sdest(neighsh) == tdest) ||
-            (sorg(neighsh) == tdest && sdest(neighsh) == torg)) {
-          // Find a boundary edge.  Bond them and exit the loop.
-          sspivot(neighsh, workseg);
-          if (workseg.sh == dummysh) {
-            sbond(neighsh, worksh);
-          } else {
-            // There is a subsegment, 'neighsh' is the subface which is
-            //   going to die. Do the same as above for 'worksh'.
-            spivot(neighsh, casingout);
-            if (neighsh.sh != casingout.sh) {
-              // 'neighsh' is not bonded to itself.
-              spinsh = casingout;
-              do {
-                casingin = spinsh;
-                spivotself(spinsh);
-              } while (sapex(spinsh) != sapex(neighsh));
-              assert(casingin.sh != neighsh.sh); 
-              // Bond casingin -> worksh -> casingout.
-              sbond1(casingin, worksh);
-              sbond1(worksh, casingout);
-            } else {
-              // Bond worksh -> worksh.
-              sbond(worksh, worksh);
-            }
-            // Bond the segment.
-            ssbond(worksh, workseg);
-          }
-          // Remove this boundary edge from the link.
-          boundedgelink->del(j + 1);
-          finishflag = true;
-        }
-      }
-      if (!finishflag) {
-        // It's a new boundary edge, add it to link.
-        boundedgelink->add(&worksh);
-      }
-    }
-  }
-
-  // Deallocate the set of old missing subfaces.
-  for (i = 0; i < missingshlist->len(); i++) {
-    worksh = * (face *)(* missingshlist)[i];
-    shellfacedealloc(subfaces, worksh.sh);
-  }
-  // Unmark region vertices in 'worklist'.
-  for (i = 0; i < equatptlist->len(); i++) {
-    workpt = * (point *)(* equatptlist)[i];
-    idx = pointmark(workpt) - in->firstnumber;
-    worklist[idx] = 0;
-  }
-
-  delete boundedgelink;
-  delete newshlink;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// scoutcrossingedge()    Search an edge crossing the missing region.        //
-//                                                                           //
-// 'missingshlist' forms the missing region R. This routine searches for an  //
-// edge crossing R.  It first forms a 'boundedgelist' consisting of the      //
-// boundary edges of R. Such edges are existing in CDT.  A crossing edge is  //
-// found by rotating faces around one of the boundary edges. It is possible  //
-// there is no edge crosses R (e.g. R has a degenerate point set).           //
-//                                                                           //
-// If find a croosing edge, return TRUE, 'crossedgelist' contains this edge. //
-// Otherwise, return FALSE.                                                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::scoutcrossingedge(list* missingshlist, list* boundedgelist,
-  list* crossedgelist, int* worklist)
-{
-  triface starttet, spintet, worktet;
-  face startsh, neighsh, worksh, workseg;
-  point torg, tdest, tapex;
-  point workpt[3], pa, pb, pc;
-  enum finddirectionresult collinear;
-  REAL ori1, ori2;
-  bool crossflag;
-  int hitbdry;
-  int i, j, k;
-
-  // Form the 'boundedgelist'. Loop through 'missingshlist', check each
-  //   edge of these subfaces. If an edge is a segment or the neighbor
-  //   subface is uninfected, add it to 'boundedgelist'.
-  for (i = 0; i < missingshlist->len(); i++) {
-    worksh = * (face *)(* missingshlist)[i];
-    for (j = 0; j < 3; j++) {
-      sspivot(worksh, workseg);
-      if (workseg.sh == dummysh) {
-        spivot(worksh, neighsh);
-        if (!sinfected(neighsh)) {
-          boundedgelist->append(&worksh);
-        }
-      } else {
-        boundedgelist->append(&worksh);
-      }
-      senextself(worksh);
-    }
-  }
-
-  crossflag = false;
-  // Find a crossing edge. It is possible there is no such edge. We need to
-  //   loop through all edges of 'boundedgelist' for sure we don't miss any.
-  for (i = 0; i < boundedgelist->len() && !crossflag; i++) {
-    startsh = * (face *)(* boundedgelist)[i];
-    // 'startsh' (abc) holds an existing edge of the DT, find it.
-    torg = sorg(startsh);
-    tdest = sdest(startsh);
-    tapex = sapex(startsh);
-    getsearchtet(torg, tdest, &starttet, &workpt[0]);
-    collinear = finddirection(&starttet, workpt[0], tetrahedrons->items);
-    if (collinear == LEFTCOLLINEAR) {
-      enext2self(starttet);
-      esymself(starttet);
-    } else if (collinear == TOPCOLLINEAR) {
-      fnextself(starttet);
-      enext2self(starttet);
-      esymself(starttet);
-    }
-#ifdef SELF_CHECK
-    assert(dest(starttet) == workpt[0]);
-#endif
-    // Now starttet holds edge ab. Find is edge de crossing R.
-    spintet = starttet;
-    hitbdry = 0;
-    do {
-      if (fnextself(spintet)) {
-        // splittet = abde. Check if de crosses abc.
-        workpt[1] = apex(spintet);  // workpt[1] = d.
-        workpt[2] = oppo(spintet);  // workpt[2] = e.
-        j = pointmark(workpt[1]) - in->firstnumber;
-        k = pointmark(workpt[2]) - in->firstnumber;
-        if (worklist[j] == 1) {
-          ori1 = 0.0; // d is a vertex of the missing region.
-        } else {
-          // Get the orientation of d wrt. abc.
-          ori1 = orient3d(torg, tdest, tapex, workpt[1]);
-        }
-        if (worklist[k] == 1) {
-          ori2 = 0.0; // e is a vertex of the missing region.
-        } else {
-          // Get the orientation of e wrt. abc.
-          ori2 = orient3d(torg, tdest, tapex, workpt[2]);
-        }
-        // Only do check if d and e locate on different sides of abc.
-        if (ori1 * ori2 < 0.0) {
-          // Check if de crosses any subface of R.
-          for (j = 0; j < missingshlist->len(); j++) {
-            worksh = * (face *)(* missingshlist)[j];
-            pa = sorg(worksh);
-            pb = sdest(worksh);
-            pc = sapex(worksh);
-            crossflag = (tri_tri_inter(pa, pb, pc, workpt[0], workpt[1],
-                                       workpt[2]) == INTERSECT);
-            if (crossflag) {
-              // Find a crossing edge. We're done.
-              worktet = spintet;
-              adjustedgering(worktet, CCW);
-              enextfnextself(worktet);
-              enextself(worktet);
-              // Add this edge (worktet) into 'crossedgelist'.
-              crossedgelist->append(&worktet);
-              break;
-            }
-          }
-          if (crossflag) break;
-        }
-        if (apex(spintet) == apex(starttet)) break;
-      } else {
-        hitbdry++;
-        // It is only possible to hit boundary once.
-        if (hitbdry < 2) {
-          esym(starttet, spintet);
-        }
-      }
-    } while (hitbdry < 2);
-  }
-
-  return crossflag;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// formcavity()    Form the cavity for recovering the missing region.        //
-//                                                                           //
-// The cavity C is bounded by faces of current CDT.  All tetrahedra inside C //
-// will be removed, intead a set of constrained Delaunay tetrahedra will be  //
-// filled in and the missing region are recovered.                           //
-//                                                                           //
-// 'missingshlist' contains a set of subfaces forming the missing region R.  //
-// C is formed by first finding all the tetrahedra in CDT that intersect the //
-// relative interior of R; then deleting them from the CDT, this will form C //
-// inside the CDT. At the beginning, 'crossedgelist' contains an edge which  //
-// is crossing R. All tets containing this edge must cross R. Start from it, //
-// other crossing edges can be found incrementally.  The discovered crossing //
-// tets are saved in 'crosstetlist'.                                         //
-//                                                                           //
-// Notice that not all tets in 'crosstetlist' are crossing R. The discovered //
-// tets are connected each other. However, there may be other tets crossing  //
-// R but disjoint with the found tets. Due to this fact we need to check the //
-// 'missingshlist' once more. Only recover those subfaces which are crossed  //
-// by the set of discovered tets, i.e., R may be shrinked to conform the set //
-// of discovered tets. The extra subfaces of R will be recovered later.      //
-//                                                                           //
-// Notice that some previous recovered subfaces may completely included in C.//
-// This can happen when R is very big and these subfaces lie above R and so  //
-// close to it. Such subfaces have to be queued (and sinfected()) to recover //
-// them later. Otherwise, we lost the connection to these subfaces forever.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::formcavity(list* missingshlist, list* crossedgelist,
-  list* equatptlist, list* crossshlist, list* crosstetlist,
-  list* belowfacelist, list* abovefacelist, list* horizptlist,
-  list* belowptlist, list* aboveptlist, queue* missingshqueue, int* worklist)
-{
-  triface starttet, spintet, neightet, worktet;
-  face startsh, neighsh, worksh, workseg;
-  point torg, tdest, tapex, workpt[3];
-  REAL checksign, orgori, destori;
-  bool crossflag, inlistflag;
-  bool belowflag, aboveflag;
-  int idx, share;
-  int i, j, k;
-
-  // Get a face at horizon.
-  startsh = * (face *)(* missingshlist)[0];
-  torg = sorg(startsh);
-  tdest = sdest(startsh);
-  tapex = sapex(startsh);
-
-  // Collect the set of crossing tetrahedra by rotating crossing edges.
-  for (i = 0; i < crossedgelist->len(); i++) {
-    // Get a tet abcd, ab is a crossing edge.
-    starttet = * (triface *)(* crossedgelist)[i];
-    adjustedgering(starttet, CCW);
-    if (b->verbose > 2) {
-      printf("    Collect tets containing edge (%d, %d).\n",
-             pointmark(org(starttet)), pointmark(dest(starttet)));
-    }
-    orgori = orient3d(torg, tdest, tapex, org(starttet));
-    destori = orient3d(torg, tdest, tapex, dest(starttet));
-#ifdef SELF_CHECK
-    assert(orgori * destori < 0.0); 
-#endif
-    spintet = starttet;
-    do {
-      // The face rotation should not meet boundary.
-      fnextself(spintet); 
-      // Check the validity of the PLC.
-      tspivot(spintet, worksh);
-      if (worksh.sh != dummysh) {
-        printf("Error:  Invalid PLC.\n");
-        printf("  Two subfaces (%d, %d, %d) and (%d, %d, %d)\n",
-               pointmark(torg), pointmark(tdest), pointmark(tapex),
-               pointmark(sorg(worksh)), pointmark(sdest(worksh)),
-               pointmark(sapex(worksh)));
-        printf("  are found intersecting each other.\n");
-        printf("  Hint:  Use -d switch to find all intersecting facets.\n");
-        terminatetetgen(1);
-      }
-      if (!infected(spintet)) {
-        if (b->verbose > 2) {
-          printf("      Add crossing tet (%d, %d, %d, %d).\n",
-                 pointmark(org(spintet)), pointmark(dest(spintet)),
-                 pointmark(apex(spintet)), pointmark(oppo(spintet)));
-        }
-        infect(spintet);
-        crosstetlist->append(&spintet);
-      }
-      // Check whether other two edges of 'spintet' is a crossing edge.
-      //   It can be quickly checked from the apex of 'spintet', if it is
-      //   not on the facet, then there exists a crossing edge.
-      workpt[0] = apex(spintet);
-      idx = pointmark(workpt[0]) - in->firstnumber;
-      if (worklist[idx] != 1) {
-        // Either edge (dest, apex) or edge (apex, org) crosses.
-        checksign = orient3d(torg, tdest, tapex, workpt[0]);
-#ifdef SELF_CHECK
-        assert(checksign != 0.0);
-#endif
-        if (checksign * orgori < 0.0) {
-          enext2(spintet, worktet); // edge (apex, org).
-          workpt[1] = org(spintet);
-        } else {
-#ifdef SELF_CHECK
-          assert(checksign * destori < 0.0);
-#endif
-          enext(spintet, worktet);  // edge (dest, apex).
-          workpt[1] = dest(spintet);
-        }
-        // 'worktet' represents the crossing edge. Add it into list only
-        //   it doesn't exist in 'crossedgelist'.
-        inlistflag = false;
-        for (j = 0; j < crossedgelist->len() && !inlistflag; j++) {
-          neightet = * (triface *)(* crossedgelist)[j];
-          if (org(neightet) == workpt[0]) {
-            if (dest(neightet) == workpt[1]) inlistflag = true;
-          } else if (org(neightet) == workpt[1]) {
-            if (dest(neightet) == workpt[0]) inlistflag = true;
-          }
-        }
-        if (!inlistflag) {
-          crossedgelist->append(&worktet);
-        }
-      }
-    } while (apex(spintet) != apex(starttet));
-  }
-
-  // Identifying the boundary faces and vertices of C. Sort them into
-  //   'abovefacelist', 'aboveptlist, 'belowfacelist', and 'belowptlist',
-  //    respectively. "above" and "below" are wrt.(torg, tdest, tapex). 
-  for (i = 0; i < crosstetlist->len(); i++) {
-    // Get a tet abcd, ab is the crossing edge.
-    starttet = * (triface *)(* crosstetlist)[i];
-#ifdef SELF_CHECK
-    assert(infected(starttet));
-#endif
-    adjustedgering(starttet, CCW);
-    // abc and abd are sharing the crossing edge, the two neighbors must
-    //   be crossing tetrahedra too. They can't be boundaries of C.
-    for (j = 0; j < 2; j++) {
-      if (j == 0) {
-        enextfnext(starttet, worktet); // Check bcd.
-      } else {
-        enext2fnext(starttet, worktet); // Check acd. 
-      } 
-      sym(worktet, neightet);
-      // If the neighbor doesn't exist or exists but doesn't be infected,
-      //   it's a boundary face of C, save it.
-      if ((neightet.tet == dummytet) || !infected(neightet)) {
-        workpt[0] = org(worktet);
-        workpt[1] = dest(worktet);
-        workpt[2] = apex(worktet);
-        belowflag = aboveflag = false;
-        share = 0;
-        for (k = 0; k < 3; k++) {
-          idx = pointmark(workpt[k]) - in->firstnumber;
-          if (worklist[idx] == 0) {
-            // It's not a vertices of facet, find which side it lies.
-            checksign = orient3d(torg, tdest, tapex, workpt[k]);
-#ifdef SELF_CHECK
-            assert(checksign != 0.0);
-#endif
-            if (checksign > 0.0) {
-              // It lies "below" the facet wrt. 'startsh'.
-              worklist[idx] = 2;
-              belowptlist->append(&workpt[k]);
-            } else if (checksign < 0.0) {
-              // It lies "above" the facet wrt. 'startsh'.
-              worklist[idx] = 3;
-              aboveptlist->append(&workpt[k]);
-            }
-          }
-          if (worklist[idx] == 2) {
-            // This face lies "below" the facet wrt. 'startsh'.
-            belowflag = true;
-          } else if (worklist[idx] == 3) {
-            // This face lies "above" the facet wrt. 'startsh'.
-            aboveflag = true;
-          } else {
-#ifdef SELF_CHECK
-            // In degenerate case, this face may just be the equator.
-            assert(worklist[idx] == 1);
-#endif
-            share++;
-          }
-        }
-#ifdef SELF_CHECK
-        // The degenerate case has been ruled out.
-        assert(share < 3);
-        // Only one flag is possible for a cavity face.
-        assert(belowflag ^ aboveflag); 
-#endif
-        if (belowflag) {
-          belowfacelist->append(&worktet);
-        } else if (aboveflag) {
-          abovefacelist->append(&worktet);
-        }
-      }
-    }
-  }
-
-  // Shrink R if not all its subfaces are crossing by the discovered tets.
-  //   'crossshlist' and 'horizptlist' represent the set of subfaces and
-  //   vertices of the shrinked missing region, respectively.
-  for (i = 0; i < missingshlist->len(); i++) {
-    worksh = * (face *)(* missingshlist)[i];
-#ifdef SELF_CHECK
-    assert(sinfected(worksh));
-#endif
-    workpt[0] = sorg(worksh);
-    workpt[1] = sdest(worksh);
-    workpt[2] = sapex(worksh);
-    crossflag = false;
-    for (j = 0; j < crosstetlist->len() && !crossflag; j++) {
-      // Get a tet abcd, ab is a crossing edge.
-      starttet = * (triface *)(* crosstetlist)[j];
-      adjustedgering(starttet, CCW);
-      // Only need to check two sides of worktet.
-      for (k = 0; k < 2 && !crossflag; k++) {
-        if (k == 0) {
-          worktet = starttet; // Check abc.
-        } else {
-          fnext(starttet, worktet); // Check abd.
-        }
-        crossflag = tritritest(&worktet, workpt[0], workpt[1], workpt[2]);
-      }
-    }
-    if (crossflag) {
-      // 'worksh' is crossed by 'worktet', uninfect it.
-      suninfect(worksh);
-      crossshlist->append(&worksh);
-      // Add its corners into 'horizptlist'.
-      for (k = 0; k < 3; k++) {
-        idx = pointmark(workpt[k]) - in->firstnumber;
-        if (worklist[idx] != 4) {
-          worklist[idx] = 4;
-          horizptlist->append(&workpt[k]);
-        }
-      }
-    } 
-  }
-
-  // Check 'crossingtetlist'. Queue subfaces inside them.
-  for (i = 0; i < crosstetlist->len(); i++) {
-    starttet = * (triface *)(* crosstetlist)[i];
-    for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
-      sym(starttet, neightet);
-      // If the neighbor exist and is infected, check it.
-      if ((neightet.tet != dummytet) && infected(neightet)) {
-        tspivot(starttet, worksh);
-        if (worksh.sh != dummysh) {
-          // Temporarily remove worksh. Make it missing. recover it later.
-          if (b->verbose > 2) {
-            printf("    Queuing subface (%d, %d, %d).\n",
-                   pointmark(sorg(worksh)), pointmark(sdest(worksh)),
-                   pointmark(sapex(worksh)));
-          }
-          tsdissolve(neightet);
-          tsdissolve(starttet);
-          // Detach tets at the both sides of this subface.
-          stdissolve(worksh);
-          sesymself(worksh);
-          stdissolve(worksh);
-          sinfect(worksh);
-          missingshqueue->push(&worksh);
-        }
-      }
-    }
-  }
-
-  // Clear flags set in 'worklist'.
-  for (i = 0; i < equatptlist->len(); i++) {
-    workpt[0] = * (point *)(* equatptlist)[i];
-    idx = pointmark(workpt[0]) - in->firstnumber;
-#ifdef SELF_CHECK
-    assert((worklist[idx] == 1) || (worklist[idx] == 4));
-#endif
-    worklist[idx] = 0;
-  }
-  for (i = 0; i < belowptlist->len(); i++) {
-    workpt[0] = * (point *)(* belowptlist)[i];
-    idx = pointmark(workpt[0]) - in->firstnumber;
-#ifdef SELF_CHECK
-    assert(worklist[idx] == 2);
-#endif
-    worklist[idx] = 0;
-  }
-  for (i = 0; i < aboveptlist->len(); i++) {
-    workpt[0] = * (point *)(* aboveptlist)[i];
-    idx = pointmark(workpt[0]) - in->firstnumber;
-#ifdef SELF_CHECK
-    assert(worklist[idx] == 3);
-#endif
-    worklist[idx] = 0;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertallsubfaces()    Insert all subfaces, queue missing subfaces.       //
-//                                                                           //
-// Loop through all subfaces, insert each into the DT. If one already exists,//
-// bond it to the tetrahedra having it. Otherwise, it is missing, infect it  //
-// and save it in 'missingshqueue'.                                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::insertallsubfaces(queue* missingshqueue)
-{
-  triface searchtet;
-  face subloop;
-
-  searchtet.tet = (tetrahedron *) NULL;
-  subfaces->traversalinit();
-  subloop.sh = shellfacetraverse(subfaces);
-  while (subloop.sh != (shellface *) NULL) {
-    if (!insertsubface(&subloop, &searchtet)) {
-      if (b->verbose > 1) {
-        printf("    Queuing subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
-               pointmark(sdest(subloop)), pointmark(sapex(subloop)));
-      }
-      sinfect(subloop);
-      missingshqueue->push(&subloop);
-    }
-    subloop.sh = shellfacetraverse(subfaces);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// constrainedfacets()    Recover subfaces in a Delaunay tetrahedralization. //
-//                                                                           //
-// This routine creates a CDT by incrementally updating a DT D into a CDT T. //
-// The process of recovering facets can be imagined by "merging" the surface //
-// mesh F into D. At the beginning, F and D are completely seperated.  Some  //
-// faces of them are matching some are not because they are crossed by some  //
-// tetrahedra of D. The non-matching subfaces will be forced to appear in T  //
-// by locally retetrahedralizing the regions where F and D are intersecting. //
-//                                                                           //
-// When a subface s of F is found missing in D, probably some other subfaces //
-// near to s are missing too.  The set of adjoining coplanar missing faces   //
-// forms a missing region R (R may not simply connected).                    //
-//                                                                           //
-// There are two possibilities can result a mssing region R: (1) Some edges  //
-// of D cross R; (2) No edge of D crosses R, but some faces of D spans R, ie,//
-// D is locally degenerate at R. In case (1), D is modified so that it resp- //
-// ects R (done by a cavity retetrahedralization algorithm).  In case (2), F //
-// is modified so that the set of subfaces of R matches faces in D (done by  //
-// a face rearrangment algorithm).                                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::constrainedfacets()
-{
-  queue *missingshqueue, *flipque;
-  list *missingshlist, *equatptlist;
-  list *boundedgelist, *crossedgelist, *crosstetlist;
-  list *crossshlist, *belowfacelist, *abovefacelist;
-  list *horizptlist, *belowptlist, *aboveptlist;
-  list *frontlist, *misfrontlist, *newtetlist;
-  triface searchtet, worktet;
-  face subloop, worksh;
-  int *worklist;
-  int i;
-
-  if (!b->quiet) {
-    printf("Constraining facets.\n");
-  }
-
-  // Initialize queues.
-  missingshqueue = new queue(sizeof(face));
-  flipque = new queue(sizeof(badface));
-  // Initialize the working lists.
-  missingshlist = new list(sizeof(face), NULL);
-  boundedgelist = new list(sizeof(face), NULL);
-  crossedgelist = new list(sizeof(triface), NULL);
-  equatptlist = new list("point *");
-  crossshlist = new list(sizeof(face), NULL);
-  crosstetlist = new list(sizeof(triface), NULL);
-  belowfacelist = new list(sizeof(triface), NULL);
-  abovefacelist = new list(sizeof(triface), NULL);
-  horizptlist = new list("point *");
-  belowptlist = new list("point *");
-  aboveptlist = new list("point *");
-  frontlist = new list(sizeof(triface), NULL);
-  misfrontlist = new list(sizeof(triface), NULL);
-  newtetlist = new list(sizeof(triface), NULL);
-  // Initialize the array for marking vertices.
-  worklist = new int[points->items + 1];
-  for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
-
-  // Compute a mapping from points to tetrahedra for fast searching.
-  makepoint2tetmap();
-  
-  // Match subfaces in D, queue all missing subfaces.
-  insertallsubfaces(missingshqueue);
-
-  // Recover all missing subfaces.
-  while (!missingshqueue->empty()) {
-    // Get a queued face s.
-    subloop = * (face *) missingshqueue->pop();
-    // s may have been deleted in a face rearrangment operation.
-    if (isdead(&subloop)) continue;
-    // s may have been recovered in a previous missing region.
-    if (!sinfected(subloop)) continue;
-    // s may match a face in D now due to previous transformations.
-    if (insertsubface(&subloop, &searchtet)) {
-      suninfect(subloop);
-      continue;
-    }
-    if (b->verbose > 1) {
-      printf("    Recover subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
-             pointmark(sdest(subloop)), pointmark(sapex(subloop)));
-    }
-    // Form the missing region R containing s.
-    formmissingregion(&subloop, missingshlist, equatptlist, worklist);
-    // Is R crossing by any tetrahedron?
-    if (scoutcrossingedge(missingshlist, boundedgelist, crossedgelist,
-                          worklist)) {
-      // Form the cavity C containing R.
-      formcavity(missingshlist, crossedgelist, equatptlist, crossshlist,
-                 crosstetlist, belowfacelist, abovefacelist, horizptlist,
-                 belowptlist, aboveptlist, missingshqueue, worklist);
-      // Recover the above part of C.
-      delaunizecavity(crossshlist, abovefacelist, aboveptlist, horizptlist,
-                      frontlist, misfrontlist, newtetlist, crosstetlist,
-                      missingshqueue, flipque);
-      // Inverse the direction of subfaces in R.
-      for (i = 0; i < crossshlist->len(); i++) {
-        worksh = * (face *)(* crossshlist)[i];
-        sesymself(worksh);
-        * (face *)(* crossshlist)[i] = worksh;
-      }
-      // Recover the below part of C.
-      delaunizecavity(crossshlist, belowfacelist, belowptlist, horizptlist,
-                      frontlist, misfrontlist, newtetlist, crosstetlist,
-                      missingshqueue, flipque);
-      // Delete tetrahedra in C.
-      for (i = 0; i < crosstetlist->len(); i++) {
-        worktet = * (triface *)(* crosstetlist)[i];
-        tetrahedrondealloc(worktet.tet);
-      }
-      // There may have some un-recovered subfaces of R. Put them back into
-      //   queue. Otherwise, they will be missing on the boundary.
-      for (i = 0; i < missingshlist->len(); i++) {
-        worksh = * (face *)(* missingshlist)[i];
-        if (sinfected(worksh)) {
-          // An unrecovered subface, put it back into queue.
-          missingshqueue->push(&worksh);
-        }
-      }
-      crossshlist->clear();
-      belowfacelist->clear();
-      abovefacelist->clear();
-      horizptlist->clear();
-      belowptlist->clear();
-      aboveptlist->clear();
-      crosstetlist->clear();
-    } else {
-      // No. Rearrange subfaces of F conforming to that of D in R. It can
-      //   happen when the facet has non-coplanar vertices.
-      rearrangesubfaces(missingshlist, boundedgelist, equatptlist, worklist);
-    }
-    // Clear all working lists.
-    missingshlist->clear();
-    boundedgelist->clear();
-    crossedgelist->clear();
-    equatptlist->clear();
-  }
-
-  // Subfaces have been merged into D.
-  checksubfaces = 1;
-
-  if (b->verbose > 0) {
-    printf("  The biggest cavity: %d faces, %d vertices\n", maxcavfaces,
-           maxcavverts);
-    printf("  Enlarged %d times\n", expcavcount);
-  }
-
-  delete missingshqueue;
-  delete flipque;
-  delete missingshlist;
-  delete boundedgelist;
-  delete crossedgelist;
-  delete equatptlist;
-  delete crossshlist;
-  delete crosstetlist;
-  delete belowfacelist;
-  delete abovefacelist;
-  delete horizptlist;
-  delete belowptlist;
-  delete aboveptlist;
-  delete frontlist;
-  delete misfrontlist;
-  delete newtetlist;
-  delete [] worklist;
-}
-
-//
-// End of facet recovery routines
-//
-
-//
-// Begin of carving out holes and concavities routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// 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.            //
-//                                                                           //
-// Memorypool 'viri' is used to return all the infected tetrahedra.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::infecthull(memorypool *viri)
-{
-  triface tetloop, tsymtet;
-  tetrahedron **deadtet;
-  face hullface;
-  // point horg, hdest, hapex;
-
-  if (b->verbose > 0) {
-    printf("  Marking concavities 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) {
-          // 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 (shellmark(hullface) == 0) {
-            setshellmark(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 tets to any neighbors not  //
-//             protected by subfaces.                                        //
-//                                                                           //
-// This routine 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. 'viri' returns //
-// all infected tetrahedra which are outside the domian.                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::plague(memorypool *viri)
-{
-  tetrahedron **virusloop;
-  tetrahedron **deadtet;
-  triface testtet, neighbor;
-  face neighsh, testseg;
-  face spinsh, casingin, casingout;
-  int firstdadsub;
-  int i;
-
-  if (b->verbose > 0) {
-    printf("  Marking neighbors of marked tetrahedra.\n");
-  }
-  firstdadsub = 0;
-  // 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;
-    // Temporarily uninfect this tetrahedron, not necessary.
-    uninfect(testtet);
-    // 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, neighsh);
-      // Check if the neighbor is nonexistent or already infected.
-      if ((neighbor.tet == dummytet) || infected(neighbor)) {
-        if (neighsh.sh != dummysh) {
-          // There is a subface separating the tetrahedron from its neighbor,
-          //   but both tetrahedra are dying, so the subface dies too.
-          // Before deallocte this subface, dissolve the connections between
-          //   other subfaces, subsegments and tetrahedra.
-          neighsh.shver = 0;
-          if (!firstdadsub) {
-            firstdadsub = 1; // Report the problem once.
-            if (!b->quiet) {
-              printf("Warning:  Detecting an open face (%d, %d, %d).\n",
-                     pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
-                     pointmark(sapex(neighsh)));
-            }
-          }
-          // For keep the same enext() direction.
-          findedge(&testtet, sorg(neighsh), sdest(neighsh));
-          for (i = 0; i < 3; i++) {
-            sspivot(neighsh, testseg);
-            if (testseg.sh != dummysh) {
-              // A subsegment is found at this side, dissolve this subface
-              //   from the face link of this subsegment.
-              testseg.shver = 0;
-              spinsh = neighsh;
-              if (sorg(spinsh) != sorg(testseg)) {
-                sesymself(spinsh);
-              }
-              spivot(spinsh, casingout);
-              if (casingout.sh == spinsh.sh) {
-                // This is a trivial face link, only 'neighsh' itself,
-                //   the subsegment at this side is also died.
-                shellfacedealloc(subsegs, testseg.sh);
-              } else {
-                spinsh = casingout;
-                do {
-                  casingin = spinsh;
-                  spivotself(spinsh);
-                } while (spinsh.sh != neighsh.sh);
-                // Set the link casingin->casingout.
-                sbond1(casingin, casingout);
-                // Bond the subsegment anyway.
-                ssbond(casingin, testseg);
-              }
-            }
-            senextself(neighsh);
-            enextself(testtet);
-          }
-          if (neighbor.tet != dummytet) {
-            // Make sure the subface doesn't get deallocated again later
-            //   when the infected neighbor is visited.
-            tsdissolve(neighbor);
-          }
-          // This subface has been separated.
-          if (in->mesh_dim > 2) {
-            shellfacedealloc(subfaces, neighsh.sh);
-          } else {
-            // Dimension is 2. keep it for output.
-            // Dissolve tets at both sides of this subface.
-            stdissolve(neighsh);
-            sesymself(neighsh);
-            stdissolve(neighsh);
-          }
-        }
-      } else {                   // The neighbor exists and is not infected.
-        if (neighsh.sh == dummysh) {
-          // There is no subface protecting the neighbor, infect it.
-          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(neighsh);
-          // The subface becomes a boundary.  Set markers accordingly.
-          if (shellmark(neighsh) == 0) {
-            setshellmark(neighsh, 1);
-          }
-          // This side becomes hull. Update the handle in dummytet.
-          dummytet[0] = encode(neighbor);
-        }
-      }
-    }
-    // Remark the tetrahedron as infected, so it doesn't get added to the
-    //   virus pool again.
-    infect(testtet);
-    virusloop = (tetrahedron **) viri->traverse();
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// 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 attri- //
-// bute and/or a volume constraint through a (facet-bounded) region.  The    //
-// second phase uninfects all infected tetrahedra, returning them to normal. //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::
-regionplague(memorypool *regionviri, REAL attribute, REAL volume)
-{
-  tetrahedron **virusloop;
-  tetrahedron **regiontet;
-  triface testtet, neighbor;
-  face neighsh;
-
-  if (b->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.
-  regionviri->traversalinit();
-  virusloop = (tetrahedron **) regionviri->traverse();
-  while (virusloop != (tetrahedron **) NULL) {
-    testtet.tet = *virusloop;
-    // Temporarily uninfect this tetrahedron, not necessary.
-    uninfect(testtet);
-    if (b->regionattrib) {
-      // Set an attribute.
-      setelemattribute(testtet.tet, in->numberoftetrahedronattributes,
-                       attribute);
-    }
-    if (b->varvolume) {
-      // Set a volume constraint.
-      setvolumebound(testtet.tet, volume);
-    }
-    // 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, neighsh);
-      // 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)
-          && (neighsh.sh == dummysh)) {
-        // Infect the neighbor.
-        infect(neighbor);
-        // Ensure that the neighbor's neighbors will be infected.
-        regiontet = (tetrahedron **) regionviri->alloc();
-        *regiontet = neighbor.tet;
-      }
-    }
-    // Remark the tetrahedron as infected, so it doesn't get added to the
-    //   virus pool again.
-    infect(testtet);
-    virusloop = (tetrahedron **) regionviri->traverse();
-  }
-
-  // Uninfect all tetrahedra.
-  if (b->verbose > 1) {
-    printf("  Unmarking marked tetrahedra.\n");
-  }
-  regionviri->traversalinit();
-  virusloop = (tetrahedron **) regionviri->traverse();
-  while (virusloop != (tetrahedron **) NULL) {
-    testtet.tet = *virusloop;
-    uninfect(testtet);
-    virusloop = (tetrahedron **) regionviri->traverse();
-  }
-  // Empty the virus pool.
-  regionviri->restart();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// removeholetets()    Remove tetrahedra which are outside the domain.       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::removeholetets(memorypool* viri)
-{
-  tetrahedron **virusloop;
-  triface testtet, neighbor;
-  point checkpt;
-  int *tetspernodelist;
-  int i, j;
-
-  if (b->verbose > 0) {
-    printf("  Deleting marked tetrahedra.\n");
-  }
-
-  // Create and initialize 'tetspernodelist'.
-  tetspernodelist = new int[points->items + 1];
-  for (i = 0; i < points->items + 1; i++) tetspernodelist[i] = 0;
-  
-  // Loop the tetrahedra list, counter the number of tets sharing each node.
-  tetrahedrons->traversalinit();
-  testtet.tet = tetrahedrontraverse();
-  while (testtet.tet != (tetrahedron *) NULL) {
-    // Increment the number of sharing tets for each endpoint.
-    for (i = 0; i < 4; i++) {
-      j = pointmark((point) testtet.tet[4 + i]);
-      tetspernodelist[j]++;
-    }
-    testtet.tet = tetrahedrontraverse();
-  }
-
-  viri->traversalinit();
-  virusloop = (tetrahedron **) viri->traverse();
-  while (virusloop != (tetrahedron **) NULL) {
-    testtet.tet = *virusloop;
-    // 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++;
-      }
-    }
-    // Check the four corners of this tet if they're isolated.
-    for (i = 0; i < 4; i++) {
-      checkpt = (point) testtet.tet[4 + i];
-      j = pointmark(checkpt);
-      tetspernodelist[j]--;
-      if (tetspernodelist[j] == 0) {
-        // If it is added volume vertex or '-j' is not used, delete it.
-        if ((pointtype(checkpt) == FREEVOLVERTEX) || !b->nojettison) { 
-          setpointtype(checkpt, UNUSEDVERTEX);
-          unuverts++;
-        }
-      }
-    }
-    // Return the dead tetrahedron to the pool of tetrahedra.
-    tetrahedrondealloc(testtet.tet);
-    virusloop = (tetrahedron **) viri->traverse();
-  }
-  
-  delete [] tetspernodelist;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// assignregionattribs()    Assign each tetrahedron a region number.         //
-//                                                                           //
-// This routine is called when '-AA' switch is specified.  Every tetrahedron //
-// of a (bounded) region will get a integer number to that region.  Default, //
-// regions are numbered as 1, 2, 3, etc. However, if a number has already    //
-// been used (set by user in the region section in .poly or .smesh), it is   //
-// skipped and the next available number will be used.                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::assignregionattribs()
-{
-  list *regionnumlist;
-  list *regiontetlist;
-  triface tetloop, regiontet, neightet;
-  face checksh;
-  bool flag;
-  int regionnum, num;
-  int attridx, count;
-  int i;
-
-  if (b->verbose > 0) {
-    printf("  Assign region numbers.\n");
-  }
-
-  regionnumlist = new list(sizeof(int), NULL, 256);
-  regiontetlist = new list(sizeof(triface), NULL, 1024);
-  attridx = in->numberoftetrahedronattributes;  
-
-  // Loop through all tets. Infect tets which already have a region number,
-  //   and save the used numbers in 'regionnumlist'.
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    if (!infected(tetloop)) {
-      regionnum = (int) elemattribute(tetloop.tet, attridx);
-      if (regionnum != 0.0) {
-        // Found a numbered region tet.
-        infect(tetloop);
-        regiontetlist->append(&tetloop);
-        // Found and infect all tets in this region.
-        for (i = 0; i < regiontetlist->len(); i++) {
-          regiontet = * (triface *)(* regiontetlist)[i];
-          for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
-            // Is there a boundary face?
-            tspivot(regiontet, checksh);
-            if (checksh.sh == dummysh) {
-              sym(regiontet, neightet);
-              if ((neightet.tet != dummytet) && !infected(neightet)) {
-#ifdef SELF_CHECK
-                // neightet should have the same region number. Check it.
-                num = (int) elemattribute(neightet.tet, attridx);
-                assert(num == regionnum);
-#endif
-                infect(neightet);
-                regiontetlist->append(&neightet);
-              }
-            }
-          }
-        }
-        // Add regionnum to list if it is not exist.
-        flag = false;
-        for (i = 0; i < regionnumlist->len() && !flag; i++) {
-          num = * (int *)(* regionnumlist)[i];
-          flag = (num == regionnum);
-        }
-        if (!flag) regionnumlist->append(&regionnum);
-        // Clear list for the next region.
-        regiontetlist->clear();
-      }
-    }
-    tetloop.tet = tetrahedrontraverse();
-  }
-  
-  if (b->verbose > 0) {
-    printf("  %d user-specified regions.\n", regionnumlist->len());
-  }
-
-  // Now loop the tets again. Assign region numbers to uninfected tets.
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  regionnum = 1;  // Start region number.
-  count = 0;
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    if (!infected(tetloop)) {
-      // An unassigned region tet.
-      count++;
-      do {
-        flag = false;
-        // Check if the region number has been used.
-        for (i = 0; i < regionnumlist->len() && !flag; i++) {
-          num = * (int *)(* regionnumlist)[i];
-          flag = (num == regionnum);
-        }
-        if (flag) regionnum++;
-      } while (flag);      
-      setelemattribute(tetloop.tet, attridx, (REAL) regionnum);
-      infect(tetloop);
-      regiontetlist->append(&tetloop);
-      // Found and infect all tets in this region.
-      for (i = 0; i < regiontetlist->len(); i++) {
-        regiontet = * (triface *)(* regiontetlist)[i];
-        for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
-          // Is there a boundary face?
-          tspivot(regiontet, checksh);
-          if (checksh.sh == dummysh) {
-            sym(regiontet, neightet);
-            if ((neightet.tet != dummytet) && !infected(neightet)) {
-#ifdef SELF_CHECK
-              // neightet should have not been assigned yet. Check it.
-              num = (int) elemattribute(neightet.tet, attridx);
-              assert(num == 0);
-#endif
-              setelemattribute(neightet.tet, attridx, (REAL) regionnum);
-              infect(neightet);
-              regiontetlist->append(&neightet);
-            }
-          }
-        }
-      }
-      regiontetlist->clear();
-      regionnum++; // The next region number.
-    }
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  // Uninfect all tets.
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-#ifdef SELF_CHECK
-    assert(infected(tetloop));
-#endif
-    uninfect(tetloop);
-    tetloop.tet = tetrahedrontraverse();
-  }
-  
-  if (b->verbose > 0) {
-    printf("  %d regions are numbered.\n", count);
-  }
-
-  delete regionnumlist;
-  delete regiontetlist;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// 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 tetgenmesh::carveholes()
-{
-  memorypool *holeviri, *regionviri;
-  tetrahedron *tptr, **holetet, **regiontet;
-  triface searchtet, *holetets, *regiontets;
-  enum locateresult intersect;
-  int i;
-
-  if (!b->quiet) {
-    printf("Removing unwanted tetrahedra.\n");
-    if (b->verbose && (in->numberofholes > 0)) {
-      printf("  Marking holes for elimination.\n");
-    }
-  }
-
-  // Initialize a pool of viri to be used for holes, concavities.
-  holeviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
-  // Mark as infected any unprotected tetrahedra on the boundary.
-  infecthull(holeviri);
-
-  if (in->numberofholes > 0) {
-    // Allocate storage for the tetrahedra in which hole points fall.
-    holetets = (triface *) new triface[in->numberofholes];
-    // Infect each tetrahedron in which a hole lies.
-    for (i = 0; i < 3 * in->numberofholes; i += 3) {
-      // Ignore holes that aren't within the bounds of the mesh.
-      if ((in->holelist[i] >= xmin) && (in->holelist[i] <= xmax)
-          && (in->holelist[i + 1] >= ymin)
-          && (in->holelist[i + 1] <= ymax)
-          && (in->holelist[i + 2] >= zmin)
-          && (in->holelist[i + 2] <= zmax)) {
-        searchtet.tet = dummytet;
-        // Find a tetrahedron that contains the hole.
-        intersect = locate(&in->holelist[i], &searchtet);
-        if ((intersect != OUTSIDE) && (!infected(searchtet))) {
-          // Record the tetrahedron for processing carve hole.
-          holetets[i / 3] = searchtet;
-        }
-      }
-    }
-    // Infect the hole tetrahedron.  This is done by marking the tet as
-    //   infected and including the tetrahedron in the virus pool.
-    for (i = 0; i < in->numberofholes; i++) {
-      infect(holetets[i]);
-      holetet = (tetrahedron **) holeviri->alloc();
-      *holetet = holetets[i].tet;
-    }
-    // Free up memory.
-    delete [] holetets;
-  }
-
-  // Mark as infected all tets of the holes and concavities.
-  plague(holeviri);
-  // The virus pool contains all outside tets now.
-
-  // Is -A switch in use.
-  if (b->regionattrib) {
-    // Assign every tetrahedron a regional attribute of zero.
-    tetrahedrons->traversalinit();
-    tptr = tetrahedrontraverse();
-    while (tptr != (tetrahedron *) NULL) {
-      setelemattribute(tptr, in->numberoftetrahedronattributes, 0.0);
-      tptr = tetrahedrontraverse();
-    }
-  }
-
-  if (in->numberofregions > 0) {
-    if (!b->quiet) {
-      if (b->regionattrib) {
-        if (b->varvolume) {
-          printf("Spreading regional attributes and volume constraints.\n");
-        } else {
-          printf("Spreading regional attributes.\n");
-        }
-      } else {
-        printf("Spreading regional volume constraints.\n");
-      }
-    }
-    // Allocate storage for the tetrahedra in which region points fall.
-    regiontets = (triface *) new triface[in->numberofregions];
-    // Find the starting tetrahedron for each region.
-    for (i = 0; i < in->numberofregions; i++) {
-      regiontets[i].tet = dummytet;
-      // Ignore region points that aren't within the bounds of the mesh.
-      if ((in->regionlist[5 * i] >= xmin)
-           && (in->regionlist[5 * i] <= xmax)
-           && (in->regionlist[5 * i + 1] >= ymin)
-           && (in->regionlist[5 * i + 1] <= ymax)
-           && (in->regionlist[5 * i + 2] >= zmin)
-           && (in->regionlist[5 * i + 2] <= zmax)) {
-        searchtet.tet = dummytet;
-        // Find a tetrahedron that contains the region point.
-        intersect = locate(&in->regionlist[5 * i], &searchtet);
-        if ((intersect != OUTSIDE) && (!infected(searchtet))) {
-          // Record the tetrahedron for processing after the
-          //   holes have been carved.
-          regiontets[i] = searchtet;
-        }
-      }
-    }
-    // Initialize a pool to be used for regional attrs, and/or regional
-    //   volume constraints.
-    regionviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
-    // Find and set all regions.
-    for (i = 0; i < in->numberofregions; 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 **) regionviri->alloc();
-          *regiontet = regiontets[i].tet;
-          // Apply one region's attribute and/or volume constraint.
-          regionplague(regionviri, in->regionlist[5 * i + 3],
-                       in->regionlist[5 * i + 4]);
-          // The virus pool should be empty now.
-        }
-      }
-    }
-    // Free up memory.
-    delete [] regiontets;
-    delete regionviri;
-  }
-
-  // Now acutually remove the outside and hole tets.
-  removeholetets(holeviri);
-  // The mesh is nonconvex now.
-  nonconvex = 1;
-
-  if (b->regionattrib) {
-    if (b->regionattrib > 1) {
-      // -AA switch. Assign each tet a region number (> 0).
-      assignregionattribs();
-    }
-    // Note the fact that each tetrahedron has an additional attribute.
-    in->numberoftetrahedronattributes++;
-  }
-
-  // Free up memory.
-  delete holeviri;
-}
-
-//
-// End of carving out holes and concavities routines
-//
-
-//
-// Begin of boundary Steiner points removing routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// replacepolygonsubs()    Substitute the subfaces of a polygon.             //
-//                                                                           //
-// 'oldshlist' (T_old) contains the old subfaces of P.  It will be replaced  //
-// by 'newshlist' (T_new) of new subfaces. Each boundary edge of P is bonded //
-// to 'dummysh' in T_new.                                                    //
-//                                                                           //
-// Notice that Not every boundary edge of T_new is able to bond to a subface,//
-// e.g., when it is a segment recovered by removing a Steiner point in it.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::replacepolygonsubs(list* oldshlist, list* newshlist)
-{
-  face newsh, oldsh, spinsh;
-  face casingout, casingin;
-  face checkseg;
-  point pa, pb;
-  int i, j, k, l;
-
-  for (i = 0; i < newshlist->len(); i++) {
-    // Get a new subface s.
-    newsh = * (face *)(* newshlist)[i];
-    // Check the three edges of s.
-    for (k = 0; k < 3; k++) {
-      spivot(newsh, casingout);
-      // Is it a boundary edge?
-      if (casingout.sh == dummysh) {
-        // Find the old subface s_o having the same edge as s.
-        pa = sorg(newsh);
-        pb = sdest(newsh); 
-        for (j = 0; j < oldshlist->len(); j++) {
-          oldsh = * (face *)(* oldshlist)[j];
-	  for (l = 0; l < 3; l++) {
-            if (((sorg(oldsh) == pa) && (sdest(oldsh) == pb)) ||
-                ((sorg(oldsh) == pb) && (sdest(oldsh) == pa))) break;
-            senextself(oldsh);
-          }
-          if (l < 3) break;
-        }
-        // Is there a matched edge?
-        if (j < oldshlist->len()) {
-          // Get the neighbor subface s_out.
-          spivot(oldsh, casingout);
-          sspivot(oldsh, checkseg);
-          if (checkseg.sh != dummysh) {
-            // A segment. Insert s into the face ring, ie, s_in -> s -> s_out.
-            if (oldsh.sh != casingout.sh) {
-              // s is not bonded to itself.
-              spinsh = casingout;
-              do {
-                casingin = spinsh;
-                spivotself(spinsh);
-              } while (sapex(spinsh) != sapex(oldsh));
-              assert(casingin.sh != oldsh.sh); 
-              // Bond s_in -> s -> s_out (and dissolve s_in -> s_old -> s_out).
-              sbond1(casingin, newsh);
-              sbond1(newsh, casingout);
-            } else {
-              // Bond newsh -> newsh.
-              sbond(newsh, newsh);
-            }
-            // Bond the segment.
-            ssbond(newsh, checkseg);
-          } else {
-            // Bond s <-> s_out (and dissolve s_out -> s_old).
-            sbond(newsh, casingout);
-          }
-          // Unbound oldsh to indicate it's neighbor has been replaced.
-          //   It will be used to indentfy the edge in the inverse.
-          sdissolve(oldsh);
-          ssdissolve(oldsh);
-        }
-      }
-      // Go to the next edge of s.
-      senextself(newsh);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// orientnewsubs()    Orient new subfaces facing to the inside of cavity.    //
-//                                                                           //
-// 'newshlist' contains new subfaces of the cavity C (created by re-triangu- //
-// lation the polygon P). They're not necessary facing to the inside of C.   //
-// 'orientsh', faces to the inside of C, is used to adjust new subfaces. The //
-// normal of the new subfaces is returned in 'norm'.                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::orientnewsubs(list* newshlist, face* orientsh, REAL* norm)
-{
-  face *newsh;
-  point pa, pb, pc;
-  REAL ref[3], ori, len;
-  int i;
-
-  // Calculate the normal of 'orientsh'.
-  pa = sorg(*orientsh);
-  pb = sdest(*orientsh);
-  pc = sapex(*orientsh);
-  facenormal(pa, pb, pc, norm, &len);
-  for (i = 0; i < 3; i++) ref[i] = pa[i] + norm[i];
-  for (i = 0; i < 3; i++) norm[i] /= len;
-  
-  // Orient new subfaces. Let the normal above each one.
-  for (i = 0; i < newshlist->len(); i++) {
-    newsh = (face *)(* newshlist)[i];
-    pa = sorg(*newsh);
-    pb = sdest(*newsh);
-    pc = sapex(*newsh);
-    ori = orient3d(pa, pb, pc, ref);
-    assert(ori != 0.0);
-    if (ori > 0.0) {
-      sesymself(*newsh);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// constrainedflip()    Flip a non-constrained face.                         //
-//                                                                           //
-// 'flipface' f (abc) is a face we want to flip. In addition, if 'front' is  //
-// given (not a NULL), f is a crossface. f may not be flippable if it is one //
-// of the following cases:                                                   //
-//   (1) f has an aux subface attached;                                      //
-//   (2) f is on the convex hull;                                            //
-//   (3) f is not locally Delaunay (f must be recovered by a previous flip,  //
-//       we should keep it, otherwise, we may fall into a flip loop);        //
-//   (4) f is T32 at ab, but abd or abe has an aux subface attached;         //
-//   (5) f is T22 or T44 at ab, but abd, or abe, or abf has an aux subface   //
-//       attached;                                                           //
-//   (6) f is unflipable at ab, and abd, abe, ... are all unflippable due to //
-//       the cases (1) - (5).                                                //
-// If f is a crssface ('front' != NULL) and it is unflipable due to case (3),//
-// (4), (5) and (6). Try to flip the next crossing face of front first.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::constrainedflip(triface* flipface, triface* front,
-  queue* flipque)
-{
-  triface symface, spintet;
-  face checksh;
-  point pa, pb, pc, pd, pe;
-  enum fliptype fc;
-  REAL sign;
-  bool doflip;
-  int ia, ib, ic, id, ie;
-  int i;
-
-  // (1) Is f protected by an (auxilary) subface?
-  tspivot(*flipface, checksh);
-  if (checksh.sh != dummysh) return false;
-  // (2) Is f on the convex hull?
-  sym(*flipface, symface);
-  if (symface.tet == dummytet) return false;
-  // (3) Is f not locally Delaunay?
-  adjustedgering(*flipface, CCW);
-  pa = dest(*flipface);
-  pb = org(*flipface);
-  pc = apex(*flipface);
-  pd = oppo(*flipface);
-  pe = oppo(symface);
-  // if (symbolic) {
-    ia = pointmark(pa);
-    ib = pointmark(pb);
-    ic = pointmark(pc);
-    id = pointmark(pd);
-    ie = pointmark(pe);
-    sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
-    assert(sign != 0.0);
-  // } else {
-  //   sign = insphere(pa, pb, pc, pd, pe);
-  // }
-  if (sign <= 0.0) {
-    // Get the fliptype of f.
-    checksubfaces = 0; // switch off subface test.
-    fc = categorizeface(*flipface);
-    checksubfaces = 1; // switch on subface test.
-    if (fc == T23) {
-      doflip = true;
-      // Avoid one tet created by the 2-3 flip is nearly degenerate.
-      /* pc = oppo(*flipface);
-      pd = oppo(symface);
-      adjustedgering(*flipface, CCW);
-      for (i = 0; i < 3; i++) {
-        pa = org(*flipface);
-        pb = dest(*flipface);
-        ori = orient3d(pa, pb, pc, pd);
-        if (iscoplanar(pa, pb, pc, pd, ori, b->epsilon)) {
-          doflip = false; break;
-        }
-        enextself(*flipface);
-      } */
-      if (doflip) {
-        flip23(flipface, flipque);
-        return true;
-      }
-    } else if (fc == T32) {
-      // (4) Is abd, or abe protected?
-      doflip = true;
-      spintet = *flipface;
-      for (i = 0; i < 2; i++) {
-        fnextself(spintet);
-        tspivot(spintet, checksh);
-        if (checksh.sh != dummysh) {
-          doflip = false; break; // f is protected. Unflipable.
-        }
-      }
-      if (doflip) {
-        flip32(flipface, flipque);
-        return true;
-      }
-    } else if (fc == T22 || fc == T44) {
-      // (5) Is abd, abe, or abf protected?
-      doflip = true;
-      if (fc == T22) {
-        for (i = 0; i < 2; i++) {
-          spintet = *flipface;
-          if (i == 1) {
-            esymself(spintet);
-          }
-          fnextself(spintet);
-          tspivot(spintet, checksh);
-          if (checksh.sh != dummysh) {
-            doflip = false; break; // f is protected. Unflipable.
-          }
-        }
-      } else if (fc == T44) {
-        spintet = *flipface;
-        for (i = 0; i < 3; i++) {
-          fnextself(spintet);
-          tspivot(spintet, checksh);
-          if (checksh.sh != dummysh) {
-            doflip = false; break; // f is protected. Unflipable.
-          }
-        }
-      }
-      if (doflip) {
-        flip22(flipface, flipque);
-        return true;
-      }
-    } else if (fc == N32) {
-      // Is f a crossface?
-      if (front != (triface *) NULL) {
-        // (6) Is any obstacle face (abd, or abe, ...) flipable?
-        spintet = *flipface;
-        while (fnextself(spintet)) {
-          if (apex(spintet) == apex(*flipface)) break;
-          // Check if spintet is flipable, no recursive.
-          if (constrainedflip(&spintet, NULL, flipque)) {
-            // One obstacle face has been flipped.
-            return true;
-          }
-          // Unflipable. Go to the next obstacle face.
-          findedge(&spintet, org(*flipface), dest(*flipface));
-        }
-      }
-    }
-  }
-
-  // f is unflipable. Is f a crossface?
-  if (front != (triface *) NULL) {
-    // Look if there is another crossface.
-    pa = org(*front);
-    pb = dest(*front);
-    pc = apex(*front);
-    // sym(*flipface, symface);
-    // Have we reach the end of abc (We've started from edge ab).
-    if (oppo(symface) != pc) {
-      adjustedgering(symface, CCW);
-      for (i = 0; i < 3; i++) {
-        fnext(symface, spintet);
-        // Is c ahead of this face?
-        sign = orient3d(org(spintet), dest(spintet), apex(spintet), pc);
-        if (sign < 0.0) {
-          if (tritritest(&spintet, pa, pb, pc)) {
-            if (b->verbose > 2) {
-              printf("    Next crossface (%d, %d, %d).\n",
-                     pointmark(org(spintet)), pointmark(dest(spintet)),
-                     pointmark(apex(spintet)));
-            }
-            return constrainedflip(&spintet, front, flipque);
-            // return constrainedflip(&spintet, NULL, flipque);
-          }
-        }
-        enextself(symface);
-      }
-    }
-  }
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// recoverfront()    Recover a missing front by flips.                       //
-//                                                                           //
-// 'front' f is missing in D - it was crossed by faces of D. The cross faces //
-// may be flippable, so f can be recovered by flipping them away.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::recoverfront(triface* front, list* newtetlist, queue* flipque)
-{
-  triface idfront, starttet, spintet;
-  point pa, pb, pc, pd, ref;
-  enum locateresult loc;
-  enum finddirectionresult col;
-  REAL ori, ori1, ori2, sign;
-  int hitbdry;
-  int i, j;
-
-  // Find an existing edge of f in D to start with.
-  for (i = 0; i < 3; i++) {
-    pa = org(*front);
-    pb = dest(*front);
-    // Get a tet for searching.
-    idfront = recenttet;
-    // Make sure the tet is valid (flip32() may kill a tet).
-    if (isdead(&idfront)) {
-      // The tet is dead. Get a live tet in D. !!!
-      for (j = 0; j < newtetlist->len(); j++) {
-        recenttet = * (triface *)(* newtetlist)[j];
-        if (!isdead(&recenttet)) break;
-      }
-      assert(j < newtetlist->len());
-    }
-    loc = preciselocate(pa, &idfront, (long) newtetlist->len());
-    if (loc != ONVERTEX) {
-      // Do a brute-force search in D.
-      for (j = 0; j < newtetlist->len(); j++) {
-        idfront = * (triface *)(* newtetlist)[j];
-        if (isdead(&idfront)) continue;
-        if (findorg(&idfront, pa)) break;
-      }
-      assert(j < newtetlist->len()); // a must belong to one tet.
-    }
-    recenttet = idfront;
-    // Search for a tet having edge ab.
-    col = finddirection(&idfront, pb, (long) newtetlist->len());
-    if (col == BELOWHULL) {
-      // Do a brute-force search in D.
-      for (j = 0; j < newtetlist->len(); j++) {
-        idfront = * (triface *)(* newtetlist)[j];
-        if (isdead(&idfront)) continue;
-        if (findorg(&idfront, pa)) {
-          assert(org(idfront) == pa);
-          if (dest(idfront) == pb) {
-            col = RIGHTCOLLINEAR; break;
-          } else if (apex(idfront) == pb) {
-            col = LEFTCOLLINEAR; break;
-          } else if (oppo(idfront) == pb) {
-            col = TOPCOLLINEAR; break;
-          }
-        }
-      }
-    }
-    if (col == RIGHTCOLLINEAR) {
-      // b is just the destination.
-    } else if (col == LEFTCOLLINEAR) {
-      enext2self(idfront);
-      esymself(idfront);
-    } else if (col == TOPCOLLINEAR) {
-      fnextself(idfront);
-      enext2self(idfront);
-      esymself(idfront);
-    }
-    if (dest(idfront) == pb) break; // Found.
-    // Missing. Go to the next edge of f.
-    enextself(*front);
-  }
-  if (i == 3) {
-    // All three edges of f are missing - unrecoverable.
-    return false;
-  }
-
-  // Search for a tet having f (abc).
-  pc = apex(*front);
-  spintet = idfront;
-  hitbdry = 0;
-  do {
-    if (apex(spintet) == pc) {
-      // Found abc. Insert an auxilary subface s at idfront.
-      insertauxsubface(front, &spintet);
-      return true;
-    }
-    if (!fnextself(spintet)) {
-      hitbdry ++;
-      if (hitbdry < 2) {
-        esym(idfront, spintet);
-        if (!fnextself(spintet)) {
-          hitbdry ++;
-        }
-      }
-    }
-    if (apex(spintet) == apex(idfront)) break;
-  } while (hitbdry < 2);
-
-  // Search for a crossing face to flip.
-  pd = apex(idfront);
-  assert(pd != pc);
-  // Decide the orientation of d with abc.
-  ori = orient3d(pa, pb, pc, pd);
-  if (ori < 0.0) {
-    // d is above abc. Rotate downwards.
-    esym(idfront, starttet);
-    sign = -1.0;
-  } else if (ori > 0.0) {
-    // d is below abc. Rotate upwards.
-    starttet = idfront;
-    sign = 1.0;
-  } else {
-    assert(ori == 0.0);
-    // d is coplanar with abc. Do abc and abd intersect?
-    ref = oppo(idfront);
-    ori1 = orient3d(pa, pb, ref, pc);
-    ori2 = orient3d(pa, pb, ref, pd);
-    assert(ori1 * ori2 != 0.0);
-    if (ori1 * ori2 > 0) {
-      // abc and abd intersect.  There're two possible intersections: 
-      //   ad and bc, or ac and bd.  Find it out.
-      ori1 = orient3d(pb, pc, ref, pd);
-      ori2 = orient3d(pb, pc, ref, pa);
-      assert(ori1 * ori2 != 0.0);
-      if (ori1 * ori2 > 0) {
-        // ac intersects bd.
-        enextself(idfront); // go to edge bd.
-      } else {
-        // ad intersects bc.
-        enext2self(idfront); // go to edge ad.
-      }
-      adjustedgering(idfront, CCW);
-      fnextself(idfront); // face ade or bce need a 4-to-4 flip.
-      if (b->verbose > 2) {
-        printf("    Get crossface (%d, %d, %d).\n", pointmark(org(idfront)),
-               pointmark(dest(idfront)), pointmark(apex(idfront)));
-      }
-      if (constrainedflip(&idfront, front, flipque)) {
-        // A crossface has been flipped. Continue to recover f.
-        return recoverfront(front, newtetlist, flipque);
-      }
-      // Unable to recover f.
-      return false; // sign = 0.0;
-    } else {
-      // Not intersect. We can go either direction.
-      starttet = idfront;
-      if (fnextself(starttet)) {
-        // Choose to rotate upwards.
-        sign = 1.0;
-      } else {
-        // Hit convex hull. Choose to rotate downwrads.
-        esym(idfront, starttet);
-        sign = -1.0;
-      }
-    }
-  }
-
-  assert(sign != 0.0);
-  if (sign == -1) {
-    // The edge ab has be changed. Reverse it.
-    pa = org(starttet);
-    pb = dest(starttet);
-    // The sign has been reversed as well.
-    sign = -sign;
-  }
-  // Rotate face abd around edge ab. Moreover, we've chosen the rotate
-  //   direction such that no convex hull face will be reach.
-  spintet = starttet;
-  while (fnextself(spintet)) {
-    pd = apex(spintet);
-    assert(pd != pc);
-    // Check if the orientation of d (with abc) has changed.
-    ori = orient3d(pa, pb, pc, pd);
-    if (ori == 0.0) {
-      // abc and abd must coplanar intersect (4-to-4 flip is needed).
-      ref = oppo(spintet);
-      ori1 = orient3d(pb, pc, ref, pd);
-      ori2 = orient3d(pb, pc, ref, pa);
-      assert(ori1 * ori2 != 0.0);
-      if (ori1 * ori2 > 0) {
-        // ac intersects bd.
-        enextself(spintet); // go to edge bd.
-      } else {
-        // ad intersects bc.
-        enext2self(spintet); // go to edge ad.
-      }
-      adjustedgering(spintet, CCW);
-      fnextself(spintet); // face ade or bce need a 4-to-4 flip.
-      if (b->verbose > 2) {
-        printf("    Get crossface (%d, %d, %d).\n", pointmark(org(spintet)),
-               pointmark(dest(spintet)), pointmark(apex(spintet)));
-      }
-      if (constrainedflip(&spintet, front, flipque)) {
-        // A crossface has been flipped. Continue to recover f.
-        return recoverfront(front, newtetlist, flipque);
-      }
-      // Unable to recover f.
-      return false; // sign = 0.0;
-    } else if (ori * sign < 0.0) {
-      // Sign has changed. The face dea or deb must cross abc.
-      adjustedgering(spintet, CCW);
-      enextself(spintet);
-      for (i = 0; i < 2; i++) {
-        // Get the face dea or deb.
-        fnext(spintet, starttet);
-        if (tritritest(&starttet, pa, pb, pc)) {
-          if (b->verbose > 2) {
-            printf("    Get crossface (%d, %d, %d).\n",
-                   pointmark(org(starttet)), pointmark(dest(starttet)),
-                   pointmark(apex(starttet)));
-          }
-          if (constrainedflip(&starttet, front, flipque)) {
-            // A crossface has been flipped. Continue to recover f.
-            return recoverfront(front, newtetlist, flipque);
-          }
-        }
-        enextself(spintet);
-      }
-      // Unable to recover f.
-      return false;
-    }
-  }
-  // Impossible to be here.
-  assert(0);
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// repairflips()    Flip non-Delaunay and non-constrained faces.             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::repairflips(queue* flipque)
-{
-  badface *qface;
-  triface flipface, symface, spintet;
-  face checksh;
-  point pa, pb, pc, pd, pe;
-  enum fliptype fc;
-  REAL sign;
-  long flipcount;
-  bool doflip;
-  int ia, ib, ic, id, ie;
-  int i;
-
-  if (b->verbose > 1) {
-    printf("    Repair flip %ld faces.\n", flipque->len());
-  }
-  flipcount = flip23s + flip32s + flip22s + flip44s;
-  // Loop until the queue is empty.
-  while (!flipque->empty()) {
-    qface = (badface *) flipque->pop();
-    flipface = qface->tt;
-    // Check the validity of this face.
-    if (isdead(&flipface) || flipface.tet == dummytet || 
-        (org(flipface) != qface->forg) || 
-        (dest(flipface) != qface->fdest) ||
-        (apex(flipface) != qface->fapex) ||
-        (oppo(flipface) == (point) NULL)) continue;
-    // (1) Is f protected by an (auxilary) subface?
-    tspivot(flipface, checksh);
-    if (checksh.sh != dummysh) continue;
-    // (2) Is f on the convex hull?
-    sym(flipface, symface);
-    if (symface.tet == dummytet) continue;
-    // For positive orientation that insphere() test requires.
-    adjustedgering(flipface, CW);
-    pa = org(flipface);
-    pb = dest(flipface);
-    pc = apex(flipface);
-    pd = oppo(flipface);
-    pe = oppo(symface);
-    // if (symbolic) {
-      ia = pointmark(pa);
-      ib = pointmark(pb);
-      ic = pointmark(pc);
-      id = pointmark(pd);
-      ie = pointmark(pe);
-      sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
-      assert(sign != 0.0);
-    // } else {
-    //   sign = insphere(pa, pb, pc, pd, pe);
-    // }
-    if (sign > 0.0) {
-      // f is non-lcally Delaunay. Get the fliptype of f.
-      checksubfaces = 0; // switch off subface test.
-      fc = categorizeface(flipface);
-      checksubfaces = 1; // switch on subface test.
-      if (fc == T23) {
-        doflip = true;
-        // Avoid to create a nearly degenerate tet.
-        /* pc = oppo(flipface);
-        pd = oppo(symface);
-        adjustedgering(flipface, CCW);
-        for (i = 0; i < 3; i++) {
-          pa = org(flipface);
-          pb = dest(flipface);
-          ori = orient3d(pa, pb, pc, pd);
-          if (iscoplanar(pa, pb, pc, pd, ori, b->epsilon)) {
-            doflip = false; break;
-          }
-          enextself(flipface);
-        } */
-        if (doflip) {
-          flip23(&flipface, flipque);
-        }
-      } else if (fc == T32) {
-        // (4) Is abd, or abe protected?
-        doflip = true;
-        spintet = flipface;
-        for (i = 0; i < 2; i++) {
-          fnextself(spintet);
-          tspivot(spintet, checksh);
-          if (checksh.sh != dummysh) {
-            doflip = false; break; // f is protected. Unflipable.
-          }
-        }
-        if (doflip) {
-          flip32(&flipface, flipque);
-        }
-      } else if (fc == T22 || fc == T44) {
-        // (5) Is abd, abe, or abf protected?
-        doflip = true;
-        if (fc == T22) {
-          for (i = 0; i < 2; i++) {
-            spintet = flipface;
-            if (i == 1) {
-              esymself(spintet);
-            }
-            fnextself(spintet);
-            tspivot(spintet, checksh);
-            if (checksh.sh != dummysh) {
-              doflip = false; break; // f is protected. Unflipable.
-            }
-          }
-        } else if (fc == T44) {
-          spintet = flipface;
-          for (i = 0; i < 3; i++) {
-            fnextself(spintet);
-            tspivot(spintet, checksh);
-            if (checksh.sh != dummysh) {
-              doflip = false; break; // f is protected. Unflipable.
-            }
-          }
-        }
-        if (doflip) {
-          flip22(&flipface, flipque);
-        }
-      }
-    }
-  }
-  flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
-  if (b->verbose > 1) {
-    printf("    %ld flips.\n", flipcount);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// constrainedcavity()    Tetrahedralize a cavity by constrained tetrahedra. //
-//                                                                           //
-// The cavity C is bounded by faces F in 'floorlist' and 'ceillist'. 'ptlist'//
-// V is the set of vertices of C.                                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::constrainedcavity(triface* oldtet, list* floorlist,
-  list* ceillist, list* ptlist, list* frontlist, list* misfrontlist,
-  list* newtetlist, queue* flipque)
-{
-  triface misfront, newtet;
-  long facenum;
-  int i;
-
-  if (b->verbose > 1) {
-    printf("    Constrained cavity (%d floors, %d ceilings, %d vertices).\n",
-           floorlist->len(), ceillist->len(), ptlist->len());
-  }
-
-  // symbolic = 1;
-  
-  // Initialize the cavity C.
-  initializecavity(floorlist, ceillist, frontlist);
-  // Form the D of the vertices of C.
-  delaunizecavvertices(oldtet, ptlist, NULL, newtetlist, flipque);
-  
-  // Identify faces of C in D.
-  if (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
-    // Some faces are missing.
-    recenttet = * (triface *)(* newtetlist)[0];
-    assert((recenttet.tet != dummytet) && !isdead(&recenttet));
-    // Try to recover missing faces by flips.
-    do {
-      facenum = misfrontlist->len();
-      for (i = 0; i < misfrontlist->len(); i++) {
-        // Get a missing front f.
-        misfront = * (triface *)(* misfrontlist)[i];
-        // Let f face toward the inside of C.
-        adjustedgering(misfront, CW);
-        if (b->verbose > 1) {
-          printf("    Recover face (%d, %d, %d).\n", pointmark(org(misfront)),
-                 pointmark(dest(misfront)), pointmark(apex(misfront)));
-        }
-        if (recoverfront(&misfront, newtetlist, flipque)) {
-          // f has been recovered.
-          frontlist->append(&misfront);
-          misfrontlist->del(i, 0); i--;
-        }
-        // Flip non-locally non-constrained Delaunay faces.
-        repairflips(flipque);
-      }
-      // Have all faces been recovered?
-      if (misfrontlist->len() == 0) break;
-      // No! There are still un-recovered faces. Continue the loop if any
-      //   face has been recovered.
-    } while (misfrontlist->len() < facenum);
-    // Retrieve new tets and purge dead tets in D.
-    retrievenewtets(newtetlist);
-  }
-  
-  // symbolic = 0;
-
-  if (misfrontlist->len() == 0) {
-    // All fronts have identified in D. Get the shape of C by removing out
-    //   tets of C. 'misfrontlist' is reused for removing out tets.
-    //   Don't do flip since the new tets may get deleted later.
-    carvecavity(newtetlist, misfrontlist, NULL);
-    // Recover locally Delaunay faces.
-    // flip(flipque, NULL);
-    return true;
-  } else {
-    // Fail to tetrahedralize C.
-    // Remove aux subfaces.
-    detachauxsubfaces(newtetlist);
-    // Remove new tets.
-    for (i = 0; i < newtetlist->len(); i++) {
-      newtet = * (triface *)(* newtetlist)[i];
-      assert(!isdead(&newtet));
-      tetrahedrondealloc(newtet.tet);
-    }
-    newtetlist->clear();
-    // Restore faces of C in frontlist.
-    for (i = 0; i < misfrontlist->len(); i++) {
-      misfront = * (triface *)(* misfrontlist)[i];
-      frontlist->append(&misfront);
-    }
-    return false;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// expandsteinercavity()    Expand the cavity of a Steiner point.            //
-//                                                                           //
-// Expand the cavity C if there fronts (except fronts having subfaces) which //
-// are either (nearly) coplanar or invisible by the Steiner point.           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::expandsteinercavity(point steinpt, REAL eps, list* frontlist,
-  list* oldtetlist)
-{
-  triface front, symfront, newfront, oldfront;
-  face frontsh;
-  point pa, pb, pc;
-  REAL ori;
-  bool expflag, newflag;
-  int i, j;
-
-  do {
-    expflag = false;
-    for (i = 0; i < frontlist->len(); i++) {
-      // Get a front f.
-      front =  * (triface *)(* frontlist)[i];
-      // f can be expanded if it is not a subface.
-      tspivot(front, frontsh);
-      if (frontsh.sh == dummysh) {
-        // Let f face to the inside of C.
-        adjustedgering(front, CW);
-        pa = org(front);
-        pb = dest(front);
-        pc = apex(front);
-        ori = orient3d(pa, pb, pc, steinpt);
-        if (ori != 0.0) {
-          if (iscoplanar(pa, pb, pc, steinpt, ori, eps)) {
-            ori = 0.0; // f is nearly coplanar with p.
-          }
-        }
-        if (ori >= 0.0) {
-          // f is either invisible or coplanar with p.
-          if (b->verbose > 2) {
-            printf("    Remove front (%d, %d, %d).\n", pointmark(pa),
-                   pointmark(pb), pointmark(pc));
-          }
-          frontlist->del(i, 1);
-          expflag = true;
-          break;
-        }
-      }
-    }
-    if (expflag) {
-      assert(!infected(front) && (oppo(front) != NULL));
-      // Expand C at f by including new fronts.
-      adjustedgering(front, CCW);
-      for (i = 0; i < 3; i++) {
-        newflag = true;
-        // Get a new boundary n of the cavity.
-        fnext(front, symfront);
-        tspivot(symfront, frontsh);
-        sym(symfront, newfront);
-        if (frontsh.sh == dummysh) {
-          assert(newfront.tet != dummytet);
-          // Is n a front of the unexp. cavity?
-          if (infected(newfront)) {
-            for (j = 0; j < frontlist->len(); j++) {
-              oldfront = * (triface *)(* frontlist)[j];
-              if ((oldfront.tet == symfront.tet) &&
-                  (oldfront.loc == symfront.loc)) {
-                // n is not a front anymore.
-                if (b->verbose > 2) {
-                  printf("    Remove front (%d, %d, %d).\n",
-                         pointmark(org(oldfront)), pointmark(dest(oldfront)),
-                         pointmark(apex(oldfront)));
-                }
-                frontlist->del(j, 1);
-                newflag = false;
-                break;
-              }
-            }
-          }
-        } else {
-          // n is a subface.
-          if (newfront.tet == dummytet) {
-            sesymself(frontsh);
-            // Create a fake tet to hold n.
-            maketetrahedron(&newfront);
-            setorg(newfront, sorg(frontsh));
-            setdest(newfront, sdest(frontsh));
-            setapex(newfront, sapex(frontsh));
-            setoppo(newfront, (point) NULL);
-            tsbond(newfront, frontsh);
-          } else {
-            // n should not be a front of cavity yet.
-            assert(!infected(newfront));
-          }
-        }
-        if (newflag) {
-          if (b->verbose > 2) {
-            printf("    Add front (%d, %d, %d).\n", pointmark(org(newfront)),
-                   pointmark(dest(newfront)), pointmark(apex(newfront)));
-          }
-          frontlist->append(&newfront);
-        }
-        enextself(front);
-      }
-      // Add f into oldtetlist (to be deleted).
-      infect(front);
-      oldtetlist->append(&front);
-      expcavcount++;
-    }
-  } while (expflag);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// findrelocatepoint()    Find new location for relocating a point.          //
-//                                                                           //
-// 'frontlist' contains the boundary faces of the cavity C.  Some fronts are //
-// visible by 'stpt' p, some are coplanar with p.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::findrelocatepoint(point sp, point np, REAL* n,
-  list* frontlist, list* oldtetlist)
-{
-  triface front;
-  point pa, pb, pc;
-  REAL tp[3], tvol, mvol;
-  REAL ori, eps;
-  bool visible;
-  int i, j, k;
-
-  if (b->verbose > 1) {
-    printf("    Find new location for point %d.\n", pointmark(sp));
-  }
-
-  // Avoid compilation warnings.
-  tvol = mvol = 0.0;
-  visible = false;
-
-  eps = b->epsilon;
-  // Initialize np far enough from p (outside C).
-  for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
-  // Let tp = np;
-  for (i = 0; i < 3; i++) tp[i] = np[i];
-  // Interation to adjust np until it is visible by all fronts.
-  j = 0;
-  do {
-    for (i = 0; i < frontlist->len(); i++) {
-      // Get a front face f.
-      front = * (triface *)(* frontlist)[i];
-      // Let f face to the interior of C.
-      adjustedgering(front, CW);
-      pa = org(front);
-      pb = dest(front);
-      pc = apex(front);
-      ori = orient3d(pa, pb, pc, np);
-      visible = (ori < 0.0);
-      if (!visible) {
-        // A front is invisible by np. Move it towards p along the normal.
-        for (i = 0; i < 3; i++) np[i] = sp[i] + 0.5 * (sp[i] - np[i]);
-        // Failed if tp = np.
-        if ((tp[0] == np[0]) && (tp[1] == np[1]) && (tp[2] == np[2])) {
-          // Try to expand the cavity.
-          expandsteinercavity(sp, eps, frontlist, oldtetlist);
-          eps *= 10.0;
-          if (eps > b->epsilon * 1000.0) {
-          // printf("Internal error: Fail to relocate pt %d.\n",pointmark(sp));
-            // internalerror();
-            return false;
-          }
-          // Restart the point relocation.
-          for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
-        }
-        if (j % 2) {
-          // Set tp = np (at every 2 steps) to catch the stop state.
-          for (i = 0; i < 3; i++) tp[i] = np[i];
-        }
-        break;
-      } else {
-        // Save the smallest volume.
-        if (i == 0) {
-          mvol = fabs(ori);
-        } else {
-          mvol = fabs(ori) < mvol ? fabs(ori) : mvol;
-        }
-      }
-    }
-    j++;
-  } while (!visible);
-  
-  if (b->verbose > 1) {
-    printf("    %d iterations. minvol = %.12g.\n", j, mvol);
-  }
-
-  // Continue to adjust np until the minimal volume of tets formed by
-  //   fronts and np doesn't increase (all fronts are visible by np).
-  k = 0;
-  do {
-    j = 0;
-    do {
-      if (k == 0) {
-        // Initial tp := np + 0.9 * (p - np). Move toward p.
-        for (i = 0; i < 3; i++) tp[i] = sp[i] + 0.9 * (np[i] - sp[i]);
-      } else {
-        // Initial tp := np + 1.1 * (p - np). Move away from p.
-        for (i = 0; i < 3; i++) tp[i] = sp[i] + 1.1 * (np[i] - sp[i]);
-      }
-      // Get the minial volume formed by tp with one of the fronts.
-      for (i = 0; i < frontlist->len(); i++) {
-        // Get a front face f.
-        front = * (triface *)(* frontlist)[i];
-        // Let f face to the interior of C.
-        adjustedgering(front, CW);
-        pa = org(front);
-        pb = dest(front);
-        pc = apex(front);
-        ori = orient3d(pa, pb, pc, tp);
-        visible = (ori < 0.0);
-        if (visible) {
-          // Save the smallest volume.
-          if (i == 0) {
-            tvol = fabs(ori);
-          } else {
-            tvol = fabs(ori) < tvol ? fabs(ori) : tvol;
-          }
-        } else {
-          // A front is invisible by tp. Stop.
-          tvol = 0.0;
-          break;
-        }
-      }
-      if (tvol > mvol) {
-        // Get a larger minimal volume.
-        for (i = 0; i < 3; i++) np[i] = tp[i];
-        mvol = tvol;
-      } else {
-        // Minimal volume decreases. Stop.
-        break;
-      }
-      // Continue to adjust np.
-      j++;
-    } while (true);
-    // Has np been adjusted?
-    if (j > 0) break;
-    // Try to move np to anoter direction.
-    k++;
-  } while (k < 2);
-
-  if (b->verbose > 1) {
-    printf("    %d adjust iterations. minvol = %.12g.\n", j, mvol);
-  }
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// relocatepoint()    Relocate a point into the cavity.                      //
-//                                                                           //
-// 'frontlist' contains the boundary faces of the cavity C. All fronts must  //
-// be visible by 'steinpt'.  Some fronts may hold by 'fake' tets (they are   //
-// hull faces).  Fake tets will be removed when they're finished.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::relocatepoint(point steinpt, triface* oldtet, list* frontlist,
-  list* newtetlist, queue* flipque)
-{
-  triface front, newtet, newface, neightet;
-  face checksh;
-  point pa, pb;
-  REAL attrib, volume;
-  bool bdflag;
-  int i, j, k, l;
-
-  if (b->verbose > 1) {
-    printf("    Insert Steiner point (%.12g, %.12g, %.12g) %d.\n",
-           steinpt[0], steinpt[1], steinpt[2], pointmark(steinpt));
-  }
-  // Clear the list first.
-  newtetlist->clear();
-
-  // Create the tets formed by fronts and 'steinpt'.
-  for (i = 0; i < frontlist->len(); i++) {
-    // Get a front f.
-    front = * (triface *)(* frontlist)[i];
-    // Let f face inside C. (f is a face of tet adjacent to C).
-    adjustedgering(front, CW);
-    if (b->verbose > 2) {
-      printf("    Get front (%d, %d, %d).\n", pointmark(org(front)),
-             pointmark(dest(front)), pointmark(apex(front)));
-    }
-    maketetrahedron(&newtet);
-    newtetlist->append(&newtet);
-    setorg(newtet, org(front));
-    setdest(newtet, dest(front));
-    setapex(newtet, apex(front));
-    setoppo(newtet, steinpt);
-    if (oldtet != (triface *) NULL) {
-      for (j = 0; j < in->numberoftetrahedronattributes; j++) {
-        attrib = elemattribute(oldtet->tet, j);
-        setelemattribute(newtet.tet, j, attrib);
-      }
-      if (b->varvolume) {
-        volume = volumebound(oldtet->tet);
-        setvolumebound(newtet.tet, volume);
-      }
-    }
-    // 'front' may be a 'fake' tet.
-    tspivot(front, checksh);
-    if (oppo(front) == (point) NULL) {
-      if (checksh.sh != dummysh) {
-        stdissolve(checksh);
-      }
-      // Dealloc the 'fake' tet.
-      tetrahedrondealloc(front.tet);
-      // This side (newtet) is a boundary face, let 'dummytet' bond to it.
-      //   Otherwise, 'dummytet' may point to a dead tetrahedron after the
-      //   old cavity tets are removed.
-      dummytet[0] = encode(newtet);
-    } else {
-      // Bond two tetrahedra, also dissolve the old bond at 'front'.
-      bond(newtet, front);
-    }
-    if (checksh.sh != dummysh) {
-      sesymself(checksh);
-      tsbond(newtet, checksh);
-    }
-    if (flipque != (queue *) NULL) {
-      // f may be non-locally Delaunay and flipable.
-      enqueueflipface(newtet, flipque);
-    }
-    // The three neighbors are open. Will be finished later.
-  }
-
-  // Connect new tets in C. All connecting faces must contain 'steinpt'.
-  for (i = 0; i < newtetlist->len(); i++) {
-    newtet = * (triface *)(* newtetlist)[i];
-    newtet.ver = 0;
-    for (j = 0; j < 3; j++) {
-      fnext(newtet, newface);
-      sym(newface, neightet);
-      if (neightet.tet == dummytet) {
-        // Find a neightet to connect it.
-        bdflag = false;
-        pa = org(newface);
-        pb = dest(newface);
-        assert(apex(newface) == steinpt);
-        for (k = i + 1; k < newtetlist->len() && !bdflag; k++) {
-          neightet = * (triface *)(* newtetlist)[k];
-          neightet.ver = 0;
-          for (l = 0; l < 3; l++) {
-            if ((org(neightet) == pa && dest(neightet) == pb) ||
-                (org(neightet) == pb && dest(neightet) == pa)) {
-              // Find the neighbor.
-              fnextself(neightet);
-              assert(apex(neightet) == steinpt);
-              // Now neightet is a face same as newface, bond them.
-              bond(newface, neightet);
-              bdflag = true;
-              break;
-            }
-            enextself(neightet);
-          }
-        }
-        assert(bdflag);
-      }
-      enextself(newtet);
-    }
-    // Let the corners of newtet point to it for fast searching.
-    pa = org(newtet);
-    setpoint2tet(pa, encode(newtet));
-    pa = dest(newtet);
-    setpoint2tet(pa, encode(newtet));
-    pa = apex(newtet);
-    setpoint2tet(pa, encode(newtet));
-    pa = oppo(newtet);
-    setpoint2tet(pa, encode(newtet));
-  }
-
-  if (flipque != (queue *) NULL) { 
-    // Recover locally Delaunay faces.
-    flip(flipque, NULL);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// findcollapseedge()    Find collapseable edge to suppress an endpoint.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::findcollapseedge(point suppt, point *conpt, list* oldtetlist,
-  list* ptlist)
-{
-  triface front;
-  point pt, pa, pb, pc;
-  REAL *lenarray, ltmp, ori;
-  bool visflag;
-  int *idxarray, itmp;
-  int n, i, j;
-
-  if (b->verbose > 2) {
-    printf("    Search an edge (in %d edges) for collapse %d.\n",
-           ptlist->len(), pointmark(suppt));
-  }
-
-  // Candidate edges are p to the points of B(p) (in 'ptlist').
-  n = ptlist->len();
-  lenarray = new REAL[n];
-  idxarray = new int[n];
-  // Sort the points of B(p) by distance to p.
-  for (i = 0; i < n; i++) {
-    pt = * (point *)(* ptlist)[i];
-    lenarray[i] = distance(suppt, pt);
-    idxarray[i] = i;
-  }
-  // Bubble sort.
-  for (i = 0; i < n - 1; i++) {
-    for (j = 0; j < n - 1 - i; j++) {
-      if (lenarray[j + 1] < lenarray[j]) {  // compare the two neighbors
-        ltmp = lenarray[j];           // swap a[j] and a[j + 1]
-        lenarray[j] = lenarray[j + 1];
-        lenarray[j + 1] = ltmp;
-        itmp = idxarray[j];           // swap a[j] and a[j + 1]
-        idxarray[j] = idxarray[j + 1];
-        idxarray[j + 1] = itmp;
-      }
-    }
-  }
-  // For each point q of B(p), test if the edge (p, q) can be collapseed.
-  for (i = 0; i < n; i++) {
-    pt = * (point *)(* ptlist)[idxarray[i]];
-    // Is q visible by faces of B(p) not with q as a vertex.
-    lenarray[i] = 0.0; // zero volume.
-    visflag = true;
-    for (j = 0; j < oldtetlist->len() && visflag; j++) {
-      front = * (triface *)(* oldtetlist)[j];
-      // Let f face to inside of B(p).
-      adjustedgering(front, CCW);
-      pa = org(front);
-      pb = dest(front);
-      pc = apex(front);
-      // Is f contains q?
-      if ((pa != pt) && (pb != pt) && (pc != pt)) {
-        ori = orient3d(pa, pb, pc, pt);
-        if (ori != 0.0) {
-          if (iscoplanar(pa, pb, pc, pt, ori, b->epsilon * 1e+2)) ori = 0.0;
-        }
-        visflag = ori < 0.0;
-        if (visflag) {
-          // Visible, set the smallest volume.
-          if (j == 0) {
-            lenarray[i] = fabs(ori);
-          } else {
-            lenarray[i] = fabs(ori) < lenarray[i] ? fabs(ori) : lenarray[i];
-          }
-        } else {
-          // Invisible. Do not collapse (p, q).
-          lenarray[i] = 0.0;
-        }
-      }
-    }
-    if ((b->verbose > 2) && visflag) {
-      printf("    Got candidate %d vol(%g).\n", pointmark(pt), lenarray[i]);
-    }
-  }
-
-  // Select the largest non-zero volume (result in ltmp).
-  ltmp = lenarray[0];
-  itmp = idxarray[0];
-  for (i = 1; i < n; i++) {
-    if (lenarray[i] != 0.0) {
-      if (lenarray[i] > ltmp) {
-        ltmp = lenarray[i];
-        itmp = idxarray[i]; // The index to find the point.
-      }
-    }
-  }
-
-  delete [] lenarray;
-  delete [] idxarray;
-
-  if (ltmp == 0.0) {
-    // No edge can be collapseed.
-    *conpt = (point) NULL;
-    return false;
-  } else {
-    pt = * (point *)(* ptlist)[itmp];
-    *conpt = pt;
-    return true;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// collapseedge()    Remove a point by edge collapse.                        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::collapseedge(point suppt, point conpt, list* oldtetlist,
-  list* deadtetlist)
-{
-  triface oldtet, deadtet;
-  triface adjtet1, adjtet2;
-  face adjsh;
-  point pa, pb, pc;
-  int i, j;
-
-  if (b->verbose > 2) {
-    printf("    Collapse edge (%d,%d).\n", pointmark(suppt), pointmark(conpt));
-  }
-
-  // Loop in B(p), replace p with np, queue dead tets, uninfect old tets.
-  for (i = 0; i < oldtetlist->len(); i++) {
-    oldtet = * (triface *)(* oldtetlist)[i]; // assert(infected(oldtet));
-    uninfect(oldtet);
-    pa = org(oldtet);
-    pb = dest(oldtet);
-    pc = apex(oldtet);
-    assert(oppo(oldtet) == suppt);
-    setoppo(oldtet, conpt);
-    if ((pa == conpt) || (pb == conpt) || (pc == conpt)) {
-      deadtetlist->append(&oldtet); // a collpased tet.
-    }
-  }
-  // Loop in deadtetlist, glue adjacent tets of dead tets.
-  for (i = 0; i < deadtetlist->len(); i++) {
-    deadtet = * (triface *)(* deadtetlist)[i];
-    // Get the adjacent tet n1 (outside B(p)).
-    sym(deadtet, adjtet1);
-    tspivot(deadtet, adjsh);
-    // Find the edge in deadtet opposite to conpt.
-    adjustedgering(deadtet, CCW);
-    for (j = 0; j < 3; j++) {
-      if (apex(deadtet) == conpt) break;
-      enextself(deadtet);
-    }
-    assert(j < 3);
-    // Get another adjacent tet n2.
-    fnext(deadtet, adjtet2);
-    symself(adjtet2);
-    assert(adjtet2.tet != dummytet); // n2 is inside B(p).
-    if (adjtet1.tet != dummytet) {
-      bond(adjtet1, adjtet2); // Bond n1 <--> n2.
-    } else {
-      dissolve(adjtet2); // Dissolve at n2.
-      dummytet[0] = encode(adjtet2); // Let dummytet holds n2.
-    }
-    if (adjsh.sh != dummysh) {
-      tsbond(adjtet2, adjsh); // Bond s <--> n2.
-    }
-    // Collapse deadtet.
-    tetrahedrondealloc(deadtet.tet);
-  }
-  deadtetlist->clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// deallocfaketets()    Deleted fake tets at fronts.                         //
-//                                                                           //
-// This routine is only called when the findrelocatepoint() routine fails.   //
-// In other cases, the fake tets are removed automatically in carvecavity()  //
-// or relocatepoint().                                                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::deallocfaketets(list* frontlist)
-{
-  triface front, neightet;
-  face checksh;
-  bool infectflag;
-  int i;
-
-  for (i = 0; i < frontlist->len(); i++) {
-    // Get a front f.
-    front = * (triface *)(* frontlist)[i];
-    // Let f face inside C. (f is a face of tet adjacent to C).
-    adjustedgering(front, CW);
-    sym(front, neightet);
-    tspivot(front, checksh);
-    if (oppo(front) == (point) NULL) {
-      if (b->verbose > 2) {
-        printf("    Get fake tet (%d, %d, %d).\n", pointmark(org(front)),
-               pointmark(dest(front)), pointmark(apex(front)));
-      }
-      if (neightet.tet != dummytet) {
-        // The neightet may be infected. After dissolve it, the infect flag
-        //   will be lost. Save the flag and restore it later.
-        infectflag = infected(neightet);
-        dissolve(neightet);
-        if (infectflag) {
-          infect(neightet);
-        }
-      }
-      if (checksh.sh != dummysh) {
-        infectflag = sinfected(checksh);
-        stdissolve(checksh);
-        if (infectflag) {
-          sinfect(checksh);
-        }
-      }
-      // Dealloc the 'fake' tet.
-      tetrahedrondealloc(front.tet);
-      // If 'neightet' is a hull face, let 'dummytet' bond to it. It is
-      //   a 'dummytet' when this front was created from a new subface.
-      //   In such case, it should not be bounded.
-      if (neightet.tet != dummytet) {
-        dummytet[0] = encode(neightet);
-      }
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// restorepolyhedron()    Restore the tetrahedralization in a polyhedron.    //
-//                                                                           //
-// This routine is only called when the operation of suppressing a point is  //
-// aborted (eg., findrelocatepoint() routine fails). The polyhedron has been //
-// remeshed by new tets. This routine restore the old tets in it.            //
-//                                                                           //
-// 'oldtetlist' contains the list of old tets. Each old tet t_o assumes that //
-// it still connects to a tet t_b of the mesh, however, t_b does not connect //
-// to t_o, this routine resets the connection such that t_b <--> t_o.        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::restorepolyhedron(list* oldtetlist)
-{
-  triface oldtet, neightet, neineitet;
-  face checksh;
-  int i;
-
-  for (i = 0; i < oldtetlist->len(); i++) {
-    // Get an old tet t_o.
-    oldtet = * (triface *)(* oldtetlist)[i];
-    // Check the four sides of t_o.
-    for (oldtet.loc = 0; oldtet.loc < 4; oldtet.loc++) {
-      sym(oldtet, neightet);
-      tspivot(oldtet, checksh);
-      if (neightet.tet != dummytet) {
-        sym(neightet, neineitet);
-        if (neineitet.tet != oldtet.tet) {
-          // This face of t_o is a boundary of P.
-          bond(neightet, oldtet);
-          if (checksh.sh != dummysh) {
-            tsbond(oldtet, checksh);
-          }
-        }
-      } else {
-        // t_o has a hull face. It should be the boundary of P.
-#ifdef SELF_CHECK
-        assert(checksh.sh != dummysh);
-        stpivot(checksh, neineitet);
-        assert(neineitet.tet != oldtet.tet);
-#endif
-        tsbond(oldtet, checksh);
-        // Let dummytet[0] points to it.
-        dummytet[0] = encode(oldtet);
-      }
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// suppressfacetpoint()    Suppress a point inside a facet.                  //
-//                                                                           //
-// The point p inside a facet F will be suppressed from F by either being    //
-// deleted from the mesh or being relocated into the volume.                 //
-//                                                                           //
-// 'supsh' is a subface f of F, and p = sapex(f); the other parameters are   //
-// working lists which are empty at the beginning and the end.               //
-//                                                                           //
-// 'optflag' is used for mesh optimization. If it is set, after removing p,  //
-// test the object function on each new tet, queue bad tets.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::suppressfacetpoint(face* supsh, list* frontlist,
-  list* misfrontlist, list* ptlist, list* conlist, memorypool* viri,
-  queue* flipque, bool noreloc, bool optflag)
-{
-  list *oldtetlist[2], *newtetlist[2];
-  list *oldshlist, *newshlist;
-  triface oldtet, newtet;
-  face oldsh, newsh;
-  point suppt, newpt[2];
-  point *cons;
-  REAL norm[3];
-  bool success;
-  int shmark;
-  int i, j;
-
-  suppt = sapex(*supsh);
-  if (b->verbose > 1) {
-    printf("    Suppress point %d in facet.\n", pointmark(suppt));
-  }
-
-  // Initialize working lists, variables.
-  for (i = 0; i < 2; i++) {
-    oldtetlist[i] = (list *) NULL;
-    newtetlist[i] = (list *) NULL;
-    newpt[i] = (point) NULL;
-  }
-  oldshlist = new list(sizeof(face), NULL, 256);
-  newshlist = new list(sizeof(face), NULL, 256);
-  success = true; // Assume p can be suppressed.
-
-  // Find subs of C(p).
-  oldshlist->append(supsh);
-  formstarpolygon(suppt, oldshlist, ptlist);
-  // Get the edges of C(p). They form a closed polygon.
-  for (i = 0; i < oldshlist->len(); i++) {
-    oldsh = * (face *)(* oldshlist)[i];    
-    cons = (point *) conlist->append(NULL);
-    cons[0] = sorg(oldsh);
-    cons[1] = sdest(oldsh);
-  }
-  // Re-triangulate the old C(p).
-  shmark = shellmark(*supsh);
-  triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
-  // Get new subs of C(p), remove protected segments.
-  retrievenewsubs(newshlist, true);
-  // Substitute the old C(p) with the new C(p)
-  replacepolygonsubs(oldshlist, newshlist);
-  // Clear work lists.
-  ptlist->clear();
-  conlist->clear();
-  flipque->clear();
-  viri->restart();
-
-  // B(p) (tets with p as a vertex) has been separated into two parts
-  //   (B_0(p) and B_1(p)) by F. Process them individually.
-  for (i = 0; i < 2 && success; i++) { 
-    if (i == 1) sesymself(*supsh);
-    // Get a tet containing p.
-    stpivot(*supsh, oldtet);
-    // Is this part empty?
-    if (oldtet.tet == dummytet) continue;
-    // Allocate spaces for storing (old and new) B_i(p).
-    oldtetlist[i] = new list(sizeof(triface), NULL, 256);
-    newtetlist[i] = new list(sizeof(triface), NULL, 256);
-    // Form old B_i(p) in oldtetlist[i].
-    assert(!isdead(&oldtet));
-    oldtetlist[i]->append(&oldtet);
-    formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
-    // Infect the tets in old B_i(p) (they're going to be delete).
-    for (j = 0; j < oldtetlist[i]->len(); j++) {
-      oldtet = * (triface *)(* (oldtetlist[i]))[j];
-      infect(oldtet);
-    }
-    // Preparation for re-tetrahedralzing old B_i(p).
-    orientnewsubs(newshlist, supsh, norm);
-    // Tetrahedralize old B_i(p).
-    success = constrainedcavity(&oldtet, newshlist, oldtetlist[i], ptlist,
-                frontlist, misfrontlist, newtetlist[i], flipque);
-    // If p is not suppressed, do relocation if 'noreloc' is not set.
-    if (!success && !noreloc) {
-      // Try to relocate p into the old B_i(p).
-      makepoint(&(newpt[i]));
-      success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
-                                  oldtetlist[i]);
-      // Initialize newpt = suppt.
-      // for (j = 0; j < 3; j++) newpt[i][j] = suppt[j];
-      // success = smoothvolpoint(newpt[i], frontlist, true);
-      if (success) {
-        // p is relocated by newpt[i]. Now insert it. Don't do flip since
-        //   the new tets may get deleted again.
-        relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
-        setpointtype(newpt[i], FREEVOLVERTEX);
-        relverts++;
-      } else {
-        // Fail to relocate p. Clean fake tets and quit this option.
-        deallocfaketets(frontlist);
-        pointdealloc(newpt[i]);
-        newpt[i] = (point) NULL;
-        assert(newtetlist[i]->len() == 0);
-      }
-    }
-    if (!success && noreloc) {
-      // Failed and no point relocation. Clean fake tets.
-      deallocfaketets(frontlist);
-    }
-    // Clear work lists.
-    ptlist->clear();
-    frontlist->clear();
-    misfrontlist->clear();
-    flipque->clear();
-  }
-
-  if (success) {
-    // p has been removed! (Still in the pool).
-    setpointtype(suppt, UNUSEDVERTEX);
-    unuverts++;
-    // Delete old C(p).
-    for (i = 0; i < oldshlist->len(); i++) {
-      oldsh = * (face *)(* oldshlist)[i];
-      if (i == 0) {
-        // Update the 'hullsize' if C(p) is on the hull.
-        stpivot(oldsh, oldtet);
-        if (oldtet.tet != dummytet) {
-          sesymself(oldsh);
-          stpivot(oldsh, oldtet);
-        }
-        if (oldtet.tet == dummytet) {
-          // A boundary face. Update the 'hullsize'.
-          j = oldshlist->len() - newshlist->len();
-          assert(j > 0);
-          hullsize -= j;
-        }
-      }
-      shellfacedealloc(subfaces, oldsh.sh);
-    }
-    // Delete old B_i(p).
-    for (i = 0; i < 2; i++) {
-      if (oldtetlist[i] != (list *) NULL) {
-        // Delete tets of the old B_i(p).
-        for (j = 0; j < oldtetlist[i]->len(); j++) {
-          oldtet = * (triface *)(* (oldtetlist[i]))[j];
-          assert(!isdead(&oldtet));
-          tetrahedrondealloc(oldtet.tet);
-        }
-      }
-    }
-    if (optflag) {
-      // Check for new bad-quality tets.
-      for (i = 0; i < 2; i++) {
-        if (newtetlist[i] != (list *) NULL) {
-          for (j = 0; j < newtetlist[i]->len(); j++) {
-            newtet = * (triface *)(* (newtetlist[i]))[j];
-            if (!isdead(&newtet)) checktet4opt(&newtet, true);
-          }
-        }
-      }
-    }
-  } else {
-    // p is not suppressed. Recover the original state.
-    unsupverts++;
-    // Restore the old C(p).
-    replacepolygonsubs(newshlist, oldshlist);
-    // Delete subs of the new C(p)
-    for (i = 0; i < newshlist->len(); i++) {
-      newsh = * (face *)(* newshlist)[i];
-      shellfacedealloc(subfaces, newsh.sh);
-    }
-    // Restore old B_i(p).
-    for (i = 0; i < 2; i++) {
-      if (oldtetlist[i] != (list *) NULL) {
-        // Uninfect tets of old B_i(p).
-        for (j = 0; j < oldtetlist[i]->len(); j++) {
-          oldtet = * (triface *)(* (oldtetlist[i]))[j];
-          assert(infected(oldtet));
-          uninfect(oldtet);
-        }
-        // Has it been re-meshed?
-        if (newtetlist[i]->len() > 0) {
-          // Restore the old B_i(p).
-          restorepolyhedron(oldtetlist[i]);
-          // Delete tets of the new B_i(p);
-          for (j = 0; j < newtetlist[i]->len(); j++) {
-            newtet = * (triface *)(* (newtetlist[i]))[j];
-            // Some new tets may already be deleted (by carvecavity()).
-            if (!isdead(&newtet)) {
-              tetrahedrondealloc(newtet.tet);
-            }
-          }
-        }
-        // Dealloc newpt[i] if it exists.
-        if (newpt[i] != (point) NULL) {
-          pointdealloc(newpt[i]);
-          relverts--;
-        }
-      }
-    }
-  }
-
-  // Delete work lists.
-  delete oldshlist;
-  delete newshlist;
-  for (i = 0; i < 2; i++) {
-    if (oldtetlist[i] != (list *) NULL) {
-      delete oldtetlist[i];
-      delete newtetlist[i];
-    }
-  }
-
-  return success;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// suppresssegpoint()    Suppress a point on a segment.                      //
-//                                                                           //
-// The point p on a segment S will be suppressed from S by either being      //
-// deleted from the mesh or being relocated into the volume.                 //
-//                                                                           //
-// 'supseg' is the segment S, and p = sdest(S); the other parameters are     //
-// working lists which are empty at the beginning and the end.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::suppresssegpoint(face* supseg, list* spinshlist,
-  list* newsegshlist, list* frontlist, list* misfrontlist, list* ptlist,
-  list* conlist, memorypool* viri, queue* flipque, bool noreloc, bool optflag)
-{
-  list **oldtetlist, **newtetlist;
-  list **oldshlist, **newshlist;
-  list *pnewshlist, *dnewshlist;
-  triface oldtet, newtet;
-  face oldsh, newsh;
-  face startsh, spinsh, segsh1, segsh2;
-  face nsupseg, newseg, prevseg, nextseg;
-  point suppt, *newpt;
-  point pa, pb, *cons;
-  REAL pnorm[2][3], norm[3];
-  bool success;
-  int shmark;
-  int n, i, j, k;
-
-  // Get the Steiner point p.
-  assert(supseg->shver < 2);
-  suppt = sdest(*supseg);
-  // Find the segment ab split by p.
-  senext(*supseg, nsupseg);
-  spivotself(nsupseg);
-  assert(nsupseg.sh != dummysh);
-  nsupseg.shver = 0;
-  if (sorg(nsupseg) != suppt) sesymself(nsupseg);
-  assert(sorg(nsupseg) == suppt);
-  pa = sorg(*supseg);
-  pb = sdest(nsupseg);
-  if (b->verbose > 1) {
-    printf("    Remove point %d on segment (%d, %d).\n",
-           pointmark(suppt), pointmark(pa), pointmark(pb));
-  }
-
-  // Let startsh s containing p.
-  spivot(*supseg, startsh);
-  spinsh = startsh;
-  do {
-    // Save it in list.
-    spinshlist->append(&spinsh);
-    // Go to the next facet.
-    spivotself(spinsh);
-  } while (spinsh.sh != startsh.sh);
-  if (spinshlist->len() == 1) {
-    // This case has not handled yet.
-    // printf("Unhandled case: segment only belongs to one facet.\n");
-    spinshlist->clear();
-    unsupverts++;
-    return false;
-  }
-
-  // Suppose ab is shared by n facets (n > 1), then there are n B(p) (tets
-  //   with p as a vertex). Some B(p) may be empty, eg, outside.
-  n = spinshlist->len();
-  oldtetlist = new list*[n];
-  newtetlist = new list*[n];
-  oldshlist = new list*[n];
-  newshlist = new list*[n];
-  newpt = new point[n];
-  for (i = 0; i < n; i++) {
-    oldtetlist[i] = (list *) NULL;
-    newtetlist[i] = (list *) NULL;
-    oldshlist[i] = (list *) NULL;
-    newshlist[i] = (list *) NULL;
-    newpt[i] = (point) NULL;
-  }
-
-  // Create a new segment ab (result in newseg).
-  makeshellface(subsegs, &newseg);
-  setsorg(newseg, pa);
-  setsdest(newseg, pb);
-  // ab gets the same mark and segment type as ap.
-  setshellmark(newseg, shellmark(*supseg));
-  setshelltype(newseg, shelltype(*supseg));
-  if (b->quality && varconstraint) {
-    // Copy the areabound into the new subsegment.
-    setareabound(newseg, areabound(*supseg));
-  }
-  // Save the old connection at a.
-  senext2(*supseg, prevseg);
-  spivotself(prevseg);
-  if (prevseg.sh != dummysh) {
-    prevseg.shver = 0;
-    if (sdest(prevseg) != pa) sesymself(prevseg);
-    assert(sdest(prevseg) == pa);
-    senextself(prevseg);
-    senext2self(newseg);
-    sbond(newseg, prevseg);
-    newseg.shver = 0;
-  }
-  // Save the old connection at b.
-  senext(nsupseg, nextseg);
-  spivotself(nextseg);
-  if (nextseg.sh != dummysh) {
-    nextseg.shver = 0;
-    if (sorg(nextseg) != pb) sesymself(nextseg);
-    assert(sorg(nextseg) == pb);
-    senext2self(nextseg);
-    senextself(newseg);
-    sbond(newseg, nextseg);
-    newseg.shver = 0;
-  }
-
-  // Re-triangulate C(p) (subs with p as a vertex) to remove p.
-  for (i = 0; i < spinshlist->len(); i++) {
-    spinsh = * (face *)(* spinshlist)[i];
-    // Allocate spaces for C_i(p).
-    oldshlist[i] = new list(sizeof(face), NULL, 256);
-    newshlist[i] = new list(sizeof(face), NULL, 256);
-    // Get the subs of C_i(p).
-    oldshlist[i]->append(&spinsh);
-    formstarpolygon(suppt, oldshlist[i], ptlist);
-    // Find the edges of C_i(p). It DOES NOT form a closed polygon.
-    for (j = 0; j < oldshlist[i]->len(); j++) {
-      oldsh = * (face *)(* (oldshlist[i]))[j];    
-      cons = (point *) conlist->append(NULL);
-      cons[0] = sorg(oldsh);
-      cons[1] = sdest(oldsh);
-    }
-    // The C_i(p) isn't closed without ab. Add it to it.
-    cons = (point *) conlist->append(NULL);
-    cons[0] = pa;
-    cons[1] = pb;
-    // Re-triangulate C_i(p).
-    shmark = shellmark(spinsh);
-    triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
-    // Get new subs of C_i(p), remove protected segments.
-    retrievenewsubs(newshlist[i], true);
-    // Substitute old C_i(p) with the new C_i(p). !IT IS NOT COMPLETE!
-    replacepolygonsubs(oldshlist[i], newshlist[i]);
-    // Find the new subface s having edge ab.
-    for (j = 0; j < newshlist[i]->len(); j++) {
-      segsh1 = * (face *)(* (newshlist[i]))[j];
-      for (k = 0; k < 3; k++) {
-        if (((sorg(segsh1) == pa) && (sdest(segsh1) == pb)) ||
-            ((sorg(segsh1) == pb) && (sdest(segsh1) == pa))) break;
-        senextself(segsh1);
-      }
-      if (k < 3) break; // Found.
-    }
-    assert(j < newshlist[i]->len()); // ab must exist.
-    // Bond s and ab together. The C_i(p) is completedly substituted.
-    ssbond(segsh1, newseg);
-    // Save s for forming the face ring of ab.
-    newsegshlist->append(&segsh1);
-    // Clear work lists.
-    ptlist->clear();
-    conlist->clear();
-    flipque->clear();
-    viri->restart();
-  }
-  // Form the face ring of ab.
-  for (i = 0; i < newsegshlist->len(); i++) {
-    segsh1 = * (face *)(* newsegshlist)[i];
-    if ((i + 1) == newsegshlist->len()) {
-      segsh2 = * (face *)(* newsegshlist)[0];
-    } else {
-      segsh2 = * (face *)(* newsegshlist)[i + 1];
-    }
-    sbond1(segsh1, segsh2);
-  }
-
-  // A work list for keeping subfaces from two facets.
-  dnewshlist = new list(sizeof(face), NULL, 256);
-  success = true; // Assume p is suppressable.
-
-  // Suppress p in all B(p). B_i(p) is looped wrt the right-hand rule of ab.
-  for (i = 0; i < spinshlist->len() && success; i++) {
-    // Get an old  subface s (ap) of a facet.
-    spinsh = * (face *)(* spinshlist)[i];
-    // Let the edge direction of s be a->b. Hence all subfaces follow
-    //   the right-hand rule of ab.
-    if (sorg(spinsh) != pa) sesymself(spinsh);
-    // Get a tet t of B_i(p).
-    stpivot(spinsh, oldtet);
-    // Is B_i(p) empty?
-    if (oldtet.tet == dummytet) continue;
-    // Allocate spaces for B_i(p).
-    oldtetlist[i] = new list(sizeof(triface), NULL, 256);
-    newtetlist[i] = new list(sizeof(triface), NULL, 256);
-    // Find all tets of old B_i(p).
-    oldtetlist[i]->append(&oldtet);
-    formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
-    // Infect tets of old B_i(p) (they're going to be deleted).
-    for (j = 0; j < oldtetlist[i]->len(); j++) {
-      oldtet = * (triface *)(* (oldtetlist[i]))[j];
-      infect(oldtet);
-    }
-    // Collect new subfaces (of two facets) bounded B_i(p).
-    for (k = 0; k < 2; k++) {
-      if ((i + k) < spinshlist->len()) {
-        pnewshlist = newshlist[i + k];
-        segsh1 = * (face *)(* spinshlist)[i + k];
-      } else {
-        pnewshlist = newshlist[0];
-        segsh1 = * (face *)(* spinshlist)[0];
-      }
-      // Adjust the orientation of segsh1 to face to the inside of C.
-      if (k == 0) {
-        if (sorg(segsh1) != pa) sesymself(segsh1);
-        assert(sorg(segsh1) == pa);
-      } else {
-        if (sdest(segsh1) != pa) sesymself(segsh1);
-        assert(sdest(segsh1) == pa);
-      }
-      // Preparation for re-tetrahedralzing old B_i(p).
-      orientnewsubs(pnewshlist, &segsh1, pnorm[k]);
-      for (j = 0; j < pnewshlist->len(); j++) {
-        dnewshlist->append((face *)(* pnewshlist)[j]);
-      }
-    }
-    // Tetrahedralize B_i(p).
-    success = constrainedcavity(&oldtet, dnewshlist, oldtetlist[i], ptlist,
-                frontlist, misfrontlist, newtetlist[i], flipque);
-    if (!success && !noreloc) {
-      // C must be finished by re-locating the steiner point.
-      makepoint(&(newpt[i]));
-      for (j = 0; j < 3; j++) norm[j] = 0.5 * (pnorm[0][j] + pnorm[1][j]);
-      success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
-                                  oldtetlist[i]);
-      // for (j = 0; j < 3; j++) newpt[i][j] = suppt[j];
-      // success = smoothvolpoint(newpt[i], frontlist, true);
-      if (success) {
-        // p is relocated by newpt[i]. Now insert it. Don't do flip since
-        //   the new tets may get deleted again.
-        relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
-        setpointtype(newpt[i], FREEVOLVERTEX);
-        relverts++;
-      } else {
-        // Fail to relocate p. Clean fake tets and quit this option.
-        deallocfaketets(frontlist);
-        pointdealloc(newpt[i]);
-        newpt[i] = (point) NULL;
-        assert(newtetlist[i]->len() == 0);
-      }
-    }
-    if (!success && noreloc) {
-      // Failed and no point relocation. Clean fake tets.
-      deallocfaketets(frontlist);
-    }
-    // Clear work lists.
-    dnewshlist->clear();
-    ptlist->clear();
-    frontlist->clear();
-    misfrontlist->clear();
-    flipque->clear();
-  }
-
-  if (success) {
-    // p has been suppressed. (Still in the pool).
-    setpointtype(suppt, UNUSEDVERTEX);
-    unuverts++;
-    // Update the segmnet pointers saved in a and b.
-    setpoint2sh(pa, sencode(newseg));
-    setpoint2sh(pb, sencode(newseg));
-    // Delete old segments ap, pb.
-    shellfacedealloc(subsegs, supseg->sh);
-    shellfacedealloc(subsegs, nsupseg.sh);
-    // Delete subs of old C_i(p).
-    for (i = 0; i < spinshlist->len(); i++) {
-      for (j = 0; j < oldshlist[i]->len(); j++) {
-        oldsh = * (face *)(* (oldshlist[i]))[j];
-        if (j == 0) {
-          // Update 'hullsize' if C_i(p) is on the hull.
-          stpivot(oldsh, oldtet);
-          if (oldtet.tet != dummytet) {
-            sesymself(oldsh);
-            stpivot(oldsh, oldtet);
-          }
-          if (oldtet.tet == dummytet) {
-            // Update 'hullsize'.
-            k = oldshlist[i]->len() - newshlist[i]->len();
-            assert(k > 0);
-            hullsize -= k;
-          }
-        }
-        shellfacedealloc(subfaces, oldsh.sh);
-      }
-    }
-    // Delete tets old B_i(p).
-    for (i = 0; i < spinshlist->len(); i++) {
-      // Delete them if it is not empty.
-      if (oldtetlist[i] != (list *) NULL) {
-        for (j = 0; j < oldtetlist[i]->len(); j++) {
-          oldtet = * (triface *)(* (oldtetlist[i]))[j];
-          assert(!isdead(&oldtet));
-          tetrahedrondealloc(oldtet.tet);
-        }
-      }
-    }
-    if (optflag) {
-      for (i = 0; i < spinshlist->len(); i++) {
-        // Check for new bad-quality tets.
-        if (newtetlist[i] != (list *) NULL) {
-          for (j = 0; j < newtetlist[i]->len(); j++) {
-            newtet = * (triface *)(* (newtetlist[i]))[j];
-            if (!isdead(&newtet)) checktet4opt(&newtet, true);
-          }
-        }
-      }
-    }
-  } else {
-    // p is not suppressed. Recover the original state.
-    unsupverts++;
-    // Restore old connection at a.
-    senext2(*supseg, prevseg);
-    spivotself(prevseg);
-    if (prevseg.sh != dummysh) {
-      prevseg.shver = 0;
-      if (sdest(prevseg) != pa) sesymself(prevseg);
-      assert(sdest(prevseg) == pa);
-      senextself(prevseg);
-      senext2self(*supseg);
-      sbond(*supseg, prevseg);
-      senextself(*supseg); // Restore original state.
-      assert(supseg->shver < 2);
-    }
-    // Restore old connection at b.
-    senext(nsupseg, nextseg);
-    spivotself(nextseg);
-    if (nextseg.sh != dummysh) {
-      nextseg.shver = 0;
-      if (sorg(nextseg) != pb) sesymself(nextseg);
-      assert(sorg(nextseg) == pb);
-      senext2self(nextseg);
-      senextself(nsupseg);
-      sbond(nsupseg, nextseg);
-      // nsupseg.shver = 0;
-      senext2self(nsupseg); // Restore original state
-      assert(nsupseg.shver < 2);
-    }
-    // Delete the new segment ab.
-    shellfacedealloc(subsegs, newseg.sh);
-    // Restore old C_i(p).
-    for (i = 0; i < spinshlist->len(); i++) {
-      replacepolygonsubs(newshlist[i], oldshlist[i]);
-      // Delete subs of the new C_i(p)
-      for (j = 0; j < newshlist[i]->len(); j++) {
-        newsh = * (face *)(* (newshlist[i]))[j];
-        shellfacedealloc(subfaces, newsh.sh);
-      }
-    }
-    // Restore old B_i(p).
-    for (i = 0; i < spinshlist->len(); i++) {
-      if (oldtetlist[i] != (list *) NULL) {
-        // Uninfect tets of old B_i(p).
-        for (j = 0; j < oldtetlist[i]->len(); j++) {
-          oldtet = * (triface *)(* (oldtetlist[i]))[j];
-          assert(infected(oldtet));
-          uninfect(oldtet);
-        }
-        // Has it been re-meshed?
-        if (newtetlist[i]->len() > 0) {
-          // Restore the old B_i(p).
-          restorepolyhedron(oldtetlist[i]);
-          // Delete tets of the new B_i(p);
-          for (j = 0; j < newtetlist[i]->len(); j++) {
-            newtet = * (triface *)(* (newtetlist[i]))[j];
-            // Some new tets may already be deleted (by carvecavity()).
-            if (!isdead(&newtet)) {
-              tetrahedrondealloc(newtet.tet);
-            }
-          }
-        }
-        // Dealloc newpt[i] if it exists.
-        if (newpt[i] != (point) NULL) {
-          pointdealloc(newpt[i]);
-          relverts--;
-        }
-      }
-    }
-  }
-
-  // Delete work lists.
-  delete dnewshlist;
-  for (i = 0; i < spinshlist->len(); i++) {
-    delete oldshlist[i];
-    delete newshlist[i];
-  } 
-  delete [] oldshlist;
-  delete [] newshlist;
-  for (i = 0; i < spinshlist->len(); i++) {
-    if (oldtetlist[i] != (list *) NULL) {
-      delete oldtetlist[i];
-      delete newtetlist[i];
-    }
-  }
-  delete [] oldtetlist;
-  delete [] newtetlist;
-  // Clear work lists.
-  newsegshlist->clear();
-  spinshlist->clear();
-
-  return success;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// suppressvolpoint()    Suppress a point inside mesh.                       //
-//                                                                           //
-// The point p = org(suptet) is inside the mesh and will be suppressed from  //
-// the mesh. Note that p may not be suppressed.                              //
-//                                                                           //
-// 'optflag' is used for mesh optimization. If it is set, after removing p,  //
-// test the object function on each new tet, queue bad tets.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::suppressvolpoint(triface* suptet, list* frontlist,
-  list* misfrontlist, list* ptlist, queue* flipque, bool optflag)
-{
-  list *myfrontlist, *mymisfrontlist, *myptlist;
-  list *oldtetlist, *newtetlist;
-  list *newshlist; // a dummy list.
-  queue *myflipque;
-  triface oldtet, newtet;
-  point suppt, conpt;
-  bool success;
-  int j;
-
-  // Allocate spaces for storing (old and new) B(p).
-  oldtetlist = new list(sizeof(triface), NULL, 256);
-  newtetlist = new list(sizeof(triface), NULL, 256);
-  newshlist = new list(sizeof(face), NULL, 256);
-  // Allocate work lists if user doesn't supply them.
-  myfrontlist = mymisfrontlist = myptlist = (list *) NULL;
-  myflipque = (queue *) NULL;
-  if (frontlist == (list *) NULL) {
-    myfrontlist = new list(sizeof(triface), NULL, 256);
-    frontlist = myfrontlist;
-    mymisfrontlist = new list(sizeof(triface), NULL, 256);
-    misfrontlist = mymisfrontlist;
-    myptlist = new list(sizeof(point *), NULL, 256);
-    ptlist = myptlist;
-    myflipque = new queue(sizeof(badface));
-    flipque = myflipque;
-  }
-
-  suppt = org(*suptet);
-  oldtet = *suptet;
-  success = true; // Assume p can be suppressed.
-
-  if (b->verbose > 1) {
-    printf("    Remove point %d in mesh.\n", pointmark(suppt));
-  }
-
-  // Form old B(p) in oldtetlist.
-  oldtetlist->append(&oldtet);
-  formstarpolyhedron(suppt, oldtetlist, ptlist, false);
-  // Infect the tets in old B(p) (they're going to be delete).
-  for (j = 0; j < oldtetlist->len(); j++) {
-    oldtet = * (triface *)(* oldtetlist)[j];
-    infect(oldtet);
-  }
-  // Tetrahedralize old B(p).
-  success = constrainedcavity(&oldtet, newshlist, oldtetlist, ptlist,
-              frontlist, misfrontlist, newtetlist, flipque);
-  if (!success) {
-    // Unable to suppress p.
-    deallocfaketets(frontlist);
-    // Try to collapse an edge at p. 
-    conpt = (point) NULL;
-    assert(newtetlist->len() == 0);
-    if (findcollapseedge(suppt, &conpt, oldtetlist, ptlist)) {
-      // Collapse the edge suppt->conpt. Re-use newtetlist.
-      collapseedge(suppt, conpt, oldtetlist, newtetlist);
-      // The oldtetlist contains newtetlist.
-      if (optflag) {
-        assert(newtetlist->len() == 0);
-        for (j = 0; j < oldtetlist->len(); j++) {
-          newtet = * (triface *)(* oldtetlist)[j];
-          newtetlist->append(&newtet);
-        }
-      }
-      oldtetlist->clear(); // Do not delete them.
-      collapverts++;
-      success = true;
-    }
-  }
-  if (success) {
-    // p has been removed! (Still in the pool).
-    setpointtype(suppt, UNUSEDVERTEX);
-    unuverts++;
-    suprelverts++;
-    // Delete old B(p).
-    for (j = 0; j < oldtetlist->len(); j++) {
-      oldtet = * (triface *)(* oldtetlist)[j];
-      assert(!isdead(&oldtet));
-      tetrahedrondealloc(oldtet.tet);
-    }
-    if (optflag) {
-      // Check for new bad tets.
-      for (j = 0; j < newtetlist->len(); j++) {
-        newtet = * (triface *)(* newtetlist)[j];
-        if (!isdead(&newtet)) checktet4opt(&newtet, true);
-      }
-    }
-  } else {
-    // p is not suppressed. Recover the original state.
-    // Uninfect tets of old B(p).
-    for (j = 0; j < oldtetlist->len(); j++) {
-      oldtet = * (triface *)(* oldtetlist)[j];
-      assert(infected(oldtet));
-      uninfect(oldtet);
-    }
-  }
-
-  // Clear work lists.
-  ptlist->clear();
-  frontlist->clear();
-  misfrontlist->clear();
-  flipque->clear();
-  // Deallocate work lists.
-  if (myfrontlist != (list *) NULL) {
-    delete myfrontlist;
-    delete mymisfrontlist;
-    delete myptlist;
-    delete myflipque;
-  }
-  delete oldtetlist;
-  delete newtetlist;
-  delete newshlist;
-
-  return success;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// smoothpoint()    Smooth a volume/segment point.                           //
-//                                                                           //
-// 'smthpt' (p) is inside the polyhedron (C) bounded by faces in 'starlist'. //
-// This routine moves p inside C until an object function is maximized.      //
-//                                                                           //
-// Default, the CCW edge ring of the faces on C points to p. If 'invtori' is //
-// TRUE, the orientation is inversed.                                        //
-//                                                                           //
-// If 'key' != NULL, it contains an object value to be improved. Current it  //
-// means the cosine of the largest dihedral angle. In such case, the point   //
-// is smoothed only if the final configuration improves the object value, it //
-// is returned by the 'key'.                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::smoothpoint(point smthpt, point e1, point e2, list *starlist,
-  bool invtori, REAL *key)
-{
-  triface starttet;
-  point pa, pb, pc;
-  REAL fcent[3], startpt[3], nextpt[3], bestpt[3];
-  REAL iniTmax, oldTmax, newTmax;
-  REAL ori, aspT, aspTmax, imprate;
-  REAL cosd, maxcosd;
-  bool segflag, randflag; //, subflag; 
-  int numdirs;
-  int iter, i, j;
-
-  // Is p a segment vertex?
-  segflag = (e1 != (point) NULL);
-  // Decide the number of moving directions.
-  numdirs = segflag ? 2 : starlist->len();
-  randflag = numdirs > 10;
-  if (randflag) {
-    numdirs = 10; // Maximum 10 directions.
-  }
-
-  // Calculate the initial object value (the largest aspect ratio).
-  for (i = 0; i < starlist->len(); i++) {
-    starttet = * (triface *)(* starlist)[i];
-    adjustedgering(starttet, !invtori ? CCW : CW);
-    pa = org(starttet);
-    pb = dest(starttet);
-    pc = apex(starttet);
-    aspT = tetaspectratio(pa, pb, pc, smthpt);
-    if (i == 0) {
-      aspTmax = aspT;
-    } else {
-      aspTmax = aspT > aspTmax ? aspT : aspTmax;
-    }
-  }
-  iniTmax = aspTmax;
-
-  if (b->verbose > 1) {
-    printf("    Smooth %s point %d (%g, %g, %g).\n", segflag ? "seg" : "vol",
-           pointmark(smthpt), smthpt[0], smthpt[1], smthpt[2]);
-    printf("    Initial max L/h = %g.\n", iniTmax);
-  }
-  for (i = 0; i < 3; i++) {
-    bestpt[i] = startpt[i] = smthpt[i];
-  }
-
-  // Do iteration until the new aspTmax does not decrease.
-  newTmax = iniTmax;
-  iter = 0;
-  while (true) {
-    // Find the best next location.
-    oldTmax = newTmax;
-    for (i = 0; i < numdirs; i++) {
-      // Calculate the moved point (saved in 'nextpt').
-      if (!segflag) {
-        if (randflag) {
-          // Randomly pick a direction.
-          j = (int) randomnation(starlist->len());
-        } else {
-          j = i;
-        }
-        starttet = * (triface *)(* starlist)[j];
-        adjustedgering(starttet, !invtori ? CCW : CW);
-        pa = org(starttet);
-        pb = dest(starttet);
-        pc = apex(starttet);
-        for (j = 0; j < 3; j++) {
-          fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0;
-        }
-      } else {
-        for (j = 0; j < 3; j++) {
-          fcent[j] = (i == 0 ? e1[j] : e2[j]);
-        }
-      }
-      for (j = 0; j < 3; j++) {
-        nextpt[j] = startpt[j] + 0.01 * (fcent[j] - startpt[j]); 
-      }
-      // Get the largest object value for the new location.
-      for (j = 0; j < starlist->len(); j++) {
-        starttet = * (triface *)(* starlist)[j];
-        adjustedgering(starttet, !invtori ? CCW : CW);
-        pa = org(starttet);
-        pb = dest(starttet);
-        pc = apex(starttet);
-        ori = orient3d(pa, pb, pc, nextpt);
-        if (ori < 0.0) {
-          aspT = tetaspectratio(pa, pb, pc, nextpt);
-          if (j == 0) {
-            aspTmax = aspT;
-          } else {
-            aspTmax = aspT > aspTmax ? aspT : aspTmax;
-          }
-        } else {
-          // An invalid new tet. Discard this point.
-          aspTmax = newTmax;
-        } // if (ori < 0.0)
-        // Stop looping when the object value is bigger than before.
-        if (aspTmax >= newTmax) break;
-      } // for (j = 0; j < starlist->len(); j++)
-      if (aspTmax < newTmax) {
-        // Save the improved object value and the location.
-        newTmax = aspTmax;
-        for (j = 0; j < 3; j++) bestpt[j] = nextpt[j];
-      }
-    } // for (i = 0; i < starlist->len(); i++)
-    // Does the object value improved much?
-    imprate = fabs(oldTmax - newTmax) / oldTmax;
-    if (imprate < 1e-3) break;
-    // Yes, move p to the new location and continue.
-    for (j = 0; j < 3; j++) startpt[j] = bestpt[j];
-    iter++;
-  } // while (true)
-
-  if (iter > 0) {
-    // The point is moved.
-    if (key) {
-      // Check if the quality is improved by the smoothed point.
-      maxcosd = 0.0; // = cos(90).
-      for (j = 0; j < starlist->len(); j++) {
-        starttet = * (triface *)(* starlist)[j];
-        adjustedgering(starttet, !invtori ? CCW : CW);
-        pa = org(starttet);
-        pb = dest(starttet);
-        pc = apex(starttet);
-        tetalldihedral(pa, pb, pc, startpt, NULL, &cosd, NULL);
-        if (cosd < *key) {
-          // This quality will not be improved. Stop.
-          iter = 0; break;
-        } else {
-          // Remeber the worst quality value (of the new configuration).
-          maxcosd = maxcosd < cosd ? maxcosd : cosd;
-        }
-      }
-      if (iter > 0) *key = maxcosd;
-    }
-  }
-
-  if (iter > 0) {
-    segflag ? smoothsegverts++ : smoothvolverts++;
-    for (i = 0; i < 3; i++) smthpt[i] = startpt[i];
-    if (b->verbose > 1) {
-      printf("    Move to new location (%g, %g, %g).\n", smthpt[0], smthpt[1],
-             smthpt[2]);
-      printf("    Final max L/h = %g. (%d iterations)\n", newTmax, iter);
-      if (key) {
-        printf("    Max. dihed = %g (degree).\n", acos(*key) / PI * 180.0);
-      }
-    }
-    return true;
-  } else {
-    if (b->verbose > 1) {
-      printf("    Not smoothed.\n");
-    }
-    return false;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// removesteiners()    Delete or relocate Steiner points on facets.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::removesteiners(bool coarseflag)
-{
-  list *frontlist, *misfrontlist;
-  list *spinshlist, *newsegshlist;
-  list *ptlist, *conlist;
-  memorypool *viri;
-  queue *flipque;
-  triface checktet;
-  face shloop;
-  face segloop, nextseg;
-  point pa, neipt;
-  REAL len;
-  bool remflag;
-  int *worklist;
-  int oldnum, rmstein;
-  int i, j;
-
-  if (!b->quiet) {
-    if (!coarseflag) {
-      printf("Removing Steiner points.\n");
-    } else {
-      printf("Coarsening mesh.\n");
-    }
-  }
-
-  // Initialize work lists.
-  frontlist = new list(sizeof(triface), NULL);
-  misfrontlist = new list(sizeof(triface), NULL);
-  spinshlist = new list(sizeof(face), NULL);
-  newsegshlist = new list(sizeof(face), NULL);
-  ptlist = new list(sizeof(point *), NULL);
-  conlist = new list(sizeof(point *) * 2, NULL);
-  flipque = new queue(sizeof(badface));
-  viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
-  oldnum = unuverts;
-  relverts = suprelverts = collapverts = unsupverts;
-  smoothvolverts = 0;
-  expcavcount = 0;
-
-  // Suppress Steiner points inside facets.
-  do {
-    rmstein = unuverts;
-    subfaces->traversalinit();
-    shloop.sh = shellfacetraverse(subfaces);
-    while (shloop.sh != (shellface *) NULL) {
-      remflag = false;
-      // Is s contains a Steiner point?
-      shloop.shver = 0;
-      for (i = 0; i < 3; i++) {
-        pa = sapex(shloop);
-        if (pointtype(pa) == FREESUBVERTEX) {
-          if (!coarseflag) {
-            // Remove it if it is not an input point.
-            j = pointmark(pa) - in->firstnumber;
-            if (j >= in->numberofpoints) {
-              if (b->nobisect == 1) {
-                // '-Y'. Remove p if s is a hull face.
-                stpivot(shloop, checktet);
-                if (checktet.tet != dummytet) {
-                  sesymself(shloop);
-                  stpivot(shloop, checktet);
-                }
-                remflag = (checktet.tet == dummytet);
-              } else {
-                // '-YY'. Remove p whatever s is a hull face or not.
-                remflag = true;
-              }
-            }
-          } else {
-            // Check if this vertex can be coarsed.
-            if (b->nobisect == 0) {
-              // Is a background mesh available?
-              if (b->metric) {
-                // assert(pa[pointmtrindex] > 0.0);
-                // Form the star of pa.
-                spinshlist->append(&shloop);
-                formstarpolygon(pa, spinshlist, ptlist);
-                len = 0.0;
-                for (j = 0; j < ptlist->len(); j++) {
-                  neipt = * (point *)(* ptlist)[j];
-                  len += distance(pa, neipt);
-                }
-                len /= ptlist->len();
-                // Carse it if the average edge length is small.
-                remflag = len < pa[pointmtrindex];
-                spinshlist->clear();
-                ptlist->clear();
-              } else {
-                // Coarse it if (1) it is an input point and its pointmarker
-                //   is zero, or (2) it is a Steiner point.
-                remflag = true;
-                j = pointmark(pa) - in->firstnumber;
-                if (j < in->numberofpoints) {
-                  remflag = (in->pointmarkerlist[j] == 0);
-                }
-              } // if (b->metric)
-            } // if (b->nobisect == 0)
-          } // if (!coarseflag)
-          if (remflag) break;
-        } // if (pointtype(pa) == FREESUBVERTEX)
-        senextself(shloop);
-      } // for (i = 0; i < 3; i++)
-      if (remflag) {
-        suppressfacetpoint(&shloop, frontlist, misfrontlist, ptlist, conlist,
-                           viri, flipque, coarseflag, false);
-      }
-      shloop.sh = shellfacetraverse(subfaces);
-    }
-    // Continue if any Steiner point has been removed.
-  } while (unuverts > rmstein);
-
-  if (coarseflag) {
-    shellface **segsperverlist;
-    int *idx2seglist;
-    face seg1, seg2;
-    point e1, e2;
-    // Connecting collinear segments. Hence the segment vertices may be
-    //   removed. In fact, this should be done by reconstructmesh().
-    makesegmentmap(idx2seglist, segsperverlist);
-    subsegs->traversalinit();
-    segloop.sh = shellfacetraverse(subsegs);
-    while (segloop.sh != (shellface *) NULL) {
-      for (i = 0; i < 2; i++) {
-        segloop.shver = i;
-        senext(segloop, nextseg);
-        spivotself(nextseg);
-        if ((nextseg.sh == dummysh) || (nextseg.sh > segloop.sh)) {
-          // No neighbor segment connection or haven't been processed yet.
-          pa = sdest(segloop);
-          j = pointmark(pa) - in->firstnumber;
-          if (idx2seglist[j + 1] - idx2seglist[j] == 2) {
-            // pa is shared by only two segments. Get the other one.
-            nextseg.sh = segsperverlist[idx2seglist[j]];
-            if (nextseg.sh == segloop.sh) {
-              nextseg.sh = segsperverlist[idx2seglist[j] + 1];
-            }
-            nextseg.shver = 0;
-            if (sorg(nextseg) != pa) sesymself(nextseg);
-            // Check if the two segments are collinear.
-            e1 = sorg(segloop);
-            e2 = sdest(nextseg);
-            if (iscollinear(e1, pa, e2, b->epsilon)) {
-              // Connect the two segments together.
-              if (b->verbose > 1) {
-                printf("  Glue two insegs (%d, %d) at %d.\n", pointmark(e1),
-                       pointmark(e2), pointmark(pa));
-              }
-              senext(segloop, seg1);
-              senext2(nextseg, seg2);
-              sbond(seg1, seg2);
-            }
-          }
-        } // if (nextseg.sh == dummysh)
-      } // for (i = 0;
-      segloop.sh = shellfacetraverse(subsegs);
-    }
-    delete [] segsperverlist;
-    delete [] idx2seglist;
-  }
-
-  // Suppress Steiner points on segments.
-  do {
-    rmstein = unuverts;
-    subsegs->traversalinit();
-    segloop.sh = shellfacetraverse(subsegs);
-    while (segloop.sh != (shellface *) NULL) {
-      remflag = false;
-      // for (i = 0; i < 2; i++) {
-        // Don't check the poinytype of pa, it may be a Steiner point but
-        //   has type NACUTEVERTEX due to splitting a type-3 segment.
-        segloop.shver = 0; // segloop.shver = i;
-        senext(segloop, nextseg);
-        spivotself(nextseg);
-        if (nextseg.sh != dummysh) {
-          pa = sdest(segloop); // p is going to be checked for removal.
-          nextseg.shver = 0;
-          if (sorg(nextseg) != pa) sesymself(nextseg);  
-          assert(sorg(nextseg) == pa);
-          if (!coarseflag) {
-            // try to remove it if it is not an input point.
-            j = pointmark(pa) - in->firstnumber;
-            if (j >= in->numberofpoints) {
-              if (b->nobisect == 1) {
-                // '-Y'. Remove p if it is on the hull.
-                sstpivot(&segloop, &checktet);
-                assert(checktet.tet != dummytet);
-                pa = apex(checktet);
-                do {
-                  if (!fnextself(checktet)) {
-                    // Meet a boundary face - p is on the hull.
-                    remflag = true; break;
-                  }
-                } while (pa != apex(checktet));
-              } else {
-                // '-YY'. Remove p whatever it is on the hull or not.
-                remflag = true;
-              }
-            }
-          } else {
-            // Check if this vertex can be coarsed.
-            if (b->nobisect == 0) {
-              if (b->metric) {
-                // assert(pa[pointmtrindex] > 0.0);
-                len = 0.0;
-                neipt = sorg(segloop);
-                for (j = 0; j < 2; j++) {
-                  len += distance(pa, neipt);
-                  /*// Is neipt inside the sparse ball of pa?
-                  if (len < pa[pointmtrindex]) {
-                    // Yes, the local of pa is too dense, corse it.
-                    remflag = true; break;
-                  } */
-                  neipt = sdest(nextseg);
-                }
-                len /= 2.0;
-                // Carse it if the average edge lengh is small.
-                remflag = len < pa[pointmtrindex]; 
-              } else {
-                // Coarse it if (1) it is an input point and its pointmarker
-                //   is zero, or (2) it is a Steiner point.
-                remflag = true;
-                j = pointmark(pa) - in->firstnumber;
-                if (j < in->numberofpoints) {
-                  remflag = (in->pointmarkerlist[j] == 0);
-                }
-              } // if (b->metric)
-            } // if (b->nobisect == 0)
-          } // if (!coarseflag)
-        } // if (nextseg.sh != dummysh)
-        // if (remflag) break;
-      // } // for (i = 0; i < 2; i++)
-      if (remflag) {
-        suppresssegpoint(&segloop, spinshlist, newsegshlist, frontlist,
-          misfrontlist, ptlist, conlist, viri, flipque, coarseflag, false);
-      }
-      segloop.sh = shellfacetraverse(subsegs);
-    }
-    // Continue if any Steiner point has been removed.
-  } while (unuverts > rmstein);
-
-  if ((relverts > 0) || coarseflag) {
-    worklist = new int[points->items + 1];
-    // Suppress relocated points & coarse free mesh points.
-    do {
-      // Initialize the work list. Each entry of the list counts how many
-      //   times the point has been processed.
-      for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
-      rmstein = unuverts;
-      tetrahedrons->traversalinit();
-      checktet.tet = tetrahedrontraverse();
-      while (checktet.tet != (tetrahedron *) NULL) {
-        remflag = false;
-        for (i = 0; i < 4; i++) {
-          pa = (point) checktet.tet[4 + i];
-          if (pointtype(pa) == FREEVOLVERTEX) {
-            // NOTE. Chenge the number 3 will change the number n of removed
-            //   Steiner points. In my test, n is larger when it is 1. 3
-            //   reduces n in a reasonable way (see example, mech_part,
-            //   thepart), 5 results a larger n than 3 does. While the best
-            //   result is no limit of this number, but it makes the code
-            //   extremely slow.
-            if (worklist[pointmark(pa)] < 3) {
-              worklist[pointmark(pa)]++;
-              if (!coarseflag) {
-                // Remove p if it is a Steiner point.
-                if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
-                  remflag = true;
-                }
-              } else {
-                if (b->metric) {
-                  // assert(pa[pointmtrindex] > 0.0);
-                  // Form the star of pa.
-                  frontlist->append(&checktet);
-                  formstarpolyhedron(pa, frontlist, ptlist, true);
-                  len = 0.0;
-                  for (j = 0; j < ptlist->len(); j++) {
-                    neipt = * (point *)(* ptlist)[j];
-                    len += distance(pa, neipt);
-                  }
-                  len /= ptlist->len();
-                  // Carse it if the average edge length is small.
-                  remflag = len < pa[pointmtrindex];
-                  frontlist->clear();
-                  ptlist->clear();
-                } else {
-                  // Coarse it if (1) it is an input point and its pointmarker
-                  //   is zero, or (2) it is a Steiner point.
-                  remflag = true;
-                  j = pointmark(pa) - in->firstnumber;
-                  if (j < in->numberofpoints) {
-                    remflag = (in->pointmarkerlist[j] == 0);
-                  }
-                } // if (b->metric)
-              } // if (!coarseflag)
-              if (remflag) break;
-            } // if (worklist[pointmark(pa)] == 0)
-          } // if (pointtype(pa) == FREEVOLVERTEX)
-        } // for (i = 0; i < 4; i++)
-        if (remflag) {
-          findorg(&checktet, pa);
-          assert(org(checktet) == pa);
-          suppressvolpoint(&checktet, frontlist, misfrontlist, ptlist, flipque,
-                           false);
-        }
-        checktet.tet = tetrahedrontraverse();
-      }
-      // Continue if any relocated point has been suppressed.
-    } while (unuverts > rmstein);
-
-
-    // Smooth the unsuppressed points if it is not coarse mesh.
-    if (!coarseflag && (relverts > suprelverts)) {
-      if (b->verbose) {
-        printf("  Smoothing relocated points.\n");
-      }
-      for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
-      tetrahedrons->traversalinit();
-      checktet.tet = tetrahedrontraverse();
-      while (checktet.tet != (tetrahedron *) NULL) {
-        for (i = 0; i < 4; i++) {
-          pa = (point) checktet.tet[4 + i];
-          if (pointtype(pa) == FREEVOLVERTEX) {
-            if (worklist[pointmark(pa)] == 0) {
-              worklist[pointmark(pa)] = 1;
-              if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
-                // Smooth pa.
-                findorg(&checktet, pa);
-                frontlist->append(&checktet);
-                formstarpolyhedron(pa, frontlist, NULL, false);
-                smoothpoint(pa, NULL, NULL, frontlist, false, NULL);
-                frontlist->clear();
-              }
-            } // if (worklist[pointmark(pa)] == 0)
-          } // if (pointtype(pa) == FREEVOLVERTEX)
-        } // for (i = 0; i < 4; i++)
-        checktet.tet = tetrahedrontraverse();
-      }
-    }
-    delete [] worklist;
-  }
-
-  if (b->verbose > 0) {
-    if (!coarseflag) {
-      printf("  %d points removed from boundary", unuverts - oldnum);
-      if (expcavcount > 0) {
-        printf(" (%d cavity corrections)", expcavcount);
-      }
-      printf("\n");
-      if (relverts > 0) {
-        printf("  %d points relocated (%d suppressed, %d collapsed).\n",
-               relverts, suprelverts - collapverts, collapverts);
-        if (smoothvolverts > 0) {
-          printf("  %d points are smoothed.\n", smoothvolverts);
-        }
-      }
-      if (unsupverts > 0) {
-        printf("  !! %d points are unsuppressed.\n", unsupverts);
-      }
-    } else {
-      printf("  %d points are removed.\n", unuverts - oldnum);
-    }
-  }
-
-  // Delete work lists.
-  delete frontlist;
-  delete misfrontlist;
-  delete spinshlist;
-  delete newsegshlist;
-  delete ptlist;
-  delete conlist;
-  delete flipque;
-  delete viri;
-}
-
-//
-// End of boundary Steiner points removing routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// reconstructmesh()    Reconstruct a tetrahedral mesh from a list of        //
-//                      tetrahedra and possibly a list of boundary faces.    //
-//                                                                           //
-// The list of tetrahedra is stored in 'in->tetrahedronlist',  the list of   //
-// boundary faces is stored in 'in->trifacelist'.  The tetrahedral mesh is   //
-// reconstructed in memorypool 'tetrahedrons', its boundary faces (subfaces) //
-// are reconstructed in 'subfaces', its boundary edges (subsegments) are     //
-// reconstructed in 'subsegs'. If the -a switch is used, this procedure will //
-// also read a list of REALs from 'in->tetrahedronvolumelist' and set a      //
-// maximum volume constraint on each tetrahedron.                            //
-//                                                                           //
-// If the user has provided the boundary faces in 'in->trifacelist', they    //
-// will be inserted the mesh. Otherwise subfaces will be identified from the //
-// mesh.  All hull faces (including faces of the internal holes) will be     //
-// recognized as subfaces, internal faces between two tetrahedra which have  //
-// different attributes will also be recognized as subfaces.                 //
-//                                                                           //
-// Subsegments will be identified after subfaces are reconstructed. Edges at //
-// the intersections of non-coplanar subfaces are recognized as subsegments. //
-// Edges between two coplanar subfaces with different boundary markers are   //
-// also recognized as subsegments.                                           //
-//                                                                           //
-// The facet index of each subface will be set automatically after we have   //
-// recovered subfaces and subsegments.  That is, the set of subfaces, which  //
-// are coplanar and have the same boundary marker will be recognized as a    //
-// facet and has a unique index, stored as the facet marker in each subface  //
-// of the set, the real boundary marker of each subface will be found in     //
-// 'in->facetmarkerlist' by the index.  Facet index will be used in Delaunay //
-// refinement for detecting two incident facets.                             //
-//                                                                           //
-// Points which are not corners of tetrahedra will be inserted into the mesh.//
-// Return the number of faces on the hull after the reconstruction.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-long tetgenmesh::reconstructmesh()
-{
-  tetrahedron **tetsperverlist;
-  shellface **facesperverlist;
-  triface tetloop, neightet, neineightet, spintet;
-  face subloop, neighsh, neineighsh, subseg;
-  face sface1, sface2;
-  point *idx2verlist;
-  point torg, tdest, tapex, toppo;
-  point norg, ndest, napex;
-  list *neighshlist, *markerlist;
-  REAL sign, attrib, volume;
-  REAL da1, da2;
-  bool bondflag, insertsegflag;
-  int *idx2tetlist;
-  int *idx2facelist;
-  int *worklist;
-  int facetidx, marker;
-  int iorg, idest, iapex, ioppo;
-  int inorg, indest, inapex;
-  int index, i, j;
-
-  if (!b->quiet) {
-    printf("Reconstructing mesh.\n");
-  }
-
-  // Create a map from index to points.
-  makeindex2pointmap(idx2verlist);
-
-  // Create the tetrahedra.
-  for (i = 0; i < in->numberoftetrahedra; i++) {
-    // Create a new tetrahedron and set its four corners, make sure that
-    //   four corners form a positive orientation.
-    maketetrahedron(&tetloop);
-    index = i * in->numberofcorners;
-    // Although there may be 10 nodes, we only read the first 4.
-    iorg = in->tetrahedronlist[index] - in->firstnumber;
-    idest = in->tetrahedronlist[index + 1] - in->firstnumber;
-    iapex = in->tetrahedronlist[index + 2] - in->firstnumber;
-    ioppo = in->tetrahedronlist[index + 3] - in->firstnumber;
-    torg = idx2verlist[iorg];
-    tdest = idx2verlist[idest];
-    tapex = idx2verlist[iapex];
-    toppo = idx2verlist[ioppo];
-    sign = orient3d(torg, tdest, tapex, toppo);
-    if (sign > 0.0) {
-      norg = torg; torg = tdest; tdest = norg;
-    } else if (sign == 0.0) {
-      if (!b->quiet) {
-        printf("Warning:  Tet %d is degenerate.\n", i + in->firstnumber);
-      }
-    }
-    setorg(tetloop, torg);
-    setdest(tetloop, tdest);
-    setapex(tetloop, tapex);
-    setoppo(tetloop, toppo);
-    // Temporarily set the vertices be type FREEVOLVERTEX, to indicate that
-    //   they belong to the mesh.  These types may be changed later.
-    setpointtype(torg, FREEVOLVERTEX);
-    setpointtype(tdest, FREEVOLVERTEX);
-    setpointtype(tapex, FREEVOLVERTEX);
-    setpointtype(toppo, FREEVOLVERTEX);
-    // Set element attributes if they exist.
-    for (j = 0; j < in->numberoftetrahedronattributes; j++) {
-      index = i * in->numberoftetrahedronattributes;
-      attrib = in->tetrahedronattributelist[index + j];
-      setelemattribute(tetloop.tet, j, attrib);
-    }
-    // If -a switch is used (with no number follows) Set a volume
-    //   constraint if it exists.
-    if (b->varvolume) {
-      if (in->tetrahedronvolumelist != (REAL *) NULL) {
-        volume = in->tetrahedronvolumelist[i];
-      } else {
-        volume = -1.0;
-      }
-      setvolumebound(tetloop.tet, volume);
-    }
-  }
-
-  // Set the connection between tetrahedra.
-  hullsize = 0l;
-  // Create a map from nodes to tetrahedra.
-  maketetrahedronmap(idx2tetlist, tetsperverlist);
-  // Initialize the worklist.
-  worklist = new int[points->items];
-  for (i = 0; i < points->items; i++) worklist[i] = 0;
-
-  // Loop all tetrahedra, bond two tetrahedra if they share a common face.
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    // Loop the four sides of the tetrahedron.
-    for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
-      sym(tetloop, neightet);
-      if (neightet.tet != dummytet) continue; // This side has finished.
-      torg = org(tetloop);
-      tdest = dest(tetloop);
-      tapex = apex(tetloop);
-      iorg = pointmark(torg) - in->firstnumber;
-      idest = pointmark(tdest) - in->firstnumber;
-      iapex = pointmark(tapex) - in->firstnumber;
-      worklist[iorg] = 1;
-      worklist[idest] = 1;
-      worklist[iapex] = 1;
-      bondflag = false;
-      // Search its neighbor in the adjacent tets of torg.
-      for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag; 
-           j++) {
-        if (tetsperverlist[j] == tetloop.tet) continue; // Skip myself.
-        neightet.tet = tetsperverlist[j];
-        for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
-          sym(neightet, neineightet);
-          if (neineightet.tet == dummytet) {
-            norg = org(neightet);
-            ndest = dest(neightet);
-            napex = apex(neightet);
-            inorg = pointmark(norg) - in->firstnumber;
-            indest = pointmark(ndest) - in->firstnumber;
-            inapex = pointmark(napex) - in->firstnumber;
-            if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
-              // Find! Bond them together and break the loop.
-              bond(tetloop, neightet);
-              bondflag = true;
-              break;
-            }
-          }
-        }
-      }
-      if (!bondflag) {
-        hullsize++;  // It's a hull face.
-        // Bond this side to outer space.
-        dummytet[0] = encode(tetloop);
-        if ((in->pointmarkerlist != (int *) NULL) && !b->coarse) {
-          // Set its three corners's markers be boundary (hull) vertices.
-          if (in->pointmarkerlist[iorg] == 0) {
-            in->pointmarkerlist[iorg] = 1;
-          }
-          if (in->pointmarkerlist[idest] == 0) {
-            in->pointmarkerlist[idest] = 1;
-          }
-          if (in->pointmarkerlist[iapex] == 0) {
-            in->pointmarkerlist[iapex] = 1;
-          }
-        }
-      }
-      worklist[iorg] = 0;
-      worklist[idest] = 0;
-      worklist[iapex] = 0;
-    }
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  // Subfaces will be inserted into the mesh. It has two phases:
-  //   (1) Insert subfaces provided by user (in->trifacelist);
-  //   (2) Create subfaces for hull faces (if they're not subface yet) and
-  //       interior faces which separate two different materials.
-
-  // Phase (1). Is there a list of user-provided subfaces?
-  if (in->trifacelist != (int *) NULL) {
-    // Recover subfaces from 'in->trifacelist'.
-    for (i = 0; i < in->numberoftrifaces; i++) {
-      index = i * 3;
-      iorg = in->trifacelist[index] - in->firstnumber;
-      idest = in->trifacelist[index + 1] - in->firstnumber;
-      iapex = in->trifacelist[index + 2] - in->firstnumber;
-      // Look for the location of this subface.
-      worklist[iorg] = 1;
-      worklist[idest] = 1;
-      worklist[iapex] = 1;
-      bondflag = false;
-      // Search its neighbor in the adjacent tets of torg.
-      for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag; 
-           j++) {
-        neightet.tet = tetsperverlist[j];
-        for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
-          norg = org(neightet);
-          ndest = dest(neightet);
-          napex = apex(neightet);
-          inorg = pointmark(norg) - in->firstnumber;
-          indest = pointmark(ndest) - in->firstnumber;
-          inapex = pointmark(napex) - in->firstnumber;
-          if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
-            bondflag = true;  // Find!
-            break;
-          }
-        }
-      }
-      if (bondflag) {
-        // Create a new subface and insert it into the mesh.
-        makeshellface(subfaces, &subloop);
-        torg = idx2verlist[iorg];
-        tdest = idx2verlist[idest];
-        tapex = idx2verlist[iapex];
-        setsorg(subloop, torg);
-        setsdest(subloop, tdest);
-        setsapex(subloop, tapex);
-        // Set the vertices be FREESUBVERTEX to indicate they belong to a
-        //   facet of the domain.  They may be changed later.
-        setpointtype(torg, FREESUBVERTEX);
-        setpointtype(tdest, FREESUBVERTEX);
-        setpointtype(tapex, FREESUBVERTEX);
-        if (in->trifacemarkerlist != (int *) NULL) {
-          setshellmark(subloop, in->trifacemarkerlist[i]);
-        }
-        adjustedgering(neightet, CCW);
-        findedge(&subloop, org(neightet), dest(neightet));
-        tsbond(neightet, subloop);
-        sym(neightet, neineightet);
-        if (neineightet.tet != dummytet) {
-          sesymself(subloop);
-          tsbond(neineightet, subloop);
-        }
-      } else {
-        if (!b->quiet) {
-          printf("Warning:  Subface %d is discarded.\n", i + in->firstnumber);
-        }
-      }
-      worklist[iorg] = 0;
-      worklist[idest] = 0;
-      worklist[iapex] = 0;
-    }
-  } 
-
-  // Phase (2). Indentify subfaces from the mesh.
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    // Loop the four sides of the tetrahedron.
-    for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
-      tspivot(tetloop, subloop);
-      if (subloop.sh != dummysh) continue;
-      bondflag = false;
-      sym(tetloop, neightet);
-      if (neightet.tet == dummytet) {
-        // It's a hull face. Insert a subface at here.
-        bondflag = true;
-      } else {
-        // It's an interior face. Insert a subface if two tetrahedra have
-        //   different attributes (i.e., they belong to two regions).
-        if (in->numberoftetrahedronattributes > 0) {
-          if (elemattribute(neightet.tet,
-              in->numberoftetrahedronattributes - 1) != 
-              elemattribute(tetloop.tet,
-              in->numberoftetrahedronattributes - 1)) {
-            bondflag = true;
-          }
-        }
-      }
-      if (bondflag) {
-        adjustedgering(tetloop, CCW);
-        makeshellface(subfaces, &subloop);
-        torg = org(tetloop);
-        tdest = dest(tetloop);
-        tapex = apex(tetloop);
-        setsorg(subloop, torg);
-        setsdest(subloop, tdest);
-        setsapex(subloop, tapex);
-        // Set the vertices be FREESUBVERTEX to indicate they belong to a
-        //   facet of the domain.  They may be changed later.
-        setpointtype(torg, FREESUBVERTEX);
-        setpointtype(tdest, FREESUBVERTEX);
-        setpointtype(tapex, FREESUBVERTEX);
-        tsbond(tetloop, subloop);
-        if (neightet.tet != dummytet) {
-          sesymself(subloop);
-          tsbond(neightet, subloop);
-        }
-      }
-    }
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  // Set the connection between subfaces. A subsegment may have more than
-  //   two subfaces sharing it, 'neighshlist' stores all subfaces sharing
-  //   one edge.
-  neighshlist = new list(sizeof(face), NULL);
-  // Create a map from nodes to subfaces.
-  makesubfacemap(idx2facelist, facesperverlist);
-
-  // Loop over the set of subfaces, setup the connection between subfaces.
-  subfaces->traversalinit();
-  subloop.sh = shellfacetraverse(subfaces);
-  while (subloop.sh != (shellface *) NULL) {
-    for (i = 0; i < 3; i++) {
-      spivot(subloop, neighsh);
-      if (neighsh.sh == dummysh) {
-        // This side is 'empty', operate on it.
-        torg = sorg(subloop);
-        tdest = sdest(subloop);
-        tapex = sapex(subloop);
-        neighshlist->append(&subloop);
-        iorg = pointmark(torg) - in->firstnumber;
-        // Search its neighbor in the adjacent list of torg.
-        for (j = idx2facelist[iorg]; j < idx2facelist[iorg + 1]; j++) {
-          neighsh.sh = facesperverlist[j];
-          if (neighsh.sh == subloop.sh) continue;
-          neighsh.shver = 0;
-          if (isfacehasedge(&neighsh, torg, tdest)) {
-            findedge(&neighsh, torg, tdest);
-            // Insert 'neighsh' into 'neighshlist'.
-            if (neighshlist->len() < 2) {
-              neighshlist->append(&neighsh);
-            } else {
-              for (index = 0; index < neighshlist->len() - 1; index++) {
-                sface1 = * (face *)(* neighshlist)[index];
-                sface2 = * (face *)(* neighshlist)[index + 1];
-                da1 = facedihedral(torg, tdest, sapex(sface1), sapex(neighsh));
-                da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
-                if (da1 < da2) {
-                  break;  // Insert it after index.
-                }
-              }
-              neighshlist->insert(index + 1, &neighsh);
-            }
-          }
-        }
-        // Bond the subfaces in 'neighshlist'. 
-        if (neighshlist->len() > 1) {
-          neighsh = * (face *)(* neighshlist)[0];
-          for (j = 1; j <= neighshlist->len(); j++) {
-            if (j < neighshlist->len()) {
-              neineighsh = * (face *)(* neighshlist)[j];
-            } else {
-              neineighsh = * (face *)(* neighshlist)[0];
-            }
-            sbond1(neighsh, neineighsh);
-            neighsh = neineighsh;
-          }
-        } else {
-          // No neighbor subface be found, bond 'subloop' to itself.
-          sbond(subloop, subloop);
-        }
-        neighshlist->clear();
-      }
-      senextself(subloop);
-    }
-    subloop.sh = shellfacetraverse(subfaces);
-  }
-
-  // Segments will be introudced. Each segment has a unique marker (1-based).
-  marker = 1;
-  subfaces->traversalinit();
-  subloop.sh = shellfacetraverse(subfaces);
-  while (subloop.sh != (shellface *) NULL) {
-    for (i = 0; i < 3; i++) {
-      sspivot(subloop, subseg);
-      if (subseg.sh == dummysh) {
-        // This side has no subsegment bonded, check it.
-        torg = sorg(subloop);
-        tdest = sdest(subloop);
-        tapex = sapex(subloop);
-        spivot(subloop, neighsh);
-        spivot(neighsh, neineighsh);
-        insertsegflag = false;
-        if (subloop.sh == neighsh.sh || subloop.sh != neineighsh.sh) {
-          // This side is either self-bonded or more than two subfaces,
-          //   insert a subsegment at this side.
-          insertsegflag = true;
-        } else {
-          // Only two subfaces case.
-#ifdef SELF_CHECK
-          assert(subloop.sh != neighsh.sh);
-#endif
-          napex = sapex(neighsh);
-          sign = orient3d(torg, tdest, tapex, napex);
-          if (iscoplanar(torg, tdest, tapex, napex, sign, b->epsilon)) {
-            // Although they are coplanar, we still need to check if they
-            //   have the same boundary marker.
-            insertsegflag = (shellmark(subloop) != shellmark(neighsh));
-          } else {
-            // Non-coplanar.
-            insertsegflag = true;
-          }
-        }
-        if (insertsegflag) {
-          // Create a subsegment at this side.
-          makeshellface(subsegs, &subseg);
-          setsorg(subseg, torg);
-          setsdest(subseg, tdest);
-          // The two vertices have been marked as FREESUBVERTEX. Now mark
-          //   them as NACUTEVERTEX.
-          setpointtype(torg, NACUTEVERTEX);
-          setpointtype(tdest, NACUTEVERTEX);
-          setshellmark(subseg, marker);
-          marker++;
-          // Bond all subfaces to this subsegment.
-          neighsh = subloop;
-          do {
-            ssbond(neighsh, subseg);
-            spivotself(neighsh);
-          } while (neighsh.sh != subloop.sh);
-        }
-      }
-      senextself(subloop);
-    }
-    subloop.sh = shellfacetraverse(subfaces);
-  }
-  // Remember the number of input segments.
-  insegments = subsegs->items;
-  // Find the acute vertices and set them be type ACUTEVERTEX.
-
-  // Indentify facets and set the facet marker (1-based) for subfaces.
-  markerlist = new list("int");
-  
-  subfaces->traversalinit();
-  subloop.sh = shellfacetraverse(subfaces);
-  while (subloop.sh != (shellface *) NULL) {
-    // Only operate on uninfected subface, after operating, infect it.
-    if (!sinfected(subloop)) {
-      // A new facet is found.
-      marker = shellmark(subloop);
-      markerlist->append(&marker);
-      facetidx = markerlist->len(); // 'facetidx' starts from 1.
-      setshellmark(subloop, facetidx);
-      sinfect(subloop);
-      neighshlist->append(&subloop);
-      // Find out all subfaces of this facet (bounded by subsegments).
-      for (i = 0; i < neighshlist->len(); i++) {
-        neighsh = * (face *) (* neighshlist)[i];
-        for (j = 0; j < 3; j++) {
-          sspivot(neighsh, subseg);
-          if (subseg.sh == dummysh) {
-            spivot(neighsh, neineighsh);
-            if (!sinfected(neineighsh)) {
-              // 'neineighsh' is in the same facet as 'subloop'.
-#ifdef SELF_CHECK
-              assert(shellmark(neineighsh) == marker);
-#endif
-              setshellmark(neineighsh, facetidx);
-              sinfect(neineighsh);
-              neighshlist->append(&neineighsh);
-            }
-          }
-          senextself(neighsh);
-        }
-      }
-      neighshlist->clear();
-    }
-    subloop.sh = shellfacetraverse(subfaces);
-  }
-  // Uninfect all subfaces.
-  subfaces->traversalinit();
-  subloop.sh = shellfacetraverse(subfaces);
-  while (subloop.sh != (shellface *) NULL) {
-#ifdef SELF_CHECK
-    assert(sinfected(subloop));
-#endif
-    suninfect(subloop);
-    subloop.sh = shellfacetraverse(subfaces);
-  }
-  // Save the facet markers in 'in->facetmarkerlist'.
-  in->numberoffacets = markerlist->len();
-  in->facetmarkerlist = new int[in->numberoffacets];
-  for (i = 0; i < in->numberoffacets; i++) {
-    marker = * (int *) (* markerlist)[i];
-    in->facetmarkerlist[i] = marker;
-  }
-  // Initialize the 'facetabovepointlist'.
-  facetabovepointarray = new point[in->numberoffacets + 1];
-  for (i = 0; i < in->numberoffacets + 1; i++) {
-    facetabovepointarray[i] = (point) NULL;
-  }
-
-  // The mesh contains boundary now.
-  checksubfaces = 1;
-  // The mesh is nonconvex now.
-  nonconvex = 1;
-
-  // Is there periodic boundary confitions?
-  if (checkpbcs) {
-    tetgenio::pbcgroup *pg;
-    pbcdata *pd;
-    // Initialize the global array 'subpbcgrouptable'.
-    createsubpbcgrouptable();
-    // Loop for each pbcgroup i.
-    for (i = 0; i < in->numberofpbcgroups; i++) {
-      pg = &(in->pbcgrouplist[i]);
-      pd = &(subpbcgrouptable[i]);
-      // Find all subfaces of pd, set each subface's group id be i.
-      for (j = 0; j < 2; j++) {
-        subfaces->traversalinit();
-        subloop.sh = shellfacetraverse(subfaces);
-        while (subloop.sh != (shellface *) NULL) {
-          facetidx = shellmark(subloop);
-          marker = in->facetmarkerlist[facetidx - 1];
-          if (marker == pd->fmark[j]) {
-            setshellpbcgroup(subloop, i);
-            pd->ss[j] = subloop;
-          }
-          subloop.sh = shellfacetraverse(subfaces);
-        }
-      }
-      if (pg->pointpairlist != (int *) NULL) {
-        // Set the connections between pbc point pairs.
-        for (j = 0; j < pg->numberofpointpairs; j++) {
-          iorg = pg->pointpairlist[j * 2] - in->firstnumber;
-          idest = pg->pointpairlist[j * 2 + 1] - in->firstnumber;
-          torg = idx2verlist[iorg];
-          tdest = idx2verlist[idest];
-          setpoint2pbcpt(torg, tdest);
-          setpoint2pbcpt(tdest, torg);
-        }
-      }
-    }
-    // Create the global array 'segpbcgrouptable'.
-    createsegpbcgrouptable();
-  }
-
-  delete markerlist;
-  delete neighshlist;
-  delete [] worklist;
-  delete [] idx2tetlist;
-  delete [] tetsperverlist;
-  delete [] idx2facelist;
-  delete [] facesperverlist;
-  delete [] idx2verlist;
-  
-  return hullsize;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// insertconstrainedpoints()    Insert a list of constrained points.         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
-{
-  queue *flipqueue;
-  triface searchtet;
-  face checksh, checkseg;
-  point newpoint;
-  enum locateresult loc;
-  REAL *attr;
-  bool insertflag;
-  int covertices, outvertices;
-  int index;
-  int i, j;
-  
-  if (!b->quiet) {
-    printf("Insert additional points into mesh.\n");
-  }
-  // Initialize 'flipqueue'.
-  flipqueue = new queue(sizeof(badface));
-  recenttet.tet = dummytet;
-  covertices = outvertices = 0;
-
-  index = 0;
-  for (i = 0; i < addio->numberofpoints; i++) {
-    // Create a newpoint.
-    makepoint(&newpoint);
-    newpoint[0] = addio->pointlist[index++];
-    newpoint[1] = addio->pointlist[index++];
-    newpoint[2] = addio->pointlist[index++];
-    // Read the add point attributes if current points have attributes.
-    if ((addio->numberofpointattributes > 0) &&
-        (in->numberofpointattributes > 0)) {
-      attr = addio->pointattributelist + addio->numberofpointattributes * i;
-      for (j = 0; j < in->numberofpointattributes; j++) {
-        if (j < addio->numberofpointattributes) {
-          newpoint[3 + j] = attr[j];
-        }
-      }
-    }
-    // Find the location of the inserted point.
-    searchtet = recenttet;
-    loc = locate(newpoint, &searchtet);
-    if (loc != ONVERTEX) {
-      loc = adjustlocate(newpoint, &searchtet, loc, b->epsilon2);
-    }
-    if (loc == OUTSIDE) {
-      loc = hullwalk(newpoint, &searchtet);
-      if (loc == OUTSIDE) {
-        // Perform a brute-force search.
-        tetrahedrons->traversalinit();
-        searchtet.tet = tetrahedrontraverse();
-        while (searchtet.tet != (tetrahedron *) NULL) {
-          loc = adjustlocate(newpoint, &searchtet, OUTSIDE, b->epsilon2);
-          if (loc != OUTSIDE) break;
-          searchtet.tet = tetrahedrontraverse();
-        }
-      }
-    }
-    // Insert the point if it not lies outside or on a vertex.
-    insertflag = true;
-    switch (loc) {
-    case INTETRAHEDRON:
-      setpointtype(newpoint, FREEVOLVERTEX);
-      splittetrahedron(newpoint, &searchtet, flipqueue);
-      break;
-    case ONFACE:
-      tspivot(searchtet, checksh);
-      if (checksh.sh != dummysh) {
-        // It is a boundary face. Don't insert it if -Y option is used.
-        if (b->nobisect) {
-          insertflag = false;
-        } else {
-          setpointtype(newpoint, FREESUBVERTEX);
-        }
-      } else {
-        setpointtype(newpoint, FREEVOLVERTEX);
-      }
-      if (insertflag) {
-        splittetface(newpoint, &searchtet, flipqueue);
-      }
-      break;
-    case ONEDGE:
-      tsspivot(&searchtet, &checkseg);
-      if (checkseg.sh != dummysh) {
-        if (b->nobisect) {
-          insertflag = false;
-        } else {
-          setpointtype(newpoint, FREESEGVERTEX);
-          setpoint2sh(newpoint, sencode(checkseg));
-        }
-      } else {
-        tspivot(searchtet, checksh);
-        if (checksh.sh != dummysh) {
-          if (b->nobisect) {
-            insertflag = false;
-          } else {
-            setpointtype(newpoint, FREESUBVERTEX);
-          }
-        } else {
-          setpointtype(newpoint, FREEVOLVERTEX);
-        }
-      }
-      if (insertflag) {
-        splittetedge(newpoint, &searchtet, flipqueue);
-      }
-      break;
-    case ONVERTEX:
-      insertflag = false;
-      covertices++;
-      break;
-    case OUTSIDE:
-      insertflag = false;
-      outvertices++;
-      break;
-    }
-    // Remember the tetrahedron for next point searching.
-    recenttet = searchtet;
-    if (!insertflag) {
-      pointdealloc(newpoint);
-    } else {
-      flip(flipqueue, NULL);
-    }
-  }
-
-  if (b->verbose) {
-    if (covertices > 0) {
-      printf("  %d constrained points already exist.\n", covertices);
-    }
-    if (outvertices > 0) {
-      printf("  %d constrained points lie outside the mesh.\n", outvertices);
-    }
-    printf("  %d constrained points have been inserted.\n", 
-           addio->numberofpoints - covertices - outvertices);
-  }
-
-  delete flipqueue;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// p1interpolatebgm()    Set pt size by p^1 interpolation in background mesh.//
-//                                                                           //
-// On input, 'bgmtet' is a suggesting tet in background mesh for searching   //
-// 'pt'. It returns the tet containing 'pt'.                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::p1interpolatebgm(point pt, triface* bgmtet, long *scount)
-{
-  point bgmpt[4];
-  enum locateresult loc;
-  REAL vol, volpt[4], weights[4];
-  int i;
-
-  loc = bgm->preciselocate(pt, bgmtet, bgm->tetrahedrons->items);
-  if (loc == OUTSIDE) {
-    loc = bgm->hullwalk(pt, bgmtet);
-    if (loc == OUTSIDE) {
-      // Perform a brute-force search.
-      if (b->verbose) {
-        printf("Warning:  Global point location.\n");
-      }
-      if (scount) (*scount)++;
-      bgm->tetrahedrons->traversalinit(); // in bgm
-      bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
-      while (bgmtet->tet != (tetrahedron *) NULL) {
-        loc = bgm->adjustlocate(pt, bgmtet, OUTSIDE, b->epsilon);
-        if (loc != OUTSIDE) break;
-        bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
-      }
-    }
-  }
-  if (loc != OUTSIDE) {
-    // Let p remember t.
-    setpoint2bgmtet(pt, encode(*bgmtet)); // in m
-    // get the corners of t.
-    for (i = 0; i < 4; i++) bgmpt[i] = (point) bgmtet->tet[4 + i];
-    // Calculate the weighted coordinates of p in t.
-    vol = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], bgmpt[3]);
-    volpt[0] = orient3d(pt, bgmpt[1], bgmpt[2], bgmpt[3]);
-    volpt[1] = orient3d(bgmpt[0], pt, bgmpt[2], bgmpt[3]);
-    volpt[2] = orient3d(bgmpt[0], bgmpt[1], pt, bgmpt[3]);
-    volpt[3] = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], pt);
-    for (i = 0; i < 4; i++) weights[i] = fabs(volpt[i] / vol);
-    // Interpolate the solution for p.
-    for (i = 0; i < bgm->in->numberofpointmtrs; i++) {
-      pt[pointmtrindex + i] = weights[0] * bgmpt[0][bgm->pointmtrindex + i]
-                            + weights[1] * bgmpt[1][bgm->pointmtrindex + i]
-                            + weights[2] * bgmpt[2][bgm->pointmtrindex + i]
-                            + weights[3] * bgmpt[3][bgm->pointmtrindex + i];
-    }
-  } else {
-    setpoint2bgmtet(pt, (tetrahedron) NULL);  // in m
-  }
-  return loc != OUTSIDE;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// interpolatesizemap()    Interpolate the point sizes in the given size map.//
-//                                                                           //
-// The size map is specified on each node of the background mesh. The points //
-// of current mesh get their sizes by interpolating.                         //
-//                                                                           //
-// This function operation on two meshes simultaneously, the current mesh m, //
-// and the background mesh bgm. After this function, each point p in m will  //
-// have a pointer to a tet of bgm.                                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::interpolatesizemap()
-{
-  list *adjtetlist;
-  triface tetloop, neightet, bgmtet;
-  point searchpt;
-  long scount;
-  int *worklist;
-  int sepcount;
-  int i;
-
-  if (b->verbose) {
-    printf("  Interpolating size map.\n");
-  }
-
-  worklist = new int[points->items + 1];
-  for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
-  sepcount = 0;
-  scount = 0l;
-
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    if (!infected(tetloop)) {
-      // Find a new subdomain.
-      adjtetlist = new list(sizeof(triface), NULL, 1024);
-      infect(tetloop);
-      // Search the four corners in background mesh.
-      for (i = 0; i < 4; i++) {
-        searchpt = (point) tetloop.tet[4 + i];
-        // Mark the point for avoiding multiple searchings.
-        // assert(worklist[pointmark(searchpt)] == 0);
-        worklist[pointmark(searchpt)] = 1;
-        // Does it contain a pointer to bgm tet?
-        bgm->decode(point2bgmtet(searchpt), bgmtet);
-        if (bgm->isdead(&bgmtet)) {
-          bgmtet = bgm->recenttet;
-        }
-        if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
-          bgm->recenttet = bgmtet;
-        }
-      } // for (i = 0; i < 4; i++)
-      // Collect all tets in this region.
-      adjtetlist->append(&tetloop);
-      // Collect the tets in the subdomain.
-      for (i = 0; i < adjtetlist->len(); i++) {
-        tetloop = * (triface *)(* adjtetlist)[i];
-        for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
-          sym(tetloop, neightet);
-          if ((neightet.tet != dummytet) && !infected(neightet)) {
-            // Only need to search for the opposite point.
-            searchpt = oppo(neightet);
-            if (worklist[pointmark(searchpt)] == 0) {
-              worklist[pointmark(searchpt)] = 1;
-              decode(point2bgmtet(searchpt), bgmtet);
-              if (bgm->isdead(&bgmtet)) {
-                bgmtet = bgm->recenttet;
-              }
-              if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
-                bgm->recenttet = bgmtet;
-              }
-            }
-            infect(neightet);
-            adjtetlist->append(&neightet);
-          }
-        }
-      }
-      // Increase the number of separated domains.
-      sepcount++;
-      delete adjtetlist;
-    } // if (!infect())
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  // Unmark all tets.
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    assert(infected(tetloop));
-    uninfect(tetloop);
-    tetloop.tet = tetrahedrontraverse();
-  }
-  delete [] worklist;
-
-#ifdef SELF_CHECK
-  if (b->verbose && scount > 0l) {
-    printf("  %ld brute-force searches.\n", scount);
-  }
-  if (b->verbose && sepcount > 0) {
-    printf("  %d separate domains.\n", sepcount);
-  }
-#endif
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// duplicatebgmesh()    Duplicate current mesh to background mesh.           //
-//                                                                           //
-// Current mesh 'this' is copied into 'this->bgm'.Both meshes share the same //
-// input tetgenio object, 'this->in', same tetgenbehavior object 'this->b'.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::duplicatebgmesh()
-{
-  triface tetloop, btetloop;
-  triface symtet, bsymtet;
-  face bhullsh, bneighsh;
-  point *idx2bplist, *tetptbaklist;
-  point ploop, bploop;
-  int idx, i;
-
-  if (!b->quiet) {
-    printf("Duplicating background mesh.\n");
-  }
-
-  // The background mesh itself has no background mesh.
-  // assert(bgm->bgm == (tetgenmesh *) NULL);
-  // The space for metric tensor should be allocated.
-  // assert(bgm->sizeoftensor > 0);
-
-  // Copy point list.
-  idx2bplist = new point[points->items + 1];
-  idx = in->firstnumber;
-  points->traversalinit();
-  ploop = pointtraverse();
-  while (ploop != (point) NULL) {
-    bgm->makepoint(&bploop);
-    // Copy coordinates, attributes.
-    for (i = 0; i < 3 + in->numberofpointattributes; i++) {
-      bploop[i] = ploop[i];
-    }
-    // Transfer the metric tensor.
-    for (i = 0; i < bgm->sizeoftensor; i++) {
-      bploop[bgm->pointmtrindex + i] = ploop[pointmtrindex + i];
-      // Metric tensor should have a positive value.
-      if (bploop[bgm->pointmtrindex + i] <= 0.0) {
-        printf("Error:  Point %d has non-positive size %g (-m option).\n",
-               bgm->pointmark(bploop), bploop[bgm->pointmtrindex + i]);
-        terminatetetgen(1);
-      }
-    }
-    // Remember the point for searching.
-    idx2bplist[idx++] = bploop; 
-    ploop = pointtraverse();
-  }
-
-  // Copy tetrahedra list.
-  tetptbaklist = new point[tetrahedrons->items + 1];
-  idx = in->firstnumber;
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    bgm->maketetrahedron(&btetloop);
-    // Set the four corners.
-    for (i = 0; i < 4; i++) {
-      ploop = (point) tetloop.tet[4 + i];
-      bploop = idx2bplist[pointmark(ploop)];
-      btetloop.tet[4 + i] = (tetrahedron) bploop;
-    }
-    // Remember the tet for setting neighbor connections.
-    tetptbaklist[idx++] = (point) tetloop.tet[4];
-    tetloop.tet[4] = (tetrahedron) btetloop.tet; 
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  // Set the connections between background tetrahedra. Create background
-  //   hull subfaces. Create the map of point-to-bgmtet. 
-  idx = in->firstnumber;
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    // Get the corresponding background tet.
-    btetloop.tet = (tetrahedron *) tetloop.tet[4];
-    // Set the four neighbors.
-    for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
-      btetloop.loc = tetloop.loc;
-      sym(tetloop, symtet);
-      if ((symtet.tet != dummytet) && (symtet.tet > tetloop.tet)) {
-        // Operate on the un-connected interior face.
-        bsymtet.tet = (tetrahedron *) symtet.tet[4]; // The saved bgm tet.
-        bsymtet.loc = symtet.loc;
-        bgm->bond(btetloop, bsymtet);
-      } else if (symtet.tet == dummytet) {
-        // Create a subface in background mesh.
-        bgm->makeshellface(bgm->subfaces, &bhullsh);
-        bgm->adjustedgering(btetloop, CCW); // face to inside.
-        bgm->setsorg(bhullsh, bgm->org(btetloop));
-        bgm->setsdest(bhullsh, bgm->dest(btetloop));
-        bgm->setsapex(bhullsh, bgm->apex(btetloop));
-        bgm->tsbond(btetloop, bhullsh);
-        // Remember a hull face for point location.
-        bgm->dummytet[0] = bgm->encode(btetloop);
-      }
-    }
-    // Restore the backup tet point.
-    tetloop.tet[4] = (tetrahedron) tetptbaklist[idx++];
-    // Make the point-to-bgmtet map for size interpolation.
-    btetloop.loc = 0;
-    for (i = 0; i < 4; i++) {
-      ploop = (point) tetloop.tet[4 + i];
-      setpoint2bgmtet(ploop, bgm->encode(btetloop));
-    } 
-    // Go to the next tet, btet.
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  // Connect bgm hull subfaces. Note: all hull subfaces form a 2-manifold.
-  bgm->subfaces->traversalinit();
-  bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
-  while (bhullsh.sh != (shellface *) NULL) {
-    bhullsh.shver = 0;
-    bgm->stpivot(bhullsh, btetloop);
-    assert(btetloop.tet != bgm->dummytet);
-    bgm->adjustedgering(btetloop, CCW);
-    for (i = 0; i < 3; i++) {
-      bgm->spivot(bhullsh, bneighsh);
-      if (bneighsh.sh == bgm->dummysh) {
-        // This side is open, operate on it.
-        bsymtet = btetloop;
-        while (bgm->fnextself(bsymtet));
-        bgm->tspivot(bsymtet, bneighsh);
-        bgm->findedge(&bneighsh, bgm->sdest(bhullsh), bgm->sorg(bhullsh));
-        bgm->sbond(bhullsh, bneighsh);
-      }
-      bgm->enextself(btetloop);
-      bgm->senextself(bhullsh);
-    }
-    bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
-  }
-
-  delete [] tetptbaklist;
-  delete [] idx2bplist;
-}
-
-//
-// Begin of Delaunay refinement routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// marksharpsegments()    Mark sharp segments.                               //
-//                                                                           //
-// A segment s is called sharp if it is in one of the two cases:             //
-//  (1) There is a segment s' intersecting with s.  The internal angle (*)   //
-//      between s and s' is acute.                                           //
-//  (2) There are two facets f1 and f2 intersecting at s.  The internal      //
-//      dihedral angle (*) between f1 and f2 is acute.                       //
-// This routine finds the sharp segments and marked them as type SHARP.      //
-// The minimum angle between segments (minfaceang) and the minimum dihedral  //
-// angle between facets (minfacetdihed) are calulcated.                      //
-//                                                                           //
-// (*) The internal angle (or dihedral) bewteen two features means the angle //
-// inside the mesh domain.                                                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::marksharpsegments(REAL sharpangle)
-{
-  triface adjtet;
-  face startsh, spinsh, neighsh;
-  face segloop, prevseg, nextseg;
-  point eorg, edest;
-  REAL ang, smallang;
-  bool issharp;
-  int sharpsegcount;
-
-  if (b->verbose > 0) {
-    printf("  Marking sharp segments.\n");
-  }
-
-  smallang = sharpangle * PI / 180.;
-  sharpsegcount = 0;
-  eorg = edest = (point) NULL; // To avoid compiler warnings.
-   
-  // A segment s may have been split into many subsegments. Operate the one
-  //   which contains the origin of s. Then mark the rest of subsegments.
-  subsegs->traversalinit();
-  segloop.sh = shellfacetraverse(subsegs);
-  while (segloop.sh != (shellface *) NULL) {
-    segloop.shver = 0;
-    senext2(segloop, prevseg);
-    spivotself(prevseg);
-    if (prevseg.sh == dummysh) {
-      // Operate on this seg s.
-      assert(shelltype(segloop) != SHARP); // It should be unmarked.
-      issharp = false;
-      spivot(segloop, startsh);
-      if (startsh.sh != dummysh) {
-        // First check if two facets form an acute dihedral angle at s.
-        eorg = sorg(segloop);
-        edest = sdest(segloop);
-        spinsh = startsh;
-        do {
-          if (sorg(spinsh) != eorg) {
-            sesymself(spinsh);
-          }
-          // Only do test when the spinsh is faceing inward.
-          stpivot(spinsh, adjtet);          
-          if (adjtet.tet != dummytet) {
-            // Get the subface on the adjacent facet.
-            spivot(spinsh, neighsh);
-            // Do not calculate if it is self-bonded.
-            if (neighsh.sh != spinsh.sh) {
-              // Calculate the dihedral angle between the two subfaces.
-              ang = facedihedral(eorg, edest, sapex(spinsh), sapex(neighsh));
-              // Only do check if a sharp angle has not been found.
-              if (!issharp) issharp = (ang < smallang);
-              // Remember the smallest facet dihedral angle.
-              minfacetdihed = minfacetdihed < ang ? minfacetdihed : ang;
-            }
-          }
-          // Go to the next facet.
-          spivotself(spinsh);
-        } while (spinsh.sh != startsh.sh);
-        // if (!issharp) {
-          // Second check if s forms an acute angle with another seg.
-          spinsh = startsh;
-          do {
-            if (sorg(spinsh) != eorg) {
-              sesymself(spinsh);
-            }
-            // Calculate the angle between s and s' of this facet.
-            neighsh = spinsh;
-            // Rotate edges around 'eorg' until meeting another seg s'. Such  
-            //   seg (s') must exist since the facet is segment-bounded.
-            //   The sum of the angles of faces at 'eorg' gives the internal
-            //   angle between the two segments.
-            ang = 0.0;
-            do {
-              ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
-              senext2self(neighsh);
-              sspivot(neighsh, nextseg);
-              if (nextseg.sh != dummysh) break;
-              // Go to the next coplanar subface.
-              spivotself(neighsh);
-              assert(neighsh.sh != dummysh);
-              if (sorg(neighsh) != eorg) {
-                sesymself(neighsh);
-              }
-            } while (true);
-            // Only do check if a sharp angle has not been found.
-            if (!issharp) issharp = (ang < smallang);
-            // Remember the smallest input face angle.
-            minfaceang = minfaceang < ang ? minfaceang : ang;
-            // Go to the next facet.
-            spivotself(spinsh);
-          } while (spinsh.sh != startsh.sh);
-        // }
-      }
-      if (issharp) {
-        setshelltype(segloop, SHARP);
-        // Set the type for all subsegments at forwards.
-        senext(segloop, nextseg);
-        spivotself(nextseg);
-        while (nextseg.sh != dummysh) {
-          nextseg.shver = 0;
-          setshelltype(nextseg, SHARP);
-          senextself(nextseg);
-          spivotself(nextseg);
-        }
-        sharpsegcount++;
-      }
-    }
-    segloop.sh = shellfacetraverse(subsegs);
-  }
-
-  // So far we have marked all segments which have an acute dihedral angle
-  //   or whose ORIGINs have an acute angle. In the un-marked subsegments,
-  //   there are possible ones whose DESTINATIONs have an acute angle.
-  subsegs->traversalinit();
-  segloop.sh = shellfacetraverse(subsegs);
-  while (segloop.sh != (shellface *) NULL) {
-    // Only operate if s is non-sharp and contains the dest.
-    segloop.shver = 0;
-    senext(segloop, nextseg);
-    spivotself(nextseg);
-    // if ((nextseg.sh == dummysh) && (shelltype(segloop) != SHARP)) {
-    if (nextseg.sh == dummysh) {
-      // issharp = false;
-      issharp = (shelltype(segloop) == SHARP);
-      spivot(segloop, startsh);
-      if (startsh.sh != dummysh) {
-        // Check if s forms an acute angle with another seg.
-        eorg = sdest(segloop);
-        spinsh = startsh;
-        do {
-          if (sorg(spinsh) != eorg) {
-            sesymself(spinsh);
-          }
-          // Calculate the angle between s and s' of this facet.
-          neighsh = spinsh;
-          ang = 0.0;
-          do {
-            ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
-            senext2self(neighsh);
-            sspivot(neighsh, nextseg);
-            if (nextseg.sh != dummysh) break;
-            // Go to the next coplanar subface.
-            spivotself(neighsh);
-            assert(neighsh.sh != dummysh);
-            if (sorg(neighsh) != eorg) {
-              sesymself(neighsh);
-            }
-          } while (true);
-          // Only do check if a sharp angle has not been found.
-          if (!issharp) issharp = (ang < smallang);
-          // Remember the smallest input face angle.
-          minfaceang = minfaceang < ang ? minfaceang : ang;
-          // Go to the next facet.
-          spivotself(spinsh);
-        } while (spinsh.sh != startsh.sh);
-      }
-      if (issharp) {
-        setshelltype(segloop, SHARP);
-        // Set the type for all subsegments at backwards.
-        senext2(segloop, prevseg);
-        spivotself(prevseg);
-        while (prevseg.sh != dummysh) {
-          prevseg.shver = 0;
-          setshelltype(prevseg, SHARP);
-          senext2self(prevseg);
-          spivotself(prevseg);
-        }
-        sharpsegcount++;
-      }
-    }
-    segloop.sh = shellfacetraverse(subsegs);
-  } 
-
-  if ((b->verbose > 0) && (sharpsegcount > 0)) {
-    printf("  %d sharp segments.\n", sharpsegcount);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// decidefeaturepointsizes()    Decide the sizes for all feature points.     //
-//                                                                           //
-// A feature point is a point on a sharp segment. Every feature point p will //
-// be assigned a positive size which is the radius of the protecting ball.   //
-//                                                                           //
-// The size of a feature point may be specified by one of the following ways://
-//   (1) directly specifying on an input vertex (by using .mtr file);        //
-//   (2) imposing a fixed maximal volume constraint ('-a__' option);         //
-//   (3) imposing a maximal volume constraint in a region ('-a' option);     //
-//   (4) imposing a maximal area constraint on a facet (in .var file);       //
-//   (5) imposing a maximal length constraint on a segment (in .var file);   //
-//   (6) combining (1) - (5).                                                //
-//   (7) automatically deriving a size if none of (1) - (6) is available.    //
-// In case (7),the size of p is set to be the smallest edge length among all //
-// edges connecting at p.  The final size of p is the minimum of (1) - (7).  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::decidefeaturepointsizes()
-{
-  list *tetlist, *verlist;
-  shellface **segsperverlist;
-  triface starttet;
-  face shloop;
-  face checkseg, prevseg, nextseg, testseg;
-  point ploop, adjpt, e1, e2;
-  REAL lfs_0, len, vol, maxlen, varlen;
-  bool isfeature;
-  int *idx2seglist;
-  int featurecount;
-  int idx, i, j;
-
-  if (b->verbose > 0) {
-    printf("  Deciding feature-point sizes.\n");
-  }
-
-  // Constructing a map from vertices to segments.
-  makesegmentmap(idx2seglist, segsperverlist);
-  // Initialize working lists.
-  tetlist = new list(sizeof(triface), NULL, 256);
-  verlist = new list(sizeof(point *), NULL, 256);
-
-  if (b->fixedvolume) {
-    // A fixed volume constraint is imposed. This gives an upper bound of
-    //   the maximal radius of the protect ball of a vertex.
-    maxlen = pow(6.0 * b->maxvolume, 1.0/3.0);
-  }
-
-  if (!b->refine) {
-    // Initially correct types for Steiner points.
-    featurecount = 0;
-    points->traversalinit();
-    ploop = pointtraverse();
-    while (ploop != (point) NULL) {
-      if (pointtype(ploop) == NACUTEVERTEX) {
-        if (point2sh(ploop) != (shellface) NULL) {
-          setpointtype(ploop, FREESEGVERTEX);
-          featurecount++;
-        }
-      }
-      ploop = pointtraverse();
-    }
-#ifdef SELF_CHECK
-    if ((b->verbose > 0) && (featurecount > 0)) {
-      printf("  %d Steiner points correction.\n", featurecount);
-    }
-#endif
-  }
-
-  // First only assign a size of p if p is not a Steiner point. The size of
-  //   a Steiner point will be interpolated later from the endpoints of the
-  //   segment on which it lies. 
-  featurecount = 0;
-  points->traversalinit();
-  ploop = pointtraverse();
-  while (ploop != (point) NULL) {
-    if (pointtype(ploop) != FREESEGVERTEX) {
-      // Is p a feature point?
-      isfeature = false;
-      idx = pointmark(ploop) - in->firstnumber;
-      for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; i++) {
-        checkseg.sh = segsperverlist[i];
-        isfeature = (shelltype(checkseg) == SHARP);
-      }
-      // Decide the size of p if it is on a sharp segment.
-      if (isfeature) {
-        // Find a tet containing p (checkseg is a sharp seg which contains p).
-        sstpivot(&checkseg, &starttet);
-        // Form star(p).
-        tetlist->append(&starttet);
-        formstarpolyhedron(ploop, tetlist, verlist, true);
-        // Decide the size for p if no input size is given on input.
-        if (ploop[pointmtrindex] == 0.0) {
-          // Calculate lfs_0(p).
-          lfs_0 = longest;
-          for (i = 0; i < verlist->len(); i++) {
-            adjpt = * (point *)(* verlist)[i];
-            if (pointtype(adjpt) == FREESEGVERTEX) {
-              // A Steiner point q. Find the seg it lies on.
-              sdecode(point2sh(adjpt), checkseg);
-              assert(checkseg.sh != dummysh);
-              checkseg.shver = 0;
-              // Find the origin of this seg.
-              prevseg = checkseg;
-              do {
-                senext2(prevseg, testseg);
-                spivotself(testseg);
-                if (testseg.sh == dummysh) break;
-                prevseg = testseg; // Go to the previous subseg.
-                prevseg.shver = 0;
-              } while (true);
-              // Find the dest of this seg.
-              nextseg = checkseg;
-              do {
-                senext(nextseg, testseg);
-                spivotself(testseg);
-                if (testseg.sh == dummysh) break;
-                nextseg = testseg; // Go to the next subseg.
-                nextseg.shver = 0;
-              } while (true);
-              e1 = sorg(prevseg);
-              e2 = sdest(nextseg);
-              // Check if p is the origin or the dest of this seg.
-              if (ploop == e1) {
-                // Set q to be the dest of this seg.
-                adjpt = e2;
-              } else if (ploop == e2) {
-                // Set q to be the org of this seg.
-                adjpt = e1;
-              }
-            }
-            len = distance(ploop, adjpt);
-            if (lfs_0 > len) lfs_0 = len;
-          }
-          ploop[pointmtrindex] = lfs_0;
-        }
-        if (b->fixedvolume) {
-          // A fixed volume constraint is imposed. Adjust H(p) <= maxlen.
-          if (ploop[pointmtrindex] > maxlen) {
-            ploop[pointmtrindex] = maxlen;
-          }
-        }
-        if (b->varvolume) {
-          // Variant volume constraints are imposed. Adjust H(p) <= varlen.
-          for (i = 0; i < tetlist->len(); i++) {
-            starttet = * (triface *)(* tetlist)[i];
-            vol = volumebound(starttet.tet);
-            if (vol > 0.0) {
-              varlen = pow(6 * vol, 1.0/3.0);
-              if (ploop[pointmtrindex] > varlen) {
-                ploop[pointmtrindex] = varlen;
-              }
-            }
-          }
-        }
-        // Clear working lists.
-        tetlist->clear();
-        verlist->clear();
-        featurecount++;
-      } else {
-        // NO feature point, set the size of p be zero.
-        ploop[pointmtrindex] = 0.0;
-      }
-    } // if (pointtype(ploop) != FREESEGVERTEX) {
-    ploop = pointtraverse();
-  }
-
-  if (b->verbose > 0) {
-    printf("  %d feature points.\n", featurecount);
-  }
-
-  if (!b->refine) {
-    // Second only assign sizes for all Steiner points. A Steiner point p
-    //   inserted on a sharp segment s is assigned a size by interpolating
-    //   the sizes of the original endpoints of s.
-    featurecount = 0;
-    points->traversalinit();
-    ploop = pointtraverse();
-    while (ploop != (point) NULL) {
-      if (pointtype(ploop) == FREESEGVERTEX) {
-        if (ploop[pointmtrindex] == 0.0) {
-          sdecode(point2sh(ploop), checkseg);
-          assert(checkseg.sh != dummysh);
-          if (shelltype(checkseg) == SHARP) {
-            checkseg.shver = 0;
-            // Find the origin of this seg.
-            prevseg = checkseg;
-            do {
-              senext2(prevseg, testseg);
-              spivotself(testseg);
-              if (testseg.sh == dummysh) break;
-              prevseg = testseg; // Go the previous subseg.
-              prevseg.shver = 0;
-            } while (true);
-            // Find the dest of this seg.
-            nextseg = checkseg;
-            do {
-              senext(nextseg, testseg);
-              spivotself(testseg);
-              if (testseg.sh == dummysh) break;
-              nextseg = testseg; // Go the next subseg.
-              nextseg.shver = 0;
-            } while (true);
-            e1 = sorg(prevseg);
-            e2 = sdest(nextseg);
-            len = distance(e1, e2);
-            lfs_0 = distance(e1, ploop);
-            // The following assert() happens when -Y option is used.
-            if (b->nobisect == 0) {
-              assert(lfs_0 < len); 
-            }
-            ploop[pointmtrindex] = e1[pointmtrindex]
-              + (lfs_0 / len) * (e2[pointmtrindex] - e1[pointmtrindex]);
-            featurecount++;
-          } else {
-            // NO feature point, set the size of p be zero.
-            ploop[pointmtrindex] = 0.0;
-          } // if (shelltype(checkseg) == SHARP)
-        } // if (ploop[pointmtrindex] == 0.0)
-      } // if (pointtype(ploop) != FREESEGVERTEX)
-      ploop = pointtraverse();
-    }
-    if ((b->verbose > 0) && (featurecount > 0)) {
-      printf("  %d Steiner feature points.\n", featurecount);
-    }
-  }
-
-  if (varconstraint) {
-    // A .var file exists. Adjust feature sizes.
-    if (in->facetconstraintlist) {
-      // Have facet area constrains.
-      subfaces->traversalinit();
-      shloop.sh = shellfacetraverse(subfaces);
-      while (shloop.sh != (shellface *) NULL) {
-        varlen = areabound(shloop);
-        if (varlen > 0.0) {
-          // Check if the three corners are feature points.
-          varlen = sqrt(varlen);
-          for (j = 0; j < 3; j++) {
-            ploop = (point) shloop.sh[3 + j];
-            isfeature = false;
-            idx = pointmark(ploop) - in->firstnumber;
-            for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; 
-                 i++) {
-              checkseg.sh = segsperverlist[i];
-              isfeature = (shelltype(checkseg) == SHARP);
-            }
-            if (isfeature) {
-              assert(ploop[pointmtrindex] > 0.0);
-              if (ploop[pointmtrindex] > varlen) {
-                ploop[pointmtrindex] = varlen;
-              }
-            }
-          } // for (j = 0; j < 3; j++)
-        }
-        shloop.sh = shellfacetraverse(subfaces);
-      }
-    }
-    if (in->segmentconstraintlist) {
-      // Have facet area constrains.
-      subsegs->traversalinit();
-      shloop.sh = shellfacetraverse(subsegs);
-      while (shloop.sh != (shellface *) NULL) {
-        varlen = areabound(shloop);
-        if (varlen > 0.0) {
-          // Check if the two endpoints are feature points.
-          for (j = 0; j < 2; j++) {
-            ploop = (point) shloop.sh[3 + j];
-            isfeature = false;
-            idx = pointmark(ploop) - in->firstnumber;
-            for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; 
-                 i++) {
-              checkseg.sh = segsperverlist[i];
-              isfeature = (shelltype(checkseg) == SHARP);
-            }
-            if (isfeature) {
-              assert(ploop[pointmtrindex] > 0.0);
-              if (ploop[pointmtrindex] > varlen) {
-                ploop[pointmtrindex] = varlen;
-              }
-            }
-          } // for (j = 0; j < 2; j++)
-        }
-        shloop.sh = shellfacetraverse(subsegs);
-      }
-    }
-  } // if (varconstraint)
-
-  delete [] segsperverlist;
-  delete [] idx2seglist;
-  delete tetlist;
-  delete verlist;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// enqueueencsub()    Add an encroached subface into the queue.              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::enqueueencsub(face* testsub, point encpt, int quenumber,
-  REAL* cent)
-{
-  badface *encsub;
-  int i;
-
-  encsub = (badface *) badsubfaces->alloc();
-  encsub->ss = *testsub;
-  encsub->forg = sorg(*testsub);
-  encsub->fdest = sdest(*testsub);
-  encsub->fapex = sapex(*testsub);
-  encsub->foppo = (point) encpt;
-  for (i = 0; i < 3; i++) encsub->cent[i] = cent[i];
-  encsub->nextitem = (badface *) NULL;
-  // Set the pointer of 'encsubseg' into 'testsub'.  It has two purposes:
-  //   (1) We can regonize it is encroached; (2) It is uniquely queued.
-  setshell2badface(encsub->ss, encsub);
-  // Add the subface to the end of a queue (quenumber = 2, high priority).
-  *subquetail[quenumber] = encsub;
-  // Maintain a pointer to the NULL pointer at the end of the queue.
-  subquetail[quenumber] = &encsub->nextitem;
-  if (b->verbose > 2) {
-    printf("    Queuing subface (%d, %d, %d) [%d].\n", pointmark(encsub->forg),
-           pointmark(encsub->fdest), pointmark(encsub->fapex), quenumber);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dequeueencsub()    Remove an enc-subface from the front of the queue.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::badface* tetgenmesh::dequeueencsub(int* pquenumber)
-{
-  badface *result;
-  int quenumber;
-
-  // Look for a nonempty queue.
-  for (quenumber = 2; quenumber >= 0; quenumber--) {
-    result = subquefront[quenumber];
-    if (result != (badface *) NULL) {
-      // Remove the badface from the queue.
-      subquefront[quenumber] = result->nextitem;
-      // Maintain a pointer to the NULL pointer at the end of the queue.
-      if (subquefront[quenumber] == (badface *) NULL) {
-        subquetail[quenumber] = &subquefront[quenumber];
-      }
-      *pquenumber = quenumber;
-      return result;
-    }
-  }
-  return (badface *) NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// enqueuebadtet()    Add a tetrahedron into the queue.                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::enqueuebadtet(triface* testtet, REAL ratio2, REAL* cent)
-{
-  badface *newbadtet;
-  int queuenumber;
-  int i;
-
-  // Allocate space for the bad tetrahedron.
-  newbadtet = (badface *) badtetrahedrons->alloc();
-  newbadtet->tt = *testtet;
-  newbadtet->key = ratio2;
-  if (cent != NULL) {
-    for (i = 0; i < 3; i++) newbadtet->cent[i] = cent[i];
-  } else {
-    for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
-  }
-  newbadtet->forg = org(*testtet);
-  newbadtet->fdest = dest(*testtet);
-  newbadtet->fapex = apex(*testtet);
-  newbadtet->foppo = oppo(*testtet);
-  newbadtet->nextitem = (badface *) NULL;
-  // Determine the appropriate queue to put the bad tetrahedron into.
-  if (ratio2 > b->goodratio) {
-    // queuenumber = (int) ((ratio2 - b->goodratio) / 0.5);
-    queuenumber = (int) (64.0 - 64.0 / ratio2);
-    // 'queuenumber' may overflow (negative) caused by a very large ratio.
-    if ((queuenumber > 63) || (queuenumber < 0)) {
-      queuenumber = 63;
-    }
-  } else {
-    // It's not a bad ratio; put the tet in the lowest-priority queue.
-    queuenumber = 0;
-  }
-
-  // Are we inserting into an empty queue?
-  if (tetquefront[queuenumber] == (badface *) NULL) {
-    // Yes. Will this become the highest-priority queue?
-    if (queuenumber > firstnonemptyq) {
-      // Yes, this is the highest-priority queue.
-      nextnonemptyq[queuenumber] = firstnonemptyq;
-      firstnonemptyq = queuenumber; 
-    } else {
-      // No. Find the queue with next higher priority.
-      i = queuenumber + 1;
-      while (tetquefront[i] == (badface *) NULL) {
-        i++;
-      }
-      // Mark the newly nonempty queue as following a higher-priority queue.
-      nextnonemptyq[queuenumber] = nextnonemptyq[i];
-      nextnonemptyq[i] = queuenumber;
-    }
-    // Put the bad tetrahedron at the beginning of the (empty) queue.
-    tetquefront[queuenumber] = newbadtet;
-  } else {
-    // Add the bad tetrahedron to the end of an already nonempty queue.
-    tetquetail[queuenumber]->nextitem = newbadtet;
-  }
-  // Maintain a pointer to the last tetrahedron of the queue.
-  tetquetail[queuenumber] = newbadtet;
-
-  if (b->verbose > 2) {
-    printf("    Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
-           pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
-           pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
-           sqrt(ratio2), queuenumber);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// dequeuebadtet()    Remove a tetrahedron from the front of the queue.      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::badface* tetgenmesh::topbadtetra()
-{
-  // Keep a record of which queue was accessed in case dequeuebadtetra()
-  //   is called later.
-  recentq = firstnonemptyq;
-  // If no queues are nonempty, return NULL.
-  if (firstnonemptyq < 0) {
-    return (badface *) NULL;
-  } else {
-    // Return the first tetrahedron of the highest-priority queue.
-    return tetquefront[firstnonemptyq];
-  }
-}
-
-void tetgenmesh::dequeuebadtet()
-{
-  badface *deadbadtet;
-  int i;
-
-  // If queues were empty last time topbadtetra() was called, do nothing.
-  if (recentq >= 0) {
-    // Find the tetrahedron last returned by topbadtetra().
-    deadbadtet = tetquefront[recentq];
-    // Remove the tetrahedron from the queue.
-    tetquefront[recentq] = deadbadtet->nextitem;
-    // If this queue is now empty, update the list of nonempty queues.
-    if (deadbadtet == tetquetail[recentq]) {
-      // Was this the highest-priority queue?
-      if (firstnonemptyq == recentq) {
-        // Yes; find the queue with next lower priority.
-        firstnonemptyq = nextnonemptyq[firstnonemptyq];
-      } else {
-        // No; find the queue with next higher priority.
-        i = recentq + 1;
-        while (tetquefront[i] == (badface *) NULL) {
-          i++;
-        }
-        nextnonemptyq[i] = nextnonemptyq[recentq];
-      }
-    }
-    // Return the bad tetrahedron to the pool.
-    badfacedealloc(badtetrahedrons, deadbadtet);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checkseg4encroach()    Check a subsegment to see if it is encroached.     //
-//                                                                           //
-// A segment s is encroached if there is a vertex lies inside or on its dia- //
-// metral circumsphere, i.e., s faces an angle theta >= 90 degrees.          //
-//                                                                           //
-// If 'testpt' (p) != NULL, only test if 'testseg' (s) is encroached by it,  //
-// else, check all apexes of faces around s. Return TRUE if s is encroached. //
-// If and 'enqflag' is TRUE, add it into 'badsubsegs' if s is encroached.    //
-//                                                                           //
-// If 'prefpt' != NULL, it returns the reference point (defined in my paper) //
-// if it exists.  This point is will be used to split s.                     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::checkseg4encroach(face* testseg, point testpt, point* prefpt,
-  bool enqflag)
-{
-  badface *encsubseg;
-  triface starttet, spintet;
-  point eorg, edest, eapex, encpt;
-  REAL cent[3], radius, dist, diff;
-  REAL maxradius;
-  bool enq;
-  int hitbdry;
-
-  enq = false;
-  eorg = sorg(*testseg);
-  edest = sdest(*testseg);
-  cent[0] = 0.5 * (eorg[0] + edest[0]);
-  cent[1] = 0.5 * (eorg[1] + edest[1]);
-  cent[2] = 0.5 * (eorg[2] + edest[2]);
-  radius = distance(cent, eorg);
-
-  if (varconstraint && (areabound(*testseg) > 0.0)) {
-    enq = (2.0 * radius) > areabound(*testseg);
-  }
-
-  if (!enq) {
-    maxradius = 0.0;
-    if (testpt == (point) NULL) {
-      // Check if it is encroached by traversing all faces containing it.
-      sstpivot(testseg, &starttet);
-      eapex = apex(starttet);
-      spintet = starttet;
-      hitbdry = 0;
-      do {
-        dist = distance(cent, apex(spintet));
-        diff = dist - radius;
-        if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
-        if (diff <= 0.0) {
-          // s is encroached.
-          enq = true;
-          if (prefpt != (point *) NULL) {
-            // Find the reference point.
-            encpt = apex(spintet);
-            circumsphere(eorg, edest, encpt, NULL, NULL, &dist);
-            if (dist > maxradius) {
-              // Rememebr this point.
-              *prefpt = encpt;
-              maxradius = dist;
-            }
-          } else {
-            break;
-          }
-        }
-        if (!fnextself(spintet)) {
-          hitbdry++;
-          if (hitbdry < 2) {
-            esym(starttet, spintet);
-            if (!fnextself(spintet)) {
-              hitbdry++;
-            } 
-          }
-        }
-      } while (apex(spintet) != eapex && (hitbdry < 2));
-    } else {
-      // Only check if 'testseg' is encroached by 'testpt'.
-      dist = distance(cent, testpt);
-      diff = dist - radius;
-      if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
-      enq = (diff <= 0.0);
-    }
-  }
-
-  if (enq && enqflag) {
-    if (b->verbose > 2) {
-      printf("    Queuing encroaching subsegment (%d, %d).\n",
-             pointmark(eorg), pointmark(edest));
-    }
-    encsubseg = (badface *) badsubsegs->alloc();
-    encsubseg->ss = *testseg;
-    encsubseg->forg = eorg;
-    encsubseg->fdest = edest;
-    encsubseg->foppo = (point) NULL; // Not used.
-    // Set the pointer of 'encsubseg' into 'testseg'.  It has two purposes:
-    //   (1) We can regonize it is encroached; (2) It is uniquely queued.
-    setshell2badface(encsubseg->ss, encsubseg);
-  }
-  
-  return enq;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checksub4encroach()    Check a subface to see if it is encroached.        //
-//                                                                           //
-// A subface f is encroached if there is a vertex inside or on its diametral //
-// circumsphere.                                                             //
-//                                                                           //
-// If 'testpt (p) != NULL', test if 'testsub' (f) is encroached by it, else, //
-// test if f is encroached by one of the two opposites of the adjacent tets. //
-// Return TRUE if f is encroached and queue it if 'enqflag' is set.          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::checksub4encroach(face* testsub, point testpt, bool enqflag)
-{
-  triface abuttet;
-  point pa, pb, pc, encpt;
-  REAL A[4][4], rhs[4], D;
-  REAL cent[3], area;
-  REAL radius, dist, diff;
-  bool enq;
-  int indx[4];
-  int quenumber;
-  
-  enq = false;
-  radius = 0.0;
-  encpt = (point) NULL;
-
-  pa = sorg(*testsub);
-  pb = sdest(*testsub);
-  pc = sapex(*testsub);
-  
-  // Compute the coefficient matrix A (3x3).
-  A[0][0] = pb[0] - pa[0];
-  A[0][1] = pb[1] - pa[1];
-  A[0][2] = pb[2] - pa[2]; // vector V1 (pa->pb)
-  A[1][0] = pc[0] - pa[0];
-  A[1][1] = pc[1] - pa[1];
-  A[1][2] = pc[2] - pa[2]; // vector V2 (pa->pc)
-  cross(A[0], A[1], A[2]); // vector V3 (V1 X V2)
-
-  if (varconstraint && (areabound(*testsub) > 0.0)) {
-    // Check if the subface has too big area.
-    area = 0.5 * sqrt(dot(A[2], A[2]));
-    enq = area > areabound(*testsub);
-    if (enq) {
-      quenumber = 2; // A queue of subfaces having too big area.
-    }
-  }
-
-  // Compute the right hand side vector b (3x1).
-  rhs[0] = 0.5 * dot(A[0], A[0]);
-  rhs[1] = 0.5 * dot(A[1], A[1]);
-  rhs[2] = 0.0;
-  // Solve the 3 by 3 equations use LU decomposition with partial pivoting
-  //   and backward and forward substitute..
-  if (lu_decmp(A, 3, indx, &D, 0)) {
-    lu_solve(A, 3, indx, rhs, 0);
-    cent[0] = pa[0] + rhs[0];
-    cent[1] = pa[1] + rhs[1];
-    cent[2] = pa[2] + rhs[2];
-    radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
-  }
-  
-  if (!enq) {
-    // Check if the subface is encroached.
-    if (testpt == (point) NULL) {
-      stpivot(*testsub, abuttet);
-      if (abuttet.tet != dummytet) {
-        dist = distance(cent, oppo(abuttet));
-        diff = dist - radius;
-        if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
-        enq = (diff <= 0.0);
-        if (enq) encpt = oppo(abuttet);
-      }
-      if (!enq) {
-        sesymself(*testsub);
-        stpivot(*testsub, abuttet);
-        if (abuttet.tet != dummytet) {
-          dist = distance(cent, oppo(abuttet));
-          diff = dist - radius;
-          if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
-          enq = (diff <= 0.0);
-          if (enq) encpt = oppo(abuttet);
-        }
-      }
-    } else {
-      dist = distance(cent, testpt);
-      diff = dist - radius;
-      if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
-      enq = (diff <= 0.0);
-    }
-    if (enq) {
-      quenumber = 0; // A queue of encroached subfaces.
-    }
-  }
-
-  if (enq && enqflag) {
-    enqueueencsub(testsub, encpt, quenumber, cent);    
-  }
-
-  return enq;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checktet4badqual()    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.                                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::checktet4badqual(triface* testtet, bool enqflag)
-{
-  point pa, pb, pc, pd, pe1, pe2;
-  REAL vda[3], vdb[3], vdc[3];
-  REAL vab[3], vbc[3], vca[3]; 
-  REAL N[4][3], A[4][4], rhs[4], D;
-  REAL elen[6], circumcent[3];
-  REAL bicent[3], offcent[3];
-  REAL volume, L, cosd;
-  REAL radius2, smlen2, ratio2;
-  REAL dist, sdist, split;
-  bool enq;
-  int indx[4];
-  int sidx, i, j; 
-
-  pa = (point) testtet->tet[4];
-  pb = (point) testtet->tet[5];
-  pc = (point) testtet->tet[6];
-  pd = (point) testtet->tet[7];
-
-  // Get the edge vectors vda: d->a, vdb: d->b, vdc: d->c.
-  // Set the matrix A = [vda, vdb, vdc]^T.
-  for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
-  for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
-  for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
-  // Get the rest edge vectors
-  for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
-  for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i];
-  for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i];
-
-  // Lu-decompose the matrix A.
-  lu_decmp(A, 3, indx, &D, 0);
-  // Get the volume of abcd.
-  volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
-  if (volume < 0.0) volume = -volume;
-  // Check the radiu-edge ratio of the tet.
-  rhs[0] = 0.5 * dot(vda, vda);
-  rhs[1] = 0.5 * dot(vdb, vdb);
-  rhs[2] = 0.5 * dot(vdc, vdc);
-  lu_solve(A, 3, indx, rhs, 0);
-  // Get the circumcenter.
-  for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
-  // Get the square of the circumradius.
-  radius2 = dot(rhs, rhs);
-  // Find the square of the shortest edge length.
-  elen[0] = dot(vda, vda);
-  elen[1] = dot(vdb, vdb);
-  elen[2] = dot(vdc, vdc);
-  elen[3] = dot(vab, vab);
-  elen[4] = dot(vbc, vbc);
-  elen[5] = dot(vca, vca);
-  smlen2 = elen[0]; sidx = 0;
-  for (i = 1; i < 6; i++) {
-    if (smlen2 > elen[i]) { smlen2 = elen[i]; sidx = i; }
-  }
-  // Calculate the square of radius-edge ratio.
-  ratio2 = radius2 / smlen2;
-  // Check whether the ratio is smaller than permitted.
-  enq = ratio2 > b->goodratio;
-  if (!enq) {
-    // abcd has good ratio.
-    // ratio2 = 0.0;
-    // if (b->offcenter) {
-      // Test if it is a sliver.
-      // Compute the 4 face normals (N[0], ..., N[3]).
-      for (j = 0; j < 3; j++) {
-        for (i = 0; i < 3; i++) rhs[i] = 0.0;
-        rhs[j] = 1.0;  // Positive means the inside direction
-        lu_solve(A, 3, indx, rhs, 0);
-        for (i = 0; i < 3; i++) N[j][i] = rhs[i];
-      }
-      // Get the fourth normal by summing up the first three.
-      for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
-      // Normalized the normals.
-      for (i = 0; i < 4; i++) {
-        L = sqrt(dot(N[i], N[i]));
-        if (L > 0.0) {
-          for (j = 0; j < 3; j++) N[i][j] /= L;
-        }
-      }
-      // N[0] is the normal of face bcd. Test the dihedral angles at edge
-      //   cd, bd, and bc to see if they are too small or too big.
-      for (i = 1; i < 4 && !enq; i++) {
-        cosd = -dot(N[0], N[i]); // Edge cd, bd, bc.
-        enq = cosd > cosmindihed;
-      }
-      if (!enq) {
-        for (i = 2; i < 4 && !enq; i++) {
-          cosd = -dot(N[1], N[i]); // Edge ad, ac
-          enq = cosd > cosmindihed;
-        }
-        if (!enq) {
-          cosd = -dot(N[2], N[3]); // Edge ab
-          enq = cosd > cosmindihed;
-        }
-      }
-    // }
-  } else if (b->offcenter) {
-    // abcd has bad-quality. Use off-center instead of circumcenter.
-    switch (sidx) {
-    case 0: // edge da.
-      pe1 = pd; pe2 = pa; break;
-    case 1: // edge db.
-      pe1 = pd; pe2 = pb; break;
-    case 2: // edge dc.
-      pe1 = pd; pe2 = pc; break;
-    case 3: // edge ab.
-      pe1 = pa; pe2 = pb; break;
-    case 4: // edge bc.
-      pe1 = pb; pe2 = pc; break;
-    case 5: // edge ca.
-      pe1 = pc; pe2 = pa; break;
-    default: 
-      pe1 = pe2 = (point) NULL; // Avoid a compile warning.
-    }
-    // The shortest edge is e1->e2.
-    for (i = 0; i < 3; i++) bicent[i] = 0.5 * (pe1[i] + pe2[i]);
-    dist = distance(bicent, circumcent);
-    // sdist = sqrt(smlen2) * sin(PI / 3.0); // A icoso-triangle.
-    // The following formulae is from 
-    sdist = b->alpha3 * (b->minratio+sqrt(b->goodratio-0.25))* sqrt(smlen2);
-    split = sdist / dist;
-    if (split > 1.0) split = 1.0;
-    // Get the off-center.
-    for (i = 0; i < 3; i++) {
-      offcent[i] = bicent[i] + split * (circumcent[i] - bicent[i]);
-    }
-  }
-
-  if (!enq && (b->varvolume || b->fixedvolume)) {
-    // Check if the tet has too big volume.
-    enq = b->fixedvolume && (volume > b->maxvolume);
-    if (!enq && b->varvolume) {
-      enq = (volume > volumebound(testtet->tet)) &&
-            (volumebound(testtet->tet) > 0.0);
-    }
-  }
-
-  if (!enq) {
-    // Check if the user-defined sizing function is satisfied. 
-    if (b->metric) {
-      // assert(b->alpha1 > 0.0);
-      sdist = sqrt(radius2) / b->alpha1;
-      for (i = 0; i < 4; i++) {
-        pa = (point) testtet->tet[4 + i];
-        // Get the indicated size of p.
-        dist = pa[pointmtrindex]; // dist = b->alpha1 * pa[pointmtrindex];
-        enq = ((dist < sdist) && (dist > 0.0));
-        if (enq) break; // It is bad wrt. a node constraint.
-        // *** Experiment ! Stop test if c is inside H(a).
-        // if ((dist > 0.0) && (dist > sdist)) break;
-      }
-      // *** Experiment !
-      // enq = (i == 4); // Does c lies outside all sparse-ball?
-    } // if (b->metric)
-  }
-
-  if (enq && enqflag) {
-    if (b->offcenter && (ratio2 > b->goodratio)) {
-      for (i = 0; i < 3; i++) circumcent[i] = offcent[i];
-    }
-    enqueuebadtet(testtet, ratio2, circumcent);
-  }
-
-  return enq;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// acceptsegpt()    Check if a segment point can be inserted or not.         //
-//                                                                           //
-// Segment(ab) is indicated to be split by a point p (\in ab). This routine  //
-// decides whether p can be inserted or not.                                 //
-//                                                                           //
-// p can not be inserted either the '-Y' option is used and ab is a hull     //
-// segment or '-YY' option is used.                                          //
-//                                                                           //
-// p can be inserted if it is in one of the following cases:                 //
-//   (1) if L = |a - b| is too long wrt the edge constraint; or              //
-//   (2) if |x - p| > \alpha_2 H(x) for x = a, b; or                         //
-//   (3) if 'refpt' != NULL.                                                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::acceptsegpt(point segpt, point refpt, face* splitseg)
-{
-  point p[2];
-  REAL L, lfs;
-  int i, j;
-
-  if (b->nobisect == 1) {
-    // '-Y'. It can not be split if it is on the hull.
-    triface spintet;
-    point pc;
-    sstpivot(splitseg, &spintet);
-    assert(spintet.tet != dummytet);
-    pc = apex(spintet);
-    do {
-      if (!fnextself(spintet)) {
-        // Meet a boundary face - s is on the hull.
-        return false;
-      }
-    } while (pc != apex(spintet));
-  } else if (b->nobisect > 1) {
-    // '-YY'. Do not split it.
-    return false;
-  }
-  
-  p[0] = sorg(*splitseg);
-  p[1] = sdest(*splitseg);
-  if (varconstraint && (areabound(*splitseg) > 0)) {
-    lfs = areabound(*splitseg);
-    L = distance(p[0], p[1]);
-    if (L > lfs) {
-      return true; // case (1)
-    }
-  }
-
-  j = 0; // Use j to count the number of inside balls.
-  for (i = 0; i < 2; i++) {
-    // Check if p is inside the protect ball of q.
-    if (p[i][pointmtrindex] > 0.0) {
-      lfs = b->alpha2 * p[i][pointmtrindex];
-      L = distance(p[i], segpt);
-      if (L < lfs) j++; // p is inside ball.
-    }
-  }
-  if (j == 0) return true; // case (3).
-
-  // If 'refpt' != NULL, force p to be inserted.
-  if (refpt != (point) NULL) {
-    cdtenforcesegpts++;
-    return true;
-  }
-
-  // Do not split it.
-  rejsegpts++;
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// acceptfacpt()    Check if a facet point can be inserted or not.           //
-//                                                                           //
-// 'subceillist' is CBC(p). 'verlist' (V) is empty on input, it returns the  //
-// set of vertices of CBC(p).                                                //
-//                                                                           //
-// p can not be inserted either the '-Y' option is used and the facet is on  //
-// the hull or '-YY' option is used.                                         //
-//                                                                           //
-// p can be inserted if |p - v| > \alpha_2 H(v), for all v \in V.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::acceptfacpt(point facpt, list* subceillist, list* verlist)
-{
-  face *testsh;
-  point p[2], ploop;
-  REAL L, lfs;
-  int idx, i, j;
-
-  if (b->nobisect == 1) {
-    // '-Y'. p can not be inserted if CBC(p) is on the hull.
-    triface testtet;
-    testsh = (face *)(* subceillist)[0];
-    stpivot(*testsh, testtet);
-    if (testtet.tet != dummytet) {
-      sesymself(*testsh);
-      stpivot(*testsh, testtet);
-    }
-    if (testtet.tet == dummytet) return false;
-  } else if (b->nobisect > 1) {
-    // '-YY'. Do not split s.
-    return false;
-  }
-
-  // Collect the vertices of CBC(p), save them in V.
-  for (i = 0; i < subceillist->len(); i++) {
-    testsh = (face *)(* subceillist)[i];
-    p[0] = sorg(*testsh);
-    p[1] = sdest(*testsh);
-    for (j = 0; j < 2; j++) {
-      idx = pointmark(p[j]);
-      if (idx >= 0) {
-        setpointmark(p[j], -idx - 1);
-        verlist->append(&(p[j]));
-      }
-    }
-  }
-
-  j = 0; // Use j to count the number of inside balls.
-  for (i = 0; i < verlist->len(); i++) {
-    ploop = * (point *)(* verlist)[i];
-    // Uninfect q.
-    idx = pointmark(ploop);
-    setpointmark(ploop, -(idx + 1)); 
-    // Check if p is inside the protect ball of q.
-    if (ploop[pointmtrindex] > 0.0) {
-      lfs = b->alpha2 * ploop[pointmtrindex];
-      L = distance(ploop, facpt);
-      if (L < lfs) j++; // p is inside ball.
-    }
-  }
-  verlist->clear();
-
-  if (j == 0) return true; // case (3).
-
-  rejsubpts++;
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// acceptvolpt()    Check if a volume point can be inserted or not.          //
-//                                                                           //
-// 'ceillist' is B(p).  'verlist' (V) is empty on input, it returns the set  //
-// of vertices of B(p).                                                      //
-//                                                                           //
-// p can be split if |p - v| > \alpha_2 H(v), for all v \in V.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::acceptvolpt(point volpt, list* ceillist, list* verlist)
-{
-  triface* testtet;
-  point p[3], ploop;
-  REAL L, lfs;
-  int idx, i, j;
-
-  // Collect the vertices of CBC(p), save them in V.
-  for (i = 0; i < ceillist->len(); i++) {
-    testtet = (triface *)(* ceillist)[i];
-    p[0] = org(*testtet);
-    p[1] = dest(*testtet);
-    p[2] = apex(*testtet);
-    for (j = 0; j < 3; j++) {
-      idx = pointmark(p[j]);
-      if (idx >= 0) {
-        setpointmark(p[j], -idx - 1);
-        verlist->append(&(p[j]));
-      }
-    }
-  }
-
-  j = 0; // Use j to counte the number of inside balls.
-  for (i = 0; i < verlist->len(); i++) {
-    ploop = * (point *)(* verlist)[i];
-    // Uninfect q.
-    idx = pointmark(ploop);
-    setpointmark(ploop, -(idx + 1));
-    // Check if p is inside the protect ball of q.
-    if (ploop[pointmtrindex] > 0.0) {
-      lfs = b->alpha2 * ploop[pointmtrindex];
-      L = distance(ploop, volpt);
-      if (L < lfs) j++; // p is inside the protect ball.
-    }
-  }
-  verlist->clear();
-  
-  if (j == 0) return true; // case (2).
-
-  rejtetpts++;
-  return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// getsplitpoint()    Get the inserting point in a segment.                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::getsplitpoint(point e1, point e2, point refpt, point newpt)
-{
-  point ei, ej;
-  REAL split, L, d1, d2, ps, rs;
-  bool acutea, acuteb;
-  int i;
-
-  if (refpt != (point) NULL) {
-    // Use the CDT rules to split the segment.
-    acutea = (pointtype(e1) == ACUTEVERTEX);
-    acuteb = (pointtype(e2) == ACUTEVERTEX);
-    if (acutea ^ acuteb) {
-      // Only one endpoint is acute. Use rule-2 or rule-3.
-      ei = acutea ? e1 : e2;
-      ej = acutea ? e2 : e1;
-      L = distance(ei, ej);
-      // Apply rule-2.
-      d1 = distance(ei, refpt);
-      split = d1 / L;
-      for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
-      // Check if rule-3 is needed.
-      d2 = distance(refpt, newpt);
-      if (d2 > (L - d1)) {
-        // Apply rule-3.
-        if ((d1 - d2) > (0.5 * d1)) {
-          split = (d1 - d2) / L;
-        } else {
-          split = 0.5 * d1 / L;
-        }
-        for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
-        if (b->verbose > 1) {
-          printf("    Found by rule-3:");
-        }
-        r3count++;
-      } else {
-        if (b->verbose > 1) {
-          printf("    Found by rule-2:");
-        }
-        r2count++;
-      }
-      if (b->verbose > 1) {
-        printf(" center %d, split = %.12g.\n", pointmark(ei), split);
-      }
-      // Add a random perturbation on newpt.
-      d1 = distance(ei, newpt);
-      d2 = distance(newpt, refpt);
-      ps = randgenerator(d2 * b->epsilon2 * 1e+2);
-      rs = ps / d1;
-      // Perturb newpt away from ei.
-      for (i = 0; i < 3; i++) newpt[i] = ei[i] + (1.0+rs) * (newpt[i] - ei[i]);
-    } else {
-      // Both endpoints are acute or not. Split it at the middle.
-      for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
-      // Add a random perturbation on newpt.
-      d1 = 0.5 * distance(e1, e2);
-      ps = randgenerator(d1 * b->epsilon2 * 1e+2);
-      rs = ps / d1;
-      for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
-    }
-  } else {
-    // Split the segment at its midpoint.
-    for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
-    // Add a random perturbation on newpt.
-    d1 = 0.5 * distance(e1, e2);
-    ps = randgenerator(d1 * b->epsilon2 * 1e+2);
-    rs = ps / d1;
-    for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// shepardinterpolation()    Interpolate the local size of a newpoint.       //
-//                                                                           //
-// The classical Shepard interoplation (inversed weighted distance) is used. //
-// (With the choice p = 2).                                                  //
-//                                                                           //
-// 'verlist' contains a list vertices neighboring to 'newpt'.                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::shepardinterpolate(point newpt, list *verlist)
-{
-  point neipt;
-  REAL *weights, sumweight;
-  REAL vec[3];
-  int i, j;
-
-  weights = new REAL[verlist->len()];
-  sumweight = 0.0;
-
-  // Calculate the weight of each point.
-  for (i = 0; i < verlist->len(); i++) {
-    neipt = * (point *)(* verlist)[i];
-    for (j = 0; j < 3; j++) vec[j] = neipt[j] - newpt[j];
-    weights[i] = 1.0 / dot(vec, vec);
-    sumweight += weights[i];
-  }
-  // Interpolate.
-  newpt[pointmtrindex] = 0.0;
-  for (i = 0; i < verlist->len(); i++) {
-    neipt = * (point *)(* verlist)[i];
-    newpt[pointmtrindex] += (weights[i] * neipt[pointmtrindex]) / sumweight;
-  }
-
-  delete [] weights;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// setnewpointsize()    Set the size for a new point.                        //
-//                                                                           //
-// The size of the new point p is interpolated either from a background mesh //
-// (b->bgmesh) or from the two input endpoints.                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::setnewpointsize(point newpt, point e1, point e2)
-{
-  if (b->metric) {
-    // Interpolate the point size in a background mesh.
-    triface bgmtet;
-    // Get a tet in background mesh for locating p.
-    decode(point2bgmtet(e1), bgmtet);
-    p1interpolatebgm(newpt, &bgmtet, NULL);
-  } else {
-    if (e2 != (point) NULL) {
-      // Interpolate the size between the two endpoints.
-      REAL split, l, d;
-      l = distance(e1, e2);
-      d = distance(e1, newpt);
-      split = d / l;
-#ifdef SELF_CHECK
-      // Check if e1 and e2 are endpoints of a sharp segment.
-      assert(e1[pointmtrindex] > 0.0);
-      assert(e2[pointmtrindex] > 0.0);
-#endif
-      newpt[pointmtrindex] = (1.0 - split) * e1[pointmtrindex] 
-                           + split * e2[pointmtrindex];
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// splitencseg()    Split an enc-seg and recover the Delaunayness by flips.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::splitencseg(point newpt, face* splitseg, list* tetlist,
-  list* sublist, list* verlist, queue* flipque, bool chkencsub, bool chkbadtet,
-  bool optflag)
-{
-  list *mytetlist;
-  queue *myflipque;
-  triface starttet;
-  face startsh, spinsh, checksh;
-  int i;
-
-  if (optflag) {
-    mytetlist = new list(sizeof(triface), NULL, 1024);
-    myflipque = new queue(sizeof(badface));
-    tetlist = mytetlist;
-    flipque = myflipque;
-  }
-
-  // Use the base orientation (important in this routine).
-  splitseg->shver = 0;
-  // Insert p, this should always success.
-  sstpivot(splitseg, &starttet);
-  splittetedge(newpt, &starttet, flipque);
-  // Remove locally non-Delaunay faces by flipping.
-  flip(flipque, NULL); // lawson(NULL, flipque);
-  
-  if (!optflag) { 
-    // Check the two new subsegs to see if they're encroached (not by p).
-    for (i = 0; i < 2; i++) {
-      if (!shell2badface(*splitseg)) {
-        checkseg4encroach(splitseg, NULL, NULL, true);
-      }
-      if (i == 1) break; // Two new segs have been checked.
-      senextself(*splitseg);
-      spivotself(*splitseg);
-#ifdef SELF_CHECK
-      assert(splitseg->sh != (shellface *) NULL);
-#endif
-      splitseg->shver = 0;
-    }
-    // Check the new subfaces to see if they're encroached (not by p).
-    if (chkencsub) {
-      spivot(*splitseg, startsh);
-      spinsh = startsh;
-      do {
-        sublist->append(&spinsh);
-        formstarpolygon(newpt, sublist, verlist);
-        for (i = 0; i < sublist->len(); i++) {
-          checksh = * (face *)(* sublist)[i];
-          if (!shell2badface(checksh)) {
-            checksub4encroach(&checksh, NULL, true);
-          }
-        }
-        sublist->clear();
-        if (verlist) verlist->clear();
-        spivotself(spinsh);
-      } while (spinsh.sh != startsh.sh);
-    }
-  } // if (!optflag)  
-
-  // Collect the new tets connecting at p.
-  sstpivot(splitseg, &starttet);
-  tetlist->append(&starttet);
-  formstarpolyhedron(newpt, tetlist, verlist, true);
-
-  if (!optflag) {
-    // Check if p encroaches adjacent segments.
-    tallencsegs(newpt, 1, &tetlist);
-    if (chkencsub) {
-      // Check if p encroaches adjacent subfaces.
-      tallencsubs(newpt, 1, &tetlist);
-    }
-    if (chkbadtet) {
-      // Check if there are new bad quality tets at p.
-      for (i = 0; i < tetlist->len(); i++) {
-        starttet = * (triface *)(* tetlist)[i];
-        checktet4badqual(&starttet, true);
-      }
-    }
-    tetlist->clear();
-  } else {
-    // Check if new tets are non-optimal.
-    for (i = 0; i < tetlist->len(); i++) {
-      starttet = * (triface *)(* tetlist)[i];
-      checktet4opt(&starttet, true);
-    }
-    delete mytetlist;
-    delete myflipque;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tallencsegs()    Check for encroached segments and save them in list.     //
-//                                                                           //
-// If 'testpt' (p) != NULL, only check if segments are encroached by p, else,//
-// check all the nearby mesh vertices.                                       //
-//                                                                           //
-// If 'ceillists' (B_i(p)) != NULL, there are 'n' B_i(p)s, only check the    //
-// segments which are on B_i(p)s, else, check the entire list of segments    //
-// (in the pool 'this->subsegs').                                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::tallencsegs(point testpt, int n, list **ceillists)
-{
-  list *ceillist;
-  triface ceiltet;
-  face checkseg;
-  long oldencnum;
-  int i, j, k;
-  
-  // Remember the current number of encroached segments.
-  oldencnum = badsubsegs->items;
-
-  if (ceillists != (list **) NULL) {
-    for (k = 0; k < n; k++) {
-      ceillist = ceillists[k];
-      // Check the segments on B_i(p).
-      for (i = 0; i < ceillist->len(); i++) {
-        ceiltet = * (triface *)(* ceillist)[i];
-        ceiltet.ver = 0;
-        for (j = 0; j < 3; j++) {
-          tsspivot(&ceiltet, &checkseg);
-          if (checkseg.sh != dummysh) {
-            // Found a segment. Test it if it isn't in enc-list.
-            if (!shell2badface(checkseg)) {
-              checkseg4encroach(&checkseg, testpt, NULL, true);
-            }
-          }
-          enextself(ceiltet);
-        }
-      }
-    }
-  } else {
-    // Check the entire list of segments.
-    subsegs->traversalinit();
-    checkseg.sh = shellfacetraverse(subsegs);
-    while (checkseg.sh != (shellface *) NULL) {
-      // Test it if it isn't in enc-list.
-      if (!shell2badface(checkseg)) {
-        checkseg4encroach(&checkseg, testpt, NULL, true);
-      }
-      checkseg.sh = shellfacetraverse(subsegs);
-    }
-  }
-
-  return (badsubsegs->items > oldencnum);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tallencsubs()    Find all encroached subfaces and save them in list.      //
-//                                                                           //
-// If 'testpt' (p) != NULL, only check if subfaces are encroached by p, else,//
-// check the adjacent vertices of subfaces.                                  //
-//                                                                           //
-// If 'ceillists' (B_i(p)) != NULL, there are 'n' B_i(p)s, only check the    //
-// subfaces which are on B_i(p)s, else, check the entire list of subfaces    //
-// (in the pool 'this->subfaces').                                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::tallencsubs(point testpt, int n, list** ceillists)
-{
-  list *ceillist;
-  triface ceiltet;
-  face checksh;
-  long oldencnum;
-  int i, k;
-  
-  // Remember the current number of encroached segments.
-  oldencnum = badsubfaces->items;
-
-  if (ceillists != (list **) NULL) {
-    for (k = 0; k < n; k++) {
-      ceillist = ceillists[k];
-      // Check the subfaces on B_i(p).
-      for (i = 0; i < ceillist->len(); i++) {
-        ceiltet = * (triface *)(* ceillist)[i];
-        tspivot(ceiltet, checksh);
-        if (checksh.sh != dummysh) {
-          // Found a subface. Test it if it isn't in enc-list.
-          if (!shell2badface(checksh)) {
-            checksub4encroach(&checksh, testpt, true);
-          }
-        }
-      }
-    }
-  } else {
-    // Check the entire list of subfaces.
-    subfaces->traversalinit();
-    checksh.sh = shellfacetraverse(subfaces);
-    while (checksh.sh != (shellface *) NULL) {
-      // Test it if it isn't in enc-list.
-      if (!shell2badface(checksh)) {
-        checksub4encroach(&checksh, testpt, true);
-      }
-      checksh.sh = shellfacetraverse(subfaces);
-    }
-  }
-
-  return (badsubfaces->items > oldencnum);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tallbadtetrahedrons()    Queue all the bad-quality tetrahedra in the mesh.//
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::tallbadtetrahedrons()
-{
-  triface tetloop;
-
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    checktet4badqual(&tetloop, true);
-    tetloop.tet = tetrahedrontraverse();
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// repairencsegs()    Repair (split) all the encroached segments.            //
-//                                                                           //
-// Each encroached segment is repaired by splitting it - inserting a vertex  //
-// at or near its midpoint.  Newly inserted vertices may encroach upon other //
-// subsegments, these are also repaired.                                     //
-//                                                                           //
-// 'chkencsub' and 'chkbadtet' are two flags that specify whether one should //
-// take note of new encroaced subfaces and bad quality tets that result from //
-// inserting vertices to repair encroached subsegments.                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::repairencsegs(bool chkencsub, bool chkbadtet)
-{
-  list **tetlists, **ceillists;
-  list **sublists, **subceillists;
-  list *tetlist, *sublist;
-  queue *flipque;
-  badface *encloop;
-  face splitseg, symsplitseg;
-  point newpt, sympt, refpt;
-  point e1, e2;
-  enum locateresult symloc;
-  int nmax, n, i, j;
-
-  n = 0;
-  nmax = 128;
-  if (!b->fliprepair) {
-    tetlists = new list*[nmax];
-    ceillists = new list*[nmax];
-    sublists = new list*[nmax];
-    subceillists = new list*[nmax];
-  } else {
-    tetlist = new list(sizeof(triface), NULL, 1024);
-    sublist = new list(sizeof(face), NULL, 256);
-    flipque = new queue(sizeof(badface));
-  }
-
-  // Loop until the pool 'badsubsegs' is empty. Note that steinerleft == -1
-  //   if an unlimited number of Steiner points is allowed.
-  while ((badsubsegs->items > 0) && (steinerleft != 0)) {
-    badsubsegs->traversalinit();
-    encloop = badfacetraverse(badsubsegs);
-    while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
-      // Get an encroached subsegment s.
-      splitseg = encloop->ss;
-      // Clear the in-queue flag in s.
-      setshell2badface(splitseg, NULL);
-      if ((sorg(splitseg) == encloop->forg) && 
-          (sdest(splitseg) == encloop->fdest)) {
-        if (b->verbose > 1) {
-          printf("  Get an enc-seg (%d, %d)\n", pointmark(encloop->forg),
-                 pointmark(encloop->fdest));
-        }
-        refpt = (point) NULL;
-        if (b->conformdel) {
-          // Look for a reference point.
-          checkseg4encroach(&splitseg, NULL, &refpt, false);
-        }
-        // Create the new point p (at the middle of s).
-        makepoint(&newpt);
-        getsplitpoint(encloop->forg, encloop->fdest, refpt, newpt);
-        setpointtype(newpt, FREESEGVERTEX);
-        setpoint2sh(newpt, sencode(splitseg));
-        // Decide whether p can be inserted or not.
-        if (acceptsegpt(newpt, refpt, &splitseg)) {
-          // Is there periodic boundary condition?
-          if (checkpbcs) {
-            // Insert points on other segments of incident pbcgroups.
-            i = shellmark(splitseg) - 1;
-            for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
-              makepoint(&sympt);
-              symloc = getsegpbcsympoint(newpt, &splitseg, sympt, &symsplitseg,
-                                         segpglist[j]);
-              if (symloc == ONEDGE) {
-                if (symsplitseg.sh != splitseg.sh) {
-                  // Insert sympt.
-                  setpointtype(sympt, FREESEGVERTEX);
-                  setpoint2sh(sympt, sencode(symsplitseg));
-                  // Save the endpoints of the seg for size interpolation.
-                  e1 = sorg(symsplitseg);
-                  if (shelltype(symsplitseg) == SHARP) {
-                    e2 = sdest(symsplitseg);
-                  } else {
-                    e2 = (point) NULL; // No need to do size interpolation.
-                  }
-                  if (!b->fliprepair) {
-                    // Form BC(symp), B(symp), CBC(symp)s, C(symp)s.
-                    formbowatcavity(sympt, &symsplitseg, NULL, &n, &nmax,
-                      sublists, subceillists, tetlists, ceillists);
-                    // Validate BC(symp), B(symp), CBC(symp)s, C(symp)s.
-                    if (trimbowatcavity(sympt, &symsplitseg, n, sublists,
-                          subceillists, tetlists, ceillists, -1.0)) {
-                      bowatinsertsite(sympt, &symsplitseg, n, sublists,
-                        subceillists, tetlists, ceillists, NULL, flipque,
-                        true, chkencsub, chkbadtet);
-                      setnewpointsize(sympt, e1, e2);
-                      if (steinerleft > 0) steinerleft--;
-                    } else {
-                      // p did not insert for invalid BC(symp).
-                      pointdealloc(sympt);
-                    }
-                    // Free the memory allocated in formbowatcavity().
-                    releasebowatcavity(&symsplitseg, n, sublists, subceillists,
-                                       tetlists, ceillists);
-                  } else {
-                    splitencseg(sympt, &symsplitseg, tetlist, sublist, NULL,
-                                flipque, chkencsub, chkbadtet, false);
-                    setnewpointsize(sympt, e1, e2);
-                    if (steinerleft > 0) steinerleft--;
-                  }
-                } else {
-                  // The sympt are on the same segment. It is possible when
-                  //   splitseg is the symmetric rotating axes.
-                  pointdealloc(sympt);
-                }
-              } else if (symloc == ONVERTEX) {
-                // The sympt already exists. It is possible when two pbc
-                //   groups are exactly the same. Omit this point.
-                pointdealloc(sympt);
-              } else {
-                // Do not isnert symp for unknown cases: ONFACE, OUTSIDE.
-                // assert(0);
-                pointdealloc(sympt);
-              }
-            } // for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++)
-          } // if (checkpbcs)
-          // Save the endpoints of the seg for size interpolation.
-          e1 = sorg(splitseg);
-          if (shelltype(splitseg) == SHARP) {
-            e2 = sdest(splitseg);
-          } else {
-            e2 = (point) NULL; // No need to do size interoplation.
-          }
-          if (!b->fliprepair) {
-            // Form BC(p), B(p), CBC(p)s, and C(p)s.
-            formbowatcavity(newpt, &splitseg, NULL, &n, &nmax, sublists,
-                            subceillists, tetlists, ceillists);
-            // Validate/update BC(p), B(p), CBC(p)s, and C(p)s.
-            if (trimbowatcavity(newpt, &splitseg, n, sublists, subceillists, 
-                                tetlists, ceillists, -1.0)) {
-              bowatinsertsite(newpt, &splitseg, n, sublists, subceillists,
-                              tetlists, ceillists, NULL, flipque, true,
-                              chkencsub, chkbadtet);
-              setnewpointsize(newpt, e1, e2);
-              if (steinerleft > 0) steinerleft--;
-            } else {
-              // p did not insert for invalid B(p).
-              pointdealloc(newpt);
-            }
-            // Free the memory allocated in formbowatcavity().
-            releasebowatcavity(&splitseg, n, sublists, subceillists, tetlists,
-                               ceillists);
-          } else {
-            splitencseg(newpt, &splitseg, tetlist, sublist, NULL, flipque,
-                        chkencsub, chkbadtet, false);
-            setnewpointsize(newpt, e1, e2);
-            if (steinerleft > 0) steinerleft--;
-          }
-        } else {
-          // p did not accept for insertion.
-          pointdealloc(newpt);
-        } // if (checkseg4splitting(newpt, &splitseg))
-      } // if ((encloop->forg == pa) && (encloop->fdest == pb))
-      badfacedealloc(badsubsegs, encloop); // Remove this entry from list.
-      encloop = badfacetraverse(badsubsegs); // Get the next enc-segment.
-    } // while ((encloop != (badface *) NULL) && (steinerleft != 0))
-  } // while ((badsubsegs->items > 0) && (steinerleft != 0))
-
-  if (!b->fliprepair) {
-    delete [] tetlists;
-    delete [] ceillists;
-    delete [] sublists;
-    delete [] subceillists;
-  } else {
-    delete tetlist;
-    delete sublist;
-    delete flipque;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// repairencsubs()    Repair (split) all the encroached subfaces.            //
-//                                                                           //
-// Each encroached subface is repaired by splitting it - inserting a vertex  //
-// at or near its circumcenter.  Newly inserted vertices may encroach upon   //
-// other subfaces, these are also repaired.                                  //
-//                                                                           //
-// 'chkbadtet' is a flag that specifies whether one should take note of new  //
-// bad quality tets that result from inserted vertices.                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::repairencsubs(bool chkbadtet)
-{
-  list *tetlists[2], *ceillists[2];
-  list *sublist, *subceillist;
-  list *verlist;
-  badface *encloop;
-  face splitsub, symsplitsub;
-  point newpt, sympt, e1;
-  enum locateresult loc, symloc;
-  bool reject;
-  long oldptnum;
-  int quenumber, n, i;
-
-  n = 0;
-  sublist = (list *) NULL;
-  subceillist = (list *) NULL;
-  verlist = new list(sizeof(point *), NULL, 256);
-
-  // Loop until the pool 'badsubfaces' is empty. Note that steinerleft == -1
-  //   if an unlimited number of Steiner points is allowed.
-  while ((badsubfaces->items > 0) && (steinerleft != 0)) {
-    // Get an encroached subface f.
-    encloop = dequeueencsub(&quenumber);
-    splitsub = encloop->ss;
-    // Clear the in-queue flag of f.
-    setshell2badface(splitsub, NULL);
-    // f may not be the same one when it was determined to be encroached.
-    if (!isdead(&splitsub)
-        && (sorg(splitsub) == encloop->forg)
-        && (sdest(splitsub) == encloop->fdest)
-        && (sapex(splitsub) == encloop->fapex)) {
-      if (b->verbose > 1) {
-        printf("    Dequeuing ensub (%d, %d, %d) [%d].\n",
-               pointmark(encloop->forg), pointmark(encloop->fdest),
-               pointmark(encloop->fapex), quenumber);
-      }
-      // Create a new point p at the circumcenter of f.
-      makepoint(&newpt);
-      for (i = 0; i < 3; i++) newpt[i] = encloop->cent[i];
-      setpointtype(newpt, FREESUBVERTEX);
-      setpoint2sh(newpt, sencode(splitsub));
-      // Set the abovepoint of f for point location.
-      abovepoint = facetabovepointarray[shellmark(splitsub)];
-      if (abovepoint == (point) NULL) {
-        getfacetabovepoint(&splitsub);
-      }
-      // Locate p, start from f, stop at segment (1), use a tolerance to
-      //   detect ONVERTEX or OUTSIDE case. Update f on return.
-      loc = locatesub(newpt, &splitsub, 1, b->epsilon * 1e+2);
-      if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
-        // Form BC(p), B(p), CBC(p) and C(p).
-        formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
-                        &subceillist, tetlists, ceillists);
-        // Check for encroached subsegments (on B(p)).
-        reject = tallencsegs(newpt, 2, ceillists);
-        // Execute point accept rule if p does not encroach upon any segment.
-        if (!reject) {
-          reject = !acceptfacpt(newpt, subceillist, verlist);
-        }
-        if (!reject) {
-          // Validate/update cavity.
-          reject = !trimbowatcavity(newpt, NULL, n, &sublist, &subceillist,
-                                    tetlists, ceillists, -1.0);
-        }
-        if (!reject) {
-          // CBC(p) should include s, so that s can be removed after CBC(p)
-          //   is remeshed. However, if there are locally non-Delaunay faces
-          //   and encroached subsegments, s may not be collected in CBC(p).
-          //   p should not be inserted in such case.
-          reject = !sinfected(encloop->ss);
-        }
-        if (!reject) {
-          if (checkpbcs) {
-            if (shellpbcgroup(splitsub) >= 0) {
-              // Check for splitting of the symmetric subface of f.
-              makepoint(&sympt);
-              symloc = getsubpbcsympoint(newpt,&splitsub,sympt,&symsplitsub);
-              if (symloc != ONVERTEX) {
-                // Release CBC(p) and BC(p) and free the memory..
-                releasebowatcavity(NULL, 2, &sublist, &subceillist, tetlists,
-                                   ceillists);
-                // Form CBC(symp), C(symp), BC(sympt) and B(sympt).
-                formbowatcavity(sympt, NULL, &symsplitsub, &n, NULL, &sublist,
-                                &subceillist, tetlists, ceillists);
-                reject = tallencsegs(sympt, 2, ceillists);
-                if (!reject) {
-                  reject = !acceptfacpt(sympt, subceillist, verlist);
-                }
-                if (!reject) {
-                  reject = !trimbowatcavity(sympt,NULL,n,&sublist,&subceillist,
-                                            tetlists, ceillists, -1.0);
-                }
-                if (!reject) {
-                  // Insert sympt.
-                  setpoint2pbcpt(newpt, sympt);
-                  setpoint2pbcpt(sympt, newpt);
-                  setpointtype(sympt, FREESUBVERTEX);
-                  setpoint2sh(sympt, sencode(symsplitsub));
-                  // Save a point for size interpolation.
-                  e1 = sorg(symsplitsub);
-                  bowatinsertsite(sympt, NULL, n, &sublist, &subceillist,
-                     tetlists,ceillists,NULL,NULL,false,true,chkbadtet);
-                  setnewpointsize(sympt, e1, NULL);
-                  if (steinerleft > 0) steinerleft--;
-                  // Release CBC(symp) and BC(symp) and free the memory..
-                  releasebowatcavity(NULL, n, &sublist, &subceillist, tetlists,
-                                     ceillists);
-                } else {
-                  // symp is rejected for one of the following reasons:
-                  //   (1) BC(symp) is not valid; or
-                  //   (2) symp encroaches upon some subsegments (queued); or
-                  //   (3) symp is rejected by point accepting rule.
-                  pointdealloc(sympt);
-                  // Cavity will be released by the following code.
-                }
-              } else {
-                // Do not insert sympt for invalid PBC data.
-                pointdealloc(sympt);
-                // p is rejected due to symp.
-                reject = true;
-              }
-            }
-          } // if (checkpbcs)
-        }
-        if (!reject) {
-          // Insert p.
-          if (checkpbcs) {
-            if (shellpbcgroup(splitsub) >= 0) {
-              // Form CBC(p), C(p), BC(p) and B(p).
-              formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
-                              &subceillist, tetlists, ceillists);
-              trimbowatcavity(newpt, NULL, n, &sublist, &subceillist, tetlists,
-                              ceillists, -1.0);
-            }
-          }
-          // Save a point for size interpolation.
-          e1 = sorg(splitsub);
-          bowatinsertsite(newpt, NULL, n, &sublist, &subceillist, tetlists,
-                          ceillists, NULL, NULL, true, true, chkbadtet);
-          setnewpointsize(newpt, e1, NULL);
-          if (steinerleft > 0) steinerleft--;
-        } else {
-          // p is rejected for the one of the following reasons:
-          //   (1) BC(p) is not valid.
-          //   (2) s does not in CBC(p).
-          //   (3) p encroaches upon some segments (queued); or
-          //   (4) p is rejected by point accepting rule, or
-          //   (5) due to the rejection of symp (the PBC).
-          pointdealloc(newpt);
-        } // if (!reject)
-        // Release the cavity and free the memory.
-        releasebowatcavity(NULL,n,&sublist,&subceillist,tetlists,ceillists);
-        if (reject) {
-          // Are there queued encroached subsegments.
-          if (badsubsegs->items > 0) {
-            // Repair enc-subsegments.
-            oldptnum = points->items;
-            repairencsegs(true, chkbadtet);
-            if (points->items > oldptnum) {
-              // Some enc-subsegments got split. Try to repair f later.
-              splitsub = encloop->ss;
-              if (!isdead(&splitsub)) {
-                if (!shell2badface(splitsub)) {
-                  checksub4encroach(&splitsub, NULL, true);
-                }
-              }
-            }
-          }
-        }
-      } else {
-        // Don't insert p for one of the following reasons:
-        //   (1) Locate on an existing vertex; or
-        //   (2) locate outside the domain.
-        // Case (1) should not be possible. If such vertex v exists, it is
-        //   the circumcenter of f, ie., f is non-Delaunay. Either f was got
-        //   split before by v, but survived after v was inserted, or the
-        //   same for a f' which is nearly co-circular with f.  Whatsoever,
-        //   there are encroached segs by v, but the routine tallencsegs()
-        //   did not find them out.
-        if (loc == ONVERTEX) {
-          printf("Internal error in repairencsubs():\n");
-          printf("  During repairing encroached subface (%d, %d, %d)\n",
-                 pointmark(encloop->forg), pointmark(encloop->fdest),
-                 pointmark(encloop->fapex));
-          printf("  New point %d is coincident with an existing vertex %d\n",
-                 pointmark(newpt), pointmark(sorg(splitsub)));
-          internalerror();
-        }
-        // Case (2) can happen when thers is a segment s which is close to f
-        //   and is non-conforming Delaunay. The circumcenter of f encroaches
-        //   upon s, but the circumcenter of s is rejected for insertion.
-        pointdealloc(newpt);
-      } // if ((loc != ONVERTEX) && (loc != OUTSIDE))
-    } else {
-      if (!isdead(&splitsub)) {
-        // The subface has been changed, re-check it.
-        checksub4encroach(&splitsub, NULL, true);
-      }
-    } // if (!isdead(&splitsub) && (sorg(splitsub) == encloop->forg) &&
-    // Remove this entry from list.
-    badfacedealloc(badsubfaces, encloop);
-  } // while ((badsubfaces->items > 0) && (steinerleft != 0))
-
-  delete verlist;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// repairbadtets()    Repair all bad-quality tetrahedra.                     //
-//                                                                           //
-// All bad-quality tets are stored in pool 'badtetrahedrons'.  Each bad tet  //
-// is repaired by inserting a point at or near its circumcenter. However, if //
-// this point encroaches any subsegment or subface, it is not inserted. Ins- //
-// tead the encroached segment and subface are split.  Newly inserted points //
-// may create other bad-quality tets, these are also repaired.               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::repairbadtets()
-{
-  list *tetlist, *ceillist;
-  list *verlist;
-  badface *badtet;
-  triface starttet;
-  point newpt, e1;
-  enum locateresult loc;
-  bool reject;
-  long oldptnum;
-  int i;
-
-  tetlist = new list(sizeof(triface), NULL, 1024);
-  ceillist = new list(sizeof(triface), NULL, 1024);
-  verlist = new list(sizeof(point *), NULL, 256);
-
-  // Loop until pool 'badtetrahedrons' is empty. Note that steinerleft == -1
-  //   if an unlimited number of Steiner points is allowed.
-  while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
-    // Get a bad-quality tet t.
-    badtet = topbadtetra();
-    // Make sure that the tet is still the same one when it was tested.
-    //   Subsequent transformations may have made it a different tet.
-    if ((badtet != (badface *) NULL) && !isdead(&badtet->tt)
-         && org(badtet->tt) == badtet->forg
-         && dest(badtet->tt) == badtet->fdest
-         && apex(badtet->tt) == badtet->fapex
-         && oppo(badtet->tt) == badtet->foppo) {
-      if (b->verbose > 1) {
-        printf("    Dequeuing btet (%d, %d, %d, %d).\n",
-               pointmark(badtet->forg), pointmark(badtet->fdest),
-               pointmark(badtet->fapex), pointmark(badtet->foppo));
-      }
-      // Create the new point p (at the circumcenter of t).
-      makepoint(&newpt);
-      for (i = 0; i < 3; i++) newpt[i] = badtet->cent[i];
-      setpointtype(newpt, FREEVOLVERTEX);
-      // Locate p.
-      starttet = badtet->tt;
-      loc = preciselocate(newpt, &starttet, tetrahedrons->items);
-      if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
-        // For BC(p) and B(p).
-        infect(starttet);
-        tetlist->append(&starttet);
-        formbowatcavityquad(newpt, tetlist, ceillist);
-        // Check for encroached subsegments.
-        reject = tallencsegs(newpt, 1, &ceillist);
-        if (!reject) {
-          // Check for encroached subfaces.
-          reject = tallencsubs(newpt, 1, &ceillist);
-        }
-        // Execute point accepting rule if p does not encroach upon any
-        //   subsegment and subface.
-        if (!reject) {
-          reject = !acceptvolpt(newpt, ceillist, verlist);
-        }
-        if (!reject) {
-          reject = !trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist,
-                                    &ceillist, -1.0);
-        }
-        if (!reject) {
-          // BC(p) should include t, so that t can be removed after BC(p) is
-          //   remeshed. However, if there are locally non-Delaunay faces
-          //   and encroached subsegments/subfaces, t may not be collected
-          //   in BC(p). p should not be inserted in such case.
-          reject = !infected(badtet->tt);
-          if (reject) outbowatcircumcount++;
-        }
-        if (!reject) {
-          // Save a point for size interpolation.
-          e1 = org(starttet);
-          // Insert p.
-          bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist,
-                          NULL, NULL, false, false, true);
-          setnewpointsize(newpt, e1, NULL);
-          if (steinerleft > 0) steinerleft--;
-        } else {
-          // p is rejected for one of the following reasons:
-          //   (1) BC(p) is not valid.
-          //   (2) t does not in BC(p).
-          //   (3) p encroaches upon some segments;
-          //   (4) p encroaches upon some subfaces;
-          //   (5) p is rejected by the point accepting rule.
-          pointdealloc(newpt);
-          // Uninfect tets of BC(p).
-          for (i = 0; i < tetlist->len(); i++) {
-            starttet = * (triface *)(* tetlist)[i];
-            uninfect(starttet);
-          }
-        }
-        tetlist->clear();
-        ceillist->clear();
-        // Split encroached subsegments/subfaces if there are.
-        if (reject) {
-          oldptnum = points->items;
-          if (badsubsegs->items > 0) {
-            repairencsegs(true, true);
-          }
-          if (badsubfaces->items > 0) {
-            repairencsubs(true);
-          }
-          if (points->items > oldptnum) {
-            // Some encroaching subsegments/subfaces got split. Re-queue the
-            //   tet if it is still alive.
-            starttet = badtet->tt;
-            if (!isdead(&starttet)) {
-              checktet4badqual(&starttet, true);
-            }
-          }
-        }
-      } else {
-        // Do not insert p. The reason may be one of:
-        //   (1) p is coincident (ONVERTEX) with an existing vertex; or
-        //   (2) p is outside (OUTSIDE) the mesh.
-        // Case (1) should not be possible. If such vertex v exists, it is
-        //   the circumcenter of t, ie., t is non-Delaunay. Either t was got
-        //   split before by v, but survived after v was inserted, or the
-        //   same for a t' which is nearly co-spherical with t.  Whatsoever,
-        //   there are encroached segments or subfaces by v but the routines
-        //   tallencsegs() or tallencsubs() did not find them out.
-        if (loc == ONVERTEX) {
-          printf("Internal error in repairbadtets():\n");
-          printf("  During repairing bad tet (%d, %d, %d, %d)\n",
-                 pointmark(badtet->forg), pointmark(badtet->fdest),
-                 pointmark(badtet->fapex), pointmark(badtet->foppo));
-          printf("  New point %d is coincident with an existing vertex %d\n",
-                 pointmark(newpt), pointmark(org(starttet)));
-          internalerror();
-        }
-        // Case (2) can happen when there is a segment s (or subface f) which
-        //   is close to f and is non-conforming Delaunay.  The circumcenter
-        //   of t encroaches upon s (or f), but the circumcenter of s (or f)
-        //   is rejected for insertion.
-        pointdealloc(newpt);
-      } // if ((loc != ONVERTEX) && (loc != OUTSIDE))
-    } // if (!isdead(&badtet->tt) && org(badtet->tt) == badtet->forg &&
-    // Remove the tet from the queue.
-    dequeuebadtet();
-  } // while ((badtetrahedrons->items > 0) && (steinerleft != 0))
-
-  delete tetlist;
-  delete ceillist;
-  delete verlist;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// enforcequality()    Refine the mesh.                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::enforcequality()
-{
-  long total, vertcount;
-  int i;
-  
-  if (!b->quiet) {
-    printf("Adding Steiner points to enforce quality.\n");
-  } 
-
-  total = vertcount = 0l;
-  if (b->conformdel) {
-    r2count = r3count = 0l;
-  }
-
-  // If both '-D' and '-r' options are used. 
-  if (b->conformdel && b->refine) {
-    markacutevertices(65.0);
-  }
-  // If '-m' is not used.
-  if (!b->metric) {
-    // Find and mark all sharp segments.
-    marksharpsegments(65.0);
-    // Decide the sizes for feature points.
-    decidefeaturepointsizes();
-  }
-
-  // Initialize the pool of encroached subsegments.
-  badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
-  // Looking for encroached subsegments.
-  tallencsegs(NULL, 0, NULL);
-  if (b->verbose && badsubsegs->items > 0) {
-    printf("  Splitting encroached subsegments.\n");
-  }
-  vertcount = points->items;
-  // Fix encroached segments without noting any enc subfaces.
-  repairencsegs(false, false);
-  if (b->verbose > 0) {
-    printf("  %ld split points.\n", points->items - vertcount);
-  }
-  total += points->items - vertcount;
-
-  // Initialize the pool of encroached subfaces.
-  badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
-  // Initialize the priority queues of badfaces.
-  for (i = 0; i < 3; i++) subquefront[i] = (badface *) NULL;
-  for (i = 0; i < 3; i++) subquetail[i] = &subquefront[i];
-  // Looking for encroached subfaces.
-  tallencsubs(NULL, 0, NULL);
-  if (b->verbose && badsubfaces->items > 0) {
-    printf("  Splitting encroached subfaces.\n");
-  }
-  vertcount = points->items;
-  // Fix encroached subfaces without noting bad tetrahedra.
-  repairencsubs(false);
-  if (b->verbose > 0) {
-    printf("  %ld split points.\n", points->items - vertcount);
-  }
-  total += points->items - vertcount;
-  // At this point, the mesh should be conforming Delaunay if no input
-  //   angle is smaller than 90 degree.
-
-  // Next, fix bad quality tetrahedra.
-  if ((b->minratio > 0.0) || b->varvolume || b->fixedvolume) {
-    // Initialize the pool of bad tets
-    badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
-    // Initialize the priority queues of bad tets.
-    for (i = 0; i < 64; i++) tetquefront[i] = (badface *) NULL;
-    firstnonemptyq = -1;
-    recentq = -1;
-    // Looking for bad quality tets.
-    cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
-    cosmindihed = cos(b->mindihedral * PI / 180.0);
-    tallbadtetrahedrons();
-    if (b->verbose && badtetrahedrons->items > 0) {
-      printf("  Splitting bad tetrahedra.\n");
-    }
-    vertcount = points->items;
-    repairbadtets();
-    if (b->verbose > 0) {
-      printf("  %ld refinement points.\n", points->items - vertcount);
-    }
-    total += points->items - vertcount;
-    delete badtetrahedrons;
-  }
-
-  if (b->verbose > 0) {
-    printf("  Totally added %ld points.\n", total);
-  }
-
-  delete badsubfaces;
-  delete badsubsegs;
-}
-
-//
-// End of Delaunay refinement routines
-//
-
-//
-// Begin of mesh optimization routines
-//
-
-void tetgenmesh::dumpbadtets()
-{
-  FILE *fout;
-  badface *remtet;
-
-  // Write out a file of remaining bad tets.
-  printf("  Writing bad tets to file bad-dump.lua.\n");
-  fout = fopen("bad-dump.lua", "w");
-  fprintf(fout, "-- %ld remaining bad tets (> %g degree).\n",
-          badtetrahedrons->items, b->maxdihedral);
-  badtetrahedrons->traversalinit();
-  remtet = badfacetraverse(badtetrahedrons);
-  while (remtet != (badface *) NULL) {
-    if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
-        dest(remtet->tt) == remtet->fdest && 
-        apex(remtet->tt) == remtet->fapex &&
-        oppo(remtet->tt) == remtet->foppo) {
-      fprintf(fout, "p:draw_tet(%d, %d, %d, %d) -- %g\n",
-              pointmark(remtet->forg), pointmark(remtet->fdest),
-              pointmark(remtet->fapex), pointmark(remtet->foppo),
-              acos(remtet->key) * 180.0 / PI);
-    }
-    remtet = badfacetraverse(badtetrahedrons);
-  }
-  fclose(fout);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checktet4ill()    Check a tet to see if it is illegal.                    //
-//                                                                           //
-// A tet is "illegal" if it spans on one input facet.  Save the tet in queue //
-// if it is illegal and the flag 'enqflag' is set.                           //
-//                                                                           //
-// Note: Such case can happen when the input facet has non-coplanar vertices //
-// and the Delaunay tetrahedralization of the vertices may creat such tets.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::checktet4ill(triface* testtet, bool enqflag)
-{
-  badface *newbadtet;
-  triface checktet;
-  face checksh1, checksh2;
-  face checkseg;
-  bool illflag;
-  int i;
-
-  illflag = false;
-  for (testtet->loc = 0; testtet->loc < 4; testtet->loc++) {
-    tspivot(*testtet, checksh1);
-    if (checksh1.sh != dummysh) {
-      testtet->ver = 0;
-      findedge(&checksh1, org(*testtet), dest(*testtet));
-      for (i = 0; i < 3; i++) {
-        fnext(*testtet, checktet);
-        tspivot(checktet, checksh2);
-        if (checksh2.sh != dummysh) {
-          // Two subfaces share this edge.
-          sspivot(checksh1, checkseg);
-          if (checkseg.sh == dummysh) {
-            // The four corners of the tet are on one facet. Illegal! Try to
-            //   flip the opposite edge of the current one.
-            enextfnextself(*testtet);
-            enextself(*testtet);
-            illflag = true; 
-            break;
-          }
-        }
-        enextself(*testtet);
-        senextself(checksh1);
-      }
-    }
-    if (illflag) break;
-  }
-
-  if (illflag && enqflag) {
-    // Allocate space for the bad tetrahedron.
-    newbadtet = (badface *) badtetrahedrons->alloc();
-    newbadtet->tt = *testtet;
-    newbadtet->key = -1.0; // = 180 degree.
-    for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
-    newbadtet->forg = org(*testtet);
-    newbadtet->fdest = dest(*testtet);
-    newbadtet->fapex = apex(*testtet);
-    newbadtet->foppo = oppo(*testtet);
-    newbadtet->nextitem = (badface *) NULL;
-    if (b->verbose > 2) {
-      printf("    Queueing illtet: (%d, %d, %d, %d).\n",
-             pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
-             pointmark(newbadtet->fapex), pointmark(newbadtet->foppo));
-    }
-  }
-
-  return illflag;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checktet4opt()    Check a tet to see if it needs to be optimized.         //
-//                                                                           //
-// A tet t needs to be optimized if it fails to certain quality measures.    //
-// The only quality measure currently used is the maximal dihedral angle at  //
-// edges. The desired maximal dihedral angle is b->maxdihed (set by the '-s' //
-// option.                                                                   //
-//                                                                           //
-// A tet may have one, two, or three big dihedral angles. Examples: Let the  //
-// tet t = abcd, and its four corners are nearly co-planar. Then t has one   //
-// big dihedral angle if d is very close to the edge ab; t has three big     //
-// dihedral angles if d's projection on the face abc is also inside abc, i.e.//
-// the shape of t likes a hat; finally, t has two big dihedral angles if d's //
-// projection onto abc is outside abc.                                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::checktet4opt(triface* testtet, bool enqflag)
-{
-  badface *newbadtet;
-  point pa, pb, pc, pd;
-  REAL N[4][3], len;
-  REAL cosd;
-  bool enq;
-  int i, j;
-
-  enq = false;
-  pa = (point) testtet->tet[4];
-  pb = (point) testtet->tet[5];
-  pc = (point) testtet->tet[6];
-  pd = (point) testtet->tet[7];
-  // Compute the 4 face normals: N[0] cbd, N[1] acd, N[2] bad, N[3] abc.
-  tetallnormal(pa, pb, pc, pd, N, NULL);
-  // Normalize the normals.
-  for (i = 0; i < 4; i++) {
-    len = sqrt(dot(N[i], N[i]));
-    if (len != 0.0) {
-      for (j = 0; j < 3; j++) N[i][j] /= len;
-    }
-  }
-  // Find all large dihedral angles.
-  for (i = 0; i < 6; i++) {
-    // Locate the edge i and calculate the dihedral angle at the edge.
-    testtet->loc = 0;
-    testtet->ver = 0;
-    switch (i) {
-    case 0: // edge ab
-      cosd = -dot(N[2], N[3]);
-      break;
-    case 1: // edge cd 
-      enextfnextself(*testtet);
-      enextself(*testtet);
-      cosd = -dot(N[0], N[1]);
-      break;
-    case 2: // edge bd
-      enextfnextself(*testtet);
-      enext2self(*testtet);
-      cosd = -dot(N[0], N[2]);
-      break;
-    case 3: // edge bc
-      enextself(*testtet);
-      cosd = -dot(N[0], N[3]);
-      break;
-    case 4: // edge ad
-      enext2fnextself(*testtet);
-      enextself(*testtet);
-      cosd = -dot(N[1], N[2]);
-      break;
-    case 5: // edge ac
-      enext2self(*testtet);
-      cosd = -dot(N[1], N[3]);
-      break;
-    }
-    if (cosd < cosmaxdihed) {
-      // A bigger dihedral angle.
-      if (enqflag) {
-        // Allocate space for the bad tetrahedron.
-        newbadtet = (badface *) badtetrahedrons->alloc();
-        newbadtet->tt = *testtet;
-        newbadtet->key = cosd;
-        for (j = 0; j < 3; j++) newbadtet->cent[j] = 0.0;
-        newbadtet->forg = org(*testtet);
-        newbadtet->fdest = dest(*testtet);
-        newbadtet->fapex = apex(*testtet);
-        newbadtet->foppo = oppo(*testtet);
-        newbadtet->nextitem = (badface *) NULL;
-        if (b->verbose > 2) {
-          printf("    Queueing tet: (%d, %d, %d, %d), dihed %g (degree).\n",
-                 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
-                 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
-                 acos(cosd) * 180.0 / PI);
-        }
-      }
-      enq = true;
-    }
-  }
-
-  return enq;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// removeedge()    Remove an edge                                            //
-//                                                                           //
-// 'remedge' is a tet (abcd) having the edge ab wanted to be removed.  Local //
-// reconnecting operations are used to remove edge ab.  The following opera- //
-// tion will be tryed.                                                       //
-//                                                                           //
-// If ab is on the hull, and abc and abd are both hull faces. Then ab can be //
-// removed by stripping abcd from the mesh. However, if ab is a segemnt, do  //
-// the operation only if 'b->optlevel' > 1 and 'b->nobisect == 0'.           //
-//                                                                           //
-// If ab is an internal edge, there are n tets contains it.  Then ab can be  //
-// removed if there exists another m tets which can replace the n tets with- //
-// out changing the boundary of the n tets.                                  //
-//                                                                           //
-// If 'optflag' is set.  The value 'remedge->key' means cos(theta), where    //
-// 'theta' is the maximal dishedral angle at ab. In this case, even if the   //
-// n-to-m flip exists, it will not be performed if the maximum dihedral of   //
-// the new tets is larger than 'theta'.                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::removeedge(badface* remedge, bool optflag)
-{
-  triface abcd, badc;  // Tet configuration at edge ab.
-  triface baccasing, abdcasing;
-  triface abtetlist[11];  // Old configuration at ab, save maximum 10 tets.
-  triface bftetlist[11];  // Old configuration at bf, save maximum 10 tets.
-  triface newtetlist[33]; // New configuration after removing ab.
-  face checksh;
-  enum fliptype fty;
-  REAL key;
-  bool remflag, subflag;
-  int n, n1, m, i, j;
-
-  // First try to strip abcd from the mesh. This needs to check either ab
-  //   or cd is on the hull. Try to strip it whichever is true.
-  abcd = remedge->tt;
-  adjustedgering(abcd, CCW);
-  i = 0;
-  do {
-    sym(abcd, baccasing);
-    // Is the tet on the hull?
-    if (baccasing.tet == dummytet) {
-      fnext(abcd, badc);
-      sym(badc, abdcasing);
-      if (abdcasing.tet == dummytet) {
-        // Strip the tet from the mesh -> ab is removed as well.
-        if (removetetbypeeloff(&abcd)) {
-          if (b->verbose > 1) {
-            printf("    Stripped tet from the mesh.\n");
-          }
-          optcount[0]++;
-          return true;
-        }
-      }
-    }
-    // Check if the oppsite edge cd is on the hull.
-    enext2fnextself(abcd);
-    enext2self(abcd);
-    esymself(abcd); // --> cdab
-    i++;
-  } while (i < 2);
-  
-  // Get the tets configuration at ab. Collect maximum 10 tets.
-  subflag = false;
-  abcd = remedge->tt;
-  adjustedgering(abcd, CW);
-  n = 0;
-  abtetlist[n] = abcd;
-  do {
-    // Is the list full?
-    if (n == 10) break;
-    // Stop if a subface appears.
-    tspivot(abtetlist[n], checksh);
-    if (checksh.sh != dummysh) {
-      // ab is either a segment or a facet edge. The latter case is not
-      //   handled yet! An edge flip is needed.
-      subflag = true; break; // return false;
-    }
-    // Get the next tet at ab.
-    fnext(abtetlist[n], abtetlist[n + 1]);
-    n++;
-  } while (apex(abtetlist[n]) != apex(abcd));
-
-  remflag = false;
-  key = remedge->key;
-
-  if (subflag && optflag) {
-    abcd = remedge->tt;
-    adjustedgering(abcd, CCW);
-    // Try to flip face cda or cdb to improve quality.
-    for (j = 0; j < 2; j++) {
-      if (j == 0) {
-        enext2fnext(abcd, abtetlist[0]); // Goto cda.
-      } else {
-        enextfnext(abcd, abtetlist[0]); // Goto cdb.
-      }
-      fty = categorizeface(abtetlist[0]);
-      if (fty == T23) {
-        // A 2-to-3 flip is possible.
-        sym(abtetlist[0], abtetlist[1]);
-        assert(abtetlist[1].tet != dummytet);
-        n = 2; 
-        m = 3;
-        remflag = removefacebyflip23(&key, abtetlist, newtetlist, NULL);
-      } else if (fty == T22) {
-        // A 2-to-2 or 4-to-4 flip is possible.
-        n = 2;
-        newtetlist[0] = abtetlist[0];
-        adjustedgering(newtetlist[0], CW);
-        fnext(newtetlist[0], newtetlist[1]);
-        assert(newtetlist[1].tet != dummytet);
-        // May it is 4-to-4 flip.
-        if (fnext(newtetlist[1], newtetlist[2])) {
-          fnext(newtetlist[2], newtetlist[3]);
-          assert(newtetlist[3].tet != dummytet);
-          n = 4;
-        }
-        m = n;
-        remflag = removeedgebyflip22(&key, n, newtetlist, NULL);
-      }
-      // Has quality been improved?
-      if (remflag) {
-        if (b->verbose > 1) {
-          printf("  Done flip %d-to-%d. Qual: %g -> %g.\n", n, m,
-                 acos(remedge->key) / PI * 180.0, acos(key) / PI * 180.0);
-        }
-        // Delete the old tets. Note, flip22() does not create new tets.
-        if (m == 3) {
-          for (i = 0; i < n; i++) {
-            tetrahedrondealloc(abtetlist[i].tet);
-          }
-        }
-        for (i = 0; i < m; i++) {
-          checktet4opt(&(newtetlist[i]), true);
-        }
-        optcount[1]++;
-        return true;
-      }
-    } // if (j = 0; j < 2; j++)
-    // Faces are not flipable. Return.
-    return false;
-  }
-
-  // 2 <= n <= 10.
-  if (n == 3) {
-    // There are three tets at ab. Try to do a flip32 at ab.
-    remflag = removeedgebyflip32(&key, abtetlist, newtetlist, NULL);
-  } else if ((n == 4) || (n == 5) || (n == 6)) {
-    // Four tets case. Try to do edge transformation.
-    remflag = removeedgebytranNM(&key,n,abtetlist,newtetlist,NULL,NULL,NULL);
-  } else {
-    if (b->verbose > 1) {
-      printf("  !! Unhandled case: n = %d.\n", n);
-    }
-  }
-  if (remflag) {
-    optcount[n]++;
-    // Delete the old tets.
-    for (i = 0; i < n; i++) {
-      tetrahedrondealloc(abtetlist[i].tet);
-    }
-    m = (n - 2) * 2; // The numebr of new tets.
-    if (b->verbose > 1) {
-      printf("  Done flip %d-to-%d. ", n, m);
-      if (optflag) {
-        printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
-               acos(key) / PI * 180.0);
-      }
-      printf("\n");
-    }
-  } 
-
-  if (!remflag && (key == remedge->key) && (n < 7)) {
-    // Try to do a combination of flips.
-    n1 = 0;
-    remflag = removeedgebycombNM(&key, n, abtetlist, &n1, bftetlist,
-      newtetlist, NULL);
-    if (remflag) {
-      optcount[9]++;
-      // Delete the old tets.
-      for (i = 0; i < n; i++) {
-        tetrahedrondealloc(abtetlist[i].tet);
-      }
-      for (i = 0; i < n1; i++) {
-        if (!isdead(&(bftetlist[i]))) {
-          tetrahedrondealloc(bftetlist[i].tet);
-        }
-      }
-      m = ((n1 - 2) * 2 - 1) + (n - 3) * 2; // The number of new tets.
-      if (b->verbose > 1) {
-        printf("  Done flip %d-to-%d (n-1=%d, n1=%d). ", n+n1-2, m, n-1,n1);
-        if (optflag) {
-          printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
-               acos(key) / PI * 180.0);
-        }
-        printf("\n");
-      }
-    }
-  }
-
-  if (remflag) {
-    // edge is removed. Test new tets for further optimization.
-    for (i = 0; i < m; i++) {
-      if (optflag) {
-        checktet4opt(&(newtetlist[i]), true);
-      } else {
-        checktet4ill(&(newtetlist[i]), true);
-      }
-    }
-  }
-
-  return remflag;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// smoothsliver()    Remove a sliver by smoothing a vertex of it.            //
-//                                                                           //
-// The 'slivtet' represents a sliver abcd, and ab is the current edge which  //
-// has a large dihedral angle (close to 180 degree).                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::smoothsliver(badface* remedge, list *starlist)
-{
-  triface checktet;
-  point smthpt;
-  bool smthed;
-  int idx, i, j;
-
-  // Find a Steiner volume point and smooth it.
-  smthed = false;
-  for (i = 0; i < 4 && !smthed; i++) {
-    smthpt = (point) remedge->tt.tet[4 + i];
-    // Is it a volume point?
-    if (pointtype(smthpt) == FREEVOLVERTEX) {
-      // Is it a Steiner point?
-      idx = pointmark(smthpt) - in->firstnumber;
-      if (!(idx < in->numberofpoints)) {
-        // Smooth a Steiner volume point.
-        starlist->append(&(remedge->tt.tet));
-        formstarpolyhedron(smthpt, starlist, NULL, false);
-        smthed = smoothpoint(smthpt,NULL,NULL,starlist,false,&remedge->key);
-        // If it is smoothed. Queue new bad tets.
-        if (smthed) {
-          for (j = 0; j < starlist->len(); j++) {
-            checktet = * (triface *)(* starlist)[j];
-            checktet4opt(&checktet, true);
-          }
-        }
-        starlist->clear();
-      }
-    }
-  } 
-
-  /* Omit to smooth segment points. This may cause infinite loop.
-  if (smthed) {
-    return true;
-  }
-  face abseg, nextseg, prevseg;
-  point pt[2];
-  // Check if ab is a segment.
-  tsspivot(slivtet, &abseg);
-  if (abseg.sh == dummysh) {
-    // ab is not a segment. Check if a or b is a Steiner segment point.
-    for (i = 0; i < 2 && !smthed; i++) {
-      smthpt = (i == 0 ? org(*slivtet) : dest(*slivtet));
-      if (pointtype(smthpt) == FREESEGVERTEX) {
-        // Is it a Steiner point?
-        idx = pointmark(smthpt) - in->firstnumber;
-        if (!(idx < in->numberofpoints)) {
-          // Smooth a Steiner segment point. Get the segment.
-          sdecode(point2sh(smthpt), nextseg);
-          locateseg(smthpt, &nextseg);
-          assert(sorg(nextseg) == smthpt);
-          pt[0] = sdest(nextseg);
-          senext2(nextseg, prevseg);
-          spivotself(prevseg);
-          prevseg.shver = 0;
-          if (sorg(prevseg) == smthpt) sesymself(prevseg);
-          assert(sdest(prevseg) == smthpt);
-          pt[1] = sorg(prevseg);
-          starlist->append(slivtet);
-          formstarpolyhedron(smthpt, starlist, NULL, true);
-          smthed = smoothpoint(smthpt, pt[0], pt[1], starlist, false);
-          // If it is smoothed. Check if the tet is still a sliver.
-          if (smthed) checktet4opt(slivtet, true);
-          starlist->clear();
-        }
-      }
-    }
-  }
-  */
-
-  return smthed;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// splitsliver()    Remove a sliver by inserting a point.                    //
-//                                                                           //
-// The 'remedge->tt' represents a sliver abcd, ab is the current edge which  //
-// has a large dihedral angle (close to 180 degree).                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-bool tetgenmesh::splitsliver(badface *remedge, list *tetlist, list *ceillist)
-{
-  triface starttet;
-  face checkseg;
-  point newpt, pt[4];
-  bool remflag;
-  int i;
-
-  starttet = remedge->tt;
-
-  // Check if cd is a segment.
-  adjustedgering(starttet, CCW);
-  enextfnextself(starttet);
-  enextself(starttet);
-  tsspivot(&starttet, &checkseg);
-  if (b->nobisect == 0) {
-    if (checkseg.sh != dummysh) {
-      // cd is a segment. The seg will be split. BUT do not flip! Due to the
-      //   exact predicates, lot of slivers ay be rsulted and hard to remove.
-      checkseg.shver = 0;
-      pt[0] = sorg(checkseg);
-      pt[1] = sdest(checkseg);
-      makepoint(&newpt);
-      getsplitpoint(pt[0], pt[1], NULL, newpt);
-      setpointtype(newpt, FREESEGVERTEX);
-      setpoint2sh(newpt, sencode(checkseg));
-      // Insert p, this should always success.
-      sstpivot(&checkseg, &starttet);
-      splittetedge(newpt, &starttet, NULL);
-      // Collect the new tets connecting at p.
-      sstpivot(&checkseg, &starttet);
-      ceillist->append(&starttet);
-      formstarpolyhedron(newpt, ceillist, NULL, true);
-      setnewpointsize(newpt, pt[0], NULL);
-      if (steinerleft > 0) steinerleft--;
-      // Smooth p.
-      smoothpoint(newpt, pt[0], pt[1], ceillist, false, NULL);
-      // Queue new slivers.
-      for (i = 0; i < ceillist->len(); i++) {
-        starttet = * (triface *)(* ceillist)[i];
-        checktet4opt(&starttet, true);
-      }
-      ceillist->clear();
-      return true;
-    }
-  }
-
-  // Get the four corners.
-  for (i = 0; i < 4; i++) {
-    pt[i] = (point) starttet.tet[4 + i];
-  }
-  // Create the new point p (at the circumcenter of t).
-  makepoint(&newpt);
-  for (i = 0; i < 3; i++) {
-    newpt[i] = 0.25 * (pt[0][i] + pt[1][i] + pt[2][i] + pt[3][i]);
-  }
-  setpointtype(newpt, FREEVOLVERTEX);
-
-  // Form the Bowyer-Watson cavity of p.
-  remflag = false;
-  infect(starttet);
-  tetlist->append(&starttet);
-  formbowatcavityquad(newpt, tetlist, ceillist);
-  if (trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, -1.0)) {
-    // Smooth p.
-    if (smoothpoint( newpt, NULL, NULL, ceillist, false, &remedge->key)) {
-      // Insert p.
-      bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, NULL,
-                      NULL, false, false, false);
-      setnewpointsize(newpt, pt[0], NULL);
-      if (steinerleft > 0) steinerleft--;
-      // Queue new slivers.
-      for (i = 0; i < ceillist->len(); i++) {
-        starttet = * (triface *)(* ceillist)[i];
-        checktet4opt(&starttet, true);
-      }
-      remflag = true;
-    } // if (smoothpoint) 
-  } // if (trimbowatcavity) 
-
-  if (!remflag) {
-    // p is rejected for BC(p) is not valid.
-    pointdealloc(newpt);
-    // Uninfect tets of BC(p).
-    for (i = 0; i < tetlist->len(); i++) {
-      starttet = * (triface *)(* tetlist)[i];
-      uninfect(starttet);
-    }
-  }
-  tetlist->clear();
-  ceillist->clear();
-
-  return remflag;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tallslivers()    Queue all the slivers in the mesh.                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::tallslivers(bool optflag)
-{
-  triface tetloop;
-
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    if (optflag) {
-      checktet4opt(&tetloop, true);
-    } else {
-      checktet4ill(&tetloop, true);
-    }
-    tetloop.tet = tetrahedrontraverse();
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// optimizemesh()    Improve mesh quality by mesh optimizations.             //
-//                                                                           //
-// Available mesh optimizing operations are: (1) multiple edge flips (3-to-2,//
-// 4-to-4, 5-to-6, etc), (2) free vertex deletion, (3) new vertex insertion. //
-// (1) is mandatory, while (2) and (3) are optionally.                       //
-//                                                                           //
-// The variable 'b->optlevel' (set after '-s') determines the use of these   //
-// operations. If it is: 0, do no optimization; 1, only do (1) operation; 2, //
-// do (1) and (2) operations; 3, do all operations. Deault, b->optlvel = 2.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::optimizemesh(bool optflag)
-{
-  list *splittetlist, *tetlist, *ceillist;
-  badface *remtet, *lastentry;
-  REAL maxdihed, objdihed, curdihed;
-  long oldnum;
-  int iter, i;
-
-  if (!b->quiet) {
-    if (optflag) {
-      printf("Optimizing mesh.\n");
-    } else {
-      printf("Repairing mesh.\n");
-    }
-  }
-
-#ifdef SELF_CHECK
-  if (optflag && (b->verbose)) {
-    printf("  level = %d.\n", b->optlevel);
-  }
-#endif
-
-  // Initialize the pool of bad tets.
-  badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
-  if (optflag) {
-    cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
-    cosmindihed = cos(b->mindihedral * PI / 180.0);
-    // The radian of the maximum dihedral angle.
-    maxdihed = b->maxdihedral / 180.0 * PI;
-    // A sliver has an angle large than 'objdihed' will be split.
-    objdihed = b->maxdihedral + 5.0;
-    if (objdihed < 170.0) objdihed = 170.0;
-    objdihed = objdihed / 180.0 * PI;
-  }
-  // Looking for non-optimal tets.
-  tallslivers(optflag);
-
-  optcount[0] = 0l;  // tet strip count.
-  optcount[1] = 0l;  // face (2-3) and edge (2-2) flip count.
-  optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l; // edge flips.
-  optcount[9] = 0l;  // combined flip count.
-
-  // Perform edge flip to improve quality.
-  lastentry = (badface *) NULL;
-  // Loop until pool 'badtetrahedrons' is empty.
-  while (badtetrahedrons->items > 0) {
-    badtetrahedrons->traversalinit();
-    remtet = badfacetraverse(badtetrahedrons);
-    while (remtet != (badface *) NULL) {
-      // Make sure that the tet is still the same one when it was tested.
-      //   Subsequent transformations may have made it a different tet.
-      if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
-          dest(remtet->tt) == remtet->fdest && 
-          apex(remtet->tt) == remtet->fapex &&
-          oppo(remtet->tt) == remtet->foppo) {
-        if (b->verbose > 1) {
-          printf("    Repair tet (%d, %d, %d, %d) %g (degree).\n",
-                 pointmark(remtet->forg), pointmark(remtet->fdest),
-                 pointmark(remtet->fapex), pointmark(remtet->foppo),
-                 acos(remtet->key) / PI * 180.0);
-        }
-        if (!removeedge(remtet, optflag)) {
-          // An unremoveable tet. Check if it forms a loop.
-          if (lastentry != (badface *) NULL) {
-            if (remtet == lastentry) break;
-          } else {
-            // Remember this tet as a breakpoint.
-            lastentry = remtet;
-          }
-        } else {
-          // Clear the breakpoint.
-          lastentry = (badface *) NULL;
-          // Remove the entry from the queue.
-          badfacedealloc(badtetrahedrons, remtet);
-        }
-      } else {
-        // Remove the entry from the queue.
-        badfacedealloc(badtetrahedrons, remtet);
-      }
-      remtet = badfacetraverse(badtetrahedrons);
-    }
-    // Stop if the above loop was out by force.
-    if (remtet != (badface *) NULL) break;
-  }
-
-  if (b->verbose) {
-    if (optcount[0] > 0l) {
-      printf("  %ld tets are peeled off.\n", optcount[0]);
-    }
-    if (optcount[1] > 0l) {
-      printf("  %ld faces are flipped.\n", optcount[1]);
-    }
-    if (optcount[3] + optcount[4] + optcount[5] + optcount[6] + 
-        optcount[9] > 0l) {
-      printf("  %ld edges are flipped.\n", optcount[3] + optcount[4] +
-             optcount[5] + optcount[6] + optcount[9]);
-    }
-    // if (badtetrahedrons->items > 0l) {
-    //   printf("  %ld edges remain.\n", badtetrahedrons->items);
-    // }
-  }
-
-  if ((badtetrahedrons->items > 0l) && optflag  && (b->optlevel > 2)) {
-    splittetlist = new list(sizeof(badface), NULL, 256);
-    tetlist = new list(sizeof(triface), NULL, 256);
-    ceillist = new list(sizeof(triface), NULL, 256);
-    oldnum = points->items;
-    smoothsegverts = smoothvolverts = 0;
-    optcount[1] = 0l;
-    optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l; // edge flips.
-    optcount[9] = 0l;  // combined flip count.
-    iter = 0;
-
-    do {
-      // Form a list of slivers to be split and clean the pool.
-      badtetrahedrons->traversalinit();
-      remtet = badfacetraverse(badtetrahedrons);
-      while (remtet != (badface *) NULL) {
-        splittetlist->append(remtet);
-        // Remove the entry from the queue.
-        badfacedealloc(badtetrahedrons, remtet);
-        remtet = badfacetraverse(badtetrahedrons);
-      }
-      for (i = 0; i < splittetlist->len(); i++) {
-        remtet = (badface *)(* splittetlist)[i];
-        // Make sure that the tet is still the same one when it was tested.
-        //   Subsequent transformations may have made it a different tet.
-        if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
-            dest(remtet->tt) == remtet->fdest && 
-            apex(remtet->tt) == remtet->fapex &&
-            oppo(remtet->tt) == remtet->foppo) {
-          // The sliver may get smoothed due to a neighboring tet.
-          curdihed = facedihedral(remtet->forg, remtet->fdest, remtet->fapex,
-                                  remtet->foppo);
-          // The dihedral angle of a tet must less than PI, correct it.
-          if (curdihed > PI) curdihed = 2 * PI - curdihed;
-          // Is it a large angle?
-          if (curdihed > objdihed) {
-            remtet->key = cos(curdihed);
-            if (b->verbose > 1) {
-              printf("    Get sliver (%d, %d, %d, %d) %g (degree).\n",
-                     pointmark(remtet->forg), pointmark(remtet->fdest),
-                     pointmark(remtet->fapex), pointmark(remtet->foppo),
-                     acos(remtet->key) / PI * 180.0);
-            }
-            if (!removeedge(remtet, optflag)) {
-              if (!smoothsliver(remtet, tetlist)) {
-                splitsliver(remtet, tetlist, ceillist);
-              }
-            }
-          }
-        }
-      }
-      iter++;
-    } while ((badtetrahedrons->items > 0l) && (iter < b->optpasses));
-    
-    if (b->verbose) {
-      printf("  %d passes.\n", iter);
-      if ((points->items - oldnum) > 0l) {
-        printf("  %ld points are inserted (%d on segment).\n",
-               points->items - oldnum, smoothsegverts);
-      }
-      if (optcount[1] > 0l) {
-        printf("  %ld faces are flipped.\n", optcount[1]);
-      }
-      if (optcount[3] + optcount[4] + optcount[5] + optcount[6] + 
-          optcount[9] > 0l) {
-        printf("  %ld edges are flipped.\n", optcount[3] + optcount[4] +
-               optcount[5] + optcount[6] + optcount[9]);
-      }
-      // if (badtetrahedrons->items > 0l) {
-      //   printf("  %ld edges remain.\n", badtetrahedrons->items);
-      // }
-    }
-    delete tetlist;
-    delete ceillist;
-    delete splittetlist;
-  }
-
-  delete badtetrahedrons;
-  badtetrahedrons = (memorypool *) NULL;
-}
-
-//
-// End of mesh optimization routines
-//
-
-//
-// Begin of I/O rouitnes
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// transfernodes()    Transfer nodes from 'io->pointlist' to 'this->points'. //
-//                                                                           //
-// Initializing 'this->points'.  Transferring all points from 'in->pointlist'//
-// into it. All points are indexed (start from in->firstnumber).  Each point //
-// is initialized be UNUSEDVERTEX.  The bounding box (xmin, xmax, ymin, ymax,//
-// zmin, zmax) and the diameter (longest) of the point set are calculated.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::transfernodes()
-{
-  point pointloop;
-  REAL x, y, z;
-  int coordindex;
-  int attribindex;
-  int mtrindex;
-  int i, j;
-
-  // Read the points.
-  coordindex = 0;
-  attribindex = 0;
-  mtrindex = 0;
-  for (i = 0; i < in->numberofpoints; i++) {
-    makepoint(&pointloop);
-    // Read the point coordinates.
-    x = pointloop[0] = in->pointlist[coordindex++];
-    y = pointloop[1] = in->pointlist[coordindex++];
-    z = pointloop[2] = in->pointlist[coordindex++];
-    // Read the point attributes.
-    for (j = 0; j < in->numberofpointattributes; j++) {
-      pointloop[3 + j] = in->pointattributelist[attribindex++];
-    }
-    // Read the point metric tensor.
-    for (j = 0; j < in->numberofpointmtrs; j++) {
-      pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
-    }
-    // Determine the smallest and largests x, y and z 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 < zmin) ? z : zmin;
-      zmax = (z > zmax) ? z : zmax;
-    }
-  }
-  // 'longest' is the largest possible edge length formed by input vertices.
-  x = xmax - xmin;
-  y = ymax - ymin;
-  z = zmax - zmin;
-  longest = sqrt(x * x + y * y + z * z);
-  if (longest == 0.0) {
-    printf("Error:  The point set is trivial.\n");
-    terminatetetgen(1);
-  }
-  // Two identical points are distinguished by 'lengthlimit'.
-  lengthlimit = longest * b->epsilon * 1e+2;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// jettisonnodes()    Jettison unused or duplicated vertices.                //
-//                                                                           //
-// Unused points are those input points which are outside the mesh domain or //
-// have no connection (isolated) to the mesh.  Duplicated points exist for   //
-// example if the input PLC is read from a .stl mesh file (marked during the //
-// Delaunay tetrahedralization step. This routine remove these points from   //
-// points list. All existing points are reindexed.                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::jettisonnodes()
-{
-  point pointloop;
-  bool jetflag;
-  int oldidx, newidx;
-  int remcount;
-
-  if (!b->quiet) {
-    printf("Jettisoning redundants points.\n");
-  }
-
-  points->traversalinit();
-  pointloop = pointtraverse();
-  oldidx = newidx = 0; // in->firstnumber;
-  remcount = 0;
-  while (pointloop != (point) NULL) {
-    jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) || 
-      (pointtype(pointloop) == UNUSEDVERTEX);
-    if (jetflag) {
-      // It is a duplicated point, delete it.
-      pointdealloc(pointloop);
-      remcount++;
-    } else {
-      // Re-index it.
-      setpointmark(pointloop, newidx + in->firstnumber);
-      if (in->pointmarkerlist != (int *) NULL) {
-        if (oldidx < in->numberofpoints) {
-          // Re-index the point marker as well.
-          in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
-        }
-      }
-      newidx++;
-    }
-    oldidx++;
-    if (oldidx == in->numberofpoints) {
-      // Update the numbe of input points (Because some were removed).
-      in->numberofpoints -= remcount;
-      // Remember this number for output original input nodes.
-      jettisoninverts = remcount;
-    }
-    pointloop = pointtraverse();
-  }
-  if (b->verbose) {
-    printf("  %d duplicated vertices have been removed.\n", dupverts);
-    printf("  %d unused vertices have been removed.\n", unuverts);
-  }
-  dupverts = 0;
-  unuverts = 0;
-
-  // The following line ensures that dead items in the pool of nodes cannot
-  //   be allocated for the new created nodes. This ensures that the input
-  //   nodes will occur earlier in the output files, and have lower indices.
-  points->deaditemstack = (void *) NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// highorder()   Create extra nodes for quadratic subparametric elements.    //
-//                                                                           //
-// 'highordertable' is an array (size = numberoftetrahedra * 6) for storing  //
-// high-order nodes of each tetrahedron.  This routine is used only when -o2 //
-// switch is used.                                                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::highorder()
-{
-  triface tetloop, worktet;
-  triface spintet, adjtet;
-  point torg, tdest, tapex;
-  point *extralist, *adjextralist;
-  point newpoint;
-  int hitbdry, ptmark;
-  int i, j;
-
-  if (!b->quiet) {
-    printf("Adding vertices for second-order tetrahedra.\n");
-  }
-
-  // Initialize the 'highordertable'.
-  highordertable = new point[tetrahedrons->items * 6];
-  if (highordertable == (point *) NULL) {
-    printf("Error:  Out of memory.\n");
-    terminatetetgen(1);
-  }
-
-  // The following line ensures that dead items in the pool of nodes cannot
-  //   be allocated for the extra nodes associated with high order elements.
-  //   This ensures that the primary nodes (at the corners of elements) will
-  //   occur earlier in the output files, and have lower indices, than the
-  //   extra nodes.
-  points->deaditemstack = (void *) NULL;
-
-  // Assign an entry for each tetrahedron to find its extra nodes. At the
-  //   mean while, initialize all extra nodes be NULL.
-  i = 0;
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
-    for (j = 0; j < 6; j++) {
-      highordertable[i + j] = (point) NULL;
-    }
-    i += 6;
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  // To create a unique node on each edge. Loop over all tetrahedra, and
-  //   look at the six edges of each tetrahedron.  If the extra node in
-  //   the tetrahedron corresponding to this edge is NULL, create a node
-  //   for this edge, at the same time, set the new node into the extra
-  //   node lists of all other tetrahedra sharing this edge.  
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    // Get the list of extra nodes.
-    extralist = (point *) tetloop.tet[highorderindex];
-    worktet.tet = tetloop.tet;
-    for (i = 0; i < 6; i++) {
-      if (extralist[i] == (point) NULL) {
-        // Operate on this edge.
-        worktet.loc = edge2locver[i][0];
-        worktet.ver = edge2locver[i][1];
-        // Create a new node on this edge.
-        torg = org(worktet);
-        tdest = dest(worktet);
-        // Create a new node in the middle of the edge.
-        newpoint = (point) points->alloc();
-        // Interpolate its attributes.
-        for (j = 0; j < 3 + in->numberofpointattributes; j++) {
-          newpoint[j] = 0.5 * (torg[j] + tdest[j]);
-        }
-        ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
-        setpointmark(newpoint, ptmark);
-        // Add this node to its extra node list.
-        extralist[i] = newpoint;
-        // Set 'newpoint' into extra node lists of other tetrahedra
-        //   sharing this edge.
-        tapex = apex(worktet);
-        spintet = worktet;
-        hitbdry = 0;
-        while (hitbdry < 2) {
-          if (fnextself(spintet)) {
-            // Get the extra node list of 'spintet'.
-            adjextralist = (point *) spintet.tet[highorderindex];
-            // Find the index of its extra node list.
-            j = locver2edge[spintet.loc][spintet.ver];
-            // Only set 'newpoint' into 'adjextralist' if it is a NULL.
-            //   Because two faces can belong to the same tetrahedron.
-            if (adjextralist[j] == (point) NULL) {
-              adjextralist[j] = newpoint;
-            }
-            if (apex(spintet) == tapex) {
-              break;
-            }
-          } else {
-            hitbdry++;
-            if (hitbdry < 2) {
-              esym(worktet, spintet);
-	    }
-          }
-        }
-      }
-    }
-    tetloop.tet = tetrahedrontraverse();
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outnodes()    Output the points to a .node file or a tetgenio structure.  //
-//                                                                           //
-// Note: each point has already been numbered on input (the first index is   //
-// 'in->firstnumber').                                                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outnodes(tetgenio* out)
-{
-  FILE *outfile;
-  char outnodefilename[FILENAMESIZE];
-  shellface subptr;
-  triface adjtet;
-  face subloop;
-  point pointloop;
-  point *extralist, ep[3];
-  int nextras, bmark, shmark, marker;
-  int coordindex, attribindex;
-  int pointnumber, firstindex;
-  int index, i;
-
-  if (out == (tetgenio *) NULL) {
-    strcpy(outnodefilename, b->outfilename);
-    strcat(outnodefilename, ".node");
-  } 
-  
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", outnodefilename);
-    } else {
-      printf("Writing nodes.\n");
-    }
-  }
-
-  nextras = in->numberofpointattributes;
-  bmark = !b->nobound && in->pointmarkerlist;
-
-  // Avoid compile warnings.
-  outfile = (FILE *) NULL;
-  marker = coordindex = 0;
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(outnodefilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", outnodefilename);
-      terminatetetgen(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, 3, nextras, bmark);
-  } else {
-    // Allocate space for 'pointlist';
-    out->pointlist = new REAL[points->items * 3];
-    if (out->pointlist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-    // Allocate space for 'pointattributelist' if necessary;
-    if (nextras > 0) {
-      out->pointattributelist = new REAL[points->items * nextras];
-      if (out->pointattributelist == (REAL *) NULL) {
-        printf("Error:  Out of memory.\n");
-        terminatetetgen(1);
-      }
-    }
-    // Allocate space for 'pointmarkerlist' if necessary;
-    if (bmark) {
-      out->pointmarkerlist = new int[points->items];
-      if (out->pointmarkerlist == (int *) NULL) {
-        printf("Error:  Out of memory.\n");
-        terminatetetgen(1);
-      }
-    }
-    out->numberofpoints = points->items;
-    out->numberofpointattributes = nextras;
-    coordindex = 0;
-    attribindex = 0;
-  }
-
-  if (bmark && (b->plc || b->refine)) {
-    // Initialize the point2tet field of each point.
-    points->traversalinit();
-    pointloop = pointtraverse();
-    while (pointloop != (point) NULL) {
-      setpoint2tet(pointloop, (tetrahedron) NULL);
-      pointloop = pointtraverse();
-    }
-    // Make a map point-to-subface. Hence a boundary point will get the
-    //   facet marker from that facet where it lies on.
-    subfaces->traversalinit();
-    subloop.sh = shellfacetraverse(subfaces);
-    while (subloop.sh != (shellface *) NULL) {
-      subloop.shver = 0;
-      // Check all three points of the subface.
-      for (i = 0; i < 3; i++) {
-        pointloop = (point) subloop.sh[3 + i];
-        setpoint2tet(pointloop, (tetrahedron) sencode(subloop));
-      }
-      if (b->order == 2) {
-        // '-o2' switch. Set markers for quadratic nodes of this subface.
-        stpivot(subloop, adjtet);
-        if (adjtet.tet == dummytet) {
-          sesymself(subloop);
-          stpivot(subloop, adjtet);
-        }
-        assert(adjtet.tet != dummytet);
-        extralist = (point *) adjtet.tet[highorderindex];
-        switch (adjtet.loc) {
-        case 0:
-          ep[0] = extralist[0];
-          ep[1] = extralist[1];
-          ep[2] = extralist[2];
-          break;
-        case 1:
-          ep[0] = extralist[0];
-          ep[1] = extralist[4];
-          ep[2] = extralist[3];
-          break;
-        case 2:
-          ep[0] = extralist[1];
-          ep[1] = extralist[5];
-          ep[2] = extralist[4];
-          break;
-        case 3:
-          ep[0] = extralist[2];
-          ep[1] = extralist[3];
-          ep[2] = extralist[5];
-          break;
-        default: break;
-        }
-        for (i = 0; i < 3; i++) {
-          setpoint2tet(ep[i], (tetrahedron) sencode(subloop));
-        }
-      }
-      subloop.sh = shellfacetraverse(subfaces);
-    }
-  }
-
-  // Determine the first index (0 or 1).
-  firstindex = b->zeroindex ? 0 : in->firstnumber; 
-
-  points->traversalinit();
-  pointloop = pointtraverse();
-  pointnumber = firstindex; // in->firstnumber;
-  index = 0;
-  while (pointloop != (point) NULL) {
-    if (bmark) {
-      // Default the vertex has a zero marker.
-      marker = 0;
-      // Is it an input vertex?
-      if (index < in->numberofpoints) {
-        // Input point's marker is directly copied to output.
-        marker = in->pointmarkerlist[index];
-      }
-      // Is it a boundary vertex has marker zero?
-      if ((marker == 0) && (b->plc || b->refine)) {
-        subptr = (shellface) point2tet(pointloop);
-        if (subptr != (shellface) NULL) {
-          // Default a boundary vertex has marker 1.
-          marker = 1;
-          if (in->facetmarkerlist != (int *) NULL) {
-            // The vertex gets the marker from the facet it lies on.
-            sdecode(subptr, subloop);
-            shmark = shellmark(subloop);
-            marker = in->facetmarkerlist[shmark - 1];
-          }
-        }
-      }
-    }
-    if (out == (tetgenio *) 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[3 + i]);
-      }
-      if (bmark) {
-        // Write the boundary marker.
-        fprintf(outfile, "    %d", marker);
-      }
-      fprintf(outfile, "\n");
-    } else {
-      // X, y, and z coordinates.
-      out->pointlist[coordindex++] = pointloop[0];
-      out->pointlist[coordindex++] = pointloop[1];
-      out->pointlist[coordindex++] = pointloop[2];
-      // Point attributes.
-      for (i = 0; i < nextras; i++) {
-        // Output an attribute.
-        out->pointattributelist[attribindex++] = pointloop[3 + i];
-      }
-      if (bmark) {
-        // Output the boundary marker.  
-        out->pointmarkerlist[index] = marker;
-      }
-    }
-    pointloop = pointtraverse();
-    pointnumber++; 
-    index++;
-  }
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outmetrics()    Output the metric to a file (*.mtr) or a tetgenio obj.    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outmetrics(tetgenio* out)
-{
-  FILE *outfile;
-  char outmtrfilename[FILENAMESIZE];
-  list *tetlist, *ptlist;
-  triface tetloop;
-  point ptloop, neipt;
-  REAL lave, len; // lmin, lmax, 
-  int mtrindex;
-  int i;  
-
-  if (out == (tetgenio *) NULL) {
-    strcpy(outmtrfilename, b->outfilename);
-    strcat(outmtrfilename, ".mtr");
-  }
-
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", outmtrfilename);
-    } else {
-      printf("Writing metrics.\n");
-    }
-  }
-
-  // Avoid compile warnings.
-  outfile = (FILE *) NULL;
-  mtrindex = 0;
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(outmtrfilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", outmtrfilename);
-      terminatetetgen(1);
-    }
-    // Number of points, number of point metrices,
-    // fprintf(outfile, "%ld  %d\n", points->items, sizeoftensor + 3);
-    fprintf(outfile, "%ld  %d\n", points->items, 1);
-  } else {
-    // Allocate space for 'pointmtrlist' if necessary;
-    // out->pointmtrlist = new REAL[points->items * (sizeoftensor + 3)];
-    out->pointmtrlist = new REAL[points->items];
-    if (out->pointmtrlist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-    out->numberofpointmtrs = 1; // (sizeoftensor + 3);
-    mtrindex = 0;
-  }
-  
-  // Initialize the point2tet field of each point.
-  points->traversalinit();
-  ptloop = pointtraverse();
-  while (ptloop != (point) NULL) {
-    setpoint2tet(ptloop, (tetrahedron) NULL);
-    ptloop = pointtraverse();
-  }
-  // Create the point-to-tet map.
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    for (i = 0; i < 4; i++) {
-      ptloop = (point) tetloop.tet[4 + i];
-      setpoint2tet(ptloop, encode(tetloop));
-    }
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  tetlist = new list(sizeof(triface), NULL, 256);
-  ptlist = new list(sizeof(point *), NULL, 256);
-
-  points->traversalinit();
-  ptloop = pointtraverse();
-  while (ptloop != (point) NULL) {
-    decode(point2tet(ptloop), tetloop);
-    if (!isdead(&tetloop)) {
-      // Form the star of p.
-      tetlist->append(&tetloop);
-      formstarpolyhedron(ptloop, tetlist, ptlist, true);
-      // lmin = longest;
-      // lmax = 0.0;
-      lave = 0.0;
-      for (i = 0; i < ptlist->len(); i++) {
-        neipt = * (point *)(* ptlist)[i];
-        len = distance(ptloop, neipt);
-        // lmin = lmin < len ? lmin : len;
-        // lmax = lmax > len ? lmax : len;
-        lave += len;
-      }
-      lave /= ptlist->len();
-    }
-    if (out == (tetgenio *) NULL) {
-      // for (i = 0; i < sizeoftensor; i++) {
-      //   fprintf(outfile, "%-16.8e ", ptloop[pointmtrindex + i]);
-      // }
-      if (ptlist->len() > 0) {
-        // fprintf(outfile, "%-16.8e %-16.8e %-16.8e", lmin, lmax, lave);
-        fprintf(outfile, "%-16.8e ", lave);
-      } else {
-        fprintf(outfile, "0.0 "); // fprintf(outfile, "0.0  0.0  0.0");
-      }
-      fprintf(outfile, "\n");
-    } else {
-      // for (i = 0; i < sizeoftensor; i++) {
-      //   out->pointmtrlist[mtrindex++] = ptloop[pointmtrindex + i];
-      // }
-      if (ptlist->len() > 0) {
-        // out->pointmtrlist[mtrindex++] = lmin;
-        // out->pointmtrlist[mtrindex++] = lmax;
-        out->pointmtrlist[mtrindex++] = lave;
-      } else {
-        // out->pointmtrlist[mtrindex++] = 0.0;
-        // out->pointmtrlist[mtrindex++] = 0.0;
-        out->pointmtrlist[mtrindex++] = 0.0;
-      }
-    }
-    tetlist->clear();
-    ptlist->clear();
-    ptloop = pointtraverse();
-  }
-
-  delete tetlist;
-  delete ptlist;
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outelements()    Output the tetrahedra to an .ele file or a tetgenio      //
-//                  structure.                                               //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outelements(tetgenio* out)
-{
-  FILE *outfile;
-  char outelefilename[FILENAMESIZE];
-  tetrahedron* tptr;
-  int *tlist;
-  REAL *talist;
-  int firstindex, shift;
-  int pointindex;
-  int attribindex;
-  point p1, p2, p3, p4;
-  point *extralist;
-  int elementnumber;
-  int eextras;
-  int i;
-
-  if (out == (tetgenio *) NULL) {
-    strcpy(outelefilename, b->outfilename);
-    strcat(outelefilename, ".ele");
-  }
-
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", outelefilename);
-    } else {
-      printf("Writing elements.\n");
-    }
-  }
-
-  // Avoid compile warnings.
-  outfile = (FILE *) NULL;
-  tlist = (int *) NULL;
-  talist = (double *) NULL;
-  pointindex = attribindex = 0;
-
-  eextras = in->numberoftetrahedronattributes;
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(outelefilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", outelefilename);
-      terminatetetgen(1);
-    }
-    // Number of tetras, points per tetra, attributes per tetra.
-    fprintf(outfile, "%ld  %d  %d\n", tetrahedrons->items,
-            b->order == 1 ? 4 : 10, eextras);
-  } else {
-    // Allocate memory for output tetrahedra.
-    out->tetrahedronlist = new int[tetrahedrons->items * 
-                                   (b->order == 1 ? 4 : 10)];
-    if (out->tetrahedronlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-    // Allocate memory for output tetrahedron attributes if necessary.
-    if (eextras > 0) {
-      out->tetrahedronattributelist = new REAL[tetrahedrons->items * eextras];
-      if (out->tetrahedronattributelist == (REAL *) NULL) {
-        printf("Error:  Out of memory.\n");
-        terminatetetgen(1);
-      }
-    }
-    out->numberoftetrahedra = tetrahedrons->items;
-    out->numberofcorners = b->order == 1 ? 4 : 10;
-    out->numberoftetrahedronattributes = eextras;
-    tlist = out->tetrahedronlist;
-    talist = out->tetrahedronattributelist;
-    pointindex = 0;
-    attribindex = 0;
-  }
-
-  // Determine the first index (0 or 1).
-  firstindex = b->zeroindex ? 0 : in->firstnumber;
-  shift = 0; // Default no shiftment.
-  if ((in->firstnumber == 1) && (firstindex == 0)) {
-    shift = 1; // Shift the output indices by 1.
-  }
-
-  tetrahedrons->traversalinit();
-  tptr = tetrahedrontraverse();
-  elementnumber = firstindex; // in->firstnumber;
-  while (tptr != (tetrahedron *) NULL) {
-    p1 = (point) tptr[4];
-    p2 = (point) tptr[5];
-    p3 = (point) tptr[6];
-    p4 = (point) tptr[7];
-    if (out == (tetgenio *) NULL) {
-      // Tetrahedron number, indices for four points.
-      fprintf(outfile, "%5d   %5d %5d %5d %5d", elementnumber,
-              pointmark(p1) - shift, pointmark(p2) - shift,
-              pointmark(p3) - shift, pointmark(p4) - shift);
-      if (b->order == 2) {
-        extralist = (point *) tptr[highorderindex];
-        // Tetrahedron number, indices for four points plus six extra points.
-        fprintf(outfile, "  %5d %5d %5d %5d %5d %5d",
-          pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
-          pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
-          pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
-      }
-      for (i = 0; i < eextras; i++) {
-        fprintf(outfile, "    %.17g", elemattribute(tptr, i));
-      }
-      fprintf(outfile, "\n");
-    } else {
-      tlist[pointindex++] = pointmark(p1) - shift;
-      tlist[pointindex++] = pointmark(p2) - shift;
-      tlist[pointindex++] = pointmark(p3) - shift;
-      tlist[pointindex++] = pointmark(p4) - shift;
-      if (b->order == 2) {
-        extralist = (point *) tptr[highorderindex];
-        tlist[pointindex++] = pointmark(extralist[0]) - shift;
-        tlist[pointindex++] = pointmark(extralist[1]) - shift;
-        tlist[pointindex++] = pointmark(extralist[2]) - shift;
-        tlist[pointindex++] = pointmark(extralist[3]) - shift;
-        tlist[pointindex++] = pointmark(extralist[4]) - shift;
-        tlist[pointindex++] = pointmark(extralist[5]) - shift;
-      }
-      for (i = 0; i < eextras; i++) {
-        talist[attribindex++] = elemattribute(tptr, i);
-      }
-    }
-    if (b->neighout) {
-      // Remember the index of this element.
-      * (int *) (tptr + elemmarkerindex) = elementnumber;
-    }
-    tptr = tetrahedrontraverse();
-    elementnumber++;
-  }
-  if (b->neighout) {
-    // Set the outside element marker.
-    * (int *) (dummytet + elemmarkerindex) = -1;
-  }
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outfaces()    Output all faces to a .face file or a tetgenio structure.   //
-//                                                                           //
-// This routines outputs all triangular faces (including outer boundary      //
-// faces and inner faces) of this mesh.                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outfaces(tetgenio* out)
-{
-  FILE *outfile;
-  char facefilename[FILENAMESIZE];
-  int *elist;
-  int *emlist;
-  int neigh1, neigh2;
-  int index;
-  triface tface, tsymface;
-  face checkmark;
-  point torg, tdest, tapex;
-  long faces;
-  int bmark, faceid, marker;
-  int firstindex, shift;
-  int facenumber;
-
-  if (out == (tetgenio *) NULL) {
-    strcpy(facefilename, b->outfilename);
-    strcat(facefilename, ".face");
-  }
-
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", facefilename);
-    } else {
-      printf("Writing faces.\n");
-    }
-  }
-
-  // Avoid compile warnings.
-  outfile = (FILE *) NULL;
-  elist = (int *) NULL;
-  emlist = (int *) NULL;
-  index =  marker = 0;
-
-  faces = (4l * tetrahedrons->items + hullsize) / 2l;
-  bmark = !b->nobound && in->facetmarkerlist;
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(facefilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", facefilename);
-      terminatetetgen(1);
-    }
-    fprintf(outfile, "%ld  %d\n", faces, bmark);
-  } else {
-    // Allocate memory for 'trifacelist'.
-    out->trifacelist = new int[faces * 3];
-    if (out->trifacelist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-    // Allocate memory for 'trifacemarkerlist' if necessary.
-    if (bmark) {
-      out->trifacemarkerlist = new int[faces];
-      if (out->trifacemarkerlist == (int *) NULL) {
-        printf("Error:  Out of memory.\n");
-        terminatetetgen(1);
-      }
-    }
-    if (b->neighout > 1) {
-      // '-nn' switch.
-      out->adjtetlist = new int[subfaces->items * 2];
-      if (out->adjtetlist == (int *) NULL) {
-        printf("Error:  Out of memory.\n");
-        terminatetetgen(1);
-      }
-    }
-    out->numberoftrifaces = faces;
-    elist = out->trifacelist;
-    emlist = out->trifacemarkerlist;
-    index = 0;
-  }
-
-  // Determine the first index (0 or 1).
-  firstindex = b->zeroindex ? 0 : in->firstnumber;
-  shift = 0; // Default no shiftment.
-  if ((in->firstnumber == 1) && (firstindex == 0)) {
-    shift = 1; // Shift the output indices by 1.
-  }
-
-  tetrahedrons->traversalinit();
-  tface.tet = tetrahedrontraverse();
-  facenumber = firstindex; // in->firstnumber;
-  // To loop over the set of faces, loop over all tetrahedra, and look at
-  //   the four faces of each one. If there isn't another tetrahedron
-  //   adjacent to this 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.
-  while (tface.tet != (tetrahedron *) NULL) {
-    for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
-      sym(tface, tsymface);
-      if ((tsymface.tet == dummytet) || (tface.tet < tsymface.tet)) {
-        torg = org(tface);
-        tdest = dest(tface);
-        tapex = apex(tface);
-        if (bmark) {
-          // Get the boundary marker of this face. If it is an inner face,
-          //   it has no boundary marker, set it be zero.
-          if (b->useshelles) {
-            // Shell face is used.
-            tspivot(tface, checkmark);
-            if (checkmark.sh == dummysh) {
-              marker = 0;  // It is an inner face.
-            } else {
-              faceid = shellmark(checkmark) - 1;
-              marker = in->facetmarkerlist[faceid];
-            }
-          } else {
-            // Shell face is not used, only distinguish outer and inner face.
-            marker = tsymface.tet != dummytet ? 1 : 0;
-          }
-        }
-        if (b->neighout > 1) {
-          // '-nn' switch. Output adjacent tets indices.
-          neigh1 = * (int *)(tface.tet + elemmarkerindex);
-          if (tsymface.tet != dummytet) {
-            neigh2 = * (int *)(tsymface.tet + elemmarkerindex);
-          } else {
-            neigh2 = -1;  
-          }
-        }
-        if (out == (tetgenio *) NULL) {
-          // Face number, indices of three vertices.
-          fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
-                  pointmark(torg) - shift, pointmark(tdest) - shift,
-                  pointmark(tapex) - shift);
-          if (bmark) {
-            // Output a boundary marker.
-            fprintf(outfile, "  %d", marker);
-          }
-          if (b->neighout > 1) {
-            fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
-          }
-          fprintf(outfile, "\n");
-        } else {
-          // Output indices of three vertices.
-          elist[index++] = pointmark(torg) - shift;
-          elist[index++] = pointmark(tdest) - shift;
-          elist[index++] = pointmark(tapex) - shift;
-          if (bmark) {
-            emlist[facenumber - in->firstnumber] = marker;
-          }
-          if (b->neighout > 1) {
-            out->adjtetlist[(facenumber - in->firstnumber) * 2]     = neigh1;
-            out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
-          }
-        }
-        facenumber++;
-      }
-    }
-    tface.tet = tetrahedrontraverse();
-  }
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outhullfaces()    Output outer boundary faces to a .face file or a        //
-//                   tetgenio structure.                                     //
-//                                                                           //
-// The normal of each face is arranged to point inside of the domain (use    //
-// right-hand rule).  This routines will outputs convex hull faces if the    //
-// mesh is a Delaunay tetrahedralization.                                    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outhullfaces(tetgenio* out)
-{
-  FILE *outfile;
-  char facefilename[FILENAMESIZE];
-  int *elist;
-  int index;
-  triface tface, tsymface;
-  face checkmark;
-  point torg, tdest, tapex;
-  int firstindex, shift;
-  int facenumber;
-
-  if (out == (tetgenio *) NULL) {
-    strcpy(facefilename, b->outfilename);
-    strcat(facefilename, ".face");
-  }
-
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", facefilename);
-    } else {
-      printf("Writing faces.\n");
-    }
-  }
-
-  // Avoid compile warnings.
-  outfile = (FILE *) NULL;
-  elist = (int *) NULL;
-  index = 0;
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(facefilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", facefilename);
-      terminatetetgen(1);
-    }
-    fprintf(outfile, "%ld  0\n", hullsize);
-  } else {
-    // Allocate memory for 'trifacelist'.
-    out->trifacelist = new int[hullsize * 3];
-    if (out->trifacelist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-    out->numberoftrifaces = hullsize;
-    elist = out->trifacelist;
-    index = 0;
-  }
-
-  // Determine the first index (0 or 1).
-  firstindex = b->zeroindex ? 0 : in->firstnumber;
-  shift = 0; // Default no shiftment.
-  if ((in->firstnumber == 1) && (firstindex == 0)) {
-    shift = 1; // Shift the output indices by 1.
-  }
-
-  tetrahedrons->traversalinit();
-  tface.tet = tetrahedrontraverse();
-  facenumber = firstindex; // in->firstnumber;
-  // To loop over the set of hull faces, loop over all tetrahedra, and look
-  //   at the four faces of each one. If there isn't another tetrahedron
-  //   adjacent to this face, operate on the face.
-  while (tface.tet != (tetrahedron *) NULL) {
-    for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
-      sym(tface, tsymface);
-      if (tsymface.tet == dummytet) {
-        torg = org(tface);
-        tdest = dest(tface);
-        tapex = apex(tface);
-        if (out == (tetgenio *) NULL) {
-          // Face number, indices of three vertices.
-          fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
-                  pointmark(torg) - shift, pointmark(tdest) - shift,
-                  pointmark(tapex) - shift);
-          fprintf(outfile, "\n");
-        } else {
-          // Output indices of three vertices.
-          elist[index++] = pointmark(torg) - shift;
-          elist[index++] = pointmark(tdest) - shift;
-          elist[index++] = pointmark(tapex) - shift;
-        }
-        facenumber++;
-      }
-    }
-    tface.tet = tetrahedrontraverse();
-  }
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outsubfaces()    Output subfaces (i.e. boundary faces) to a .face file or //
-//                  a tetgenio structure.                                    //
-//                                                                           //
-// The boundary faces are exist in 'subfaces'. For listing triangle vertices //
-// in the same sense for all triangles in the mesh, the direction determined //
-// by right-hand rule is pointer to the inside of the volume.                //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outsubfaces(tetgenio* out)
-{
-  FILE *outfile;
-  char facefilename[FILENAMESIZE];
-  int *elist;
-  int *emlist;
-  int index, index1, index2;
-  triface abuttingtet;
-  face faceloop;
-  point torg, tdest, tapex;
-  int bmark, faceid, marker;
-  int firstindex, shift;
-  int neigh1, neigh2;
-  int facenumber;
-
-  if (out == (tetgenio *) NULL) {
-    strcpy(facefilename, b->outfilename);
-    strcat(facefilename, ".face");
-  }
-
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", facefilename);
-    } else {
-      printf("Writing faces.\n");
-    }
-  }
-
-  // Avoid compile warnings.
-  outfile = (FILE *) NULL;
-  elist = (int *) NULL;
-  emlist = (int *) NULL;
-  index = index1 = index2 = 0;
-  faceid = marker = 0;
-  neigh1 = neigh2 = 0;
-
-  bmark = !b->nobound && in->facetmarkerlist;
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(facefilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", facefilename);
-      terminatetetgen(1);
-    }
-    // Number of subfaces.
-    fprintf(outfile, "%ld  %d\n", subfaces->items, bmark);
-  } else {
-    // Allocate memory for 'trifacelist'.
-    out->trifacelist = new int[subfaces->items * 3];
-    if (out->trifacelist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-    if (bmark) {
-      // Allocate memory for 'trifacemarkerlist'.
-      out->trifacemarkerlist = new int[subfaces->items];
-      if (out->trifacemarkerlist == (int *) NULL) {
-        printf("Error:  Out of memory.\n");
-        terminatetetgen(1);
-      }
-    }
-    if (b->neighout > 1) {
-      // '-nn' switch.
-      out->adjtetlist = new int[subfaces->items * 2];
-      if (out->adjtetlist == (int *) NULL) {
-        printf("Error:  Out of memory.\n");
-        terminatetetgen(1);
-      }
-    }
-    out->numberoftrifaces = subfaces->items;
-    elist = out->trifacelist;
-    emlist = out->trifacemarkerlist;
-  }
-
-  // Determine the first index (0 or 1).
-  firstindex = b->zeroindex ? 0 : in->firstnumber;
-  shift = 0; // Default no shiftment.
-  if ((in->firstnumber == 1) && (firstindex == 0)) {
-    shift = 1; // Shift the output indices by 1.
-  }
-
-  subfaces->traversalinit();
-  faceloop.sh = shellfacetraverse(subfaces);
-  facenumber = firstindex; // in->firstnumber;
-  while (faceloop.sh != (shellface *) NULL) {
-    stpivot(faceloop, abuttingtet);
-    if (abuttingtet.tet == dummytet) {
-      sesymself(faceloop);
-      stpivot(faceloop, abuttingtet);
-    }
-    if (abuttingtet.tet != dummytet) {
-      // If there is a tetrahedron containing this subface, orient it so
-      //   that the normal of this face points to inside of the volume by
-      //   right-hand rule.
-      adjustedgering(abuttingtet, CCW);
-      torg = org(abuttingtet);
-      tdest = dest(abuttingtet);
-      tapex = apex(abuttingtet);
-    } else {
-      // This may happen when only a surface mesh be generated.
-      torg = sorg(faceloop);
-      tdest = sdest(faceloop);
-      tapex = sapex(faceloop);
-    }
-    if (bmark) {
-      faceid = shellmark(faceloop) - 1;
-      marker = in->facetmarkerlist[faceid];
-    }
-    if (b->neighout > 1) {
-      // '-nn' switch. Output adjacent tets indices.
-      neigh1 = -1;
-      stpivot(faceloop, abuttingtet);
-      if (abuttingtet.tet != dummytet) {
-        neigh1 = * (int *)(abuttingtet.tet + elemmarkerindex);
-      }
-      neigh2 = -1;
-      sesymself(faceloop);
-      stpivot(faceloop, abuttingtet);
-      if (abuttingtet.tet != dummytet) {
-        neigh2 = * (int *)(abuttingtet.tet + elemmarkerindex);
-      }
-    }
-    if (out == (tetgenio *) NULL) {
-      fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
-              pointmark(torg) - shift, pointmark(tdest) - shift,
-              pointmark(tapex) - shift);
-      if (bmark) {
-        fprintf(outfile, "    %d", marker);
-      }
-      if (b->neighout > 1) {
-        fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
-      }
-      fprintf(outfile, "\n");
-    } else {
-      // Output three vertices of this face;
-      elist[index++] = pointmark(torg) - shift;
-      elist[index++] = pointmark(tdest) - shift;
-      elist[index++] = pointmark(tapex) - shift;
-      if (bmark) {
-        emlist[index1++] = marker;
-      }
-      if (b->neighout > 1) {
-        out->adjtetlist[index2++] = neigh1;
-        out->adjtetlist[index2++] = neigh2;
-      }
-    }
-    facenumber++;
-    faceloop.sh = shellfacetraverse(subfaces);
-  }
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outedges()    Output all edges to a .edge file or a structure.            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outedges(tetgenio* out)
-{
-  FILE *outfile;
-  char edgefilename[FILENAMESIZE];
-  int *elist, *emlist;
-  int index, index1;
-  triface tetloop, worktet, spintet;
-  face checksh;
-  point torg, tdest;
-  long faces, edges;
-  int firstindex, shift;
-  int edgenumber, faceid, marker;
-  int hitbdry, i;
-
-  if (out == (tetgenio *) NULL) {
-    strcpy(edgefilename, b->outfilename);
-    strcat(edgefilename, ".edge");
-  }
-
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", edgefilename);
-    } else {
-      printf("Writing edges.\n");
-    }
-  }
-
-  // Avoid compile warnings.
-  outfile = (FILE *) NULL;
-  elist = (int *) NULL;
-  emlist = (int *) NULL;
-  index = index1 = 0;
-  faceid = marker = 0;
-
-  // Using the Euler formula (V-E+F-T=1) to get the total number of edges.
-  faces = (4l * tetrahedrons->items + hullsize) / 2l;
-  edges = points->items + faces - tetrahedrons->items - 1l;
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(edgefilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
-      terminatetetgen(1);
-    }
-    // Write the number of edges, boundary markers (0 or 1).
-    fprintf(outfile, "%ld  %d\n", edges, !b->nobound);
-  } else {
-    // Allocate memory for 'edgelist'.
-    out->edgelist = new int[edges * 2];
-    if (out->edgelist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-    if (!b->nobound) {
-      out->edgemarkerlist = new int[edges];
-    }
-    out->numberofedges = edges;
-    elist = out->edgelist;
-    emlist = out->edgemarkerlist;
-  }
-
-  // Determine the first index (0 or 1).
-  firstindex = b->zeroindex ? 0 : in->firstnumber;
-  shift = 0; // Default no shiftment.
-  if ((in->firstnumber == 1) && (firstindex == 0)) {
-    shift = 1; // Shift (reduce) the output indices by 1.
-  }
-
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  edgenumber = firstindex; // in->firstnumber;
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    // Count the number of Voronoi faces. Look at the six edges of each
-    //   tetrahedron. Count the edge only if the tetrahedron's pointer is
-    //   smaller than those of all other tetrahedra that share the edge.
-    worktet.tet = tetloop.tet;
-    for (i = 0; i < 6; i++) {
-      worktet.loc = edge2locver[i][0];
-      worktet.ver = edge2locver[i][1];
-      adjustedgering(worktet, CW);
-      spintet = worktet;
-      hitbdry = 0;
-      while (hitbdry < 2) {
-        if (fnextself(spintet)) {
-          if (apex(spintet) == apex(worktet)) break;
-          if (spintet.tet < worktet.tet) break;
-        } else {
-          hitbdry++;
-          if (hitbdry < 2) {
-            esym(worktet, spintet);
-            fnextself(spintet); // In the same tet.
-	  }
-        }
-      }
-      // Count this edge if no adjacent tets are smaller than this tet.
-      if (spintet.tet >= worktet.tet) {
-        torg = org(worktet);
-        tdest = dest(worktet);
-        if (out == (tetgenio *) NULL) {
-          fprintf(outfile, "%5d   %4d  %4d", edgenumber,
-                  pointmark(torg) - shift, pointmark(tdest) - shift);
-        } else {
-          // Output three vertices of this face;
-          elist[index++] = pointmark(torg) - shift;
-          elist[index++] = pointmark(tdest) - shift;
-        }
-        if (!b->nobound) {
-          if (hitbdry > 0) {
-            // It is a boundary edge. Get the boundary marker of the facet
-            //   containing this edge. Note there may have more than one
-            //   facet, choose one arbitrarily.
-            if ((b->plc || b->refine) && in->facetmarkerlist) {
-              tspivot(spintet, checksh);
-              faceid = shellmark(checksh) - 1;
-              marker = in->facetmarkerlist[faceid];
-            } else {
-              marker = 1;  // Indicate it's a boundary edge.
-            }
-          } else {
-            marker = 0;
-          }
-          if (out == (tetgenio *) NULL) {
-            fprintf(outfile, "  %d", marker);
-          } else {
-            emlist[index1++] = marker;
-          }
-        }
-        if (out == (tetgenio *) NULL) {
-          fprintf(outfile, "\n");
-        }
-        edgenumber++;
-      }
-    }
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outsubsegments()    Output segments to a .edge file or a structure.       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outsubsegments(tetgenio* out)
-{
-  FILE *outfile;
-  char edgefilename[FILENAMESIZE];
-  int *elist;
-  int index;
-  face edgeloop;
-  point torg, tdest;
-  int firstindex, shift;
-  int edgenumber;
-
-  if (out == (tetgenio *) NULL) {
-    strcpy(edgefilename, b->outfilename);
-    strcat(edgefilename, ".edge");
-  }
-
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", edgefilename);
-    } else {
-      printf("Writing edges.\n");
-    }
-  }
-
-  // Avoid compile warnings.
-  outfile = (FILE *) NULL;
-  elist = (int *) NULL;
-  index = 0;  
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(edgefilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
-      terminatetetgen(1);
-    }
-    // Number of subsegments.
-    fprintf(outfile, "%ld\n", subsegs->items);
-  } else {
-    // Allocate memory for 'edgelist'.
-    out->edgelist = new int[subsegs->items * 2];
-    if (out->edgelist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-    out->numberofedges = subsegs->items;
-    elist = out->edgelist;
-  }
-
-  // Determine the first index (0 or 1).
-  firstindex = b->zeroindex ? 0 : in->firstnumber;
-  shift = 0; // Default no shiftment.
-  if ((in->firstnumber == 1) && (firstindex == 0)) {
-    shift = 1; // Shift the output indices by 1.
-  }
-
-  subsegs->traversalinit();
-  edgeloop.sh = shellfacetraverse(subsegs);
-  edgenumber = firstindex; // in->firstnumber;
-  while (edgeloop.sh != (shellface *) NULL) {
-    torg = sorg(edgeloop);
-    tdest = sdest(edgeloop);
-    if (out == (tetgenio *) NULL) {
-      fprintf(outfile, "%5d   %4d  %4d\n", edgenumber,
-              pointmark(torg) - shift, pointmark(tdest) - shift);
-    } else {
-      // Output three vertices of this face;
-      elist[index++] = pointmark(torg) - shift;
-      elist[index++] = pointmark(tdest) - shift;
-    }
-    edgenumber++;
-    edgeloop.sh = shellfacetraverse(subsegs);
-  }
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outneighbors()    Output tet neighbors to a .neigh file or a structure.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outneighbors(tetgenio* out)
-{
-  FILE *outfile;
-  char neighborfilename[FILENAMESIZE];
-  int *nlist;
-  int index;
-  triface tetloop, tetsym;
-  int neighbor1, neighbor2, neighbor3, neighbor4;
-  int firstindex;
-  int elementnumber;
-
-  if (out == (tetgenio *) NULL) {
-    strcpy(neighborfilename, b->outfilename);
-    strcat(neighborfilename, ".neigh");
-  }
-
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", neighborfilename);
-    } else {
-      printf("Writing neighbors.\n");
-    }
-  }
-
-  // Avoid compile warnings.
-  outfile = (FILE *) NULL;
-  nlist = (int *) NULL;
-  index = 0;
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(neighborfilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", neighborfilename);
-      terminatetetgen(1);
-    }
-    // Number of tetrahedra, four faces per tetrahedron.
-    fprintf(outfile, "%ld  %d\n", tetrahedrons->items, 4);
-  } else {
-    // Allocate memory for 'neighborlist'.
-    out->neighborlist = new int[tetrahedrons->items * 4];
-    if (out->neighborlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-    nlist = out->neighborlist;
-  }
-
-  // Determine the first index (0 or 1).
-  firstindex = b->zeroindex ? 0 : in->firstnumber;
-
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  elementnumber = firstindex; // in->firstnumber;
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    tetloop.loc = 2;
-    sym(tetloop, tetsym);
-    neighbor1 = * (int *) (tetsym.tet + elemmarkerindex);
-    tetloop.loc = 3;
-    sym(tetloop, tetsym);
-    neighbor2 = * (int *) (tetsym.tet + elemmarkerindex);
-    tetloop.loc = 1;
-    sym(tetloop, tetsym);
-    neighbor3 = * (int *) (tetsym.tet + elemmarkerindex);
-    tetloop.loc = 0;
-    sym(tetloop, tetsym);
-    neighbor4 = * (int *) (tetsym.tet + elemmarkerindex);
-    if (out == (tetgenio *) NULL) {
-      // Tetrahedra number, neighboring tetrahedron numbers.
-      fprintf(outfile, "%4d    %4d  %4d  %4d  %4d\n", elementnumber,
-              neighbor1, neighbor2, neighbor3, neighbor4);
-    } else {
-      nlist[index++] = neighbor1;
-      nlist[index++] = neighbor2;
-      nlist[index++] = neighbor3;
-      nlist[index++] = neighbor4;
-    }
-    tetloop.tet = tetrahedrontraverse();
-    elementnumber++;
-  }
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outvoronoi()    Output the Voronoi diagram to .v.node, .v.edge, v.face,   //
-//                 and .v.cell.                                              //
-//                                                                           //
-// The Voronoi diagram is the geometric dual of the Delaunay triangulation.  //
-// The Voronoi vertices are the circumcenters of Delaunay tetrahedra.  Each  //
-// Voronoi edge connects two Voronoi vertices at two sides of a common Dela- //
-// unay face. At a face of convex hull, it becomes a ray (goto the infinity).//
-// A Voronoi face is the convex hull of all Voronoi vertices around a common //
-// Delaunay edge. It is a closed polygon for any interal Delaunay edge. At a //
-// ridge, it is unbounded.  Each Voronoi cell is the convex hull of all Vor- //
-// onoi vertices around a common Delaunay vertex. It is a polytope for any   //
-// internal Delaunay vertex. It is an unbounded polyhedron for a Delaunay    //
-// vertex belonging to the convex hull.                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outvoronoi(tetgenio* out)
-{
-  FILE *outfile;
-  char outfilename[FILENAMESIZE];
-  tetgenio::voroedge *vedge;
-  tetgenio::vorofacet *vfacet;
-  list *tetlist, *ptlist;
-  triface tetloop, worktet, spintet;
-  point pt[4], ptloop, neipt;
-  REAL ccent[3], infvec[3], vec1[3], vec2[3], L;
-  long faces, edges;
-  int *tetfaceindexarray, *tetedgeindexarray;
-  int arraysize, *vertarray;
-  int vpointcount, vedgecount, vfacecount, tcount;
-  int index, shift;
-  int end1, end2;
-  int hitbdry, i, j, k;
-
-  // Output Voronoi vertices to .v.node file.
-  if (out == (tetgenio *) NULL) {
-    strcpy(outfilename, b->outfilename);
-    strcat(outfilename, ".v.node");
-  }
-
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", outfilename);
-    } else {
-      printf("Writing Voronoi vertices.\n");
-    }
-  }
-
-  // Determine the first index (0 or 1).
-  shift = (b->zeroindex ? 0 : in->firstnumber);
-  // The number of Delaunay faces (= the number of Voronoi edges).
-  faces = (4l * tetrahedrons->items + hullsize) / 2l;
-  // The number of Delaunay edges (= the number of Voronoi faces).
-  edges = points->items + faces - tetrahedrons->items - 1;
-  outfile = (FILE *) NULL; // Avoid compile warnings.
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(outfilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", outfilename);
-      terminatetetgen(1);
-    }
-    // Number of voronoi points, 3 dim, no attributes, no marker.
-    fprintf(outfile, "%ld  3  0  0\n", tetrahedrons->items);
-  } else {
-    // Allocate space for 'vpointlist'.
-    out->numberofvpoints = (int) tetrahedrons->items;
-    out->vpointlist = new REAL[out->numberofvpoints * 3];
-    if (out->vpointlist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-  }
-
-  // Loop the tetrahedronlist once, do the following: 
-  //   (1) Output Voronoi vertices (the circumcenter of the tetrahedron).
-  //   (2) Make a map from points-to-tetrahedra (for Voronoi cells).
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  vpointcount = 0;
-  index = 0;
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    // Calculate the circumcenter.
-    for (i = 0; i < 4; i++) {
-      pt[i] = (point) tetloop.tet[4 + i];
-      setpoint2tet(pt[i], encode(tetloop));
-    }
-    circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
-    if (out == (tetgenio *) NULL) {
-      fprintf(outfile, "%4d  %16.8e %16.8e %16.8e\n", vpointcount + shift,
-              ccent[0], ccent[1], ccent[2]);
-    } else {
-      out->vpointlist[index++] = ccent[0];
-      out->vpointlist[index++] = ccent[1];
-      out->vpointlist[index++] = ccent[2];
-    }
-    // Remember the index of this element.
-    * (int *) (tetloop.tet + elemmarkerindex) = vpointcount;
-    vpointcount++;
-    tetloop.tet = tetrahedrontraverse();
-  }
-  // Set the outside element marker.
-  * (int *) (dummytet + elemmarkerindex) = -1;
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-
-  // Output Voronoi edges to .v.edge file.
-  if (out == (tetgenio *) NULL) {
-    strcpy(outfilename, b->outfilename);
-    strcat(outfilename, ".v.edge");
-  }
-  
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", outfilename);
-    } else {
-      printf("Writing Voronoi edges.\n");
-    }
-  }
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(outfilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", outfilename);
-      terminatetetgen(1);
-    }
-    // Number of Voronoi edges, no marker.
-    fprintf(outfile, "%ld  0\n", faces);
-  } else {
-    // Allocate space for 'vpointlist'.
-    out->numberofedges = (int) faces;
-    out->vedgelist = new tetgenio::voroedge[out->numberofvedges];
-  }
-
-  // Loop the tetrahedronlist once, output the Voronoi edges. The index of
-  //   each Voronoi edge corresponding to the index of the Delaunay face.
-  //   The four faces' indices of each tetrahedron are saved in the list
-  //   'tetfaceindexarray', in the entry of i,  where i (0-based) is the
-  //   index of this tetrahedron (= vpointcount). 
-  tetfaceindexarray = new int[tetrahedrons->items * 4];  
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  vedgecount = 0;
-  index = 0;
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    // Count the number of Voronoi edges. Look at the four faces of each
-    //   tetrahedron. Count the face if the tetrahedron's pointer is
-    //   smaller than its neighbor's or the neighbor is outside.
-    end1 = * (int *) (tetloop.tet + elemmarkerindex);
-    for (i = 0; i < 4; i++) {
-      decode(tetloop.tet[i], worktet);
-      if ((worktet.tet == dummytet) || (tetloop.tet < worktet.tet)) {
-        if (out == (tetgenio *) NULL) {
-          fprintf(outfile, "%4d  %4d", vedgecount + shift, end1 + shift);
-        } else {
-          vedge = &(out->vedgelist[index++]);
-          vedge->v1 = end1 + shift;
-        }
-        end2 = * (int *) (worktet.tet + elemmarkerindex);
-        // Note that end2 may be -1 (worktet.tet is outside).
-        if (end2 == -1) {
-          // Calculate the out normal of this hull face.
-          worktet.tet = tetloop.tet;
-          worktet.loc = i;
-          worktet.ver = 1; // The CW edge ring.
-          pt[0] = org(worktet);
-          pt[1] = dest(worktet);
-          pt[2] = apex(worktet);
-          for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j];
-          for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j];
-          cross(vec1, vec2, infvec);
-          // Normalize it.
-          L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1]
-                   + infvec[2] * infvec[2]);
-          if (L > 0) for (j = 0; j < 3; j++) infvec[j] /= L;
-          if (out == (tetgenio *) NULL) {
-            fprintf(outfile, " -1");
-            fprintf(outfile, " %g %g %g\n", infvec[0], infvec[1], infvec[2]);
-          } else {
-            vedge->v2 = -1;
-            vedge->vnormal[0] = infvec[0];
-            vedge->vnormal[1] = infvec[1];
-            vedge->vnormal[2] = infvec[2];
-          }
-        } else {
-          if (out == (tetgenio *) NULL) {
-            fprintf(outfile, " %4d\n", end2 + shift);
-          } else {
-            vedge->v2 = end2 + shift;
-            vedge->vnormal[0] = 0.0;
-            vedge->vnormal[1] = 0.0;
-            vedge->vnormal[2] = 0.0;
-          }
-        }
-        // Save the face index in this tet and its neighbor if exists.
-        tetfaceindexarray[end1 * 4 + i] = vedgecount;
-        if (end2 != -1) {
-          tetfaceindexarray[end2 * 4 + worktet.loc] = vedgecount;
-        }
-        vedgecount++;
-      }
-    }
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-
-  // Output Voronoi faces to .v.face file.
-  if (out == (tetgenio *) NULL) {
-    strcpy(outfilename, b->outfilename);
-    strcat(outfilename, ".v.face");
-  }
-  
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", outfilename);
-    } else {
-      printf("Writing Voronoi faces.\n");
-    }
-  }
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(outfilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", outfilename);
-      terminatetetgen(1);
-    }
-    // Number of Voronoi faces.
-    fprintf(outfile, "%ld  0\n", edges);
-  } else {
-    out->numberofvfacets = edges;
-    out->vfacetlist = new tetgenio::vorofacet[out->numberofvfacets];
-    if (out->vfacetlist == (tetgenio::vorofacet *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-  }
-
-  // Loop the tetrahedronlist once, Output Voronoi facets. The index of each
-  //   Voronoi facet corresponding to the index of the Delaunay edge.  The
-  //   six edges' indices of each tetrahedron are saved in the list 'tetedge-
-  //   indexarray', in the entry of i,  where i (0-based) is the index of
-  //   this tetrahedron (= vpointcount). 
-  tetedgeindexarray = new int[tetrahedrons->items * 6];
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  vfacecount = 0;
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    // Count the number of Voronoi faces. Look at the six edges of each
-    //   tetrahedron. Count the edge only if the tetrahedron's pointer is
-    //   smaller than those of all other tetrahedra that share the edge.
-    worktet = tetloop;
-    for (i = 0; i < 6; i++) {
-      worktet.loc = edge2locver[i][0];
-      worktet.ver = edge2locver[i][1];
-      // Now count the number of tets surrounding this edge.
-      tcount = 1;
-      adjustedgering(worktet, CW);
-      spintet = worktet;
-      hitbdry = 0;
-      while (hitbdry < 2) {
-        if (fnextself(spintet)) {
-          if (apex(spintet) == apex(worktet)) break;
-          if (spintet.tet < worktet.tet) break;
-          tcount++;
-        } else {
-          hitbdry++;
-          if (hitbdry < 2) {
-            esym(worktet, spintet);
-            fnextself(spintet); // In the same tet.
-	  }
-        }
-      }
-      // Count this edge if no adjacent tets are smaller than this tet.
-      if (spintet.tet >= worktet.tet) {
-        // Get the two endpoints of this edge.
-        pt[0] = org(worktet);
-        pt[1] = dest(worktet);
-        end1 = pointmark(pt[0]) - in->firstnumber;
-        end2 = pointmark(pt[1]) - in->firstnumber;
-        if (out == (tetgenio *) NULL) {
-          fprintf(outfile, "%4d  %4d %4d  %-2d ", vfacecount + shift, 
-                  end1 + shift, end2 + shift, tcount + (hitbdry > 0));
-        } else {
-          vfacet = &(out->vfacetlist[vfacecount]);
-          vfacet->c1 = end1 + shift;
-          vfacet->c2 = end2 + shift;
-          vfacet->elist = new int[tcount + (hitbdry > 0) + 1];
-          vfacet->elist[0] = tcount + (hitbdry > 0);
-          index = 1;
-        }
-        // If hitbdry > 0, then spintet is a hull face.
-        if (hitbdry > 0) {
-          // The edge list starts with a ray.
-          vpointcount = * (int *) (spintet.tet + elemmarkerindex);
-          vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
-          if (out == (tetgenio *) NULL) {
-            fprintf(outfile, " %d", vedgecount + shift);
-          } else {
-            vfacet->elist[index++] = vedgecount + shift;
-          }
-          // Save this facet number in tet.
-          tetedgeindexarray[vpointcount * 6 + 
-            locver2edge[spintet.loc][spintet.ver]] = vfacecount;
-          esymself(spintet);
-          fnextself(spintet); // In the same tet.
-        }
-        // Output internal Voronoi edges.
-        for (j = 0; j < tcount; j++) {
-          vpointcount = * (int *) (spintet.tet + elemmarkerindex);
-          vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
-          if (out == (tetgenio *) NULL) {
-            fprintf(outfile, " %d", vedgecount + shift);
-          } else {
-            vfacet->elist[index++] = vedgecount + shift;
-          }
-          // Save this facet number in tet.
-          tetedgeindexarray[vpointcount * 6 + 
-            locver2edge[spintet.loc][spintet.ver]] = vfacecount;
-          fnextself(spintet);
-        }
-        if (out == (tetgenio *) NULL) {
-          fprintf(outfile, "\n");
-        }
-        vfacecount++;
-      }
-    } // if (i = 0; i < 6; i++)
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-
-  // Output Voronoi cells to .v.cell file.
-  if (out == (tetgenio *) NULL) {
-    strcpy(outfilename, b->outfilename);
-    strcat(outfilename, ".v.cell");
-  }
-  
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", outfilename);
-    } else {
-      printf("Writing Voronoi cells.\n");
-    }
-  }
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(outfilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", outfilename);
-      terminatetetgen(1);
-    }
-    // Number of Voronoi cells.
-    fprintf(outfile, "%ld\n", points->items);
-  } else {
-    out->numberofvcells = points->items;
-    out->vcelllist = new int*[out->numberofvcells];
-    if (out->vcelllist == (int **) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-  }
-
-  // Loop through point list, for each point, output a Voronoi cell.
-  tetlist = new list(sizeof(triface), NULL, 256);
-  ptlist = new list(sizeof(point *), NULL, 256);
-  points->traversalinit();
-  ptloop = pointtraverse();
-  vpointcount = 0;
-  while (ptloop != (point) NULL) {
-    decode(point2tet(ptloop), tetloop);
-    // assert(!isdead(&tetloop));
-    if (!isdead(&tetloop)) {
-      // Form the star of p.
-      tetlist->append(&tetloop);
-      formstarpolyhedron(ptloop, tetlist, ptlist, true);
-      tcount = ptlist->len();
-      if (out == (tetgenio *) NULL) {
-        fprintf(outfile, "%4d  %-2d ", vpointcount + shift, tcount);
-      } else {
-        arraysize = tcount;
-        vertarray = out->vcelllist[vpointcount];
-        vertarray = new int[arraysize + 1];
-        vertarray[0] = arraysize;
-        index = 1;
-      }
-      // List Voronoi facets bounding this cell.
-      for (i = 0; i < ptlist->len(); i++) {
-        neipt =  * (point *)(* ptlist)[i];
-        // Find a tet in tetlist having edge (ptloop, neipt) -- Very Slow.
-        for (j = 0; j < tetlist->len(); j++) {
-          tetloop = * (triface *)(* tetlist)[j];
-          for (k = 0; k < 6; k++) {
-            tetloop.loc = edge2locver[k][0];
-            tetloop.ver = edge2locver[k][1];
-            if (org(tetloop) == ptloop) {
-              if (dest(tetloop) == neipt) break;
-            } else if (org(tetloop) == neipt) {
-              if (dest(tetloop) == ptloop) break;
-            }
-          }
-          if (k < 6) break; // Found this edge.
-        }
-        assert(j < tetlist->len());
-        // k is the right edge number.        
-        end1 = * (int *) (tetloop.tet + elemmarkerindex);
-        vfacecount = tetedgeindexarray[end1 * 6 + k];
-        if (out == (tetgenio *) NULL) {
-          fprintf(outfile, " %d", vfacecount + shift);
-        } else {
-          vertarray[index++] = vfacecount + shift;
-        }
-      } // for (i = 0; i < ptlist->len(); i++) {
-      if (out == (tetgenio *) NULL) {
-        fprintf(outfile, "\n");
-      }
-      vpointcount++;
-    }
-    tetlist->clear();
-    ptlist->clear();
-    ptloop = pointtraverse();
-  }
-  delete tetlist;
-  delete ptlist;
-  delete [] tetfaceindexarray;
-  delete [] tetedgeindexarray;
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outpbcnodes()    Output pbc node pairs to a .pbc file or a structure.     //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outpbcnodes(tetgenio* out)
-{ 
-  FILE *outfile;
-  char pbcfilename[FILENAMESIZE];
-  list *ptpairlist;
-  tetgenio::pbcgroup *pgi, *pgo;
-  pbcdata *pd;
-  face faceloop;
-  face checkseg, symseg;
-  point *ptpair, pa, pb;
-  enum locateresult loc;
-  REAL sympt[3], d1, d2;
-  int *worklist;
-  int firstindex, shift;
-  int index, idx;
-  int i, j, k, l;
-
-  if (out == (tetgenio *) NULL) {
-    strcpy(pbcfilename, b->outfilename);
-    strcat(pbcfilename, ".pbc");
-  }
-
-  if (!b->quiet) {
-    if (out == (tetgenio *) NULL) {
-      printf("Writing %s.\n", pbcfilename);
-    } else {
-      printf("Writing pbc nodes.\n");
-    }
-  }
-
-  // Avoid compilation warnings.
-  outfile = (FILE *) NULL;
-  pgo = (tetgenio::pbcgroup *) NULL;
-  index = 0;
-
-  if (out == (tetgenio *) NULL) {
-    outfile = fopen(pbcfilename, "w");
-    if (outfile == (FILE *) NULL) {
-      printf("File I/O Error:  Cannot create file %s.\n", pbcfilename);
-      terminatetetgen(1);
-    }
-    // Number of pbc groups.
-    fprintf(outfile, "# number of PBCs.\n");
-    fprintf(outfile, "%d\n\n", in->numberofpbcgroups);
-  } else {
-    out->numberofpbcgroups = in->numberofpbcgroups;
-    // Allocate memory for 'out->pbcgrouplist'.
-    out->pbcgrouplist = new tetgenio::pbcgroup[in->numberofpbcgroups];
-    // (Next line was a bug, reported by Murry Nigel). 
-    if (out->pbcgrouplist == (tetgenio::pbcgroup *) NULL) {
-      printf("Error:  Out of memory.\n");
-      terminatetetgen(1);
-    }
-  }
-
-  ptpairlist = new list(2 * sizeof(point *), NULL, 256);
-  worklist = new int[points->items + 1];
-  for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
-
-  // Determine the first index (0 or 1).
-  firstindex = b->zeroindex ? 0 : in->firstnumber;
-  shift = 0; // Default no shiftment.
-  if ((in->firstnumber == 1) && (firstindex == 0)) {
-    shift = 1; // Shift the output indices by 1.
-  }
-
-  for (i = 0; i < in->numberofpbcgroups; i++) {
-    // Group i.
-    pgi = &(in->pbcgrouplist[i]);
-    if (out == (tetgenio *) NULL) {
-      fprintf(outfile, "# PBC %d\n", in->firstnumber + i);
-      // Output facet markers.
-      fprintf(outfile, "%d  %d\n", pgi->fmark1, pgi->fmark2);
-      // Output transformation matrix.
-      fprintf(outfile, "[\n");
-      for (j = 0; j < 4; j++) {
-        fprintf(outfile, "  %.12g %.12g %.12g %.12g\n", pgi->transmat[j][0],
-                pgi->transmat[j][1], pgi->transmat[j][2], pgi->transmat[j][3]);
-      }
-      fprintf(outfile, "]\n");
-    } else {
-      pgo = &(out->pbcgrouplist[i]);
-      // Copy data from pgi to pgo.
-      pgo->fmark1 = pgi->fmark1;
-      pgo->fmark2 = pgi->fmark2;
-      for (j = 0; j < 4; j++) {
-        for (k = 0; k < 4; k++) pgo->transmat[j][k] = pgi->transmat[j][k];
-      }
-    }
-
-    // Find the point pairs of group i.
-    subfaces->traversalinit();
-    faceloop.sh = shellfacetraverse(subfaces);
-    while (faceloop.sh != (shellface *) NULL) {
-      if (shellpbcgroup(faceloop) == i) {
-        // It is in group i. Operate on it if it has pgi->fmark1.
-        idx = shellmark(faceloop) - 1;
-        if (in->facetmarkerlist[idx] == pgi->fmark1) {
-          // Loop three edges of the subface.
-          for (j = 0; j < 3; j++) {
-            sspivot(faceloop, checkseg);
-            // Loop two vertices of the edge.
-            for (k = 0; k < 2; k++) {
-              if (k == 0) pa = sorg(faceloop);
-              else pa = sdest(faceloop);
-              if (worklist[pointmark(pa)] == 0) {
-                pb = (point) NULL;
-                if (checkseg.sh != dummysh) {
-                  // pa is on a segment. Find pb.
-                  // Find the incident pbcgroup of checkseg.
-                  idx = shellmark(checkseg) - 1;
-                  for (l = idx2segpglist[idx]; l < idx2segpglist[idx + 1];
-                       l++) {
-                    pd = (pbcdata *)(* segpbcgrouptable)[segpglist[l]];
-                    if (((pd->fmark[0] == pgi->fmark1) &&
-                         (pd->fmark[1] == pgi->fmark2)) ||
-                        ((pd->fmark[0] == pgi->fmark2) &&
-                         (pd->fmark[1] == pgi->fmark1))) break;
-                  }
-#ifdef SELF_CHECK
-                  assert(l < idx2segpglist[idx + 1]);
-#endif
-                  loc = getsegpbcsympoint(pa, &checkseg, sympt, &symseg,
-                                          segpglist[l]);
-                  if (loc != ONVERTEX) {
-                    // Not found a match point! It may be caused by the
-                    //   pair of input vertices don't have enough digits.
-                    //   Choose a near vertex.
-                    d1 = distance(sympt, sorg(symseg));
-                    d2 = distance(sympt, sdest(symseg));
-                    if (d1 > d2) sesymself(symseg);
-                  }
-                  pb = sorg(symseg);
-                } else {
-                  // Operate on pa if it is inside the facet.
-                  if (pointtype(pa) == FREESUBVERTEX) {
-                    pb = point2pbcpt(pa);
-                  }
-                }
-                if (pb != (point) NULL) {
-                  // Add the pair (pa, pb) into list. 
-                  ptpair = (point *) ptpairlist->append(NULL);
-                  ptpair[0] = pa;
-                  ptpair[1] = pb;
-                  // Mark pa (avoid to operate on it later).
-                  worklist[pointmark(pa)] = 1;
-                }
-              }
-            }
-            // Get the next edge.
-            senextself(faceloop);
-          }
-        }
-      }
-      faceloop.sh = shellfacetraverse(subfaces);
-    }
-
-    // Output the list of pbc points.
-    if (out == (tetgenio *) NULL) {
-      fprintf(outfile, "%d\n", ptpairlist->len());
-    } else {
-      pgo->numberofpointpairs = ptpairlist->len();
-      pgo->pointpairlist = new int[pgo->numberofpointpairs * 2];
-      index = 0;
-    }
-    for (j = 0; j < ptpairlist->len(); j++) {
-      ptpair = (point *)(* ptpairlist)[j];
-      pa = ptpair[0];
-      pb = ptpair[1];
-      if (out == (tetgenio *) NULL) {
-        fprintf(outfile, "  %4d %4d\n", pointmark(pa) - shift,
-                pointmark(pb) - shift);
-      } else {
-        pgo->pointpairlist[index++] = pointmark(pa) - shift;
-        pgo->pointpairlist[index++] = pointmark(pb) - shift;
-      }
-      // Unmark pa.
-      worklist[pointmark(pa)] = 0;
-    }
-    if (out == (tetgenio *) NULL) {
-      fprintf(outfile, "\n");
-    }
-    ptpairlist->clear();
-  }
-
-  delete [] worklist;
-  delete ptpairlist;
-
-  if (out == (tetgenio *) NULL) {
-    fprintf(outfile, "# Generated by %s\n", b->commandline);
-    fclose(outfile);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outsmesh()    Write surface mesh to a .smesh file, which can be read and  //
-//               tetrahedralized by TetGen.                                  //
-//                                                                           //
-// You can specify a filename (without suffix) in 'smfilename'. If you don't //
-// supply a filename (let smfilename be NULL), the default name stored in    //
-// 'tetgenbehavior' will be used.                                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outsmesh(char* smfilename)
-{
-  FILE *outfile;
-  char nodfilename[FILENAMESIZE];
-  char smefilename[FILENAMESIZE];
-  face faceloop;
-  point p1, p2, p3;
-  int firstindex, shift;
-  int bmark;
-  int faceid, marker;
-  int i;
-
-  if (smfilename != (char *) NULL && smfilename[0] != '\0') {
-    strcpy(smefilename, smfilename);
-  } else if (b->outfilename[0] != '\0') {
-    strcpy(smefilename, b->outfilename);
-  } else {
-    strcpy(smefilename, "unnamed");
-  }
-  strcpy(nodfilename, smefilename);
-  strcat(smefilename, ".smesh");
-  strcat(nodfilename, ".node");
-
-  if (!b->quiet) {
-    printf("Writing %s.\n", smefilename);
-  }
-  outfile = fopen(smefilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", smefilename);
-    return;
-  }
-
-  // Determine the first index (0 or 1).
-  firstindex = b->zeroindex ? 0 : in->firstnumber;
-  shift = 0; // Default no shiftment.
-  if ((in->firstnumber == 1) && (firstindex == 0)) {
-    shift = 1; // Shift the output indices by 1.
-  }
-
-  fprintf(outfile, "# %s.  TetGen's input file.\n", smefilename);
-  fprintf(outfile, "\n# part 1: node list.\n");
-  fprintf(outfile, "0  3  0  0  # nodes are found in %s.\n", nodfilename);
-
-  marker = 0; // avoid compile warning.
-  bmark = !b->nobound && in->facetmarkerlist;  
-
-  fprintf(outfile, "\n# part 2: facet list.\n");
-  // Number of facets, boundary marker.
-  fprintf(outfile, "%ld  %d\n", subfaces->items, bmark);
-  
-  subfaces->traversalinit();
-  faceloop.sh = shellfacetraverse(subfaces);
-  while (faceloop.sh != (shellface *) NULL) {
-    p1 = sorg(faceloop);
-    p2 = sdest(faceloop);
-    p3 = sapex(faceloop);
-    if (bmark) {
-      faceid = shellmark(faceloop) - 1;
-      if (faceid >= 0) { 
-        marker = in->facetmarkerlist[faceid];
-      } else {
-        marker = 0; // This subface must be added manually later.
-      }
-    }
-    fprintf(outfile, "3    %4d  %4d  %4d", pointmark(p1) - shift,
-            pointmark(p2) - shift, pointmark(p3) - shift);
-    if (bmark) {
-      fprintf(outfile, "    %d", marker);
-    }
-    fprintf(outfile, "\n");
-    faceloop.sh = shellfacetraverse(subfaces);
-  }
-
-  // Copy input holelist.
-  fprintf(outfile, "\n# part 3: hole list.\n");
-  fprintf(outfile, "%d\n", in->numberofholes);
-  for (i = 0; i < in->numberofholes; i++) {
-    fprintf(outfile, "%d  %g  %g  %g\n", i + in->firstnumber,
-            in->holelist[i * 3], in->holelist[i * 3 + 1],
-            in->holelist[i * 3 + 2]);
-  }
-
-  // Copy input regionlist.
-  fprintf(outfile, "\n# part 4: region list.\n");
-  fprintf(outfile, "%d\n", in->numberofregions);
-  for (i = 0; i < in->numberofregions; i++) {
-    fprintf(outfile, "%d  %g  %g  %g  %d  %g\n", i + in->firstnumber,
-            in->regionlist[i * 5], in->regionlist[i * 5 + 1],
-            in->regionlist[i * 5 + 2], (int) in->regionlist[i * 5 + 3],
-            in->regionlist[i * 5 + 4]);
-  }
-
-  fprintf(outfile, "# Generated by %s\n", b->commandline);
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outmesh2medit()    Write mesh to a .mesh file, which can be read and      //
-//                    rendered by Medit (a free mesh viewer from INRIA).     //
-//                                                                           //
-// You can specify a filename (without suffix) in 'mfilename'.  If you don't //
-// supply a filename (let mfilename be NULL), the default name stored in     //
-// 'tetgenbehavior' will be used. The output file will have the suffix .mesh.//
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outmesh2medit(char* mfilename)
-{
-  FILE *outfile;
-  char mefilename[FILENAMESIZE];
-  tetrahedron* tetptr;
-  triface tface, tsymface;
-  face segloop, checkmark;
-  point ptloop, p1, p2, p3, p4;
-  long faces;
-  int pointnumber;
-  int i;
-
-  if (mfilename != (char *) NULL && mfilename[0] != '\0') {
-    strcpy(mefilename, mfilename);
-  } else if (b->outfilename[0] != '\0') {
-    strcpy(mefilename, b->outfilename);
-  } else {
-    strcpy(mefilename, "unnamed");
-  }
-  strcat(mefilename, ".mesh");
-
-  if (!b->quiet) {
-    printf("Writing %s.\n", mefilename);
-  }
-  outfile = fopen(mefilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("File I/O Error:  Cannot create file %s.\n", mefilename);
-    return;
-  }
-
-  fprintf(outfile, "MeshVersionFormatted 1\n");
-  fprintf(outfile, "\n");
-  fprintf(outfile, "Dimension\n");
-  fprintf(outfile, "3\n");
-  fprintf(outfile, "\n");
-
-  fprintf(outfile, "\n# Set of mesh vertices\n");
-  fprintf(outfile, "Vertices\n");
-  fprintf(outfile, "%ld\n", points->items);
-
-  points->traversalinit();
-  ptloop = pointtraverse();
-  pointnumber = 1;                        // Medit need start number form 1.
-  while (ptloop != (point) NULL) {
-    // Point coordinates.
-    fprintf(outfile, "%.17g  %.17g  %.17g", ptloop[0], ptloop[1], ptloop[2]);
-    if (in->numberofpointattributes > 0) {
-      // Write an attribute, ignore others if more than one.
-      fprintf(outfile, "  %.17g\n", ptloop[3]);
-    } else {
-      fprintf(outfile, "    0\n");
-    }
-    setpointmark(ptloop, pointnumber);
-    ptloop = pointtraverse();
-    pointnumber++;
-  }
-
-  // Compute the number of edges.
-  faces = (4l * tetrahedrons->items + hullsize) / 2l;
-
-  fprintf(outfile, "\n# Set of Triangles\n");
-  fprintf(outfile, "Triangles\n");
-  fprintf(outfile, "%ld\n", faces);
-
-  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.
-  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) {
-        p1 = org (tface);
-        p2 = dest(tface);
-        p3 = apex(tface);
-        fprintf(outfile, "%5d  %5d  %5d",
-                pointmark(p1), pointmark(p2), pointmark(p3));
-        fprintf(outfile, "    0\n");
-      }
-    }
-    tface.tet = tetrahedrontraverse();
-  }
-
-  fprintf(outfile, "\n# Set of Tetrahedra\n");
-  fprintf(outfile, "Tetrahedra\n");
-  fprintf(outfile, "%ld\n", tetrahedrons->items);
-
-  tetrahedrons->traversalinit();
-  tetptr = tetrahedrontraverse();
-  while (tetptr != (tetrahedron *) NULL) {
-    p1 = (point) tetptr[4];
-    p2 = (point) tetptr[5];
-    p3 = (point) tetptr[6];
-    p4 = (point) tetptr[7];
-    fprintf(outfile, "%5d  %5d  %5d  %5d",
-            pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
-    if (in->numberoftetrahedronattributes > 0) {
-      fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
-    } else {
-      fprintf(outfile, "  0");
-    }
-    fprintf(outfile, "\n");
-    tetptr = tetrahedrontraverse();
-  }
-
-  fprintf(outfile, "\nCorners\n");
-  fprintf(outfile, "%d\n", in->numberofpoints);
-
-  for (i = 0; i < in->numberofpoints; i++) {
-    fprintf(outfile, "%4d\n", i + 1);
-  }
-
-  if (b->useshelles) {
-    fprintf(outfile, "\nEdges\n");
-    fprintf(outfile, "%ld\n", subsegs->items);
-
-    subsegs->traversalinit();
-    segloop.sh = shellfacetraverse(subsegs);
-    while (segloop.sh != (shellface *) NULL) {
-      p1 = sorg(segloop);
-      p2 = sdest(segloop);
-      fprintf(outfile, "%5d  %5d", pointmark(p1), pointmark(p2));
-      fprintf(outfile, "    0\n");
-      segloop.sh = shellfacetraverse(subsegs);
-    }
-  }
-
-  fprintf(outfile, "\nEnd\n");
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outmesh2gid()    Write mesh to a .ele.msh file and a .face.msh file,      //
-//                  which can be imported and rendered by Gid.               //
-//                                                                           //
-// You can specify a filename (without suffix) in 'gfilename'.  If you don't //
-// supply a filename (let gfilename be NULL), the default name stored in     //
-// 'tetgenbehavior' will be used. The suffixes (.ele.msh and .face.msh) will //
-// be automatically added.                                                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outmesh2gid(char* gfilename)
-{
-  FILE *outfile;
-  char gidfilename[FILENAMESIZE];
-  tetrahedron* tetptr;
-  triface tface, tsymface;
-  face sface;
-  point ptloop, p1, p2, p3, p4;
-  int pointnumber;
-  int elementnumber;
-
-  if (gfilename != (char *) NULL && gfilename[0] != '\0') {
-    strcpy(gidfilename, gfilename);
-  } else if (b->outfilename[0] != '\0') {
-    strcpy(gidfilename, b->outfilename);
-  } else {
-    strcpy(gidfilename, "unnamed");
-  }
-  strcat(gidfilename, ".ele.msh");
-
-  if (!b->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();
-  ptloop = pointtraverse();
-  pointnumber = 1;                        // Gid need start number form 1.
-  while (ptloop != (point) NULL) {
-    // Point coordinates.
-    fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
-            ptloop[0], ptloop[1], ptloop[2]);
-    if (in->numberofpointattributes > 0) {
-      // Write an attribute, ignore others if more than one.
-      fprintf(outfile, "  %.17g", ptloop[3]);
-    }
-    fprintf(outfile, "\n");
-    setpointmark(ptloop, pointnumber);
-    ptloop = pointtraverse();
-    pointnumber++;
-  }
-
-  fprintf(outfile, "end coordinates\n");
-  fprintf(outfile, "elements\n");
-
-  tetrahedrons->traversalinit();
-  tetptr = tetrahedrontraverse();
-  elementnumber = 1;
-  while (tetptr != (tetrahedron *) NULL) {
-    p1 = (point) tetptr[4];
-    p2 = (point) tetptr[5];
-    p3 = (point) tetptr[6];
-    p4 = (point) tetptr[7];
-    fprintf(outfile, "%5d  %5d %5d %5d %5d", elementnumber,
-            pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
-    if (in->numberoftetrahedronattributes > 0) {
-      fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
-    } 
-    fprintf(outfile, "\n");
-    tetptr = tetrahedrontraverse();
-    elementnumber++;
-  }
-
-  fprintf(outfile, "end elements\n");
-  fclose(outfile);
-
-  if (gfilename != (char *) NULL && gfilename[0] != '\0') {
-    strcpy(gidfilename, gfilename);
-  } else if (b->outfilename[0] != '\0') {
-    strcpy(gidfilename, b->outfilename);
-  } else {
-    strcpy(gidfilename, "unnamed");
-  }
-  strcat(gidfilename, ".face.msh");
-
-  if (!b->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();
-  ptloop = pointtraverse();
-  pointnumber = 1;                        // Gid need start number form 1.
-  while (ptloop != (point) NULL) {
-    // Point coordinates.
-    fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
-            ptloop[0], ptloop[1], ptloop[2]);
-    if (in->numberofpointattributes > 0) {
-      // Write an attribute, ignore others if more than one.
-      fprintf(outfile, "  %.17g", ptloop[3]);
-    }
-    fprintf(outfile, "\n");
-    setpointmark(ptloop, pointnumber);
-    ptloop = pointtraverse();
-    pointnumber++;
-  }
-
-  fprintf(outfile, "end coordinates\n");
-  fprintf(outfile, "elements\n");
-
-  tetrahedrons->traversalinit();
-  tface.tet = tetrahedrontraverse();
-  elementnumber = 1;
-  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)) {
-        p1 = org(tface);
-        p2 = dest(tface);
-        p3 = apex(tface);
-        if (tsymface.tet == dummytet) {
-          // It's a hull face, output it.
-          fprintf(outfile, "%5d   %d  %d  %d\n", elementnumber,
-                  pointmark(p1), pointmark(p2), pointmark(p3));
-          elementnumber++;
-        } else if (b->useshelles) {
-          // Only output it if it's a subface.
-          tspivot(tface, sface);
-          if (sface.sh != dummysh) {
-            fprintf(outfile, "%5d   %d  %d  %d\n", elementnumber,
-                    pointmark(p1), pointmark(p2), pointmark(p3));
-            elementnumber++;
-          }
-        }
-      }
-    }
-    tface.tet = tetrahedrontraverse();
-  }
-
-  fprintf(outfile, "end elements\n");
-  fclose(outfile);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// outmesh2off()    Write the mesh to an .off file.                          //
-//                                                                           //
-// .off, the Object File Format, is one of the popular file formats from the //
-// Geometry Center's Geomview package (http://www.geomview.org).             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::outmesh2off(char* ofilename)
-{
-  FILE *outfile;
-  char offfilename[FILENAMESIZE];
-  triface tface, tsymface;
-  point ptloop, p1, p2, p3;
-  long faces;
-  int shift;
-
-  if (ofilename != (char *) NULL && ofilename[0] != '\0') {
-    strcpy(offfilename, ofilename);
-  } else if (b->outfilename[0] != '\0') {
-    strcpy(offfilename, b->outfilename);
-  } else {
-    strcpy(offfilename, "unnamed");
-  }
-  strcat(offfilename, ".off");
-
-  if (!b->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);
-    return;
-  }
-
-  // Calculate the number of triangular faces in the tetrahedral mesh.
-  faces = (4l * tetrahedrons->items + hullsize) / 2l;
-
-  // 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();
-  ptloop = pointtraverse();
-  while (ptloop != (point) NULL) {
-    fprintf(outfile, " %.17g  %.17g  %.17g\n",ptloop[0], ptloop[1], ptloop[2]);
-    ptloop = pointtraverse();
-  }
-
-  // OFF always use zero as the first index.
-  shift = in->firstnumber == 1 ? 1 : 0;
-
-  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.
-  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)) {
-        p1 = org(tface);
-        p2 = dest(tface);
-        p3 = apex(tface);
-        // Face number, indices of three vertexs.
-        fprintf(outfile, "3   %4d  %4d  %4d\n", pointmark(p1) - shift,
-                pointmark(p2) - shift, pointmark(p3) - shift);
-      }
-    }
-    tface.tet = tetrahedrontraverse();
-  }
-
-  fprintf(outfile, "# Generated by %s\n", b->commandline);
-  fclose(outfile);
-}
-
-//
-// End of I/O rouitnes
-//
-
-//
-// Begin of user interaction routines
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// internalerror()    Ask the user to send me the defective product.  Exit.  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::internalerror()
-{
-  printf("  Please report this bug to sihang@mail.berlios.de. 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");
-  terminatetetgen(2);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checkmesh()    Test the mesh for topological consistency.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::checkmesh()
-{
-  triface tetraloop;
-  triface oppotet, oppooppotet;
-  point tetorg, tetdest, tetapex, tetoppo;
-  REAL oritest;
-  int horrors;
-
-  if (!b->quiet) {
-    printf("  Checking consistency of mesh...\n");
-  }
-
-  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++) {
-      tetorg = org(tetraloop);
-      tetdest = dest(tetraloop);
-      tetapex = apex(tetraloop);
-      tetoppo = oppo(tetraloop);
-      if (tetraloop.loc == 0) {             // Only test for inversion once.
-        oritest = orient3d(tetorg, tetdest, tetapex, tetoppo);
-        if (oritest >= 0.0) {
-          printf("  !! !! %s ", oritest > 0.0 ? "Inverted" : "Degenerated");
-          printtet(&tetraloop);
-          printf("  orient3d = %.17g.\n", oritest);
-          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 ");
-          printtet(&tetraloop);
-          printf("    Second (nonreciprocating) ");
-          printtet(&oppotet);
-          horrors++;
-        }
-      }
-    }
-    tetraloop.tet = tetrahedrontraverse();
-  }
-  if (horrors == 0) {
-    if (!b->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);
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checkshells()       Test the boundary mesh for topological consistency.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::checkshells()
-{
-  triface oppotet, oppooppotet, testtet; 
-  face shloop, segloop, spin;
-  face testsh, testseg, testshsh;
-  point shorg, shdest, segorg, segdest;
-  REAL checksign;
-  bool same;
-  int horrors;
-  int i;
-
-  if (!b->quiet) {
-    printf("  Checking consistency of the mesh boundary...\n");
-  }
-  horrors = 0;
-
-  // Run through the list of subfaces, checking each one.
-  subfaces->traversalinit();
-  shloop.sh = shellfacetraverse(subfaces);
-  while (shloop.sh != (shellface *) NULL) {
-    // Check two connected tetrahedra if they exist.
-    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: ");
-        printtet(&oppotet);
-        printf("    Subface: ");
-        printsh(&shloop);
-        horrors++;
-      }
-      if (oppo(oppotet) != (point) NULL) {
-        adjustedgering(oppotet, CCW);
-        checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
-                             oppo(oppotet));
-        if (checksign >= 0.0) {
-          printf("  !! !! Wrong subface orientation.\n");
-          printf("    Subface: ");
-          printsh(&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: ");
-        printtet(&oppooppotet);
-        printf("    Subface: ");
-        printsh(&shloop);
-        horrors++;
-      }
-      if (oppotet.tet != dummytet) {
-        sym(oppotet, testtet);
-        if (testtet.tet != oppooppotet.tet) {
-          printf("  !! !! Wrong tetra-subface-tetra connection.\n");
-          printf("    Tetra 1: ");
-          printtet(&oppotet);
-          printf("    Subface: ");
-          printsh(&shloop);
-          printf("    Tetra 2: ");
-          printtet(&oppooppotet);
-          horrors++;
-        }
-      }
-      if (oppo(oppooppotet) != (point) NULL) {
-        adjustedgering(oppooppotet, CCW);
-        checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
-                             oppo(oppooppotet));
-        if (checksign >= 0.0) {
-          printf("  !! !! Wrong subface orientation.\n");
-          printf("    Subface: ");
-          printsh(&shloop);
-          horrors++;
-        }
-      }
-    }
-    // Check connection between subfaces.
-    shloop.shver = 0;
-    for (i = 0; i < 3; i++) {
-      shorg = sorg(shloop);
-      shdest = sdest(shloop);
-      sspivot(shloop, testseg);
-      if (testseg.sh != dummysh) {
-        segorg = sorg(testseg);
-        segdest = sdest(testseg);
-        same = ((shorg == segorg) && (shdest == segdest)) 
-	    || ((shorg == segdest) && (shdest == segorg));
-        if (!same) {
-          printf("  !! !! Wrong subface-subsegment connection.\n");
-          printf("    Subface: ");
-          printsh(&shloop);
-          printf("    Subsegment: ");
-          printsh(&testseg);
-          horrors++;
-        } 
-      } 
-      spivot(shloop, testsh);
-      if (testsh.sh != dummysh) {
-        segorg = sorg(testsh);
-        segdest = sdest(testsh);
-        same = ((shorg == segorg) && (shdest == segdest)) 
-	    || ((shorg == segdest) && (shdest == segorg));
-        if (!same) {
-          printf("  !! !! Wrong subface-subface connection.\n");
-          printf("    Subface 1: ");
-          printsh(&shloop);
-          printf("    Subface 2: ");
-          printsh(&testsh);
-          horrors++;
-        }
-        spivot(testsh, testshsh);
-        shorg = sorg(testshsh);
-        shdest = sdest(testshsh);
-        same = ((shorg == segorg) && (shdest == segdest)) 
-	    || ((shorg == segdest) && (shdest == segorg));
-        if (!same) {
-          printf("  !! !! Wrong subface-subface connection.\n");
-          printf("    Subface 1: ");
-          printsh(&testsh);
-          printf("    Subface 2: ");
-          printsh(&testshsh);
-          horrors++;
-        }
-        if (testseg.sh == dummysh) {
-          if (testshsh.sh != shloop.sh) {
-            printf("  !! !! Wrong subface-subface connection.\n");
-            printf("    Subface 1: ");
-            printsh(&shloop);
-            printf("    Subface 2: ");
-            printsh(&testsh);
-            horrors++;
-          }
-        } 
-      }
-      senextself(shloop);
-    }
-    shloop.sh = shellfacetraverse(subfaces);
-  }
-
-  // Run through the list of subsegs, checking each one.
-  subsegs->traversalinit();
-  segloop.sh = shellfacetraverse(subsegs);
-  while (segloop.sh != (shellface *) NULL) {
-    segorg = sorg(segloop);
-    segdest = sdest(segloop);
-    spivot(segloop, testsh);
-    if (testsh.sh == dummysh) {
-      printf("  !! !! Wrong subsegment-subface connection.\n");
-      printf("    Subsegment: ");
-      printsh(&segloop);
-      horrors++;
-      segloop.sh = shellfacetraverse(subsegs);
-      continue;
-    }
-    shorg = sorg(testsh);
-    shdest = sdest(testsh);
-    same = ((shorg == segorg) && (shdest == segdest)) 
-        || ((shorg == segdest) && (shdest == segorg));
-    if (!same) {
-      printf("  !! !! Wrong subsegment-subface connection.\n");
-      printf("    Subsegment : ");
-      printsh(&segloop);
-      printf("    Subface : ");
-      printsh(&testsh);
-      horrors++;
-      segloop.sh = shellfacetraverse(subsegs);
-      continue;
-    }
-    // Check the connection of face loop around this subsegment.
-    spin = testsh;
-    i = 0;
-    do {
-      spivotself(spin);
-      shorg = sorg(spin);
-      shdest = sdest(spin);
-      same = ((shorg == segorg) && (shdest == segdest)) 
-          || ((shorg == segdest) && (shdest == segorg));
-      if (!same) {
-        printf("  !! !! Wrong subsegment-subface connection.\n");
-        printf("    Subsegment : ");
-        printsh(&segloop);
-        printf("    Subface : ");
-        printsh(&testsh);
-        horrors++;
-        break;
-      }
-      i++;
-    } while (spin.sh != testsh.sh && i < 1000);
-    if (i >= 1000) {
-      printf("  !! !! Wrong subsegment-subface connection.\n");
-      printf("    Subsegment : ");
-      printsh(&segloop);
-      horrors++;
-    }
-    segloop.sh = shellfacetraverse(subsegs);
-  }
-  if (horrors == 0) {
-    if (!b->quiet) {
-      printf("  Mesh boundaries connected correctly.\n");
-    }
-  } else {
-    printf("  !! !! !! !! %d boundary connection viewed with horror.\n",
-           horrors);
-    return;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checkdelaunay()    Ensure that the mesh is constrained Delaunay.          //
-//                                                                           //
-// If 'flipqueue' is not NULL, non-locally Delaunay faces are saved in it.   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::checkdelaunay(REAL eps, queue* flipqueue)
-{
-  triface tetraloop;
-  triface oppotet;
-  face opposhelle;
-  point tetorg, tetdest, tetapex, tetoppo;
-  point oppooppo;
-  enum fliptype fc;
-  REAL sign;
-  int shouldbedelaunay;
-  int horrors;
-
-  if (!b->quiet) {
-    printf("  Checking Delaunay property of the mesh...\n");
-  }
-  horrors = 0;
-  // Run through the list of triangles, 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++) {
-      tetorg = org(tetraloop);
-      tetdest = dest(tetraloop);
-      tetapex = apex(tetraloop);
-      tetoppo = oppo(tetraloop);
-      sym(tetraloop, oppotet);
-      oppooppo = oppo(oppotet);
-      // Only do testif there is an adjoining tetrahedron whose pointer is
-      //   larger (to ensure that each pair isn't tested twice).
-      shouldbedelaunay = (oppotet.tet != dummytet)
-                          && (tetoppo != (point) NULL)
-                          && (oppooppo != (point) NULL)
-                          && (tetraloop.tet < oppotet.tet);
-      if (checksubfaces && shouldbedelaunay) {
-        // If a shell face separates the tetrahedra, then the face is
-        //   constrained, so no local Delaunay test should be done.
-        tspivot(tetraloop, opposhelle);
-        if (opposhelle.sh != dummysh){
-          shouldbedelaunay = 0;
-        }
-      }
-      if (shouldbedelaunay) {
-        sign = insphere(tetdest, tetorg, tetapex, tetoppo, oppooppo);
-        if ((sign > 0.0) && (eps > 0.0)) {
-          if (iscospheric(tetdest, tetorg, tetapex, tetoppo, oppooppo, sign,
-                          eps)) sign = 0.0;
-        }
-        if (sign > 0.0) {
-          if (flipqueue) {
-            enqueueflipface(tetraloop, flipqueue);
-          } else {
-            printf("  !! Non-locally Delaunay face (%d, %d, %d) ",
-                   pointmark(tetorg), pointmark(tetdest), pointmark(tetapex));
-            fc = categorizeface(tetraloop);
-            switch (fc) {
-            case T23: printf("\"T23\""); break;
-            case T32: printf("\"T32\""); break;
-            case T22: printf("\"T22\""); break;
-            case T44: printf("\"T44\""); break;
-            case N32: printf("\"N32\""); break;
-            case N40: printf("\"N40\""); break;
-            case FORBIDDENFACE:printf("\"FORBIDDENFACE\""); break;
-            case FORBIDDENEDGE:printf("\"FORBIDDENEDGE\""); break;
-            }
-            printf("\n");
-          }
-          horrors++;
-        }
-      }
-    }
-    tetraloop.tet = tetrahedrontraverse();
-  }
-  if (flipqueue == (queue *) NULL) {
-    if (horrors == 0) {
-      if (!b->quiet) {
-        printf("  The mesh is %s.\n",
-               checksubfaces ? "constrained Delaunay" : "Delaunay");
-      }
-    } else {
-      printf("  !! !! !! !! %d obscenities viewed with horror.\n", horrors);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// checkconforming()    Ensure that the mesh is conforming Delaunay.         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::checkconforming()
-{
-  face segloop, shloop;
-  int encsubsegs, encsubfaces;
-
-  if (!b->quiet) {
-    printf("  Checking conforming Delaunay property of mesh...\n");
-  }
-  encsubsegs = encsubfaces = 0;
-  // Run through the list of subsegments, check each one.
-  subsegs->traversalinit();
-  segloop.sh = shellfacetraverse(subsegs);
-  while (segloop.sh != (shellface *) NULL) {
-    if (checkseg4encroach(&segloop, NULL, NULL, false)) {
-      printf("  !! !! Non-conforming subsegment: (%d, %d)\n",
-             pointmark(sorg(segloop)), pointmark(sdest(segloop)));
-      encsubsegs++;
-    }
-    segloop.sh = shellfacetraverse(subsegs);
-  }
-  // Run through the list of subfaces, check each one.
-  subfaces->traversalinit();
-  shloop.sh = shellfacetraverse(subfaces);
-  while (shloop.sh != (shellface *) NULL) {
-    if (checksub4encroach(&shloop, NULL, false)) {
-      printf("  !! !! Non-conforming subface: (%d, %d, %d)\n",
-             pointmark(sorg(shloop)), pointmark(sdest(shloop)),
-             pointmark(sapex(shloop)));
-      encsubfaces++;
-    }
-    shloop.sh = shellfacetraverse(subfaces);
-  }
-  if (encsubsegs == 0 && encsubfaces == 0) {
-    if (!b->quiet) {
-      printf("  The mesh is conforming Delaunay.\n");
-    }
-  } else {
-    if (encsubsegs > 0) {
-      printf("  !! !! %d subsegments are non-conforming.\n", encsubsegs);
-    }
-    if (encsubfaces > 0) {
-      printf("  !! !! %d subfaces are non-conforming.\n", encsubfaces);
-    }
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// algorithmicstatistics()    Print statistics about the mesh algorithms.    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef SELF_CHECK
-
-void tetgenmesh::algorithmicstatistics()
-{
-  /*
-  printf("Algorithmic statistics:\n\n");
-  printf("  Point location millisecond:  %g\n", (REAL) tloctime * 1e+3);
-  printf("  Flip millisecond:  %g\n", (REAL) tfliptime * 1e+3);
-  if (b->plc || b->refine) {
-    printf("  Number of facet above points calculations: %ld\n", abovecount);
-  }
-  if (b->plc) {
-    printf("  Segment split rules: R1 %ld, R2 %ld, R3 %ld\n", r1count, r2count,
-           r3count);
-  }
-  if (b->quality) {
-    printf("  Bowyer-Watson insertions: seg %ld, sub %ld, vol %ld.\n",
-           bowatsegcount, bowatsubcount, bowatvolcount);
-    printf("  Bowyer-Watson corrections: seg %ld, sub %ld, vol %ld\n",
-           updsegcount, updsubcount, updvolcount);
-    printf("  Bowyer-Watson failures: seg %ld, sub %ld, vol %ld\n",
-           failsegcount, failsubcount, failvolcount);
-    printf("  Number of repair flips: %ld.\n", repairflipcount);
-    printf("  Number of circumcenters outside Bowat-cav.: %ld.\n",
-           outbowatcircumcount);
-    if (b->conformdel) {
-      printf("  Segment split rules: R2 %ld, R3 %ld\n", r2count, r3count);
-      printf("  Number of CDT enforcement points: %ld.\n", cdtenforcesegpts);
-    }
-    printf("  Number of Rejections: seg %ld, sub %ld, tet %ld.\n", rejsegpts,
-           rejsubpts, rejtetpts);
-    if (b->optlevel) {
-      printf(
-      "  Optimization flips: f32 %ld, f44 %ld, f56 %ld, f68 %ld, fnm %ld.\n",
-             optcount[3], optcount[4], optcount[5], optcount[6], optcount[9]);
-      printf("  Optimization segment deletions: %ld.\n", optcount[1]);
-    }
-  }
-  printf("\n");
-  */
-}
-
-#endif // #ifdef SELF_CHECK
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// qualitystatistics()    Print statistics about the quality of the mesh.    //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::qualitystatistics()
-{
-  triface tetloop, neightet;
-  point p[4];
-  char sbuf[128];
-  REAL radiusratiotable[12];
-  REAL aspectratiotable[12];
-  REAL A[4][4], rhs[4], D;
-  REAL V[6][3], N[4][3], H[4]; // edge-vectors, face-normals, face-heights.
-  REAL edgelength[6], alldihed[6], faceangle[3];
-  REAL shortest, longest;
-  REAL smallestvolume, biggestvolume;
-  REAL smallestdiangle, biggestdiangle;
-  REAL smallestfaangle, biggestfaangle;
-  REAL tetvol, minaltitude;
-  REAL cirradius, minheightinv; // insradius;
-  REAL shortlen, longlen;
-  REAL tetaspect, tetradius;
-  REAL smalldiangle, bigdiangle;
-  REAL smallfaangle, bigfaangle;
-  int radiustable[12];
-  int aspecttable[16];
-  int dihedangletable[18];
-  int faceangletable[18];
-  int indx[4];
-  int radiusindex;
-  int aspectindex;
-  int tendegree;
-  int i, j;
-
-  printf("Mesh quality statistics:\n\n");
-
-  // Avoid compile warnings.
-  shortlen = longlen = 0.0;
-  smalldiangle = bigdiangle = 0.0;
-
-  radiusratiotable[0]  =    0.707;    radiusratiotable[1]  =     1.0;
-  radiusratiotable[2]  =      1.1;    radiusratiotable[3]  =     1.2;
-  radiusratiotable[4]  =      1.4;    radiusratiotable[5]  =     1.6;
-  radiusratiotable[6]  =      1.8;    radiusratiotable[7]  =     2.0;
-  radiusratiotable[8]  =      2.5;    radiusratiotable[9]  =     3.0;
-  radiusratiotable[10] =     10.0;    radiusratiotable[11] =     0.0;
-
-  aspectratiotable[0]  =      1.5;    aspectratiotable[1]  =     2.0;
-  aspectratiotable[2]  =      2.5;    aspectratiotable[3]  =     3.0;
-  aspectratiotable[4]  =      4.0;    aspectratiotable[5]  =     6.0;
-  aspectratiotable[6]  =     10.0;    aspectratiotable[7]  =    15.0;
-  aspectratiotable[8]  =     25.0;    aspectratiotable[9]  =    50.0;
-  aspectratiotable[10] =    100.0;    aspectratiotable[11] =     0.0;
-  
-  for (i = 0; i < 12; i++) radiustable[i] = 0;
-  for (i = 0; i < 12; i++) aspecttable[i] = 0;
-  for (i = 0; i < 18; i++) dihedangletable[i] = 0;
-  for (i = 0; i < 18; i++) faceangletable[i] = 0;
-
-  minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
-  minaltitude = minaltitude * minaltitude;
-  shortest = minaltitude;
-  longest = 0.0;
-  smallestvolume = minaltitude;
-  biggestvolume = 0.0;
-  smallestdiangle = smallestfaangle = 180.0;
-  biggestdiangle = biggestfaangle = 0.0;
-
-  // Loop all elements, calculate quality parameters for each element.
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    
-    // Get four vertices: p0, p1, p2, p3.
-    for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i];
-    // Set the edge vectors: V[0], ..., V[5]
-    for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i]; // V[0]: p3->p0.
-    for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i]; // V[1]: p3->p1.
-    for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i]; // V[2]: p3->p2.
-    for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i]; // V[3]: p0->p1.
-    for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i]; // V[4]: p1->p2.
-    for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i]; // V[5]: p2->p0.
-    // Set the matrix A = [V[0], V[1], V[2]]^T.
-    for (j = 0; j < 3; j++) {
-      for (i = 0; i < 3; i++) A[j][i] = V[j][i];
-    }
-    // Decompose A just once.
-    lu_decmp(A, 3, indx, &D, 0);   
-    // Get the tet volume.
-    tetvol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
-    // Get the three faces normals.
-    for (j = 0; j < 3; j++) {
-      for (i = 0; i < 3; i++) rhs[i] = 0.0;
-      rhs[j] = 1.0;  // Positive means the inside direction
-      lu_solve(A, 3, indx, rhs, 0);
-      for (i = 0; i < 3; i++) N[j][i] = rhs[i];
-    }
-    // Get the fourth face normal by summing up the first three.
-    for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
-    // Get the radius of the circumsphere.
-    for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]);
-    lu_solve(A, 3, indx, rhs, 0);
-    cirradius = sqrt(dot(rhs, rhs));
-    // Normalize the face normals.
-    for (i = 0; i < 4; i++) {
-      // H[i] is the inverse of height of its corresponding face.
-      H[i] = sqrt(dot(N[i], N[i]));
-      for (j = 0; j < 3; j++) N[i][j] /= H[i];
-    }
-    // Get the radius of the inscribed sphere.
-    // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]);
-    // Get the biggest H[i] (corresponding to the smallest height).
-    minheightinv = H[0];
-    for (i = 1; i < 3; i++) {
-      if (H[i] > minheightinv) minheightinv = H[i];
-    }
-    // Get the squares of the edge lengthes.
-    for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
-    // Get the dihedrals (in degree) at each edges.
-    j = 0;
-    for (i = 1; i < 4; i++) {
-      alldihed[j] = -dot(N[0], N[i]); // Edge cd, bd, bc.
-      if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
-      else if (alldihed[j] > 1.0) alldihed[j] = 1;
-      alldihed[j] = acos(alldihed[j]) / PI * 180.0;
-      j++;
-    }
-    for (i = 2; i < 4; i++) {
-      alldihed[j] = -dot(N[1], N[i]); // Edge ad, ac.
-      if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
-      else if (alldihed[j] > 1.0) alldihed[j] = 1;
-      alldihed[j] = acos(alldihed[j]) / PI * 180.0;
-      j++;
-    }
-    alldihed[j] = -dot(N[2], N[3]); // Edge ab.
-    if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
-    else if (alldihed[j] > 1.0) alldihed[j] = 1;
-    alldihed[j] = acos(alldihed[j]) / PI * 180.0;
-    
-    // Calculate the longest and shortest edge length.
-    for (i = 0; i < 6; i++) {
-      if (i == 0) {
-        shortlen = longlen = edgelength[i];
-      } else {
-        shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen;
-        longlen  = edgelength[i] > longlen  ? edgelength[i] : longlen;
-      }
-      if (edgelength[i] > longest) {
-        longest = edgelength[i];
-      } 
-      if (edgelength[i] < shortest) {
-        shortest = edgelength[i];
-      }
-    }
-    
-    // Calculate the largest and smallest volume.
-    if (tetvol < smallestvolume) {
-      smallestvolume = tetvol;
-    } 
-    if (tetvol > biggestvolume) {
-      biggestvolume = tetvol;
-    }
-    
-    // Calculate the largest and smallest dihedral angles.
-    for (i = 0; i < 6; i++) {
-      if (i == 0) {
-        smalldiangle = bigdiangle = alldihed[i];
-      } else {
-        smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle;
-        bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle;
-      }
-      if (alldihed[i] < smallestdiangle) {
-        smallestdiangle = alldihed[i];
-      } 
-      if (alldihed[i] > biggestdiangle) {
-        biggestdiangle = alldihed[i];
-      }
-    }
-    // Accumulate the corresponding number in the dihedral angle histogram.
-    if (smalldiangle < 5.0) {
-      tendegree = 0;
-    } else if (smalldiangle >= 5.0 && smalldiangle < 10.0) {
-      tendegree = 1;
-    } else if (smalldiangle >= 80.0 && smalldiangle < 110.0) {
-      tendegree = 9; // Angles between 80 to 110 degree are in one entry.
-    } else {
-      tendegree = (int) (smalldiangle / 10.);
-      if (smalldiangle < 80.0) {
-        tendegree++;  // In the left column.
-      } else {
-        tendegree--;  // In the right column.
-      }
-    }
-    dihedangletable[tendegree]++;
-    if (bigdiangle >= 80.0 && bigdiangle < 110.0) {
-      tendegree = 9; // Angles between 80 to 110 degree are in one entry.
-    } else if (bigdiangle >= 170.0 && bigdiangle < 175.0) {
-      tendegree = 16;
-    } else if (bigdiangle >= 175.0) {
-      tendegree = 17;
-    } else {
-      tendegree = (int) (bigdiangle / 10.);
-      if (bigdiangle < 80.0) {
-        tendegree++;  // In the left column.
-      } else {
-        tendegree--;  // In the right column.
-      }
-    }
-    dihedangletable[tendegree]++;
-
-    // Calulate the largest and smallest face angles.
-    tetloop.ver = 0;
-    for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
-      sym(tetloop, neightet);
-      // Only do the calulation once for a face.
-      if ((neightet.tet == dummytet) || (tetloop.tet < neightet.tet)) {
-        p[0] = org(tetloop);
-        p[1] = dest(tetloop);
-        p[2] = apex(tetloop);
-        faceangle[0] = interiorangle(p[0], p[1], p[2], NULL);
-        faceangle[1] = interiorangle(p[1], p[2], p[0], NULL);
-        faceangle[2] = PI - (faceangle[0] + faceangle[1]);
-        // Translate angles into degrees.
-        for (i = 0; i < 3; i++) {
-          faceangle[i] = (faceangle[i] * 180.0) / PI;
-        }
-        // Calculate the largest and smallest face angles.
-        for (i = 0; i < 3; i++) {
-          if (i == 0) {
-            smallfaangle = bigfaangle = faceangle[i];
-          } else {
-            smallfaangle = faceangle[i] < smallfaangle ? 
-              faceangle[i] : smallfaangle;
-            bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle;
-          }
-          if (faceangle[i] < smallestfaangle) {
-            smallestfaangle = faceangle[i];
-          } 
-          if (faceangle[i] > biggestfaangle) {
-            biggestfaangle = faceangle[i];
-          }
-        }
-        tendegree = (int) (smallfaangle / 10.);
-        faceangletable[tendegree]++;
-        tendegree = (int) (bigfaangle / 10.);
-        faceangletable[tendegree]++;
-      }
-    }
-
-    // Calculate aspect ratio and radius-edge ratio for this element.
-    tetradius = cirradius / sqrt(shortlen);
-    // tetaspect = sqrt(longlen) / (2.0 * insradius);
-    tetaspect = sqrt(longlen) * minheightinv;
-    aspectindex = 0;
-    while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) {
-      aspectindex++;
-    }
-    aspecttable[aspectindex]++;
-    radiusindex = 0;
-    while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) {
-      radiusindex++;
-    }
-    radiustable[radiusindex]++;
-
-    tetloop.tet = tetrahedrontraverse();
-  }
-
-  shortest = sqrt(shortest);
-  longest = sqrt(longest);
-  minaltitude = sqrt(minaltitude);
-
-  printf("  Smallest volume: %16.5g   |  Largest volume: %16.5g\n",
-         smallestvolume, biggestvolume);
-  printf("  Shortest edge:   %16.5g   |  Longest edge:   %16.5g\n",
-         shortest, longest);
-  sprintf(sbuf, "%.17g", biggestfaangle);
-  if (strlen(sbuf) > 8) {
-    sbuf[8] = '\0';
-  }
-  printf("  Smallest facangle: %14.5g   |  Largest facangle:       %s\n",
-         smallestfaangle, sbuf);
-  sprintf(sbuf, "%.17g", biggestdiangle);
-  if (strlen(sbuf) > 8) {
-    sbuf[8] = '\0';
-  }
-  printf("  Smallest dihedral: %14.5g   |  Largest dihedral:       %s\n\n",
-         smallestdiangle, sbuf);
-
-  /*
-  printf("  Radius-edge ratio histogram:\n");
-  printf("         < %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
-         radiusratiotable[0], radiustable[0], radiusratiotable[5],
-         radiusratiotable[6], radiustable[6]);
-  for (i = 1; i < 5; i++) {
-    printf("  %6.6g - %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
-           radiusratiotable[i - 1], radiusratiotable[i], radiustable[i],
-           radiusratiotable[i + 5], radiusratiotable[i + 6],
-           radiustable[i + 6]);
-  }
-  printf("  %6.6g - %-6.6g    :  %8d      | %6.6g -            :  %8d\n",
-         radiusratiotable[4], radiusratiotable[5], radiustable[5],
-         radiusratiotable[10], radiustable[11]);
-  printf("  (A tetrahedron's radius-edge ratio is its radius of ");
-  printf("circumsphere divided\n");
-  printf("    by its shortest edge length)\n\n");
-  */
-
-  printf("  Aspect ratio histogram:\n");
-  printf("         < %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
-         aspectratiotable[0], aspecttable[0], aspectratiotable[5],
-         aspectratiotable[6], aspecttable[6]);
-  for (i = 1; i < 5; i++) {
-    printf("  %6.6g - %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
-           aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i],
-           aspectratiotable[i + 5], aspectratiotable[i + 6],
-           aspecttable[i + 6]);
-  }
-  printf("  %6.6g - %-6.6g    :  %8d      | %6.6g -            :  %8d\n",
-         aspectratiotable[4], aspectratiotable[5], aspecttable[5],
-         aspectratiotable[10], aspecttable[11]);
-  printf("  (A tetrahedron's aspect ratio is its longest edge length");
-  printf(" divided by its\n");
-  printf("    smallest side height)\n\n");
-
-  printf("  Face angle histogram:\n");
-  for (i = 0; i < 9; i++) {
-    printf("    %3d - %3d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
-           i * 10, i * 10 + 10, faceangletable[i],
-           i * 10 + 90, i * 10 + 100, faceangletable[i + 9]);
-  }
-  if (minfaceang != PI) {
-    printf("  Minimum input face angle is %g (degree).\n",
-           minfaceang / PI * 180.0);
-  }
-  printf("\n");
-
-  printf("  Dihedral angle histogram:\n");
-  // Print the three two rows:
-  printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
-         0, 5, dihedangletable[0], 80, 110, dihedangletable[9]);
-  printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
-         5, 10, dihedangletable[1], 110, 120, dihedangletable[10]);
-  // Print the third to seventh rows.
-  for (i = 2; i < 7; i++) {
-    printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
-           (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i],
-           (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]);
-  }
-  // Print the last two rows.
-  printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
-         60, 70, dihedangletable[7], 170, 175, dihedangletable[16]);
-  printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
-         70, 80, dihedangletable[8], 175, 180, dihedangletable[17]);
-  if (minfacetdihed != PI) {
-    printf("  Minimum input facet dihedral angle is %g (degree).\n",
-           minfacetdihed / PI * 180.0);
-  }
-  printf("\n");
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// statistics()    Print all sorts of cool facts.                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::statistics()
-{
-  printf("\nStatistics:\n\n");
-  printf("  Input points: %d\n", in->numberofpoints + jettisoninverts);
-  if (b->refine) {
-    printf("  Input tetrahedra: %d\n", in->numberoftetrahedra);
-  }
-  if (b->plc) {
-    printf("  Input facets: %d\n", in->numberoffacets);
-    printf("  Input segments: %ld\n", insegments);
-    printf("  Input holes: %d\n", in->numberofholes);
-    printf("  Input regions: %d\n", in->numberofregions);
-  }
-
-  printf("\n  Mesh points: %ld\n", points->items);
-  printf("  Mesh tetrahedra: %ld\n", tetrahedrons->items);
-  if (b->plc || b->refine) {
-    printf("  Mesh triangles: %ld\n", (4l*tetrahedrons->items+hullsize)/2l);
-  }
-  if (b->plc || b->refine) {
-    printf("  Mesh subfaces: %ld\n", subfaces->items);
-    printf("  Mesh subsegments: %ld\n\n", subsegs->items);
-  } else {
-    printf("  Convex hull triangles: %ld\n\n", hullsize);
-  }
-  if (b->verbose > 0) {
-    qualitystatistics();
-    unsigned long totalmeshbytes;
-    printf("Memory allocation statistics:\n\n");
-    printf("  Maximum number of vertices: %ld\n", points->maxitems);
-    totalmeshbytes = points->maxitems * points->itembytes;
-    printf("  Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems);
-    totalmeshbytes += tetrahedrons->maxitems * tetrahedrons->itembytes;
-    if (subfaces != (memorypool *) NULL) {
-      printf("  Maximum number of subfaces: %ld\n", subfaces->maxitems);
-      totalmeshbytes += subfaces->maxitems * subfaces->itembytes;
-    }
-    if (subsegs != (memorypool *) NULL) {
-      printf("  Maximum number of segments: %ld\n", subsegs->maxitems);
-      totalmeshbytes += subsegs->maxitems * subsegs->itembytes;
-    }
-    printf("  Approximate heap memory used by the mesh (K bytes): %g\n\n",
-           (double) totalmeshbytes / 1024.0);
-#ifdef SELF_CHECK
-    algorithmicstatistics();
-#endif
-  }
-}
-
-//
-// End of user interaction routines
-//
-
-//
-// Begin of constructor and destructor of tetgenmesh
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// ~tetgenmesh()    Deallocte memory occupied by a tetgenmesh object.        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::~tetgenmesh()
-{
-  bgm = (tetgenmesh *) NULL;
-  in = (tetgenio *) NULL;
-  b = (tetgenbehavior *) NULL;
-
-  if (tetrahedrons != (memorypool *) NULL) {
-    delete tetrahedrons;
-  }
-  if (subfaces != (memorypool *) NULL) {
-    delete subfaces;
-  }
-  if (subsegs != (memorypool *) NULL) {
-    delete subsegs;
-  }
-  if (points != (memorypool *) NULL) {
-    delete points;
-  }
-  if (dummytetbase != (tetrahedron *) NULL) {
-    delete [] dummytetbase;
-  }
-  if (dummyshbase != (shellface *) NULL) {
-    delete [] dummyshbase;
-  }
-  if (facetabovepointarray != (point *) NULL) {
-    delete [] facetabovepointarray;
-  }
-  if (highordertable != (point *) NULL) {
-    delete [] highordertable;
-  }
-  if (subpbcgrouptable != (pbcdata *) NULL) {
-    delete [] subpbcgrouptable;
-  }
-  if (segpbcgrouptable != (list *) NULL) {
-    delete segpbcgrouptable;
-    delete [] idx2segpglist;
-    delete [] segpglist;
-  }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetgenmesh()    Initialize a tetgenmesh object.                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-tetgenmesh::tetgenmesh()
-{
-  bgm = (tetgenmesh *) NULL;
-  in = (tetgenio *) NULL;
-  b = (tetgenbehavior *) NULL;
-
-  tetrahedrons = (memorypool *) NULL;
-  subfaces = (memorypool *) NULL;
-  subsegs = (memorypool *) NULL;
-  points = (memorypool *) NULL;
-  badsubsegs = (memorypool *) NULL;
-  badsubfaces = (memorypool *) NULL;
-  badtetrahedrons = (memorypool *) NULL;
-  flipstackers = (memorypool *) NULL;
-
-  dummytet = (tetrahedron *) NULL;
-  dummytetbase = (tetrahedron *) NULL;
-  dummysh = (shellface *) NULL;
-  dummyshbase = (shellface *) NULL;
-
-  facetabovepointarray = (point *) NULL;
-  abovepoint = (point) NULL;
-  highordertable = (point *) NULL;
-  subpbcgrouptable = (pbcdata *) NULL;
-  segpbcgrouptable = (list *) NULL;
-  idx2segpglist = (int *) NULL;
-  segpglist = (int *) NULL;
-
-  xmax = xmin = ymax = ymin = zmax = zmin = 0.0; 
-  longest = 0.0;
-  hullsize = 0l;
-  insegments = 0l;
-  pointmtrindex = 0;
-  pointmarkindex = 0;
-  point2simindex = 0;
-  point2pbcptindex = 0;
-  highorderindex = 0;
-  elemattribindex = 0;
-  volumeboundindex = 0;
-  shmarkindex = 0;
-  areaboundindex = 0;
-  checksubfaces = 0;
-  checksubsegs = 0;
-  checkpbcs = 0;
-  varconstraint = 0;
-  nonconvex = 0;
-  dupverts = 0;
-  unuverts = 0;
-  relverts = 0;
-  suprelverts = 0;
-  collapverts = 0;
-  unsupverts = 0;
-  jettisoninverts = 0;
-  symbolic = 1;
-  samples = 0l;
-  randomseed = 1l;
-  macheps = 0.0;
-  minfaceang = minfacetdihed = PI;
-  maxcavfaces = maxcavverts = 0;
-  expcavcount = 0;
-  abovecount = 0l;
-  bowatvolcount = bowatsubcount = bowatsegcount = 0l;
-  updvolcount = updsubcount = updsegcount = 0l;
-  repairflipcount = 0l;
-  outbowatcircumcount = 0l;
-  failvolcount = failsubcount = failsegcount = 0l;
-  r1count = r2count = r3count = 0l;
-  cdtenforcesegpts = 0l;
-  rejsegpts = rejsubpts = rejtetpts = 0l;
-  flip23s = flip32s = flip22s = flip44s = 0l;
-  tloctime = tfliptime = 0.0;
-}
-
-//
-// End of constructor and destructor of tetgenmesh
-//
-
-//
-// End of class 'tetgenmesh' implementation.
-//
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetrahedralize()    The interface for users using TetGen library to       //
-//                     generate tetrahedral meshes with all features.        //
-//                                                                           //
-// 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 vertices from a file and either                                //
-//   - tetrahedralize them (no -r), or                                       //
-//   - read an old mesh from files and reconstruct it (-r).                  //
-// - Insert the PLC segments and facets (-p).                                //
-// - Read the holes (-p), regional attributes (-pA), and regional volume     //
-//   constraints (-pa).  Carve the holes and concavities, and spread the     //
-//   regional attributes and volume constraints.                             //
-// - Enforce the constraints on minimum quality bound (-q) and maximum       //
-//   volume (-a). Also enforce the conforming Delaunay property (-q and -a). //
-// - Promote the mesh's linear tetrahedra to higher order elements (-o).     //
-// - Write the output files and print the statistics.                        //
-// - Check the consistency and Delaunay property of the mesh (-C).           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
-  tetgenio *addin, tetgenio *bgmin)
-{
-  tetgenmesh m;
-  // Variables for timing the performance of TetGen (defined in time.h).
-  clock_t tv[14];
-
-  tv[0] = clock();
- 
-  m.b = b;
-  m.in = in;
-  m.macheps = exactinit();
-  m.steinerleft = b->steiner;
-  if (b->metric) {
-    m.bgm = new tetgenmesh();
-    m.bgm->b = b;
-    m.bgm->in = bgmin;
-    m.bgm->macheps = exactinit();
-  }
-  m.initializepools();
-  m.transfernodes();
-
-  tv[1] = clock();
-
-  if (b->refine) {
-    m.reconstructmesh();
-  } else {
-    m.delaunizevertices();
-  }
-
-  tv[2] = clock();
-
-  if (!b->quiet) {
-    if (b->refine) {
-      printf("Mesh reconstruction seconds:");
-    } else {
-      printf("Delaunay seconds:");
-    }
-    printf("  %g\n", (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
-  }
-
-  if (b->metric) {
-    if (bgmin != (tetgenio *) NULL) {
-      m.bgm->initializepools();
-      m.bgm->transfernodes();
-      m.bgm->reconstructmesh();
-    } else {
-      m.bgm->in = in;
-      m.bgm->initializepools();
-      m.duplicatebgmesh();
-    }
-  }
-
-  tv[3] = clock();
-
-  if (!b->quiet) {
-    if (b->metric) {
-      printf("Background mesh reconstruct seconds:  %g\n",
-             (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
-
-  if (b->useshelles && !b->refine) {
-    m.meshsurface();
-    if (b->diagnose != 1) {
-      m.markacutevertices(89.0);
-      m.incrperturbvertices(b->epsilon);
-      m.delaunizesegments();
-      if (m.checkpbcs) {
-        long oldnum;
-        do {
-          oldnum = m.points->items;
-          m.incrperturbvertices(b->epsilon);
-          if (m.points->items > oldnum) {
-            oldnum = m.points->items;
-            m.delaunizesegments();
-          }
-        } while (oldnum < m.points->items);
-      }
-      m.constrainedfacets();
-    } else {
-      m.detectinterfaces();
-    }
-  }
-
-  tv[4] = clock();
-
-  if (!b->quiet) {
-    if (b->useshelles && !b->refine) {
-      if (b->diagnose != 1) {
-        printf("Segment and facet ");
-      } else {
-        printf("Intersection "); 
-      }
-      printf("seconds:  %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
-
-  if (b->plc && !(b->diagnose == 1)) {
-    m.carveholes();
-  }
-
-  tv[5] = clock();
-
-  if (!b->quiet) {
-    if (b->plc && !(b->diagnose == 1)) {
-      printf("Hole seconds:  %g\n", (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
-
-  if ((b->plc || b->refine) && !(b->diagnose == 1)) {
-    m.optimizemesh(false); 
-  }
-
-  tv[6] = clock();
-
-  if (!b->quiet) {
-    if ((b->plc || b->refine) && !(b->diagnose == 1)) {
-      printf("Repair seconds:  %g\n", (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
-
-  if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
-    m.removesteiners(false);
-  }
-
-  tv[7] = clock();
-
-  if (!b->quiet) {
-    if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
-      printf("Steiner removal seconds:  %g\n",
-             (tv[7] - tv[6]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
-
-  if (b->insertaddpoints && (addin != (tetgenio *) NULL)) {
-    if (addin->numberofpoints > 0) {
-      m.insertconstrainedpoints(addin); 
-    }
-  }
-
-  tv[8] = clock();
-
-  if (!b->quiet) {
-    if ((b->plc || b->refine) && (b->insertaddpoints)) {
-      printf("Constrained points seconds:  %g\n", 
-             (tv[8] - tv[7]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
-
-  if (b->metric) {
-    m.interpolatesizemap();
-  }
-
-  tv[9] = clock();
-
-  if (!b->quiet) {
-    if (b->metric) {
-      printf("Size interpolating seconds:  %g\n",
-             (tv[9] - tv[8]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
-
-  if (b->coarse) {
-    m.removesteiners(true);
-  }
-
-  tv[10] = clock();
-
-  if (!b->quiet) {
-    if (b->coarse) {
-      printf("Mesh coarsening seconds:  %g\n",
-             (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
-
-  if (b->quality) {
-    m.enforcequality();
-  }
-
-  tv[11] = clock();
-
-  if (!b->quiet) {
-    if (b->quality) {
-      printf("Quality seconds:  %g\n",
-             (tv[11] - tv[10]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
-
-  if (b->quality && (b->optlevel > 0)) {
-    m.optimizemesh(true);
-  }
-
-  tv[12] = clock();
-
-  if (!b->quiet) {
-    if (b->quality && (b->optlevel > 0)) {
-      printf("Optimize seconds:  %g\n",
-             (tv[12] - tv[11]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
-
-  if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0)
-      || (b->refine && (in->numberofcorners == 10)))) {
-    m.jettisonnodes();
-  }
-
-  if (b->order > 1) {
-    m.highorder();
-  }
-
-  if (!b->quiet) {
-    printf("\n");
-  }
-
-  if (out != (tetgenio *) NULL) {
-    out->firstnumber = in->firstnumber;
-    out->mesh_dim = in->mesh_dim;
-  }
-
-  if (b->nonodewritten || b->noiterationnum) {
-    if (!b->quiet) {
-      printf("NOT writing a .node file.\n");
-    }
-  } else {
-    if (b->diagnose == 1) {
-      if (m.subfaces->items > 0l) {
-        m.outnodes(out);  // Only output when self-intersecting faces exist.
-      }
-    } else {
-      m.outnodes(out);
-      if (b->quality || b->metric) {
-        // m.outmetrics(out);
-      }
-    }
-  }
-
-  if (b->noelewritten) {
-    if (!b->quiet) {
-      printf("NOT writing an .ele file.\n");
-    }
-  } else {
-    if (!(b->diagnose == 1)) {
-      if (m.tetrahedrons->items > 0l) {
-        m.outelements(out);
-      }
-    }
-  }
-
-  if (b->nofacewritten) {
-    if (!b->quiet) {
-      printf("NOT writing an .face file.\n");
-    }
-  } else {
-    if (b->facesout) {
-      if (m.tetrahedrons->items > 0l) {
-        m.outfaces(out);  // Output all faces.
-      }
-    } else {
-      if (b->diagnose == 1) {
-        if (m.subfaces->items > 0l) {
-          m.outsubfaces(out); // Only output self-intersecting faces.
-        }
-      } else if (b->plc || b->refine) {
-        if (m.subfaces->items > 0l) {
-          m.outsubfaces(out); // Output boundary faces.
-        }
-      } else {
-        if (m.tetrahedrons->items > 0l) {
-          m.outhullfaces(out); // Output convex hull faces.
-        }
-      }
-    }
-  }
-
-  if (m.checkpbcs) {
-    m.outpbcnodes(out);
-  }
-
-  if (b->edgesout) {
-    if (b->edgesout > 1) {
-      m.outedges(out); // -ee, output all mesh edges. 
-    } else {
-      m.outsubsegments(out); // -e, only output subsegments.
-    }
-  }
-
-  if (!out && b->plc && 
-      ((b->object == tetgenbehavior::OFF) ||
-       (b->object == tetgenbehavior::PLY) ||
-       (b->object == tetgenbehavior::STL))) {
-    m.outsmesh(b->outfilename);
-  }
-
-  if (!out && b->meditview) {
-    m.outmesh2medit(b->outfilename); 
-  }
-
-  if (!out && b->gidview) {
-    m.outmesh2gid(b->outfilename); 
-  }
-
-  if (!out && b->geomview) {
-    m.outmesh2off(b->outfilename); 
-  }
-
-  if (b->neighout) {
-    m.outneighbors(out);
-  }
-
-  if (b->voroout) {
-    m.outvoronoi(out);
-  }
-
-  tv[13] = clock();
-
-  if (!b->quiet) {
-    printf("\nOutput seconds:  %g\n",
-           (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
-    printf("Total running seconds:  %g\n",
-           (tv[13] - tv[0]) / (REAL) CLOCKS_PER_SEC);
-  }
-
-  if (b->docheck) {
-    m.checkmesh();
-    if (m.checksubfaces) {
-      m.checkshells();
-    }
-    if (b->docheck > 1) {
-      m.checkdelaunay(0.0, NULL);
-      if (b->docheck > 2) {
-        if (b->quality || b->refine) {
-          m.checkconforming();
-        }
-      }
-    }
-  }
-
-  if (!b->quiet) {
-    m.statistics();
-  }
-
-  if (b->metric) {
-    delete m.bgm;
-  }
-}
-
-#ifndef TETLIBRARY
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// main()    The entrance for running TetGen from command line.              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-int main(int argc, char *argv[])
-
-#else // with TETLIBRARY
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// tetrahedralize()    The entrance for calling TetGen from another program. //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
-  tetgenio *addin, tetgenio *bgmin)
-
-#endif // not TETLIBRARY
-
-{
-  tetgenbehavior b;
-
-#ifndef TETLIBRARY
-
-  tetgenio in, addin, bgmin;
-  
-  if (!b.parse_commandline(argc, argv)) {
-    terminatetetgen(1);
-  }
-  if (b.refine) {
-    if (!in.load_tetmesh(b.infilename)) {
-      terminatetetgen(1);
-    }
-  } else {
-    if (!in.load_plc(b.infilename, (int) b.object)) {
-      terminatetetgen(1);
-    }
-  }
-  if (b.insertaddpoints) {
-    if (!addin.load_node(b.addinfilename)) {
-      addin.numberofpoints = 0l;
-    }
-  }
-  if (b.metric) {
-    if (!bgmin.load_tetmesh(b.bgmeshfilename)) {
-      bgmin.numberoftetrahedra = 0l;
-    }
-  }
-
-  if (bgmin.numberoftetrahedra > 0l) {
-    tetrahedralize(&b, &in, NULL, &addin, &bgmin);
-  } else {
-    tetrahedralize(&b, &in, NULL, &addin, NULL);
-  }
-
-  return 0;
-
-#else // with TETLIBRARY
-
-  if (!b.parse_commandline(switches)) {
-    terminatetetgen(1);
-  }
-  tetrahedralize(&b, in, out, addin, bgmin);
-
-#endif // not TETLIBRARY
-}
diff --git a/contrib/Tetgen/tetgen.h b/contrib/Tetgen/tetgen.h
index 74106f92601af6ca5b6458882f7f7c1802d0aae5..eb31cbd036b44500a4e605cb67d76faa72f0b122 100644
--- a/contrib/Tetgen/tetgen.h
+++ b/contrib/Tetgen/tetgen.h
@@ -4,12 +4,12 @@
 //                                                                           //
 // A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
 //                                                                           //
-// Version 1.4                                                               //
-// April 16, 2007                                                            //
+// Develop version                                                           //
+// Start: August 9, 2008                                                     //
 //                                                                           //
-// Copyright (C) 2002--2007                                                  //
+// Copyright (C) 2002--2008                                                  //
 // Hang Si                                                                   //
-// Research Group Numerical Mathematics and Scientific Computing             //
+// Research Group: Numerical Mathematics and Scientific Computing            //
 // Weierstrass Institute for Applied Analysis and Stochastics                //
 // Mohrenstr. 39, 10117 Berlin, Germany                                      //
 // si@wias-berlin.de                                                         //
@@ -20,56 +20,8 @@
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// TetGen computes Delaunay tetrahedralizations, constrained Delaunay tetra- //
-//   hedralizations, and quality Delaunay tetrahedral meshes. The latter are //
-//   nicely graded and whose tetrahedra have radius-edge ratio bounded. Such //
-//   meshes are suitable for finite element and finite volume methods.       //
-//                                                                           //
-// TetGen incorporates a suit of geometrical and mesh generation algorithms. //
-//   A brief description of algorithms used in TetGen is found in the first  //
-//   section of the user's manual.  References are given for users who are   //
-//   interesting in these approaches. The main references are given below:   //
-//                                                                           //
-//   The efficient Delaunay tetrahedralization algorithm is: H. Edelsbrunner //
-//   and N. R. Shah, "Incremental Topological Flipping Works for Regular     //
-//   Triangulations". Algorithmica 15: 223--241, 1996.                       //
-//                                                                           //
-//   The constrained Delaunay tetrahedralization algorithm is described in:  //
-//   H. Si and K. Gaertner,  "Meshing Piecewise Linear Complexes by Constr-  //
-//   ained Delaunay Tetrahedralizations".  In Proceeding of the 14th Inter-  //
-//   national Meshing Roundtable. September 2005.                            //
-//                                                                           //
-//   The mesh refinement algorithm is from:  Hang Si, "Adaptive Tetrahedral  //
-//   Mesh Generation by Constrained Delaunay Refinement". WIAS Preprint No.  //
-//   1176, Berlin 2006.                                                      //
-//                                                                           //
-// The mesh data structure of TetGen is a combination of two types of mesh   //
-//   data structures.  The tetrahedron-based mesh data structure introduced  //
-//   by Shewchuk is eligible for tetrahedralization algorithms. The triangle //
-//   -edge data structure developed by Muecke is adopted for representing    //
-//   boundary elements: subfaces and subsegments.                            //
-//                                                                           //
-//   J. R. Shewchuk, "Delaunay Refinement Mesh Generation". PhD thesis,      //
-//   Carnegie Mellon University, Pittsburgh, PA, 1997.                       //
-//                                                                           //
-//   E. P. Muecke, "Shapes and Implementations in Three-Dimensional          //
-//   Geometry". PhD thesis, Univ. of Illinois, Urbana, Illinois, 1993.       //
-//                                                                           //
-// The research of mesh generation is definitly on the move. Many State-of-  //
-//   the-art algorithms need implementing and evaluating. I heartily welcome //
-//   any new algorithm especially for generating quality conforming Delaunay //
-//   meshes and anisotropic conforming Delaunay meshes.                      //
-//                                                                           //
-// TetGen is supported by the "pdelib" project of Weierstrass Institute for  //
-//   Applied Analysis and Stochastics (WIAS) in Berlin.  It is a collection  //
-//   of software components for solving non-linear partial differential      //
-//   equations including 2D and 3D mesh generators, sparse matrix solvers,   //
-//   and scientific visualization tools, etc.  For more information please   //
-//   visit: http://www.wias-berlin.de/software/pdelib.                       //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
+#ifndef tetgenH
+#define tetgenH
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
@@ -79,28 +31,24 @@
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-// Here are the most general used head files for C/C++ programs.
+// Header files for using the C/C++ standard library.
 
-#include <stdio.h>            // Standard IO: FILE, NULL, EOF, printf(), ...
-#include <stdlib.h>        // Standard lib: abort(), system(), getenv(), ...
-#include <string.h>         // String lib: strcpy(), strcat(), strcmp(), ...
-#include <math.h>                     // Math lib: sin(), sqrt(), pow(), ...
-#include <time.h>           // Defined type clock_t, constant CLOCKS_PER_SEC.
-#include <assert.h> 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <assert.h>
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// TetGen Library Overview                                                   //
+// TetGen Library                                                            //
 //                                                                           //
-// TetGen library is comprised by several data types and global functions.   //
-//                                                                           //
-// There are three main data types: tetgenio, tetgenbehavior, and tetgenmesh.//
-// Tetgenio is used to pass data into and out of TetGen library; tetgenbeha- //
-// vior keeps the runtime options and thus controls the behaviors of TetGen; //
-// tetgenmesh, the biggest data type I've ever defined, contains mesh data   //
-// structures and mesh traversing and transformation operators.  The meshing //
-// algorithms are implemented on top of it.  These data types are defined as //
-// C++ classes.                                                              //
+// The library consists of three classes: tetgenio, tetgenbehavior, and      //
+// tetgenmesh. Tetgenio provides interfaces for passing data into and out of //
+// the library; tetgenbehavior keeps the runtime options and thus controls   //
+// the behaviors of TetGen; tetgenmesh implements mesh data strcutures and   //
+// algorithms for generating meshes.                                         //
 //                                                                           //
 // There are few global functions. tetrahedralize() is provided for calling  //
 // TetGen from another program. Two functions: orient3d() and insphere() are //
@@ -109,9 +57,6 @@
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-#ifndef tetgenH
-#define tetgenH
-
 // To compile TetGen as a library instead of an executable program, define
 //   the TETLIBRARY symbol.
 
@@ -127,7 +72,7 @@
 
 // #define SELF_CHECK
 
-// For single precision ( which will save some memory and reduce paging ),
+// 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.
 //
@@ -142,19 +87,24 @@
   #define REAL double
 #endif 	// not defined SINGLE
 
+// Maximum number of characters in a file name (including the null).
+
+enum {FILENAMESIZE = 1024};
+
+// Maximum numbers of chars in a line read from a file (incl. the null).
+
+enum {INPUTLINESIZE = 1024};
+
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// tetgenio    Passing data into and out of the library of TetGen.           //
+// tetgenio    Passing data into and out of the library.                     //
 //                                                                           //
-// The tetgenio data structure is actually a collection of arrays of points, //
-// facets, tetrahedra, and so forth.  The library will read and write these  //
-// arrays according to the options specified in tetgenbehavior structure.    //
-//                                                                           //
-// If you want to program with the library of TetGen, it's necessary for you //
-// to understand this data type,while the other two structures can be hidden //
-// through calling the global function "tetrahedralize()". Each array corre- //
-// sponds to a list of data in the file formats of TetGen.  It is necessary  //
-// to understand TetGen's input/output file formats (see user's manual).     //
+// This class contains a collection of arrays which stores points, facets,   //
+// tetrahedra, and so forth. TetGen will read and write these arrays accord- //
+// ing to the options specified in a tetgenbehavior object. The arrays are   //
+// corresponding to the fields defined in TetGen's input/output file formats.//
+// If you want to use the library of TetGen, It is necessary to understand   //
+// TetGen's input/output file formats (see user's manual).                   //
 //                                                                           //
 // Once an object of tetgenio is declared,  no array is created. One has to  //
 // allocate enough memory for them, e.g., use the "new" operator in C++. On  //
@@ -168,12 +118,11 @@
 // In all cases, the first item in an array is stored starting at index [0]. //
 // However, that item is item number `firstnumber' which may be '0' or '1'.  //
 // Be sure to set the 'firstnumber' be '1' if your indices pointing into the //
-// pointlist is starting from '1'. Default, it is initialized be '0'.        //
+// pointlist is starting from '1'. Default, it is '0'.                       //
 //                                                                           //
 // Tetgenio also contains routines for reading and writing TetGen's files as //
 // well.  Both the library of TetGen and TetView use these routines to parse //
 // input files, i.e., .node, .poly, .smesh, .ele, .face, and .edge files.    //
-// Other routines are provided mainly for debugging purpose.                 //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -181,19 +130,11 @@ class tetgenio {
 
   public:
 
-    // Maximum number of characters in a file name (including the null).
-    enum {FILENAMESIZE = 1024};
-
-    // Maxi. numbers of chars in a line read from a file (incl. the null).
-    enum {INPUTLINESIZE = 1024};
-
-    // The polygon data structure.  A "polygon" is a planar polygon. It can
-    //   be arbitrary shaped (convex or non-convex) and bounded by non-
-    //   crossing segments, i.e., the number of vertices it has indictes the
-    //   same number of edges.
-    // 'vertexlist' is a list of vertex indices (integers), its length is
-    //   indicated by 'numberofvertices'.  The vertex indices are odered in
-    //   either counterclockwise or clockwise way.
+    // The polygon structure.  A "polygon" is a planar polygon which may be
+    //   non-convex but contains no holes. 
+    // 'vertexlist' is a list of vertices (indices) of the polygon odered in
+    //   either counterclockwise or clockwise way. 
+    
     typedef struct {
       int *vertexlist;
       int numberofvertices;
@@ -204,10 +145,10 @@ class tetgenio {
       p->numberofvertices = 0;
     }
 
-    // The facet data structure.  A "facet" is a planar facet.  It is used
-    //   to represent a planar straight line graph (PSLG) in two dimension.
-    //   A PSLG contains a list of polygons. It also may conatin holes in it,
-    //   indicated by a list of hole points (their coordinates).
+    // The facet structure.  A "facet" is a facet. It may be non-convex and
+    //   contains arbitrary number of holes. Hence it consistes of a list of
+    //   polygons and a list holes.
+
     typedef struct {
       polygon *polygonlist;
       int numberofpolygons;
@@ -229,6 +170,7 @@ class tetgenio {
     //   list of Voronoi vertices. 'v1' must be non-negative, while 'v2' may
     //   be -1 if it is a ray, in this case, the unit normal of this ray is
     //   given in 'vnormal'. 
+    
     typedef struct {
       int v1, v2;
       REAL vnormal[3];
@@ -241,6 +183,7 @@ class tetgenio {
     //   share this facet.  'elist' is an array of indices pointing into the
     //   list of Voronoi edges, 'elist[0]' saves the number of Voronoi edges
     //   (including rays) of this facet.
+    
     typedef struct {
       int c1, c2;
       int *elist;
@@ -253,6 +196,7 @@ class tetgenio {
     //   maps a point in f1 into f2.  An array of pbc point pairs are saved
     //   in 'pointpairlist'. The first point pair is at indices [0] and [1],
     //   followed by remaining pairs. Two integers per pair.
+    
     typedef struct {
       int fmark1, fmark2;
       REAL transmat[4][4];
@@ -269,7 +213,7 @@ class tetgenio {
     // Does the lines in .node file contain index or not, default is TRUE.
     bool useindex;
 
-    // 'pointlist':  An array of point coordinates.  The first point's x
+    // 'pointlist':  The array of point coordinates.  The first point's x
     //   coordinate is at index [0] and its y coordinate at index [1], its
     //   z coordinate is at index [2], followed by the coordinates of the
     //   remaining points.  Each point occupies three REALs. 
@@ -277,7 +221,8 @@ class tetgenio {
     //   attributes occupy 'numberofpointattributes' REALs.
     // 'pointmtrlist': An array of metric tensors at points. Each point's
     //   tensor occupies 'numberofpointmtr' REALs.
-    // `pointmarkerlist':  An array of point markers; one int per point.
+    // 'pointmarkerlist':  An array of point markers; one int per point.
+    
     REAL *pointlist;
     REAL *pointattributelist;
     REAL *pointmtrlist;
@@ -286,17 +231,17 @@ class tetgenio {
     int numberofpointattributes;
     int numberofpointmtrs;
  
-    // `elementlist':  An array of element (triangle or tetrahedron) corners. 
-    //   The first element's first corner is at index [0], followed by its
-    //   other corners in counterclockwise order, followed by any other
-    //   nodes if the element represents a nonlinear element.  Each element
-    //   occupies `numberofcorners' ints.
-    // `elementattributelist':  An array of element attributes.  Each
-    //   element's attributes occupy `numberofelementattributes' REALs.
-    // `elementconstraintlist':  An array of constraints, i.e. triangle's
-    //   area or tetrahedron's volume; one REAL per element.  Input only.
-    // `neighborlist':  An array of element neighbors; 3 or 4 ints per
-    //   element.  Output only.
+    // 'tetrahedronlist':  The array of tetrahedra.  The first tet's first
+    //   node is at index [0], followed by its other nodes, optionally
+    //   followed by quadratc nodes of the tet.  Each tet occupies
+    //   'numberofcorners' (4 or 6) ints.
+    // 'tetrahedronattributelist':  The array of tet attributes.  Each tet
+    //   has `numberoftetrahedronattributes' REALs.
+    // 'tetrahedronvolumelist':  The array of constraints, i.e. tetrahedron's
+    //   maximum volume; one REAL per element. Input only.
+    // 'neighborlist':  The array of element neighbors; 'numberofcorners'
+    //   ints per element. Output only.
+    
     int *tetrahedronlist;
     REAL *tetrahedronattributelist;
     REAL *tetrahedronvolumelist;
@@ -305,75 +250,83 @@ class tetgenio {
     int numberofcorners;
     int numberoftetrahedronattributes;
 
-    // `facetlist':  An array of facets.  Each entry is a structure of facet.
+    // `facetlist':  The array of facets.  Each entry is a structure of facet.
     // `facetmarkerlist':  An array of facet markers; one int per facet.
+    
     facet *facetlist;
     int *facetmarkerlist;
     int numberoffacets;
 
-    // `holelist':  An array of holes.  The first hole's x, y and z
+    // `holelist':  The array of volume holes.  The first hole's x, y and z
     //   coordinates  are at indices [0], [1] and [2], followed by the
     //   remaining holes. Three REALs per hole. 
+    
     REAL *holelist;
     int numberofholes;
 
-    // `regionlist': An array of regional attributes and volume constraints.
+    // `regionlist': The array of regional attributes and volume constraints.
     //   The first constraint's x, y and z coordinates are at indices [0],
     //   [1] and [2], followed by the regional attribute at index [3], foll-
     //   owed by the maximum volume at index [4]. Five REALs per constraint. 
     // Note that each regional attribute is used only if you select the `A'
     //   switch, and each volume constraint is used only if you select the
     //   `a' switch (with no number following).
+    
     REAL *regionlist;
     int numberofregions;
 
-    // `facetconstraintlist': An array of facet maximal area constraints.
+    // `facetconstraintlist': The array of facet maximal area constraints.
     //   Two REALs per constraint. The first one is the facet marker (cast
     //   it to int), the second is its maximum area bound.
     // Note the 'facetconstraintlist' is used only for the 'q' switch. 
+    
     REAL *facetconstraintlist;
     int numberoffacetconstraints;
 
-    // `segmentconstraintlist': An array of segment max. length constraints.
+    // `segmentconstraintlist': The array of segment max. length constraints.
     //   Three REALs per constraint. The first two are the indices (pointing
     //   into 'pointlist') of the endpoints of the segment, the third is its
     //   maximum length bound.
-    // Note the 'segmentconstraintlist' is used only for the 'q' switch. 
+    // Note the 'segmentconstraintlist' is used only for the 'q' switch.
+     
     REAL *segmentconstraintlist;
     int numberofsegmentconstraints;
 
-    // 'pbcgrouplist':  An array of periodic boundary condition groups.
+    // 'pbcgrouplist':  The array of periodic boundary condition groups.
+    
     pbcgroup *pbcgrouplist;
     int numberofpbcgroups;
 
-    // `trifacelist':  An array of triangular face endpoints.  The first
-    //   face's endpoints are at indices [0], [1] and [2], followed by the
+    // `trifacelist':  The array of triangluar face list.  The first face's
+    //   endpoints are at indices [0], [1] and [2], followed by the
     //   remaining faces.  Three ints per face.
-    // `adjtetlist':  An array of adjacent tetrahedra to the faces of
-    //   trifacelist. Each face has at most two adjacent tets, the first
-    //   face's adjacent tets are at [0], [1]. Two ints per face. A '-1'
-    //   indicates outside (no adj. tet). This list is output when '-nn'
-    //   switch is used.
-    // `trifacemarkerlist':  An array of face markers; one int per face.
+    // `adjtetlist':  The array of adjacent tets. Each face has at most two
+    //   adjacent tets, the first face's adjacent tets are at [0], [1]. Two
+    //   ints per face. A '-1' indicates outside (no adj. tet).  This list
+    //   is output when '-nn' switch is used.
+    // `trifacemarkerlist':  The array of face markers; one int per face.
+    
     int *trifacelist;
     int *adjtetlist;
     int *trifacemarkerlist;
     int numberoftrifaces;
 
-    // `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.
-    // `edgemarkerlist':  An array of edge markers; one int per edge.
+    // `edgelist':  The array of edges (or segments).  The first edge's 
+    //   endpoints are at indices [0] and [1], followed by the remaining 
+    //   edges.  Two ints per edge.
+    // `edgemarkerlist':  The array of edge markers; one int per edge.
+    
     int *edgelist;
     int *edgemarkerlist;
     int numberofedges;
 
-    // 'vpointlist':  An array of Voronoi vertex coordinates (like pointlist).
-    // 'vedgelist':  An array of Voronoi edges.  Each entry is a 'voroedge'.
-    // 'vfacetlist':  An array of Voronoi facets. Each entry is a 'vorofacet'.
-    // 'vcelllist':  An array of Voronoi cells.  Each entry is an array of
+    // 'vpointlist':  The array of Voronoi vertex coordinates (like pointlist).
+    // 'vedgelist':  The array of Voronoi edges.  Each entry is a 'voroedge'.
+    // 'vfacetlist':  The array of Voronoi facets. Each entry is a 'vorofacet'.
+    // 'vcelllist':  The array of Voronoi cells.  Each entry is an array of
     //   indices pointing into 'vfacetlist'. The 0th entry is used to store
     //   the length of this array.
+    
     REAL *vpointlist;
     voroedge *vedgelist;
     vorofacet *vfacetlist;
@@ -390,30 +343,31 @@ class tetgenio {
     void deinitialize();
 
     // Input & output routines.
-    bool load_node_call(FILE* infile, int markers, char* nodefilename);
-    bool load_node(char* filename);
-    bool load_pbc(char* filename);
-    bool load_var(char* filename);
-    bool load_mtr(char* filename);
-    bool load_poly(char* filename);
-    bool load_off(char* filename);
-    bool load_ply(char* filename);
-    bool load_stl(char* filename);
-    bool load_medit(char* filename);
-    bool load_plc(char* filename, int object);
-    bool load_tetmesh(char* filename);
-    bool load_voronoi(char* filename);
-    void save_nodes(char* filename);
-    void save_elements(char* filename);
-    void save_faces(char* filename);
-    void save_edges(char* filename);
-    void save_neighbors(char* filename);
-    void save_poly(char* filename);
+    bool load_node_call(FILE* infile, int markers, const char* nodefilename);
+    bool load_node(const char* filename);
+    bool load_pbc(const char* filename);
+    bool load_var(const char* filename);
+    bool load_mtr(const char* filename);
+    bool load_poly(const char* filename);
+    bool load_off(const char* filename);
+    bool load_ply(const char* filename);
+    bool load_stl(const char* filename);
+    bool load_medit(const char* filename);
+    bool load_vtk(const char* filename);
+    bool load_plc(const char* filename, int object);
+    bool load_tetmesh(const char* filename);
+    bool load_voronoi(const char* filename);
+    void save_nodes(const char* filename);
+    void save_elements(const char* filename);
+    void save_faces(const char* filename);
+    void save_edges(const char* filename);
+    void save_neighbors(const char* filename);
+    void save_poly(const char* filename);
 
     // Read line and parse string functions.
     char *readline(char* string, FILE* infile, int *linenumber);
     char *findnextfield(char* string);
-    char *readnumberline(char* string, FILE* infile, char* infilename);
+    char *readnumberline(char* string, FILE* infile, const char* infilename);
     char *findnextnumber(char* string);
 
     // Constructor and destructor.
@@ -429,111 +383,99 @@ class tetgenio {
 // for control the behavior of TetGen.  These varibales are all initialized  //
 // to their default values.                                                  //
 //                                                                           //
-// parse_commandline() provides an simple interface to set the vaules of the //
-// variables.  It accepts the standard parameters (e.g., 'argc' and 'argv')  //
-// that pass to C/C++ main() function. Alternatively a string which contains //
-// the command line options can be used as its parameter.                    //
-//                                                                           //
-// You don't need to understand this data type. It can be implicitly called  //
-// by the global function "tetrahedralize()" defined below.  The necessary   //
-// thing you need to know is the meaning of command line switches of TetGen. //
-// They are described in the third section of the user's manual.             //
+// Use function parse_commandline() to set the vaules of the variables.  It  //
+// accepts the standard parameters (e.g., 'argc' and 'argv') that pass to C  //
+// & C++ main() function. Alternatively a string which contains the command  //
+// line options can be used as its parameter.  Please refer to the User's    //
+// manula for the availble options of TetGen.                                //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-class tetgenbehavior {
+class tetgenbehavior {    // Begin of class tetgenbehavior
 
   public:
 
-    // Labels define the objects which are acceptable by TetGen. They are 
-    //   recognized by the file extensions.
-    //   - NODES, a list of nodes (.node); 
-    //   - POLY, a piecewise linear complex (.poly or .smesh); 
-    //   - OFF, a polyhedron (.off, Geomview's file format); 
-    //   - PLY, a polyhedron (.ply, file format from gatech);
-    //   - STL, a surface mesh (.stl, stereolithography format);
-    //   - MEDIT, a surface mesh (.mesh, Medit's file format); 
-    //   - MESH, a tetrahedral mesh (.ele).
-    //   If no extension is available, the imposed commandline switch
-    //   (-p or -r) implies the object. 
-
-    enum objecttype {NONE, NODES, POLY, OFF, PLY, STL, MEDIT, MESH};
-
-    // Variables of command line switches. Each variable corresponds to a
-    //   switch and will be initialized.  The meanings of these switches
-    //   are explained in the user's manul.
-
-    int plc;                                              // '-p' switch, 0.
-    int quality;                                          // '-q' switch, 0.
-    int refine;                                           // '-r' switch, 0.
-    int coarse;                                           // '-R' switch, 0.
-    int metric;                                           // '-m' switch, 0.
-    int varvolume;                         // '-a' switch without number, 0.
-    int fixedvolume;                          // '-a' switch with number, 0.
-    int insertaddpoints;                                  // '-i' switch, 0.
-    int regionattrib;                                     // '-A' switch, 0.
-    int conformdel;                                       // '-D' switch, 0.
-    int diagnose;                                         // '-d' switch, 0.
-    int zeroindex;                                        // '-z' switch, 0.
-    int optlevel;                  // number specified after '-s' switch, 3.
-    int optpasses;                // number specified after '-ss' switch, 5.
-    int order;             // element order, specified after '-o' switch, 1.
-    int facesout;                                         // '-f' switch, 0.
-    int edgesout;                                         // '-e' switch, 0.
-    int neighout;                                         // '-n' switch, 0.
-    int voroout;                                          // '-v',switch, 0.
-    int meditview;                                        // '-g' switch, 0.
-    int gidview;                                          // '-G' switch, 0.
-    int geomview;                                         // '-O' switch, 0.
-    int nobound;                                          // '-B' switch, 0.
-    int nonodewritten;                                    // '-N' switch, 0.
-    int noelewritten;                                     // '-E' switch, 0.
-    int nofacewritten;                                    // '-F' switch, 0.
-    int noiterationnum;                                   // '-I' switch, 0.
-    int nomerge;                                          // '-M',switch, 0.
-    int nobisect;          // count of how often '-Y' switch is selected, 0.
-    int noflip;                     // do not perform flips. '-X' switch. 0.
-    int nojettison;     // do not jettison redundants nodes. '-J' switch. 0.
-    int steiner;                             // number after '-S' switch. 0.
-    int fliprepair;                                       // '-X' switch, 1.
-    int offcenter;                                        // '-R' switch, 0.
-    int docheck;                                          // '-C' switch, 0.
-    int quiet;                                            // '-Q' switch, 0.
-    int verbose;           // count of how often '-V' switch is selected, 0.
-    int useshelles;            // '-p', '-r', '-q', '-d', or '-R' switch, 0.
-    REAL minratio;                         // number after '-q' switch, 2.0.
-    REAL goodratio;               // number calculated from 'minratio', 0.0. 
-    REAL minangle;                             // minimum angle bound, 20.0.
-    REAL goodangle;                      // cosine squared of minangle, 0.0.
-    REAL maxvolume;                       // number after '-a' switch, -1.0.
-    REAL mindihedral;                     // number after '-qq' switch, 5.0.
-    REAL maxdihedral;                  // number after '-qqq' switch, 165.0.
-    REAL alpha1;                       // number after '-m' switch, sqrt(2).
-    REAL alpha2;                          // number after '-mm' switch, 1.0.
-    REAL alpha3;                         // number after '-mmm' switch, 0.6.
-    REAL epsilon;                       // number after '-T' switch, 1.0e-8.
-    REAL epsilon2;                     // number after '-TT' switch, 1.0e-5.
-    enum objecttype object;         // determined by -p, or -r switch. NONE.
-
-    // Variables used to save command line switches and in/out file names.
-    char commandline[1024];
-    char infilename[1024];
-    char outfilename[1024];
-    char addinfilename[1024];
-    char bgmeshfilename[1024];
-
-    tetgenbehavior();
-    ~tetgenbehavior() {}
-
-    void versioninfo();
-    void syntax();
-    void usage();
-
-    // Command line parse routine.
-    bool parse_commandline(int argc, char **argv);
-    bool parse_commandline(char *switches) {
-      return parse_commandline(0, &switches);
-    }
+  // Labels defining the input objects supported by TetGen. They are 
+  //   identified from the file extension of the inputs.
+  //   - NODES, a list of nodes (.node); 
+  //   - POLY, a piecewise linear complex (.poly or .smesh); 
+  //   - OFF, a polyhedron (.off, Geomview's file format); 
+  //   - PLY, a polyhedron (.ply, file format from gatech);
+  //   - STL, a surface mesh (.stl, stereolithography format);
+  //   - MEDIT, a surface mesh (.mesh, Medit's file format); 
+  //   - MESH, a tetrahedral mesh (.ele).
+  //   If no extension is available, the imposed commandline switch
+  //   (-p or -r) implies the type of the object. 
+
+  enum objecttype {NONE, NODES, POLY, OFF, PLY, STL, MEDIT, VTK, MESH};
+
+  // Variables of command line switches. Each variable corresponds to a
+  //   switch. Most of them are initialized to 0.
+
+  int plc;                                                           // -p
+  int quality;                                                       // -q
+  int refine;                                                        // -r
+  int coarse;                                                        // -R
+  int metric;                                                        // -m
+  int varvolume;                                    // -a without a number
+  int fixedvolume;                                     // -a with a number
+  int bowyerwatson;                                                  // -b
+  int convexity;                                                     // -c
+  int insertaddpoints;                                               // -i
+  int regionattrib;                                                  // -A
+  int conformdel;                                                    // -D
+  int diagnose;                                                      // -d
+  int zeroindex;                                                     // -z
+  int order;                                                         // -o
+  int facesout;                                                      // -f
+  int edgesout;                                                      // -e
+  int neighout;                                                      // -n
+  int voroout;                                                       // -v
+  int meditview;                                                     // -g
+  int gidview;                                                       // -G
+  int geomview;                                                      // -O
+  int nobound;                                                       // -B
+  int nonodewritten;                                                 // -N
+  int noelewritten;                                                  // -E
+  int nofacewritten;                                                 // -F
+  int noiterationnum;                                                // -I
+  int nomerge;                                                       // -M
+  int nobisect;                                                      // -Y
+  int nojettison;                                                    // -J
+  int steiner;                                         // -S with a number
+  int docheck;                                                       // -C
+  int quiet;                                                         // -Q
+  int verbose;                                                       // -V
+  int useshelles;                                 // -p, -r, -q, -d, or -R
+  REAL minratio;                                        // number after -q
+  REAL goodratio;                     // number calculated from 'minratio' 
+  REAL minangle;                                    // minimum angle bound
+  REAL goodangle;                            // cosine squared of minangle
+  REAL maxvolume;                                       // number after -a
+  REAL mindihedral;                                    // number after -qq
+  REAL maxdihedral;                                   // number after -qqq
+  REAL epsilon;                                         // number after -T
+  enum objecttype object;                       // determined by -p, or -r
+
+  // Variables used to save command line switches and in/out file names.
+  char commandline[1024];
+  char infilename[1024];
+  char outfilename[1024];
+  char addinfilename[1024];
+  char bgmeshfilename[1024];
+
+  void versioninfo();
+  void syntax();
+  void usage();
+
+  // Command line parse routine.
+  bool parse_commandline(int argc, char **argv);
+  bool parse_commandline(char *switches) {
+    return parse_commandline(0, &switches);
+  }
+  
+  tetgenbehavior();
+  ~tetgenbehavior() {}  
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -573,10 +515,7 @@ REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe);
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// The tetgenmesh data type                                                  //
-//                                                                           //
-// Includes data types and mesh routines for creating tetrahedral meshes and //
-// Delaunay tetrahedralizations, mesh input & output, and so on.             //
+// Class tetgenmesh                                                          //
 //                                                                           //
 // An object of tetgenmesh can be used to store a triangular or tetrahedral  //
 // mesh and its settings. TetGen's functions operates on one mesh each time. //
@@ -589,228 +528,66 @@ REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe);
 // All algorithms TetGen used are implemented in this data type as member    //
 // functions. References of these algorithms can be found in user's manual.  //
 //                                                                           //
-// It's not necessary to understand this type. There is a global function    //
-// "tetrahedralize()" (defined at the end of this file) implicitly creates   //
-// the object and calls its member functions according to the command line   //
-// switches you specified.                                                   //
-//                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-class tetgenmesh {
+///////////////////////////////////////////////////////////////////////////////
+class tetgenmesh {  // Begin of class tetgenmesh
+///////////////////////////////////////////////////////////////////////////////
 
-  public:
+public:
+  
+// For efficiency, a variety of data structures are allocated in bulk.
+//   The following constants determine how many of each structure is
+//   allocated at once.
 
-    // Maximum number of characters in a file name (including the null).
-    enum {FILENAMESIZE = 1024};
-
-    // For efficiency, a variety of data structures are allocated in bulk.
-    //   The following constants determine how many of each structure is
-    //   allocated at once.
-    enum {VERPERBLOCK = 4092, SUBPERBLOCK = 4092, ELEPERBLOCK = 8188};
-
-    // Used for the point location scheme of Mucke, Saias, and Zhu, to
-    //   decide how large a random sample of tetrahedra to inspect.
-    enum {SAMPLEFACTOR = 11};
-
-    // Labels that signify two edge rings of a triangle defined in Muecke's
-    //   triangle-edge data structure, one (CCW) traversing edges in count-
-    //   erclockwise direction and one (CW) in clockwise direction.
-    enum {CCW = 0, CW = 1};
-
-    // 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};
-
-    // Labels that signify the type of a vertex. An UNUSEDVERTEX is a vertex
-    //   read from input (.node file or tetgenio structure) or an isolated
-    //   vertex (outside the mesh).  It is the default type for a newpoint.
-    enum verttype {UNUSEDVERTEX, DUPLICATEDVERTEX, NACUTEVERTEX, ACUTEVERTEX,
-           FREESEGVERTEX, FREESUBVERTEX, FREEVOLVERTEX, DEADVERTEX = -32768};
- 
-    // Labels that signify the type of a subface/subsegment.
-    enum shestype {NSHARP, SHARP};
+enum {VERPERBLOCK = 4092, SUBPERBLOCK = 4092, ELEPERBLOCK = 8188};
+    
+// Labels that signify whether a record consists primarily of pointers
+//   or of floating-point words. Used for data alignment in memorypool.
+
+enum wordtype {POINTER, FLOATINGPOINT};
 
-    // Labels that signify the type of flips can be applied on a face.
-    //   A flipable face has the one of the types T23, T32, T22, and T44.
-    //   Types N32, N40 are unflipable.
-    enum fliptype {T23, T32, T22, T44, N32, N40, FORBIDDENFACE, FORBIDDENEDGE};
+// Labels that signify the type of a vertex. 
 
-    // Labels that signify the result of triangle-triangle intersection test.
-    //   Two triangles are DISJOINT, or adjoint at a vertex SHAREVERTEX, or
-    //   adjoint at an edge SHAREEDGE, or coincident SHAREFACE or INTERSECT.
-    enum interresult {DISJOINT, SHAREVERTEX, SHAREEDGE, SHAREFACE, INTERSECT};
+enum verttype {UNUSEDVERTEX, DUPLICATEDVERTEX, VOLVERTEX, RIDGEVERTEX, 
+  ACUTEVERTEX, FACETVERTEX, STEINERVERTEX, DEADVERTEX};
 
-    // Labels that signify the result of point location.  The result of a
-    //   search indicates that the point falls inside a tetrahedron, inside
-    //   a triangle, on an edge, on a vertex, or outside the mesh. 
-    enum locateresult {INTETRAHEDRON, ONFACE, ONEDGE, ONVERTEX, OUTSIDE};
+// Labels that signify the result of point location.
 
-    // Labels that signify the result of vertex insertion.  The result
-    //   indicates that the vertex was inserted with complete success, was
-    //   inserted but encroaches upon a subsegment, was not inserted because
-    //   it lies on a segment, or was not inserted because another vertex
-    //   occupies the same location.
-    enum insertsiteresult {SUCCESSINTET, SUCCESSONFACE, SUCCESSONEDGE,
-                           DUPLICATEPOINT, OUTSIDEPOINT};
+enum location {INTET, ONFACE, ONEDGE, ONVERTEX, OUTSIDE, ENCSEGMENT, ENCFACE};
 
-    // Labels that signify the result of direction finding.  The result
-    //   indicates that a segment connecting the two query points accross
-    //   an edge of the direction triangle/tetrahedron, across a face of
-    //   the direction tetrahedron, along the left edge of the direction
-    //   triangle/tetrahedron, along the right edge of the direction
-    //   triangle/tetrahedron, or along the top edge of the tetrahedron.
-    enum finddirectionresult {ACROSSEDGE, ACROSSFACE, LEFTCOLLINEAR,
-                              RIGHTCOLLINEAR, TOPCOLLINEAR, BELOWHULL};
+// Labels that signify the result of intersection tests.
+
+enum intersection {DISJOINT, INTERSECT, SHAREVERT, SHAREEDGE, SHAREFACE,
+  TOUCHEDGE, TOUCHFACE, ACROSSVERT, ACROSSEDGE, ACROSSFACE, ACROSSTET,
+  TRIEDGEINT, EDGETRIINT, COLLISIONFACE};
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// The basic mesh element data structures                                    //
+// Mesh data structures                                                      //
 //                                                                           //
 // There are four types of mesh elements: tetrahedra, subfaces, subsegments, //
 // and points,  where subfaces and subsegments are triangles and edges which //
-// appear on boundaries.  A tetrahedralization of a 3D point set comprises   //
-// tetrahedra and points;  a surface mesh of a 3D domain comprises subfaces  //
-// subsegments and points.  The elements of all the four types consist of a  //
-// tetrahedral mesh of a 3D domain.  However, TetGen uses three data types:  //
-// 'tetrahedron', 'shellface', and 'point'. A 'tetrahedron' is a tetrahedron;//
-// while a 'shellface' can be either a subface or a subsegment; and a 'point'//
+// appear on boundaries.  The elements of all the four types consist of a    //
+// tetrahedral mesh of a 3D domain.  TetGen uses three data types:  'tetra-  //
+// hedron', 'shellface', and 'point'. A 'tetrahedron' is a tetrahedron;  a   //
+// 'shellface' represents either a subface or a subsegment;  and a 'point'   //
 // is a point.  These three data types, linked by pointers comprise a mesh.  //
 //                                                                           //
-// A tetrahedron primarily consists of a list of 4 pointers to its corners,  //
-// a list of 4 pointers to its adjoining tetrahedra, a list of 4 pointers to //
-// its adjoining subfaces (when subfaces are needed). Optinoally, (depending //
-// on the selected switches), it may contain an arbitrary number of user-    //
-// defined floating-point attributes,  an optional maximum volume constraint //
-// (for -a switch), and a pointer to a list of high-order nodes (-o2 switch).//
-// Since the size of a tetrahedron is not determined until running time, it  //
-// is not simply declared as a structure.                                    //
-//                                                                           //
-// The data structure of tetrahedron also stores the geometrical information.//
-// Let t be a tetrahedron, v0, v1, v2, and v3 be the 4 nodes corresponding   //
-// to the order of their storage in t.  v3 always has a negative orientation //
-// with respect to v0, v1, v2 (ie,, v3 lies above the oriented plane passes  //
-// through v0, v1, v2). Let the 4 faces of t be f0, f1, f2, and f3. Vertices //
-// of each face are stipulated as follows: f0 (v0, v1, v2), f1 (v0, v3, v1), //
-// f2 (v1, v3, v2), f3 (v2, v3, v0).                                         //
-//                                                                           //
-// A subface has 3 pointers to vertices, 3 pointers to adjoining subfaces, 3 //
-// pointers to adjoining subsegments, 2 pointers to adjoining tetrahedra, a  //
-// boundary marker(an integer). Like a tetrahedron, the pointers to vertices,//
-// subfaces, and subsegments are ordered in a way that indicates their geom- //
-// etric relation.  Let s be a subface, v0, v1 and v2 be the 3 nodes corres- //
-// ponding to the order of their storage in s,  e0, e1 and e2 be the 3 edges,//
-// then we have: e0 (v0, v1), e1 (v1, v2), e2 (v2, v0).                      //
-//                                                                           //
-// A subsegment has exactly the same data fields as a subface has, but only  //
-// uses some of them. It has 2 pointers to its endpoints, 2 pointers to its  //
-// adjoining (and collinear) subsegments, a pointer to a subface containing  //
-// it (there may exist any number of subfaces having it, choose one of them  //
-// arbitrarily). The geometric relation between its endpoints and adjoining  //
-// subsegments is kept with respect to the storing order of its endpoints.   //
-//                                                                           //
-// The data structure of point is relatively simple.  A point is a list of   //
-// floating-point numbers, starting with the x, y, and z coords, followed by //
-// an arbitrary number of optional user-defined floating-point attributes,   //
-// an integer boundary marker, an integer for the point type, and a pointer  //
-// to a tetrahedron (used for speeding up point location).                   //
-//                                                                           //
-// For a tetrahedron on a boundary (or a hull) of the mesh, some or all of   //
-// the adjoining tetrahedra may not be present. For an interior tetrahedron, //
-// often no neighboring subfaces are present,  Such absent tetrahedra and    //
-// subfaces are never represented by the NULL pointers; they are represented //
-// by two special records: `dummytet', the tetrahedron fills "outer space",  //
-// and `dummysh',  the vacuous subfaces which are omnipresent.               //
-//                                                                           //
-// Tetrahedra and adjoining subfaces are glued together through the pointers //
-// saved in each data fields of them. Subfaces and adjoining subsegments are //
-// connected in the same fashion.  However, there are no pointers directly   //
-// gluing tetrahedra and adjoining subsegments.  For the purpose of saving   //
-// space, the connections between tetrahedra and subsegments are entirely    //
-// mediated through subfaces.  The following part explains how subfaces are  //
-// connected in TetGen.                                                      //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// The subface-subface and subface-subsegment connections                    //
-//                                                                           //
-// Adjoining subfaces sharing a common edge are connected in such a way that //
-// they form a face ring around the edge. It is indeed a single linked list  //
-// which is cyclic, e.g., one can start from any subface in it and traverse  //
-// back. When the edge is not a subsegment, the ring only has two coplanar   //
-// subfaces which are pointing to each other. Otherwise, the face ring may   //
-// have any number of subfaces (and are not all coplanar).                   //
-//                                                                           //
-// How is the face ring formed?  Let s be a subsegment, f is one of subfaces //
-// containing s as an edge.  The direction of s is stipulated from its first //
-// endpoint to its second (according to their storage in s). Once the dir of //
-// s is determined, the other two edges of f are oriented to follow this dir.//
-// The "directional normal" N_f is a vector formed from any point in f and a //
-// points orthogonally above f.                                              //
-//                                                                           //
-// The face ring of s is a cyclic ordered set of subfaces containing s, i.e.,//
-// F(s) = {f1, f2, ..., fn}, n >= 1.  Where the order is defined as follows: //
-// let fi, fj be two faces in F(s), the "normal-angle", NAngle(i,j) (range   //
-// from 0 to 360 degree) is the angle between the N_fi and N_fj;  then fi is //
-// in front of fj (or symbolically, fi < fj) if there exists another fk in   //
-// F(s), and NAangle(k, i) < NAngle(k, j).  The face ring of s is: f1 < f2 < //
-// ... < fn < f1.                                                            //
-//                                                                           //
-// The easiest way to imagine how a face ring is formed is to use the right- //
-// hand rule.  Make a fist using your right hand with the thumb pointing to  //
-// the direction of the subsegment. The face ring is connected following the //
-// direction of your fingers.                                                //
-//                                                                           //
-// The subface and subsegment are also connected through pointers stored in  //
-// their own data fields.  Every subface has a pointer to its adjoining sub- //
-// segment. However, a subsegment only has one pointer to a subface which is //
-// containing it. Such subface can be chosen arbitrarily, other subfaces are //
-// found through the face ring.                                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-    // The tetrahedron data structure.  Fields of a tetrahedron contains:
-    //   - a list of four adjoining tetrahedra;
-    //   - a list of four vertices;
-    //   - a list of four subfaces (optional, used for -p switch);
-    //   - a list of user-defined floating-point attributes (optional);
-    //   - a volume constraint (optional, used for -a switch);
-    //   - an integer of element marker (optional, used for -n switch);
-    //   - a pointer to a list of high-ordered nodes (optional, -o2 switch);
-
-    typedef REAL **tetrahedron;
-
-    // The shellface data structure.  Fields of a shellface contains:
-    //   - a list of three adjoining subfaces;
-    //   - a list of three vertices;
-    //   - a list of two adjoining tetrahedra;
-    //   - a list of three adjoining subsegments;
-    //   - a pointer to a badface containing it (used for -q);
-    //   - an area constraint (optional, used for -q);
-    //   - an integer for boundary marker;
-    //   - an integer for type: SHARPSEGMENT, NONSHARPSEGMENT, ...;
-    //   - an integer for pbc group (optional, if in->pbcgrouplist exists);
-
-    typedef REAL **shellface;
-
-    // The point data structure.  It is actually an array of REALs:
-    //   - x, y and z coordinates;
-    //   - a list of user-defined point attributes (optional);
-    //   - a list of REALs of a user-defined metric tensor (optional);
-    //   - a pointer to a simplex (tet, tri, edge, or vertex);
-    //   - a pointer to a parent (or duplicate) point;
-    //   - a pointer to a tet in background mesh (optional);
-    //   - a pointer to another pbc point (optional);
-    //   - an integer for boundary marker;
-    //   - an integer for verttype: INPUTVERTEX, FREEVERTEX, ...;
-
-    typedef REAL *point;
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// The mesh handle (triface, face) data types                                //
+///////////////////////////////////////////////////////////////////////////////
+
+// The tetrahedron data structure.  
+typedef REAL **tetrahedron;
+
+// The shellface data structure. 
+typedef REAL **shellface;
+
+// The point data structure.  
+typedef REAL *point;
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Mesh handles                                                              //
 //                                                                           //
 // Two special data types, 'triface' and 'face' are defined for maintaining  //
 // and updating meshes. They are like pointers (or handles), which allow you //
@@ -818,75 +595,157 @@ class tetgenmesh {
 // an edge and a vertex.  However, these data types do not themselves store  //
 // any part of the mesh. The mesh is made of the data types defined above.   //
 //                                                                           //
-// Muecke's "triangle-edge" data structure is the prototype for these data   //
-// types.  It allows a universal representation for every tetrahedron,       //
-// triangle, edge and vertex.  For understanding the following descriptions  //
-// of these handle data structures,  readers are required to read both the   //
-// introduction and implementation detail of "triangle-edge" data structure  //
-// in Muecke's thesis.                                                       //
-//                                                                           //
-// A 'triface' represents a face of a tetrahedron and an oriented edge of    //
-// the face simultaneously.  It has a pointer 'tet' to a tetrahedron, an     //
-// integer 'loc' (range from 0 to 3) as the face index, and an integer 'ver' //
-// (range from 0 to 5) as the edge version. A face of the tetrahedron can be //
-// uniquly determined by the pair (tet, loc), and an oriented edge of this   //
-// face can be uniquly determined by the triple (tet, loc, ver).  Therefore, //
-// different usages of one triface are possible.  If we only use the pair    //
-// (tet, loc), it refers to a face, and if we add the 'ver' additionally to  //
-// the pair, it is an oriented edge of this face.                            //
-//                                                                           //
-// A 'face' represents a subface and an oriented edge of it simultaneously.  //
-// It has a pointer 'sh' to a subface, an integer 'shver'(range from 0 to 5) //
-// as the edge version.  The pair (sh, shver) determines a unique oriented   //
-// edge of this subface.  A 'face' is also used to represent a subsegment,   //
-// in this case, 'sh' points to the subsegment, and 'shver' indicates the    //
-// one of two orientations of this subsegment, hence, it only can be 0 or 1. //
+///////////////////////////////////////////////////////////////////////////////
+
+// A 'triface' holds a tetrahedron 'tet'. In particular, it holds one
+//   edge of a face of the tetrahedron.  Since each tetrahedron has 4
+//   faces and each face has 6 directed edges, hence there are total
+//   24 different edges in 'tet'. Each edge of 'tet' is represented by
+//   a pair (loc, ver), where 'loc' (range from 0 to 3) indicates a face
+//   of 'tet', and 'ver' (range from 0 to 5) indicates a directed edge
+//   edge of that face.
+
+class triface {
+
+  public:
+
+  tetrahedron* tet;
+  int loc, ver;
+
+  // Constructors;
+  triface() : tet(0), loc(0), ver(0) {}
+  // Operators;
+  triface& operator=(const triface& t) {
+    tet = t.tet; loc = t.loc; ver = t.ver;
+    return *this;
+  }
+  bool operator==(triface& t) {
+    return tet == t.tet && loc == t.loc && ver == t.ver;
+  }
+  bool operator!=(triface& t) {
+    return tet != t.tet || loc != t.loc || ver != t.ver;
+  }
+};
+
+// A 'face' holds a shellface 'sh'. In particular, it holds one directed
+//   edge of the shellface. There are 6 directed edges in a triangle.
+//   'shver' (range from 0 to 5) indicates a directed edge in 'sh'.
+
+class face {
+
+  public:
+
+  shellface *sh;
+  int shver;
+
+  // Constructors;
+  face() : sh(0), shver(0) {}
+  // Operators;
+  face& operator=(const face& s) {
+    sh = s.sh; shver = s.shver;
+    return *this;
+  }
+  bool operator==(face& s) {return (sh == s.sh) && (shver == s.shver);}
+  bool operator!=(face& s) {return (sh != s.sh) || (shver != s.shver);}
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Arraypool    A dynamic array                                              //
 //                                                                           //
-// Mesh navigation and updating are accomplished through a set of mesh       //
-// manipulation primitives which operate on trifaces and faces.  They are    //
-// introduced below.                                                         //
+// Each arraypool contains an array of pointers to a number of blocks.  Each //
+// block contains the same fixed number of objects.  Each index of the array //
+// addesses a particular object in the pool.  The most significant bits add- //
+// ress the index of the block containing the object. The less significant   //
+// bits address this object within the block.                                //
+//                                                                           //
+// 'objectbytes' is the size of one object in blocks; 'log2objectsperblock'  //
+// is the base-2 logarithm of 'objectsperblock'; 'objects' counts the number //
+// of allocated objects; 'totalmemory' is the totoal memorypool in bytes.    //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-    class triface {
-
-      public:
+class arraypool {
 
-        tetrahedron* tet;
-        int loc, ver;
+  public:
 
-        // Constructors;
-        triface() : tet(0), loc(0), ver(0) {}
-        // Operators;
-        triface& operator=(const triface& t) {
-          tet = t.tet; loc = t.loc; ver = t.ver;
-          return *this;
-        }
-        bool operator==(triface& t) {
-          return tet == t.tet && loc == t.loc && ver == t.ver;
-        }
-        bool operator!=(triface& t) {
-          return tet != t.tet || loc != t.loc || ver != t.ver;
-        }
-    };
+  int objectbytes;
+  int objectsperblock;
+  int log2objectsperblock; 
+  int toparraylen;
+  char **toparray;
+  unsigned long objects;
+  unsigned long totalmemory;
+
+  void restart();
+  void poolinit(int sizeofobject, int log2objperblk);
+  char* getblock(int objectindex);
+  void* lookup(int objectindex);
+  int newindex(void **newptr);
+
+  arraypool(int sizeofobject, int log2objperblk);
+  ~arraypool();
+};
 
-    class face {
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Memorypool    A dynamic pool of memory                                    //
+//                                                                           //
+// A type used to allocate memory written by J. Shewchuk.                    //
+//                                                                           //
+// 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.                                                       //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
 
-      public:
+class memorypool {
 
-        shellface *sh;
-        int shver;
+  public:
 
-        // Constructors;
-        face() : sh(0), shver(0) {}
-        // Operators;
-        face& operator=(const face& s) {
-          sh = s.sh; shver = s.shver;
-          return *this;
-        }
-        bool operator==(face& s) {return (sh == s.sh) && (shver == s.shver);}
-        bool operator!=(face& s) {return (sh != s.sh) || (shver != s.shver);}
-    };
+  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;
+
+  void poolinit(int, int, enum wordtype, int);
+  void restart();
+  void *alloc();
+  void dealloc(void*);
+  void traversalinit();
+  void *traverse();
+
+  memorypool() {}
+  memorypool(int, int, enum wordtype, int);
+  ~memorypool();
+};
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
@@ -912,986 +771,1069 @@ class tetgenmesh {
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-    struct badface {
-      triface tt; 
-      face ss; 
-      REAL key;
-      REAL cent[3];
-      point forg, fdest, fapex, foppo;
-      point noppo;
-      struct badface *previtem, *nextitem; 
-    };
+struct badface {
+  triface tt; 
+  face ss; 
+  REAL key;
+  REAL cent[3];
+  point forg, fdest, fapex, foppo, noppo;
+  struct badface *previtem, *nextitem; 
+};
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// The pbcdata structure                                                     //
+// Fast Lookup Tables                                                        //
 //                                                                           //
-// A pbcdata stores data of a periodic boundary condition defined on a pair  //
-// of facets or segments. Let f1 and f2 define a pbcgroup. 'fmark' saves the //
-// facet markers of f1 and f2;  'ss' contains two subfaces belong to f1 and  //
-// f2, respectively.  Let s1 and s2 define a segment pbcgroup. 'segid' are   //
-// the segment ids of s1 and s2; 'ss' contains two segments belong to s1 and //
-// s2, respectively. 'transmat' are two transformation matrices. transmat[0] //
-// transforms a point of f1 (or s1) into a point of f2 (or s2),  transmat[1] //
-// does the inverse.                                                         //
+// The mesh data structures additionally store geometric informations which  //
+// help for fast queries.                                                    //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-    struct pbcdata {
-      int fmark[2];
-      int segid[2];
-      face ss[2];
-      REAL transmat[2][4][4];
-    };
+// For enext() primitive, uses 'ver' as the key.
+static int ve[6], ve2[6];
+
+// For sorg(), sdest, spaex(), use 'shver' as the key.
+static int vo[6], vd[6], va[6];
+
+// For bond(), t1 and t2 are two symmetric faces sharing the same edges, it
+//   takes t1's and t2's edge versions as the first and second keys, returns
+//   t2's edge corresponds to t1's 0th edge.
+// Note: the returned edge version is in {0, 2, 4}. The same follows.
+static int verver2zero[6][6];
+
+// For bond(), t1's edge corresponds to t2's 0th edge, it takes t1's edge
+//   version as the key, returns t2's edge corresponds to t1's 0th edge.
+static int ver2zero[6];
+
+// For fnext(), symedge(), t1 and t2 share the same face, and t2's edge
+//   corresponds to t1's 0th edge, it takes t1's and t2's edge versions as
+//   the first and second keys, return t2's edge corresponds to t1's edge. 
+static int zero2ver[6][6];
+
+// For org(), dest() and apex() primitives, use ('loc', 'ver') as the key.
+static int locver2org[4][6];
+static int locver2dest[4][6];
+static int locver2apex[4][6];
+
+// For oppo() primitives, uses 'loc' as the key.
+static int loc2oppo[4];
+
+// For fnext() primitives, uses ('loc' * 8 + 'ver') as the key. Returns
+//   an array containing a new ('loc', 'ver'). 
+// Note: Only valid for 'ver' equals one of {0, 2, 4}.
+static int locver2nextf[32];
+
+// Twos maps between ('loc', 'ver') and the edge number (from 0 to 5).
+static int locver2edge[4][6];
+static int edge2locver[6][2];
+
+// The map from a given face ('loc') to the other three faces in the tet.
+//   and the map from a given face's edge ('loc', 'ver') to other two
+//   faces in the tet opposite to this edge. (used in speeding the Bowyer-
+//   Watson cavity construction).
+static int locpivot[4][3];
+static int locverpivot[4][6][2];
+
+static int mi1mo3[3];
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// The list, link and queue data structures                                  //
+// Mesh manipulation primitives                                              //
 //                                                                           //
-// These data types are used to manipulate a set of (same-typed) data items. //
-// For a given set S = {a, b, c, ...}, a list stores the elements of S in a  //
-// piece of continuous memory. It allows quickly accessing each element of S,//
-// thus is suitable for storing a fix-sized set.  While a link stores its    //
-// elements incontinuously. It allows quickly inserting or deleting an item, //
-// thus is suitable for storing a size-variable set.  A queue is basically a //
-// special case of a link where one data element joins the link at the end   //
-// and leaves in an ordered fashion at the other end.                        //
+// Mesh navigation and updating are accomplished through a set of mesh       //
+// manipulation primitives which operate on trifaces and faces.  They are    //
+// introduced below.                                                         //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-    // The compfunc data type.  "compfunc" is a pointer to a linear-order
-    //   function, which takes two 'void*' arguments and returning an 'int'. 
-    //   
-    // 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.
-    typedef int (*compfunc) (const void *, const void *);
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Primitives for tetrahedron                                                //
+//                                                                           //
+// Each tetrahedron contains four pointers to its adjacent tetrahedra, with  //
+// their face indices (loc in [0, 3]) and edge versions (ver in [0, 5]).  To //
+// save memory, all informations of an adjacent tetrahedron are compressed   //
+// in a single pointer. To make this possible, all tetrahedra are aligned to //
+// 16-byte boundaries, so that the last four bits of each pointer are zeros. //
+// Each face indice (loc) is compressed into the last two bits,  each edge   //
+// version (ver) is compressed into the second last two bits of the pointer, //
+// respectively. encode() and decode() functions implement this feature.     //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
 
-    // The predefined compare functions for primitive data types.  They
-    //   take two pointers of the corresponding date type, perform the
-    //   comparation, and return -1, 0 or 1 indicating the default linear
-    //   order of them.
-    static int compare_2_ints(const void* x, const void* y);
-    static int compare_2_longs(const void* x, const void* y);
-    static int compare_2_unsignedlongs(const void* x, const void* y);
+// encode() -- to compress a triface 't' into a single pointer. 
+//   't.ver' is in [0, 5], first we map it to [0, 2], this is equal to
+//   divide it by 2 (>> 1), next we shift it to the second last two bits
+//   of the pointer, this is equal to multiply it by 4 (<< 2). 
+// Note: Do not combine the bit options for (t).ver.
+
+#define encode(t) (tetrahedron) ((unsigned long) (t).tet | \
+  ((unsigned long) (((t).ver >> 1) << 2)) | (unsigned long) (t).loc)
+
+// decode() -- to decompose a pointer 'ptr' into a triface 't'. 
+//   For obtaining t.ver, we first extract it (& 12l), then shift it to
+//   the right by 2 bits (>> 2), then multiply it by 2 (<< 1), hence 
+//   t.ver is in {0,2,4}. Combining the last two operations, we only
+//   need to divide it by 2 (>> 1).
+
+#define decode(ptr, t) \
+  (t).loc = (int) ((unsigned long) (ptr) & (unsigned long) 3l);\
+  (t).ver = (int) (((unsigned long) (ptr) & (unsigned long) 12l) >> 1);\
+  (t).tet = (tetrahedron *) ((unsigned long) (ptr) & ~(unsigned long) 15l)
+    
+// sym() -- given triface 't1', get a triface 't2', where 't1' and 't2'
+//   are the same face in two adjacent tetrahedra. But they may not be 
+//   the same edge. (Refer to bond() function.)
+    
+#define sym(t1, t2) decode((t1).tet[(t1).loc], (t2))
+    
+#define symself(t) \
+  ptr = (t).tet[(t).loc];\
+  decode(ptr, (t))
+  
+// symedge() -- given triface 't1', get a triface 't2', where 't1' and 't2'
+//   are the same face and the same edge in two adjacent tetrahedra.
+// Require "tetrahedron ptr;" and "int tver".
+
+#define symedge(t1, t2) \
+  decode((t1).tet[(t1).loc], (t2));\
+  (t2).ver = zero2ver[(t1).ver][(t2).ver]
+
+#define symedgeself(t) \
+  ptr = (t).tet[(t).loc];\
+  tver = (t).ver;\
+  decode(ptr, (t));\
+  (t).ver = zero2ver[tver][(t).ver];
+
+// org(), dest(), apex(), oppo() -- return the origin, destination, apex,
+//   and opposite vertices of the triface.
+    
+#define org(t) (point) (t).tet[locver2org[(t).loc][(t).ver] + 4]
+
+#define dest(t) (point) (t).tet[locver2dest[(t).loc][(t).ver] + 4]
+
+#define apex(t) (point) (t).tet[locver2apex[(t).loc][(t).ver] + 4]
+
+#define oppo(t) (point) (t).tet[loc2oppo[(t).loc] + 4]
+
+#define setorg(t, p) \
+  (t).tet[locver2org[(t).loc][(t).ver] + 4] = (tetrahedron) (p)
+
+#define setdest(t, p) \
+  (t).tet[locver2dest[(t).loc][(t).ver] + 4] = (tetrahedron) (p)
+
+#define setapex(t, p) \
+  (t).tet[locver2apex[(t).loc][(t).ver] + 4] = (tetrahedron) (p)
+
+#define setoppo(t, p) (t).tet[loc2oppo[(t).loc] + 4] = (tetrahedron) (p)
+
+#define setvertices(t, p1, p2, p3, p4) \
+  setorg(t, p1); \
+  setdest(t, p2); \
+  setapex(t, p3); \
+  setoppo(t, p4)
+
+// esym(), enext(), enext2() -- primitives for moving edges in face.
+//   The face remains the same.
+
+#define esym(t1, t2) \
+  (t2).tet = (t1).tet; (t2).loc = (t1).loc;\
+  (t2).ver = (t1).ver + (((t1).ver & 01) ? -1 : 1)
+
+#define esymself(t) (t).ver += (((t).ver & 01) ? -1 : 1)
+
+#define enext(t1, t2) \
+  (t2).tet = (t1).tet; (t2).loc = (t1).loc;\
+  (t2).ver = ve[(t1).ver]
+
+#define enextself(t) (t).ver = ve[(t).ver]
+
+#define enext2(t1, t2) \
+  (t2).tet = (t1).tet; (t2).loc = (t1).loc;\
+  (t2).ver = ve2[(t1).ver]
+
+#define enext2self(t) (t).ver = ve2[(t).ver]
+
+// enextfnext(), enext2fnext() -- primitives for moving faces in tet.
+//   the tetrahedron remains the same. 
+// Note: The input edge version is in {0, 2, 4}.
+
+#define enext0fnext(t1, t2) \
+  iptr = &(locver2nextf[(t1).loc * 8 + (t1).ver]);\
+  (t2).tet = (t1).tet;\
+  (t2).loc = iptr[0];\
+  (t2).ver = iptr[1]
+
+#define enext0fnextself(t) \
+  iptr = &(locver2nextf[(t).loc * 8 + (t).ver]);\
+  (t).loc = iptr[0];\
+  (t).ver = iptr[1]
+
+#define enextfnext(t1, t2) \
+  iptr = &(locver2nextf[(t1).loc * 8 + ve[(t1).ver]]);\
+  (t2).tet = (t1).tet;\
+  (t2).loc = iptr[0];\
+  (t2).ver = iptr[1]
+
+#define enextfnextself(t) \
+  iptr = &(locver2nextf[(t).loc * 8 + ve[(t).ver]]);\
+  (t).loc = iptr[0];\
+  (t).ver = iptr[1]
 
-    // The function used to determine the size of primitive data types and
-    //   set the corresponding predefined linear order functions for them.
-    static void set_compfunc(char* str, int* itembytes, compfunc* pcomp);
+#define enext2fnext(t1, t2) \
+  iptr = &(locver2nextf[(t1).loc * 8 + ve2[(t1).ver]]);\
+  (t2).tet = (t1).tet;\
+  (t2).loc = iptr[0];\
+  (t2).ver = iptr[1]
+
+#define enext2fnextself(t) \
+  iptr = &(locver2nextf[(t).loc * 8 + ve2[(t).ver]]);\
+  (t).loc = iptr[0];\
+  (t).ver = iptr[1]
+
+// fnext() -- given an edge (i, j) of a face (i, j, k1) = t1, find the
+//   next face t2 in the face ring of (i, j), i.e. a face (i, j, k2),
+//   where (i, j, k1) and (i, j, k2) belong to two tetrahedra.
+    
+void fnext(triface& t1, triface& t2) {
+  int *iptr;
+  if (t1.ver & 01) {
+    // Get the adjacent tet.
+    decode(t1.tet[t1.loc], t2);
+    // Adjust the edge (see Fig. fnext-base).
+    t2.ver = zero2ver[t1.ver][t2.ver];
+    // Go to the next face in t2.
+    iptr = &(locver2nextf[t2.loc * 8 + t2.ver]);
+    t2.loc = iptr[0];
+    t2.ver = iptr[1];
+  } else {
+    // Go to the next face in t1.
+    iptr = &(locver2nextf[t1.loc * 8 + t1.ver]);
+    // Get the adjacent tet.
+    decode(t1.tet[iptr[0]], t2);
+    // Adjust the edge (see Fig. fnext-base).
+    t2.ver = zero2ver[iptr[1]][t2.ver];
+  }
+}
+
+void fnextself(triface& t) {
+  tetrahedron ptr;
+  int *iptr, tver;
+  if (t.ver & 01) {
+    ptr = t.tet[t.loc];
+    tver = t.ver;
+    decode(ptr, t);
+    t.ver = zero2ver[tver][t.ver];
+    iptr = &(locver2nextf[t.loc * 8 + t.ver]);
+    t.loc = iptr[0];
+    t.ver = iptr[1]; 
+  } else {
+    iptr = &(locver2nextf[t.loc * 8 + t.ver]);
+    ptr = t.tet[iptr[0]];
+    decode(ptr, t);
+    t.ver = zero2ver[iptr[1]][t.ver];
+  }
+}
+
+// bond() -- to setup the connections between 't1.loc' <==> 't2.loc'.
+//   From t1 <-- t2, we bond the edge in 't2' corresponding to the 0-th
+//   edge in 't1', and vice versa for t1 --> t2.
+// NOTE: We assume that t1 and t2 refer to the same edge on input.  
+
+void bond(triface& t1, triface& t2) {
+  // We will modify edge vers, backup them.
+  int t1ver = t1.ver, t2ver = t2.ver;
+  // Find t2's edge corresponds to the t1's 0th edge.
+  t2.ver = verver2zero[t1.ver][t2.ver];
+  // t1 <-- t2
+  t1.tet[t1.loc] = encode(t2);
+  // Find t1's edge corresponds to t2's 0th edge.
+  t1.ver = ver2zero[t2.ver];
+  // t1 --> t2
+  t2.tet[t2.loc] = encode(t1);
+  // Restore the original vers.
+  t1.ver = t1ver; t2.ver = t2ver;
+}
+
+// elemmarker() -- to read or set element's marker.
+
+#define elemmarker(ptr) ((int *) (ptr))[elemmarkerindex]
+
+// elemattribute() -- to check or set element attributes.
+
+#define elemattribute(ptr, num) (((REAL *) (ptr))[elemattribindex + num])
+
+#define setelemattribute(ptr, num, value) \
+  ((REAL *) (ptr))[elemattribindex + num] = value
+
+// volumebound() -- to check or set element's maximum volume bound.
+
+#define volumebound(ptr) (((REAL *) (ptr))[volumeboundindex])
+
+#define setvolumebound(ptr, value) \
+  ((REAL *) (ptr))[volumeboundindex] = value
+
+// infect(), infected(), uninfect() -- primitives to flag or unflag a
+//   tetrahedron. The last bit of the element marker is flagged (1)
+//   or unflagged (0).
+
+#define infect(t) elemmarker((t).tet) |= 1
+
+#define uninfect(t) elemmarker((t).tet) &= ~1
+
+#define infected(t) ((elemmarker((t).tet) & 1) != 0)
+
+// marktest(), marktested(), unmarktest() -- primitives to flag or unflag a
+//   tetrahedron.  The last second bit of the element marker is marked (1)
+//   or unmarked (0).
+// One needs them in forming Bowyer-Watson cavity, to mark a tetrahedron if
+//   it has been checked (for Delaunay case) so later check can be avoided.
+
+#define marktest(t) elemmarker((t).tet) |= 2
+
+#define unmarktest(t) elemmarker((t).tet) &= ~2
+    
+#define marktested(t) ((elemmarker((t).tet) & 2) != 0)
+
+// markface(), unmarkface(), facemarked() -- primitives to flag or unflag a
+//   face of a tetrahedron.  From the last 3rd to 6th bits are used for
+//   face markers, e.g., the last third bit corresponds to loc = 0. 
+// One use of the face marker is in flip algorithm. Each queued face (check
+//   for locally Delaunay) is marked.
+
+#define markface(t) elemmarker((t).tet) |= (4<<(t).loc)
+
+#define unmarkface(t) elemmarker((t).tet) &= ~(4<<(t).loc)
+
+#define facemarked(t) ((elemmarker((t).tet) & (4<<(t).loc)) != 0)
+
+// markedge(), unmarkedge(), edgemarked() -- primitives to flag or unflag an
+//   edge of a tetrahedron.  From the last 7th to 12th bits are used for
+//   edge markers, e.g., the last 7th bit corresponds to the 0th edge, etc. 
+// Remark: The last 7th bit is marked by 2^6 = 64.
+
+#define markedge(t) elemmarker((t).tet) |= (64<<locver2edge[(t).loc][(t).ver])
+
+#define unmarkedge(t) \
+  elemmarker((t).tet) &= ~(64<<locver2edge[(t).loc][(t).ver])
+
+#define edgemarked(t) \
+  ((elemmarker((t).tet) & (64<<locver2edge[(t).loc][(t).ver])) != 0)
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// List data structure.                                                      //
+// Primitives for shellfaces                                                 //
 //                                                                           //
-// A 'list' is an array of items with automatically reallocation of memory.  //
-// It behaves like an array.                                                 //
+// Each shellface contains three pointers to its adjacent shellfaces, with   //
+// their edge versions (shver in [0, 5]).  To save memory, all informations  //
+// of an adjacent shellface are compressed in a single pointer. To make this //
+// possible, all shellface are aligned to 8-byte boundaries.                 //
 //                                                                           //
-// 'base' is the starting address of the array;  The memory unit in list is  //
-//   byte, i.e., sizeof(char). 'itembytes' is the size of each item in byte, //
-//   so that the next item in list will be found at the next 'itembytes'     //
-//   counted from the current position.                                      //
+///////////////////////////////////////////////////////////////////////////////
+
+// sencode(), sdecode -- to compress/uncompress a face/pointer. 
+//   The pointer 's.sh' is assumed to be 8-byte aligned.
+
+#define sencode(s) \
+  (shellface) ((unsigned long) (s).sh | (unsigned long) (s).shver)
+
+#define sdecode(sptr, s) \
+  (s).shver = (int) ((unsigned long) (sptr) & (unsigned long) 7l);\
+  (s).sh = (shellface *) ((unsigned long) (sptr) & ~ (unsigned long) 7l)
+
+// sorg(), sdest(), sapex() -- return the origin, destination, apex,
+//   of the subface.
+    
+#define sorg(s) (point) (s).sh[vo[(s).shver] + 3]
+
+#define sdest(s) (point) (s).sh[vd[(s).shver] + 3]
+
+#define sapex(s) (point) (s).sh[va[(s).shver] + 3]
+
+#define setsdest(s, p) (s).sh[vd[(s).shver] + 3] = (shellface) (p)
+
+#define setsapex(s, p) (s).sh[va[(s).shver] + 3] = (shellface) (p)
+
+#define setshvertices(s, p1, p2, p3) \
+  (s).sh[vo[(s).shver] + 3] = (shellface) (p1); \
+  (s).sh[vd[(s).shver] + 3] = (shellface) (p2); \
+  (s).sh[va[(s).shver] + 3] = (shellface) (p3)
+
+// sesym() - change the origin and destination of the face edge.
+
+#define sesym(s1, s2) \
+  (s2).sh = (s1).sh;\
+  (s2).shver = (s1).shver + (((s1).shver & 01) ? -1 : 1);
+
+#define sesymself(s) \
+  (s).shver += (((s).shver & 01) ? -1 : 1);
+
+// senext(), senext2() -- go to the next (or the previous) face edge.
+
+#define senext(s1, s2) \
+  (s2).sh = (s1).sh;\
+  (s2).shver = ve[(s1).shver]
+  
+#define senextself(s) \
+  (s).shver = ve[(s).shver]
+
+#define senext2(s1, s2) \
+  (s2).sh = (s1).sh;\
+  (s2).shver = ve2[(s1).shver]
+  
+#define senext2self(s) \
+  (s).shver = ve2[(s).shver]
+
+// The general rule to connect two subfaces s1 and s2 is:  Let s1's edge
+//   be a->b, which is in s1's 0th edge ring, then the edge b->a of s2 is
+//   bonded to s1.  The same rule for connecting a subface and a subseg.
+
+// sbond1() -- s1 and s2 share an edge, connect s1 <-- s2, i.e., s1 knows
+//   its neighbor is s2. sbond2() connects s1 <==> s2.
+
+#define sbond1(s1, s2) (s1).sh[(s1).shver >> 1] = sencode(s2);
+
+#define sbond2(s1, s2) \
+  (s1).sh[(s1).shver >> 1] = sencode(s2);\
+  (s2).sh[(s2).shver >> 1] = sencode(s1)
+
+// sdisolve() -- dissolve a subface-subface connection (at one side).
+
+#define sdissolve(s) (s).sh[(s).shver >> 1] = NULL;
+
+// ssbond() -- connect a subface (s) and a subsegment (seg) together.
+// NOTE: we allow that 'seg.sh' should not be NULL.
+
+#define ssbond(s, seg) \
+  (s).sh[((s).shver >> 1) + 6] = sencode(seg);\
+  if ((seg).sh != NULL) (seg).sh[0] = sencode(s)
+
+// ssdisolve() -- dissolve a subface-subsegment connection (at subface side).
+
+#define ssdissolve(s) (s).sh[((s).shver >> 1) + 6] = NULL;
+
+// spivot() -- find the next face in the face ring.
+
+#define spivot(s1, s2) sdecode((s1).sh[(s1).shver >> 1], s2)
+
+#define spivotself(s) \
+  sptr = (s).sh[(s).shver >> 1];\
+  sdecode(sptr, s)
+
+// sspivot() -- find the abutting subsegment (seg) at the face (s).
+
+#define sspivot(s, seg) sdecode((s).sh[((s).shver >> 1) + 6], seg)
+
+// shellmark() -- set or read the shell mark.
+
+// #define shellmark(s) ((int *) ((s).sh))[shmarkindex]
+
+// The last two bits of the int ((int *) ((s).sh))[shmarkindex] are used
+//   by sinfect() and smarktest().
+
+int getshellmark(face& s) {
+  return (((int *) ((s).sh))[shmarkindex]) >> 2;
+}
+
+void setshellmark(face& s, int mark) {
+  ((int *) ((s).sh))[shmarkindex] = (mark << 2) + 
+    ((((int *) ((s).sh))[shmarkindex]) & 3);
+}
+
+// areabound() -- set of read the maximal area bound.
+
+#define areabound(s) ((REAL *) ((s).sh))[areaboundindex]
+
+// sinfect(), sinfected(), suninfect() -- primitives to flag or unflag a
+//   subface. The last bit of ((int *) ((s).sh))[shmarkindex] is flaged.
+
+#define sinfect(s) \
+  ((int *) ((s).sh))[shmarkindex] = (((int *) ((s).sh))[shmarkindex] | 1)
+
+#define suninfect(s) \
+  ((int *) ((s).sh))[shmarkindex] = (((int *) ((s).sh))[shmarkindex] & ~1)
+
+#define sinfected(s) ((((int *) ((s).sh))[shmarkindex] & 1) != 0)
+
+// smarktest(), smarktested(), sunmarktest() -- primitives to flag or unflag
+//   a subface. The last 2nd bit of ((int *) ((s).sh))[shmarkindex] is flaged.
+
+#define smarktest(s) \
+  ((int *) ((s).sh))[shmarkindex] = (((int *) ((s).sh))[shmarkindex] | 2)
+
+#define sunmarktest(s) \
+  ((int *) ((s).sh))[shmarkindex] = (((int *) ((s).sh))[shmarkindex] & ~2)
+
+#define smarktested(s) ((((int *) ((s).sh))[shmarkindex] & 2) != 0)
+
+// farsorg(), farsdest() -- s is a subsegment, return the origin or
+//   destination of the segment containing s.
+// Note: here we assume that two subsegment (a->p) and (p->b) bonded
+//   at p as: (p->nil->a) and (nil->p->b), in flipn2nf().
+
+point farsorg(face& s) {
+  face travesh, neighsh;
+  shellface sptr;
+  travesh = s;
+  while (1) {
+    senext2(travesh, neighsh);
+    spivotself(neighsh); 
+    if (neighsh.sh == NULL) break;
+    if (sorg(neighsh) != sorg(travesh)) sesymself(neighsh);
+    assert(sorg(neighsh) == sorg(travesh)); // SELF_CHECK
+    senext2(neighsh, travesh); 
+  }
+  return sorg(travesh);
+}
+
+point farsdest(face& s) {
+  face travesh, neighsh;
+  shellface sptr;
+  travesh = s;
+  while (1) {
+    senext(travesh, neighsh);
+    spivotself(neighsh); 
+    if (neighsh.sh == NULL) break;
+    if (sdest(neighsh) != sdest(travesh)) sesymself(neighsh);
+    assert(sdest(neighsh) == sdest(travesh)); // SELF_CHECK
+    senext(neighsh, travesh); 
+  }
+  return sdest(travesh);
+}
+
+///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// 'items' is the number of items stored in list.  'maxitems' indicates how  //
-//   many items can be stored in this list. 'expandsize' is the increasing   //
-//   size (items) when the list is full.                                     //
+// Interactions between tetrahedra and subfaces and subsegments.             //
 //                                                                           //
-// 'comp' is a pointer pointing to a linear order function for the list.     //
-//   default it is set to 'NULL'.                                            //
+///////////////////////////////////////////////////////////////////////////////
+
+// tspivot(), stpivot -- given a tet's face t (or a subface s), find the
+//   abutting subface (or tet).
+
+void tspivot(triface& t, face& s) {
+  if ((t).tet[9] != NULL) {
+    sdecode(((shellface *) (t).tet[9])[(t).loc], s);
+  } else {
+    (s).sh = NULL;
+  }
+}
+
+#define stpivot(s, t) decode((tetrahedron) (s).sh[9], t)
+
+// tsbond() -- connect a tet and subface.
+
+void tsbond(triface& t, face& s) {
+  if ((t).tet[9] == NULL) {
+    // Allocate space for this tet.
+    (t).tet[9] = (tetrahedron) tet2subpool->alloc();
+    // NULL all fields in this space.
+    for (int i = 0; i < 4; i++) {
+      ((shellface *) (t).tet[9])[i] = NULL;
+    }
+  }
+  // Bond t <==> s.
+  ((shellface *) (t).tet[9])[(t).loc] = sencode(s);
+  (s).sh[9] = (shellface) encode(t);
+}
+
+// tsdissolve() -- dissolve a tet-subface bond at the tet side.
+
+void tsdissolve(triface& t) {
+  if ((t).tet[9] != NULL) {
+    ((shellface *) (t).tet[9])[(t).loc] = NULL;
+  }
+}
+
+// stdissolve() -- dissolbe a tet-subface bond at the subface side.
+
+#define stdissolve(s) (s).sh[9] = NULL;
+
+// tsspivot() -- given a tet's edge t, return a subsegment s at this edge.
+//   t and s is bonded through tssbond1(). if s.sh == NULL, the edge is
+//   not a subsegment.
+
+void tsspivot(triface& t, face& s) {
+  if ((t).tet[8] != NULL) {
+    sdecode(((shellface *) (t).tet[8])[locver2edge[(t).loc][(t).ver]], s);
+  } else {
+    (s).sh = NULL;
+  }
+}
+
+// tssbond1() -- bond a tet edge and a segment (only at tet's edge).
+
+void tssbond1(triface& t, face& s) {
+  if ((t).tet[8] == NULL) {
+    // Allocate space for this tet.
+    (t).tet[8] = (tetrahedron) tet2segpool->alloc();
+    // NULL all fields in this space.
+    for (int i = 0; i < 6; i++) {
+      ((shellface *) (t).tet[8])[i] = NULL;
+    }
+  }
+  // Bond the segment.
+  ((shellface *) (t).tet[8])[locver2edge[(t).loc][(t).ver]] = sencode((s));
+} 
+
+// tssdissolve() -- dissolve a tet-seg bond at the tet edge.
+
+void tssdissolve(triface& t) {
+  if ((t).tet[8] != NULL) {
+    ((shellface *) (t).tet[8])[locver2edge[(t).loc][(t).ver]] = NULL;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// The index of list always starts from zero, i.e., for a list L contains    //
-//   n elements, the first element is L[0], and the last element is L[n-1].  //
-//   This feature lets lists like C/C++ arrays.                              //
+// Primitives for points                                                     //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-    class list {
+#define pointmark(pt) ((int *) (pt))[pointmarkindex]
+    
+#define point2tet(pt) ((tetrahedron *) (pt))[point2tetindex]
+    
+#define point2ppt(pt) ((point *) (pt))[point2tetindex + 1]
+
+// #define pointtype(pt) ((enum verttype *) (pt))[pointmarkindex + 1]
 
-      public:
+enum verttype getpointtype(point pt) {
+  return (enum verttype) (((int *) (pt))[pointmarkindex + 1] >> 1);
+}
 
-        char *base;
-        int  itembytes;
-        int  items, maxitems, expandsize;
-        compfunc comp;
+void setpointtype(point pt, enum verttype type) {
+  ((int *) (pt))[pointmarkindex + 1] = 
+    ((int) type << 1) + (((int *) (pt))[pointmarkindex + 1] & 1);
+}
 
-      public:
+// pinfect(), puninfect(), pinfected() -- primitives to flag or unflag
+//   a point. The last bit of the integer '[pointindex+1]' is flaged.
 
-        list(int itbytes, compfunc pcomp, int mitems = 256, int exsize = 128) {
-          listinit(itbytes, pcomp, mitems, exsize);
-        }
-        list(char* str, int mitems = 256, int exsize = 128) {
-          set_compfunc(str, &itembytes, &comp);
-          listinit(itembytes, comp, mitems, exsize);
-        }
-        ~list() { free(base); }
+#define pinfect(pt) \
+  ((int *) (pt))[pointmarkindex + 1] = ((int *) (pt))[pointmarkindex + 1] | 1
 
-        void *operator[](int i) { return (void *) (base + i * itembytes); }
+#define puninfect(pt) \
+  ((int *) (pt))[pointmarkindex + 1] = ((int *) (pt))[pointmarkindex + 1] & ~1
 
-        void listinit(int itbytes, compfunc pcomp, int mitems, int exsize);
-        void setcomp(compfunc compf) { comp = compf; }    
-        void clear() { items = 0; }
-        int  len() { return items; }
-        void *append(void* appitem);
-        void *insert(int pos, void* insitem);
-        void del(int pos, int order);
-        int  hasitem(void* checkitem);
-        void sort();
-    }; 
+#define pinfected(pt) ((((int *) (pt))[pointmarkindex + 1] & 1) != 0)
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// Memorypool data structure.                                                //
+// Primitives for arraypools.                                                //
 //                                                                           //
-// A type used to allocate memory.  (It is incorporated from Shewchuk's      //
-// Triangle program)                                                         //
+///////////////////////////////////////////////////////////////////////////////
+
+// fastlookup() -- A fast, unsafe operation. Return the pointer to the object
+//   with a given index.  Note: The object's block must have been allocated,
+//   i.e., by the function newindex().
+
+#define fastlookup(pool, index) \
+  (void *) ((pool)->toparray[(index) >> (pool)->log2objectsperblock] + \
+            ((index) & ((pool)->objectsperblock - 1)) * (pool)->objectbytes)
+
+///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// 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.          //
+// Class Variables.                                                          //
 //                                                                           //
-// 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.                                              //
+///////////////////////////////////////////////////////////////////////////////
+
+// Pointer to the input data (a PLC or a mesh).
+tetgenio *in;
+
+// Pointer to the options (and filenames).
+tetgenbehavior *b;
+
+// Pools of tetrahedra, shellfaces, points, etc.
+memorypool *tetrahedronpool;
+memorypool *subsegpool, *subfacepool;
+memorypool *tet2segpool, *tet2subpool;
+memorypool *pointpool;
+memorypool *flippool;
+
+// A dummy point at infinity (see [Guibas & Stolfi 85]).  All the hull
+//   tetrahedra having this point as a vertex.
+point dummypoint;
+
+// Statck and queue (use flippool) for flips.
+badface *futureflip;
+
+// Arrays used by Bowyer-Watson algorithm.
+arraypool *cavetetlist, *cavebdrylist, *caveoldtetlist;
+arraypool *caveshlist, *caveshbdlist;
+
+// Stacks used by the boundary recovery algorithm.
+arraypool *subsegstack, *subfacstack;
+
+// Variables for accessing data fields (initialized in initializepools()).
+int point2tetindex, pointmarkindex;
+int elemmarkerindex;
+int elemattribindex, volumeboundindex, highorderindex;
+int shmarkindex, areaboundindex;
+
+// The number of hull tetrahedra (= the number of outer boundary faces).
+long hullsize;
+
+// Current random number seed, number of random samples (for point location).
+unsigned long randomseed, samples;
+
+// Pointers to a recently visited tetrahedron and subface.
+triface recenttet;
+face recentsh;
+
+// Two handles used in facet recovery (formcavity and fillcavity).
+triface firsttopface, firstbotface;
+
+// The size of bounding boxes.
+REAL xmax, xmin, ymax, ymin, zmax, zmin;
+
+// The number of duplicated vertices, mesh edges, and input segments.
+long dupverts, meshedges, meshsubedges, insegments;
+
+// Flags to check imposed constraints, subfaces, subsegs.
+int checkconstraints, checksubfaces, checksubsegs, checkpbcs;
+
+// Algorithm statistical counters.
+long ptloc_count, ptloc_max_count;
+long orient3dcount;
+long inspherecount, insphere_sos_count;
+long maxbowatcavsize, totalbowatcavsize, totaldeadtets;
+long flip14count, flip26count, flipn2ncount;
+long flip23count, flip32count, flipnmcount;
+long flip13count, flip22count, flipn2nfcount;
+REAL tloctime, tfliptime, tinserttime;
+long triedgcount, triedgcopcount, trivercopcount;
+long across_face_count, across_edge_count, across_max_count;
+long r1count, r2count, r3count;
+long maxcavsize, maxregionsize;
+long ndelaunayedgecount, cavityexpcount;
+
+///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// 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.                                                       //
+// Functions for using memorypools.                                          //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-    class memorypool {
+void initializepools();
+void tetrahedrondealloc(tetrahedron*);
+tetrahedron *tetrahedrontraverse();
+tetrahedron *alltetrahedrontraverse();
+void shellfacedealloc(memorypool*, shellface*);
+shellface *shellfacetraverse(memorypool*);
+void badfacedealloc(memorypool*, badface*);
+badface *badfacetraverse(memorypool*);
+void pointdealloc(point);
+point pointtraverse();
+void maketetrahedron(triface*);
+void makeshellface(memorypool*, face*);
+void makepoint(point*);
+void makeindex2pointmap(point*&);
+void makepoint2submap(memorypool*, int*&, face*&);
+void makepoint2tetmap();
 
-      public:
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Linear algebra operators.                                                 //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
 
-        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;
+#define NORM2(x, y, z) ((x) * (x) + (y) * (y) + (z) * (z))
 
-      public:
+#define DIST(p1, p2) \
+  sqrt(NORM2((p2)[0] - (p1)[0], (p2)[1] - (p1)[1], (p2)[2] - (p1)[2]))
 
-        memorypool();
-        memorypool(int, int, enum wordtype, int);
-        ~memorypool();
-    
-        void poolinit(int, int, enum wordtype, int);
-        void restart();
-        void *alloc();
-        void dealloc(void*);
-        void traversalinit();
-        void *traverse();
-    };  
+#define DOT(v1, v2) \
+  ((v1)[0] * (v2)[0] + (v1)[1] * (v2)[1] + (v1)[2] * (v2)[2])
+
+#define CROSS(v1, v2, n) \
+  (n)[0] =   (v1)[1] * (v2)[2] - (v2)[1] * (v1)[2];\
+  (n)[1] = -((v1)[0] * (v2)[2] - (v2)[0] * (v1)[2]);\
+  (n)[2] =   (v1)[0] * (v2)[1] - (v2)[0] * (v1)[1]
+
+#define SETVECTOR3(V, a0, a1, a2) (V)[0] = (a0); (V)[1] = (a1); (V)[2] = (a2)
+
+#define SWAP2(a0, a1, tmp) (tmp) = (a0); (a0) = (a1); (a1) = (tmp)
+
+bool lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N);
+void lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N);
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Geometric predicates, advanced tests, intersections.                      //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+static REAL PI;
+
+REAL interiorangle(point o, point p1, point p2, REAL* n);
+void facenormal(point, point, point, REAL *n, int pivot);
+void circumsphere(point, point, point, point, REAL* cent, REAL* radius);
+
+REAL insphere_sos(point pa, point pb, point pc, point pd, point pe);
+REAL incircle3d(point pa, point pb, point pc, point pd);
+bool iscoplanar(point k, point l, point m, point n, REAL ori);
+
+int tri_edge_2d(point,point,point,point,point,point,int,int*,int*);
+int tri_edge_test(point,point,point,point,point,point,int,int*,int*);
+int tri_tri_2d(point,point,point,point,point,point,point,int,int*,int*);
+int tri_tri_test(point,point,point,point,point,point,point,int,int*,int*);
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// Link data structure.                                                      //
-//                                                                           //
-// A 'link' is a double linked nodes. It uses the memorypool data structure  //
-// for memory management.  Following is an image of a link.                  //
-//                                                                           //
-//   head-> ____0____      ____1____      ____2____      _________<-tail     //
-//         |__next___|--> |__next___|--> |__next___|--> |__NULL___|          //
-//         |__NULL___|<-- |__prev___|<-- |__prev___|<-- |__prev___|          //
-//         |         |    |_       _|    |_       _|    |         |          //
-//         |         |    |_ Data1 _|    |_ Data2 _|    |         |          //
-//         |_________|    |_________|    |_________|    |_________|          //
-//                                                                           //
-// The unit size for storage is size of pointer, which may be 4-byte (in 32- //
-//   bit machine) or 8-byte (in 64-bit machine). The real size of an item is //
-//   stored in 'linkitembytes'.                                              //
+// Mesh transformation operations.                                           //
+//                                                                           //
+// Mesh transformation operations translate an old set of tetrahedra into a  //
+// new set of tetrahedra in the same region of the tetrahedralization. Such  //
+// operations include face/edge flips, vertex insertion/deletions.           //
 //                                                                           //
-// 'head' and 'tail' are pointers pointing to the first and last nodes. They //
-//   do not conatin data (See above).                                        //
+///////////////////////////////////////////////////////////////////////////////
+
+badface* flipshpush(badface* flipstack, face* flipedge);
+void flip13(point newpt, face* splitface, int flipflag);
+void flipn2nf(point newpt, face* splitedges, int flipflag);
+void flip22(face* flipfaces, int flipflag);
+void lawsonflip();
+
+badface* flippush(badface* flipstack, triface* flipface, point pushpt);
+void flip14(point newpt, triface* splittet, int flipflag);
+void flip26(point newpt, triface* splitface, int flipflag);
+void flipn2n(point newpt, triface* splitedge, int flipflag);
+void flip23(triface* fliptets, int hullflag, int flipflag);
+void flip32(triface* fliptets, int hullflag, int flipflag);
+//bool flipnm(int n, triface* fliptets, int flipflag);
+void lawsonflip3d(int flipflag);
+
+///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// 'nextlinkitem' is a pointer pointing to a node which is the next one will //
-//   be traversed. 'curpos' remembers the position (1-based) of the current  //
-//   traversing node.                                                        //
+// Jump-and-Walk point location algorithm.                                   //
 //                                                                           //
-// 'linkitems' indicates how many items in link. Note it is different with   //
-//   'items' of memorypool.                                                  //
+// The following functions implemented the randomized jump-and-walk point    //
+// location algorithm of Muecke, Saias, and Zhu [MueckeSaiasZhu96].          //
 //                                                                           //
-// The index of link starts from 1, i.e., for a link K contains n elements,  //
-//   the first element of the link is K[1], and the last element is K[n].    //
-//   See the above figure.                                                   //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-    class link : public memorypool {
-
-      public:
-
-        void **head, **tail;
-        void *nextlinkitem;
-        int  linkitembytes;
-        int  linkitems;
-        int  curpos;
-        compfunc comp;
-
-      public:
-
-        link(int _itembytes, compfunc _comp, int itemcount) {
-          linkinit(_itembytes, _comp, itemcount);
-        }
-        link(char* str, int itemcount) {
-          set_compfunc(str, &linkitembytes, &comp);
-          linkinit(linkitembytes, comp, itemcount);
-        }
-
-        void linkinit(int _itembytes, compfunc _comp, int itemcount);
-        void setcomp(compfunc compf) { comp = compf; }
-        void rewind() { nextlinkitem = *head; curpos = 1; }
-        void goend() { nextlinkitem = *(tail + 1); curpos = linkitems; }    
-        long len() { return linkitems; }
-        void clear();
-        bool move(int numberofnodes);
-        bool locate(int pos);
-        void *add(void* newitem);
-        void *insert(int pos, void* insitem);
-        void *deletenode(void** delnode);
-        void *del(int pos);
-        void *getitem();
-        void *getnitem(int pos);
-        int  hasitem(void* checkitem);
-    };
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Queue data structure.                                                     //
-//                                                                           //
-// A 'queue' is basically a link.  Following is an image of a queue.         //
-//              ___________     ___________     ___________                  //
-//   Pop() <-- |_         _|<--|_         _|<--|_         _| <-- Push()      //
-//             |_  Data0  _|   |_  Data1  _|   |_  Data2  _|                 //
-//             |___________|   |___________|   |___________|                 //
-//              queue head                       queue tail                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-    class queue : public link {
-
-      public:
-
-        queue(int bytes, int count = 256) : link(bytes, NULL, count) {}
-        bool empty() { return linkitems == 0; }
-        void *push(void* newitem) {return link::add(newitem);} 
-        void *pop() {return link::deletenode((void **) *head);}
-        // Stack is implemented as a single link list.
-        void *stackpush() {
-          void **newnode = (void **) alloc();
-          // if (newitem != (void *) NULL) {
-          //   memcpy((void *)(newnode + 2), newitem, linkitembytes);
-          // }
-          void **nextnode = (void **) *head;
-          *head = (void *) newnode;
-          *newnode = (void *) nextnode;
-          linkitems++;
-          return (void *)(newnode + 2); 
-        }
-        void *stackpop() {
-          void **deadnode = (void **) *head;
-          *head = *deadnode;
-          linkitems--;
-          return (void *)(deadnode + 2);
-        }
-    };
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Global variables used for miscellaneous purposes.                         //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-    // Pointer to the input data (a set of nodes, a PLC, or a mesh).
-    tetgenio *in;
-    // Pointer to the options (and filenames).
-    tetgenbehavior *b;
-    // Pointer to a background mesh (contains size specification map).
-    tetgenmesh *bgm;
-
-    // Variables used to allocate and access memory for tetrahedra, subfaces
-    //   subsegments, points, encroached subfaces, encroached subsegments,
-    //   bad-quality tetrahedra, and so on.
-    memorypool *tetrahedrons;
-    memorypool *subfaces;
-    memorypool *subsegs;
-    memorypool *points;
-    memorypool *badsubsegs;
-    memorypool *badsubfaces;
-    memorypool *badtetrahedrons;
-    memorypool *flipstackers;
-
-    // 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 subface.  Referenced by any tetrahedron,
-    //   or subface that isn't connected to a subface at that location.
-    shellface *dummysh;
-    shellface *dummyshbase;    // Keep base address so we can free it later.
-
-    // A point above the plane in which the facet currently being used lies.
-    //   It is used as a reference point for orient3d().
-    point *facetabovepointarray, abovepoint;
-
-    // Array (size = numberoftetrahedra * 6) for storing high-order nodes of
-    //   tetrahedra (only used when -o2 switch is selected).
-    point *highordertable;
-
-    // Arrays for storing and searching pbc data. 'subpbcgrouptable', (size
-    //   is numberofpbcgroups) for pbcgroup of subfaces. 'segpbcgrouptable',
-    //   a list for pbcgroup of segments. Because a segment can have several
-    //   pbcgroup incident on it, its size is unknown on input, it will be
-    //   found in 'createsegpbcgrouptable()'.
-    pbcdata *subpbcgrouptable;
-    list *segpbcgrouptable;
-    // A map for searching the pbcgroups of a given segment. 'idx2segpglist'
-    //   (size = number of input segments + 1), and 'segpglist'.  
-    int *idx2segpglist, *segpglist;
-
-    // Queues that maintain the bad (badly-shaped or too large) tetrahedra.
-    //   The tails are pointers to the pointers that have to be filled in to
-    //   enqueue an item.  The queues are ordered from 63 (highest priority)
-    //   to 0 (lowest priority).
-    badface *subquefront[3], **subquetail[3];
-    badface *tetquefront[64], *tetquetail[64];
-    int nextnonemptyq[64];
-    int firstnonemptyq, recentq;
-
-    // Pointer to a recently visited tetrahedron. Improves point location
-    //   if proximate points are inserted sequentially.
-    triface recenttet;
-
-    REAL xmax, xmin, ymax, ymin, zmax, zmin;      // Bounding box of points.
-    REAL longest;                       // The longest possible edge length.
-    REAL lengthlimit;                  // The limiting length of a new edge.
-    long hullsize;                        // Number of faces of convex hull.
-    long insegments;                            // Number of input segments.
-    int steinerleft;               // Number of Steiner points not yet used.
-    int sizeoftensor;                  // Number of REALs per metric tensor.
-    int pointmtrindex;        // Index to find the metric tensor of a point.
-    int point2simindex;      // Index to find a simplex adjacent to a point.
-    int pointmarkindex;         // Index to find boundary marker of a point.
-    int point2pbcptindex;           // Index to find a pbc point to a point.
-    int highorderindex; // Index to find extra nodes for highorder elements.
-    int elemattribindex;       // Index to find attributes of a tetrahedron.
-    int volumeboundindex;    // Index to find volume bound of a tetrahedron.
-    int elemmarkerindex;           // Index to find marker of a tetrahedron.
-    int shmarkindex;          // Index to find boundary marker of a subface.
-    int areaboundindex;            // Index to find area bound of a subface.
-    int checksubfaces;                // Are there subfaces in the mesh yet?
-    int checksubsegs;                  // Are there subsegs in the mesh yet?
-    int checkpbcs;                // Are there periodic boundary conditions?
-    int varconstraint;  // Are there variant (node, seg, facet) constraints?
-    int nonconvex;                            // Is current mesh non-convex?
-    int dupverts;                          // Are there duplicated vertices?
-    int unuverts;                              // Are there unused vertices?
-    int relverts;                       // The number of relocated vertices.
-    int suprelverts;         // The number of suppressed relocated vertices.
-    int collapverts;          // The number of collapsed relocated vertices.
-    int unsupverts;                  // The number of unsuppressed vertices.
-    int smoothsegverts;                  // The number of smoothed vertices.
-    int smoothvolverts;                  // The number of smoothed vertices.
-    int jettisoninverts;         // The number of jettisoned input vertices.
-    int symbolic;                             // Use symbolic insphere test.
-    long samples;            // Number of random samples for point location.
-    unsigned long randomseed;                 // Current random number seed.
-    REAL macheps;                                    // The machine epsilon.
-    REAL cosmaxdihed, cosmindihed; // The cosine values of max/min dihedral.
-    REAL minfaceang, minfacetdihed;  // The minimum input (dihedral) angles.
-    int maxcavfaces, maxcavverts;         // The size of the largest cavity.
-    int expcavcount;                      // The times of expanding cavitys.
-    long abovecount;                   // Number of abovepoints calculation.
-    long bowatvolcount, bowatsubcount, bowatsegcount;     // Bowyer-Watsons.
-    long updvolcount, updsubcount, updsegcount; // Bow-Wat cavities updates.
-    long failvolcount, failsubcount, failsegcount;         // Bow-Wat fails.
-    long repairflipcount;         // Number of flips for repairing segments.
-    long outbowatcircumcount;  // Number of circumcenters outside Bowat-cav.
-    long r1count, r2count, r3count;      // Numbers of edge splitting rules.
-    long cdtenforcesegpts;              // Number of CDT enforcement points.
-    long rejsegpts, rejsubpts, rejtetpts;      // Number of rejected points.
-    long optcount[10];          // Numbers of various optimizing operations.
-    long flip23s, flip32s, flip22s, flip44s;   // Number of flips performed.
-    REAL tloctime, tfliptime;      // Time (microseconds) of point location.
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Fast lookup tables for mesh manipulation primitives.                      //
-//                                                                           //
-// Mesh manipulation primitives (given below) are basic operations on mesh   //
-// data structures. They answer basic queries on mesh handles, such as "what //
-// is the origin (or destination, or apex) of the face?", "what is the next  //
-// (or previous) edge in the edge ring?", and "what is the next face in the  //
-// face ring?", and so on.                                                   //
-//                                                                           //
-// The implementation of teste basic queries can take advangtage of the fact //
-// that the mesh data structures additionally store geometric informations.  //
-// For example, we have ordered the 4 vertices (from 0 to 3) and the 4 faces //
-// (from 0 to 3) of a tetrahedron,  and for each face of the tetrahedron, a  //
-// sequence of vertices has stipulated,  therefore the origin of any face of //
-// the tetrahedron can be quickly determined by a table 'locver2org', which  //
-// takes the index of the face and the edge version as inputs.  A list of    //
-// fast lookup tables are defined below. They're just like global variables. //
-// These tables are initialized at the runtime.                              //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-    // For enext() primitive, uses 'ver' as the index. 
-    static int ve[6];
-
-    // For org(), dest() and apex() primitives, uses 'ver' as the index.
-    static int vo[6], vd[6], va[6];
-
-    // For org(), dest() and apex() primitives, uses 'loc' as the first
-    //   index and 'ver' as the second index.
-    static int locver2org[4][6];
-    static int locver2dest[4][6];
-    static int locver2apex[4][6];
-
-    // For oppo() primitives, uses 'loc' as the index.
-    static int loc2oppo[4];
-
-    // For fnext() primitives, uses 'loc' as the first index and 'ver' as
-    //   the second index,  returns an array containing a new 'loc' and a
-    //   new 'ver'. Note: Only valid for 'ver' equals one of {0, 2, 4}.
-    static int locver2nextf[4][6][2];
-
-    // The edge number (from 0 to 5) of a tet is defined as follows:
-    static int locver2edge[4][6];
-    static int edge2locver[6][2];
-
-    // For enumerating three edges of a triangle.
-    static int plus1mod3[3];
-    static int minus1mod3[3];
+///////////////////////////////////////////////////////////////////////////////
+
+unsigned long randomnation(unsigned long choices);
+void randomsample(point searchpt, triface* searchtet);
+enum location locate(point searchpt, triface* searchtet);
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// Mesh manipulation primitives                                              //
+// Incremental Delaunay tetrahedralization algorithms.                       //
 //                                                                           //
-// A serial of mesh operations such as topological maintenance,  navigation, //
-// local modification, etc.,  is accomplished through a set of mesh manipul- //
-// ation primitives. These primitives are indeed very simple functions which //
-// take one or two handles ('triface's and 'face's) as parameters,  perform  //
-// basic operations such as "glue two tetrahedra at a face",  "return the    //
-// origin of a tetrahedron", "return the subface adjoining at the face of a  //
-// tetrahedron", and so on.                                                  //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-        // Primitives for tetrahedra.
-    inline void decode(tetrahedron ptr, triface& t);
-    inline tetrahedron encode(triface& t);
-    inline void sym(triface& t1, triface& t2);
-    inline void symself(triface& t);
-    inline void bond(triface& t1, triface& t2);
-    inline void dissolve(triface& t);
-    inline point org(triface& t);
-    inline point dest(triface& t);
-    inline point apex(triface& t);
-    inline point oppo(triface& t);
-    inline void setorg(triface& t, point pointptr);
-    inline void setdest(triface& t, point pointptr);
-    inline void setapex(triface& t, point pointptr);
-    inline void setoppo(triface& t, point pointptr);
-    inline void esym(triface& t1, triface& t2);
-    inline void esymself(triface& t);
-    inline void enext(triface& t1, triface& t2);
-    inline void enextself(triface& t);
-    inline void enext2(triface& t1, triface& t2);
-    inline void enext2self(triface& t);
-    inline bool fnext(triface& t1, triface& t2);
-    inline bool fnextself(triface& t);
-    inline void enextfnext(triface& t1, triface& t2);
-    inline void enextfnextself(triface& t);
-    inline void enext2fnext(triface& t1, triface& t2);
-    inline void enext2fnextself(triface& t);
-    inline void infect(triface& t);
-    inline void uninfect(triface& t);
-    inline bool infected(triface& t);
-    inline REAL elemattribute(tetrahedron* ptr, int attnum);
-    inline void setelemattribute(tetrahedron* ptr, int attnum, REAL value);
-    inline REAL volumebound(tetrahedron* ptr);
-    inline void setvolumebound(tetrahedron* ptr, REAL value);
- 
-    // Primitives for subfaces and subsegments.
-    inline void sdecode(shellface sptr, face& s);
-    inline shellface sencode(face& s);
-    inline void spivot(face& s1, face& s2);
-    inline void spivotself(face& s);
-    inline void sbond(face& s1, face& s2);
-    inline void sbond1(face& s1, face& s2);
-    inline void sdissolve(face& s);
-    inline point sorg(face& s);
-    inline point sdest(face& s);
-    inline point sapex(face& s);
-    inline void setsorg(face& s, point pointptr);
-    inline void setsdest(face& s, point pointptr);
-    inline void setsapex(face& s, point pointptr);
-    inline void sesym(face& s1, face& s2);
-    inline void sesymself(face& s);
-    inline void senext(face& s1, face& s2);
-    inline void senextself(face& s);
-    inline void senext2(face& s1, face& s2);
-    inline void senext2self(face& s);
-    inline void sfnext(face&, face&);
-    inline void sfnextself(face&);
-    inline badface* shell2badface(face& s);
-    inline void setshell2badface(face& s, badface* value);
-    inline REAL areabound(face& s);
-    inline void setareabound(face& s, REAL value);
-    inline int shellmark(face& s);
-    inline void setshellmark(face& s, int value);
-    inline enum shestype shelltype(face& s);
-    inline void setshelltype(face& s, enum shestype value); 
-    inline int shellpbcgroup(face& s);
-    inline void setshellpbcgroup(face& s, int value);
-    inline void sinfect(face& s);
-    inline void suninfect(face& s);
-    inline bool sinfected(face& s);
-
-    // Primitives for interacting tetrahedra and subfaces.
-    inline void tspivot(triface& t, face& s);
-    inline void stpivot(face& s, triface& t);
-    inline void tsbond(triface& t, face& s);
-    inline void tsdissolve(triface& t);
-    inline void stdissolve(face& s);
-
-    // Primitives for interacting subfaces and subsegs.
-    inline void sspivot(face& s, face& edge);
-    inline void ssbond(face& s, face& edge);
-    inline void ssdissolve(face& s);
-
-    inline void tsspivot1(triface& t, face& seg);
-    inline void tssbond1(triface& t, face& seg);
-    inline void tssdissolve1(triface& t);
-
-    // Primitives for points.
-    inline int  pointmark(point pt);
-    inline void setpointmark(point pt, int value);
-    inline enum verttype pointtype(point pt);
-    inline void setpointtype(point pt, enum verttype value);
-    inline tetrahedron point2tet(point pt);
-    inline void setpoint2tet(point pt, tetrahedron value);
-    inline shellface point2sh(point pt);
-    inline void setpoint2sh(point pt, shellface value);
-    inline point point2ppt(point pt);
-    inline void setpoint2ppt(point pt, point value);
-    inline tetrahedron point2bgmtet(point pt);
-    inline void setpoint2bgmtet(point pt, tetrahedron value);
-    inline point point2pbcpt(point pt);
-    inline void setpoint2pbcpt(point pt, point value);
-
-    // Advanced primitives.
-    inline void adjustedgering(triface& t, int direction);
-    inline void adjustedgering(face& s, int direction);
-    inline bool isdead(triface* t);
-    inline bool isdead(face* s);
-    inline bool isfacehaspoint(triface* t, point testpoint);
-    inline bool isfacehaspoint(face* t, point testpoint);
-    inline bool isfacehasedge(face* s, point tend1, point tend2);
-    inline bool issymexist(triface* t);
-    void getnextsface(face*, face*);
-    void tsspivot(triface*, face*);
-    void sstpivot(face*, triface*);   
-    bool findorg(triface* t, point dorg);
-    bool findorg(face* s, point dorg);
-    void findedge(triface* t, point eorg, point edest);
-    void findedge(face* s, point eorg, point edest);
-    void findface(triface *fface, point forg, point fdest, point fapex);
-    void getonextseg(face* s, face* lseg);
-    void getseghasorg(face* sseg, point dorg);
-    point getsubsegfarorg(face* sseg);
-    point getsubsegfardest(face* sseg);
-    void printtet(triface*);
-    void printsh(face*);
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Triangle-triangle intersection test                                       //
-//                                                                           //
-// The triangle-triangle intersection test is implemented with exact arithm- //
-// etic. It exactly tells whether or not two triangles in three dimensions   //
-// intersect.  Before implementing this test myself,  I tried two C codes    //
-// (implemented by Thomas Moeller and Philippe Guigue, respectively), which  //
-// are all public available. However both of them failed frequently. Another //
-// unconvenience is both codes only tell whether or not the two triangles    //
-// intersect without distinguishing the cases whether they exactly intersect //
-// in interior or they just share a vertex or share an edge. The two latter  //
-// cases are acceptable and should return not intersection in TetGen.        //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-    enum interresult edge_vert_col_inter(REAL*, REAL*, REAL*);
-    enum interresult edge_edge_cop_inter(REAL*, REAL*, REAL*, REAL*, REAL*);
-    enum interresult tri_vert_cop_inter(REAL*, REAL*, REAL*, REAL*, REAL*);
-    enum interresult tri_edge_cop_inter(REAL*, REAL*, REAL*,REAL*,REAL*,REAL*);
-    enum interresult tri_edge_inter_tail(REAL*, REAL*, REAL*, REAL*, REAL*,
-                                        REAL, REAL);
-    enum interresult tri_edge_inter(REAL*, REAL*, REAL*, REAL*, REAL*);
-    enum interresult tri_tri_inter(REAL*, REAL*, REAL*, REAL*, REAL*, REAL*);
-
-    // Geometric predicates
-    REAL insphere_sos(REAL*, REAL*, REAL*, REAL*, REAL*, int, int,int,int,int);
-    bool iscollinear(REAL*, REAL*, REAL*, REAL eps);
-    bool iscoplanar(REAL*, REAL*, REAL*, REAL*, REAL vol6, REAL eps);
-    bool iscospheric(REAL*, REAL*, REAL*, REAL*, REAL*, REAL vol24, REAL eps);
-
-    // Linear algebra functions
-    inline REAL dot(REAL* v1, REAL* v2);
-    inline void cross(REAL* v1, REAL* v2, REAL* n);
-    bool lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N);
-    void lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N);
-
-    // Geometric quantities calculators.
-    inline REAL distance(REAL* p1, REAL* p2);
-    REAL shortdistance(REAL* p, REAL* e1, REAL* e2);
-    REAL shortdistance(REAL* p, REAL* e1, REAL* e2, REAL* e3);
-    REAL interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n);
-    void projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj);
-    void projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj);
-    void facenormal(REAL* pa, REAL* pb, REAL* pc, REAL* n, REAL* nlen);
-    void edgeorthonormal(REAL* e1, REAL* e2, REAL* op, REAL* n);
-    REAL facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2);
-    void tetalldihedral(point, point, point, point, REAL*, REAL*, REAL*);
-    void tetallnormal(point, point, point, point, REAL N[4][3], REAL* volume);
-    REAL tetaspectratio(point, point, point, point);
-    bool circumsphere(REAL*, REAL*, REAL*, REAL*, REAL* cent, REAL* radius);
-    void inscribedsphere(REAL*, REAL*, REAL*, REAL*, REAL* cent, REAL* radius);
-    void rotatepoint(REAL* p, REAL rotangle, REAL* p1, REAL* p2);
-    void spherelineint(REAL* p1, REAL* p2, REAL* C, REAL R, REAL p[7]);
-    void linelineint(REAL *p1,REAL *p2, REAL *p3, REAL *p4, REAL p[7]);
-    void planelineint(REAL*, REAL*, REAL*, REAL*, REAL*, REAL*, REAL*);
-
-    // Memory managment routines.
-    void dummyinit(int, int);
-    void initializepools();
-    void tetrahedrondealloc(tetrahedron*);
-    tetrahedron *tetrahedrontraverse();
-    void shellfacedealloc(memorypool*, shellface*);
-    shellface *shellfacetraverse(memorypool*);
-    void badfacedealloc(memorypool*, badface*);
-    badface *badfacetraverse(memorypool*);
-    void pointdealloc(point);
-    point pointtraverse();
-    void maketetrahedron(triface*);
-    void makeshellface(memorypool*, face*);
-    void makepoint(point*);
-
-    // Mesh items searching routines.
-    void makepoint2tetmap();
-    void makeindex2pointmap(point*& idx2verlist);
-    void makesegmentmap(int*& idx2seglist, shellface**& segsperverlist);
-    void makesubfacemap(int*& idx2facelist, shellface**& facesperverlist);
-    void maketetrahedronmap(int*& idx2tetlist, tetrahedron**& tetsperverlist);
-
-    // Point location routines.
-    unsigned long randomnation(unsigned int choices);
-    REAL distance2(tetrahedron* tetptr, point p);
-    enum locateresult preciselocate(point searchpt, triface* searchtet, long);
-    enum locateresult locate(point searchpt, triface* searchtet);
-    enum locateresult adjustlocate(point, triface*, enum locateresult, REAL);
-    enum locateresult hullwalk(point searchpt, triface* hulltet);
-    enum locateresult locatesub(point searchpt, face* searchsh, int, REAL);
-    enum locateresult adjustlocatesub(point, face*, enum locateresult, REAL);
-    enum locateresult locateseg(point searchpt, face* searchseg);
-    enum locateresult adjustlocateseg(point, face*, enum locateresult, REAL);
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// Mesh Local Transformation Operators                                       //
-//                                                                           //
-// These operators (including flips, insert & remove vertices and so on) are //
-// used to transform (or replace) a set of mesh elements into another set of //
-// mesh elements.                                                            //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-    // Mesh transformation routines.
-    enum fliptype categorizeface(triface& horiz);
-    void enqueueflipface(triface& checkface, queue* flipqueue);
-    void enqueueflipedge(face& checkedge, queue* flipqueue);
-    void flip23(triface* flipface, queue* flipqueue);
-    void flip32(triface* flipface, queue* flipqueue);
-    void flip22(triface* flipface, queue* flipqueue);
-    void flip22sub(face* flipedge, queue* flipqueue);
-    long flip(queue* flipqueue, badface **plastflip);
-    long lawson(list *misseglist, queue* flipqueue);
-    void undoflip(badface *lastflip);
-    long flipsub(queue* flipqueue);
-    bool removetetbypeeloff(triface *striptet);
-    bool removefacebyflip23(REAL *key, triface*, triface*, queue*);
-    bool removeedgebyflip22(REAL *key, int, triface*, queue*);
-    bool removeedgebyflip32(REAL *key, triface*, triface*, queue*);
-    bool removeedgebytranNM(REAL*,int,triface*,triface*,point,point,queue*);
-    bool removeedgebycombNM(REAL*,int,triface*,int*,triface*,triface*,queue*);
-
-    void splittetrahedron(point newpoint, triface* splittet, queue* flipqueue);
-    void unsplittetrahedron(triface* splittet);
-    void splittetface(point newpoint, triface* splittet, queue* flipqueue);
-    void unsplittetface(triface* splittet);
-    void splitsubface(point newpoint, face* splitface, queue* flipqueue);
-    void unsplitsubface(face* splitsh);
-    void splittetedge(point newpoint, triface* splittet, queue* flipqueue);
-    void unsplittetedge(triface* splittet);
-    void splitsubedge(point newpoint, face* splitsh, queue* flipqueue);
-    void unsplitsubedge(face* splitsh);
-    enum insertsiteresult insertsite(point newpoint, triface* searchtet,
-                                     bool approx, queue* flipqueue);
-    void undosite(enum insertsiteresult insresult, triface* splittet, 
-                  point torg, point tdest, point tapex, point toppo);
-    void closeopenface(triface* openface, queue* flipque);
-    void inserthullsite(point inspoint, triface* horiz, queue* flipque);
-
-    void formbowatcavitysub(point, face*, list*, list*);
-    void formbowatcavityquad(point, list*, list*);
-    void formbowatcavitysegquad(point, list*, list*);
-    void formbowatcavity(point bp, face* bpseg, face* bpsh, int* n, int* nmax,
-                         list** sublists, list** subceillists, list** tetlists,
-                         list** ceillists);
-    void releasebowatcavity(face*, int, list**, list**, list**, list**);
-    bool validatebowatcavityquad(point bp, list* ceillist, REAL maxcosd);
-    void updatebowatcavityquad(list* tetlist, list* ceillist);
-    void updatebowatcavitysub(list* sublist, list* subceillist, int* cutcount);
-    bool trimbowatcavity(point bp, face* bpseg, int n, list** sublists,
-                         list** subceillists, list** tetlists,list** ceillists,
-                         REAL maxcosd);
-    void bowatinsertsite(point bp, face* splitseg, int n, list** sublists,
-                         list** subceillists, list** tetlists,
-                         list** ceillists, list* verlist, queue* flipque,
-                         bool chkencseg, bool chkencsub, bool chkbadtet);
-
-    // Delaunay tetrahedralization routines.
-    void formstarpolyhedron(point pt, list* tetlist, list* verlist, bool);
-    bool unifypoint(point testpt, triface*, enum locateresult, REAL);
-    void incrflipdelaunay(triface*, point*, long, bool, bool, REAL, queue*);
-    long delaunizevertices();
-
-    // Surface triangulation routines.
-    void formstarpolygon(point pt, list* trilist, list* verlist);
-    void getfacetabovepoint(face* facetsh);
-    void collectcavsubs(point newpoint, list* cavsublist);
-    void collectvisiblesubs(int shmark, point inspoint, face* horiz, queue*);
-    void incrflipdelaunaysub(int shmark, REAL eps, list*, int, REAL*, queue*);
-    enum finddirectionresult finddirectionsub(face* searchsh, point tend);
-    void insertsubseg(face* tri);
-    bool scoutsegmentsub(face* searchsh, point tend);
-    void flipedgerecursive(face* flipedge, queue* flipqueue);
-    void constrainededge(face* startsh, point tend, queue* flipqueue);
-    void recoversegment(point tstart, point tend, queue* flipqueue);
-    void infecthullsub(memorypool* viri);
-    void plaguesub(memorypool* viri);
-    void carveholessub(int holes, REAL* holelist, memorypool* viri);
-    void triangulate(int shmark, REAL eps, list* ptlist, list* conlist,
-                     int holes, REAL* holelist, memorypool* viri, queue*);
-    void retrievenewsubs(list* newshlist, bool removeseg);
-    void unifysegments();
-    void mergefacets(queue* flipqueue);
-    long meshsurface();
-
-    // Detect intersecting facets of PLC.
-    void interecursive(shellface** subfacearray, int arraysize, int axis,
-                       REAL bxmin, REAL bxmax, REAL bymin, REAL bymax,
-                       REAL bzmin, REAL bzmax, int* internum);
-    void detectinterfaces(); 
-
-    // Periodic boundary condition supporting routines.
-    void createsubpbcgrouptable();
-    void getsubpbcgroup(face* pbcsub, pbcdata** pd, int *f1, int *f2);
-    enum locateresult getsubpbcsympoint(point, face*, point, face*);
-    void createsegpbcgrouptable();
-    enum locateresult getsegpbcsympoint(point, face*, point, face*, int);
-
-    // Vertex perturbation routines.
-    REAL randgenerator(REAL range);
-    bool checksub4cocir(face* testsub, REAL eps, bool once, bool enqflag);
-    void tallcocirsubs(REAL eps, bool enqflag);
-    bool tallencsegsfsubs(point testpt, list* cavsublist);
-    void collectflipedges(point inspoint, face* splitseg, queue* flipqueue);
-    void perturbrepairencsegs(queue* flipqueue);
-    void perturbrepairencsubs(list* cavsublist, queue* flipqueue);
-    void incrperturbvertices(REAL eps);
-
-    // Segment recovery routines.
-    void markacutevertices(REAL acuteangle);
-    enum finddirectionresult finddirection(triface* searchtet, point, long);
-    void getsearchtet(point p1, point p2, triface* searchtet, point* tend);
-    bool isedgeencroached(point p1, point p2, point testpt, bool degflag);
-    point scoutrefpoint(triface* searchtet, point tend);
-    point getsegmentorigin(face* splitseg);
-    point getsplitpoint(face* splitseg, point refpoint);
-    bool insertsegment(face *insseg, list *misseglist);
-    void tallmissegs(list *misseglist);
-    void delaunizesegments();
-
-    // Facets recovery routines.
-    bool insertsubface(face* insertsh, triface* searchtet);
-    bool tritritest(triface* checktet, point p1, point p2, point p3);
-    void initializecavity(list* floorlist, list* ceillist, list* frontlist);
-    void delaunizecavvertices(triface*, list*, list*, list*, queue*);
-    void retrievenewtets(list* newtetlist);
-    void insertauxsubface(triface* front, triface* idfront);
-    bool scoutfront(triface* front, triface* idfront, list* newtetlist);
-    void gluefronts(triface* front, triface* front1);
-    bool identifyfronts(list* frontlist, list* misfrontlist, list* newtetlist);
-    void detachauxsubfaces(list* newtetlist);
-    void expandcavity(list* frontlist, list* misfrontlist, list* newtetlist,
-                      list* crosstetlist, queue* missingshqueue, queue*);
-    void carvecavity(list* newtetlist, list* outtetlist, queue* flipque);
-    void delaunizecavity(list* floorlist, list* ceillist, list* ceilptlist,
-                         list* floorptlist, list* frontlist,list* misfrontlist,
-                         list* newtetlist, list* crosstetlist, queue*, queue*);
-    void formmissingregion(face* missingsh, list* missingshlist,
-                           list* equatptlist, int* worklist);
-    void formcavity(list* missingshlist, list* crossedgelist, 
-                    list* equatptlist, list* crossshlist, list* crosstetlist,
-                    list* belowfacelist, list* abovefacelist,
-                    list* horizptlist, list* belowptlist, list* aboveptlist,
-                    queue* missingshqueue, int* worklist);
-    bool scoutcrossingedge(list* missingshlist, list* boundedgelist,
-                           list* crossedgelist, int* worklist);
-    void rearrangesubfaces(list* missingshlist, list* boundedgelist,
-                           list* equatptlist, int* worklist);
-    void insertallsubfaces(queue* missingshqueue);
-    void constrainedfacets();
-
-    // Carving out holes and concavities routines.
-    void infecthull(memorypool *viri);
-    void plague(memorypool *viri);
-    void regionplague(memorypool *viri, REAL attribute, REAL volume);
-    void removeholetets(memorypool *viri);
-    void assignregionattribs();
-    void carveholes();
-
-    // Steiner points removing routines.
-    void replacepolygonsubs(list* oldshlist, list* newshlist);
-    void orientnewsubs(list* newshlist, face* orientsh, REAL* norm);
-    bool constrainedflip(triface* flipface, triface* front, queue* flipque);
-    bool recoverfront(triface* front, list* newtetlist, queue* flipque);
-    void repairflips(queue* flipque);
-    bool constrainedcavity(triface* oldtet, list* floorlist, list* ceillist,
-                           list* ptlist, list* frontlist, list* misfrontlist,
-                           list* newtetlist, queue* flipque);
-    void expandsteinercavity(point steinpt, REAL eps, list* frontlist, list*);
-    bool findrelocatepoint(point sp, point np, REAL* n, list*, list*);
-    void relocatepoint(point steinpt, triface* oldtet, list*, list*, queue*);
-    bool findcollapseedge(point suppt, point* conpt, list* oldtetlist, list*);
-    void collapseedge(point suppt, point conpt, list* oldtetlist, list*);
-    void deallocfaketets(list* frontlist);
-    void restorepolyhedron(list* oldtetlist);
-    bool suppressfacetpoint(face* supsh, list* frontlist, list* misfrontlist,
-                            list* ptlist, list* conlist, memorypool* viri,
-                            queue* flipque, bool noreloc, bool optflag);
-    bool suppresssegpoint(face* supseg, list* spinshlist, list* newsegshlist,
-                          list* frontlist, list* misfrontlist, list* ptlist,
-                          list* conlist, memorypool* viri, queue* flipque,
-                          bool noreloc, bool optflag);
-    bool suppressvolpoint(triface* suptet, list* frontlist, list* misfrontlist,
-                          list* ptlist, queue* flipque, bool optflag);
-    bool smoothpoint(point smthpt, point, point, list *starlist, bool, REAL*);
-    void removesteiners(bool coarseflag);
-
-    // Mesh reconstruction routines.
-    long reconstructmesh();
-    // Constrained points insertion routines.
-    void insertconstrainedpoints(tetgenio *addio);
-    // Background mesh operations.
-    bool p1interpolatebgm(point pt, triface* bgmtet, long *scount);
-    void interpolatesizemap();
-    void duplicatebgmesh();
-
-    // Delaunay refinement routines.
-    void marksharpsegments(REAL sharpangle);
-    void decidefeaturepointsizes();
-    void enqueueencsub(face* ss, point encpt, int quenumber, REAL* cent);
-    badface* dequeueencsub(int* quenumber);
-    void enqueuebadtet(triface* tt, REAL key, REAL* cent);
-    badface* topbadtetra();
-    void dequeuebadtet();
-    bool checkseg4encroach(face* testseg, point testpt, point*, bool enqflag);
-    bool checksub4encroach(face* testsub, point testpt, bool enqflag);
-    bool checktet4badqual(triface* testtet, bool enqflag);
-    bool acceptsegpt(point segpt, point refpt, face* splitseg);
-    bool acceptfacpt(point facpt, list* subceillist, list* verlist);
-    bool acceptvolpt(point volpt, list* ceillist, list* verlist);
-    void getsplitpoint(point e1, point e2, point refpt, point newpt);
-    void shepardinterpolate(point newpt, list* verlist);
-    void setnewpointsize(point newpt, point e1, point e2);
-    void splitencseg(point, face*, list*, list*, list*,queue*,bool,bool,bool);
-    bool tallencsegs(point testpt, int n, list** ceillists);
-    bool tallencsubs(point testpt, int n, list** ceillists);
-    void tallbadtetrahedrons();
-    void repairencsegs(bool chkencsub, bool chkbadtet);
-    void repairencsubs(bool chkbadtet);
-    void repairbadtets();
-    void enforcequality();
-
-    // Mesh optimization routines.
-    void dumpbadtets();
-    bool checktet4ill(triface* testtet, bool enqflag);
-    bool checktet4opt(triface* testtet, bool enqflag);
-    bool removeedge(badface* remedge, bool optflag);
-    bool smoothsliver(badface* remedge, list *starlist);
-    bool splitsliver(badface* remedge, list *tetlist, list *ceillist);
-    void tallslivers(bool optflag);
-    void optimizemesh(bool optflag);
-
-    // I/O routines
-    void transfernodes();
-    void jettisonnodes();
-    void highorder();
-    void outnodes(tetgenio* out);
-    void outmetrics(tetgenio* out);
-    void outelements(tetgenio* out);
-    void outfaces(tetgenio* out);
-    void outhullfaces(tetgenio* out);
-    void outsubfaces(tetgenio* out);
-    void outedges(tetgenio* out);
-    void outsubsegments(tetgenio* out);
-    void outneighbors(tetgenio* out);
-    void outvoronoi(tetgenio* out);
-    void outpbcnodes(tetgenio* out);
-    void outsmesh(char* smfilename);
-    void outmesh2medit(char* mfilename);
-    void outmesh2gid(char* gfilename);
-    void outmesh2off(char* ofilename);
-
-    // User interaction routines.
-    void internalerror();
-    void checkmesh();
-    void checkshells();
-    void checkdelaunay(REAL eps, queue* flipqueue);
-    void checkconforming();
-    void algorithmicstatistics();
-    void qualitystatistics();
-    void statistics();
+// Bowyer and Watson's incrmental insertion algorithm [Bowyer81, Watson81],  //
+// and Edelsbrunner and Shah's incrmental flip algorithm [Edelsbrunner96].   //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
 
-  public:
+void initialDT(point pa, point pb, point pc, point pd);
+enum location insertvertex(point, triface*, bool, bool, bool, bool);
+void flipinsertvertex(point, triface*, int);
+void incrementaldelaunay();
 
-    // Constructor and destructor.
-    tetgenmesh();
-    ~tetgenmesh();
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Surface mesh routines.                                                    //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool calculateabovepoint(arraypool*, point*, point*, point*);
+enum location slocate(point, face*, bool);
+enum location sinsertvertex(point, face*, face*, bool, bool);
+enum intersection sscoutsegment(face* searchsh, point endpt);
+void scarveholes(int, REAL*);
+void triangulate(int, arraypool*, arraypool*, int, REAL*);
+
+void unifysubfaces(face*, face*);
+void unifysegments();
+void mergefacets();
+void markacutevertices();
+void meshsurface();
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Boundary recovery functions.                                              //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+enum intersection finddirection(triface* searchtet, point endpt);
+enum intersection scoutsegment(face* sseg, triface* searchtet, point* refpt);
+void getsegmentsplitpoint(face* sseg, point refpt, REAL* vt);
+void delaunizesegments();
+
+enum intersection scoutsubface(face* ssub, triface* searchtet);
+enum intersection scoutcrosstet(face* ssub, triface* searchtet, arraypool*);
+void recoversubfacebyflips(face* pssub, triface* crossface, arraypool*);
+void formcavity(face*, arraypool*, arraypool*, arraypool*, arraypool*, 
+                arraypool*, arraypool*);
+void formedgecavity(point, point, arraypool*, arraypool*, arraypool*);
+bool delaunizecavity(arraypool*, arraypool*, arraypool*, arraypool*,
+                     arraypool*, arraypool*);
+bool fillcavity(arraypool*, arraypool*, arraypool*, arraypool*);
+void carvecavity(arraypool*, arraypool*, arraypool*);
+void restorecavity(arraypool*, arraypool*, arraypool*);
+void splitsubedge(point, face*, arraypool*, arraypool*);
+void constrainedfacets();
+
+void formskeleton();
+void carveholes();
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Mesh input & output functions.                                            //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void transfernodes();
+void reconstructmesh();
+void jettisonnodes();
+void highorder();
+void numberedges();
+void numbersubedges();
+void outnodes(tetgenio* out);
+void outelements(tetgenio* out);
+void outfaces(tetgenio* out);
+void outhullfaces(tetgenio* out);
+void outsubfaces(tetgenio* out);
+void outedges(tetgenio* out);
+void outsubsegments(tetgenio* out);
+void outneighbors(tetgenio* out);
+void outvoronoi(tetgenio* out);
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Mesh statistic functions.                                                 //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
 
-};                                               // End of class tetgenmesh.
+void checkmesh();
+int checkshells(int);
+int checkdelaunay(int);
+int checksegments();
+void checkconforming();
+void algorithmstatistics();
+void qualitystatistics();
+void statistics();
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Class Constructor and Destructor.                                         //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void initialize()
+{
+  in = (tetgenio *) NULL;
+  b = (tetgenbehavior *) NULL;
+  tetrahedronpool = (memorypool *) NULL;
+  subfacepool = subsegpool = (memorypool *) NULL;
+  tet2segpool = tet2subpool = (memorypool *) NULL;
+  pointpool = (memorypool *) NULL;
+  flippool = (memorypool *) NULL;
+  dummypoint = (point) NULL;
+  futureflip = (badface *) NULL;
+  cavetetlist = cavebdrylist = caveoldtetlist = (arraypool *) NULL;
+  caveshlist = caveshbdlist = (arraypool *) NULL;
+  subsegstack = subfacstack = (arraypool *) NULL;
+  point2tetindex = pointmarkindex = 0;
+  elemmarkerindex = 0;
+  elemattribindex = volumeboundindex = highorderindex = 0;
+  hullsize = 0l;
+  randomseed = samples = 1l;
+  recenttet.tet = (tetrahedron *) NULL;
+  recenttet.loc = recenttet.ver = 0;
+  xmax = xmin = ymax = ymin = zmax = zmin = 0.0;
+  dupverts = meshedges = meshsubedges = insegments = 0l;
+  checkconstraints = checksubfaces = checksubsegs = checkpbcs = 0;
+  ptloc_count = ptloc_max_count = 0l;
+  orient3dcount = 0l;
+  inspherecount = insphere_sos_count = 0l;
+  maxbowatcavsize = totalbowatcavsize = totaldeadtets = 0l;
+  flip14count = flip26count = flipn2ncount = 0l;
+  flip23count = flip32count = flipnmcount = 0l;
+  flip13count = flip22count = flipn2nfcount = 0l;
+  tloctime = tfliptime = tinserttime = 0.0;
+  triedgcount = triedgcopcount = trivercopcount = 0l;
+  across_face_count = across_edge_count = across_max_count = 0l;
+  r1count = r2count = r3count = 0l;
+  maxcavsize = maxregionsize = 0l;
+  ndelaunayedgecount = cavityexpcount = 0l;
+}
+
+void deinitialize()
+{
+  in = (tetgenio *) NULL;
+  b = (tetgenbehavior *) NULL;
+  if (pointpool != (memorypool *) NULL) {
+    delete pointpool;
+    delete [] dummypoint;
+  }
+  if (tetrahedronpool != (memorypool *) NULL) {
+    delete tetrahedronpool;
+    delete cavetetlist;
+    delete cavebdrylist;
+    delete caveoldtetlist;
+    delete flippool;
+  }
+  if (subfacepool != (memorypool *) NULL) {
+    delete subfacepool;
+    delete subsegpool;
+    delete tet2segpool;
+    delete tet2subpool;
+    delete subsegstack;
+    delete subfacstack;
+    delete caveshlist;
+    delete caveshbdlist;
+  }
+  futureflip = (badface *) NULL;
+}
+
+tetgenmesh() 
+{
+  initialize();
+}
+
+~tetgenmesh() 
+{
+  deinitialize();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// Debug functions.                                                          //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void ptet(triface* t);
+void psh(face* s);
+void pteti(int i, int j, int k, int l);
+void pface(int i, int j, int k);
+bool pedge(int i, int j);
+void psubface(int i, int j, int k);
+void psubseg(int i, int j);
+int pmark(point p);
+void pvert(point p);
+int pverti(int i);
+REAL test_orient3d(int i, int j, int k, int l);
+REAL test_insphere(int i, int j, int k, int l, int m);
+int test_tritri(int a, int b, int c, int p,  int q, int r);
+void print_cavebdrylist();
+void print_flipstack();
+void print_tetarray(arraypool* tetarray, bool nohulltet);
+void print_facearray(arraypool* facearray);
+void print_subfacearray(arraypool* subfacearray);
+void dump_cavity(arraypool *topfaces, arraypool *botfaces);
+void dump_facetof(face* pssub, char* filename);
+
+///////////////////////////////////////////////////////////////////////////////
+};  // End of class tetgenmesh;
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// terminatetetgen()    Terminate TetGen with a given exit code.             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void terminatetetgen(int x);
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
@@ -1910,6 +1852,7 @@ class tetgenmesh {
 
 void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out, 
                     tetgenio *addin = NULL, tetgenio *bgmin = NULL);
+
 void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
                     tetgenio *addin = NULL, tetgenio *bgmin = NULL);
 
diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi
index 8af6a22708fc5eaa13631dbb260fbc7a011f8016..f7a36f5c7928c052429fe5fd040c9037365a987b 100644
--- a/doc/texinfo/gmsh.texi
+++ b/doc/texinfo/gmsh.texi
@@ -2150,6 +2150,16 @@ algorithm can be quite poor.
 @c holes with surfaces in contact with the exterior shell, intersecting
 @c primitives, etc.)
 
+@c todo: add section explaining which algorithm to choose in which
+@c situation: 2D (robustness: MeshAdapt>Delaunay>Frontal; performance:
+@c Delaunay>Frontal>MeshAdapt; element quality:
+@c Frontal>Delaunay/MeshAdapt). Tip: for large 2D/plane meshes use
+@c Delaunay/or frontal. Most robust algo for complex curved surfaces:
+@c meshadapt. 3D: most robust and fastest: Tetgen+Delaunay. But if you
+@c need coupling to structured grid: Netgen. In most cases, you should
+@c optimize the mesh.
+
+
 @menu
 * Elementary vs physical entities::  
 * Mesh commands::