[tetgen] 03/15: Remove unused patch.

Anton Gladky gladk at moszumanska.debian.org
Tue Jan 28 22:13:45 UTC 2014


This is an automated email from the git hooks/post-receive script.

gladk pushed a commit to branch master
in repository tetgen.

commit e4b48d6517aad9277d7d744d6b1f903440d3b78d
Author: Anton Gladky <gladk at debian.org>
Date:   Tue Jan 28 20:20:14 2014 +0100

    Remove unused patch.
---
 debian/patches/quality.patch | 14927 -----------------------------------------
 1 file changed, 14927 deletions(-)

diff --git a/debian/patches/quality.patch b/debian/patches/quality.patch
deleted file mode 100644
index 4150041..0000000
--- a/debian/patches/quality.patch
+++ /dev/null
@@ -1,14927 +0,0 @@
-Index: tetgen1.4.2/tetgen.cxx
-===================================================================
---- tetgen1.4.2.orig/tetgen.cxx	2008-02-16 01:32:45.022628815 +0100
-+++ tetgen1.4.2/tetgen.cxx	2008-02-16 01:33:00.862609011 +0100
-@@ -5,18 +5,16 @@
- // A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
- //                                                                           //
- // Version 1.4                                                               //
--// April 16, 2007                                                            //
-+// January 14, 2006                                                          //
- //                                                                           //
--// Copyright (C) 2002--2007                                                  //
-+// Copyright 2002, 2004, 2005, 2006                                          //
- // Hang Si                                                                   //
--// Research Group Numerical Mathematics and Scientific Computing             //
--// Weierstrass Institute for Applied Analysis and Stochastics                //
--// Mohrenstr. 39, 10117 Berlin, Germany                                      //
-+// Rathausstr. 9, 10178 Berlin, Germany                                      //
- // si at 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.     //
-+// You can obtain TetGen via internet: http://tetgen.berlios.de.  It may be  //
-+//   freely copied, modified, and redistributed under the copyright notices  //
-+//   given in the file LICENSE.                                              //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
-@@ -24,7 +22,7 @@
- //                                                                           //
- // tetgen.cxx                                                                //
- //                                                                           //
--// The TetGen library and program.                                           //
-+// The C++ implementation file of the TetGen library.                        //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
-@@ -66,15 +64,15 @@
- {
-   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;
-+  addpointlist = (REAL *) NULL;
-+  addpointattributelist = (REAL *) NULL;
-   pointmarkerlist = (int *) NULL;
-   numberofpoints = 0;
-   numberofpointattributes = 0;
--  numberofpointmtrs = 0;
-+  numberofaddpoints = 0;
- 
-   tetrahedronlist = (int *) NULL;
-   tetrahedronattributelist = (REAL *) NULL;
-@@ -107,18 +105,11 @@
-   numberoffacetconstraints = 0;
-   segmentconstraintlist = (REAL *) NULL;
-   numberofsegmentconstraints = 0;
-+  nodeconstraintlist = (REAL *) NULL;
-+  numberofnodeconstraints = 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;
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -149,8 +140,11 @@
-   if (pointattributelist != (REAL *) NULL) {
-     delete [] pointattributelist;
-   }
--  if (pointmtrlist != (REAL *) NULL) {
--    delete [] pointmtrlist;
-+  if (addpointlist != (REAL *) NULL) {
-+    delete [] addpointlist;
-+  }
-+  if (addpointattributelist != (REAL *) NULL) {
-+    delete [] addpointattributelist;
-   }
-   if (pointmarkerlist != (int *) NULL) {
-     delete [] pointmarkerlist;
-@@ -216,6 +210,9 @@
-   if (segmentconstraintlist != (REAL *) NULL) {
-     delete [] segmentconstraintlist;
-   }
-+  if (nodeconstraintlist != (REAL *) NULL) {
-+    delete [] nodeconstraintlist;
-+  }
-   if (pbcgrouplist != (pbcgroup *) NULL) {
-     for (i = 0; i < numberofpbcgroups; i++) {
-       pg = &(pbcgrouplist[i]);
-@@ -225,24 +222,6 @@
-     }
-     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;
--  }
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -295,15 +274,13 @@
-   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;
--        }
-+    if (i == 0) {
-+      firstnode = (int) strtol (stringptr, &stringptr, 0);
-+      if ((firstnode == 0) || (firstnode == 1)) {
-+        firstnumber = firstnode;
-       }
--      stringptr = findnextnumber(stringptr);
--    } // if (useindex)
-+    }
-+    stringptr = findnextnumber(stringptr);
-     if (*stringptr == '\0') {
-       printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
-       break;
-@@ -395,50 +372,34 @@
-     return false;
-   }
-   printf("Opening %s.\n", innodefilename);  
--  // Read the first line of the file.
-+  // Read number of points, number of dimensions, number of point
-+  //   attributes, and number of boundary markers.
-   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);
--    }
-+  numberofpoints = (int) strtol (stringptr, &stringptr, 0);
-+  stringptr = findnextnumber(stringptr);
-+  if (*stringptr == '\0') {
-+    mesh_dim = 3;
-   } 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;
-+  }
-+  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);
-   }
- 
--  // if ((mesh_dim != 3) && (mesh_dim != 2)) {
--  //   printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
--  //   fclose(infile);
--  //   return false;
--  // }
-+  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);
-@@ -456,6 +417,91 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
-+// load_addnodes()    Load a list of additional nodes into 'addpointlists'.  //
-+//                                                                           //
-+// 'filename' is the filename of the original inputfile without suffix. The  //
-+// additional nodes are found in file 'filename-a.node'.                     //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+bool tetgenio::load_addnodes(char* filename)
-+{
-+  FILE *infile;
-+  char addnodefilename[FILENAMESIZE];
-+  char inputline[INPUTLINESIZE];
-+  char *stringptr;
-+  REAL x, y, z;
-+  int index;
-+  int i;
-+
-+  // Additional nodes are saved in file "filename-a.node".
-+  strcpy(addnodefilename, filename);
-+  strcat(addnodefilename, "-a.node");
-+  infile = fopen(addnodefilename, "r");
-+  if (infile != (FILE *) NULL) {
-+    printf("Opening %s.\n", addnodefilename);
-+  } else {
-+    // Strange! However, it is not a fatal error.
-+    printf("Warning:  Can't opening %s. Skipped.\n", addnodefilename);
-+    numberofaddpoints = 0;
-+    return false;
-+  }
-+
-+  // Read the number of additional points.
-+  stringptr = readnumberline(inputline, infile, addnodefilename);
-+  numberofaddpoints = (int) strtol (stringptr, &stringptr, 0);
-+  if (numberofaddpoints == 0) {
-+    // It looks this file contains no point.
-+    fclose(infile);
-+    return false; 
-+  }
-+  // Initialize 'addpointlist';
-+  addpointlist = new REAL[numberofaddpoints * mesh_dim];
-+  if (addpointlist == (REAL *) NULL) {
-+    printf("Error:  Out of memory.\n");
-+    terminatetetgen(1);
-+  }
-+
-+  // Read the list of additional points.
-+  index = 0;
-+  for (i = 0; i < numberofaddpoints; i++) {
-+    stringptr = readnumberline(inputline, infile, addnodefilename);
-+    stringptr = findnextnumber(stringptr);
-+    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);
-+    stringptr = findnextnumber(stringptr);
-+    if (*stringptr == '\0') {
-+      printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
-+      break;
-+    }
-+    z = (REAL) strtod(stringptr, &stringptr);
-+    addpointlist[index++] = x;
-+    addpointlist[index++] = y;
-+    addpointlist[index++] = z;
-+  }
-+  fclose(infile);
-+
-+  if (i < numberofaddpoints) {
-+    // Failed to read to additional points due to some error.
-+    delete [] addpointlist;
-+    addpointlist = (REAL *) NULL;
-+    numberofaddpoints = 0;
-+    return false;
-+  }
-+  return true;
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
- // load_pbc()    Load a list of pbc groups into 'pbcgrouplist'.              //
- //                                                                           //
- // 'filename' is the filename of the original inputfile without suffix. The  //
-@@ -670,6 +716,43 @@
-     }
-   }
- 
-+  // Read the node constraint section. It is optional.
-+  stringptr = readnumberline(inputline, infile, NULL);
-+  if (stringptr != (char *) NULL && *stringptr != '\0') {
-+    numberofnodeconstraints = (int) strtol (stringptr, &stringptr, 0);
-+  } else {
-+    numberofnodeconstraints = 0;
-+  }
-+  if (numberofnodeconstraints > 0) {
-+    // Initialize 'nodeconstraintlist'.
-+    nodeconstraintlist = new REAL[numberofnodeconstraints * 2];
-+    index = 0;
-+    for (i = 0; i < numberofnodeconstraints; i++) {
-+      stringptr = readnumberline(inputline, infile, varfilename);
-+      stringptr = findnextnumber(stringptr);
-+      if (*stringptr == '\0') {
-+        printf("Error:  node constraint %d has no node index.\n",
-+               firstnumber + i);
-+        break;
-+      } else {
-+        nodeconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
-+      }
-+      stringptr = findnextnumber(stringptr);
-+      if (*stringptr == '\0') {
-+        printf("Error:  node constraint %d has no edge length bound.\n",
-+               firstnumber + i);
-+        break;
-+      } else {
-+        nodeconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
-+      }
-+    }
-+    if (i < numberofnodeconstraints) {
-+      // This must be caused by an error.
-+      fclose(infile);
-+      return false;
-+    }
-+  }
-+
-   fclose(infile);
-   return true;
- }
-@@ -689,8 +772,8 @@
-   char mtrfilename[FILENAMESIZE];
-   char inputline[INPUTLINESIZE];
-   char *stringptr;
--  REAL mtr;
--  int mtrindex;
-+  REAL attrib;
-+  int attribindex;
-   int i, j;
- 
-   strcpy(mtrfilename, filename);
-@@ -706,33 +789,38 @@
-   // 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;
-+  i = (int) strtol (stringptr, &stringptr, 0);
-+  if ((i != 1) && (i != 3) && (i != 6)) {
-+    // Column number doesn't match. Do nothing with this file.
-+    fclose(infile);
-+    return false;
-   }
- 
--  // Allocate space for pointmtrlist.
--  pointmtrlist = new REAL[numberofpoints * numberofpointmtrs];
--  if (pointmtrlist == (REAL *) NULL) {
-+  // Metric tensors are saved in pointattributelist.
-+  if (pointattributelist != (REAL *) NULL) {
-+    delete [] pointattributelist;
-+    pointattributelist = (REAL *) NULL;
-+  }
-+  numberofpointattributes = i;
-+  // Allocate space for pointattributelist.
-+  pointattributelist = new REAL[numberofpoints * numberofpointattributes];
-+  if (pointattributelist == (REAL *) NULL) {
-     printf("Error:  Out of memory.\n");
-     terminatetetgen(1);
-   }
--  mtrindex = 0;
-+  attribindex = 0;
-   for (i = 0; i < numberofpoints; i++) {
-     // Read metrics.
-     stringptr = readnumberline(inputline, infile, mtrfilename);
--    for (j = 0; j < numberofpointmtrs; j++) {
-+    for (j = 0; j < numberofpointattributes; j++) {
-+      // stringptr = findnextnumber(stringptr);
-       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);
-+      attrib = (REAL) strtod(stringptr, &stringptr);
-+      pointattributelist[attribindex++] = attrib;
-     }
-   }
- 
-@@ -1729,21 +1817,20 @@
- // 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.//
-+// This routine ONLY reads the sections containing vertices and triangles,   //
-+// other sections (such as tetrahedra, edges, ...) are ignored.              //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
- bool tetgenio::load_medit(char* filename)
- {
-   FILE *fp;
--  tetgenio::facet *tmpflist, *f;
-+  tetgenio::facet *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;
-@@ -1844,7 +1931,6 @@
-     } 
-     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");
-@@ -1867,32 +1953,13 @@
-         }
-         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];
--          }
-+        if (nfaces > 0) {        
-+          numberoffacets = nfaces;
-+          facetlist = new tetgenio::facet[nfaces];
-+          facetmarkerlist = new int[nfaces];
-         }
-         // Read the following list of faces.
--        for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
-+        for (i = 0; i < nfaces; i++) {
-           bufferp = readline(buffer, fp, &line_count);
-           if (bufferp == NULL) {
-             printf("Unexpected end of file on line %d in file %s\n",
-@@ -1934,12 +2001,10 @@
-             facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
-           }
-         }
--        // Have read in a list of triangles/quads.
--        numberoffacets += nfaces;
--        nfaces = 0;
-+        continue;
-       }
-     }
--    // if (nverts > 0 && nfaces > 0) break; // Ignore other data.
-+    if (nverts > 0 && nfaces > 0) break; // Ignore other data.
-   }
- 
-   // Close file
-@@ -2027,43 +2092,38 @@
-     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);
--    }
-+  // Read number of points, number of dimensions, number of point
-+  //   attributes, and number of boundary markers.
-+  stringptr = readnumberline(inputline, infile, infilename);
-+  numberofpoints = (int) strtol (stringptr, &stringptr, 0);
-+  stringptr = findnextnumber(stringptr);
-+  if (*stringptr == '\0') {
-+    mesh_dim = 3;
-   } 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;
-+  }
-+  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);
-+  }
-+
-+  if (mesh_dim != 3) {
-+    printf("Error:  load_tetmesh() only works for 3D points.\n");
-+    fclose(infile);
-+    return false;
-+  }
-+  if (numberofpoints < 4) {
-+    printf("File I/O error:  Input should has at least 4 points.\n");
-+    fclose(infile);
-+    return false;
-   }
- 
-   // Load the list of nodes.
-@@ -2074,92 +2134,86 @@
-   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;
-+  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 tetrahedra.
--      if (numberoftetrahedra > 0) {
--        tetrahedronlist = new int[numberoftetrahedra * numberofcorners]; 
--        if (tetrahedronlist == (int *) NULL) {
-+      // 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);
-         }
--        // 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 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);
-         }
--        // 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;
-+        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)
-+    fclose(infile);
-+  }
-   
-   // Read the hullfaces or subfaces from a .face file if it exists.
--  if (mesh_dim == 3) {
--    infilename = infacefilename;
--  } else {
--    infilename = inelefilename;
--  }
-+  infilename = infacefilename;
-   infile = fopen(infilename, "r");
-   if (infile != (FILE *) NULL) {
-     printf("Opening %s.\n", infilename);
-@@ -2167,10 +2221,6 @@
-     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 {
-@@ -2307,177 +2357,16 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// load_voronoi()    Load a Voronoi diagram from files.                      //
-+// save_nodes()    Save points to a .node file.                              //
- //                                                                           //
--// 'filename' is the inputfile without suffix.  The Voronoi diagram is read  //
--// from files: filename.v.node, filename.v.edge, and filename.v.face.        //
-+// 'filename' is a string containing the file name without suffix.           //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--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)
-+void tetgenio::save_nodes(char* filename)
- {
-   FILE *fout;
-   char outnodefilename[FILENAMESIZE];
--  char outmtrfilename[FILENAMESIZE];
-   int i, j;
- 
-   sprintf(outnodefilename, "%s.node", filename);
-@@ -2502,22 +2391,8 @@
-     }
-     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);
--  }
-+  fclose(fout);
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -2897,16 +2772,16 @@
- {
-   // Initialize command line switches.
-   plc = 0;
--  quality = 0;
-   refine = 0;
--  coarse = 0;
-+  quality = 0;
-+  smooth = 1;
-   metric = 0;
-+  bgmesh = 0;
-   minratio = 2.0;
-   goodratio = 0.0;
-   minangle = 20.0;
-   goodangle = 0.0;
--  maxdihedral = 165.0;
--  mindihedral = 5.0;
-+  maxdihedral = 170.0;
-   varvolume = 0;
-   fixedvolume = 0;
-   maxvolume = -1.0;
-@@ -2916,18 +2791,15 @@
-   offcenter = 0;
-   conformdel = 0;
-   alpha1 = sqrt(2.0);
--  alpha2 = 1.0;
-+  alpha2 = 0.5;
-   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;
-@@ -2943,6 +2815,7 @@
-   docheck = 0;
-   quiet = 0;
-   verbose = 0;
-+  tol = 0;
-   useshelles = 0;
-   epsilon = 1.0e-8;
-   epsilon2 = 1.0e-5;
-@@ -2951,7 +2824,6 @@
-   commandline[0] = '\0';
-   infilename[0] = '\0';
-   outfilename[0] = '\0';
--  addinfilename[0] = '\0';
-   bgmeshfilename[0] = '\0';
- }
- 
-@@ -2963,12 +2835,7 @@
- 
- 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 at wias-berlin.de\n");
-+  printf("Version 1.4.1 (July 06, 2006).\n");
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -2979,28 +2846,27 @@
- 
- 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("  tetgen [-pq__a__AriMYS__T__dzjo_fengGOJBNEFICQVvh] input_file\n");
-+  printf("    -p  Tetrahedralizes a piecewise linear complex.\n");
-+  printf("    -q  Quality mesh generation. A minimum radius-edge ratio may\n");
-+  printf("        be specified (default 2.0).\n");
-   printf("    -a  Applies a maximum tetrahedron volume constraint.\n");
-   printf("    -A  Assigns attributes to identify tetrahedra in different ");
-   printf("regions.\n");
-+  printf("    -r  Reconstructs and Refines a previously generated mesh.\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("    -S  Specifies maximum number of added Steiner points.\n");
-+  printf("    -T  Set a tolerance for coplanar test (default 1e-8).\n");
-+  printf("    -d  Diagnoses the validation of the input 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("    -P  Outputs triangulated PLC facets to .smesh file.\n");
-+  printf("    -f  Outputs all faces (instead of boundary faces) to .face ");
-   printf("file.\n");
--  printf("    -e  Outputs all edges to .edge file.\n");
-+  printf("    -e  Outputs subsegments 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");
-@@ -3013,6 +2879,7 @@
-   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("    -v  Prints the version information.\n");
-   printf("    -h  Help:  A brief instruction for using TetGen.\n");
- }
- 
-@@ -3029,6 +2896,11 @@
-   printf("Triangulator\n");
-   versioninfo();
-   printf("\n");
-+  printf("Copyright 2002, 2004, 2005, 2006\n");
-+  printf("Hang Si\n");
-+  printf("Rathausstr. 9, 10178 Berlin, Germany\n");
-+  printf("si at wias-berlin.de\n");
-+  printf("\n");
-   printf("What Can TetGen Do?\n");
-   printf("\n");
-   printf("  TetGen generates exact Delaunay tetrahedralizations, exact\n");
-@@ -3102,7 +2974,7 @@
-   int startindex;
-   int increment;
-   int meshnumber;
--  int scount;
-+  int Rcount;
-   int i, j, k;
-   char workstring[1024];
- 
-@@ -3118,7 +2990,7 @@
-   }
-   
-   // Rcount used to count the number of '-R' be used.
--  scount = 0;
-+  Rcount = 0;
- 
-   for (i = startindex; i < argc; i++) {
-     // Remember the command line switches.
-@@ -3139,34 +3011,12 @@
-         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++;
-+        metric = 1;
-+      } else if (argv[i][j] == 'b') {
-+        bgmesh = 1;
-+      } else if (argv[i][j] == 'q') {
-+        quality = 1;
-         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-             (argv[i][j + 1] == '.')) {
-           k = 0;
-@@ -3177,13 +3027,10 @@
-             k++;
-           }
-           workstring[k] = '\0';
--          if (metric == 1) {
--            alpha1 = (REAL) strtod(workstring, (char **) NULL);
--          } else if (metric == 2) {
--            alpha2 = (REAL) strtod(workstring, (char **) NULL);
--          }
--        }
-+          minratio = (REAL) strtod(workstring, (char **) NULL);
-+        } 
-       } else if (argv[i][j] == 'a') {
-+        quality = 1;
-         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-             (argv[i][j + 1] == '.')) {
-           fixedvolume = 1;
-@@ -3211,11 +3058,9 @@
-       } else if (argv[i][j] == 'f') {
-         facesout = 1;
-       } else if (argv[i][j] == 'e') {
--        edgesout++;
-+        edgesout = 1;
-       } 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') {
-@@ -3258,7 +3103,6 @@
-           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;
-@@ -3270,15 +3114,34 @@
-             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);
-+          maxdihedral = (REAL) strtod(workstring, (char **) NULL);
-+          if (maxdihedral >= 180.0) smooth = 0;
-+        }
-+      } else if (argv[i][j] == 'R') {
-+        Rcount++;
-+        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 (Rcount == 1) {
-+            alpha1 = (REAL) strtod(workstring, (char **) NULL);
-+          } else if (Rcount == 2) {
-+            alpha2 = (REAL) strtod(workstring, (char **) NULL);
-+          } else if (Rcount == 3) {
-+            alpha3 = (REAL) strtod(workstring, (char **) NULL);
-+          } 
-         }
-       } else if (argv[i][j] == 'D') {
-         conformdel++;
-       } else if (argv[i][j] == 'T') {
-+        tol++;
-         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-             (argv[i][j + 1] == '.')) {
-           k = 0;
-@@ -3290,7 +3153,11 @@
-             k++;
-           }
-           workstring[k] = '\0';
--          epsilon = (REAL) strtod(workstring, (char **) NULL);
-+          if (tol == 1) {
-+            epsilon = (REAL) strtod(workstring, (char **) NULL);
-+          } else if (tol == 2) {
-+            epsilon2 = (REAL) strtod(workstring, (char **) NULL);
-+          }
-         } 
-       } else if (argv[i][j] == 'C') {
-         docheck++;
-@@ -3300,9 +3167,9 @@
-         quiet = 1;
-       } else if (argv[i][j] == 'V') {
-         verbose++;
--      // } else if (argv[i][j] == 'v') {
--        // versioninfo();
--        // terminatetetgen(0);
-+      } else if (argv[i][j] == 'v') {
-+        versioninfo();
-+        terminatetetgen(0);
-       } else if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
-                  (argv[i][j] == '?')) {
-         usage();
-@@ -3357,7 +3224,7 @@
-     }
-   }
-   plc = plc || diagnose;
--  useshelles = plc || refine || coarse || quality;
-+  useshelles = plc || refine || quality;
-   goodratio = minratio;
-   goodratio *= goodratio;
- 
-@@ -3368,7 +3235,7 @@
-   }
-   if (refine && (plc || noiterationnum)) {
-     printf("Error:  Switches %s cannot use together with -r.\n",
--           "-p, -d, and -I");
-+           "-p, -d, -c, and -I");
-     return false;
-   }
-   if (diagnose && (quality || insertaddpoints || (order == 2) || neighout
-@@ -3388,12 +3255,6 @@
-   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;
-@@ -3430,9 +3291,6 @@
-     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");
-@@ -4188,15 +4046,18 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// del()    Delete a node.                                                   //
-+// del()    Delete a node containing the given pointer.                      //
- //                                                                           //
- // 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* tetgenmesh::link::del(void* delitem)
- {
-+  void **deadnode = (void **) ((void **) delitem - 2);
-+  
-+  // now delete the nownode
-   void **nextnode = (void **) *deadnode;
-   void **prevnode = (void **) *(deadnode + 1);
-   *prevnode = (void *) nextnode;
-@@ -4224,7 +4085,7 @@
-   if (!locate(pos) || (linkitems == 0)) {
-     return (void *) NULL;
-   }
--  return deletenode((void **) nextlinkitem);
-+  return del((void *) ((void **) nextlinkitem + 2));
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -4359,26 +4220,6 @@
-   { {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.
- //
-@@ -4528,67 +4369,12 @@
- //   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;
-+inline bool tetgenmesh::fnext(triface& t1, triface& t2) {
-+  return getnextface(&t1, &t2);
-+}
-+
-+inline bool tetgenmesh::fnextself(triface& t) {
-+  return getnextface(&t, NULL);
- }
- 
- // enextfnext() and enext2fnext() are combination primitives of enext(),
-@@ -4923,32 +4709,6 @@
- //
- 
- //
--// 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
- //
- 
-@@ -5082,6 +4842,64 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
-+// getnextface()    Get the successor of 'tface1' in the face ring.          //
-+//                                                                           //
-+// If 'tface1' is not a boundary (or hull) face, then its successor in the   //
-+// face ring exists. The successor is returned in 'tface2' if it is not a    //
-+// NULL, or the 'tface1' itself is used to return this face. On finish, the  //
-+// function returns TRUE.                                                    //
-+//                                                                           //
-+// If 'tface1' is a boundary (or hull) face, its successor does not exist.   //
-+// This case, return FALSE and 'tface1' remains unchanged.                   //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+bool tetgenmesh::getnextface(triface* tface1, triface* tface2)
-+{
-+  point torg, tdest;
-+  int tloc, tver;
-+
-+  // Where the next face locates, in 'tface1' or in its neigbhour? It can be
-+  //   quickly determined by checking the edge ring of 'tface1'.
-+  // if (EdgeRing(tface1->ver) == CW) {
-+  if ((tface1->ver & 01) == CW) {
-+    // The next face is in the neigbhour of 'tface1'.
-+    if (!issymexist(tface1)) {
-+      // Hit outer space - The next face does not exist.
-+      return false;
-+    }
-+    torg = org(*tface1);
-+    tdest = dest(*tface1);
-+    if (tface2) {
-+      sym(*tface1, *tface2);
-+      findedge(tface2, torg, tdest);
-+    } else {
-+      symself(*tface1);
-+      findedge(tface1, torg, tdest);
-+    }
-+  } else {
-+    // The next face is in 'tface1'.
-+    if (tface2) {
-+      *tface2 = *tface1;
-+    }
-+  }
-+
-+  if (tface2) {
-+    tloc = tface2->loc;
-+    tver = tface2->ver;
-+    tface2->loc = locver2nextf[tloc][tver][0];
-+    tface2->ver = locver2nextf[tloc][tver][1];
-+  } else {
-+    tloc = tface1->loc;
-+    tver = tface1->ver;
-+    tface1->loc = locver2nextf[tloc][tver][0];
-+    tface1->ver = locver2nextf[tloc][tver][1];
-+  }
-+  return true;
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
- // getnextsface()    Finds the next subface in the face ring.                //
- //                                                                           //
- // For saving space in the data structure of subface, there only exists one  //
-@@ -5149,13 +4967,13 @@
-   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.      
-+    if (parentsh.sh != dummysh && !isdead(&parentsh)) {
-+      // Find a subface!
-       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)) {
-+        if (sorg(*checkseg) != sorg(parentsh)) {
-           sesymself(*checkseg);
-         }
-       }
-@@ -5659,7 +5477,7 @@
-   if (b->useshelles) {
-     tmpface = *tface;
-     facecount = 0;
--    while(facecount < 6) {
-+    while(facecount < 4) {
-       tmpface.loc = facecount;
-       tspivot(tmpface, tmpsh);
-       if(tmpsh.sh != dummysh) {
-@@ -5705,6 +5523,8 @@
-   if (sapex(*sface) != NULL) {
-     if (shelltype(*sface) == SHARP) {
-       printf(" (sharp)");
-+    } else if (shelltype(*sface) == SKINNY) {
-+      printf(" (skinny)");
-     }
-   } else {
-     if (shelltype(*sface) == SHARP) {
-@@ -7547,72 +7367,6 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// 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.                      //
- //                                                                           //
-@@ -8137,41 +7891,29 @@
-     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; 
-+  // The index within each point at which its local feature size is found.
-+  //   It is saved directly after the list of point attributes.
-+  if (b->bgmesh && (bgm != (tetgenmesh *) NULL)) {
-+    // A background mesh is in use. That point attributes should be the
-+    //   same as that of the background mesh.
-+    pointlfsindex = 3 + bgm->in->numberofpointattributes; 
-   } else {
--    // For '-q' option. Make sure to have space for saving a scalar value.
--    sizeoftensor = b->quality ? 1 : 0;
-+    pointlfsindex = 3 + in->numberofpointattributes; 
-   }
--  // The index within each point at which an element pointer is found, where
-+  // The index within each point at which a 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)
-+  point2simindex = ((pointlfsindex + b->quality) * 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 + 3) * sizeof(tetrahedron);
-+    if (bgm != (tetgenmesh *) NULL) {
-+      // Increase the size by 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)
-@@ -8199,11 +7941,7 @@
-   // 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);
--  }
-+  elesize = (8 + b->useshelles * 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);
-@@ -8220,15 +7958,15 @@
-     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) {
-+  //   integer is allocated for each element. 
-+  if (b->neighout) {
-+    elemmarkerindex = (elesize + sizeof(int) - 1) / sizeof(int);
-     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) {
-+    highorderindex = (elesize + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
-     elesize = (highorderindex + 1) * sizeof(tetrahedron);
-   }
-   // Having determined the memory size of an element, initialize the pool.
-@@ -8434,8 +8172,6 @@
-     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);
-@@ -8483,7 +8219,7 @@
-   // Set the boundary marker to zero.
-   setshellmark(*newface, 0);
-   // Set the type.
--  setshelltype(*newface, NSHARP);
-+  setshelltype(*newface, NSHARPNSKINNY);
-   if (checkpbcs) {
-     // Set the pbcgroup be ivalid.
-     setshellpbcgroup(*newface, -1);
-@@ -8508,19 +8244,21 @@
-   (*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 (bgm != (tetgenmesh *) NULL) {
-+    for (i = 0; i < bgm->in->numberofpointattributes; i++) {
-+      (*pnewpoint)[3 + i] = 0.0;
-+    } 
-+  } else {
-+    for (i = 0; i < in->numberofpointattributes; i++) {
-+      (*pnewpoint)[3 + 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) {
-+    if (bgm != (tetgenmesh *) NULL) {
-       setpoint2bgmtet(*pnewpoint, NULL);
-     }
-     if (checkpbcs) {
-@@ -8531,7 +8269,7 @@
-   // Initialize the point marker (starting from in->firstnumber).
-   ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
-   setpointmark(*pnewpoint, ptmark);
--  // Initialize the point type.
-+  // Initialize the point type be UNUSEDVERTEX.
-   setpointtype(*pnewpoint, UNUSEDVERTEX);
- }
- 
-@@ -8551,24 +8289,8 @@
- 
- 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);
-+  randomseed = (randomseed * 1366l + 150889l) % 714025l;
-+  return randomseed / (714025l / choices + 1);
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -8641,12 +8363,8 @@
-   }
-   // 'searchtet' should be a valid tetrahedron now.
- #ifdef SELF_CHECK
--  // assert(!isdead(searchtet) && (searchtet->tet != dummytet));
-+  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
-@@ -8781,8 +8499,8 @@
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--enum tetgenmesh::locateresult tetgenmesh::locate(point searchpt, 
--  triface *searchtet)
-+enum tetgenmesh::locateresult tetgenmesh::
-+locate(point searchpt, triface *searchtet)
- {
-   tetrahedron *firsttet, *tetptr;
-   void **sampleblock;
-@@ -8801,12 +8519,8 @@
-     symself(*searchtet);
-   }
- #ifdef SELF_CHECK
--  // assert(!isdead(searchtet));
-+  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);
-@@ -8888,8 +8602,9 @@
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--enum tetgenmesh::locateresult tetgenmesh::adjustlocate(point searchpt,
--  triface* searchtet, enum locateresult precise, REAL epspp)
-+enum tetgenmesh::locateresult tetgenmesh::
-+adjustlocate(point searchpt, triface* searchtet, enum locateresult precise,
-+             REAL epspp)
- {
-   point torg, tdest, tapex, toppo;
-   REAL s1, s2, s3, s4;
-@@ -9040,77 +8755,6 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// 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  //
-@@ -9535,21 +9179,26 @@
- //                                                                           //
- // 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.                  //
-+// On input, 'horiz' represents the face we want to flip (you can imagine it //
-+// is parallel to the horizon).  Let the tetrahedron above it be abcd, where //
-+// abc is 'horiz'.                                                           //
- //                                                                           //
- // 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.                                   //
-+//   - Returns T32 if a 3-to-2 flip is applicable. 'horiz' is adjusted so    //
-+//     that the primary edge of 'horiz' is the flipable edge.                //
-+//   - Returns T22 if a 2-to-2 or 4-to-4 flip is applicable.  'horiz' is     //
-+//     adjusted so that the primary edge of 'horiz' is the flipable edge.    //
-+//   - Returns FORBIDDENFACE indicates although a 2-to-3 flip is applicable, //
-+//     but it is a subface and should not be flipped away.                   //
-+//   - Returns FORBIDDENEDGE indicates although a 3-to-2, or 2-to-2, or      //
-+//     4-to-4 flip is applicable, but the flipable edge is a subsegment and  //
-+//     should not be flipped away.  'horiz' is adjusted so that the primary  //
-+//     edge of 'horiz' is the flipable edge.                                 //
-+//   - Returns UNFLIPABLE indicates it is unflipable due to the absence of   //
-+//     a tetrahedron. 'horiz' is adjusted so that the primary edge of 'horiz'//
-+//     is the unflipable edge. Possibly, It is a subsegment.                 //
-+//   - Returns NONCONVEX indicates it is unflipable and is locally Delaunay. //
- //                                                                           //
- // 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  //
-@@ -9575,7 +9224,7 @@
-   sym(horiz, symhoriz);
-   if (symhoriz.tet == dummytet) {
-     // A hull face is unflipable and locally Delaunay.
--    return N40;
-+    return NONCONVEX;
-   }
-   
-   adjustedgering(horiz, CCW);
-@@ -9660,7 +9309,7 @@
-           return FORBIDDENEDGE;
-         }
-       }
--      return N32;
-+      return UNFLIPABLE;
-     }
-     ori2 = orient3d(pb, pc, pd, pe);
-     if (checksubfaces && ori2 != 0.0) {
-@@ -9707,7 +9356,7 @@
-           return FORBIDDENEDGE;
-         }
-       }
--      return N32;
-+      return UNFLIPABLE;
-     } 
-     ori3 = orient3d(pc, pa, pd, pe);
-     if (checksubfaces && ori3 != 0.0) {
-@@ -9757,7 +9406,7 @@
-           return FORBIDDENEDGE;
-         }
-       }
--      return N32;
-+      return UNFLIPABLE;
-     }
-     if (ori1 == 0.0) {
-       // e is coplanar with abd.
-@@ -9766,7 +9415,7 @@
-         // 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;
-+        return NONCONVEX;
-       }
-     } else if (ori2 == 0.0) {
-       // e is coplanar with bcd.
-@@ -9775,7 +9424,7 @@
-         // 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;
-+        return NONCONVEX;
-       }
-       // Adjust 'horiz' and 'symhoriz' be the edge bc.
-       enextself(horiz);
-@@ -9787,7 +9436,7 @@
-         // 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;
-+        return NONCONVEX;
-       }
-       // Adjust 'horiz' and 'symhoriz' be the edge ca.
-       enext2self(horiz);
-@@ -9840,14 +9489,14 @@
-         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;
-+        if (ori1 <= 0) return NONCONVEX;
-         ori1 = orient3d(pd, pc, pe, pb);
--        if (ori1 <= 0) return N40;
-+        if (ori1 <= 0) return NONCONVEX;
-         if (pf != (point) NULL) {
-           ori1 = orient3d(pd, pf, pe, pa);
--          if (ori1 <= 0) return N40;
-+          if (ori1 <= 0) return NONCONVEX;
-           ori1 = orient3d(pf, pd, pe, pb);
--          if (ori1 <= 0) return N40;
-+          if (ori1 <= 0) return NONCONVEX;
-         }
-       }
-       if (pf == (point) NULL) {
-@@ -9862,7 +9511,7 @@
-       }
-     } else {
-       // ab has more than four faces around it, unflipable.
--      return N32;
-+      return UNFLIPABLE;
-     }
-   } else if (adjtet == 1) {
-     // One of its three edges is locally non-convex. Type T32 is possible.
-@@ -9917,7 +9566,7 @@
-     }
-     if (ori1 <= 0.0) {
-       // a lies above or is coplanar cde, abc is locally Delaunay.
--      return N40;
-+      return NONCONVEX;
-     }
-     ori2 = orient3d(pd, pc, pe, pb);
-     if (checksubfaces && ori2 != 0.0) {
-@@ -9948,7 +9597,7 @@
-     }
-     if (ori2 <= 0.0) {
-       // b lies above dce, unflipable, and abc is locally Delaunay.
--      return N40;
-+      return NONCONVEX;
-     }
-     // Edge ab crosses face cde properly.
-     if (checksubfaces) {
-@@ -9973,14 +9622,14 @@
-           printf("Warning:  A tetrahedron spans two subfaces of a facet.\n");
-         }
-         // Temporarily, let it be there.
--        return N32;
-+        return UNFLIPABLE;
-       }
-     }
-     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;
-+    return NONCONVEX;
-   }
- }
- 
-@@ -9998,14 +9647,12 @@
- 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);
--  }
-+  queface = (badface *) flipqueue->push((void *) NULL);
-+  queface->tt = checkface;
-+  queface->forg = org(checkface);
-+  queface->fdest = dest(checkface);
-+  queface->fapex = apex(checkface);
- }
- 
- void tetgenmesh::enqueueflipedge(face& checkedge, queue* flipqueue)
-@@ -10039,14 +9686,10 @@
-   triface abcd, bace;                                  // Old configuration.
-   triface oldabd, oldbcd, oldcad;
-   triface abdcasing, bcdcasing, cadcasing;
-+  face abdsh, bcdsh, cadsh;
-   triface oldbae, oldcbe, oldace;
-   triface baecasing, cbecasing, acecasing;
--  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;
-@@ -10054,25 +9697,27 @@
- 
-   abcd = *flipface;
-   adjustedgering(abcd, CCW); // abcd represents edge ab.
-+  sym(abcd, bace);
-+  findedge(&bace, dest(abcd), org(abcd)); // bace represents edge ba.
-   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));
-+    printf("    Do T23 on face (%d, %d, %d, %d).\n", pointmark(pa),
-+           pointmark(pb), pointmark(pc), pointmark(pd));
-   }
-   flip23s++;
- 
-+#ifdef SELF_CHECK
-+  // Edge de must cross face abc properly.
-+  assert(orient3d(pa, pb, pd, pe) >= 0.0);
-+  assert(orient3d(pb, pc, pd, pe) >= 0.0);
-+  assert(orient3d(pc, pa, pd, pe) >= 0.0);
-+#endif
-+
-   // Storing the old configuration outside the convex hull.
-   fnext(abcd, oldabd);
-   enextfnext(abcd, oldbcd);
-@@ -10093,24 +9738,6 @@
-     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.
-@@ -10144,10 +9771,10 @@
- 
-   // 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;
-+    edab.loc = i;
-+    dissolve(edab);
-+    edbc.loc = i;
-+    dissolve(edbc);
-   }
-   // Bond the faces inside the convex hull.
-   edab.loc = 0;
-@@ -10171,7 +9798,7 @@
-   edca.loc = 2;
-   bond(edca, cadcasing);
-   edca.loc = 3;
--  bond(edca, acecasing);
-+  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).
-@@ -10205,55 +9832,6 @@
-       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;
-@@ -10311,44 +9889,40 @@
-   triface edab, edbc, edca;                            // Old configuration.
-   triface oldabd, oldbcd, oldcad;
-   triface abdcasing, bcdcasing, cadcasing;
-+  face abdsh, bcdsh, cadsh;
-   triface oldbae, oldcbe, oldace;
-   triface baecasing, cbecasing, acecasing;
--  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);
-+  findedge(&edbc, org(edab), dest(edab));
-   fnext(edbc, edca);
-   symself(edca);
--  edca.ver = 0;
--  for (i = 0; (i < 3) && (org(edca) != pe); i++) {
--    enextself(edca);
--  }
-+  findedge(&edca, org(edab), dest(edab));
-+  pa = apex(edab);
-+  pb = oppo(edab);
-+  pc = oppo(edbc);
-+  pd = dest(edab);
-+  pe = org(edab);
- 
-   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));
-+    printf("    Do T32 on face (%d, %d, %d, %d).\n",
-+           pointmark(pe), pointmark(pd), pointmark(pa), pointmark(pb));
-   }
-   flip32s++;
- 
-+#ifdef SELF_CHECK
-+  // Edge de must cross face abc properly.
-+  // assert(orient3d(pa, pb, pc, pd) <= 0.0);
-+  // assert(orient3d(pb, pa, pc, pe) <= 0.0);
-+#endif
-+
-   // Storing the old configuration outside the convex hull.
-   enextfnext(edab, oldabd);
-   enext2fnext(edab, oldbae);
-@@ -10369,28 +9943,6 @@
-     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.
-@@ -10409,10 +9961,10 @@
- 
-   // 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;
-+    abcd.loc = i;
-+    dissolve(abcd);
-+    bace.loc = i;
-+    dissolve(bace);
-   }
-   // Bond the inside face of the convex hull.
-   abcd.loc = 0;
-@@ -10434,72 +9986,35 @@
-   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;
-+      abcd.loc = i;
-+      tsdissolve(abcd);
-+      bace.loc = i;
-+      tsdissolve(bace);
-     }
-     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 (bcdsh.sh != dummysh) {
-+      abcd.loc = 2;
-+      tsbond(abcd, bcdsh);
-+    }
-     if (cbesh.sh != dummysh) {
-       bace.loc = 3;
-       tsbond(bace, cbesh);
-     }
-+    if (cadsh.sh != dummysh) {
-+      abcd.loc = 3;
-+      tsbond(abcd, cadsh);
-+    }
-     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;
-@@ -10569,14 +10084,10 @@
-   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;
-+  int mirrorflag;
- 
-   adjustedgering(*flipface, CCW); // 'flipface' is bae.
-   fnext(*flipface, abce);
-@@ -10598,20 +10109,12 @@
-   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);
--    }
-+    findedge(&bacf, pb, pa);
-     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);
--    }
-+    findedge(&abdf, pa, pb);
-     pf = oppo(bacf);
- #ifdef SELF_CHECK
-     assert(oppo(abdf) == pf);
-@@ -10624,6 +10127,12 @@
-   }
-   mirrorflag ? flip44s++ : flip22s++;
- 
-+#ifdef SELF_CHECK
-+  // The quadrilateral formed by a, b, c, and d must be convex.
-+  assert(orient3d(pc, pd, pe, pa) <= 0.0);
-+  assert(orient3d(pd, pc, pe, pb) <= 0.0);
-+#endif
-+  
-   // Save the old configuration at the convex hull.
-   enextfnext(abce, oldbce);
-   enext2fnext(abce, oldcae);
-@@ -10640,29 +10149,6 @@
-     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);
-@@ -10678,20 +10164,6 @@
-       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);
-     }
-   }
- 
-@@ -10722,75 +10194,6 @@
-     } 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.
-@@ -10820,75 +10223,6 @@
-       } 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);
--      }
-     }
-   }
- 
-@@ -11219,10 +10553,15 @@
-   while (!flipqueue->empty()) {
-     qface = (badface *) flipqueue->pop();
-     flipface = qface->tt;
--    if (isdead(&flipface)) continue;
-+    // 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;
-     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)) {
-+    if (symface.tet != dummytet && oppo(symface) != (point) NULL) {
-       // For positive orientation that insphere() test requires.
-       adjustedgering(flipface, CW);
-       pa = org(flipface);
-@@ -11230,7 +10569,7 @@
-       pc = apex(flipface);
-       pd = oppo(flipface);
-       pe = oppo(symface);
--      if (symbolic) {
-+      // if (symbolic) {
-         ia = pointmark(pa);
-         ib = pointmark(pb);
-         ic = pointmark(pc);
-@@ -11238,9 +10577,9 @@
-         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 = insphere(pa, pb, pc, pd, pe);
-+      // }
-     } else {
-       sign = -1.0; // A hull face is locally Delaunay.
-     }
-@@ -11252,7 +10591,7 @@
-         epscount = 0;
-         while (epscount < 32) {
-           fc = categorizeface(flipface);
--          if (fc == N40) {
-+          if (fc == NONCONVEX) {
-             b->epsilon *= 1e-1;
-             epscount++;
-             continue;
-@@ -11264,12 +10603,12 @@
-           if (b->verbose > 0) {
-             printf("Warning:  Can't flip a degenerate tetrahedron.\n");
-           }
--          fc = N40;
-+          fc = NONCONVEX;
-         }
-       } else {
-         fc = categorizeface(flipface);
- #ifdef SELF_CHECK
--        assert(fc != N40);
-+        assert(fc != NONCONVEX);
- #endif
-       }
-       switch (fc) {
-@@ -11285,14 +10624,14 @@
-         flip32(&flipface, flipqueue); 
-         break;
-       // The following face types are unflipable.
--      case N32:
-+      case UNFLIPABLE:
-         break;
-       case FORBIDDENFACE:
-         break;
-       case FORBIDDENEDGE:
-         break;
-       // This case is only possible when the domain is nonconvex.
--      case N40:
-+      case NONCONVEX:
-         // assert(nonconvex);
-         break;
-       }
-@@ -11322,233 +10661,6 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// 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 //
-@@ -11615,8 +10727,7 @@
- 
-   edgeflips = 0;
- 
--  while (!flipqueue->empty()) {
--    qedge = (badface *) flipqueue->pop();
-+  while ((qedge = (badface *) flipqueue->pop()) != NULL) {
-     flipedge = qedge->ss;
-     if (flipedge.sh == dummysh) continue;
-     if ((sorg(flipedge) != qedge->forg) || 
-@@ -11675,1128 +10786,43 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// removetetbypeeloff()    Remove a boundary tet by peeling it off.          //
-+// splittetrahedron()    Insert a point into a tetrahedron, split it into    //
-+//                       four tetrahedra.                                    //
- //                                                                           //
--// 'striptet' (abcd) is on boundary and can be removed by stripping it off.  //
--// Let abc and bad are the external boundary faces.                          //
-+// The tetrahedron is given by 'splittet'.  Let it is abcd.  The inserting   //
-+// point 'newpoint' v should lie strictly inside abcd.                       //
- //                                                                           //
--// 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).                //
-+// Splitting a tetrahedron is to shrink abcd to abcv,  and create three new  //
-+// tetrahedra badv, cbdv, and acdv.                                          //
- //                                                                           //
--// 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.           //
-+// On completion, 'splittet' returns abcv.  If 'flipqueue' is not NULL, it   //
-+// contains all possibly non-locally Delaunay faces.                         //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--bool tetgenmesh::removetetbypeeloff(triface *striptet)
-+void tetgenmesh::
-+splittetrahedron(point newpoint, triface* splittet, queue* flipqueue)
- {
--  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));
-+  triface oldabd, oldbcd, oldcad;                      // Old configuration.
-+  triface abdcasing, bcdcasing, cadcasing;
-+  face abdsh, bcdsh, cadsh;
-+  triface abcv, badv, cbdv, acdv;                      // New configuration.
-+  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);
-@@ -12863,51 +10889,6 @@
-       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;
-@@ -13041,18 +11022,14 @@
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--void tetgenmesh::splittetface(point newpoint, triface* splittet,
--  queue* flipqueue)
-+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;
-@@ -13088,6 +11065,13 @@
-            pointmark(pa), pointmark(pb), pointmark(pc));
-   }
- 
-+#ifdef SELF_CHECK
-+    // Make sure no inversed tetrahedron has been created.
-+    assert(orient3d(pa, pb, pd, newpoint) >= 0.0);
-+    assert(orient3d(pb, pc, pd, newpoint) >= 0.0);
-+    assert(orient3d(pc, pa, pd, newpoint) >= 0.0);
-+#endif
-+
-   // Save the old configuration at faces bcd and cad.
-   enextfnext(abcd, oldbcd);
-   enext2fnext(abcd, oldcad);
-@@ -13224,95 +11208,6 @@
-       // 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.
-@@ -13505,8 +11400,8 @@
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--void tetgenmesh::splitsubface(point newpoint, face* splitface,
--  queue* flipqueue)
-+void tetgenmesh::
-+splitsubface(point newpoint, face* splitface, queue* flipqueue)
- {
-   triface abvd, bcvd, cavd, bave, cbve, acve;
-   face abc, oldbc, oldca, bc, ca, spinsh;
-@@ -13811,15 +11706,13 @@
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--void tetgenmesh::splittetedge(point newpoint, triface* splittet,
--  queue* flipqueue)
-+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;
-@@ -13962,14 +11855,14 @@
-     }
- #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);
--    // }
-+    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
-   }
- 
-@@ -14005,29 +11898,6 @@
-     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) {
-@@ -14438,7 +12308,6 @@
-       // 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
-@@ -14715,8 +12584,8 @@
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--enum tetgenmesh::insertsiteresult tetgenmesh::insertsite(point newpoint,
--  triface* searchtet, bool approx, queue* flipqueue)
-+enum tetgenmesh::insertsiteresult tetgenmesh::
-+insertsite(point newpoint, triface* searchtet, bool approx, queue* flipqueue)
- {
-   enum locateresult intersect, exactloc;
-   point checkpt;
-@@ -14808,8 +12677,9 @@
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--void tetgenmesh::undosite(enum insertsiteresult insresult, triface* splittet,
--  point torg, point tdest, point tapex, point toppo)
-+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);
-@@ -14844,145 +12714,6 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// 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  //
-@@ -16194,7 +13925,17 @@
-       if (chkencseg) {
-         // Check if a->p and p->b are encroached by other vertices.
-         checkseg4encroach(&apseg, NULL, NULL, true);
-+        if (!shell2badface(apseg)) {
-+          if (varconstraint && (areabound(apseg) > 0.0)) {
-+            checkseg4badqual(&apseg, true);
-+          }
-+        }
-         checkseg4encroach(&pbseg, NULL, NULL, true);
-+        if (!shell2badface(pbseg)) {
-+          if (varconstraint && (areabound(pbseg) > 0.0)) {
-+            checkseg4badqual(&pbseg, true);
-+          }
-+        }
-         // Check if the adjacent segments are encroached by p.
-         tallencsegs(bp, n, ceillists);
-       }
-@@ -16221,6 +13962,11 @@
-         for (i = 0; i < subceillist->len(); i++) {
-           newsh = * (face *)(* subceillist)[i];
-           checksub4encroach(&newsh, NULL, true);
-+          if (!shell2badface(newsh)) {
-+            if (varconstraint && (areabound(newsh) > 0.0)) {
-+              checksub4badqual(&newsh, true);
-+            }
-+          }
-         }
-         // Only do once if p is on a facet.
-         if (splitseg == (face *) NULL) break; 
-@@ -16300,17 +14046,15 @@
-   // 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]));
--    }
-+  // 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.
-@@ -16333,17 +14077,14 @@
-           // 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]));
--            }
-+          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]));
-           }
-         }
-       }
-@@ -16356,13 +14097,11 @@
-     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));
--    }
-+  // Uninfect vertices.
-+  for (i = 0; i < verlist->len(); i++) {
-+    ver[0] = * (point *)(* verlist)[i];
-+    idx = pointmark(ver[0]);
-+    setpointmark(ver[0], -(idx + 1));
-   }
- }
- 
-@@ -16441,24 +14180,163 @@
-             }
-           }
-         }
--      } while ((apex(spintet) != tapex) && (hitbdry < 2));
-+      } 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;
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
-+// 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);
-   }
--  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++;
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
-+// 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);
-     }
--    // Remember it is a duplicated point.
--    setpointtype(testpt, DUPLICATEDVERTEX);
--    // Set a pointer to the point it duplicates.
--    setpoint2ppt(testpt, checkpt);
-+    // Go to the next open face of t.
-+    enextself(firstnewtet);
-   }
--  return merged;
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -16489,7 +14367,6 @@
-   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");
-@@ -16574,11 +14451,6 @@
-     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]);
-@@ -16593,18 +14465,18 @@
-       setvolumebound(newtet.tet, volume);
-     }
-   }
--  // Set vertex type be FREEVOLVERTEX if it has no type yet.
-+  // Set vertex type be VOLVERTEX if it has no type yet.
-   if (pointtype(insertarray[0]) == UNUSEDVERTEX) {
--    setpointtype(insertarray[0], FREEVOLVERTEX);
-+    setpointtype(insertarray[0], VOLVERTEX);
-   }
-   if (pointtype(insertarray[1]) == UNUSEDVERTEX) {
--    setpointtype(insertarray[1], FREEVOLVERTEX);
-+    setpointtype(insertarray[1], VOLVERTEX);
-   }
-   if (pointtype(insertarray[2]) == UNUSEDVERTEX) {
--    setpointtype(insertarray[2], FREEVOLVERTEX);
-+    setpointtype(insertarray[2], VOLVERTEX);
-   }
-   if (pointtype(lastpt) == UNUSEDVERTEX) {
--    setpointtype(lastpt, FREEVOLVERTEX);
-+    setpointtype(lastpt, VOLVERTEX);
-   }
-   // Bond to 'dummytet' for point location.
-   dummytet[0] = encode(newtet);
-@@ -16625,18 +14497,11 @@
-   // 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) {
-@@ -16684,26 +14549,18 @@
-     }
-     if (pointtype(insertarray[i]) == UNUSEDVERTEX) {
-       // p_i becomes a (volume) vertex of T.
--      setpointtype(insertarray[i], FREEVOLVERTEX);
-+      setpointtype(insertarray[i], VOLVERTEX);
-     }
--#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();
-+      flipque->clear();
-     }
--#ifdef SELF_CHECK
--    loc_end = clock();
--    tfliptime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
--#endif
-   }
- 
--  if (b->verbose > 0) {
-+  if (!b->noflip && b->verbose > 0) {
-     printf("  %ld Flips (T23 %ld, T32 %ld, T22 %ld, T44 %ld)\n",
-       flip23s+flip32s+flip22s+flip44s, flip23s, flip32s, flip22s, flip44s);
-   }
-@@ -16734,29 +14591,23 @@
-     }
-   }
- 
--  flipque = new queue(sizeof(badface));
-   // Prepare the array of points for inserting.
-   arraysize = points->items;
--  insertarray = new point[arraysize];  
--  points->traversalinit();
--
-+  insertarray = new point[arraysize];
-   // Randomize the point order.
-   // randomseed = b->srandseed;
-+  points->traversalinit();
-   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;
-+  flipque = new queue(sizeof(badface));
- 
-   // 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;
-@@ -16799,15 +14650,12 @@
-     senextself(steinsh);
-   }
-   assert(i < 3);
--  // Add the edge f into list.
-   * (face *)(* trilist)[0] = steinsh;
-+  // Add two verts a, b and one edge ab of f into lists,
-   pa = sorg(steinsh);
-   pb = sdest(steinsh);
--  if (vertlist != (list *) NULL) {
--    // Add two verts a, b into V,
--    vertlist->append(&pa);
--    vertlist->append(&pb);
--  }
-+  vertlist->append(&pa);
-+  vertlist->append(&pb);
- 
-   // Rotate edge pa to the left (CW) until meet pb or a segment.
-   lnextsh = steinsh;
-@@ -16829,10 +14677,8 @@
-     // 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);
--    }
-+    // Add vert c to V.
-+    vertlist->append(&pc);
-   } while (true);
- 
-   if (pc != pb) {
-@@ -16855,10 +14701,8 @@
-       // 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);
--      }
-+      // Add vert d to V.
-+      vertlist->append(&pd);
-     } while (true);
-   }
- }
-@@ -16885,7 +14729,7 @@
- //                                                                           //
- // getfacetabovepoint()    Get a point above a plane pass through a facet.   //
- //                                                                           //
--// The calculcated point is saved in 'facetabovepointarray'. The 'abovepoint'//
-+// The calulcated point is saved in 'facetabovepointarray'. The 'abovepoint' //
- // is set on return.                                                         //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
-@@ -16893,6 +14737,7 @@
- void tetgenmesh::getfacetabovepoint(face* facetsh)
- {
-   list *verlist, *trilist, *tetlist;
-+  tetrahedron tetptr;
-   triface adjtet;
-   face symsh;
-   point p1, p2, p3, pa;
-@@ -16959,22 +14804,17 @@
-       stpivot(symsh, adjtet);
-     }
-     if (adjtet.tet == dummytet) {
--      decode(point2tet(p1), adjtet);
--      if (isdead(&adjtet)) {
--        adjtet.tet = dummytet;
--      } else {
--        if (!findorg(&adjtet, p1)) {
-+      tetptr = point2tet(p1);
-+      if (tetptr != (tetrahedron) NULL) {
-+        decode(tetptr, adjtet);
-+        if (isdead(&adjtet)) {
-           adjtet.tet = dummytet;
-         }
-       }
-     }
-     if (adjtet.tet == dummytet) {
-       loc = locate(p1, &adjtet);
--      if (loc == ONVERTEX) {
--        setpoint2tet(p1, encode(adjtet));
--      } else {
--        adjtet.tet = dummytet;
--      }
-+      if (loc != ONVERTEX) adjtet.tet = dummytet;
-     }
-     if (adjtet.tet != dummytet) {
-       // Get the star polyhedron of p1.
-@@ -17248,7 +15088,6 @@
-   REAL det, area;
-   bool aboveflag;
-   int arraysize;
--  int epscount;
-   int fmarker;
-   int idx, i, j, k;  
- 
-@@ -17264,8 +15103,6 @@
-   //   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;
-@@ -17291,23 +15128,22 @@
-     // 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(", ...");
-+    if (eps == 0.0) {
-+      if (!b->quiet) {
-+        printf("Warning:  Facet %d (%d, %d, %d", shmark,
-+               pointmark(insertarray[0]), pointmark(insertarray[1]),
-+               pointmark(insertarray[2]));
-+        if (ptlist->len() > 3) {
-+          printf(", ...");
-+        }
-+        printf(") is not a valid polygon.\n");
-       }
--      printf(") (%d) is not a valid polygon.\n", shmark);
--      terminatetetgen(1);
-     }
--    // Decrease the eps, and continue to try.
--    eps *= 1e-2;
--    epscount++;
--    continue;
-+    // Only use the first three points.
-+    i = arraysize;
-+    // Don't do calculation of abovepoint.
-+    aboveflag = false;
-   }
--  break;
--  } // while (true);
- 
-   // Create the initial triangle.
-   makeshellface(subfaces, &newsh);
-@@ -17316,15 +15152,15 @@
-   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);
-+  // Set vertex type be FACETVERTEX if it has no type yet.
-+  if (pointtype(insertarray[0]) == VOLVERTEX) {
-+    setpointtype(insertarray[0], FACETVERTEX);
-   }
--  if (pointtype(insertarray[1]) == FREEVOLVERTEX) {
--    setpointtype(insertarray[1], FREESUBVERTEX);
-+  if (pointtype(insertarray[1]) == VOLVERTEX) {
-+    setpointtype(insertarray[1], FACETVERTEX);
-   }
--  if (pointtype(insertarray[2]) == FREEVOLVERTEX) {
--    setpointtype(insertarray[2], FREESUBVERTEX);
-+  if (pointtype(insertarray[2]) == VOLVERTEX) {
-+    setpointtype(insertarray[2], FACETVERTEX);
-   }
-   // Let 'dummysh' point to it (for point location).
-   dummysh[0] = sencode(newsh);
-@@ -17388,9 +15224,9 @@
-     } 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);
-+    // Set p_i's type FACETVERTEX if it has no type yet.
-+    if (pointtype(insertarray[i]) == VOLVERTEX) {
-+      setpointtype(insertarray[i], FACETVERTEX);
-     }
-     flipsub(flipque);
-   }
-@@ -18011,14 +15847,6 @@
-       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]);
-   }
- }
- 
-@@ -18240,8 +16068,8 @@
- //                                                                           //
- // 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.                                       //
-+// FACETVERTEX. Edge flips will be performed to ensure the Delaunay criteria //
-+// of the triangulation of merged facets.                                    //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
-@@ -18318,12 +16146,12 @@
-             j = pointmark(eorg);
-             segspernodelist[j]--;
-             if (segspernodelist[j] == 0) {
--              setpointtype(eorg, FREESUBVERTEX);
-+              setpointtype(eorg, FACETVERTEX);
-             }
-             j = pointmark(edest);
-             segspernodelist[j]--;
-             if (segspernodelist[j] == 0) {
--              setpointtype(edest, FREESUBVERTEX);
-+              setpointtype(edest, FACETVERTEX);
-             }
-             // Add 'parentsh' to queue checking for flip.
-             enqueueflipedge(parentsh, flipqueue);
-@@ -18517,8 +16345,6 @@
-   // 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'.
-@@ -18530,7 +16356,7 @@
-     jettisonnodes();
-   }
- 
--  if (!b->nomerge && !b->nobisect && !checkpbcs) {
-+  if (!b->nomerge && !checkpbcs) {
-     // No '-M' switch - merge adjacent facets if they are coplanar.
-     mergefacets(flipqueue);
-   }
-@@ -19009,15 +16835,13 @@
- 
- void tetgenmesh::createsegpbcgrouptable()
- {
--  shellface** segsperverlist;
--  pbcdata *pd, *ppd, pd1, pd2;
-+  pbcdata *pd, *pd1, *pd2;
-   face segloop, symseg;
-   face startsh, spinsh, symsh;
--  point pa, pb, syma, symb;
-+  point pa, pb;
-   enum locateresult symloc;
-   REAL testpt[3], sympt[3];
-   bool inflag;
--  int *idx2seglist;
-   int segid1, segid2;
-   int f1, f2;
-   int i, j, k, l;
-@@ -19025,11 +16849,6 @@
-   // 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);
-@@ -19048,52 +16867,13 @@
-       // 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);
-+        //   '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);
-+        assert(symloc == ONEDGE);
- #endif
--          sspivot(symsh, symseg);
--        }
-+        sspivot(symsh, symseg);
- #ifdef SELF_CHECK
-         assert(symseg.sh != dummysh);
- #endif
-@@ -19118,19 +16898,19 @@
-           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];
-+          getsubpbcgroup(&spinsh, &pd1, &f1, &f2);
-+          pd->fmark[0] = pd1->fmark[f1];
-+          pd->fmark[1] = pd1->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];
-+              pd->transmat[0][i][j] = pd1->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];
-+              pd->transmat[1][i][j] = pd1->transmat[f2][i][j];
-             }
-           }
-         }
-@@ -19140,35 +16920,27 @@
-     } 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];
-+    pd1 = (pbcdata *)(* segpbcgrouptable)[i];
-     for (f1 = 0; f1 < 2; f1++) {
--      // Search for a group (except i) contains pd1.segid[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];
-+        pd2 = (pbcdata *)(* segpbcgrouptable)[j];
-         f2 = -1;
--        if (pd1.segid[f1] == pd2.segid[0]) {
-+        if (pd1->segid[f1] == pd2->segid[0]) {
-           f2 = 0;
--        } else if (pd1.segid[f1] == pd2.segid[1]) {
-+        } else if (pd1->segid[f1] == pd2->segid[1]) {
-           f2 = 1;
-         }
-         if (f2 != -1) {
- #ifdef SELF_CHECK
--          assert(pd1.segid[f1] == pd2.segid[f2]);
-+          assert(pd1->segid[f1] == pd2->segid[f2]);
- #endif
--          segid1 = pd1.segid[1 - f1];
--          segid2 = pd2.segid[1 - f2];
-+          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++) {
-@@ -19181,28 +16953,28 @@
-           }
-           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];
-+            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].
-+            //   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];
-+                pd->transmat[0][k][l] = pd2->transmat[f2][k][l];
-               }
-             }
--            m4xm4(pd->transmat[0], pd1.transmat[1 - f1]);
-+            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].
-+            //   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];
-+                pd->transmat[1][k][l] = pd1->transmat[f1][k][l];
-               }
-             }
--            m4xm4(pd->transmat[1], pd2.transmat[1 - f2]);
-+            m4xm4(pd->transmat[1], pd2->transmat[1 - f2]);
-           }
-         }
-       }
-@@ -20040,93 +17812,92 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// markacutevertices()    Mark acute vertices.                               //
-+// markacutevertices()    Mark each vertex to be ACUTE or NACUTE.            //
- //                                                                           //
--// 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.                       //
-+// A vertex is acute if at least two segments incident at it with an angle   //
-+// smaller than a given angle bound (e.g. 90 degree).                        //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
- void tetgenmesh::markacutevertices(REAL acuteangle)
- {
-   shellface **segsperverlist;
--  face segloop, nextseg;
--  point pointloop, edest, eapex;
-+  face segloop, workseg, inciseg;
-+  point eorg, 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");
-+    printf("  Marking segments have acute corners.\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++;
-+  
-+  // Loop over the set of subsegments.
-+  subsegs->traversalinit();
-+  segloop.sh = shellfacetraverse(subsegs);
-+  while (segloop.sh != (shellface *) NULL) {
-+    // Check and set types for the two ends of this segment.
-+    for (segloop.shver = 0; segloop.shver < 2; segloop.shver++) {
-+      eorg = sorg(segloop);
-+      if ((pointtype(eorg) != ACUTEVERTEX) && 
-+          (pointtype(eorg) != NACUTEVERTEX) &&
-+          (pointtype(eorg) != FREESEGVERTEX)) {
-+        // This vertex has no type be set yet.
-+        idx = pointmark(eorg) - in->firstnumber;
-+        isacute = false;
-+        for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isacute; i++) {
-+          workseg.sh = segsperverlist[i];
-+          workseg.shver = 0;
-+          if (sorg(workseg) != eorg) sesymself(workseg);
-+#ifdef SELF_CHECK
-+          assert(sorg(workseg) == eorg);
-+#endif
-+          edest = sdest(workseg);
-+          for (j = i + 1; j < idx2seglist[idx + 1] && !isacute; j++) {
-+            inciseg.sh = segsperverlist[j];
-+            inciseg.shver = 0;
-+#ifdef SELF_CHECK
-+            assert(inciseg.sh != workseg.sh);
-+#endif
-+            if (sorg(inciseg) != eorg) sesymself(inciseg);
-+#ifdef SELF_CHECK
-+            assert(sorg(inciseg) == eorg);
-+#endif
-+            eapex = sdest(inciseg);
-+            // Check angles between segs (eorg, edest) and (eorg, eapex).
-+            for (k = 0; k < 3; k++) {
-+              v1[k] = edest[k] - eorg[k];
-+              v2[k] = eapex[k] - eorg[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];  
-+            if (D >= cosbound) {
-+              isacute = true; 
-+            }
-+          }
-+        }
-+        if (isacute) {
-+          setpointtype(eorg, ACUTEVERTEX);
-+        } else {
-+          setpointtype(eorg, NACUTEVERTEX);
-+        }
-       }
-     }
--    pointloop = pointtraverse();
-+    segloop.sh = shellfacetraverse(subsegs);
-   }
- 
-   delete [] idx2seglist;
-   delete [] segsperverlist;
--
--  if ((b->verbose > 0) && (acutecount > 0)) {
--    printf("  %d acute vertices.\n", acutecount);
--  }
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -20655,7 +18426,7 @@
-   point farorg, fardest;
-   point ei, ej, ek, c;
-   REAL v[3], r, split;
--  REAL d1, d2, ps, rs;
-+  REAL d1, ps, rs;
-   bool acuteorg, acutedest;
-   int stype, rule;
-   int i;   
-@@ -20765,6 +18536,7 @@
-   if (rule == 1) r1count++;
-   else if (rule == 2) r2count++;
-   else if (rule == 3) r3count++;
-+  else if (rule == 4) r4count++;
- 
-   if (b->verbose > 1) {
-     if (stype == 2) {
-@@ -20778,13 +18550,12 @@
-   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);
-+    REAL d2 = distance(refpoint, v);
-     ps = randgenerator(d2 * 1.0e-5);
-   }
-   rs = ps / d1;
-@@ -20809,100 +18580,6 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// 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.                       //
- //                                                                           //
-@@ -20940,20 +18617,19 @@
- 
- void tetgenmesh::delaunizesegments()
- {
--  list *misseglist;
-   queue *flipqueue;
--  badface *misloop;
-   tetrahedron encodedtet;
-   triface searchtet, splittet;
-   face splitsh, symsplitsub;
-   face segloop, symsplitseg;
-+  face lastsplit;
-   point refpoint, splitpoint, sympoint;
-   point tend, checkpoint;
-   point p1, p2, pa;
-   enum finddirectionresult collinear;
-   enum insertsiteresult success;
-   enum locateresult symloc;
--  bool coll;
-+  bool finish, coll;
-   long vertcount;
-   int i, j;
- 
-@@ -20961,35 +18637,30 @@
-     printf("Delaunizing segments.\n");
-   }
- 
--  // Construct a map from points to tets for speeding point location.
--  makepoint2tetmap();
--  // Initialize a flipqueue.
-+  // Mark segment vertices (acute or not) for determining segment types.
-+  markacutevertices(89.0);
-+  // Construct a map from points to tetrahedra for speeding point location.
-+  // makepoint2tetmap(); // This is done in above routine.
-+  // Initialize a queue for returning non-Delaunay faces and edges.
-   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;
-+  // 'lastsplit' is the last segment be split in one loop, all segments
-+  //   after it are existing. At first, set it be NULL;
-+  lastsplit.sh = (shellface *) NULL;
-   // Remember the current number of points.
-   vertcount = points->items;
-   // Initialize the counters.
--  r1count = r2count = r3count = 0l;
-+  r1count = r2count = r3count = r4count = 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));
-+  finish = false;
-+  while (!finish && (steinerleft != 0)) {
-+    subsegs->traversalinit();
-+    segloop.sh = shellfacetraverse(subsegs);
-+    while ((segloop.sh != (shellface *) NULL) && (steinerleft != 0)) {
-+      // Search segment ab in DT.
-+      p1 = sorg(segloop);  // p1 = a;
-+      p2 = sdest(segloop);  // p2 = b;
-+      if (b->verbose > 2) {
-+        printf("  Checking segment (%d, %d).\n", pointmark(p1), pointmark(p2));
-       }
-       getsearchtet(p1, p2, &searchtet, &tend);
-       collinear = finddirection(&searchtet, tend, tetrahedrons->items);
-@@ -21013,7 +18684,7 @@
-           //   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) {
-+          if (pointtype(checkpoint) == VOLVERTEX) {
-             // c is not a segment vertex yet. It becomes NACUTEVERTEX.
-             setpointtype(splitpoint, NACUTEVERTEX);  
-           } else if (pointtype(checkpoint) == ACUTEVERTEX) {
-@@ -21026,7 +18697,7 @@
-         } else {
-           // Find a reference point p of ab.
-           refpoint = scoutrefpoint(&searchtet, tend);
--          if (pointtype(refpoint) == FREEVOLVERTEX) {
-+          if (pointtype(refpoint) == VOLVERTEX) {
-             // p is an input point, check if it is nearly collinear with ab.
-             coll = iscollinear(p1, p2, refpoint, b->epsilon);
-             if (coll) {
-@@ -21080,7 +18751,7 @@
-                   // Let sympoint remember splittet.
-                   setpoint2tet(sympoint, encode(splittet));
-                   // Do flip in DT.
--                  lawson(misseglist, flipqueue);
-+                  flip(flipqueue, NULL);
-                   // Insert sympoint into F.
-                   symsplitseg.shver = 0;
-                   spivot(symsplitseg, symsplitsub);
-@@ -21088,13 +18759,6 @@
-                   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.
-@@ -21117,42 +18781,35 @@
-             //   consequent point location.
-             setpoint2tet(splitpoint, encode(searchtet));
-             // Maintain Delaunayness in DT.
--            lawson(misseglist, flipqueue);
-+            flip(flipqueue, NULL);
-           }
-         }
-         // 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);
-+        // Remember 'segloop'.
-+        lastsplit = segloop;
-+      } else {
-+        // ab exists. Is it the last one we've checked?
-+        if (segloop.sh == lastsplit.sh) {
-+          finish = true;
-+          break;
-+        }
-       }
--  }
--
--  // 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;
-+      segloop.sh = shellfacetraverse(subsegs);
-+    }
-+    if (lastsplit.sh == (shellface *) NULL) {
-+      // No missing segment!
-+      finish = true;
-     }
--    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;
- }
- 
- //
-@@ -23453,8 +21110,6 @@
-           if (shellmark(neighsh) == 0) {
-             setshellmark(neighsh, 1);
-           }
--          // This side becomes hull. Update the handle in dummytet.
--          dummytet[0] = encode(neighbor);
-         }
-       }
-     }
-@@ -23605,8 +21260,9 @@
-       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) { 
-+        // If it is a volume vertex, mark to delete it.
-+        if ((pointtype(checkpt) == VOLVERTEX) ||
-+            (pointtype(checkpt) == FREEVOLVERTEX)) { 
-           setpointtype(checkpt, UNUSEDVERTEX);
-           unuverts++;
-         }
-@@ -24175,7 +21831,7 @@
-         flip22(flipface, flipque);
-         return true;
-       }
--    } else if (fc == N32) {
-+    } else if (fc == UNFLIPABLE) {
-       // Is f a crossface?
-       if (front != (triface *) NULL) {
-         // (6) Is any obstacle face (abd, or abe, ...) flipable?
-@@ -24613,7 +22269,7 @@
-            floorlist->len(), ceillist->len(), ptlist->len());
-   }
- 
--  // symbolic = 1;
-+  symbolic = 1;
-   
-   // Initialize the cavity C.
-   initializecavity(floorlist, ceillist, frontlist);
-@@ -24654,7 +22310,7 @@
-     retrievenewtets(newtetlist);
-   }
-   
--  // symbolic = 0;
-+  symbolic = 0;
- 
-   if (misfrontlist->len() == 0) {
-     // All fronts have identified in D. Get the shape of C by removing out
-@@ -25199,8 +22855,8 @@
- 
-   // 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);
-+    oldtet = * (triface *)(* oldtetlist)[i];
-+    assert(!infected(oldtet));
-     pa = org(oldtet);
-     pb = dest(oldtet);
-     pc = apex(oldtet);
-@@ -25289,12 +22945,8 @@
-       }
-       // 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);
--      }
-+      // This side (neightet) is a boundary face, let 'dummytet' bond to it.
-+      dummytet[0] = encode(neightet);
-     }
-   }
- }
-@@ -25360,14 +23012,11 @@
- // '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)
-+  queue* flipque)
- {
-   list *oldtetlist[2], *newtetlist[2];
-   list *oldshlist, *newshlist;
-@@ -25441,17 +23090,12 @@
-     // 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).
-+    if (!constrainedcavity(&oldtet, newshlist, oldtetlist[i], ptlist,
-+          frontlist, misfrontlist, newtetlist[i], flipque)) {
-+      // Unable to mesh old B_i(p), try to relocate p into it.
-       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.
-@@ -25466,10 +23110,6 @@
-         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();
-@@ -25511,17 +23151,6 @@
-         }
-       }
-     }
--    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++;
-@@ -25590,7 +23219,7 @@
- 
- 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* conlist, memorypool* viri, queue* flipque)
- {
-   list **oldtetlist, **newtetlist;
-   list **oldshlist, **newshlist;
-@@ -25601,20 +23230,19 @@
-   face nsupseg, newseg, prevseg, nextseg;
-   point suppt, *newpt;
-   point pa, pb, *cons;
--  REAL pnorm[2][3], norm[3];
-+  REAL norm[3], pnorm[2][3];
-   bool success;
-   int shmark;
-   int n, i, j, k;
- 
-   // Get the Steiner point p.
--  assert(supseg->shver < 2);
-+  assert(supseg->shver == 0);
-   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);
-@@ -25672,7 +23300,6 @@
-   spivotself(prevseg);
-   if (prevseg.sh != dummysh) {
-     prevseg.shver = 0;
--    if (sdest(prevseg) != pa) sesymself(prevseg);
-     assert(sdest(prevseg) == pa);
-     senextself(prevseg);
-     senext2self(newseg);
-@@ -25684,7 +23311,6 @@
-   spivotself(nextseg);
-   if (nextseg.sh != dummysh) {
-     nextseg.shver = 0;
--    if (sorg(nextseg) != pb) sesymself(nextseg);
-     assert(sorg(nextseg) == pb);
-     senext2self(nextseg);
-     senextself(newseg);
-@@ -25801,16 +23427,13 @@
-       }
-     }
-     // Tetrahedralize B_i(p).
--    success = constrainedcavity(&oldtet, dnewshlist, oldtetlist[i], ptlist,
--                frontlist, misfrontlist, newtetlist[i], flipque);
--    if (!success && !noreloc) {
-+    if (!constrainedcavity(&oldtet, dnewshlist, oldtetlist[i], ptlist,
-+          frontlist, misfrontlist, newtetlist[i], flipque)) {
-       // 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.
-@@ -25825,10 +23448,6 @@
-         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();
-@@ -25841,9 +23460,6 @@
-     // 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);
-@@ -25879,17 +23495,6 @@
-         }
-       }
-     }
--    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++;
-@@ -25898,27 +23503,22 @@
-     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);
-+      supseg->shver = 0;
-     }
-     // 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);
-+      nsupseg.shver = 0;
-     }
-     // Delete the new segment ab.
-     shellfacedealloc(subsegs, newseg.sh);
-@@ -25989,52 +23589,52 @@
- //                                                                           //
- // 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.                 //
-+// The point p inside the mesh will be suppressed by being deleted from the  //
-+// mesh. p may not be suppressed.                                            //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--bool tetgenmesh::suppressvolpoint(triface* suptet, list* frontlist,
--  list* misfrontlist, list* ptlist, queue* flipque, bool optflag)
-+bool tetgenmesh::suppressvolpoint(point suppt, list* frontlist,
-+  list* misfrontlist, list* ptlist, queue* flipque)
- {
--  list *myfrontlist, *mymisfrontlist, *myptlist;
-   list *oldtetlist, *newtetlist;
-   list *newshlist; // a dummy list.
--  queue *myflipque;
-+  tetrahedron tetptr;
-   triface oldtet, newtet;
--  point suppt, conpt;
-   bool success;
-   int j;
- 
-+  if (b->verbose > 1) {
-+    printf("    Remove point %d in mesh.\n", pointmark(suppt));
-+  }
-+
-+  // Get a tet with p as a vertex.
-+  oldtet.tet = (tetrahedron *) NULL;
-+  tetptr = point2tet(suppt);
-+  if (tetptr != (tetrahedron) NULL) {
-+    decode(tetptr, oldtet);
-+  }
-+  // Make sure oldtet contains p.
-+  if (isdead(&oldtet) || !findorg(&oldtet, suppt)) {
-+    // The pointer is invalid. Recreate the map.
-+    makepoint2tetmap();
-+    tetptr = point2tet(suppt);
-+    decode(tetptr, oldtet);
-+    if (isdead(&oldtet)) {
-+      // There is no tet contain p, it is indeed an unused point.
-+      //   expandsteinercavity() deleted all tets of p.
-+      setpointtype(suppt, UNUSEDVERTEX);
-+      unuverts++;
-+      return true;
-+    }
-+  }
-+
-   // 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);
-@@ -26044,30 +23644,20 @@
-     infect(oldtet);
-   }
-   // Tetrahedralize old B(p).
--  success = constrainedcavity(&oldtet, newshlist, oldtetlist, ptlist,
--              frontlist, misfrontlist, newtetlist, flipque);
--  if (!success) {
--    // Unable to suppress p.
-+  if (!constrainedcavity(&oldtet, newshlist, oldtetlist, ptlist, frontlist,
-+        misfrontlist, newtetlist, flipque)) {
-+    // Unable to suppress p. 
-+    success = false;
-+    // Clean fake tets and quit this option.
-     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;
--    }
-   }
-+  // Clear work lists.
-+  ptlist->clear();
-+  frontlist->clear();
-+  misfrontlist->clear();
-+  flipque->clear();
-+
-   if (success) {
-     // p has been removed! (Still in the pool).
-     setpointtype(suppt, UNUSEDVERTEX);
-@@ -26079,13 +23669,6 @@
-       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).
-@@ -26096,18 +23679,6 @@
-     }
-   }
- 
--  // 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;
-@@ -26117,177 +23688,61 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// 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'.                                                 //
-+// collapseedgepoint()    Delete a point by edge collapse.                   //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--bool tetgenmesh::smoothpoint(point smthpt, point e1, point e2, list *starlist,
--  bool invtori, REAL *key)
-+bool tetgenmesh::collapseedgepoint(point colpt, list *oldtetlist, 
-+  list* deadtetlist, list *ptlist)
- {
--  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;
-+  tetrahedron tetptr;
-+  triface oldtet, newtet;
-+  point conpt;
-+  bool success;
- 
-   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];
-+    printf("    Collapse point %d.\n", pointmark(colpt));
-   }
- 
--  // 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;
-+  // Get a tet with p as a vertex.
-+  oldtet.tet = (tetrahedron *) NULL;
-+  tetptr = point2tet(colpt);
-+  if (tetptr != (tetrahedron) NULL) {
-+    decode(tetptr, oldtet);
-+  }
-+  // Make sure oldtet contains p.
-+  if (isdead(&oldtet) || !findorg(&oldtet, colpt)) {
-+    // The pointer is invalid. Recreate the map.
-+    makepoint2tetmap();
-+    tetptr = point2tet(colpt);
-+    decode(tetptr, oldtet);
-+    if (isdead(&oldtet)) {
-+      // There is no tet contain p, it is indeed an unused point.
-+      //   expandsteinercavity() deleted all tets of p.
-+      setpointtype(colpt, UNUSEDVERTEX);
-+      unuverts++;
-+      return true;
-     }
-   }
- 
--  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;
-+  // Form old B(p) in oldtetlist.
-+  oldtetlist->append(&oldtet);
-+  formstarpolyhedron(colpt, oldtetlist, ptlist, false);
-+  // Try to collapse p.
-+  success = findcollapseedge(colpt, &conpt, oldtetlist, ptlist);
-+  if (success) {
-+    // Collapse p by edge contraction.
-+    collapseedge(colpt, conpt, oldtetlist, deadtetlist);
-+    collapverts++;
-+    // p has been removed! (Still in the pool).
-+    setpointtype(colpt, UNUSEDVERTEX);
-+    unuverts++;
-+    deadtetlist->clear();
-   }
-+  oldtetlist->clear();
-+  ptlist->clear();
-+
-+  return success;
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -26296,7 +23751,7 @@
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--void tetgenmesh::removesteiners(bool coarseflag)
-+void tetgenmesh::removesteiners()
- {
-   list *frontlist, *misfrontlist;
-   list *spinshlist, *newsegshlist;
-@@ -26306,22 +23761,12 @@
-   triface checktet;
-   face shloop;
-   face segloop, nextseg;
--  point pa, neipt;
--  REAL len;
-+  point pa;
-   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");
--    }
--  }
-+  int i;
- 
--  // Initialize work lists.
-+  // Initiliaze work lists.
-   frontlist = new list(sizeof(triface), NULL);
-   misfrontlist = new list(sizeof(triface), NULL);
-   spinshlist = new list(sizeof(face), NULL);
-@@ -26331,10 +23776,13 @@
-   flipque = new queue(sizeof(badface));
-   viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
-   oldnum = unuverts;
--  relverts = suprelverts = collapverts = unsupverts;
--  smoothvolverts = 0;
-+  relverts = suprelverts = collapverts = unsupverts = 0;
-   expcavcount = 0;
- 
-+  if (!b->quiet) {
-+    printf("Removing Steiner points.\n");
-+  }
-+
-   // Suppress Steiner points inside facets.
-   do {
-     rmstein = unuverts;
-@@ -26347,115 +23795,32 @@
-       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;
--              }
-+          // Find a Steiner point p.
-+          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 {
--            // 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)
-+            // '-YY'. Remove p whatever s is a hull face or not.
-+            remflag = true;
-+          }
-+          break;
-+        }
-         senextself(shloop);
--      } // for (i = 0; i < 3; i++)
-+      }
-       if (remflag) {
-         suppressfacetpoint(&shloop, frontlist, misfrontlist, ptlist, conlist,
--                           viri, flipque, coarseflag, false);
-+                           viri, flipque);
-       }
-       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;
-@@ -26463,202 +23828,95 @@
-     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;
--              }
-+      // Don't check the poinytype of pa, it may be a Steiner point but has
-+      //   type NACUTEVERTEX due to splitting a type-3 segment.
-+      // if (pointtype(pa) == FREESEGVERTEX) {
-+      segloop.shver = 0;
-+      senext(segloop, nextseg);
-+      spivotself(nextseg);
-+      if (nextseg.sh != dummysh) {
-+        // Find a Steiner point p.
-+        pa = sdest(segloop); // For checking.
-+        nextseg.shver = 0;  
-+        assert(sorg(nextseg) == pa);
-+        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;
-             }
--          } 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++)
-+          } while (pa != apex(checktet));
-+        } else {
-+          // '-YY'. Remove p whatever it is on the hull or not.
-+          remflag = true;
-+        }
-+      }
-       if (remflag) {
-         suppresssegpoint(&segloop, spinshlist, newsegshlist, frontlist,
--          misfrontlist, ptlist, conlist, viri, flipque, coarseflag, false);
-+                         misfrontlist, ptlist, conlist, viri, flipque);
-       }
-       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.
-+  if (relverts > 0) {
-+    // Suppress relocated 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++)
-+      points->traversalinit();
-+      pa = pointtraverse();
-+      while (pa != (point) NULL) {
-+        remflag = (pointtype(pa) == FREEVOLVERTEX);
-         if (remflag) {
--          findorg(&checktet, pa);
--          assert(org(checktet) == pa);
--          suppressvolpoint(&checktet, frontlist, misfrontlist, ptlist, flipque,
--                           false);
-+          suppressvolpoint(pa, frontlist, misfrontlist, ptlist, flipque);
-         }
--        checktet.tet = tetrahedrontraverse();
-+        pa = pointtraverse();
-       }
-       // 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 ((relverts - suprelverts) > 0) {
-+    // Try to collapse relocated points.
-+    do {
-+      rmstein = unuverts;
-+      points->traversalinit();
-+      pa = pointtraverse();
-+      while (pa != (point) NULL) {
-+        remflag = (pointtype(pa) == FREEVOLVERTEX);
-+        if (remflag) {
-+          collapseedgepoint(pa, frontlist, misfrontlist, ptlist);
-         }
-+        pa = pointtraverse();
-       }
--      if (unsupverts > 0) {
--        printf("  !! %d points are unsuppressed.\n", unsupverts);
--      }
--    } else {
--      printf("  %d points are removed.\n", unuverts - oldnum);
-+      // Continue if any relocated point has been suppressed.
-+    } while (unuverts > rmstein);
-+  } */
-+
-+  if (b->verbose > 0) {
-+    printf("  %d points removed from boundary.\n", unuverts - oldnum);
-+    if (relverts > 0) {
-+      printf("  %d points relocated into volume.\n", relverts);
-+    }
-+    if (suprelverts > 0) {
-+      printf("  %d relocated points are suppressed.\n", suprelverts);
-+    }
-+    if (collapverts > 0) {
-+      printf("  %d relocated points are collapsed.\n", collapverts);
-+    }
-+    if (unsupverts > 0) {
-+      printf("  %d points are unsuppressed.\n", unsupverts);
-+    }
-+    if (expcavcount > 0) {
-+      printf("  %d cavity corrections.\n", expcavcount);
-     }
-   }
--
-+  
-   // Delete work lists.
-   delete frontlist;
-   delete misfrontlist;
-@@ -26674,6 +23932,10 @@
- // End of boundary Steiner points removing routines
- //
- 
-+//
-+// Begin of mesh reconstruction routines
-+//
-+
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
- // reconstructmesh()    Reconstruct a tetrahedral mesh from a list of        //
-@@ -26767,12 +24029,12 @@
-     setdest(tetloop, tdest);
-     setapex(tetloop, tapex);
-     setoppo(tetloop, toppo);
--    // Temporarily set the vertices be type FREEVOLVERTEX, to indicate that
-+    // Temporarily set the vertices be type VOLVERTEX, 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);
-+    setpointtype(torg, VOLVERTEX);
-+    setpointtype(tdest, VOLVERTEX);
-+    setpointtype(tapex, VOLVERTEX);
-+    setpointtype(toppo, VOLVERTEX);
-     // Set element attributes if they exist.
-     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
-       index = i * in->numberoftetrahedronattributes;
-@@ -26844,7 +24106,7 @@
-         hullsize++;  // It's a hull face.
-         // Bond this side to outer space.
-         dummytet[0] = encode(tetloop);
--        if ((in->pointmarkerlist != (int *) NULL) && !b->coarse) {
-+        if (in->pointmarkerlist != (int *) NULL) {
-           // Set its three corners's markers be boundary (hull) vertices.
-           if (in->pointmarkerlist[iorg] == 0) {
-             in->pointmarkerlist[iorg] = 1;
-@@ -26969,11 +24231,11 @@
-         setsorg(subloop, torg);
-         setsdest(subloop, tdest);
-         setsapex(subloop, tapex);
--        // Set the vertices be FREESUBVERTEX to indicate they belong to a
-+        // Set the vertices be FACETVERTEX to indicate they belong to a
-         //   facet of the domain.  They may be changed later.
--        setpointtype(torg, FREESUBVERTEX);
--        setpointtype(tdest, FREESUBVERTEX);
--        setpointtype(tapex, FREESUBVERTEX);
-+        setpointtype(torg, FACETVERTEX);
-+        setpointtype(tdest, FACETVERTEX);
-+        setpointtype(tapex, FACETVERTEX);
-         tsbond(tetloop, subloop);
-         if (neightet.tet != dummytet) {
-           sesymself(subloop);
-@@ -27091,10 +24353,11 @@
-           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);
-+          // At the moment, all segment vertices have type FACETVERTEX.
-+          //   They will be set to type ACUTEVERTEX or NACUTEVERTEX by
-+          //   routine markacutevertices() later.
-+          // setpointtype(torg, SEGMENTVERTEX);
-+          // setpointtype(tdest, SEGMENTVERTEX);
-           setshellmark(subseg, marker);
-           marker++;
-           // Bond all subfaces to this subsegment.
-@@ -27220,6 +24483,24 @@
-     createsegpbcgrouptable();
-   }
- 
-+  // if (b->quality && varconstraint) {
-+  //   // Assign constraints on facets, segments, and nodes.
-+  //   assignvarconstraints(idx2verlist);
-+  // }
-+
-+  /*
-+  if (b->quality) {
-+    // Check and recover the Delaunay property.
-+    queue* flipqueue = new queue(sizeof(badface)); 
-+    checkdelaunay(0.0, flipqueue);
-+    if (!flipqueue->empty()) {
-+      // Call flip algorithm to recover Delaunayness.
-+      flip(flipqueue, NULL); 
-+    }
-+    delete flipqueue;
-+  }
-+  */
-+
-   delete markerlist;
-   delete neighshlist;
-   delete [] worklist;
-@@ -27234,11 +24515,54 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// insertconstrainedpoints()    Insert a list of constrained points.         //
-+// intettest()    Test if a point is inside (or on) a tetrahedron.           //
-+//                                                                           //
-+// Return TRUE if the point p and the tet t has one of the relations: (1) p  //
-+// is inside t; (2) p is on a faces of t; (3) p is on an edge of t; (4) p is //
-+// a vertex of t. Otherwise, return FALSE.                                   //
-+//                                                                           //
-+// An relative tolerance is used to determine coplanar case when a face of t //
-+// is on the hull. To bring back a boundary point inside the mesh.           //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+bool tetgenmesh::intettest(point testpt, triface* testtet, REAL eps)
-+{
-+  triface checktet;
-+  point p1, p2, p3;
-+  REAL ori;
-+
-+  testtet->ver = 0;
-+  for (testtet->loc = 0; testtet->loc < 4; testtet->loc++) {
-+    // Get points of the side f.
-+    p1 = org(*testtet);
-+    p2 = dest(*testtet);
-+    p3 = apex(*testtet);
-+    ori = orient3d(p1, p2, p3, testpt);
-+    if (ori > 0.0) {
-+      if (eps > 0.0) {
-+        // Is f on the hull.
-+        sym(*testtet, checktet);
-+        if (checktet.tet == dummytet) {
-+          if (iscoplanar(p1, p2, p3, testpt, ori, eps)) continue;
-+        }
-+      }
-+      // p is below f. outside.
-+      return false;
-+    }
-+  }
-+  testtet->loc = 0;
-+
-+  return true;
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
-+// insertaddpoints()    Insert additional points in 'in->addpointlist'.      //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
-+void tetgenmesh::insertaddpoints()
- {
-   queue *flipqueue;
-   triface searchtet;
-@@ -27246,8 +24570,6 @@
-   point newpoint;
-   enum locateresult loc;
-   REAL *attr;
--  bool insertflag;
--  int covertices, outvertices;
-   int index;
-   int i, j;
-   
-@@ -27257,134 +24579,117 @@
-   // Initialize 'flipqueue'.
-   flipqueue = new queue(sizeof(badface));
-   recenttet.tet = dummytet;
--  covertices = outvertices = 0;
- 
-   index = 0;
--  for (i = 0; i < addio->numberofpoints; i++) {
-+  for (i = 0; i < in->numberofaddpoints; 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];
--        }
--      }
-+    newpoint[0] = in->addpointlist[index++];
-+    newpoint[1] = in->addpointlist[index++];
-+    newpoint[2] = in->addpointlist[index++];
-+    // Copy new attributes (if available).
-+    if(in->addpointattributelist != (REAL *) NULL) {
-+      attr = in->addpointattributelist + in->numberofpointattributes * i;
-+      for (j = 0; j < in->numberofpointattributes; j++)
-+        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) {
-+      if (loc != ONVERTEX) {
-+        loc = adjustlocate(newpoint, &searchtet, loc, b->epsilon);
-+      }
-     }
-     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();
-+      // Perform a brute-force search.
-+      tetrahedrons->traversalinit();
-+      searchtet.tet = tetrahedrontraverse();
-+      while (searchtet.tet != (tetrahedron *) NULL) {
-+        if (intettest(newpoint, &searchtet, b->epsilon)) {
-+          loc = adjustlocate(newpoint, &searchtet, OUTSIDE, b->epsilon);
-+          assert(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);
-+      setpointtype(newpoint, VOLVERTEX);
-       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);
--        }
-+        setpointtype(newpoint, FREESUBVERTEX);
-       } else {
-         setpointtype(newpoint, FREEVOLVERTEX);
-       }
--      if (insertflag) {
--        splittetface(newpoint, &searchtet, flipqueue);
--      }
-+      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));
--        }
-+        setpointtype(newpoint, FREESEGVERTEX);
-+        setpoint2sh(newpoint, sencode(checkseg));
-       } else {
-         tspivot(searchtet, checksh);
-         if (checksh.sh != dummysh) {
--          if (b->nobisect) {
--            insertflag = false;
--          } else {
--            setpointtype(newpoint, FREESUBVERTEX);
--          }
-+          setpointtype(newpoint, FREESUBVERTEX);
-         } else {
--          setpointtype(newpoint, FREEVOLVERTEX);
-+          setpointtype(newpoint, VOLVERTEX);
-         }
-       }
--      if (insertflag) {
--        splittetedge(newpoint, &searchtet, flipqueue);
--      }
-+      splittetedge(newpoint, &searchtet, flipqueue);
-       break;
-     case ONVERTEX:
--      insertflag = false;
--      covertices++;
-+      if (!b->quiet) {
-+        printf("Warning: Point (%.17g, %.17g, %.17g) falls on a vertex.\n",
-+               newpoint[0], newpoint[1], newpoint[2]);
-+      }
-       break;
-     case OUTSIDE:
--      insertflag = false;
--      outvertices++;
-+      if (!b->quiet) {
-+        printf("Warning: Point (%.17g, %.17g, %.17g) lies outside the mesh.\n",
-+               newpoint[0], newpoint[1], newpoint[2]);
-+      }
-       break;
-     }
-     // Remember the tetrahedron for next point searching.
-     recenttet = searchtet;
--    if (!insertflag) {
-+    if (loc == ONVERTEX || loc == OUTSIDE) {
-       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;
- }
- 
-+//
-+// End of mesh reconstruction routines
-+//
-+
-+//
-+// Begin of background mesh routines
-+//
-+
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// p1interpolatebgm()    Set pt size by p^1 interpolation in background mesh.//
-+// interpolatepointsize()    Set a point size by interpolating in bgmesh.    //
- //                                                                           //
--// On input, 'bgmtet' is a suggesting tet in background mesh for searching   //
--// 'pt'. It returns the tet containing 'pt'.                                 //
-+// This function first finds the tet t in background mesh contains 'pt, then //
-+// set the size of 'pt' by interpolating the sizes of the corners of t.      //
-+//                                                                           //
-+// 'bgmtet' is a suggesting tet in background mesh for locating 'pt' in it.  //
-+// It returns the tet containing 'pt'.                                       //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--bool tetgenmesh::p1interpolatebgm(point pt, triface* bgmtet, long *scount)
-+bool tetgenmesh::interpolatepointsize(point pt, triface* bgmtet, long *scount)
- {
-   point bgmpt[4];
-   enum locateresult loc;
-@@ -27393,25 +24698,23 @@
- 
-   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) {
-+    // Perform a brute-force search.
-+    if (scount) (*scount)++;
-+    bgm->tetrahedrons->traversalinit(); // in bgm
-+    bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
-+    while (bgmtet->tet != (tetrahedron *) NULL) {
-+      if (bgm->intettest(pt, bgmtet, b->epsilon)) {
-         loc = bgm->adjustlocate(pt, bgmtet, OUTSIDE, b->epsilon);
--        if (loc != OUTSIDE) break;
--        bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
-+        assert(loc != OUTSIDE);
-+        break;
-       }
-+      bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
-     }
-   }
-   if (loc != OUTSIDE) {
-     // Let p remember t.
-     setpoint2bgmtet(pt, encode(*bgmtet)); // in m
-+    // Interpolate the point size.
-     // 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.
-@@ -27422,11 +24725,11 @@
-     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];
-+    for (i = 0; i < bgm->in->numberofpointattributes; i++) {
-+      pt[3 + i] = weights[0] * bgmpt[0][3 + i]
-+                + weights[1] * bgmpt[1][3 + i]
-+                + weights[2] * bgmpt[2][3 + i]
-+                + weights[3] * bgmpt[3][3 + i];
-     }
-   } else {
-     setpoint2bgmtet(pt, (tetrahedron) NULL);  // in m
-@@ -27436,6 +24739,45 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
-+// searchpointrecursive()    Search point in background mesh recursively.    //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+void tetgenmesh::searchpointrecursive(triface *curtet, long *scount)
-+{
-+  triface searchtet, bgmtet;
-+  point searchpt;
-+  int idx, i;
-+
-+  // Mark t as proceed.
-+  infect(*curtet);
-+  // Get the opposite point of t.
-+  searchpt = oppo(*curtet);
-+  // Has p already been processed?
-+  if (pointmark(searchpt) >= 0) {
-+    // Find the location of p.
-+    bgmtet = bgm->recenttet;
-+    if (interpolatepointsize(searchpt, &bgmtet, scount)) {
-+      bgm->recenttet = bgmtet; // in bgm
-+    }
-+    // Mark p as processed.
-+    idx = pointmark(searchpt);
-+    setpointmark(searchpt, -idx - 1);
-+  }
-+  // Recursively do the above searching.
-+  adjustedgering(*curtet, CCW);
-+  for (i = 0; i < 3; i++) {
-+    fnext(*curtet, searchtet);
-+    symself(searchtet);
-+    if ((searchtet.tet != dummytet) && (!infected(searchtet))) {
-+      searchpointrecursive(&searchtet, scount);
-+    }
-+    enextself(*curtet);
-+  }
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
- // interpolatesizemap()    Interpolate the point sizes in the given size map.//
- //                                                                           //
- // The size map is specified on each node of the background mesh. The points //
-@@ -27449,78 +24791,46 @@
- 
- void tetgenmesh::interpolatesizemap()
- {
--  list *adjtetlist;
--  triface tetloop, neightet, bgmtet;
-+  triface tetloop, bgmtet;
-   point searchpt;
-   long scount;
--  int *worklist;
--  int sepcount;
--  int i;
-+  int idx, 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)) {
-+      // Found an traversed tet t.
-+      tetloop.loc = 0;
-+      tetloop.ver = 0;
-+      // Locate the three vertices of current face of t.
-+      for (i = 0; i < 3; i++) {
-+        searchpt = org(tetloop);
-+        // Has p already been processed?
-+        if (pointmark(searchpt) >= 0) {
-+          // Interpolate p in background mesh.
-           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);
-+          if (interpolatepointsize(searchpt, &bgmtet, &scount)) {
-+            bgm->recenttet = bgmtet;
-           }
-+          // Mark p as processed.
-+          idx = pointmark(searchpt);
-+          setpointmark(searchpt, -idx - 1);
-         }
-+        enextself(tetloop);
-       }
--      // Increase the number of separated domains.
--      sepcount++;
--      delete adjtetlist;
--    } // if (!infect())
-+      // Recursively do the above searching in the neighbring tets of t.
-+      searchpointrecursive(&tetloop, &scount);
-+    }
-     tetloop.tet = tetrahedrontraverse();
-   }
- 
--  // Unmark all tets.
-+  // Have searched all points. Unmark tets.
-   tetrahedrons->traversalinit();
-   tetloop.tet = tetrahedrontraverse();
-   while (tetloop.tet != (tetrahedron *) NULL) {
-@@ -27528,201 +24838,192 @@
-     uninfect(tetloop);
-     tetloop.tet = tetrahedrontraverse();
-   }
--  delete [] worklist;
-+  // Unmark points.
-+  points->traversalinit(); // in m
-+  searchpt = pointtraverse(); // in m
-+  while (searchpt != (point) NULL) {
-+    idx = pointmark(searchpt);
-+    assert(idx < 0);
-+    setpointmark(searchpt, -(idx + 1));
-+    searchpt = pointtraverse(); // in m
-+  }
- 
- #ifdef SELF_CHECK
--  if (b->verbose && scount > 0l) {
-+  if (b->verbose) {
-     printf("  %ld brute-force searches.\n", scount);
-   }
--  if (b->verbose && sepcount > 0) {
--    printf("  %d separate domains.\n", sepcount);
--  }
- #endif
- }
- 
-+//
-+// End of of background mesh routines
-+//
-+
-+//
-+// Begin of Delaunay refinement routines
-+//
-+
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// duplicatebgmesh()    Duplicate current mesh to background mesh.           //
-+// calclocalfeaturesizes()    Calculate local feature sizes of all points.   //
- //                                                                           //
--// Current mesh 'this' is copied into 'this->bgm'.Both meshes share the same //
--// input tetgenio object, 'this->in', same tetgenbehavior object 'this->b'.  //
-+// Given a PLC X, the local feature size, lfs_d(x), of any point x in X is   //
-+// defined as the distance from x to two features of X which are of dim no   //
-+// large than d. For example, lfs_0(x) is the distance from x to the second  //
-+// nearest point of X. Let lfs(x) = lfs_2(x).                                //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--void tetgenmesh::duplicatebgmesh()
-+void tetgenmesh::calclocalfeaturesizes()
- {
--  triface tetloop, btetloop;
--  triface symtet, bsymtet;
--  face bhullsh, bneighsh;
--  point *idx2bplist, *tetptbaklist;
--  point ploop, bploop;
--  int idx, i;
-+  list *tetlist, *verlist;
-+  tetrahedron tetptr;
-+  triface starttet;
-+  face checksh, checkseg;
-+  point ploop, ver[3];
-+  point ptlfslarge, ptlfssmall;
-+  enum locateresult loc;
-+  REAL prj[3], lfs[3], len;
-+  REAL lfslarge, lfssmall;
-+  int i, j;
- 
--  if (!b->quiet) {
--    printf("Duplicating background mesh.\n");
-+  if (b->verbose > 0) {
-+    printf("  Calculating local feature sizes.\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);
-+  // Construct a map from points to tetrahedra.
-+  makepoint2tetmap();
-+  // Initialize working lists.
-+  tetlist = new list(sizeof(triface), NULL, 256);
-+  verlist = new list(sizeof(point *), NULL, 256);
-+  // Initialize bookkeeping variables.
-+  ptlfslarge = ptlfssmall = (point) NULL;
-+  lfslarge = lfssmall = 0.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);
-+    tetptr = point2tet(ploop);
-+    // Only calculate lfs(p) if it is in the mesh.
-+    if (tetptr != (tetrahedron) NULL) {
-+      decode(tetptr, starttet);
-+      tetlist->append(&starttet);
-+      formstarpolyhedron(ploop, tetlist, verlist, true); // Form star(p).
-+      lfs[0] = lfs[1] = lfs[2] = longest;
-+      // Calculate lfs_0(p).
-+      for (i = 0; i < verlist->len(); i++) {
-+        ver[0] = * (point *)(* verlist)[i];
-+        len = distance(ploop, ver[0]);
-+        if (lfs[0] > len) lfs[0] = len;
-+      }
-+      // Claculate lfs_1(p).
-+      for (i = 0; i < tetlist->len(); i++) {
-+        starttet = * (triface *)(* tetlist)[i];
-+        starttet.ver = 0;
-+        for (j = 0; j < 3; j++) {
-+          tsspivot(&starttet, &checkseg);
-+          if (checkseg.sh != dummysh) {
-+            checkseg.shver = 0;
-+            ver[0] = sorg(checkseg);
-+            ver[1] = sdest(checkseg);
-+            projpt2edge(ploop, ver[0], ver[1], prj);
-+            loc = locateseg(prj, &checkseg);
-+            if (loc != OUTSIDE) {
-+              len = distance(ploop, prj);
-+              if (lfs[1] > len) lfs[1] = len;
-+            }
-+          }
-+          enextself(starttet);
-+        }
-+      }
-+      // Claculate lfs_2(p).
-+      for (i = 0; i < tetlist->len(); i++) {
-+        starttet = * (triface *)(* tetlist)[i];
-+        tspivot(starttet, checksh);
-+        if (checksh.sh != dummysh) {
-+          ver[0] = sorg(checksh);
-+          ver[1] = sdest(checksh);
-+          ver[2] = sapex(checksh);
-+          projpt2face(ploop, ver[0], ver[1], ver[2], prj);
-+          abovepoint = facetabovepointarray[shellmark(checksh)];
-+          if (abovepoint == (point) NULL) {
-+            getfacetabovepoint(&checksh);
-+          }
-+          loc = locatesub(prj, &checksh, 1, b->epsilon);
-+          if (loc != OUTSIDE) {
-+            len = distance(ploop, prj);
-+            if (lfs[2] > len) lfs[2] = len;
-+          }
-+        }
-       }
-+      // Decide lfs(p).
-+      ploop[pointlfsindex] = lfs[0];
-+      if (ploop[pointlfsindex] > lfs[1]) ploop[pointlfsindex] = lfs[1];
-+      if (ploop[pointlfsindex] > lfs[2]) ploop[pointlfsindex] = lfs[2];
-+      // Update statistics.
-+      if (ptlfslarge == (point) NULL) {
-+        ptlfslarge = ptlfssmall = ploop;
-+        lfslarge = lfssmall = ploop[pointlfsindex];
-+      } else {
-+        if (lfslarge < ploop[pointlfsindex]) {
-+          lfslarge = ploop[pointlfsindex];
-+          ptlfslarge = ploop;
-+        }
-+        if (lfssmall > ploop[pointlfsindex]) {
-+          lfssmall = ploop[pointlfsindex];
-+          ptlfssmall = ploop;
-+        }
-+      }
-+      // Clear working lists.
-+      tetlist->clear();
-+      verlist->clear();
-     }
--    // 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);
-+  if (b->verbose > 1) {
-+    printf("  smallest lfs = %g (%d).\n", lfssmall, pointmark(ptlfssmall));
-+    printf("  largest  lfs = %g (%d).\n", lfslarge, pointmark(ptlfslarge));
-   }
- 
--  delete [] tetptbaklist;
--  delete [] idx2bplist;
-+  delete tetlist;
-+  delete verlist;
- }
- 
--//
--// 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.                      //
-+// marksharpsubsegs()    Mark all sharp subsegments.                         //
- //                                                                           //
--// (*) The internal angle (or dihedral) bewteen two features means the angle //
--// inside the mesh domain.                                                   //
-+// A segment is sharp if it is between two facets that form a small dihedral //
-+// angle (< 'dihedbound', given in degrees). It is marked as SHARP.          //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--void tetgenmesh::marksharpsegments(REAL sharpangle)
-+void tetgenmesh::marksharpsubsegs(REAL dihedbound)
- {
-+  list *spinshlist;
-   triface adjtet;
-   face startsh, spinsh, neighsh;
-   face segloop, prevseg, nextseg;
-   point eorg, edest;
--  REAL ang, smallang;
-+  enum shestype stype;
-+  REAL angle, smallang;
-   bool issharp;
--  int sharpsegcount;
-+  int scount;
-+  int i;
- 
-   if (b->verbose > 0) {
--    printf("  Marking sharp segments.\n");
-+    printf("  Marking sharp subsegments.\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.
-+  smallang = dihedbound * PI / 180.;
-+  scount = 0;
-+  eorg = edest = (point) NULL; // avoid compilation warnings.
-+  // Initial working list.
-+  spinshlist = new list(sizeof(face), NULL, 256);
-+
-+  // A segment s may be 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) {
-@@ -27730,512 +25031,148 @@
-     senext2(segloop, prevseg);
-     spivotself(prevseg);
-     if (prevseg.sh == dummysh) {
--      // Operate on this seg s.
--      assert(shelltype(segloop) != SHARP); // It should be unmarked.
-+      // Operate on this seg.
-       issharp = false;
-+      segloop.shver = 0;
-       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.
-+        spivot(startsh, spinsh);
-+        if (spinsh.sh != startsh.sh) {
-+          // This subface is not self-bonded.
-+          eorg = sorg(segloop);
-+          edest = sdest(segloop);
-+          // Get all incident subfaces around the 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.
-+            spinshlist->append(&spinsh);  
-             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);
-+        // Check the pair of adjacent subfaces for small angle.
-+        spinsh = * (face *)(* spinshlist)[0];
-+        for (i = 1; i <= spinshlist->len() && !issharp; i++) {
-+          if (i == spinshlist->len()) {
-+            neighsh = * (face *)(* spinshlist)[0];
-+          } else {
-+            neighsh = * (face *)(* spinshlist)[i];
-           }
--          // 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);
-+          // Only do test when the spinsh is faceing inward.
-+          stpivot(spinsh, adjtet);
-+          if (adjtet.tet != dummytet) {
-+            angle = facedihedral(eorg, edest, sapex(spinsh), sapex(neighsh));
-+            issharp = angle < smallang;
-+          }
-+          spinsh = neighsh;
-         }
--        sharpsegcount++;
-+        spinshlist->clear();
-       }
--    }
--    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++;
--        }
-+      // Set type for this segment (inclusing subsegments).
-+      stype = issharp ? SHARP : NSHARPNSKINNY;
-+      scount += issharp ? 1 : 0;
-+      setshelltype(segloop, stype);
-+      senext(segloop, nextseg);
-+      spivotself(nextseg);
-+      while (nextseg.sh != dummysh) {
-+        nextseg.shver = 0;
-+        setshelltype(nextseg, stype);
-+        senextself(nextseg);
-+        spivotself(nextseg);
-       }
--      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();
-+    segloop.sh = shellfacetraverse(subsegs);
-   }
- 
-   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);
--    }
-+    printf("  %d sharp segments.\n", scount);
-   }
--
--  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;
-+  delete spinshlist;
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// enqueueencsub()    Add an encroached subface into the queue.              //
-+// markskinnysubfaces()    Mark all skinny subfaces.                         //
- //                                                                           //
--///////////////////////////////////////////////////////////////////////////////
--
--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);
--  }
--}
--
--///////////////////////////////////////////////////////////////////////////////
-+// A subface is skinny if it has an angle smaller than 'anglebound' and the  //
-+// two edges form the angle are both segments. Such subface is not be able   //
-+// to refine.  It will be marked as type SKINNY.                             //
- //                                                                           //
--// dequeueencsub()    Remove an enc-subface from the front of the queue.     //
-+// This procedure operates in two phases.  The first phase finds some skinny //
-+// subfaces by checking the angles of subfaces.  The second phase finds all  //
-+// skinny subfaces by a neighbor-first search.                               //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--tetgenmesh::badface* tetgenmesh::dequeueencsub(int* pquenumber)
--{
--  badface *result;
--  int quenumber;
-+void tetgenmesh::markskinnysubfaces(REAL anglebound)
-+{
-+  list *skinnyshlist;
-+  face subloop, checksub;
-+  face startsh, neighsh;
-+  face seg1, seg2, checkseg;
-+  point pa, pb, pc;
-+  enum shestype shty;
-+  REAL smallang, angle;
-+  int i, j;
-+
-+  if (b->verbose > 0) {
-+    printf("  Marking skinny subfaces.\n");
-+  }
- 
--  // 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];
-+  smallang = anglebound * PI / 180.;
-+  // Initial working list.
-+  skinnyshlist = new list(sizeof(face), NULL, subfaces->items);
-+
-+  // Loop the set of subfaces, collect some skinny ones.
-+  subfaces->traversalinit();
-+  subloop.sh = shellfacetraverse(subfaces);
-+  while (subloop.sh != (shellface *) NULL) {
-+    // Check the three angles of subloop;
-+    for (i = 0; i < 3; i++) {
-+      sspivot(subloop, seg1);
-+      if (seg1.sh != dummysh) {
-+        senext2(subloop, checksub);
-+        sspivot(checksub, seg2);
-+        if (seg2.sh != dummysh) {
-+          pa = sorg(subloop);
-+          pb = sdest(subloop);
-+          pc = sapex(subloop);
-+          angle = interiorangle(pa, pb, pc, NULL);
-+          if (angle < smallang) {
-+            // It is skinny!
-+            setshelltype(subloop, SKINNY);
-+            skinnyshlist->append(&subloop);
-+            break;
-+          }
-+        }
-       }
--      *pquenumber = quenumber;
--      return result;
-+      senextself(subloop);
-     }
-+    subloop.sh = shellfacetraverse(subfaces);
-   }
--  return (badface *) NULL;
-+
-+  // Next finds all skinny subfaces.
-+  for (i = 0; i < skinnyshlist->len(); i++) {
-+    startsh = * (face *)(* skinnyshlist)[i];
-+    shty = shelltype(startsh);
-+    for (j = 0; j < 3; j++) {
-+      sspivot(startsh, checkseg);
-+      if (checkseg.sh == dummysh) {
-+        spivot(startsh, neighsh);
-+        if (shelltype(neighsh) != shty) {
-+          setshelltype(neighsh, shty);
-+          skinnyshlist->append(&neighsh);
-+        }
-+      }
-+      senextself(startsh);
-+    }
-+  }
-+
-+  if (b->verbose > 0) {
-+    printf("  %d skinny subfaces.\n", skinnyshlist->len());
-+  }
-+  delete skinnyshlist;
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -28266,8 +25203,7 @@
-   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 = (int) ((ratio2 - b->goodratio) / 0.5);
-     // 'queuenumber' may overflow (negative) caused by a very large ratio.
-     if ((queuenumber > 63) || (queuenumber < 0)) {
-       queuenumber = 63;
-@@ -28276,33 +25212,10 @@
-     // 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;
--
-+  // Add the tetrahedron to the end of a queue.
-+  *tetquetail[queuenumber] = newbadtet;
-+  // Maintain a pointer to the NULL pointer at the end of the queue.
-+  tetquetail[queuenumber] = &newbadtet->nextitem;
-   if (b->verbose > 2) {
-     printf("    Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
-            pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
-@@ -28313,53 +25226,94 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// dequeuebadtet()    Remove a tetrahedron from the front of the queue.      //
-+// enqueueencsub()    Add an encroached subface into the queue.              //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--tetgenmesh::badface* tetgenmesh::topbadtetra()
-+void tetgenmesh::enqueueencsub(face* testsub, point encpt, int quenumber,
-+  REAL* cent)
- {
--  // 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;
-+  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;
-+  if (quenumber == 2) {
-+    for (i = 0; i < 3; i++) encsub->cent[i] = 0.0;
-   } else {
--    // Return the first tetrahedron of the highest-priority queue.
--    return tetquefront[firstnonemptyq];
-+    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);
-   }
- }
- 
--void tetgenmesh::dequeuebadtet()
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
-+// dequeuebadtet()    Remove a tetrahedron from the front of the queue.      //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+tetgenmesh::badface* tetgenmesh::dequeuebadtet()
- {
--  badface *deadbadtet;
--  int i;
-+  badface *result;
-+  int queuenumber;
- 
--  // 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];
-+  // Look for a nonempty queue.
-+  for (queuenumber = 63; queuenumber >= 0; queuenumber--) {
-+    result = tetquefront[queuenumber];
-+    if (result != (badface *) NULL) {
-+      // Remove the tetrahedron from the queue.
-+      tetquefront[queuenumber] = result->nextitem;
-+      // Maintain a pointer to the NULL pointer at the end of the queue.
-+      if (tetquefront[queuenumber] == (badface *) NULL) {
-+        tetquetail[queuenumber] = &tetquefront[queuenumber];
-+      }
-+      return result;
-+    }
-+  }
-+  return (badface *) NULL;
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
-+// 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 the bad tetrahedron to the pool.
--    badfacedealloc(badtetrahedrons, deadbadtet);
-   }
-+  return (badface *) NULL;
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -28389,7 +25343,6 @@
-   bool enq;
-   int hitbdry;
- 
--  enq = false;
-   eorg = sorg(*testseg);
-   edest = sdest(*testseg);
-   cent[0] = 0.5 * (eorg[0] + edest[0]);
-@@ -28397,55 +25350,50 @@
-   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;
-+  enq = false;
-+  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++;
--            } 
--          }
-+      }
-+      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);
--    }
-+      }
-+    } 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) {
-@@ -28482,57 +25430,31 @@
- 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;
-+  point forg, fdest, fapex, encpt;
-+  REAL cent[3];
-   REAL radius, dist, diff;
--  bool enq;
--  int indx[4];
-+  bool enq, ncollinear;
-   int quenumber;
-   
--  enq = false;
--  radius = 0.0;
--  encpt = (point) NULL;
--
--  pa = sorg(*testsub);
--  pb = sdest(*testsub);
--  pc = sapex(*testsub);
-+  forg = sorg(*testsub);
-+  fdest = sdest(*testsub);
-+  fapex = sapex(*testsub);
-+  ncollinear = circumsphere(forg, fdest, fapex, NULL, cent, &radius);
-+  if (!ncollinear) return false; // Not a valid subface.
-   
--  // 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.
-+  enq = false;
-+  encpt = (point) NULL;  
-+  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);
-     }
--  }
--
--  // 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) {
-+    if (!enq) {
-+      sesymself(*testsub);
-       stpivot(*testsub, abuttet);
-       if (abuttet.tet != dummytet) {
-         dist = distance(cent, oppo(abuttet));
-@@ -28541,30 +25463,190 @@
-         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 && enqflag) {
-+    /* REAL prj[3], ori1, ori2, ori3;
-+    bool inflag;
-+    // Test if encpt is inside the face.
-+    if (encpt) {
-+      projpt2face(encpt, forg, fdest, fapex, prj);
-     } else {
--      dist = distance(cent, testpt);
--      diff = dist - radius;
--      if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
--      enq = (diff <= 0.0);
-+      assert(testpt);
-+      projpt2face(testpt, forg, fdest, fapex, prj);
-     }
--    if (enq) {
--      quenumber = 0; // A queue of encroached subfaces.
-+    abovepoint = facetabovepointarray[shellmark(*testsub)];
-+    if (abovepoint == (point) NULL) {
-+      getfacetabovepoint(testsub);
-     }
-+    ori1 = orient3d(forg, fdest, abovepoint, prj);
-+    ori2 = orient3d(fdest, fapex, abovepoint, prj);
-+    inflag = (ori1 * ori2 >= 0.0);
-+    if (inflag) { 
-+      ori3 = orient3d(fapex, forg, abovepoint, prj);
-+      inflag = (ori2 * ori3 >= 0.0);
-+    }
-+    // Decide which queue (1 or 0) to put s (1 has higher priority).
-+    quenumber = (inflag ? 1 : 0); */
-+    quenumber = 0;
-+    enqueueencsub(testsub, encpt, quenumber, cent);    
-   }
- 
-+  return enq;
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
-+// checkseg4badqual()    Check if a segment is longer than it is allowed.    //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+bool tetgenmesh::checkseg4badqual(face* testseg, bool enqflag)
-+{
-+  badface *encsubseg;
-+  point eorg, edest;
-+  REAL dist;
-+  bool enq;
-+
-+  eorg = sorg(*testseg);
-+  edest = sdest(*testseg);
-+  dist = distance(eorg, edest);
-+  
-+  enq = dist > areabound(*testseg);
-+
-   if (enq && enqflag) {
--    enqueueencsub(testsub, encpt, quenumber, cent);    
-+    if (b->verbose > 2) {
-+      printf("    Queuing badqual subsegment (%d, %d).\n",
-+             pointmark(eorg), pointmark(edest));
-+    }
-+    encsubseg = (badface *) badsubsegs->alloc();
-+    encsubseg->ss = *testseg;
-+    encsubseg->forg = eorg;
-+    encsubseg->fdest = edest;
-+    encsubseg->foppo = NULL;
-+    // 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;
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
-+// checksub4badqual()    Test if the quality of a subface is bad.            //
-+//                                                                           //
-+// A subface has bad quality if: (1) its minimum internal angle is smaller   //
-+// than 20 degree; or (2) its area is larger than a maximum area condition.  //
-+// Return TRUE if it is bad.                                                 //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+bool tetgenmesh::checksub4badqual(face* testsub, bool enqflag)
-+{
-+  face sametestsub;
-+  face subseg1, subseg2;
-+  point torg, tdest, tapex;
-+  point anglevertex;
-+  REAL dxod, dyod, dzod;
-+  REAL dxda, dyda, dzda;
-+  REAL dxao, dyao, dzao;
-+  REAL dxod2, dyod2, dzod2;
-+  REAL dxda2, dyda2, dzda2;
-+  REAL dxao2, dyao2, dzao2;
-+  REAL apexlen, orglen, destlen;
-+  REAL angle, area;
-+  bool enq;
-+
-+  enq = false;
-+  torg = sorg(*testsub);
-+  tdest = sdest(*testsub);
-+  tapex = sapex(*testsub);
-+  dxod = torg[0] - tdest[0];
-+  dyod = torg[1] - tdest[1];
-+  dzod = torg[2] - tdest[2];
-+  dxda = tdest[0] - tapex[0];
-+  dyda = tdest[1] - tapex[1];
-+  dzda = tdest[2] - tapex[2];
-+  dxao = tapex[0] - torg[0];
-+  dyao = tapex[1] - torg[1];
-+  dzao = tapex[2] - torg[2];
-+  dxod2 = dxod * dxod;
-+  dyod2 = dyod * dyod;
-+  dzod2 = dzod * dzod;
-+  dxda2 = dxda * dxda;
-+  dyda2 = dyda * dyda;
-+  dzda2 = dzda * dzda;
-+  dxao2 = dxao * dxao;
-+  dyao2 = dyao * dyao;
-+  dzao2 = dzao * dzao;
-+  // Find the lengths of the triangle's three edges.
-+  apexlen = dxod2 + dyod2 + dzod2;
-+  orglen = dxda2 + dyda2 + dzda2;
-+  destlen = dxao2 + dyao2 + dzao2;
-+  if ((apexlen < orglen) && (apexlen < destlen)) {
-+    // The edge opposite the apex is shortest.
-+    // Find the square of the cosine of the angle at the apex.
-+    angle = dxda * dxao + dyda * dyao + dzda * dzao;
-+    angle = angle * angle / (orglen * destlen);
-+    anglevertex = tapex;
-+    senext(*testsub, sametestsub);
-+    sspivot(sametestsub, subseg1);
-+    senext2(*testsub, sametestsub);
-+    sspivot(sametestsub, subseg2);
-+  } else if (orglen < destlen) {
-+    // The edge opposite the origin is shortest.
-+    // Find the square of the cosine of the angle at the origin.
-+    angle = dxod * dxao + dyod * dyao + dzod * dzao;
-+    angle = angle * angle / (apexlen * destlen);
-+    anglevertex = torg;
-+    sspivot(*testsub, subseg1);
-+    senext2(*testsub, sametestsub);
-+    sspivot(sametestsub, subseg2);
-+  } else {
-+    // The edge opposite the destination is shortest.
-+    // Find the square of the cosine of the angle at the destination.
-+    angle = dxod * dxda + dyod * dyda + dzod * dzda;
-+    angle = angle * angle / (apexlen * orglen);
-+    anglevertex = tdest;
-+    sspivot(*testsub, subseg1);
-+    senext(*testsub, sametestsub);
-+    sspivot(sametestsub, subseg2);
-+  }
-+
-+  // Check if both edges that form the angle are segments.
-+  // if ((subseg1.sh != dummysh) && (subseg2.sh != dummysh)) {
-+  if (shelltype(*testsub) == SKINNY) {
-+    // The angle is a segment intersection.  Don't add this bad subface to
-+    //   the list; there's nothing that can be done about a small angle
-+    //   between two segments.
-+    angle = 0.0;
-+  }
-+
-+  // Check whether the angle is smaller than permitted.
-+  if (angle > b->goodangle) {
-+    enq = true;
-+  }
-+
-+  if (!enq && varconstraint && areabound(*testsub) > 0.0) {
-+    // Check whether the area is larger than desired.  A variation form of
-+    //   Heron's formula which only uses the squares of the edge lengthes
-+    //   is used to calculated the area of a 3D triangle.
-+    area = apexlen + orglen - destlen;
-+    area = area * area;
-+    area = 4 * apexlen * orglen - area;
-+    area = 0.25 * sqrt(fabs(area));
-+    enq = area > areabound(*testsub);
-+  }
-+
-+  if (enq && enqflag) {   
-+    enqueueencsub(testsub, NULL, 2, NULL);
-   }
- 
-   return enq;
-@@ -28582,17 +25664,19 @@
- 
- bool tetgenmesh::checktet4badqual(triface* testtet, bool enqflag)
- {
-+  badface *newbadtet;
-   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 volume, L, q, cosd;
-   REAL radius2, smlen2, ratio2;
-   REAL dist, sdist, split;
-   bool enq;
-   int indx[4];
-+  int queuenumber;
-   int sidx, i, j; 
- 
-   pa = (point) testtet->tet[4];
-@@ -28600,6 +25684,10 @@
-   pc = (point) testtet->tet[6];
-   pd = (point) testtet->tet[7];
- 
-+  // Avoid compile warnings.
-+  pe1 = pe2 = (point) NULL;
-+  radius2 = 0.0;
-+
-   // 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];
-@@ -28615,118 +25703,135 @@
-   // 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.
-+  // Compare the volume to average edge length of abcd.
-   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;
-+  
-+  enq = false;
-+  if (b->offcenter) {
-+    // Check if the tet is very flat.
-+    L = 0.0;
-+    for (i = 0; i < 6; i++) L += sqrt(elen[i]);
-+    L /= 6.0;
-+    q = volume / (L * L * L);
-+    enq = (q < b->epsilon * 1e+2);
-+  }
-+  
-+  // Is abcd very flat?
-   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;
-+    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.
-+    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.
-+      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) || ((cosd < cosmaxdihed)));
-+        }
-+        if (enq) {
-+          // A sliver! Split it at the barycenter.
-+          for (i = 0; i < 3; i++) {
-+            circumcent[i] = 0.25 * (pa[i] + pb[i] + pc[i] + pd[i]);
-+          }
-+          ratio2 = 0.0;
-         }
-       }
--    // }
--  } 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.
-+    } 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: break;
-+      }
-+      // 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]);
-+      }
-+    }
-+  } else {
-+    // A fat tet. Split it at the centroid.
-     for (i = 0; i < 3; i++) {
--      offcent[i] = bicent[i] + split * (circumcent[i] - bicent[i]);
-+      circumcent[i] = 0.25 * (pa[i] + pb[i] + pc[i] + pd[i]);
-     }
-+    ratio2 = 0.0;
-   }
- 
-   if (!enq && (b->varvolume || b->fixedvolume)) {
--    // Check if the tet has too big volume.
-+    // The tet is in good shape.
-+    ratio2 = 0.0;
-     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);
-+    // The tet is in good shape.
-+    ratio2 = 0.0;
-+    if (b->bgmesh && (b->alpha1 > 0.0)) {
-       sdist = sqrt(radius2) / b->alpha1;
-+      // Check if the nodal size map is satisfied. 
-       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];
-+        dist = pa[3]; // dist = b->alpha1 * pa[pointlfsindex];
-         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).
-@@ -28734,14 +25839,44 @@
-       }
-       // *** 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];
-+    // Allocate space for the bad tetrahedron.
-+    newbadtet = (badface *) badtetrahedrons->alloc();
-+    newbadtet->tt = *testtet;
-+    newbadtet->key = ratio2;
-+    if ((ratio2 != 0) && b->offcenter) {
-+      for (i = 0; i < 3; i++) newbadtet->cent[i] = offcent[i];
-+    } else {
-+      for (i = 0; i < 3; i++) newbadtet->cent[i] = circumcent[i];
-+    }
-+    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' 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;
-+    }
-+    // Add the tetrahedron to the end of a queue.
-+    *tetquetail[queuenumber] = newbadtet;
-+    // Maintain a pointer to the NULL pointer at the end of the queue.
-+    tetquetail[queuenumber] = &newbadtet->nextitem;
-+    if (b->verbose > 2) {
-+      printf("    Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
-+             pointmark(pa), pointmark(pb), pointmark(pc), pointmark(pd),
-+             sqrt(ratio2), queuenumber);
-     }
--    enqueuebadtet(testtet, ratio2, circumcent);
-   }
- 
-   return enq;
-@@ -28757,23 +25892,28 @@
- // 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.                                                 //
-+// p can be inserted if it is in one of the following cases (L = |a - b|):   //
-+//   (1) if ab is too long wrt the edge constraint (bad-quality); or         //
-+//   (2) if a subface having ab has max. area constraint A, and L^2 > 2 * A, //
-+//   (3) if a tet having ab has maximal volume constraint V, and L^3 > 6 * V.//
-+//   (4) if |a - p| > \alpha_2 H(a) and |p - b| > \alpha_2 H(b).             //
-+//   (5) if 'refpt' != NULL.                                                 //
-+//                                                                           //
-+// The purpose of using L instead of area and volume is to avoid resulting   //
-+// too skinny triangles and tetrahedron.                                     //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
- bool tetgenmesh::acceptsegpt(point segpt, point refpt, face* splitseg)
- {
--  point p[2];
--  REAL L, lfs;
--  int i, j;
-+  triface spintet;
-+  face parentsh, spinsh;
-+  point pa, pb, pc;
-+  REAL ablen, palen, pblen;
-+  REAL V, A;
- 
-   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);
-@@ -28788,26 +25928,73 @@
-     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) {
-+  pa = sorg(*splitseg);
-+  pb = sdest(*splitseg);
-+  ablen = distance(pa, pb);
-+  if (varconstraint) {
-+    A = areabound(*splitseg);
-+    if ((A > 0.0) && (ablen > A)) {
-       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 (varconstraint && in->facetconstraintlist) {
-+    A = ablen * ablen / 2.0;
-+    spinsh = parentsh;
-+    do {
-+      if ((A > areabound(spinsh)) && (areabound(spinsh) > 0.0)) {
-+        return true; // case (2)
-+      }
-+      spivotself(spinsh);
-+    } while (spinsh.sh != parentsh.sh);
-+  }
-+
-+  if (b->varvolume || b->fixedvolume) {
-+    V = ablen * ablen * ablen / 6.0;
-+    if (b->fixedvolume && (V > b->maxvolume)) {
-+      return true; // case (3)
-+    }
-+    if (b->varvolume) {
-+      spivot(*splitseg, parentsh);
-+      if (sorg(parentsh) != pa) sesymself(parentsh);
-+      stpivot(parentsh, spintet);
-+      if (spintet.tet == dummytet) {
-+        sesymself(parentsh);
-+        stpivot(parentsh, spintet);
-+      }
-+      findedge(&spintet, pa, pb);
-+      pc = apex(spintet);
-+      while (true) {
-+        if (!fnextself(spintet)) {
-+          // Meet a boundary, walk through it.
-+          tspivot(spintet, spinsh);
-+          findedge(&spinsh, pa, pb);
-+          sfnextself(spinsh);
-+          stpivot(spinsh, spintet);
-+          findedge(&spintet, pa, pb);
-+        }
-+        if ((V > volumebound(spintet.tet)) && 
-+            (volumebound(spintet.tet) > 0.0)) {
-+          return true; // case (3)
-+        }
-+        if (apex(spintet) == pc) break;
-+      }
-+    }
-+  }
-+
-+  // If p is outside both protect balls of a and b.
-+  palen = distance(segpt, pa);
-+  pblen = distance(segpt, pb);
-+  if (!b->bgmesh) {
-+    if ((palen > (b->alpha2 * pa[pointlfsindex])) &&
-+        (pblen > (b->alpha2 * pb[pointlfsindex]))) {
-+      return true; // case (4)
-+    }
-+  } else {
-+    if ((palen > b->alpha2 * pa[3]) && (pblen > b->alpha2 * pb[3])) {
-+      return true; // case (4)
-     }
-   }
--  if (j == 0) return true; // case (3).
- 
-   // If 'refpt' != NULL, force p to be inserted.
-   if (refpt != (point) NULL) {
-@@ -28830,20 +26017,26 @@
- // 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.            //
-+// p can be inserted if it is in one of the following cases (f is a subface  //
-+// of CBC(p), L = max{|p - v|, v \in V}):                                    //
-+//   (1) if f has maximal area constraints A, and L^2 > 2 * A.               //
-+//   (2) if a tet having f has max. volume constraint V, and L^3 > 6 * V.    //
-+//   (3) if |p - v| > \alpha_2 H(v), for all v \in V.                        //
-+//                                                                           //
-+// The purpose of using L^3 is to avoid resulting too skinny tetrahedron.    //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
- bool tetgenmesh::acceptfacpt(point facpt, list* subceillist, list* verlist)
- {
-+  triface testtet;
-   face *testsh;
--  point p[2], ploop;
--  REAL L, lfs;
-+  point p[3];
-+  REAL L, L2, L3, 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) {
-@@ -28869,23 +26062,76 @@
-       }
-     }
-   }
--
--  j = 0; // Use j to count the number of inside balls.
-+  // Uninfect collected vertices.
-   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.
-+    p[0] = * (point *)(* verlist)[i];
-+    idx = pointmark(p[0]);
-+    setpointmark(p[0], -(idx + 1));
-+  }
-+
-+  if (varconstraint && in->facetconstraintlist) {
-+    for (i = 0; i < subceillist->len(); i++) {
-+      testsh = (face *)(* subceillist)[i];
-+      if (areabound(*testsh) > 0.0) {
-+        // Get the longest edge length of testsh = L.
-+        for (j = 0; j < 3; j++) p[j] = (point) testsh->sh[j + 3];
-+        L = distance(p[0], p[1]);
-+        L2 = distance(p[1], p[2]);
-+        L = (L >= L2 ? L : L2);
-+        L2 = distance(p[2], p[0]);
-+        L = (L >= L2 ? L : L2);
-+        L2 = L * L / 2.0;
-+        if (L2 > areabound(*testsh)) {
-+          return true; // case (1)
-+        }
-+      }
-+    }
-+  }
-+
-+  // Check if it is in case (2).
-+  if (b->varvolume || b->fixedvolume) {
-+    for (i = 0; i < subceillist->len(); i++) {
-+      testsh = (face *)(* subceillist)[i];
-+      // Get the longest edge length of testsh = L.
-+      for (j = 0; j < 3; j++) p[j] = (point) testsh->sh[j + 3];
-+      L = distance(p[0], p[1]);
-+      L3 = distance(p[1], p[2]);
-+      L = (L >= L3 ? L : L3);
-+      L3 = distance(p[2], p[0]);
-+      L = (L >= L3 ? L : L3);
-+      L3 = L * L * L / 6.0;
-+      if (b->fixedvolume && (L3 > b->maxvolume)) {
-+        // This face is too large wrt. the maximum volume bound. Split it.
-+        return true; // case (2) 
-+      }
-+      if (b->varvolume) {
-+        for (j = 0; j < 2; j ++) {
-+          stpivot(*testsh, testtet);
-+          if (testtet.tet != dummytet) {
-+            if ((L3 > volumebound(testtet.tet)) && 
-+                (volumebound(testtet.tet) > 0.0)) {
-+              // This face is too large wrt the maximum volume bound.
-+              return true; // case (2)
-+            }
-+          }
-+          sesymself(*testsh);
-+        }
-+      }
-     }
-   }
--  verlist->clear();
- 
--  if (j == 0) return true; // case (3).
-+  // Check if p is inside the protect balls of vertices of V.
-+  for (i = 0; i < verlist->len(); i++) {
-+    p[0] = * (point *)(* verlist)[i];
-+    if (!b->bgmesh) {
-+      lfs = b->alpha2 * p[0][pointlfsindex];
-+    } else {
-+      lfs = b->alpha2 * p[0][3];
-+    }
-+    L = distance(p[0], facpt);
-+    if (L < lfs) break; // p is inside ball.
-+  }
-+  if (i == verlist->len()) return true; // case (3).
- 
-   rejsubpts++;
-   return false;
-@@ -28898,15 +26144,17 @@
- // '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.               //
-+// p can be split if it is in one of the following cases:                    //
-+//   (1) if the t \in B(p) has maximal volume constraint V, and vol(t) < V.  //
-+//   (2) 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;
-+  point p[4];
-+  REAL L, vol, lfs;
-   int idx, i, j;
- 
-   // Collect the vertices of CBC(p), save them in V.
-@@ -28923,23 +26171,45 @@
-       }
-     }
-   }
-+  // Uninfect collected vertices.
-+  for (i = 0; i < verlist->len(); i++) {
-+    p[0] = * (point *)(* verlist)[i];
-+    idx = pointmark(p[0]);
-+    setpointmark(p[0], -(idx + 1));
-+  }
-+
-+  if (b->varvolume || b->fixedvolume) {
-+    for (i = 0; i < ceillist->len(); i++) {
-+      testtet = (triface *)(* ceillist)[i];
-+      for (j = 0; j < 4; j++) p[j] = (point) testtet->tet[4 + j];
-+      vol = orient3d(p[0], p[1], p[2], p[3]) / 6.0;
-+      if (vol < 0) vol = -vol;
-+      if (b->fixedvolume && (vol > b->maxvolume)) {
-+        // This tet is too large wrt. the maximum volume bound. Split it.
-+        return true; // case (1) 
-+      }
-+      if (b->varvolume) {
-+        if ((vol > volumebound(testtet->tet)) && 
-+            (volumebound(testtet->tet) > 0.0)) {
-+          // This tet is too large wrt the maximum volume bound.
-+          return true; // case (1)
-+        }
-+      }
-+    }
-+  }
- 
--  j = 0; // Use j to counte the number of inside balls.
-+  // Check if p is inside the protect balls of vertices of V.
-   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.
-+    p[0] = * (point *)(* verlist)[i];
-+    if (!b->bgmesh) {
-+      lfs = b->alpha2 * p[0][pointlfsindex];
-+    } else {
-+      lfs = b->alpha2 * p[0][3];
-     }
-+    L = distance(p[0], volpt);
-+    if (L < lfs) break; // p is inside ball.
-   }
--  verlist->clear();
--  
--  if (j == 0) return true; // case (2).
-+  if (i == verlist->len()) return true; // case (2).
- 
-   rejtetpts++;
-   return false;
-@@ -28997,27 +26267,17 @@
-       // Add a random perturbation on newpt.
-       d1 = distance(ei, newpt);
-       d2 = distance(newpt, refpt);
--      ps = randgenerator(d2 * b->epsilon2 * 1e+2);
-+      ps = randgenerator(d2 * b->epsilon2);
-       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]);
-   }
- }
- 
-@@ -29050,10 +26310,10 @@
-     sumweight += weights[i];
-   }
-   // Interpolate.
--  newpt[pointmtrindex] = 0.0;
-+  newpt[pointlfsindex] = 0.0;
-   for (i = 0; i < verlist->len(); i++) {
-     neipt = * (point *)(* verlist)[i];
--    newpt[pointmtrindex] += (weights[i] * neipt[pointmtrindex]) / sumweight;
-+    newpt[pointlfsindex] += (weights[i] * neipt[pointlfsindex]) / sumweight;
-   }
- 
-   delete [] weights;
-@@ -29064,33 +26324,22 @@
- // 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.                              //
-+// (b->bgmesh) or from the sizes of the adjacent vertices of p.              //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--void tetgenmesh::setnewpointsize(point newpt, point e1, point e2)
-+void tetgenmesh::setnewpointsize(point newpt, list* verlist)
- {
--  if (b->metric) {
--    // Interpolate the point size in a background mesh.
-+  if (b->bgmesh) {
-     triface bgmtet;
-+    point pa;
-     // Get a tet in background mesh for locating p.
--    decode(point2bgmtet(e1), bgmtet);
--    p1interpolatebgm(newpt, &bgmtet, NULL);
-+    pa = * (point *)(* verlist)[0];
-+    decode(point2bgmtet(pa), bgmtet);
-+    interpolatepointsize(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];
--    }
-+    // Interpolate a local size for p using Shepard interpolation.
-+    shepardinterpolate(newpt, verlist);
-   }
- }
- 
-@@ -29101,93 +26350,82 @@
- ///////////////////////////////////////////////////////////////////////////////
- 
- void tetgenmesh::splitencseg(point newpt, face* splitseg, list* tetlist,
--  list* sublist, list* verlist, queue* flipque, bool chkencsub, bool chkbadtet,
--  bool optflag)
-+  list* sublist, list* verlist, queue* flipque, bool chkencsub, bool chkbadtet)
- {
--  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);
-+  if (steinerleft > 0) steinerleft--;
-   // Remove locally non-Delaunay faces by flipping.
--  flip(flipque, NULL); // lawson(NULL, flipque);
-+  flip(flipque, NULL);
-   
--  if (!optflag) { 
--    // Check the two new subsegs to see if they're encroached (not by p).
--    for (i = 0; i < 2; i++) {
-+  // 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 (!shell2badface(*splitseg)) {
--        checkseg4encroach(splitseg, NULL, NULL, true);
-+        if (varconstraint && (areabound(*splitseg) > 0.0)) {
-+          checkseg4badqual(splitseg, true);
-+        }
-       }
--      if (i == 1) break; // Two new segs have been checked.
--      senextself(*splitseg);
--      spivotself(*splitseg);
-+    }
-+    if (i == 1) break; // Two new segs have been checked.
-+    senextself(*splitseg);
-+    spivotself(*splitseg);
- #ifdef SELF_CHECK
--      assert(splitseg->sh != (shellface *) NULL);
-+    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];
-+    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);
-           if (!shell2badface(checksh)) {
--            checksub4encroach(&checksh, NULL, true);
-+            if (varconstraint && (areabound(checksh) > 0.0)) {
-+              checksub4badqual(&checksh, true);
-+            }
-           }
-         }
--        sublist->clear();
--        if (verlist) verlist->clear();
--        spivotself(spinsh);
--      } while (spinsh.sh != startsh.sh);
--    }
--  } // if (!optflag)  
--
-+      }
-+      sublist->clear();
-+      verlist->clear();
-+      spivotself(spinsh);
-+    } while (spinsh.sh != startsh.sh);
-+  }
-+  
-   // 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.
-+  // 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];
--      checktet4opt(&starttet, true);
-+      checktet4badqual(&starttet, true);
-     }
--    delete mytetlist;
--    delete myflipque;
-   }
-+  tetlist->clear();
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -29227,6 +26465,11 @@
-             // Found a segment. Test it if it isn't in enc-list.
-             if (!shell2badface(checkseg)) {
-               checkseg4encroach(&checkseg, testpt, NULL, true);
-+              if (!shell2badface(checkseg)) {
-+                if (varconstraint && (areabound(checkseg) > 0.0)) {
-+                  checkseg4badqual(&checkseg, true);
-+                }
-+              }
-             }
-           }
-           enextself(ceiltet);
-@@ -29241,6 +26484,11 @@
-       // Test it if it isn't in enc-list.
-       if (!shell2badface(checkseg)) {
-         checkseg4encroach(&checkseg, testpt, NULL, true);
-+        if (!shell2badface(checkseg)) {
-+          if (varconstraint && (areabound(checkseg) > 0.0)) {
-+            checkseg4badqual(&checkseg, true);
-+          }
-+        }
-       }
-       checkseg.sh = shellfacetraverse(subsegs);
-     }
-@@ -29284,6 +26532,11 @@
-           // Found a subface. Test it if it isn't in enc-list.
-           if (!shell2badface(checksh)) {
-             checksub4encroach(&checksh, testpt, true);
-+            if (!shell2badface(checksh)) {
-+              if (varconstraint && (areabound(checksh) > 0.0)) {
-+                checksub4badqual(&checksh, true);
-+              }
-+            }
-           }
-         }
-       }
-@@ -29296,6 +26549,11 @@
-       // Test it if it isn't in enc-list.
-       if (!shell2badface(checksh)) {
-         checksub4encroach(&checksh, testpt, true);
-+        if (!shell2badface(checksh)) {
-+          if (varconstraint && (areabound(checksh) > 0.0)) {
-+            checksub4badqual(&checksh, true);
-+          }
-+        }
-       }
-       checksh.sh = shellfacetraverse(subfaces);
-     }
-@@ -29340,17 +26598,18 @@
- {
-   list **tetlists, **ceillists;
-   list **sublists, **subceillists;
--  list *tetlist, *sublist;
-+  list *tetlist, *sublist, *verlist;
-   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;
-+  tetlist = (list *) NULL;
-+  flipque = (queue *) NULL;
-   if (!b->fliprepair) {
-     tetlists = new list*[nmax];
-     ceillists = new list*[nmax];
-@@ -29359,6 +26618,9 @@
-   } else {
-     tetlist = new list(sizeof(triface), NULL, 1024);
-     sublist = new list(sizeof(face), NULL, 256);
-+  }
-+  verlist = new list(sizeof(point *), NULL, 256);
-+  if (b->fliprepair) {
-     flipque = new queue(sizeof(badface));
-   }
- 
-@@ -29385,6 +26647,9 @@
-         }
-         // Create the new point p (at the middle of s).
-         makepoint(&newpt);
-+        // for (i = 0; i < 3; i++) {
-+        //   newpt[i] = 0.5 * (encloop->forg[i] + encloop->fdest[i]);
-+        // }
-         getsplitpoint(encloop->forg, encloop->fdest, refpt, newpt);
-         setpointtype(newpt, FREESEGVERTEX);
-         setpoint2sh(newpt, sencode(splitseg));
-@@ -29403,13 +26668,6 @@
-                   // 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,
-@@ -29418,9 +26676,9 @@
-                     if (trimbowatcavity(sympt, &symsplitseg, n, sublists,
-                           subceillists, tetlists, ceillists, -1.0)) {
-                       bowatinsertsite(sympt, &symsplitseg, n, sublists,
--                        subceillists, tetlists, ceillists, NULL, flipque,
-+                        subceillists, tetlists, ceillists, verlist, flipque,
-                         true, chkencsub, chkbadtet);
--                      setnewpointsize(sympt, e1, e2);
-+                      setnewpointsize(sympt, verlist);
-                       if (steinerleft > 0) steinerleft--;
-                     } else {
-                       // p did not insert for invalid BC(symp).
-@@ -29430,11 +26688,12 @@
-                     releasebowatcavity(&symsplitseg, n, sublists, subceillists,
-                                        tetlists, ceillists);
-                   } else {
--                    splitencseg(sympt, &symsplitseg, tetlist, sublist, NULL,
--                                flipque, chkencsub, chkbadtet, false);
--                    setnewpointsize(sympt, e1, e2);
-+                    splitencseg(sympt, &symsplitseg, tetlist, sublist, verlist,
-+                                flipque, chkencsub, chkbadtet);
-+                    setnewpointsize(sympt, verlist);
-                     if (steinerleft > 0) steinerleft--;
-                   }
-+                  verlist->clear();
-                 } else {
-                   // The sympt are on the same segment. It is possible when
-                   //   splitseg is the symmetric rotating axes.
-@@ -29451,13 +26710,6 @@
-               }
-             } // 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,
-@@ -29466,9 +26718,9 @@
-             if (trimbowatcavity(newpt, &splitseg, n, sublists, subceillists, 
-                                 tetlists, ceillists, -1.0)) {
-               bowatinsertsite(newpt, &splitseg, n, sublists, subceillists,
--                              tetlists, ceillists, NULL, flipque, true,
-+                              tetlists, ceillists, verlist, flipque, true,
-                               chkencsub, chkbadtet);
--              setnewpointsize(newpt, e1, e2);
-+              setnewpointsize(newpt, verlist);
-               if (steinerleft > 0) steinerleft--;
-             } else {
-               // p did not insert for invalid B(p).
-@@ -29478,11 +26730,12 @@
-             releasebowatcavity(&splitseg, n, sublists, subceillists, tetlists,
-                                ceillists);
-           } else {
--            splitencseg(newpt, &splitseg, tetlist, sublist, NULL, flipque,
--                        chkencsub, chkbadtet, false);
--            setnewpointsize(newpt, e1, e2);
-+            splitencseg(newpt, &splitseg, tetlist, sublist, verlist, flipque,
-+                        chkencsub, chkbadtet);
-+            setnewpointsize(newpt, verlist);
-             if (steinerleft > 0) steinerleft--;
-           }
-+          verlist->clear();
-         } else {
-           // p did not accept for insertion.
-           pointdealloc(newpt);
-@@ -29501,6 +26754,9 @@
-   } else {
-     delete tetlist;
-     delete sublist;
-+  }
-+  delete verlist;
-+  if (b->fliprepair) {
-     delete flipque;
-   }
- }
-@@ -29525,7 +26781,7 @@
-   list *verlist;
-   badface *encloop;
-   face splitsub, symsplitsub;
--  point newpt, sympt, e1;
-+  point newpt, sympt;
-   enum locateresult loc, symloc;
-   bool reject;
-   long oldptnum;
-@@ -29545,17 +26801,21 @@
-     // 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 (!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.
-+      // Create a new point p.
-       makepoint(&newpt);
-+      // If f was added by checksub4badqual(), calculate its circumcenter.
-+      if (quenumber == 2) {
-+        circumsphere(encloop->forg, encloop->fdest, encloop->fapex, NULL,
-+                     encloop->cent, NULL);
-+      }
-       for (i = 0; i < 3; i++) newpt[i] = encloop->cent[i];
-       setpointtype(newpt, FREESUBVERTEX);
-       setpoint2sh(newpt, sencode(splitsub));
-@@ -29571,11 +26831,12 @@
-         // 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)).
-+        // Check for encroaching subsegments (on B(p)).
-         reject = tallencsegs(newpt, 2, ceillists);
--        // Execute point accept rule if p does not encroach upon any segment.
-         if (!reject) {
-+          // Decide whether f is allowed to be split or not?
-           reject = !acceptfacpt(newpt, subceillist, verlist);
-+          verlist->clear();
-         }
-         if (!reject) {
-           // Validate/update cavity.
-@@ -29605,6 +26866,7 @@
-                 reject = tallencsegs(sympt, 2, ceillists);
-                 if (!reject) {
-                   reject = !acceptfacpt(sympt, subceillist, verlist);
-+                  verlist->clear();
-                 }
-                 if (!reject) {
-                   reject = !trimbowatcavity(sympt,NULL,n,&sublist,&subceillist,
-@@ -29616,23 +26878,21 @@
-                   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);
-+                     tetlists,ceillists,verlist,NULL,false,true,chkbadtet);
-+                  setnewpointsize(sympt, verlist);
-+                  verlist->clear();
-                   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.
-                 }
-+                // Release CBC(symp) and BC(symp) and free the memory..
-+                releasebowatcavity(NULL, n, &sublist, &subceillist, tetlists,
-+                                   ceillists);
-               } else {
-                 // Do not insert sympt for invalid PBC data.
-                 pointdealloc(sympt);
-@@ -29653,11 +26913,10 @@
-                               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);
-+                          ceillists, verlist, NULL, true, true, chkbadtet);
-+          setnewpointsize(newpt, verlist);
-+          verlist->clear();
-           if (steinerleft > 0) steinerleft--;
-         } else {
-           // p is rejected for the one of the following reasons:
-@@ -29669,7 +26928,8 @@
-           pointdealloc(newpt);
-         } // if (!reject)
-         // Release the cavity and free the memory.
--        releasebowatcavity(NULL,n,&sublist,&subceillist,tetlists,ceillists);
-+        releasebowatcavity(NULL, n, &sublist, &subceillist, tetlists,
-+                           ceillists);
-         if (reject) {
-           // Are there queued encroached subsegments.
-           if (badsubsegs->items > 0) {
-@@ -29682,6 +26942,11 @@
-               if (!isdead(&splitsub)) {
-                 if (!shell2badface(splitsub)) {
-                   checksub4encroach(&splitsub, NULL, true);
-+                  if (!shell2badface(splitsub)) {
-+                    if (varconstraint && (areabound(splitsub) > 0.0)) {
-+                      checksub4badqual(&splitsub, true);
-+                    }
-+                  }
-                 }
-               }
-             }
-@@ -29715,6 +26980,11 @@
-       if (!isdead(&splitsub)) {
-         // The subface has been changed, re-check it.
-         checksub4encroach(&splitsub, NULL, true);
-+        if (!shell2badface(splitsub)) {
-+          if (varconstraint && (areabound(splitsub) > 0.0)) {
-+            checksub4badqual(&splitsub, true);
-+          }
-+        }
-       }
-     } // if (!isdead(&splitsub) && (sorg(splitsub) == encloop->forg) &&
-     // Remove this entry from list.
-@@ -29742,7 +27012,7 @@
-   list *verlist;
-   badface *badtet;
-   triface starttet;
--  point newpt, e1;
-+  point newpt;
-   enum locateresult loc;
-   bool reject;
-   long oldptnum;
-@@ -29756,20 +27026,14 @@
-   //   if an unlimited number of Steiner points is allowed.
-   while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
-     // Get a bad-quality tet t.
--    badtet = topbadtetra();
-+    badtet = dequeuebadtet();
-     // 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).
-+    if (!isdead(&badtet->tt) && org(badtet->tt) == badtet->forg &&
-+        dest(badtet->tt) == badtet->fdest && 
-+        apex(badtet->tt) == badtet->fapex &&
-+        oppo(badtet->tt) == badtet->foppo) {
-+      // Create the new point p.
-       makepoint(&newpt);
-       for (i = 0; i < 3; i++) newpt[i] = badtet->cent[i];
-       setpointtype(newpt, FREEVOLVERTEX);
-@@ -29787,9 +27051,8 @@
-           // 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) {
-+          // Does p allowed to be inseted?
-           reject = !acceptvolpt(newpt, ceillist, verlist);
-         }
-         if (!reject) {
-@@ -29805,12 +27068,10 @@
-           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);
-+          setnewpointsize(newpt, verlist);
-           if (steinerleft > 0) steinerleft--;
-         } else {
-           // p is rejected for one of the following reasons:
-@@ -29828,6 +27089,7 @@
-         }
-         tetlist->clear();
-         ceillist->clear();
-+        verlist->clear();
-         // Split encroached subsegments/subfaces if there are.
-         if (reject) {
-           oldptnum = points->items;
-@@ -29838,8 +27100,7 @@
-             repairencsubs(true);
-           }
-           if (points->items > oldptnum) {
--            // Some encroaching subsegments/subfaces got split. Re-queue the
--            //   tet if it is still alive.
-+            // Some encroaching subsegments/subfaces have been split.
-             starttet = badtet->tt;
-             if (!isdead(&starttet)) {
-               checktet4badqual(&starttet, true);
-@@ -29872,8 +27133,8 @@
-         pointdealloc(newpt);
-       } // if ((loc != ONVERTEX) && (loc != OUTSIDE))
-     } // if (!isdead(&badtet->tt) && org(badtet->tt) == badtet->forg &&
--    // Remove the tet from the queue.
--    dequeuebadtet();
-+    // Remove the tet from the pool.
-+    badfacedealloc(badtetrahedrons, badtet);
-   } // while ((badtetrahedrons->items > 0) && (steinerleft != 0))
- 
-   delete tetlist;
-@@ -29901,17 +27162,18 @@
-     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();
-+  if (b->refine) {
-+    // Mark segment vertices (acute or not).
-+    markacutevertices(89.0);
-   }
-+  if (!b->bgmesh) {
-+    // Calculate the node local feature sizes.
-+    calclocalfeaturesizes();
-+  }
-+  // Mark sharp subfaces (for termination).
-+  marksharpsubsegs(89.0);
-+  // Mark skinny subfaces (for reducing Steiner points).
-+  markskinnysubfaces(19.0);
- 
-   // Initialize the pool of encroached subsegments.
-   badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
-@@ -29954,11 +27216,8 @@
-     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;
-+    for (i = 0; i < 64; i++) tetquetail[i] = &tetquefront[i];
-     // 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");
-@@ -29985,36 +27244,9 @@
- //
- 
- //
--// Begin of mesh optimization routines
-+// Begin of mesh smoothing 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.                    //
-@@ -30046,15 +27278,10 @@
-         fnext(*testtet, checktet);
-         tspivot(checktet, checksh2);
-         if (checksh2.sh != dummysh) {
--          // Two subfaces share this edge.
-+          // Two subfaces share this edge. It should be a segment.
-           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;
-+            illflag = true; break;
-           }
-         }
-         enextself(*testtet);
-@@ -30068,7 +27295,7 @@
-     // Allocate space for the bad tetrahedron.
-     newbadtet = (badface *) badtetrahedrons->alloc();
-     newbadtet->tt = *testtet;
--    newbadtet->key = -1.0; // = 180 degree.
-+    newbadtet->key = 0.0;
-     for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
-     newbadtet->forg = org(*testtet);
-     newbadtet->fdest = dest(*testtet);
-@@ -30082,594 +27309,727 @@
-     }
-   }
- 
--  return illflag;
-+  return illflag;
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
-+// checktet4sliver()    Check a tet to see if it is a sliver.                //
-+//                                                                           //
-+// A sliver is a tet has no small edges, but has a nearly zero volume. When  //
-+// the mesh quality is measured by radios-edge ratio, slivers can have rela- //
-+// tively small value and are not classified as bad quality.                 //
-+//                                                                           //
-+// This routine finds whether a tet is a sliver or not by checking the bigg- //
-+// est dihedral angle of the tet. It is a sliver if the angle is larger than //
-+// 'maxdihed' (default is 170 degree, can be adjusted by '-s' option).       //
-+//                                                                           //
-+// If the flag 'chkill' is set, only check the volume of tet. It is a sliver //
-+// if it has a zero or negative volume.                                      //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+bool tetgenmesh::checktet4sliver(triface* testtet, bool chkill, bool enqflag)
-+{
-+  badface *newbadtet;
-+  point pa, pb, pc, pd;
-+  REAL N[4][3], volume, len;
-+  REAL cosd, smallcosd;
-+  bool enq;
-+  int edgeno, 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], ..., N[3]).
-+  tetallnormal(pa, pb, pc, pd, N, &volume);
-+  // 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 the largest dihedral and the edge.
-+  smallcosd = -dot(N[2], N[3]); // Edge ab.
-+  edgeno = 0;
-+  for (i = 1; i < 4; i++) {
-+    cosd = -dot(N[0], N[i]); // Edge cd, bd, bc.
-+    if (cosd < smallcosd) {
-+      smallcosd = cosd;
-+      edgeno = i;
-+    }
-+  }
-+  for (i = 2; i < 4; i++) {
-+    cosd = -dot(N[1], N[i]); // Edge ad, ac.
-+    if (cosd < smallcosd) {
-+      smallcosd = cosd;
-+      edgeno = i + 2;
-+    }
-+  }
-+  // Check if abcd is sliver.
-+  if (!chkill) {
-+    enq = ((smallcosd > cosmindihed) || ((smallcosd < cosmaxdihed)));
-+  } else {
-+    enq = (volume <= 0.0);
-+  }
-+
-+  if (enq && enqflag) {
-+    // Let t represent the edge having the biggest dihedral angle.
-+    testtet->loc = 0;
-+    testtet->ver = 0;
-+    switch (edgeno) {
-+    case 0: break; // edge ab
-+    case 1: // edge cd 
-+      enextfnextself(*testtet);
-+      enextself(*testtet);
-+      break;
-+    case 2: // edge bd
-+      enextfnextself(*testtet);
-+      enext2self(*testtet);
-+      break;
-+    case 3: // edge bc
-+      enextself(*testtet);
-+      break;
-+    case 4: // edge ad
-+      enext2fnextself(*testtet);
-+      enextself(*testtet);
-+      break;
-+    case 5: // edge ac
-+      enext2self(*testtet);
-+      break;
-+    }
-+    // Allocate space for the bad tetrahedron.
-+    newbadtet = (badface *) badtetrahedrons->alloc();
-+    newbadtet->tt = *testtet;
-+    newbadtet->key = smallcosd;
-+    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 sliver: (%d, %d, %d, %d), maxdihed %g (degree).\n",
-+             pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
-+             pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
-+             acos(smallcosd) * 180.0 / PI);
-+    }
-+  }
-+
-+  return enq;
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
-+// removetetbystripoff()    Remove a boundary tet by stripping 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).                //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+void tetgenmesh::removetetbystripoff(triface *striptet)
-+{
-+  triface abcd, badc;
-+  triface dcacasing, cdbcasing;
-+  face abc, bad;
-+  
-+  if (b->verbose > 1) {
-+    printf("    by stripping it off.\n");
-+  }
-+
-+  striptetcount++;
-+
-+  abcd = *striptet;
-+  adjustedgering(abcd, CCW);
-+  
-+  // Get the external subfaces abc, bad.
-+  fnext(abcd, badc);
-+  esymself(badc);
-+  tspivot(abcd, abc);
-+  tspivot(badc, bad);
-+#ifdef SELF_CHECK
-+  assert((abc.sh != dummysh) && (bad.sh != dummysh));
-+#endif
-+  findedge(&abc, org(abcd), dest(abcd));
-+  findedge(&bad, org(badc), dest(badc));
-+
-+  // Get the casing tets at the internal sides.
-+  enextfnext(abcd, cdbcasing);
-+  enext2fnext(abcd, dcacasing);
-+  symself(cdbcasing);
-+  symself(dcacasing);
-+#ifdef SELF_CHECK
-+  assert(cdbcasing.tet != dummytet && dcacasing.tet != dummytet);
-+#endif
-+
-+  // Do a 2-to-2 flip on abc and bad, transform abc->dca, bad->cdb.
-+  flip22sub(&abc, NULL);
-+  // Detach abcd from the two internal faces.
-+  dissolve(cdbcasing);
-+  dissolve(dcacasing);
-+  // The two internal faces become boundary faces.
-+  tsbond(cdbcasing, bad);
-+  tsbond(dcacasing, abc);
-+  // Delete abcd.
-+  tetrahedrondealloc(abcd.tet);
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// checktet4opt()    Check a tet to see if it needs to be optimized.         //
-+// removetetbyflip32()    Remove a tet by a 3-to-2 flip.                     //
- //                                                                           //
--// 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.                                                                   //
-+// 'fliptet' (abcd) is going to be removed by a 3-to-2 flip.  ab is the edge //
-+// will be flipped away, i.e., abc, bad, and abe are three internal faces.   //
- //                                                                           //
--// 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.                                       //
-+// Note: If abc and bad are subfaces(abe must not), a 2-to-2 flip is used to //
-+// transform abc, bad into dca, cdb prior to the 3-to-2 flip.                //
-+//                                                                           //
-+// If 'enq' flag is set, check the two new tets after flip to see if they're //
-+// slivers or illegal tets according to the 'chkill' flag.                   //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--bool tetgenmesh::checktet4opt(triface* testtet, bool enqflag)
-+void tetgenmesh::removetetbyflip32(triface *fliptet, bool enq, bool chkill)
- {
--  badface *newbadtet;
--  point pa, pb, pc, pd;
--  REAL N[4][3], len;
--  REAL cosd;
--  bool enq;
--  int i, j;
-+  triface abcd, badc;
-+  triface cdab, dcba;
-+  triface baccasing, abdcasing;
-+  triface dcacasing, cdbcasing;
-+  face abc, bad;
-+  REAL attrib, volume;
-+  int i;  
- 
--  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;
--    }
-+  if (b->verbose > 1) {
-+    printf("    by a 3-to-2 flip.\n");
-   }
--  // 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;
-+
-+   fliptetcount++;
-+
-+  abcd = *fliptet;
-+  adjustedgering(abcd, CCW);
-+  fnext(abcd, badc);
-+  esymself(badc);
-+  sym(abcd, baccasing);
-+  sym(badc, abdcasing);
-+#ifdef SELF_CHECK
-+  assert((baccasing.tet != dummytet) && (abdcasing.tet != dummytet));
-+  assert(oppo(baccasing) == oppo(abdcasing));
-+#endif  
-+
-+  // Get subfaces abc, bad.
-+  tspivot(abcd, abc);
-+  tspivot(badc, bad);
-+  if (abc.sh != dummysh) {
-+#ifdef SELF_CHECK
-+    // Because ab is not a subsegment.
-+    assert(bad.sh != dummysh);
-+#endif
-+    // abc and bad are internal subfaces. tets baccasing and abdcasing must
-+    //   have the same attributes (such as the region attribute if the -A
-+    //   switch is in use). But abcd may not be at the same region. After
-+    //   flip32, if abcd is not deleted, it will have the wrong attributes.
-+    //   Set abcd be the same region attributes as baccasing and abdcasing.
-+    for (i = 0; i < in->numberoftetrahedronattributes; i++) {
-+      attrib = elemattribute(baccasing.tet, i);
-+#ifdef SELF_CHECK
-+      REAL testattr = elemattribute(abdcasing.tet, i);
-+      assert(attrib == testattr);
-+#endif
-+      setelemattribute(abcd.tet, i, attrib);
-     }
--    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;
-+    if (b->varvolume) {
-+      volume = volumebound(baccasing.tet);
-+      setvolumebound(abcd.tet, volume);
-     }
-+    findedge(&abc, org(abcd), dest(abcd));
-+    findedge(&bad, org(badc), dest(badc));
-+    // Detach abc, bad from the four tets at both sides.
-+    stdissolve(abc);
-+    stdissolve(bad);
-+    sesymself(abc);
-+    sesymself(bad);
-+    stdissolve(abc);
-+    stdissolve(bad);
-+    sesymself(abc);
-+    sesymself(bad);
-+    // Detach the four tets which hold abc and bad.
-+    tsdissolve(abcd);
-+    tsdissolve(badc);
-+    tsdissolve(baccasing);
-+    tsdissolve(abdcasing);
-+    // Perform a 2-to-2 flip on abc, bad, transform abc->dca, bad->cdb.
-+    flip22sub(&abc, NULL);
-+    // Insert the flipped subfaces abc and bad into tets.
-+    enextfnext(abcd, dcba); // dcba = bcda
-+    esymself(dcba); // dcba = cbda
-+    enext2fnext(abcd, cdab); // cdab = cadb
-+    esymself(cdab); // cdab = acdb
-+    findedge(&abc, org(cdab), dest(cdab));
-+    tsbond(cdab, abc);
-+    findedge(&bad, org(dcba), dest(dcba));
-+    tsbond(dcba, bad);
-+    // Bond the other sides of cdab, dcba, they may outer space.
-+    sym(cdab, dcacasing);
-+    sym(dcba, cdbcasing);
-+    sesymself(abc);
-+    sesymself(bad);
-+    tsbond(dcacasing, abc);
-+    tsbond(cdbcasing, bad);          
-   }
-+  // Remove abcd by a 3-to-2 flip.
-+  flip32(&abcd, NULL);
-+  // After flip abc is the internal face.
- 
--  return enq;
-+  if (enq) {
-+    // Get the adjtet of abcd (in badc).
-+    sym(abcd, badc);
-+    if (chkill) {
-+      // Test the two new tets to see if they are illegal.
-+      checktet4ill(&abcd, true);
-+      checktet4ill(&badc, true);
-+    } else {
-+      // Test the two new tets to see if they are sliver.
-+      checktet4sliver(&abcd, false, true);
-+      checktet4sliver(&badc, false, true);
-+    }
-+  }
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// removeedge()    Remove an edge                                            //
-+// removetetbyrecon()    Remove a tet by local reconnection.                 //
- //                                                                           //
--// '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.                                                       //
-+// 'remtet' (abcd) is wanted to be removed from the mesh. ab is the primary  //
-+// edge (which is diagonal if a, b, c, and d form a convex quadrilateral).   //
- //                                                                           //
--// 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'.           //
-+// abcd is removable if it is not a segment, and either it can be stripped   //
-+// off or it can be flipped away.                                            //
- //                                                                           //
--// 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'.                                      //
-+// The return value indicates abcd is remveable or not. Note, although abcd  //
-+// is removeable but it may not be removed when 'chkill' is FALSE.           //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--bool tetgenmesh::removeedge(badface* remedge, bool optflag)
-+bool tetgenmesh::removetetbyrecon(badface* remtet, bool chkill)
- {
-   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) {
-+  face abseg;
-+  point pa, pb, pc, pd, pe;
-+  REAL ori1, ori2;
-+  REAL cosmaxd1, cosmaxd2;
-+  bool remflag;
-+  int i;
-+
-+  remflag = false;
-+  // tet 'abcd' is indicated to remove.
-+  abcd = remtet->tt;
-+  // Check if abcd is removeable (at edge ab and cd).
-+  for (i = 0; i < 2; i++) {
-+    // If ab a segment, it is unremoveable.
-+    tsspivot(&abcd, &abseg);
-+    if (abseg.sh == dummysh) {
-+      adjustedgering(abcd, CCW);
-+      // Get the tet configuration at edge ab (or cd).
-       fnext(abcd, badc);
-+      esymself(badc);
-+      sym(abcd, baccasing);
-       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");
-+      // Can 'abcd' be stripped off?
-+      if ((baccasing.tet == dummytet) && (abdcasing.tet == dummytet)) {
-+        removetetbystripoff(&abcd);
-+        remflag = true;
-+        break; // abcd has been removed.
-+      } else if (oppo(baccasing) == oppo(abdcasing)) {
-+        // Can 'abcd' be flipped away?
-+        pa = org(abcd);
-+        pb = dest(abcd);
-+        pc = apex(abcd);
-+        pd = oppo(abcd);
-+        pe = oppo(baccasing);
-+        // Check if face cde is crossed by ab.
-+        ori1 = orient3d(pc, pd, pe, pa);
-+        ori2 = orient3d(pc, pd, pe, pb);
-+        if (ori1 * ori2 < 0.0) {
-+          // ab can be flipped away.
-+          if (!chkill) {
-+            // Do flip if the maximal dihedrals of the new tets are reduced?
-+            tetalldihedral(pd, pc, pe, pa, NULL, &cosmaxd1, NULL);
-+            tetalldihedral(pc, pd, pe, pb, NULL, &cosmaxd2, NULL);
-+            if ((remtet->key <= cosmaxd1) && (remtet->key <= cosmaxd2)) {
-+              removetetbyflip32(&abcd, true, chkill);
-+              remflag = true;
-+              break; // abcd has been removed.
-+            }
-+          } else {
-+            removetetbyflip32(&abcd, true, chkill);
-+            remflag = true;
-+            break; // abcd has been removed.
-           }
--          optcount[0]++;
--          return true;
-         }
-       }
--    }
--    // Check if the oppsite edge cd is on the hull.
--    enext2fnextself(abcd);
-+    } // if (abseg.sh == dummysh)
-+    // 'abcd' is not removed (although it may be removeable).
-+    if (i == 1) break;  // Stop if both ab and cd have been checked.
-+    // Go to edge cd, re-use handle abcd.
-+    enextfnextself(abcd);
-+    esymself(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));
-+  } // for (i = 0; i < 2; i++)
- 
--  remflag = false;
--  key = remedge->key;
-+  return remflag;
-+}
- 
--  if (subflag && optflag) {
--    abcd = remedge->tt;
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
-+// removetetbysplit()    Remove a tet by inserting a point in it.            //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+bool tetgenmesh::removetetbysplit(badface* remtet)
-+{
-+  list **tetlists, **ceillists;
-+  list **sublists, **subceillists;
-+  list *tetlist, *ceillist, *verlist;
-+  triface abcd, starttet;
-+  face abseg, abcsh;
-+  point newpt, refpt;
-+  REAL maxcosd;
-+  int nmax, n;
-+  int i, j;
-+
-+  // tet 'abcd' is indicated to remove.
-+  abcd = remtet->tt;
-+  abseg.sh = dummysh;
-+  abcsh.sh = dummysh;
-+
-+  // Check if ab or cd is a segment.
-+  tsspivot(&abcd, &abseg);
-+  if (abseg.sh == dummysh) {
-     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);
-+    enextfnextself(abcd);
-+    enextself(abcd);
-+    tsspivot(&abcd, &abseg);
-+  }
-+  if (abseg.sh == dummysh) {
-+    abcd = remtet->tt;
-+    adjustedgering(abcd, CCW);
-+    // Check if abc is a subface.
-+    tspivot(abcd, abcsh);
-+    if (abcsh.sh == dummysh) {
-+      // Check if bad is a subface.
-+      fnextself(abcd);
-+      tspivot(abcd, abcsh);
-+      if (abcsh.sh == dummysh) {
-+        // Check if cda is a subface
-+        abcd = remtet->tt;
-+        adjustedgering(abcd, CCW);
-+        enext2fnextself(abcd);
-+        enext2self(abcd);
-+        esymself(abcd);
-+        tspivot(abcd, abcsh);
-+        if (abcsh.sh == dummysh) {
-+          // Check if cdb is a subface
-+          fnextself(abcd);
-+          tspivot(abcd, abcsh);
-         }
--        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);
-+  if (abseg.sh != dummysh) {
-+    if (checkpbcs) {
-+      // Do not split ab if it belongs to any pbcgroup.
-+      i = shellmark(abseg) - 1;
-+      if (idx2segpglist[i + 1] > idx2segpglist[i]) {
-+        return false; // There are pbc facets at ab.
-+      }
-+    }
-+    // Find if segment ab is encroached by an existing point.
-+    refpt = (point) NULL;
-+    checkseg4encroach(&abseg, NULL, &refpt, false);
-+    // Find a point in segment ab.
-+    makepoint(&newpt);
-+    getsplitpoint(sorg(abseg), sdest(abseg), refpt, newpt);
-+    setpointtype(newpt, FREESEGVERTEX);
-+    setpoint2sh(newpt, sencode(abseg));
-+    maxcosd = remtet->key;
-+    if (refpt != (point) NULL) {
-+      // ab is encroached. Force p to be inserted.
-+      maxcosd = -1.0; // 180 degree
-+    }
-+    n = 0;
-+    nmax = 128;
-+    tetlists = new list*[nmax];
-+    ceillists = new list*[nmax];
-+    sublists = new list*[nmax];
-+    subceillists = new list*[nmax];
-+    verlist = new list(sizeof(point *), NULL, 256);
-+    // Form BC(p).
-+    formbowatcavity(newpt, &abseg, NULL, &n, &nmax, sublists, subceillists,
-+                    tetlists, ceillists);
-+    // Can local maximal dihedral be reduced by inserting p?
-+    if (trimbowatcavity(newpt, &abseg, n, sublists, subceillists, tetlists,
-+                        ceillists, maxcosd)) {
-+      // Inserting p. Ignore any new enc-seg, enc-sub, and bad tets.
-+      bowatinsertsite(newpt, &abseg, n, sublists, subceillists, tetlists,
-+                      ceillists, verlist, NULL, false, false, false);
-+      setnewpointsize(newpt, verlist);
-+      // Check if there are new slivers at p.
-+      for (j = 0; j < n; j++) {
-+        tetlist = ceillists[j];
-+        for (i = 0; i < tetlist->len(); i++) {
-+          starttet = * (triface *)(* tetlist)[i];
-+          checktet4sliver(&starttet, false, true);
-         }
-       }
--      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);
-+      refpt != (point) NULL ? smoothcdtsegpt++ : smoothsegpt++;
-+    } else {
-+      // The local quality will not be improved. Do not insert p.
-+      pointdealloc(newpt);
-+      newpt = (point) NULL;
-+      refpt != (point) NULL ? unsmoothcdtsegpt++ : unsmoothsegpt++;
-+    }
-+    // Free the memory allocated in formbowatcavity().
-+    releasebowatcavity(&abseg, n, sublists, subceillists, tetlists, ceillists);
-+    delete [] tetlists;
-+    delete [] ceillists;
-+    delete [] sublists;
-+    delete [] subceillists;
-+    delete verlist;
-+  } else if (abcsh.sh != dummysh) {
-+    if (checkpbcs) {
-+      // Do not split abc if it belongs to a pbcgroup.
-+      if (shellpbcgroup(abcsh) >= 0) {
-+        return false; // It is on a pbc facet.
-+      }
-+    }
-+    // Insert the midpoint of ab which is on a facet.
-+    makepoint(&newpt);
-+    getsplitpoint(org(abcd), dest(abcd), NULL, newpt);
-+    setpointtype(newpt, FREESUBVERTEX);
-+    setpoint2sh(newpt, sencode(abcsh));
-+    n = 2;
-+    tetlists = new list*[2];
-+    ceillists = new list*[2];
-+    sublists = new list*[2];
-+    subceillists = new list*[2];
-+    verlist = new list(sizeof(point *), NULL, 256);
-+    // Form BC(p).
-+    formbowatcavity(newpt, NULL, &abcsh, &n, NULL, sublists, subceillists,
-+                    tetlists, ceillists);
-+    // Can local maximal dihedral be reduced by inserting p?
-+    if (trimbowatcavity(newpt, NULL, n, sublists, subceillists, tetlists,
-+                        ceillists, remtet->key)) {
-+      // Inserting p. Ignore any new enc-seg, enc-sub, and bad tets.
-+      bowatinsertsite(newpt, NULL, n, sublists, subceillists, tetlists,
-+                      ceillists, verlist, NULL, false, false, false);
-+      setnewpointsize(newpt, verlist);
-+      // Check if there are new slivers at p.
-+      for (j = 0; j < n; j++) {
-+        tetlist = ceillists[j];
-+        for (i = 0; i < tetlist->len(); i++) {
-+          starttet = * (triface *)(* tetlist)[i];
-+          checktet4sliver(&starttet, false, true);
-         }
--        printf("\n");
-       }
-+      smoothsubpt++;
-+    } else {
-+      // The local quality will not be improved. Do not insert p.
-+      pointdealloc(newpt);
-+      newpt = (point) NULL;
-+      unsmoothsubpt++;
-     }
--  }
--
--  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);
-+    // Free the memory allocated in formbowatcavity().
-+    releasebowatcavity(NULL, n, sublists, subceillists, tetlists, ceillists);
-+    delete [] tetlists;
-+    delete [] ceillists;
-+    delete [] sublists;
-+    delete [] subceillists;
-+    delete verlist;
-+  } else {
-+    // Insert the midpoint of the edge having largest dihedral angle.
-+    abcd = remtet->tt;
-+    makepoint(&newpt);
-+    getsplitpoint(org(abcd), dest(abcd), NULL, newpt);
-+    setpointtype(newpt, FREEVOLVERTEX);
-+    // Form BC(p).
-+    tetlist = new list(sizeof(triface), NULL, 1024);
-+    ceillist = new list(sizeof(triface), NULL, 1024);
-+    verlist = new list(sizeof(point *), NULL, 256);
-+    starttet = abcd;
-+    infect(starttet);
-+    tetlist->append(&starttet);
-+    formbowatcavityquad(newpt, tetlist, ceillist);
-+    // Can local maximal dihedral be reduced by inserting p?
-+    if (trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist,
-+                        remtet->key)) {
-+      // Inserting p. Ignore any new enc-seg, enc-sub, and bad tets.
-+      bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, verlist,
-+                      NULL, false, false, false);
-+      setnewpointsize(newpt, verlist);
-+      // Check if there are new slivers at p.
-+      for (i = 0; i < ceillist->len(); i++) {
-+        starttet = * (triface *)(* ceillist)[i];
-+        checktet4sliver(&starttet, false, true);
-       }
-+      smoothvolpt++;
-+    } else {
-+      // The local quality will not be improved. Do not insert p.
-+      pointdealloc(newpt);
-+      newpt = (point) NULL;
-+      // Uninfect tets of BC(p).
-+      for (i = 0; i < tetlist->len(); i++) {
-+        starttet = * (triface *)(* tetlist)[i];
-+        uninfect(starttet);
-+      }
-+      unsmoothvolpt++;
-     }
-+    delete tetlist;
-+    delete ceillist;
-+    delete verlist;
-   }
- 
--  return remflag;
-+  return newpt != (point) NULL;
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// 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).                         //
-+// tallslivers()    Queue all the slivers in the mesh.                       //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--bool tetgenmesh::smoothsliver(badface* remedge, list *starlist)
-+void tetgenmesh::tallslivers(bool chkill)
- {
--  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();
--      }
--    }
--  } 
-+  triface tetloop;
- 
--  /* 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();
--        }
-+  tetrahedrons->traversalinit();
-+  tetloop.tet = tetrahedrontraverse();
-+  while (tetloop.tet != (tetrahedron *) NULL) {
-+    if (chkill) {
-+      if (!checktet4sliver(&tetloop, true, true)) {
-+        checktet4ill(&tetloop, true);
-       }
-+    } else {
-+      checktet4sliver(&tetloop, false, true);
-     }
-+    tetloop.tet = tetrahedrontraverse();
-   }
--  */
--
--  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).                         //
-+// repairmesh()    Remove illegal tets in the mesh.                          //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--bool tetgenmesh::splitsliver(badface *remedge, list *tetlist, list *ceillist)
-+void tetgenmesh::repairmesh()
- {
--  triface starttet;
--  face checkseg;
--  point newpt, pt[4];
--  bool remflag;
--  int i;
-+  badface *remtet, *lastunrementry;
- 
--  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;
--    }
-+  if (!b->quiet) {
-+    printf("Repairing mesh.\n");
-   }
- 
--  // 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);
-+  // Initialize the pool of bad tets
-+  badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
-+  lastunrementry = (badface *) NULL;
-+  striptetcount = fliptetcount = unimprovecount = 0l;
- 
--  // 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);
-+  // Looking for illegal tets.
-+  tallslivers(true);
-+  
-+  // 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).\n", pointmark(remtet->forg),
-+                 pointmark(remtet->fdest), pointmark(remtet->fapex),
-+                 pointmark(remtet->foppo));
-+        }
-+        if (!removetetbyrecon(remtet, true)) {
-+          // An unremoveable tet. Check if it forms a loop.
-+          if (lastunrementry != (badface *) NULL) {
-+            if (remtet == lastunrementry) break;
-+          } else {
-+            // Remember this tet as a breakpoint.
-+            lastunrementry = remtet;
-+          }
-+        } else {
-+          // Clear the breakpoint.
-+          lastunrementry = (badface *) NULL;
-+          // Remove the entry from the queue.
-+          badfacedealloc(badtetrahedrons, remtet);
-+        }
-+      } else {
-+        // Remove the entry from the queue.
-+        badfacedealloc(badtetrahedrons, remtet);
-       }
--      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);
-+      remtet = badfacetraverse(badtetrahedrons);
-     }
-+    // Stop if the above loop was out by force.
-+    if (remtet != (badface *) NULL) break;
-   }
--  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);
-+  if (b->verbose) {
-+    if (striptetcount > 0l) {
-+      printf("  %ld tets are stripped off.\n", striptetcount);
-+    }
-+    if (fliptetcount > 0l) {
-+      printf("  %ld tets are flipped away.\n", fliptetcount);
-+    }
-+    if (badtetrahedrons->items > 0l) {
-+      printf("  %ld tets are unremoveable.\n", badtetrahedrons->items);
-     }
--    tetloop.tet = tetrahedrontraverse();
-   }
-+
-+  delete badtetrahedrons;
-+  badtetrahedrons = (memorypool *) NULL;
- }
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// 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.  //
-+// smoothmesh()    Smooth the mesh.                                          //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--void tetgenmesh::optimizemesh(bool optflag)
-+void tetgenmesh::smoothmesh()
- {
--  list *splittetlist, *tetlist, *ceillist;
--  badface *remtet, *lastentry;
--  REAL maxdihed, objdihed, curdihed;
--  long oldnum;
--  int iter, i;
-+  badface *remtet, *lastunrementry;
- 
-   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);
-+    printf("Smoothing mesh.\n");
-   }
--#endif
- 
--  // Initialize the pool of bad tets.
-+  // 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.
-+  cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
-+  cosmindihed = 1.0;
-+  striptetcount = fliptetcount = unimprovecount = 0l;
-+  smoothcdtsegpt = smoothsegpt = smoothsubpt = smoothvolpt = 0l;
-+  unsmoothcdtsegpt = unsmoothsegpt = unsmoothsubpt = unsmoothvolpt = 0l;
- 
--  // Perform edge flip to improve quality.
--  lastentry = (badface *) NULL;
-+  // Looking for bad tets.
-+  tallslivers(false);
-+  
-+  lastunrementry = (badface *) NULL;
-   // Loop until pool 'badtetrahedrons' is empty.
-   while (badtetrahedrons->items > 0) {
-     badtetrahedrons->traversalinit();
-@@ -30682,22 +28042,21 @@
-           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);
-+          printf("    Repair tet (%d, %d, %d, %d).\n", pointmark(remtet->forg),
-+                 pointmark(remtet->fdest), pointmark(remtet->fapex),
-+                 pointmark(remtet->foppo));
-         }
--        if (!removeedge(remtet, optflag)) {
-+        if (!removetetbyrecon(remtet, false)) {
-           // An unremoveable tet. Check if it forms a loop.
--          if (lastentry != (badface *) NULL) {
--            if (remtet == lastentry) break;
-+          if (lastunrementry != (badface *) NULL) {
-+            if (remtet == lastunrementry) break;
-           } else {
-             // Remember this tet as a breakpoint.
--            lastentry = remtet;
-+            lastunrementry = remtet;
-           }
-         } else {
-           // Clear the breakpoint.
--          lastentry = (badface *) NULL;
-+          lastunrementry = (badface *) NULL;
-           // Remove the entry from the queue.
-           badfacedealloc(badtetrahedrons, remtet);
-         }
-@@ -30712,97 +28071,71 @@
-   }
- 
-   if (b->verbose) {
--    if (optcount[0] > 0l) {
--      printf("  %ld tets are peeled off.\n", optcount[0]);
-+    if (striptetcount > 0l) {
-+      printf("  %ld tets are stripped off.\n", striptetcount);
-     }
--    if (optcount[1] > 0l) {
--      printf("  %ld faces are flipped.\n", optcount[1]);
-+    if (fliptetcount > 0l) {
-+      printf("  %ld tets are flipped away.\n", fliptetcount);
-     }
--    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);
--              }
-+  lastunrementry = (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).\n", pointmark(remtet->forg),
-+                 pointmark(remtet->fdest), pointmark(remtet->fapex),
-+                 pointmark(remtet->foppo));
-+        }
-+        if (!removetetbyrecon(remtet, false)) {
-+          // An unremoveable tet. Find if a segment which can be split.
-+          if (!removetetbysplit(remtet)) {
-+            // An unremoveable tet. Check if it forms a loop.
-+            if (lastunrementry != (badface *) NULL) {
-+              if (remtet == lastunrementry) break;
-+            } else {
-+              // Remember this tet as a breakpoint.
-+              lastunrementry = remtet;
-             }
-+          } else {
-+            // Clear the breakpoint.
-+            lastunrementry = (badface *) NULL;
-+            // Remove the entry from the queue.
-+            badfacedealloc(badtetrahedrons, remtet);
-           }
-+        } else {
-+          // Clear the breakpoint.
-+          lastunrementry = (badface *) NULL;
-+          // Remove the entry from the queue.
-+          badfacedealloc(badtetrahedrons, remtet);
-         }
-+      } else {
-+        // Remove the entry from the queue.
-+        badfacedealloc(badtetrahedrons, remtet);
-       }
--      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);
--      // }
-+      remtet = badfacetraverse(badtetrahedrons);
-+    }
-+    // Stop if the above loop was out by force.
-+    if (remtet != (badface *) NULL) break;
-+  }
-+
-+  if (b->verbose) {
-+    if ((smoothcdtsegpt + smoothsegpt + smoothsubpt + smoothvolpt) > 0l) {
-+      printf("  %ld smooth points.\n", 
-+             smoothcdtsegpt + smoothsegpt + smoothsubpt + smoothvolpt);
-+    }
-+    if (badtetrahedrons->items > 0l) {
-+      printf("  %ld remaining tets.\n", badtetrahedrons->items);
-     }
--    delete tetlist;
--    delete ceillist;
--    delete splittetlist;
-   }
- 
-   delete badtetrahedrons;
-@@ -30810,7 +28143,7 @@
- }
- 
- //
--// End of mesh optimization routines
-+// End of mesh smoothing routines
- //
- 
- //
-@@ -30834,13 +28167,11 @@
-   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.
-@@ -30851,10 +28182,6 @@
-     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;
-@@ -30870,6 +28197,7 @@
-     }
-   }
-   // 'longest' is the largest possible edge length formed by input vertices.
-+  //   It is used as the measure to distinguish two identical points.
-   x = xmax - xmin;
-   y = ymax - ymin;
-   z = zmax - zmin;
-@@ -30878,7 +28206,6 @@
-     printf("Error:  The point set is trivial.\n");
-     terminatetetgen(1);
-   }
--  // Two identical points are distinguished by 'lengthlimit'.
-   lengthlimit = longest * b->epsilon * 1e+2;
- }
- 
-@@ -30969,6 +28296,15 @@
-   int hitbdry, ptmark;
-   int i, j;
- 
-+  // The 'edgeindex' (from 0 to 5) is list as follows:
-+  //   0 - (v0, v1), 1 - (v1, v2), 2 - (v2, v0)
-+  //   3 - (v3, v0), 4 - (v3, v1), 5 - (v3, v2)
-+  // Define an edgeindex map: (loc, ver)->edgeindex.
-+  int edgeindexmap[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}};
-+
-   if (!b->quiet) {
-     printf("Adding vertices for second-order tetrahedra.\n");
-   }
-@@ -31011,21 +28347,44 @@
-   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];
-+        worktet = tetloop;
-+        worktet.loc = 0; worktet.ver = 0;
-+        // Get the correct edge in 'worktet'.
-+        switch(i) {
-+        case 0: // (v0, v1) 
-+          break;
-+        case 1: // (v1, v2)
-+          enextself(worktet);
-+          break;
-+        case 2: // (v2, v0)
-+          enext2self(worktet);
-+          break;
-+        case 3: // (v3, v0)
-+          fnextself(worktet);
-+          enext2self(worktet);
-+          break;
-+        case 4: // (v3, v1)
-+          enextself(worktet);
-+          fnextself(worktet);
-+          enext2self(worktet);
-+          break;
-+        case 5: // (v3, v2)
-+          enext2self(worktet);
-+          fnextself(worktet);
-+          enext2self(worktet);
-+        }
-         // 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]);
--        }
-+        // 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.
-@@ -31040,7 +28399,7 @@
-             // 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];
-+            j = edgeindexmap[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) {
-@@ -31098,7 +28457,8 @@
-     }
-   }
- 
--  nextras = in->numberofpointattributes;
-+  // nextras = in->numberofpointattributes;
-+  nextras = 0; // After version 1.4.0, don't output point attributes.
-   bmark = !b->nobound && in->pointmarkerlist;
- 
-   // Avoid compile warnings.
-@@ -31282,11 +28642,8 @@
- {
-   FILE *outfile;
-   char outmtrfilename[FILENAMESIZE];
--  list *tetlist, *ptlist;
--  triface tetloop;
--  point ptloop, neipt;
--  REAL lave, len; // lmin, lmax, 
--  int mtrindex;
-+  point pointloop;
-+  int nextras, attribindex;
-   int i;  
- 
-   if (out == (tetgenio *) NULL) {
-@@ -31304,103 +28661,53 @@
- 
-   // Avoid compile warnings.
-   outfile = (FILE *) NULL;
--  mtrindex = 0;
-+  attribindex = 0;
- 
-+  nextras = 0;
-+  if (b->bgmesh) {
-+    nextras = bgm->in->numberofpointattributes;
-+  } else if (b->quality) {
-+    nextras = 1;
-+  }
-   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);
-+    // Number of points, number of point attributes,
-+    fprintf(outfile, "%ld  %d\n", points->items, nextras);
-+  } else {
-+    // 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);
-+      }
-     }
--    out->numberofpointmtrs = 1; // (sizeoftensor + 3);
--    mtrindex = 0;
-+    out->numberofpointattributes = nextras;
-+    attribindex = 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();
--    }
-+  pointloop = pointtraverse();
-+  while (pointloop != (point) NULL) {
-     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");
-+      for (i = 0; i < nextras; i++) {
-+        // Write an attribute.
-+        fprintf(outfile, "%-22.17e ", pointloop[3 + i]);
-       }
-       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;
-+      for (i = 0; i < nextras; i++) {
-+        // Output an attribute.
-+        out->pointattributelist[attribindex++] = pointloop[3 + i];
-       }
-     }
--    tetlist->clear();
--    ptlist->clear();
--    ptloop = pointtraverse();
-+    pointloop = pointtraverse();
-   }
- 
--  delete tetlist;
--  delete ptlist;
--
-   if (out == (tetgenio *) NULL) {
-     fprintf(outfile, "# Generated by %s\n", b->commandline);
-     fclose(outfile);
-@@ -31567,7 +28874,6 @@
-   char facefilename[FILENAMESIZE];
-   int *elist;
-   int *emlist;
--  int neigh1, neigh2;
-   int index;
-   triface tface, tsymface;
-   face checkmark;
-@@ -31621,14 +28927,6 @@
-         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;
-@@ -31675,15 +28973,6 @@
-             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,
-@@ -31693,9 +28982,6 @@
-             // 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.
-@@ -31705,10 +28991,6 @@
-           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++;
-       }
-@@ -31843,7 +29125,7 @@
-   char facefilename[FILENAMESIZE];
-   int *elist;
-   int *emlist;
--  int index, index1, index2;
-+  int index;
-   triface abuttingtet;
-   face faceloop;
-   point torg, tdest, tapex;
-@@ -31869,8 +29151,7 @@
-   outfile = (FILE *) NULL;
-   elist = (int *) NULL;
-   emlist = (int *) NULL;
--  index = index1 = index2 = 0;
--  faceid = marker = 0;
-+  index = marker = 0;
-   neigh1 = neigh2 = 0;
- 
-   bmark = !b->nobound && in->facetmarkerlist;
-@@ -31909,6 +29190,7 @@
-     out->numberoftrifaces = subfaces->items;
-     elist = out->trifacelist;
-     emlist = out->trifacemarkerlist;
-+    index = 0;
-   }
- 
-   // Determine the first index (0 or 1).
-@@ -31963,176 +29245,28 @@
-       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.
--	  }
--        }
-+      if (bmark) {
-+        fprintf(outfile, "    %d", marker);
-       }
--      // 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++;
-+      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[facenumber - in->firstnumber] = marker;
-+      }
-+      if (b->neighout > 1) {
-+        out->adjtetlist[(facenumber - in->firstnumber) * 2]     = neigh1;
-+        out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
-       }
-     }
--    tetloop.tet = tetrahedrontraverse();
-+    facenumber++;
-+    faceloop.sh = shellfacetraverse(subfaces);
-   }
- 
-   if (out == (tetgenio *) NULL) {
-@@ -32167,7 +29301,7 @@
-     if (out == (tetgenio *) NULL) {
-       printf("Writing %s.\n", edgefilename);
-     } else {
--      printf("Writing edges.\n");
-+      printf("Writing faces.\n");
-     }
-   }
- 
-@@ -32193,6 +29327,7 @@
-     }
-     out->numberofedges = subsegs->items;
-     elist = out->edgelist;
-+    index = 0;
-   }
- 
-   // Determine the first index (0 or 1).
-@@ -32205,556 +29340,113 @@
-   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);
-+  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;
-     }
--  }
--
--  // 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();
-+    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;
- 
--  // Output Voronoi cells to .v.cell file.
-   if (out == (tetgenio *) NULL) {
--    strcpy(outfilename, b->outfilename);
--    strcat(outfilename, ".v.cell");
-+    strcpy(neighborfilename, b->outfilename);
-+    strcat(neighborfilename, ".neigh");
-   }
--  
-+
-   if (!b->quiet) {
-     if (out == (tetgenio *) NULL) {
--      printf("Writing %s.\n", outfilename);
-+      printf("Writing %s.\n", neighborfilename);
-     } else {
--      printf("Writing Voronoi cells.\n");
-+      printf("Writing neighbors.\n");
-     }
-   }
- 
-+  // Avoid compile warnings.
-+  outfile = (FILE *) NULL;
-+  nlist = (int *) NULL;
-+  index = 0;
-+
-   if (out == (tetgenio *) NULL) {
--    outfile = fopen(outfilename, "w");
-+    outfile = fopen(neighborfilename, "w");
-     if (outfile == (FILE *) NULL) {
--      printf("File I/O Error:  Cannot create file %s.\n", outfilename);
-+      printf("File I/O Error:  Cannot create file %s.\n", neighborfilename);
-       terminatetetgen(1);
-     }
--    // Number of Voronoi cells.
--    fprintf(outfile, "%ld\n", points->items);
-+    // Number of tetrahedra, four faces per tetrahedron.
-+    fprintf(outfile, "%ld  %d\n", tetrahedrons->items, 4);
-   } else {
--    out->numberofvcells = points->items;
--    out->vcelllist = new int*[out->numberofvcells];
--    if (out->vcelllist == (int **) NULL) {
-+    // 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;
-+    index = 0;
-   }
- 
--  // 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++;
-+  // 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;
-     }
--    tetlist->clear();
--    ptlist->clear();
--    ptloop = pointtraverse();
-+    tetloop.tet = tetrahedrontraverse();
-+    elementnumber++;
-   }
--  delete tetlist;
--  delete ptlist;
--  delete [] tetfaceindexarray;
--  delete [] tetedgeindexarray;
- 
-   if (out == (tetgenio *) NULL) {
-     fprintf(outfile, "# Generated by %s\n", b->commandline);
-@@ -33087,7 +29779,7 @@
-   tetrahedron* tetptr;
-   triface tface, tsymface;
-   face segloop, checkmark;
--  point ptloop, p1, p2, p3, p4;
-+  point pointloop, p1, p2, p3, p4;
-   long faces;
-   int pointnumber;
-   int i;
-@@ -33121,19 +29813,20 @@
-   fprintf(outfile, "%ld\n", points->items);
- 
-   points->traversalinit();
--  ptloop = pointtraverse();
-+  pointloop = pointtraverse();
-   pointnumber = 1;                        // Medit need start number form 1.
--  while (ptloop != (point) NULL) {
-+  while (pointloop != (point) NULL) {
-     // Point coordinates.
--    fprintf(outfile, "%.17g  %.17g  %.17g", ptloop[0], ptloop[1], ptloop[2]);
-+    fprintf(outfile, "%.17g  %.17g  %.17g",
-+            pointloop[0], pointloop[1], pointloop[2]);
-     if (in->numberofpointattributes > 0) {
-       // Write an attribute, ignore others if more than one.
--      fprintf(outfile, "  %.17g\n", ptloop[3]);
-+      fprintf(outfile, "  %.17g\n", pointloop[3]);
-     } else {
-       fprintf(outfile, "    0\n");
-     }
--    setpointmark(ptloop, pointnumber);
--    ptloop = pointtraverse();
-+    setpointmark(pointloop, pointnumber);
-+    pointloop = pointtraverse();
-     pointnumber++;
-   }
- 
-@@ -33234,7 +29927,7 @@
-   tetrahedron* tetptr;
-   triface tface, tsymface;
-   face sface;
--  point ptloop, p1, p2, p3, p4;
-+  point pointloop, p1, p2, p3, p4;
-   int pointnumber;
-   int elementnumber;
- 
-@@ -33260,19 +29953,19 @@
-   fprintf(outfile, "coordinates\n");
- 
-   points->traversalinit();
--  ptloop = pointtraverse();
-+  pointloop = pointtraverse();
-   pointnumber = 1;                        // Gid need start number form 1.
--  while (ptloop != (point) NULL) {
-+  while (pointloop != (point) NULL) {
-     // Point coordinates.
-     fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
--            ptloop[0], ptloop[1], ptloop[2]);
-+            pointloop[0], pointloop[1], pointloop[2]);
-     if (in->numberofpointattributes > 0) {
-       // Write an attribute, ignore others if more than one.
--      fprintf(outfile, "  %.17g", ptloop[3]);
-+      fprintf(outfile, "  %.17g", pointloop[3]);
-     }
-     fprintf(outfile, "\n");
--    setpointmark(ptloop, pointnumber);
--    ptloop = pointtraverse();
-+    setpointmark(pointloop, pointnumber);
-+    pointloop = pointtraverse();
-     pointnumber++;
-   }
- 
-@@ -33322,19 +30015,19 @@
-   fprintf(outfile, "coordinates\n");
- 
-   points->traversalinit();
--  ptloop = pointtraverse();
-+  pointloop = pointtraverse();
-   pointnumber = 1;                        // Gid need start number form 1.
--  while (ptloop != (point) NULL) {
-+  while (pointloop != (point) NULL) {
-     // Point coordinates.
-     fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
--            ptloop[0], ptloop[1], ptloop[2]);
-+            pointloop[0], pointloop[1], pointloop[2]);
-     if (in->numberofpointattributes > 0) {
-       // Write an attribute, ignore others if more than one.
--      fprintf(outfile, "  %.17g", ptloop[3]);
-+      fprintf(outfile, "  %.17g", pointloop[3]);
-     }
-     fprintf(outfile, "\n");
--    setpointmark(ptloop, pointnumber);
--    ptloop = pointtraverse();
-+    setpointmark(pointloop, pointnumber);
-+    pointloop = pointtraverse();
-     pointnumber++;
-   }
- 
-@@ -33388,7 +30081,7 @@
-   FILE *outfile;
-   char offfilename[FILENAMESIZE];
-   triface tface, tsymface;
--  point ptloop, p1, p2, p3;
-+  point pointloop, p1, p2, p3;
-   long faces;
-   int shift;
- 
-@@ -33418,10 +30111,11 @@
- 
-   // 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();
-+  pointloop = pointtraverse();
-+  while (pointloop != (point) NULL) {
-+    fprintf(outfile, " %.17g  %.17g  %.17g\n", pointloop[0], pointloop[1],
-+            pointloop[2]);
-+    pointloop = pointtraverse();
-   }
- 
-   // OFF always use zero as the first index.
-@@ -33833,10 +30527,10 @@
-             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 UNFLIPABLE: printf("\"UNFLIPABLE\""); break;
-             case FORBIDDENFACE:printf("\"FORBIDDENFACE\""); break;
-             case FORBIDDENEDGE:printf("\"FORBIDDENEDGE\""); break;
-+            case NONCONVEX:printf("\"NONCONVEX\""); break;
-             }
-             printf("\n");
-           }
-@@ -33860,6 +30554,69 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
-+// checkdegeneracy()    Check if the point set contains degeneracies.        //
-+//                                                                           //
-+// 'eps' is a relative error tolerance for testing approximatly degeneracies.//
-+// Set it to zero if only exact test is desired.                             //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+void tetgenmesh::checkdegeneracy(REAL eps)
-+{
-+  triface tetraloop;
-+  triface oppotet;
-+  point tetorg, tetdest, tetapex, tetoppo;
-+  point oppooppo;
-+  REAL sign;
-+  int horrors;
-+
-+  if (!b->quiet) {
-+    printf("  Checking degeneracies in the point set...\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 test if there is an adjoining tetrahedron whose pointer is
-+      //   larger (to ensure that each pair isn't tested twice).
-+      if ((oppotet.tet != dummytet) && (tetoppo != (point) NULL) &&
-+          (oppooppo != (point) NULL) && (tetraloop.tet < oppotet.tet)) {
-+        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) {
-+          printf("  !! Degenerate set (%d, %d, %d, %d, %d).\n",
-+                 pointmark(tetorg), pointmark(tetdest), pointmark(tetapex),
-+                 pointmark(tetoppo), pointmark(oppooppo));
-+          horrors++;
-+        }
-+      }
-+    }
-+    tetraloop.tet = tetrahedrontraverse();
-+  }
-+
-+  if (horrors == 0) {
-+    if (!b->quiet) {
-+      printf("  The point set is non-degenerate.\n");
-+    }
-+  } else {
-+    printf("  !! !! !! !! %d obscenities viewed with horror.\n", horrors);
-+  }
-+}
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
- // checkconforming()    Ensure that the mesh is conforming Delaunay.         //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
-@@ -33916,14 +30673,9 @@
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--#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);
-   }
-@@ -33932,11 +30684,12 @@
-            r3count);
-   }
-   if (b->quality) {
--    printf("  Bowyer-Watson insertions: seg %ld, sub %ld, vol %ld.\n",
-+    printf("  Bowyer-Watson counts (seg, sub, vol)\n");
-+    printf("    Insert vertices: %ld, %ld, %ld\n",
-            bowatsegcount, bowatsubcount, bowatvolcount);
--    printf("  Bowyer-Watson corrections: seg %ld, sub %ld, vol %ld\n",
-+    printf("    Update cavities: %ld, %ld, %ld\n",
-            updsegcount, updsubcount, updvolcount);
--    printf("  Bowyer-Watson failures: seg %ld, sub %ld, vol %ld\n",
-+    printf("    Failed cavities: %ld, %ld, %ld\n",
-            failsegcount, failsubcount, failvolcount);
-     printf("  Number of repair flips: %ld.\n", repairflipcount);
-     printf("  Number of circumcenters outside Bowat-cav.: %ld.\n",
-@@ -33945,21 +30698,25 @@
-       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("  Reject vertices counts:\n");
-+    printf("    Rejected seg splits: %ld.\n", rejsegpts);
-+    printf("    Rejected sub splits: %ld.\n", rejsubpts);
-+    printf("    Rejected tet splits: %ld.\n", rejtetpts);
-+    if (b->smooth) {
-+      printf("  Mesh smooth counts:\n");
-+      printf("    %4ld cdt enforcement points.\n", smoothcdtsegpt);
-+      printf("    %4ld segment points.\n", smoothsegpt);
-+      printf("    %4ld facet points.\n", smoothsubpt);
-+      printf("    %4ld volume points.\n", smoothvolpt);
-+      printf("    %4ld failed cdt enforcement points.\n", unsmoothcdtsegpt);
-+      printf("    %4ld unimproved segment points.\n", unsmoothsegpt);
-+      printf("    %4ld unimproved facet points.\n", unsmoothsubpt);
-+      printf("    %4ld unimproved volume points.\n", unsmoothvolpt);
-     }
-   }
-   printf("\n");
--  */
- }
- 
--#endif // #ifdef SELF_CHECK
--
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
- // qualitystatistics()    Print statistics about the quality of the mesh.    //
-@@ -33968,28 +30725,25 @@
- 
- void tetgenmesh::qualitystatistics()
- {
--  triface tetloop, neightet;
-+  triface tetloop;
-   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 edgelength[6], alldihed[6];
-   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;
-@@ -34019,7 +30773,6 @@
-   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;
-@@ -34027,8 +30780,8 @@
-   longest = 0.0;
-   smallestvolume = minaltitude;
-   biggestvolume = 0.0;
--  smallestdiangle = smallestfaangle = 180.0;
--  biggestdiangle = biggestfaangle = 0.0;
-+  smallestdiangle = 180.0;
-+  biggestdiangle = 0.0;
- 
-   // Loop all elements, calculate quality parameters for each element.
-   tetrahedrons->traversalinit();
-@@ -34172,45 +30925,6 @@
-     }
-     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);
-@@ -34237,12 +30951,6 @@
-          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';
-@@ -34250,7 +30958,6 @@
-   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],
-@@ -34267,7 +30974,6 @@
-   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",
-@@ -34286,18 +30992,6 @@
-   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",
-@@ -34315,10 +31009,7 @@
-          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");
- }
- 
-@@ -34337,7 +31028,6 @@
-   }
-   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);
-   }
-@@ -34345,35 +31035,20 @@
-   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);
-+    printf("  Mesh faces: %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);
-+    printf("  Convex hull faces: %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();
-+    // algorithmicstatistics();
- #endif
-+    qualitystatistics();
-+    printf("\n");
-   }
- }
- 
-@@ -34469,7 +31144,7 @@
-   longest = 0.0;
-   hullsize = 0l;
-   insegments = 0l;
--  pointmtrindex = 0;
-+  pointlfsindex = 0;
-   pointmarkindex = 0;
-   point2simindex = 0;
-   point2pbcptindex = 0;
-@@ -34479,7 +31154,6 @@
-   shmarkindex = 0;
-   areaboundindex = 0;
-   checksubfaces = 0;
--  checksubsegs = 0;
-   checkpbcs = 0;
-   varconstraint = 0;
-   nonconvex = 0;
-@@ -34490,11 +31164,10 @@
-   collapverts = 0;
-   unsupverts = 0;
-   jettisoninverts = 0;
--  symbolic = 1;
-+  symbolic = 0;
-   samples = 0l;
--  randomseed = 1l;
-+  randomseed = 0l;
-   macheps = 0.0;
--  minfaceang = minfacetdihed = PI;
-   maxcavfaces = maxcavverts = 0;
-   expcavcount = 0;
-   abovecount = 0l;
-@@ -34503,11 +31176,10 @@
-   repairflipcount = 0l;
-   outbowatcircumcount = 0l;
-   failvolcount = failsubcount = failsegcount = 0l;
--  r1count = r2count = r3count = 0l;
-+  r1count = r2count = r3count = r4count = 0l;
-   cdtenforcesegpts = 0l;
-   rejsegpts = rejsubpts = rejtetpts = 0l;
-   flip23s = flip32s = flip22s = flip44s = 0l;
--  tloctime = tfliptime = 0.0;
- }
- 
- //
-@@ -34542,29 +31214,31 @@
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
-+#include <time.h>           // Defined type clock_t, constant CLOCKS_PER_SEC.
-+
- void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
--  tetgenio *addin, tetgenio *bgmin)
-+  tetgenio *bgmesh)
- {
-   tetgenmesh m;
--  // Variables for timing the performance of TetGen (defined in time.h).
--  clock_t tv[14];
-+  clock_t tv0, tv1, tv2, tv3, tv4, tv5, tv6, tv7, tv8, tv9, tv10, tv11;
- 
--  tv[0] = clock();
-+  tv0 = clock();
-  
-   m.b = b;
-   m.in = in;
-   m.macheps = exactinit();
-   m.steinerleft = b->steiner;
--  if (b->metric) {
-+  if (b->bgmesh) {
-+    // '-m' switch
-     m.bgm = new tetgenmesh();
-     m.bgm->b = b;
--    m.bgm->in = bgmin;
-+    m.bgm->in = bgmesh;
-     m.bgm->macheps = exactinit();
-   }
-   m.initializepools();
-   m.transfernodes();
- 
--  tv[1] = clock();
-+  tv1 = clock();
- 
-   if (b->refine) {
-     m.reconstructmesh();
-@@ -34572,149 +31246,103 @@
-     m.delaunizevertices();
-   }
- 
--  tv[2] = clock();
--
-+  tv2 = 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();
-+      printf("Mesh reconstruction seconds:  %g\n",
-+             (tv2 - tv1) / (REAL) CLOCKS_PER_SEC);
-     } 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);
-+      printf("Delaunay seconds:  %g\n", (tv2 - tv1) / (REAL) CLOCKS_PER_SEC);
-     }
-   }
- 
-   if (b->useshelles && !b->refine) {
--    m.meshsurface();
-+    m.insegments = m.meshsurface();
-     if (b->diagnose != 1) {
--      m.markacutevertices(89.0);
--      m.incrperturbvertices(b->epsilon);
-+      m.incrperturbvertices(b->epsilon); // '-p' switch.
-       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();
-+      m.detectinterfaces(); // '-d' switch.
-     }
-   }
- 
--  tv[4] = clock();
--
-+  tv3 = clock();
-   if (!b->quiet) {
-     if (b->useshelles && !b->refine) {
-       if (b->diagnose != 1) {
--        printf("Segment and facet ");
-+        printf("Segment and facet seconds:  %g\n",
-+               (tv3 - tv2) / (REAL) CLOCKS_PER_SEC);
-       } else {
--        printf("Intersection "); 
-+        printf("Intersection seconds:  %g\n", 
-+               (tv3 - tv2) / (REAL) CLOCKS_PER_SEC);  
-       }
--      printf("seconds:  %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
--    }
-+    } 
-   }
- 
-   if (b->plc && !(b->diagnose == 1)) {
-     m.carveholes();
-   }
- 
--  tv[5] = clock();
--
-+  tv4 = clock();
-   if (!b->quiet) {
-     if (b->plc && !(b->diagnose == 1)) {
--      printf("Hole seconds:  %g\n", (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
-+      printf("Hole seconds:  %g\n", (tv4 - tv3) / (REAL) CLOCKS_PER_SEC);
-     }
-   }
- 
-   if ((b->plc || b->refine) && !(b->diagnose == 1)) {
--    m.optimizemesh(false); 
-+    m.repairmesh(); 
-   }
- 
--  tv[6] = clock();
--
-+  tv5 = 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);
-+      printf("Repair seconds:  %g\n", (tv5 - tv4) / (REAL) CLOCKS_PER_SEC);
-     }
-   }
- 
-   if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
--    m.removesteiners(false);
-+    m.removesteiners();
-   }
- 
--  tv[7] = clock();
--
-+  tv6 = 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);
-+             (tv6 - tv5) / (REAL) CLOCKS_PER_SEC);
-     }
-   }
- 
--  if (b->insertaddpoints && (addin != (tetgenio *) NULL)) {
--    if (addin->numberofpoints > 0) {
--      m.insertconstrainedpoints(addin); 
-+  if (b->insertaddpoints) {
-+    if (in->numberofaddpoints == 0) {
-+      in->load_addnodes(b->infilename);
-     }
--  }
--
--  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 (in->numberofaddpoints > 0) {
-+      m.insertaddpoints(); 
-     }
-   }
- 
--  if (b->metric) {
--    m.interpolatesizemap();
--  }
--
--  tv[9] = clock();
--
-+  tv7 = clock();
-   if (!b->quiet) {
--    if (b->metric) {
--      printf("Size interpolating seconds:  %g\n",
--             (tv[9] - tv[8]) / (REAL) CLOCKS_PER_SEC);
-+    if ((b->plc || b->refine) && (in->numberofaddpoints > 0)) {
-+      printf("Add points seconds:  %g\n", (tv7 - tv6) / (REAL) CLOCKS_PER_SEC);
-     }
-   }
- 
--  if (b->coarse) {
--    m.removesteiners(true);
-+  if (b->bgmesh) {
-+    // '-b' switch
-+    m.bgm->initializepools();
-+    m.bgm->transfernodes();
-+    m.bgm->reconstructmesh();
-+    m.interpolatesizemap();
-   }
- 
--  tv[10] = clock();
--
-+  tv8 = clock();
-   if (!b->quiet) {
--    if (b->coarse) {
--      printf("Mesh coarsening seconds:  %g\n",
--             (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
-+    if (b->bgmesh) {
-+      printf("Background mesh reconstruct seconds:  %g\n",
-+             (tv8 - tv7) / (REAL) CLOCKS_PER_SEC);
-     }
-   }
- 
-@@ -34722,25 +31350,21 @@
-     m.enforcequality();
-   }
- 
--  tv[11] = clock();
--
-+  tv9 = clock();
-   if (!b->quiet) {
-     if (b->quality) {
--      printf("Quality seconds:  %g\n",
--             (tv[11] - tv[10]) / (REAL) CLOCKS_PER_SEC);
-+      printf("Quality seconds:  %g\n", (tv9 - tv8) / (REAL) CLOCKS_PER_SEC);
-     }
-   }
- 
--  if (b->quality && (b->optlevel > 0)) {
--    m.optimizemesh(true);
-+  if (b->quality && b->smooth) {
-+    m.smoothmesh();
-   }
- 
--  tv[12] = clock();
--
-+  tv10 = 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->quality && b->smooth) {
-+      printf("Smooth seconds:  %g\n", (tv10 - tv9) / (REAL) CLOCKS_PER_SEC);
-     }
-   }
- 
-@@ -34769,12 +31393,13 @@
-   } else {
-     if (b->diagnose == 1) {
-       if (m.subfaces->items > 0l) {
--        m.outnodes(out);  // Only output when self-intersecting faces exist.
-+        // Only output when there are intersecting faces.
-+        m.outnodes(out);
-       }
-     } else {
-       m.outnodes(out);
--      if (b->quality || b->metric) {
--        // m.outmetrics(out);
-+      if (b->metric) {
-+        m.outmetrics(out);
-       }
-     }
-   }
-@@ -34798,20 +31423,24 @@
-   } else {
-     if (b->facesout) {
-       if (m.tetrahedrons->items > 0l) {
--        m.outfaces(out);  // Output all faces.
-+        // Output all faces.
-+        m.outfaces(out);
-       }
-     } else {
-       if (b->diagnose == 1) {
-         if (m.subfaces->items > 0l) {
--          m.outsubfaces(out); // Only output self-intersecting faces.
-+          // Only output when there are intersecting faces.
-+          m.outsubfaces(out);
-         }
-       } else if (b->plc || b->refine) {
-         if (m.subfaces->items > 0l) {
--          m.outsubfaces(out); // Output boundary faces.
-+          // Output boundary faces.
-+          m.outsubfaces(out); 
-         }
-       } else {
-         if (m.tetrahedrons->items > 0l) {
--          m.outhullfaces(out); // Output convex hull faces.
-+          // Output convex hull faces.
-+          m.outhullfaces(out); 
-         }
-       }
-     }
-@@ -34821,11 +31450,9 @@
-     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 (b->edgesout && b->plc) {
-+    if (m.subsegs->items > 0l) {
-+      m.outsubsegments(out); 
-     }
-   }
- 
-@@ -34852,17 +31479,11 @@
-     m.outneighbors(out);
-   }
- 
--  if (b->voroout) {
--    m.outvoronoi(out);
--  }
--
--  tv[13] = clock();
--
-+  tv11 = clock();
-   if (!b->quiet) {
--    printf("\nOutput seconds:  %g\n",
--           (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
-+    printf("\nOutput seconds:  %g\n", (tv11 - tv10) / (REAL) CLOCKS_PER_SEC);
-     printf("Total running seconds:  %g\n",
--           (tv[13] - tv[0]) / (REAL) CLOCKS_PER_SEC);
-+           (tv11 - tv0) / (REAL) CLOCKS_PER_SEC);
-   }
- 
-   if (b->docheck) {
-@@ -34884,7 +31505,7 @@
-     m.statistics();
-   }
- 
--  if (b->metric) {
-+  if (bgmesh) {
-     delete m.bgm;
-   }
- }
-@@ -34908,7 +31529,7 @@
- ///////////////////////////////////////////////////////////////////////////////
- 
- void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
--  tetgenio *addin, tetgenio *bgmin)
-+  tetgenio *bgmesh)
- 
- #endif // not TETLIBRARY
- 
-@@ -34917,7 +31538,7 @@
- 
- #ifndef TETLIBRARY
- 
--  tetgenio in, addin, bgmin;
-+  tetgenio in, bgmesh;
-   
-   if (!b.parse_commandline(argc, argv)) {
-     terminatetetgen(1);
-@@ -34931,21 +31552,16 @@
-       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 (b.bgmesh) {
-+    if (!bgmesh.load_tetmesh(b.bgmeshfilename)) {
-+      bgmesh.numberoftetrahedra = 0l;
-     }
-   }
- 
--  if (bgmin.numberoftetrahedra > 0l) {
--    tetrahedralize(&b, &in, NULL, &addin, &bgmin);
-+  if (bgmesh.numberoftetrahedra > 0l) {
-+    tetrahedralize(&b, &in, NULL, &bgmesh);
-   } else {
--    tetrahedralize(&b, &in, NULL, &addin, NULL);
-+    tetrahedralize(&b, &in, NULL, NULL);
-   }
- 
-   return 0;
-@@ -34955,7 +31571,7 @@
-   if (!b.parse_commandline(switches)) {
-     terminatetetgen(1);
-   }
--  tetrahedralize(&b, in, out, addin, bgmin);
-+  tetrahedralize(&b, in, out, bgmesh);
- 
- #endif // not TETLIBRARY
- }
-Index: tetgen1.4.2/tetgen.h
-===================================================================
---- tetgen1.4.2.orig/tetgen.h	2008-02-16 01:32:48.444098094 +0100
-+++ tetgen1.4.2/tetgen.h	2008-02-16 01:33:05.227498420 +0100
-@@ -5,22 +5,16 @@
- // A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
- //                                                                           //
- // Version 1.4                                                               //
--// April 16, 2007                                                            //
-+// January 14, 2006                                                          //
- //                                                                           //
--// Copyright (C) 2002--2007                                                  //
-+// Copyright 2002, 2004, 2005, 2006                                          //
- // Hang Si                                                                   //
--// Research Group Numerical Mathematics and Scientific Computing             //
--// Weierstrass Institute for Applied Analysis and Stochastics                //
--// Mohrenstr. 39, 10117 Berlin, Germany                                      //
-+// Rathausstr. 9, 10178 Berlin, Germany                                      //
- // si at 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.     //
--//                                                                           //
--///////////////////////////////////////////////////////////////////////////////
--
--///////////////////////////////////////////////////////////////////////////////
-+// You can obtain TetGen via internet: http://tetgen.berlios.de.  It may be  //
-+//   freely copied, modified, and redistributed under the copyright notices  //
-+//   given in the file LICENSE.                                              //
- //                                                                           //
- // TetGen computes Delaunay tetrahedralizations, constrained Delaunay tetra- //
- //   hedralizations, and quality Delaunay tetrahedral meshes. The latter are //
-@@ -34,25 +28,26 @@
- //                                                                           //
- //   The efficient Delaunay tetrahedralization algorithm is: H. Edelsbrunner //
- //   and N. R. Shah, "Incremental Topological Flipping Works for Regular     //
--//   Triangulations". Algorithmica 15: 223--241, 1996.                       //
-+//   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 Delaunay refinement algorithm is from:  Hang Si, "On Refinement of  //
-+//   Constrained Delaunay Tetrahedralizations". In Proceeding of the 15th    //
-+//   International Meshing Roundtable. September 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.                            //
-+//   boundary elements: subfaces and subsegments.  Both data structures have //
-+//   a set of fast mesh manipulation primitives.                             //
- //                                                                           //
- //   J. R. Shewchuk, "Delaunay Refinement Mesh Generation". PhD thesis,      //
--//   Carnegie Mellon University, Pittsburgh, PA, 1997.                       //
-+//   Carnegie Mellon University, 1997.                                       //
- //                                                                           //
- //   E. P. Muecke, "Shapes and Implementations in Three-Dimensional          //
- //   Geometry". PhD thesis, Univ. of Illinois, Urbana, Illinois, 1993.       //
-@@ -79,15 +74,6 @@
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
--// Here are the most general used head files for C/C++ programs.
--
--#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> 
--
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
- // TetGen Library Overview                                                   //
-@@ -142,30 +128,40 @@
-   #define REAL double
- #endif 	// not defined SINGLE
- 
-+// Here are the most general used head files for C/C++ programs.
-+
-+#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 <assert.h>
-+ 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// tetgenio    Passing data into and out of the library of TetGen.           //
-+// The tetgenio data type                                                    //
- //                                                                           //
--// 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.    //
-+// Used to pass data into and out of the library of TetGen.                  //
- //                                                                           //
- // 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).     //
--//                                                                           //
--// 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  //
--// deletion of the object, the memory occupied by these arrays needs to be   //
--// freed.  Routine deinitialize() will be automatically called. It will de-  //
--// allocate the memory for an array if it is not a NULL. However, it assumes //
--// that the memory is allocated by the C++ "new" operator. If you use malloc //
--// (), you should free() them and set the pointers to NULLs before reaching  //
--// deinitialize().                                                           //
-+// to understand the tetgenio data type, while the other two data types can  //
-+// be hidden through calling the global function "tetrahedralize()".  As you //
-+// will see, that tetgenio is just a collection of arrays to storing points  //
-+// (by coodinates), tetrahedra (by indexes), faces, boundary markers, and so //
-+// forth.  Each array corresponds 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) before using tetgenio objects.                        //
-+//                                                                           //
-+// Once an object of tetgenio is declared (or created), all arrays of it are //
-+// automatically initialized to NULLs (by routine initialize()). Before they //
-+// can be used,  one has to first allocate enough memory for them, i.e., use //
-+// either 'malloc()' or 'new' operator. On deletion of the object, one needs //
-+// to free the memory occupied by these arrays.  Routine deinitialize() will //
-+// be automatically called. It will deallocate the memory for an array if it //
-+// is not a NULL. However, it assumes that the memory is allocated by 'new'  //
-+// (C++ operator).  If you use malloc(), you should free() them and set the  //
-+// pointers to NULLs before reaching deinitialize().                         //
- //                                                                           //
--// In all cases, the first item in an array is stored starting at index [0]. //
-+// In all cases, the first item in any 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'.        //
-@@ -222,30 +218,6 @@
-       f->numberofholes = 0;
-     }
- 
--    // A 'voroedge' is an edge of the Voronoi diagram. It corresponds to a
--    //   Delaunay face.  Each voroedge is either a line segment connecting
--    //   two Voronoi vertices or a ray starting from a Voronoi vertex to an
--    //   "infinite vertex".  'v1' and 'v2' are two indices pointing to the
--    //   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];
--    } voroedge;
--
--    // A 'vorofacet' is an facet of the Voronoi diagram. It corresponds to a
--    //   Delaunay edge.  Each Voronoi facet is a convex polygon formed by a
--    //   list of Voronoi edges, it may not be closed.  'c1' and 'c2' are two
--    //   indices pointing into the list of Voronoi cells, i.e., the two cells
--    //   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;
--    } vorofacet;
--
-     // The periodic boundary condition group data structure.  A "pbcgroup"
-     //   contains the definition of a pbc and the list of pbc point pairs.
-     //   'fmark1' and 'fmark2' are the facetmarkers of the two pbc facets f1
-@@ -264,27 +236,27 @@
- 
-     // Items are numbered starting from 'firstnumber' (0 or 1), default is 0.
-     int firstnumber; 
-+
-     // Dimension of the mesh (2 or 3), default is 3.
-     int mesh_dim;
--    // 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':  An 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. 
--    // 'pointattributelist':  An array of point attributes.  Each point's
--    //   attributes occupy 'numberofpointattributes' REALs.
--    // 'pointmtrlist': An array of metric tensors at points. Each point's
--    //   tensor occupies 'numberofpointmtr' REALs.
-+    // `pointattributelist':  An array of point attributes.  Each point's
-+    //   attributes occupy `numberofpointattributes' REALs. 
-+    // 'addpointlist':  An array of additional point coordinates.
-+    // 'addpointattributelist':  An array of attributes for addition points.
-     // `pointmarkerlist':  An array of point markers; one int per point.
-     REAL *pointlist;
-     REAL *pointattributelist;
--    REAL *pointmtrlist;
-+    REAL *addpointlist;
-+    REAL *addpointattributelist;
-     int *pointmarkerlist;
-     int numberofpoints;
-     int numberofpointattributes;
--    int numberofpointmtrs;
-+    int numberofaddpoints;
-  
-     // `elementlist':  An array of element (triangle or tetrahedron) corners. 
-     //   The first element's first corner is at index [0], followed by its
-@@ -342,6 +314,13 @@
-     REAL *segmentconstraintlist;
-     int numberofsegmentconstraints;
- 
-+    // `nodeconstraintlist':  An array of segment length constraints.  Two
-+    //   REALs per constraint. The first one is the index (pointing into
-+    //   'pointlist') of the node, the second is its edge length bound.
-+    // Note the 'nodeconstraintlist' is used only for the 'q' switch. 
-+    REAL *nodeconstraintlist;
-+    int numberofnodeconstraints;
-+
-     // 'pbcgrouplist':  An array of periodic boundary condition groups.
-     pbcgroup *pbcgrouplist;
-     int numberofpbcgroups;
-@@ -352,7 +331,7 @@
-     // `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'
-+    //   indicates outside (no adj. tet). This list is output when '-n'
-     //   switch is used.
-     // `trifacemarkerlist':  An array of face markers; one int per face.
-     int *trifacelist;
-@@ -368,21 +347,6 @@
-     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
--    //   indices pointing into 'vfacetlist'. The 0th entry is used to store
--    //   the length of this array.
--    REAL *vpointlist;
--    voroedge *vedgelist;
--    vorofacet *vfacetlist;
--    int **vcelllist;
--    int numberofvpoints;
--    int numberofvedges;
--    int numberofvfacets;
--    int numberofvcells;
--
-   public:
- 
-     // Initialize routine.
-@@ -392,6 +356,7 @@
-     // Input & output routines.
-     bool load_node_call(FILE* infile, int markers, char* nodefilename);
-     bool load_node(char* filename);
-+    bool load_addnodes(char* filename);
-     bool load_pbc(char* filename);
-     bool load_var(char* filename);
-     bool load_mtr(char* filename);
-@@ -402,7 +367,6 @@
-     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);
-@@ -423,7 +387,9 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
--// tetgenbehavior    Parsing command line switches and file names.           //
-+// The tetgenbehavior data type                                              //
-+//                                                                           //
-+// Used to parse command line switches and file names.                       //
- //                                                                           //
- // It includes a list of variables corresponding to the commandline switches //
- // for control the behavior of TetGen.  These varibales are all initialized  //
-@@ -459,29 +425,28 @@
- 
-     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.
-+    // Variables of command line switches.  Each variable is corresponding
-+    //   to a specific switch and will be properly initialized.  Read the
-+    //   user's manul to find out the meaning of these switches.
- 
-     int plc;                                              // '-p' switch, 0.
--    int quality;                                          // '-q' switch, 0.
-     int refine;                                           // '-r' switch, 0.
--    int coarse;                                           // '-R' switch, 0.
-+    int quality;                                          // '-q' switch, 0.
-+    int smooth;                                           // '-s' switch, 0.
-     int metric;                                           // '-m' switch, 0.
-+    int bgmesh;                                           // '-b' 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 offcenter;                                        // '-R' 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.
-@@ -490,27 +455,26 @@
-     int noelewritten;                                     // '-E' switch, 0.
-     int nofacewritten;                                    // '-F' switch, 0.
-     int noiterationnum;                                   // '-I' switch, 0.
--    int nomerge;                                          // '-M',switch, 0.
-+    int nomerge;           // count of how often '-M' switch is selected, 0.
-     int nobisect;          // count of how often '-Y' switch is selected, 0.
--    int noflip;                     // do not perform flips. '-X' switch. 0.
-+    int noflip;                     // do not perform flips. '-Y' 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.
-+    int tol;               // count of how often '-T' switch is selected, 0.
-+    int useshelles;            // '-p', '-r', '-q', '-d', or '-c' 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 maxdihedral;                    // number after '-s' switch, 175.0.
-+    REAL alpha1;                       // number after '-R' switch, sqrt(2).
-+    REAL alpha2;                    // number after '-RR' switch, 1/sqrt(2).
-+    REAL alpha3;                         // number after '-RRR' 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.
-@@ -519,7 +483,6 @@
-     char commandline[1024];
-     char infilename[1024];
-     char outfilename[1024];
--    char addinfilename[1024];
-     char bgmeshfilename[1024];
- 
-     tetgenbehavior();
-@@ -542,8 +505,9 @@
- //                                                                           //
- // Return one of the values +1, 0, and -1 on basic geometric questions such  //
- // as the orientation of point sets, in-circle, and in-sphere tests.  They   //
--// are basic units for implmenting geometric algorithms.  TetGen uses two 3D //
--// geometric predicates: the orientation and in-sphere tests.                //
-+// are basic units for the composition of geometric algorithms.  TetGen uses //
-+// two 3D geometric predicates, which are the orientation test and the in-   //
-+// sphere test (e.g. the locally Deklaunay test).                            //
- //                                                                           //
- // Orientation test:  let a, b, c be a sequence of 3 non-collinear points in //
- // R^3.  They defines a unique hypeplane H.  Let H+ and H- be the two spaces //
-@@ -626,15 +590,20 @@
-     //   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};
-+                   FREESEGVERTEX, FACETVERTEX, FREESUBVERTEX, VOLVERTEX,
-+                   FREEVOLVERTEX, DEADVERTEX = -32768};
-  
--    // Labels that signify the type of a subface/subsegment.
--    enum shestype {NSHARP, SHARP};
-+    // Labels that signify the type of a subface/subsegment.  A subface is
-+    //   SKINNY if it has two edges which are subsegments and form a small
-+    //   angle (e.g., 10 degree); a subsegment is a SHARP if it is between
-+    //   two facets which form an acute dihedral angle.
-+    enum shestype {NSHARPNSKINNY, SHARP, SKINNY};
- 
-     // 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};
-+    //   Types UNFLIPABLE, NONCONVEX are unflipable.
-+    enum fliptype {T23, T32, T22, T44, UNFLIPABLE, FORBIDDENFACE,
-+                   FORBIDDENEDGE, NONCONVEX};
- 
-     // Labels that signify the result of triangle-triangle intersection test.
-     //   Two triangles are DISJOINT, or adjoint at a vertex SHAREVERTEX, or
-@@ -798,7 +767,7 @@
-     // 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 REAL of local feature sizes (optional -p switch);
-     //   - 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);
-@@ -946,6 +915,61 @@
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
-+// The Metric tensor data structure                                          //
-+//                                                                           //
-+// A metric is a function that specifies the "distance" between two points   //
-+// in a metric space E. Recall if d(p, q) is a metric of E, then we have:    //
-+//   (1) d(p, q) = d(q, p). (d is symmetric)                                 //
-+//   (2) d(p, q) = 0 if and only if p = q.                                   //
-+//   (3) d(p, x) + d(x, q) >= d(p, q). (d satisfies triangle inequality)     //
-+//                                                                           //
-+// In d dimensions, the metric tensor of a point p is a (dxd) symmetric      //
-+// positive definie (non-degenerate) matrix M(p). Very roughly, it tells how //
-+// to compute the distance of p and other points in the metric space of p.   //
-+//   d_M(p, q) = \sqrt{(p - q)' M (p -q)}.                                   //
-+// If for any point p, a metric tensor M(p) is given, the field of tensors   //
-+// thus defines a Riemannian space. For example, if M(q) is a metric tensor  //
-+// defined on q.  Then the distance d(p, q) can be calculated by:            //
-+//   d(p, q) = \int_{0}{1} \sqrt((p - q)' M(t) (p - q)) dt.                  //
-+// where M(t) is the interpolation of metric tensors between p and q, M(0) = //
-+// M(p) and M(1) = M(q).                                                     //
-+//                                                                           //
-+// A metric tensor in three dimension, for example, is a matrix:             //
-+//         | a b c |                                                         //
-+//   M =   | b d e |                                                         //
-+//         | c e f |                                                         //
-+// such that a > 0, d > 0, f > 0, det(M) = adf + 2bce -ccd - eea - bbf > 0.  //
-+//                                                                           //
-+// It is defined as an array mat[6] = {a, b, c, d, e, f}. Operation on       //
-+// tensors are defined as well.                                              //
-+//                                                                           //
-+///////////////////////////////////////////////////////////////////////////////
-+
-+    class metric {
-+
-+      public:
-+
-+        REAL mat[6];
-+
-+        // Initialization.
-+        void init() {for (int i = 0; i < 6; i++) mat[i] = 0.0;}
-+        void set(REAL a, REAL b, REAL c, REAL d, REAL e, REAL f) {
-+          mat[0] = a; mat[1] = b; mat[2] = c;
-+          mat[3] = d; mat[4] = e; 
-+          mat[5] = f;
-+        }
-+        void set(REAL a, REAL d, REAL f) {
-+          mat[0] = a; mat[1] = 0.0; mat[2] = 0.0;
-+          mat[3] = d; mat[4] = 0.0; 
-+          mat[5] = f;
-+        }
-+
-+        // Constructors.
-+        metric() {init();}
-+    };
-+
-+///////////////////////////////////////////////////////////////////////////////
-+//                                                                           //
- // The list, link and queue data structures                                  //
- //                                                                           //
- // These data types are used to manipulate a set of (same-typed) data items. //
-@@ -974,8 +998,12 @@
-     //   take two pointers of the corresponding date type, perform the
-     //   comparation, and return -1, 0 or 1 indicating the default linear
-     //   order of them.
-+
-+    // Compare two 'integers'.
-     static int compare_2_ints(const void* x, const void* y);
-+    // Compare two 'longs'. 
-     static int compare_2_longs(const void* x, const void* y);
-+    // Compare two 'unsigned longs'. 
-     static int compare_2_unsignedlongs(const void* x, const void* y);
- 
-     // The function used to determine the size of primitive data types and
-@@ -1168,7 +1196,7 @@
-         bool locate(int pos);
-         void *add(void* newitem);
-         void *insert(int pos, void* insitem);
--        void *deletenode(void** delnode);
-+        void *del(void* delitem);
-         void *del(int pos);
-         void *getitem();
-         void *getnitem(int pos);
-@@ -1179,7 +1207,7 @@
- //                                                                           //
- // Queue data structure.                                                     //
- //                                                                           //
--// A 'queue' is basically a link.  Following is an image of a queue.         //
-+// A 'queue' is a basically a link.  Following is an image of a queue.       //
- //              ___________     ___________     ___________                  //
- //   Pop() <-- |_         _|<--|_         _|<--|_         _| <-- Push()      //
- //             |_  Data0  _|   |_  Data1  _|   |_  Data2  _|                 //
-@@ -1193,27 +1221,12 @@
-       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);
--        }
-+        queue(char* str, int count = 256) : link(str, count) {}
-+
-+        int  empty() { return linkitems == 0; }
-+        void *push(void* newitem) { return link::add(newitem); }
-+        void *bot() { return link::getnitem(1); }
-+        void *pop() { return link::del(1); }
-     };
- 
- ///////////////////////////////////////////////////////////////////////////////
-@@ -1274,9 +1287,7 @@
-     //   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;
-+    badface *tetquefront[64], **tetquetail[64];
- 
-     // Pointer to a recently visited tetrahedron. Improves point location
-     //   if proximate points are inserted sequentially.
-@@ -1288,8 +1299,7 @@
-     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 pointlfsindex;   // Index to find the local feature size 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.
-@@ -1300,7 +1310,6 @@
-     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?
-@@ -1310,15 +1319,12 @@
-     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.
-@@ -1327,12 +1333,13 @@
-     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 r1count, r2count, r3count, r4count;   // Number of rules performed.
-     long cdtenforcesegpts;              // Number of CDT enforcement points.
-     long rejsegpts, rejsubpts, rejtetpts;      // Number of rejected points.
--    long optcount[10];          // Numbers of various optimizing operations.
-+    long striptetcount, fliptetcount, unimprovecount; // Mesh smooth counts.
-+    long smoothcdtsegpt, smoothsegpt, smoothsubpt, smoothvolpt; 
-+    long unsmoothcdtsegpt, unsmoothsegpt, unsmoothsubpt, unsmoothvolpt;
-     long flip23s, flip32s, flip22s, flip44s;   // Number of flips performed.
--    REAL tloctime, tfliptime;      // Time (microseconds) of point location.
- 
- ///////////////////////////////////////////////////////////////////////////////
- //                                                                           //
-@@ -1376,10 +1383,6 @@
-     //   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];
-@@ -1473,7 +1476,7 @@
-     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 tsdissolve(triface& t);    
-     inline void stdissolve(face& s);
- 
-     // Primitives for interacting subfaces and subsegs.
-@@ -1481,10 +1484,6 @@
-     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);
-@@ -1510,6 +1509,7 @@
-     inline bool isfacehaspoint(face* t, point testpoint);
-     inline bool isfacehasedge(face* s, point tend1, point tend2);
-     inline bool issymexist(triface* t);
-+    bool getnextface(triface*, triface*);
-     void getnextsface(face*, face*);
-     void tsspivot(triface*, face*);
-     void sstpivot(face*, triface*);   
-@@ -1544,14 +1544,16 @@
-     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_cop_inter(REAL*, REAL*, REAL*, REAL*, REAL*,
-+                                        REAL*);
-     enum interresult tri_edge_inter_tail(REAL*, REAL*, 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);
-+    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);
-@@ -1574,7 +1576,6 @@
-     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);
-@@ -1610,7 +1611,6 @@
-     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);
-@@ -1635,15 +1635,8 @@
-     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);
-@@ -1659,8 +1652,6 @@
-                                      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*);
-@@ -1683,6 +1674,8 @@
-     // Delaunay tetrahedralization routines.
-     void formstarpolyhedron(point pt, list* tetlist, list* verlist, bool);
-     bool unifypoint(point testpt, triface*, enum locateresult, REAL);
-+    void closeopenface(triface* openface, queue* flipque);
-+    void inserthullsite(point inspoint, triface* horiz, queue* flipque);
-     void incrflipdelaunay(triface*, point*, long, bool, bool, REAL, queue*);
-     long delaunizevertices();
- 
-@@ -1705,7 +1698,7 @@
-                      int holes, REAL* holelist, memorypool* viri, queue*);
-     void retrievenewsubs(list* newshlist, bool removeseg);
-     void unifysegments();
--    void mergefacets(queue* flipqueue);
-+    void mergefacets(queue* flipqueue);    
-     long meshsurface();
- 
-     // Detect intersecting facets of PLC.
-@@ -1739,8 +1732,6 @@
-     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.
-@@ -1800,43 +1791,46 @@
-     void restorepolyhedron(list* oldtetlist);
-     bool suppressfacetpoint(face* supsh, list* frontlist, list* misfrontlist,
-                             list* ptlist, list* conlist, memorypool* viri,
--                            queue* flipque, bool noreloc, bool optflag);
-+                            queue* flipque);
-     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);
-+                          list* conlist, memorypool* viri, queue* flipque);
-+    bool suppressvolpoint(point suppt, list* frontlist, list* misfrontlist,
-+                          list* ptlist, queue* flipque);
-+    bool collapseedgepoint(point colpt, list* oldtetlist, list* newtetlist,
-+                           list* ptlist);
-+    void removesteiners();
- 
--    // Mesh reconstruction routines.
-+    // Mesh reconstruction rotuines.
-     long reconstructmesh();
--    // Constrained points insertion routines.
--    void insertconstrainedpoints(tetgenio *addio);
-+    bool intettest(point testpt, triface* testtet, REAL eps);
-+    void insertaddpoints();
-+
-     // Background mesh operations.
--    bool p1interpolatebgm(point pt, triface* bgmtet, long *scount);
-+    bool interpolatepointsize(point pt, triface* bgmtet, long *scount);
-+    void searchpointrecursive(triface *curtet, long *scount);
-     void interpolatesizemap();
--    void duplicatebgmesh();
- 
-     // Delaunay refinement routines.
--    void marksharpsegments(REAL sharpangle);
--    void decidefeaturepointsizes();
-+    void calclocalfeaturesizes();
-+    void marksharpsubsegs(REAL dihedbound);
-+    void markskinnysubfaces(REAL anglebound);
-+    void enqueuebadtet(triface* tt, REAL key, REAL* cent);
-     void enqueueencsub(face* ss, point encpt, int quenumber, REAL* cent);
-+    badface* dequeuebadtet();
-     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 checkseg4badqual(face* testseg, bool enqflag);
-+    bool checksub4badqual(face* testsub, 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);
-+    void setnewpointsize(point newpt, list* verlist);
-+    void splitencseg(point, face*, list*, list*, list*, queue*, bool, bool);
-     bool tallencsegs(point testpt, int n, list** ceillists);
-     bool tallencsubs(point testpt, int n, list** ceillists);
-     void tallbadtetrahedrons();
-@@ -1845,15 +1839,16 @@
-     void repairbadtets();
-     void enforcequality();
- 
--    // Mesh optimization routines.
--    void dumpbadtets();
-+    // Mesh Smoothing routines.
-     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);
-+    bool checktet4sliver(triface* testtet, bool chkill, bool enqflag);
-+    void removetetbystripoff(triface *striptet);
-+    void removetetbyflip32(triface *fliptet, bool enq, bool chkill);
-+    bool removetetbyrecon(badface* remtet, bool chkill);
-+    bool removetetbysplit(badface* remtet);
-+    void tallslivers(bool chkill);
-+    void repairmesh();
-+    void smoothmesh();
- 
-     // I/O routines
-     void transfernodes();
-@@ -1865,10 +1860,8 @@
-     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);
-@@ -1880,6 +1873,7 @@
-     void checkmesh();
-     void checkshells();
-     void checkdelaunay(REAL eps, queue* flipqueue);
-+    void checkdegeneracy(REAL eps);
-     void checkconforming();
-     void algorithmicstatistics();
-     void qualitystatistics();
-@@ -1899,18 +1893,23 @@
- //                     Delaunay tetrahedralizations, constrained Delaunay    //
- //                     tetrahedralizations, quality tetrahedral meshes.      //
- //                                                                           //
-+// Two functions (interfaces) are available.  The difference is only the way //
-+// of passing switches.  One directly accepts an object of 'tetgenbehavior', //
-+// while the other accepts a string which is the same as one can used in the //
-+// command line.  The latter may be more convenient for users who don't want //
-+// to kown the 'tetgenbehavir' structure.                                    //
-+//                                                                           //
- // 'in' is an object of 'tetgenio' which contains a PLC you want to tetrahed-//
- // ralize or a previously generated tetrahedral mesh you want to refine.  It //
- // must not be a NULL. 'out' is another object of 'tetgenio' for storing the //
- // generated tetrahedral mesh. It can be a NULL. If so, the output will be   //
--// saved to file(s). If 'bgmin' != NULL, it contains a background mesh which //
--// defines a mesh size distruction function.                                 //
-+// saved to file(s).                                                         //
- //                                                                           //
- ///////////////////////////////////////////////////////////////////////////////
- 
- void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out, 
--                    tetgenio *addin = NULL, tetgenio *bgmin = NULL);
-+                    tetgenio *bgmesh = NULL);
- void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
--                    tetgenio *addin = NULL, tetgenio *bgmin = NULL);
-+                    tetgenio *bgmesh = NULL);
- 
- #endif // #ifndef tetgenH

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/tetgen.git



More information about the debian-science-commits mailing list