diff --git a/Fltk/onelabGroup.cpp b/Fltk/onelabGroup.cpp
index 6097b6a2d05029b0d62251ab731adff8d1db0041..4b276dd7057347789b2d96ee23523b42e3e6868f 100644
--- a/Fltk/onelabGroup.cpp
+++ b/Fltk/onelabGroup.cpp
@@ -386,31 +386,24 @@ bool gmshLocalNetworkClient::run()
   setGmshServer(server);
 
   while(1) {
-    // loop on all the clients (usually only one, but can be more if we spawned
-    // subclients; in that case we might want to start from the one after the
-    // one we read from last, for better load balancing)
-    bool stop = false, haveData = false;
-    gmshLocalNetworkClient *c = 0;
-
     if(getExecutable().empty() && !CTX::instance()->solver.listen){
       // we stopped listening to the special "Listen" client
-      stop = true;
       break;
     }
 
+    // loop on all the clients (usually only one, but can be more if we spawned
+    // subclients; in that case we might want to start from the one after the
+    // one we read from last, for better load balancing)
+    bool stop = false, haveData = false;
+    gmshLocalNetworkClient *c = 0;
     for(int i = 0; i < getNumClients(); i++){
-      if(getExecutable().empty() && !CTX::instance()->solver.listen){
-        // we stopped listening to the special "Listen" client
-        stop = true;
-        break;
-      }
       c = getClient(i);
       if(c->getPid() < 0){
         if(c == this){ // the "master" client stopped
           stop = true;
           break;
         }
-        else{ // this subclient is not active anymore
+        else{ // this subclient is not active anymore: pass to the next client
           continue;
         }
       }
@@ -422,13 +415,11 @@ bool gmshLocalNetworkClient::run()
       }
       else{
         int ret = s->NonBlockingWait(0.001, -1.);
-        if(ret == 0){
-          // we have data from this particular client
+        if(ret == 0){ // we have data from this particular client
           haveData = true;
           break;
         }
-        else if(ret == 3){
-          // pass to the next client
+        else if(ret == 3){ // pass to the next client
           continue;
         }
         else{ // an error occurred
diff --git a/contrib/Tetgen1.5/predicates.cxx b/contrib/Tetgen1.5/predicates.cxx
index 4120704c3521a80f27aa144feb1387ccf78c66a2..a4b77b69fe546cf1cf43491ab064963dfc842a60 100644
--- a/contrib/Tetgen1.5/predicates.cxx
+++ b/contrib/Tetgen1.5/predicates.cxx
@@ -149,8 +149,8 @@
 /*   which is disastrously slow.  A faster way on IEEE machines might be to  */
 /*   mask the appropriate bit, but that's difficult to do in C.              */
 
-#define Absolute(a)  ((a) >= 0.0 ? (a) : -(a))
-/* #define Absolute(a)  fabs(a) */
+//#define Absolute(a)  ((a) >= 0.0 ? (a) : -(a))
+#define Absolute(a)  fabs(a)
 
 /* Many of the operations are broken up into two pieces, a main part that    */
 /*   performs an approximate operation, and a "tail" that computes the       */
@@ -375,6 +375,24 @@ static REAL o3derrboundA, o3derrboundB, o3derrboundC;
 static REAL iccerrboundA, iccerrboundB, iccerrboundC;
 static REAL isperrboundA, isperrboundB, isperrboundC;
 
+// Options to choose types of geometric computtaions. 
+// Added by H. Si, 2012-08-23.
+static int  _use_inexact_arith; // -X option.
+static int  _use_static_filter; // -S option.
+
+// Static filters. Added by H. Si, 2012-08-23.
+static REAL o3dstaticfilter;
+static REAL ispstaticfilter;
+
+#ifndef NDEBUG
+// Counters for counting the number of calls. Added by H. Si, 2012-08-23.
+long ori3dcount, ori3dadaptcount;
+long insphcount, insphadaptcount, insphexactcount;
+long ori4dcount, ori4dadaptcount, ori4dexactcount;
+long o3dfilterfailscount;
+long ispfilterfailscount;
+#endif // #ifndef NDEBUG
+
 /*****************************************************************************/
 /*                                                                           */
 /*  doubleprint()   Print the bit representation of a double.                */
@@ -660,7 +678,7 @@ float uniformfloatrand()
 /*                                                                           */
 /*****************************************************************************/
 
-REAL exactinit()
+void exactinit(int noexact, int nofilter, REAL maxx, REAL maxy, REAL maxz)
 {
   REAL half;
   REAL check, lastcheck;
@@ -722,7 +740,36 @@ REAL exactinit()
   isperrboundB = (5.0 + 72.0 * epsilon) * epsilon;
   isperrboundC = (71.0 + 1408.0 * epsilon) * epsilon * epsilon;
 
-  return epsilon; /* Added by H. Si 30 Juli, 2004. */
+  _use_inexact_arith = noexact;
+  _use_static_filter = !nofilter;
+
+  // Sort maxx < maxy < maxz. Re-use 'half' for swapping.
+  assert(maxx > 0);
+  assert(maxy > 0);
+  assert(maxz > 0);
+
+  if (maxx > maxz) {
+    half = maxx; maxx = maxz; maxz = half;
+  }
+  if (maxy > maxz) {
+    half = maxy; maxy = maxz; maxz = half;
+  }
+  else if (maxy < maxx) {
+    half = maxy; maxy = maxx; maxx = half;
+  }
+
+  // Calculate the static filters.
+  o3dstaticfilter = 5.1107127829973299e-15 * maxx * maxy * maxz;
+  ispstaticfilter = 1.2466136531027298e-13 * maxx * maxy * maxz * (maxz * maxz);
+
+#ifndef NDEBUG
+  // Clear the counters.
+  ori3dcount = ori3dadaptcount = 0l;
+  insphcount = insphadaptcount = insphexactcount = 0l;
+  ori4dcount = ori4dadaptcount = ori4dexactcount = 0l;
+  o3dfilterfailscount = 0l;
+  ispfilterfailscount = 0l;
+#endif // #ifndef NDEBUG
 }
 
 /*****************************************************************************/
@@ -1869,16 +1916,6 @@ REAL orient3dadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL permanent)
   REAL fin1[192], fin2[192];
   int finlength;
 
-  ////////////////////////////////////////////////////////
-  // To avoid uninitialized warnings reported by valgrind.
-  int i;
-  for (i = 0; i < 8; i++) {
-    adet[i] = bdet[i] = cdet[i] = 0.0;
-  }
-  for (i = 0; i < 16; i++) {
-    abdet[i] = 0.0;
-  }
-  ////////////////////////////////////////////////////////
 
   REAL adxtail, bdxtail, cdxtail;
   REAL adytail, bdytail, cdytail;
@@ -1916,6 +1953,10 @@ REAL orient3dadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL permanent)
   INEXACT REAL _i, _j, _k;
   REAL _0;
 
+#ifndef NDEBUG
+  ori3dadaptcount++;
+#endif // #ifndef NDEBUG
+
   adx = (REAL) (pa[0] - pd[0]);
   bdx = (REAL) (pb[0] - pd[0]);
   cdx = (REAL) (pc[0] - pd[0]);
@@ -2263,31 +2304,6 @@ REAL orient3dadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL permanent)
   return finnow[finlength - 1];
 }
 
-#ifdef INEXACT_GEOM_PRED
-
-REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd)
-{
-  REAL adx, bdx, cdx;
-  REAL ady, bdy, cdy;
-  REAL adz, bdz, cdz;
-
-  adx = pa[0] - pd[0];
-  bdx = pb[0] - pd[0];
-  cdx = pc[0] - pd[0];
-  ady = pa[1] - pd[1];
-  bdy = pb[1] - pd[1];
-  cdy = pc[1] - pd[1];
-  adz = pa[2] - pd[2];
-  bdz = pb[2] - pd[2];
-  cdz = pc[2] - pd[2];
-
-  return adx * (bdy * cdz - bdz * cdy)
-       + bdx * (cdy * adz - cdz * ady)
-       + cdx * (ady * bdz - adz * bdy);
-}
-
-#else
-
 REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd)
 {
   REAL adx, bdx, cdx, ady, bdy, cdy, adz, bdz, cdz;
@@ -2295,6 +2311,10 @@ REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd)
   REAL det;
   REAL permanent, errbound;
 
+#ifndef NDEBUG
+  ori3dcount++;
+#endif // #ifndef NDEBUG
+
   adx = pa[0] - pd[0];
   bdx = pb[0] - pd[0];
   cdx = pc[0] - pd[0];
@@ -2318,6 +2338,19 @@ REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd)
       + bdz * (cdxady - adxcdy)
       + cdz * (adxbdy - bdxady);
 
+  if (_use_inexact_arith) {
+    return det;
+  }
+
+  if (_use_static_filter) {
+    if (fabs(det) > o3dstaticfilter) return det;
+    //if (det > o3dstaticfilter) return det;
+    //if (det < minus_o3dstaticfilter) return det;
+#ifndef NDEBUG
+    o3dfilterfailscount++;
+#endif // #ifndef NDEBUG
+  }
+
   permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adz)
             + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdz)
             + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdz);
@@ -2329,8 +2362,6 @@ REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd)
   return orient3dadapt(pa, pb, pc, pd, permanent);
 }
 
-#endif // ifdef INEXACT_GEOM_PRED
-
 /*****************************************************************************/
 /*                                                                           */
 /*  incirclefast()   Approximate 2D incircle test.  Nonrobust.               */
@@ -3362,6 +3393,10 @@ REAL insphereexact(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe)
   INEXACT REAL _i, _j;
   REAL _0;
 
+#ifndef NDEBUG
+  insphexactcount++;
+#endif // #ifndef NDEBUG
+
   Two_Product(pa[0], pb[1], axby1, axby0);
   Two_Product(pb[0], pa[1], bxay1, bxay0);
   Two_Two_Diff(axby1, axby0, bxay1, bxay0, ab[3], ab[2], ab[1], ab[0]);
@@ -3938,6 +3973,10 @@ REAL insphereadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe,
   INEXACT REAL _i, _j;
   REAL _0;
 
+#ifndef NDEBUG
+  insphadaptcount++;
+#endif // #ifndef NDEBUG
+
   aex = (REAL) (pa[0] - pe[0]);
   bex = (REAL) (pb[0] - pe[0]);
   cex = (REAL) (pc[0] - pe[0]);
@@ -4114,52 +4153,6 @@ REAL insphereadapt(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe,
   return insphereexact(pa, pb, pc, pd, pe);
 }
 
-#ifdef INEXACT_GEOM_PRED
-
-REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe)
-{
-  REAL aex, bex, cex, dex;
-  REAL aey, bey, cey, dey;
-  REAL aez, bez, cez, dez;
-  REAL alift, blift, clift, dlift;
-  REAL ab, bc, cd, da, ac, bd;
-  REAL abc, bcd, cda, dab;
-
-  aex = pa[0] - pe[0];
-  bex = pb[0] - pe[0];
-  cex = pc[0] - pe[0];
-  dex = pd[0] - pe[0];
-  aey = pa[1] - pe[1];
-  bey = pb[1] - pe[1];
-  cey = pc[1] - pe[1];
-  dey = pd[1] - pe[1];
-  aez = pa[2] - pe[2];
-  bez = pb[2] - pe[2];
-  cez = pc[2] - pe[2];
-  dez = pd[2] - pe[2];
-
-  ab = aex * bey - bex * aey;
-  bc = bex * cey - cex * bey;
-  cd = cex * dey - dex * cey;
-  da = dex * aey - aex * dey;
-
-  ac = aex * cey - cex * aey;
-  bd = bex * dey - dex * bey;
-
-  abc = aez * bc - bez * ac + cez * ab;
-  bcd = bez * cd - cez * bd + dez * bc;
-  cda = cez * da + dez * ac + aez * cd;
-  dab = dez * ab + aez * bd + bez * da;
-
-  alift = aex * aex + aey * aey + aez * aez;
-  blift = bex * bex + bey * bey + bez * bez;
-  clift = cex * cex + cey * cey + cez * cez;
-  dlift = dex * dex + dey * dey + dez * dez;
-
-  return (dlift * abc - clift * dab) + (blift * cda - alift * bcd);
-}
-#else
-
 REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe)
 {
   REAL aex, bex, cex, dex;
@@ -4170,12 +4163,11 @@ REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe)
   REAL alift, blift, clift, dlift;
   REAL ab, bc, cd, da, ac, bd;
   REAL abc, bcd, cda, dab;
-  REAL aezplus, bezplus, cezplus, dezplus;
-  REAL aexbeyplus, bexaeyplus, bexceyplus, cexbeyplus;
-  REAL cexdeyplus, dexceyplus, dexaeyplus, aexdeyplus;
-  REAL aexceyplus, cexaeyplus, bexdeyplus, dexbeyplus;
   REAL det;
-  REAL permanent, errbound;
+
+#ifndef NDEBUG
+  insphcount++;
+#endif // #ifndef NDEBUG
 
   aex = pa[0] - pe[0];
   bex = pb[0] - pe[0];
@@ -4222,6 +4214,25 @@ REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe)
 
   det = (dlift * abc - clift * dab) + (blift * cda - alift * bcd);
 
+  if (_use_inexact_arith) {
+    return det;
+  }
+
+  if (_use_static_filter) {
+    if (fabs(det) > ispstaticfilter) return det;
+    //if (det > ispstaticfilter) return det;
+    //if (det < minus_ispstaticfilter) return det;
+#ifndef NDEBUG
+    ispfilterfailscount++;
+#endif // #ifndef NDEBUG
+  }
+
+  REAL aezplus, bezplus, cezplus, dezplus;
+  REAL aexbeyplus, bexaeyplus, bexceyplus, cexbeyplus;
+  REAL cexdeyplus, dexceyplus, dexaeyplus, aexdeyplus;
+  REAL aexceyplus, cexaeyplus, bexdeyplus, dexbeyplus;
+  REAL permanent, errbound;
+
   aezplus = Absolute(aez);
   bezplus = Absolute(bez);
   cezplus = Absolute(cez);
@@ -4262,8 +4273,6 @@ REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe)
   return insphereadapt(pa, pb, pc, pd, pe, permanent);
 }
 
-#endif // #ifdef INEXACT_GEOM_PRED
-
 /*****************************************************************************/
 /*                                                                           */
 /*  orient4d()   Return a positive value if the point pe lies above the      */
@@ -4327,6 +4336,10 @@ REAL orient4dexact(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
   INEXACT REAL _i, _j;
   REAL _0;
 
+#ifndef NDEBUG
+  ori4dexactcount++;
+#endif // #ifndef NDEBUG
+
   Two_Product(pa[0], pb[1], axby1, axby0);
   Two_Product(pb[0], pa[1], bxay1, bxay0);
   Two_Two_Diff(axby1, axby0, bxay1, bxay0, ab[3], ab[2], ab[1], ab[0]);
@@ -4540,6 +4553,10 @@ REAL orient4dadapt(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
   INEXACT REAL _i, _j;
   REAL _0;
 
+#ifndef NDEBUG
+  ori4dadaptcount++;
+#endif // #ifndef NDEBUG
+
   aex = (REAL) (pa[0] - pe[0]);
   bex = (REAL) (pb[0] - pe[0]);
   cex = (REAL) (pc[0] - pe[0]);
@@ -4699,108 +4716,135 @@ REAL orient4d(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
               REAL aheight, REAL bheight, REAL cheight, REAL dheight, 
               REAL eheight)
 {
-  REAL aex, bex, cex, dex;
-  REAL aey, bey, cey, dey;
-  REAL aez, bez, cez, dez;
-  REAL aexbey, bexaey, bexcey, cexbey, cexdey, dexcey, dexaey, aexdey;
-  REAL aexcey, cexaey, bexdey, dexbey;
-  REAL aeheight, beheight, ceheight, deheight;
-  REAL ab, bc, cd, da, ac, bd;
-  REAL abc, bcd, cda, dab;
-  REAL aezplus, bezplus, cezplus, dezplus;
-  REAL aexbeyplus, bexaeyplus, bexceyplus, cexbeyplus;
-  REAL cexdeyplus, dexceyplus, dexaeyplus, aexdeyplus;
-  REAL aexceyplus, cexaeyplus, bexdeyplus, dexbeyplus;
-  REAL det;
-  REAL permanent, errbound;
-
-  //orient4dcount++;
-
-  aex = pa[0] - pe[0];
-  bex = pb[0] - pe[0];
-  cex = pc[0] - pe[0];
-  dex = pd[0] - pe[0];
-  aey = pa[1] - pe[1];
-  bey = pb[1] - pe[1];
-  cey = pc[1] - pe[1];
-  dey = pd[1] - pe[1];
-  aez = pa[2] - pe[2];
-  bez = pb[2] - pe[2];
-  cez = pc[2] - pe[2];
-  dez = pd[2] - pe[2];
-  aeheight = aheight - eheight;
-  beheight = bheight - eheight;
-  ceheight = cheight - eheight;
-  deheight = dheight - eheight;
-
-  aexbey = aex * bey;
-  bexaey = bex * aey;
-  ab = aexbey - bexaey;
-  bexcey = bex * cey;
-  cexbey = cex * bey;
-  bc = bexcey - cexbey;
-  cexdey = cex * dey;
-  dexcey = dex * cey;
-  cd = cexdey - dexcey;
-  dexaey = dex * aey;
-  aexdey = aex * dey;
-  da = dexaey - aexdey;
-
-  aexcey = aex * cey;
-  cexaey = cex * aey;
-  ac = aexcey - cexaey;
-  bexdey = bex * dey;
-  dexbey = dex * bey;
-  bd = bexdey - dexbey;
-
-  abc = aez * bc - bez * ac + cez * ab;
-  bcd = bez * cd - cez * bd + dez * bc;
-  cda = cez * da + dez * ac + aez * cd;
-  dab = dez * ab + aez * bd + bez * da;
+ REAL aex, bex, cex, dex;
+ REAL aey, bey, cey, dey;
+ REAL aez, bez, cez, dez;
+ REAL aexbey, bexaey, bexcey, cexbey, cexdey, dexcey, dexaey, aexdey;
+ REAL aexcey, cexaey, bexdey, dexbey;
+ REAL aeheight, beheight, ceheight, deheight;
+ REAL ab, bc, cd, da, ac, bd;
+ REAL abc, bcd, cda, dab;
+ REAL aezplus, bezplus, cezplus, dezplus;
+ REAL aexbeyplus, bexaeyplus, bexceyplus, cexbeyplus;
+ REAL cexdeyplus, dexceyplus, dexaeyplus, aexdeyplus;
+ REAL aexceyplus, cexaeyplus, bexdeyplus, dexbeyplus;
+ REAL det;
+ REAL permanent, errbound;
+
+#ifndef NDEBUG
+ ori4dcount++;
+#endif // #ifndef NDEBUG
+
+ aex = pa[0] - pe[0];
+ bex = pb[0] - pe[0];
+ cex = pc[0] - pe[0];
+ dex = pd[0] - pe[0];
+ aey = pa[1] - pe[1];
+ bey = pb[1] - pe[1];
+ cey = pc[1] - pe[1];
+ dey = pd[1] - pe[1];
+ aez = pa[2] - pe[2];
+ bez = pb[2] - pe[2];
+ cez = pc[2] - pe[2];
+ dez = pd[2] - pe[2];
+ aeheight = aheight - eheight;
+ beheight = bheight - eheight;
+ ceheight = cheight - eheight;
+ deheight = dheight - eheight;
+
+ aexbey = aex * bey;
+ bexaey = bex * aey;
+ ab = aexbey - bexaey;
+ bexcey = bex * cey;
+ cexbey = cex * bey;
+ bc = bexcey - cexbey;
+ cexdey = cex * dey;
+ dexcey = dex * cey;
+ cd = cexdey - dexcey;
+ dexaey = dex * aey;
+ aexdey = aex * dey;
+ da = dexaey - aexdey;
+
+ aexcey = aex * cey;
+ cexaey = cex * aey;
+ ac = aexcey - cexaey;
+ bexdey = bex * dey;
+ dexbey = dex * bey;
+ bd = bexdey - dexbey;
+
+ abc = aez * bc - bez * ac + cez * ab;
+ bcd = bez * cd - cez * bd + dez * bc;
+ cda = cez * da + dez * ac + aez * cd;
+ dab = dez * ab + aez * bd + bez * da;
+
+ det = (deheight * abc - ceheight * dab) + (beheight * cda - aeheight * bcd);
+
+ aezplus = Absolute(aez);
+ bezplus = Absolute(bez);
+ cezplus = Absolute(cez);
+ dezplus = Absolute(dez);
+ aexbeyplus = Absolute(aexbey);
+ bexaeyplus = Absolute(bexaey);
+ bexceyplus = Absolute(bexcey);
+ cexbeyplus = Absolute(cexbey);
+ cexdeyplus = Absolute(cexdey);
+ dexceyplus = Absolute(dexcey);
+ dexaeyplus = Absolute(dexaey);
+ aexdeyplus = Absolute(aexdey);
+ aexceyplus = Absolute(aexcey);
+ cexaeyplus = Absolute(cexaey);
+ bexdeyplus = Absolute(bexdey);
+ dexbeyplus = Absolute(dexbey);
+ permanent = ((cexdeyplus + dexceyplus) * bezplus
+              + (dexbeyplus + bexdeyplus) * cezplus
+              + (bexceyplus + cexbeyplus) * dezplus)
+           * Absolute(aeheight)
+           + ((dexaeyplus + aexdeyplus) * cezplus
+              + (aexceyplus + cexaeyplus) * dezplus
+              + (cexdeyplus + dexceyplus) * aezplus)
+           * Absolute(beheight)
+           + ((aexbeyplus + bexaeyplus) * dezplus
+              + (bexdeyplus + dexbeyplus) * aezplus
+              + (dexaeyplus + aexdeyplus) * bezplus)
+           * Absolute(ceheight)
+           + ((bexceyplus + cexbeyplus) * aezplus
+              + (cexaeyplus + aexceyplus) * bezplus
+              + (aexbeyplus + bexaeyplus) * cezplus)
+           * Absolute(deheight);
+ errbound = isperrboundA * permanent;
+ if ((det > errbound) || (-det > errbound)) {
+   return det;
+ }
+
+ return orient4dadapt(pa, pb, pc, pd, pe,
+                      aheight, bheight, cheight, dheight, eheight, permanent);
+}
 
-  det = (deheight * abc - ceheight * dab) + (beheight * cda - aeheight * bcd);
 
-  if (0) { //if (noexact) {
-    return det;
+void predicates_statistics(int weighted)
+{
+#ifndef NDEBUG
+  printf("  Number of orient3d      tests: %ld\n", ori3dcount);
+  if (_use_static_filter) {
+    printf("  Number of static filter fails: %ld\n", o3dfilterfailscount);
   }
-
-  aezplus = Absolute(aez);
-  bezplus = Absolute(bez);
-  cezplus = Absolute(cez);
-  dezplus = Absolute(dez);
-  aexbeyplus = Absolute(aexbey);
-  bexaeyplus = Absolute(bexaey);
-  bexceyplus = Absolute(bexcey);
-  cexbeyplus = Absolute(cexbey);
-  cexdeyplus = Absolute(cexdey);
-  dexceyplus = Absolute(dexcey);
-  dexaeyplus = Absolute(dexaey);
-  aexdeyplus = Absolute(aexdey);
-  aexceyplus = Absolute(aexcey);
-  cexaeyplus = Absolute(cexaey);
-  bexdeyplus = Absolute(bexdey);
-  dexbeyplus = Absolute(dexbey);
-  permanent = ((cexdeyplus + dexceyplus) * bezplus
-               + (dexbeyplus + bexdeyplus) * cezplus
-               + (bexceyplus + cexbeyplus) * dezplus)
-            * aeheight
-            + ((dexaeyplus + aexdeyplus) * cezplus
-               + (aexceyplus + cexaeyplus) * dezplus
-               + (cexdeyplus + dexceyplus) * aezplus)
-            * beheight
-            + ((aexbeyplus + bexaeyplus) * dezplus
-               + (bexdeyplus + dexbeyplus) * aezplus
-               + (dexaeyplus + aexdeyplus) * bezplus)
-            * ceheight
-            + ((bexceyplus + cexbeyplus) * aezplus
-               + (cexaeyplus + aexceyplus) * bezplus
-               + (aexbeyplus + bexaeyplus) * cezplus)
-            * deheight;
-  errbound = isperrboundA * permanent;
-  if ((det > errbound) || (-det > errbound)) {
-    return det;
+  if (!_use_inexact_arith) {
+    printf("  Number of orient3dadapt tests: %ld\n", ori3dadaptcount);
   }
-
-  return orient4dadapt(pa, pb, pc, pd, pe,
-                       aheight, bheight, cheight, dheight, eheight, permanent);
+  if (!weighted) {
+    printf("  Number of insphere      tests: %ld\n", insphcount);
+    if (_use_static_filter) {
+      printf("  Number of static filter fails: %ld\n", ispfilterfailscount);
+    }
+    if (!_use_inexact_arith) {
+      printf("  Number of insphereadapt tests: %ld\n", insphadaptcount);
+      printf("  Number of insphereexact tests: %ld\n", insphexactcount);
+    }
+  } else {
+    printf("  Number of orient4d      tests: %ld\n", ori4dcount);
+    printf("  Number of orient4dadapt tests: %ld\n", ori4dadaptcount);
+    printf("  Number of orient4dexact tests: %ld\n", ori4dexactcount);
+  }
+#endif // #ifndef NDEBUG
 }
+
diff --git a/contrib/Tetgen1.5/tetgen.cxx b/contrib/Tetgen1.5/tetgen.cxx
index 0a66de153c7e2825e01c02a2f1fdb01be35381ed..305d61b60a420fa4be0c1064abc5375a5b2d3aac 100644
--- a/contrib/Tetgen1.5/tetgen.cxx
+++ b/contrib/Tetgen1.5/tetgen.cxx
@@ -5,11 +5,7 @@
 // A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
 //                                                                           //
 // Version 1.5                                                               //
-// February 21, 2012                                                         //
-//                                                                           //
-// PRE-RELEASE TEST CODE.                                                    //
-// PLEASE DO NOT DISTRIBUTE !!                                               //
-// PLEASE HELP ME TO IMPROVE IT !!                                           //
+// October 06, 2012                                                          //
 //                                                                           //
 // Copyright (C) 2002--2012                                                  //
 // Hang Si                                                                   //
@@ -335,6 +331,10 @@ bool tetgenio::load_edge(char* filebasename)
       }
       edgelist[index++] = corner;
     }
+    if (numberofcorners == 10) {
+      // Skip an extra vertex (generated by a previous -o2 option).
+      stringptr = findnextnumber(stringptr);
+    }
     // Read the edge marker if it has.
     if (markers) {
       stringptr = findnextnumber(stringptr);
@@ -419,6 +419,12 @@ bool tetgenio::load_face(char* filebasename)
       }
       trifacelist[index++] = corner;
     }
+    if (numberofcorners == 10) {
+      // Skip 3 extra vertices (generated by a previous -o2 option).
+      for (j = 0; j < 3; j++) {
+        stringptr = findnextnumber(stringptr);
+      }
+    }
     // Read the boundary marker if it exists.
     if (markers) {
       stringptr = findnextnumber(stringptr);
@@ -627,7 +633,6 @@ bool tetgenio::load_var(char* filebasename)
   if (infile != (FILE *) NULL) {
     printf("Opening %s.\n", varfilename);
   } else {
-    // No such file. Ignore it without a message.
     return false;
   }
 
@@ -740,7 +745,6 @@ bool tetgenio::load_mtr(char* filebasename)
   if (infile != (FILE *) NULL) {
     printf("Opening %s.\n", mtrfilename);
   } else {
-    // No such file. Return.
     return false;
   }
 
@@ -1381,14 +1385,11 @@ bool tetgenio::load_off(char* filebasename)
     return false;
   }
 
-  // Check whether read all points
   if (iverts != nverts) {
     printf("Expected %d vertices, but read only %d vertices in file %s\n",
            nverts, iverts, infilename);
     return false;
   }
-
-  // Check whether read all faces
   if (ifaces != nfaces) {
     printf("Expected %d faces, but read only %d faces in file %s\n",
            nfaces, ifaces, infilename);
@@ -1603,14 +1604,11 @@ bool tetgenio::load_ply(char* filebasename)
     return false;
   }
 
-  // Check whether read all points
   if (iverts != nverts) {
     printf("Expected %d vertices, but read only %d vertices in file %s\n",
            nverts, iverts, infilename);
     return false;
   }
-
-  // Check whether read all faces
   if (ifaces != nfaces) {
     printf("Expected %d faces, but read only %d faces in file %s\n",
            nfaces, ifaces, infilename);
@@ -2389,6 +2387,7 @@ bool tetgenio::load_plc(char* filebasename, int object)
   }
 
   if (success) {
+    // Try to load the following files (.edge, .var, .mtr).
     load_edge(filebasename);
     load_var(filebasename);
     load_mtr(filebasename);
@@ -2415,6 +2414,7 @@ bool tetgenio::load_tetmesh(char* filebasename, int object)
       success = load_tet(filebasename);
     }
     if (success) {
+      // Try to load the following files (.face, .edge, .vol).
       load_face(filebasename);
       load_edge(filebasename);
       load_vol(filebasename);
@@ -2422,6 +2422,7 @@ bool tetgenio::load_tetmesh(char* filebasename, int object)
   }
 
   if (success) {
+    // Try to load the following files (.var, .mtr).
     load_var(filebasename);
     load_mtr(filebasename);
   }
@@ -2902,16 +2903,22 @@ char* tetgenio::findnextnumber(char *string)
 
 void tetgenbehavior::syntax()
 {
-  printf("  tetgen [-pYrq_a_AiS_T_dzfenvgKJBNEFICQVh] input_file\n");
+  printf("  tetgen [-pYq_Aa_mriO_S_T_XMwcdzfenvgKJBNEFICQVh] input_file\n");
   printf("    -p  Tetrahedralizes a piecewise linear complex (PLC).\n");
-  printf("    -Y  No splitting of input boundaries (facets and segments).\n");
-  printf("    -r  Reconstructs a previously generated mesh.\n");
+  printf("    -Y  Preserves the input surface mesh (does not modify it).\n");
   printf("    -q  Refines mesh (to improve mesh quality).\n");
-  printf("    -a  Applies a maximum tetrahedron volume constraint.\n");
   printf("    -A  Assigns attributes to tetrahedra in different regions.\n");
-  printf("    -i  Inserts a list of additional points into mesh.\n");
+  printf("    -a  Applies a maximum tetrahedron volume constraint.\n");
+  printf("    -m  Applies a mesh sizing function.\n");
+  printf("    -r  Reconstructs a previously generated mesh.\n");
+  printf("    -i  Inserts a list of additional points.\n");
+  printf("    -O  Specifies the level of mesh optimization.\n");
   printf("    -S  Specifies maximum number of added points.\n");
   printf("    -T  Sets a tolerance for coplanar test (default 1e-8).\n");
+  printf("    -X  Suppresses use of exact arithmetic.\n");
+  printf("    -M  No merge of coplanar facets.\n");
+  printf("    -w  Generates weighted Delaunay (regular) triangulation.\n");
+  printf("    -c  Retains the convex hull of the PLC.\n");
   printf("    -d  Detects self-intersections of facets of the PLC.\n");
   printf("    -z  Numbers all output items starting from zero.\n");
   printf("    -f  Outputs all faces to .face file.\n");
@@ -3004,19 +3011,6 @@ void tetgenbehavior::usage()
 // of a C/C++ program. They together represent the command line user invoked //
 // from an environment in which TetGen is running.                           //
 //                                                                           //
-// When TetGen is invoked from an environment. 'argc' is nonzero, switches   //
-// and input filename should be supplied as zero-terminated strings in       //
-// argv[0] through argv[argc - 1] and argv[0] shall be the name used to      //
-// invoke TetGen, i.e. "tetgen".  Switches are previously started with a     //
-// dash '-' to identify them from the input filename.                        //
-//                                                                           //
-// When TetGen is called from within another program. 'argc' is set to zero. //
-// switches are given in one zero-terminated string (no previous dash is     //
-// required.), and 'argv' is a pointer points to this string.  No input      //
-// filename is required (usually the input data has been directly created by //
-// user in the 'tetgenio' structure).  A default filename 'tetgen-tmpfile'   //
-// will be created for debugging output purpose.                             //
-//                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
 bool tetgenbehavior::parse_commandline(int argc, char **argv)
@@ -3024,7 +3018,6 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
   int startindex;
   int increment;
   int meshnumber;
-  int scount, ocount;
   int i, j, k;
   char workstring[1024];
 
@@ -3038,12 +3031,9 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
     strcpy(commandline, argv[0]);
     strcat(commandline, " ");
   }
-  
-  // Count the number of '-O' and '-o' be used.
-  scount = ocount = 0;
 
   for (i = startindex; i < argc; i++) {
-    // Remember the command line switches.
+    // Remember the command line for output.
     strcat(commandline, argv[i]);
     strcat(commandline, " ");
     if (startindex == 1) {
@@ -3051,7 +3041,6 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
       if (argv[i][0] != '-') {
         strncpy(infilename, argv[i], 1024 - 1);
         infilename[1024 - 1] = '\0';
-        // Go to the next string directly.
         continue;                     
       }
     }
@@ -3072,11 +3061,17 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
           facet_ang_tol = (REAL) strtod(workstring, (char **) NULL);
         }
       } else if (argv[i][j] == 's') {
-        psc = 1;        
+        psc = 1;
+      } else if (argv[i][j] == 'Y') {
+        nobisect = 1;
+        if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
+          nobisect_param = (argv[i][j + 1] - '0');
+          j++;
+        }
       } else if (argv[i][j] == 'r') {
-        refine++;
+        refine = 1;
       } else if (argv[i][j] == 'q') {
-        quality++;
+        quality = 1;
         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
             (argv[i][j + 1] == '.')) {
           k = 0;
@@ -3087,42 +3082,56 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
             k++;
           }
           workstring[k] = '\0';
-          if (quality == 1) { // -q#
-            minratio = (REAL) strtod(workstring, (char **) NULL);
-          } else if (quality == 2) { // -qq#
+          minratio = (REAL) strtod(workstring, (char **) NULL);
+        }
+        if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) {
+          j++;
+          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';
             mindihedral = (REAL) strtod(workstring, (char **) NULL);
           }
         }
-      } else if (argv[i][j] == 'm') {
-        metric++;
-      } else if (argv[i][j] == 'Y') {
-        nobisect = 1;
-        if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-            (argv[i][j + 1] == '.')) {
-          k = 0;
-          while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-                 (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e')) {
-            j++;
-            workstring[k] = argv[i][j];
-            k++;
+        if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) {
+          j++;
+          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';
+            optmaxdihedral = (REAL) strtod(workstring, (char **) NULL);
           }
-          workstring[k] = '\0';
-          nobisect_param = (int) strtol(workstring, (char **) NULL, 0);
         }
       } else if (argv[i][j] == 'w') {
         weighted = 1;
-        if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-            (argv[i][j + 1] == '.')) {
-          k = 0;
-          while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-                 (argv[i][j + 1] == '.')) {
-            j++;
-            workstring[k] = argv[i][j];
-            k++;
-          }
-          workstring[k] = '\0';
-          weighted_param = (int) strtol(workstring, (char **) NULL, 0);
+        if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
+          weighted_param = (argv[i][j + 1] - '0');
+          j++;
         }
+      } else if (argv[i][j] == 'b') {
+        brio_hilbert = 1;
+        if (argv[i][j + 1] == '0') { // -b0
+          brio_hilbert = 0; // Turn off BRIO sorting.
+          j++;
+        }
+      } else if (argv[i][j] == 'l') {
+        incrflip = 1;
+      } else if (argv[i][j] == 'L') {
+        flipinsert = 1;
+      } else if (argv[i][j] == 'm') {
+        metric = 1;
       } else if (argv[i][j] == 'a') {
         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
             (argv[i][j + 1] == '.')) {
@@ -3141,71 +3150,32 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
           varvolume = 1;
         }
       } else if (argv[i][j] == 'A') {
-        regionattrib++;
-      } else if (argv[i][j] == 'l') {
-        incrflip = 1;
-        // Check if a smallest edge length is given. 
-        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';
-          minedgelength = (REAL) strtod(workstring, (char **) NULL);
-        }
-      } else if (argv[i][j] == 'L') {
-        flipinsert++;
-        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 (flipinsert == 1) { // -L
-            fliplinklevel = (int) strtol(workstring, (char **) NULL, 0);
-          } else if (flipinsert == 2) { // -LL
-            flipstarsize = (int) strtol(workstring, (char **) NULL, 0);
-          }
-        }
-      } else if (argv[i][j] == 'u') {
-        // Set the maximum btree node size, -u0 means do not use btree.
-        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';
-          max_btreenode_size = (int) strtol(workstring, (char **) NULL, 0);
-        }
-        if (max_btreenode_size == 0) {
-          btree = 0;
+        regionattrib = 1;
+      } else if (argv[i][j] == 'D') {
+        conforming = 1;
+        if ((argv[i][j + 1] >= '1') && (argv[i][j + 1] <= '3')) {
+          reflevel = (argv[i][j + 1] - '1') + 1; 
+          j++;
         }
-      } else if (argv[i][j] == 'U') {
-        hilbertcurve = 1;
-        btree = 0;
       } else if (argv[i][j] == 'i') {
         insertaddpoints = 1;
       } else if (argv[i][j] == 'd') {
         diagnose = 1;
       } else if (argv[i][j] == 'c') {
         convex = 1;
+      } else if (argv[i][j] == 'M') {
+        nomerge = 1;
+      } else if (argv[i][j] == 'X') {
+        if (argv[i][j + 1] == '1') {
+          nostaticfilter = 1;
+          j++;
+        } else {
+          noexact = 1;
+        }
       } else if (argv[i][j] == 'z') {
         zeroindex = 1;
       } else if (argv[i][j] == 'f') {
-        facesout = 1;
+        facesout++;
       } else if (argv[i][j] == 'e') {
         edgesout++;
       } else if (argv[i][j] == 'n') {
@@ -3214,10 +3184,8 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
         voroout = 1;
       } else if (argv[i][j] == 'g') {
         meditview = 1;
-      } else if (argv[i][j] == 'K') {
+      } else if (argv[i][j] == 'k') {
         vtkview = 1;  
-      } else if (argv[i][j] == 'M') {
-        nomerge = 1;
       } else if (argv[i][j] == 'J') {
         nojettison = 1;
       } else if (argv[i][j] == 'B') {
@@ -3226,10 +3194,6 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
         nonodewritten = 1;
       } else if (argv[i][j] == 'E') {
         noelewritten = 1;
-        if (argv[i][j + 1] == '2') {
-          j++;
-          noelewritten = 2;
-        }
       } else if (argv[i][j] == 'F') {
         nofacewritten = 1;
       } else if (argv[i][j] == 'I') {
@@ -3249,65 +3213,36 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
           steinerleft = (int) strtol(workstring, (char **) NULL, 0);
         }
       } else if (argv[i][j] == 'o') {
-        ocount++;
-        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 (ocount == 1) { // -o#
+        if (argv[i][j + 1] == '2') {
+          order = 2;
+          j++;
+        }
+        if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) {
+          j++;
+          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';
             optmaxdihedral = (REAL) strtod(workstring, (char **) NULL);
-          } else if (ocount == 2) { // -oo#
-            optminsmtdihed = (REAL) strtod(workstring, (char **) NULL);
-          } else if (ocount == 3) { // -ooo#
-            optminslidihed = (REAL) strtod(workstring, (char **) NULL);
-          } 
+          }
         }
       } else if (argv[i][j] == 'O') {
-        scount++;
-        if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-            (argv[i][j + 1] == '.')) {
-          k = 0;
-          while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-                 (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
-                 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
-            j++;
-            workstring[k] = argv[i][j];
-            k++;
-          }
-          workstring[k] = '\0';
-          if (scount == 1) { // -O
-            optlevel = (int) strtol(workstring, (char **) NULL, 0);
-          } else if (scount == 2) { // -OO
-            optpasses = (int) strtol(workstring, (char **) NULL, 0);
-          } else if (scount == 3) { // -OOO
-            optmaxfliplevel = (int) strtol(workstring, (char **) NULL, 0);
-          } else if (scount == 4) { // -OOOO
-            delmaxfliplevel = (int) strtol(workstring, (char **) NULL, 0);
-          } else if (scount == 5) { // -OOOOO (5 Os)
-            optmaxflipstarsize = (int) strtol(workstring, (char **) NULL, 0);
-          }
+        if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
+          optlevel = (argv[i][j + 1] - '0');
+          j++;
         }
-      } else if (argv[i][j] == 'D') {
-        conforming = 1;
-        if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-            (argv[i][j + 1] == '.')) {
-          k = 0;
-          while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-                 (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
-                 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
+        if ((argv[i][j + 1] == '/') || (argv[i][j + 1] == ',')) {
+          j++;
+          if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '7')) {
+            optscheme = (argv[i][j + 1] - '0');
             j++;
-            workstring[k] = argv[i][j];
-            k++;
           }
-          workstring[k] = '\0';
-          reflevel = (int) strtol(workstring, (char **) NULL, 0);
         }
       } else if (argv[i][j] == 'T') {
         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
@@ -3323,6 +3258,8 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
           workstring[k] = '\0';
           epsilon = (REAL) strtod(workstring, (char **) NULL);
         }
+      } else if (argv[i][j] == 'R') {
+        reversetetori = 1;
       } else if (argv[i][j] == 'C') {
         docheck++;
       } else if (argv[i][j] == 'Q') {
@@ -3395,6 +3332,10 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
   if (diagnose && !plc) { // -d
     plc = 1;
   }
+  if (plc && !quality && !nobisect) { // -p only
+    // Create a CDT, do not do mesh optimization.
+    optlevel = 0;
+  }
 
   // Detect improper combinations of switches.
   if (plc && refine) {
@@ -3430,18 +3371,16 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
       }
     }
   }
-  if (ocount == 0) {
-    // No user-specified dihedral angle bound. Use default ones.
-    if (!quality) {
-      if (optmaxdihedral < 179.0) {
-        optmaxdihedral = 179.0;
-      }
-      if (optminsmtdihed < 179.999) {
-        optminsmtdihed = 179.999;
-      }
-      if (optminslidihed < 179.999) {
-        optminslidihed = 179.99;
-      }
+  // No user-specified dihedral angle bound. Use default ones.
+  if (!quality) {
+    if (optmaxdihedral < 179.0) {
+      optmaxdihedral = 179.0;
+    }
+    if (optminsmtdihed < 179.999) {
+      optminsmtdihed = 179.999;
+    }
+    if (optminslidihed < 179.999) {
+      optminslidihed = 179.999;
     }
   }
 
@@ -3500,10 +3439,8 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
 int tetgenmesh::mod12[36] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
                              0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
                              0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
-
-int tetgenmesh::mod6[18] = {0, 1, 2, 3, 4, 5,
-                            0, 1, 2, 3, 4, 5,
-                            0, 1, 2, 3, 4, 5};
+int tetgenmesh::mod6[18]  = {0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5,
+                             0, 1, 2, 3, 4, 5};
 
 // Table 'edgepivot' takes an directed edge (version) as input, returns the
 //   inversed edge (version) of it.
@@ -3542,8 +3479,6 @@ int tetgenmesh::sapexpivot[6] = {5, 5, 3, 3, 4, 4};
 
 int tetgenmesh::epivot[4] = {4, 5, 2, 11};
 
-
-
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // restart()    Deallocate all objects in this pool.                         //
@@ -4026,8 +3961,6 @@ void* tetgenmesh::memorypool::traverse()
   return newitem;
 }
 
-
-
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // makeindex2pointmap()    Create a map from index to vertices.              //
@@ -4059,7 +3992,6 @@ void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
   }
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // makesubfacemap()    Create a map from vertex to subfaces incident at it.  //
@@ -4163,15 +4095,13 @@ void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
   //   dead tetrahedra when traversing the list of all tetrahedra.
   dyingtetrahedron[4] = (tetrahedron) NULL;
 
-  //if (b->plc || b->refine) { //if (b->useshelles) {
-    // Dealloc the space to subfaces/subsegments.
-    if (dyingtetrahedron[8] != NULL) {
-      tet2segpool->dealloc((shellface *) dyingtetrahedron[8]);
-    }
-    if (dyingtetrahedron[9] != NULL) {
-      tet2subpool->dealloc((shellface *) dyingtetrahedron[9]);
-    }
-  //}
+  // Dealloc the space to subfaces/subsegments.
+  if (dyingtetrahedron[8] != NULL) {
+    tet2segpool->dealloc((shellface *) dyingtetrahedron[8]);
+  }
+  if (dyingtetrahedron[9] != NULL) {
+    tet2subpool->dealloc((shellface *) dyingtetrahedron[9]);
+  }
 
   tetrahedrons->dealloc((void *) dyingtetrahedron);
 }
@@ -4319,6 +4249,7 @@ tetgenmesh::point tetgenmesh::pointtraverse()
 void tetgenmesh::maketetrahedron(triface *newtet)
 {
   newtet->tet = (tetrahedron *) tetrahedrons->alloc();
+
   // Initialize the four adjoining tetrahedra to be "outer space".
   newtet->tet[0] = NULL;
   newtet->tet[1] = NULL;
@@ -4332,9 +4263,9 @@ void tetgenmesh::maketetrahedron(triface *newtet)
   // No attached segments and sbfaces yet.
   newtet->tet[8] = NULL; 
   newtet->tet[9] = NULL; 
-  // Initialize the marker (for flags).
+  // Initialize the marker (clear all flags).
   setelemmarker(newtet->tet, 0);
-  for (int i = 0; i < in->numberoftetrahedronattributes; i++) {
+  for (int i = 0; i < numelemattrib; i++) {
     setelemattribute(newtet->tet, i, 0.0);
   }
   if (b->varvolume) {
@@ -4355,6 +4286,7 @@ void tetgenmesh::maketetrahedron(triface *newtet)
 void tetgenmesh::makeshellface(memorypool *pool, face *newface)
 {
   newface->sh = (shellface *) pool->alloc();
+
   // No adjointing subfaces.
   newface->sh[0] = NULL;
   newface->sh[1] = NULL;
@@ -4382,7 +4314,7 @@ void tetgenmesh::makeshellface(memorypool *pool, face *newface)
   setshellmark(*newface, 0);
   // Set the default face type.
   setshelltype(*newface, NSHARP);
-  // Initialize the version to be Zero.
+
   newface->shver = 0;
 }
 
@@ -4394,9 +4326,14 @@ void tetgenmesh::makeshellface(memorypool *pool, face *newface)
 
 void tetgenmesh::makepoint(point* pnewpoint, enum verttype vtype)
 {
-  int ptmark, i;
+  int i;
 
   *pnewpoint = (point) points->alloc();
+
+  // Initialize the point attributes.
+  for (i = 0; i < numpointattrib; i++) {
+    (*pnewpoint)[3 + i] = 0.0;
+  }
   // Initialize the metric tensor.
   for (i = 0; i < sizeoftensor; i++) {
     (*pnewpoint)[pointmtrindex + i] = 0.0;
@@ -4411,8 +4348,8 @@ void tetgenmesh::makepoint(point* pnewpoint, enum verttype vtype)
     }
   }
   // Initialize the point marker (starting from in->firstnumber).
-  ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
-  setpointmark(*pnewpoint, ptmark);
+  i = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
+  setpointmark(*pnewpoint, i);
   // Initialize the point type.
   setpointtype(*pnewpoint, vtype);
   // Clear the point flags.
@@ -4447,22 +4384,43 @@ void tetgenmesh::initializepools()
     printf("  Initializing memorypools.\n");
   }
 
+  // There are three input point lists available, which are in, addin,
+  //   and bgm->in. These point lists may have different number of 
+  //   attributes. Decide the maximum number.
+  numpointattrib = in->numberofpointattributes;
+  if (bgm != NULL) {
+    if (bgm->in->numberofpointattributes > numpointattrib) {
+      numpointattrib = bgm->in->numberofpointattributes;
+    }
+  }
+  if (addin != NULL) {
+    if (addin->numberofpointattributes > numpointattrib) {
+      numpointattrib = addin->numberofpointattributes;
+    }
+  }
+  if (b->weighted || b->flipinsert) { // -w or -L.
+    // The internal number of point attribute needs to be at least 1
+    //   (for storing point weights).
+    if (numpointattrib == 0) {    
+      numpointattrib = 1;
+    }
+  }
+
   // Default varconstraint = 0;
   if (in->segmentconstraintlist || in->facetconstraintlist) {
     checkconstraints = 1;
   }
 
-  // Each vertex has three coordinates plus a weight, hence 4 REALs.
   // The index within each point at which its metric tensor is found. 
+  // Each vertex has three coordinates.
   if (b->psc) {
-    // For '-s' option (PSC), the u,v coordinates are provided. It is
-    //   saved directly after the list of point attributes.
-    pointmtrindex = 6 + in->numberofpointattributes;
+    // '-s' option (PSC), the u,v coordinates are provided.
+    pointmtrindex = 5 + numpointattrib;
   } else {
-    pointmtrindex = 4 + in->numberofpointattributes;
+    pointmtrindex = 3 + numpointattrib;
   }
   // The index within each point at which its u, v coordinates are found.
-  pointparamindex = pointmtrindex - 2; 
+  pointparamindex = 3 + (numpointattrib > 0);
   // For '-m' option. A tensor field is provided (*.mtr or *.b.mtr file).
   if (b->metric) {
     // Decide the size (1, 3, or 6) of the metric tensor.
@@ -4491,19 +4449,11 @@ void tetgenmesh::initializepools()
     //   - a pointer to a parent point, read by point2ppt()).
     //   - a pointer to a subface or segment, read by point2sh();
     if (b->metric && (bgm != (tetgenmesh *) NULL)) {
-      // Increase one pointer to into the background mesh, point2bgmtet().
+      // Increase one pointer into the background mesh, point2bgmtet().
       pointsize = (point2simindex + 4) * sizeof(tetrahedron);
     } else {
       pointsize = (point2simindex + 3) * sizeof(tetrahedron);
     }
-    // The index within each point at which a pbc point is found.
-    point2pbcptindex = (pointsize + sizeof(tetrahedron) - 1)
-                     / sizeof(tetrahedron);
-    if (checkpbcs) {
-      // Increase the size by one pointer to a corresponding pbc point,
-      //   read by point2pbcpt().
-      pointsize = (point2pbcptindex + 1) * sizeof(tetrahedron);
-    }
   } else {
     // Increase the point size by two pointer, which are:
     //   - a pointer to a tet, read by point2tet();
@@ -4517,7 +4467,6 @@ void tetgenmesh::initializepools()
   //   - an integer for boundary marker;
   //   - an integer for vertex type;
   //   - an integer for geometry tag (optional, -s option).
-  //pointsize = (pointmarkindex + 2)*sizeof(int); // Wrong for 64 bit system.
   pointsize = (pointmarkindex + 2 + (b->psc ? 1 : 0)) * sizeof(tetrahedron);
 
   // Decide the wordtype used in vertex pool.
@@ -4558,19 +4507,21 @@ void tetgenmesh::initializepools()
   assert((sizeof(tetrahedron) % sizeof(int)) == 0);
   elemmarkerindex = (elesize - sizeof(tetrahedron)) / sizeof(int);
 
+  // The actual number of element attributes. Note that if the
+  //   `b->regionattrib' flag is set, an additional attribute will be added.
+  numelemattrib = in->numberoftetrahedronattributes + (b->regionattrib > 0);
+
   // The index within each element at which its attributes are found, where
   //   the index is measured in REALs. 
   elemattribindex = (elesize + sizeof(REAL) - 1) / sizeof(REAL);
   // The index within each element at which the maximum voulme bound is
-  //   found, where the index is measured in REALs.  Note that if the
-  //   `b->regionattrib' flag is set, an additional attribute will be added.
-  volumeboundindex = elemattribindex + in->numberoftetrahedronattributes
-                   + (b->regionattrib > 0);
+  //   found, where the index is measured in REALs.
+  volumeboundindex = elemattribindex + numelemattrib;
   // If element attributes or an constraint are needed, increase the number
   //   of bytes occupied by an element.
   if (b->varvolume) {
     elesize = (volumeboundindex + 1) * sizeof(REAL);
-  } else if (in->numberoftetrahedronattributes + b->regionattrib > 0) {
+  } else if (numelemattrib > 0) {
     elesize = volumeboundindex * sizeof(REAL);
   }
 
@@ -4604,7 +4555,7 @@ void tetgenmesh::initializepools()
     shmarkindex = (shsize + sizeof(int) - 1) / sizeof(int);
     // Increase the number of bytes by two or three integers, one for facet
     //   marker, one for shellface type, and optionally one for pbc group.
-    shsize = (shmarkindex + 2 + checkpbcs) * sizeof(shellface);
+    shsize = (shmarkindex + 2) * sizeof(shellface);
 
     // Initialize the pool of subfaces. Each subface record is eight-byte
     //   aligned so it has room to store an edge version (from 0 to 5) in
@@ -4648,7 +4599,7 @@ void tetgenmesh::initializepools()
     caveencseglist = new arraypool(sizeof(face), 8);
   }
 
-  // Initialize the pool for flips.
+  // Initialize the pools for flips.
   flippool = new memorypool(sizeof(badface), 1024, memorypool::POINTER, 0);
   unflipqueue = new arraypool(sizeof(badface), 10);
 
@@ -5872,8 +5823,6 @@ REAL tetgenmesh::insphere_s(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe)
 {
   REAL sign;
 
-  inspherecount++;
-
   sign = insphere(pa, pb, pc, pd, pe);
   if (sign != 0.0) {
     return sign;
@@ -5947,15 +5896,13 @@ REAL tetgenmesh::orient4d_s(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
 {
   REAL sign;
 
-  inspherecount++;
-
   sign = orient4d(pa, pb, pc, pd, pe, 
                   aheight, bheight, cheight, dheight, eheight);
   if (sign != 0.0) {
     return sign;
   }
 
-  insphere_sos_count++;
+  orient4d_sos_count++;
 
   // Symbolic perturbation.
   point pt[5], swappt;
@@ -6000,7 +5947,6 @@ REAL tetgenmesh::orient4d_s(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
   return oriB;
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // facenormal()    Calculate the normal of the face.                         //
@@ -6108,7 +6054,6 @@ REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2)
   return sqrt(dot(v2, v2) - l_p * l_p);
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // triarea()    Return the area of a triangle.                               //
@@ -6205,9 +6150,7 @@ void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj)
   v2[2] = p[2] - e1[2];
 
   len = sqrt(dot(v1, v1));
-#ifdef SELF_CHECK
   assert(len != 0.0);
-#endif
   v1[0] /= len;
   v1[1] /= len;
   v1[2] /= len;
@@ -6249,7 +6192,6 @@ void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj)
   prj[2] = p[2] - dist * fnormal[2];
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // facedihedral()    Return the dihedral angle (in radian) between two       //
@@ -6559,7 +6501,59 @@ bool tetgenmesh::circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
   return true;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// orthosphere()    Calulcate the orthosphere of four weighted points.       //
+//                                                                           //
+// A weighted point (p, P^2) can be interpreted as a sphere centered at the  //
+// point 'p' with a radius 'P'. The 'height' of 'p' is pheight = p[0]^2 +    //
+// p[1]^2 + p[2]^2 - P^2.                                                    //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+bool tetgenmesh::orthosphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
+                             REAL  aheight, REAL bheight, REAL cheight, 
+                             REAL  dheight, REAL* orthocent, REAL* radius)
+{
+  REAL A[4][4], rhs[4], D;
+  int indx[4];
+
+  // Set the coefficient matrix A (4 x 4).
+  A[0][0] = 1.0; A[0][1] = pa[0]; A[0][2] = pa[1]; A[0][3] = pa[2];
+  A[1][0] = 1.0; A[1][1] = pb[0]; A[1][2] = pb[1]; A[1][3] = pb[2];
+  A[2][0] = 1.0; A[2][1] = pc[0]; A[2][2] = pc[1]; A[2][3] = pc[2];
+  A[3][0] = 1.0; A[3][1] = pd[0]; A[3][2] = pd[1]; A[3][3] = pd[2];
+
+  // Set the right hand side vector (4 x 1).
+  rhs[0] = 0.5 * aheight;
+  rhs[1] = 0.5 * bheight;
+  rhs[2] = 0.5 * cheight;
+  rhs[3] = 0.5 * dheight;
+
+  // Solve the 4 by 4 equations use LU decomposition with partial pivoting
+  //   and backward and forward substitute..
+  if (!lu_decmp(A, 4, indx, &D, 0)) {
+    if (radius != (REAL *) NULL) *radius = 0.0;
+    return false;
+  }
+  lu_solve(A, 4, indx, rhs, 0);
 
+  if (orthocent != (REAL *) NULL) {
+    orthocent[0] = rhs[1];
+    orthocent[1] = rhs[2];
+    orthocent[2] = rhs[3];
+  }
+  if (radius != (REAL *) NULL) {
+    // rhs[0] = - rheight / 2;
+    // rheight  = - 2 * rhs[0];
+    //          =  r[0]^2 + r[1]^2 + r[2]^2 - radius^2
+    // radius^2 = r[0]^2 + r[1]^2 + r[2]^2 -rheight
+    //          = r[0]^2 + r[1]^2 + r[2]^2 + 2 * rhs[0]
+    *radius = sqrt(rhs[1] * rhs[1] + rhs[2] * rhs[2] + rhs[3] * rhs[3]
+                   + 2.0 * rhs[0]);
+  }
+  return true;
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
@@ -6607,8 +6601,6 @@ void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
   }
 }
 
-
-
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // tetprismvol()    Calculate the volume of a tetrahedral prism in 4D.       //
@@ -6711,7 +6703,7 @@ void tetgenmesh::flippush(badface*& fstack, triface* flipface)
 // If 'flipflag = 1', it is in the process of incrmental flip DT algorithm,  //
 // and we assume that 'd' must be the newly inserted vertex.  In such case,  //
 // only the link faces at 'd', i.e., three faces [a,b,e], [b,c,e], and [c,a, //
-// e] needs to be queued, see [Edelsbrunner & Shah'1996] and [M\"ucke'1998]. //
+// e] needs to be queued ([Edelsbrunner & Shah'1996] and [M\"ucke'1998]).    //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -6725,6 +6717,7 @@ void tetgenmesh::flip23(triface* fliptets, int hullflag, int flipflag,
   badface *bface; // used by chkencflag
   point pa, pb, pc, pd, pe;
   REAL volneg[2], volpos[3], vol_diff; // volumes of involved tet-prisms.
+  REAL attrib, volume;
   int dummyflag = 0;  // range = {-1, 0, 1, 2}.
   int i;
 
@@ -6779,6 +6772,7 @@ void tetgenmesh::flip23(triface* fliptets, int hullflag, int flipflag,
   fliptets[1].ver = 11;
   setelemmarker(fliptets[0].tet, 0); // Clear all flags.
   setelemmarker(fliptets[1].tet, 0);
+  // NOTE: the element attributes and volume constraint remain unchanged.
   if (checksubsegflag) {
     // Dealloc the space to subsegments.
     if (fliptets[0].tet[8] != NULL) {
@@ -6803,6 +6797,15 @@ void tetgenmesh::flip23(triface* fliptets, int hullflag, int flipflag,
   }
   // Create a new tet.
   maketetrahedron(&(fliptets[2]));
+  // The new tet have the same attributes from the old tet.
+  for (i = 0; i < numelemattrib; i++) {
+    attrib = elemattribute(fliptets[0].tet, i);
+    setelemattribute(fliptets[2].tet, i, attrib);
+  }
+  if (b->varvolume) {
+    volume = volumebound(fliptets[0].tet);
+    setvolumebound(fliptets[2].tet, volume);
+  }
 
   if (hullflag > 0) {
     // Check if d is dummytet.
@@ -7039,17 +7042,13 @@ void tetgenmesh::flip23(triface* fliptets, int hullflag, int flipflag,
 
   if (flipflag > 0) {
     // Queue faces which may be locally non-Delaunay.  
-    //pd = dest(fliptets[0]); // 'd' may be a new vertex.
     for (i = 0; i < 3; i++) {
       eprevesym(fliptets[i], newface);
-      //flippush(flipstack, &newface, pd);
       flippush(flipstack, &newface);
     }
     if (flipflag > 1) {
-      //pe = org(fliptets[0]);
       for (i = 0; i < 3; i++) {
         enextesym(fliptets[i], newface);
-        //flippush(flipstack, &newface, pe);
         flippush(flipstack, &newface);
       }
     }
@@ -7082,8 +7081,18 @@ void tetgenmesh::flip23(triface* fliptets, int hullflag, int flipflag,
 // If 'flipflag = 1', it is in the process of incrmental flip DT algorithm,  //
 // and we assume that 'a' must be the newly inserted vertex.  In such case,  //
 // only the link faces at 'a', i.e., two faces [c,b,d] and [b,c,e] needs to  //
-// be queued, refer to [Edelsbrunner & Shah'1996] and [M\"ucke'1998].        //
+// be queued ( [Edelsbrunner & Shah'1996] and [M\"ucke'1998]).               //
 //                                                                           //
+// If 'checksubfaceflag' is on (global variable), and assume [e,d] is not a  //
+// segment. There may be two (interior) subfaces sharing at [e,d], which are //
+// [e,d,p] and [e,d,q], where the pair (p,q) may be either (a,b), or (b,c),  //
+// or (c,a)  In such case, a 2-to-2 flip is performed on these two subfaces  //
+// and two new subfaces [p,q,e] and [p,q,d] are created. They are inserted   //
+// back into the tetrahedralization.  However, it is possible that the new   //
+// subface ([p,q,e] or [p,q,d] already exists. In such case, we just delete  //
+// the conflict subface. As a result, either 'd' or 'e' is removed from the  //
+// surface mesh.  A better solution would be to detect and perform a 3-to-1  //
+// flip to remove 'd' or 'e' (see also 2011-11-15).                          //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -7097,8 +7106,9 @@ void tetgenmesh::flip32(triface* fliptets, int hullflag, int flipflag,
   badface *bface; // used by chkencflag
   point pa, pb, pc, pd, pe;
   REAL volneg[3], volpos[2], vol_diff; // volumes of involved tet-prisms.
+  REAL attrib, volume;
   int dummyflag = 0;  // Rangle = {-1, 0, 1, 2}
-  int i;
+  int i, j;
 
   // For 2-to-2 flip (subfaces).
   face flipshs[3], flipfaces[2];
@@ -7186,6 +7196,28 @@ void tetgenmesh::flip32(triface* fliptets, int hullflag, int flipflag,
   fliptets[1].ver = 11;
   setelemmarker(fliptets[0].tet, 0); // Clear all flags.
   setelemmarker(fliptets[1].tet, 0);
+  // NOTE: the element attributes and volume constraint must be set correctly.
+  if (checksubfaceflag) {
+    if (scount > 0) {
+      // There are two subfaces involved in this flip. The three tets are
+      //   separated into two different regions, one may be exterior. The
+      //   first region has two tets, and the second region has only one.
+      //   The two created tets must be in the same region as the first region. 
+      //   The element attributes and volume constraint must be set correctly.
+      //assert(spivot != -1);
+      // The tet fliptets[spivot] is in the first region.
+      for (j = 0; j < 2; j++) {
+        for (i = 0; i < numelemattrib; i++) {
+          attrib = elemattribute(fliptets[spivot].tet, i);
+          setelemattribute(fliptets[j].tet, i, attrib);
+        }
+        if (b->varvolume) {
+          volume = volumebound(fliptets[spivot].tet);
+          setvolumebound(fliptets[j].tet, volume);
+        }
+      }
+    }
+  }
   if (checksubsegflag) {
     // Dealloc the space to subsegments.
     if (fliptets[0].tet[8] != NULL) {
@@ -7686,6 +7718,7 @@ void tetgenmesh::flip41(triface* fliptets, int hullflag, int flipflag,
   // Re-use fliptets[0] for [a,b,c,d].
   fliptets[0].ver = 11;
   setelemmarker(fliptets[0].tet, 0); // Clean all flags.
+  // NOTE: the element attributes and volume constraint remain unchanged.
   if (checksubsegflag) {
     // Dealloc the space to subsegments.
     if (fliptets[0].tet[8] != NULL) {
@@ -8677,9 +8710,7 @@ int tetgenmesh::flipnm(triface* abtets, int n, int level, int abedgepivot,
         }
       }
       if (!rejflag && (fc != NULL)) {
-        //rejflag = checkflipeligibility(2, tmppts[0], tmppts[1], tmppts[2], 
-        //                               pa, pb, level, abedgepivot, fc);
-        // Here we must permute 'a' and 'b'. Since in the check... function,
+        // Here we must exchange 'a' and 'b'. Since in the check... function,
         //   we assume the following point sequence, 'a,b,c,d,e', where
         //   the face [a,b,c] will be flipped and the edge [e,d] will be
         //   created. The two new tets are [a,b,c,d] and [b,a,c,e]. 
@@ -8808,9 +8839,7 @@ int tetgenmesh::flipnm_post(triface* abtets, int n, int nn, int abedgepivot,
     } 
     // The initial size of Star(ab) is 3.
     nn++;
-  } else { // nn > 2.
-    // The edge [a,b] exists.
-  }
+  } 
 
   // Walk through the performed flips.
   for (i = nn; i < n; i++) {
@@ -9025,11 +9054,6 @@ long tetgenmesh::lawsonflip3d(point newpt, int flipflag, int peelsliverflag,
 
       unmarkface(fliptet);
 
-      // FOR DEBUG
-      if (flipflag == 1) {
-        assert(oppo(fliptet) == newpt);
-      }
-
       if (ishulltet(fliptet)) {
         // It is a hull tet.
         if (((flipflag == 4) || peelsliverflag) && !b->convex) {
@@ -9061,8 +9085,6 @@ long tetgenmesh::lawsonflip3d(point newpt, int flipflag, int peelsliverflag,
                   //   [a,e],[b,e] are subsegments. If so, a 4-to-1 flip
                   //   (including a 3-to-1, and maybe a 2-to-1 flip) should be
                   //   applied to remove an exterior vertex.
-                  //   See figures (2011-11-13 and 15) for illustraions.
-
                   // First check if the face [b,a,d] is a hull face.
                   eprev(neightet, fliptets[0]);
                   esymself(fliptets[0]);  // [d,a,b,e]
@@ -9192,7 +9214,7 @@ long tetgenmesh::lawsonflip3d(point newpt, int flipflag, int peelsliverflag,
         if (flipflag == 1) {
           // Check if the new point is visible by the hull face.
           ppt = (point *) neightet.tet;
-          ori = orient3d(ppt[4], ppt[5], ppt[6], newpt); orient3dcount++;
+          ori = orient3d(ppt[4], ppt[5], ppt[6], newpt); 
           if (ori < 0) {
             // Visible. Perform a 2-to-3 flip on the flip face.
             fliptets[0] = fliptet;  // [a,b,c,d], d = newpt.
@@ -9296,7 +9318,7 @@ long tetgenmesh::lawsonflip3d(point newpt, int flipflag, int peelsliverflag,
         for (i = 0; i < 3; i++) {
           p1 = org(fliptet);
           p2 = dest(fliptet);
-          ori = orient3d(p1, p2, pd, pe); orient3dcount++;
+          ori = orient3d(p1, p2, pd, pe); 
           if (ori < 0) {
             // A locally non-convex edge.
             convflag = -1;
@@ -9604,14 +9626,14 @@ long tetgenmesh::lawsonflip3d(point newpt, int flipflag, int peelsliverflag,
 //                                                                           //
 // insertvertex()    Insert a point into current tetrahedralization.         //
 //                                                                           //
-// This routine implements the famous Bowyer-Watson (B-W) algorithm to add a //
-// new point p into current tetrahedralization, denoted as T. The baisc idea //
-// of B-W algorithm is: first finds a "cavity", denoted as C inside T, where //
-// C is a simplicial polyhedron formed by a union of tetrahedra in T. If all //
-// boundary faces (triangles) of C are visible by p, i.e., C is star-shaped, //
-// then T can be re-tetrahedralized by first deleting all old tetrahedra in  //
-// C, then replacing new tetrahedra formed by boundary faces of C and p. The //
-// result is that p becomesis a vertex of T.                                 //
+// The Bowyer-Watson (B-W) algorithm is used to add a new point p into the   //
+// tetrahedralization T. It first finds a "cavity", denoted as C, in T,  C   //
+// consists of tetrahedra in T that "conflict" with p.  If T is a Delaunay   //
+// tetrahedralization, then all boundary faces (triangles) of C are visible  //
+// by p, i.e.,C is star-shaped. We can insert p into T by first deleting all //
+// tetrahedra in C, then creating new tetrahedra formed by boundary faces of //
+// C and p.  If T is not a DT, then C may be not star-shaped.  It must be    //
+// modified so that it becomes star-shaped.                                  //
 //                                                                           //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
@@ -9638,9 +9660,6 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
   int rejptflag, encptflag; // for protecting balls.
   int bgmloc;
 
-#ifdef WITH_RUNTIME_COUNTERS
-  clock_t tstart, tend;
-#endif
 
   if (b->verbose > 2) {
     printf("      Insert point %d\n", pointmark(insertpt));
@@ -9655,17 +9674,12 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
   }
 
   if (loc == OUTSIDE) {
-#ifdef WITH_RUNTIME_COUNTERS
-    tstart = clock();
-#endif
-    tetcount = ptloc_count; // Count the number of walked tets.
+    tetcount = ptloc_count; // Count the number of visited tets.
     if (searchtet->tet == NULL) {
       if (!b->weighted) {
-        if (b->btree) {
-          btree_search(insertpt, searchtet);
-        } else if (b->hilbertcurve) { // -U
+        if (b->brio_hilbert) { // -b
           *searchtet = recenttet;
-        } else { // -u0
+        } else { // -b0
           randomsample(insertpt, searchtet);
         }
       } else {
@@ -9673,18 +9687,14 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
         *searchtet = recenttet;
       }
     }
-    // Locate the point.  Use 'randflag' if the mesh is non-convex.
-    loc = locate(insertpt, searchtet, ivf->chkencflag, checksubfaceflag); 
+    // Locate the point.
+    loc = locate(insertpt, searchtet, ivf->chkencflag); 
     if (b->verbose > 3) {
         printf("        Walk distance (# tets): %ld\n", ptloc_count-tetcount);
     }
     if (ptloc_max_count < (ptloc_count - tetcount)) {
       ptloc_max_count = (ptloc_count - tetcount);
     }
-#ifdef WITH_RUNTIME_COUNTERS
-    tend = clock();
-    t_ptloc += (tend - tstart);
-#endif
   }
 
   if (b->verbose > 3) {
@@ -9693,9 +9703,6 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
            pointmark(apex(*searchtet)), pointmark(oppo(*searchtet)));
   }
 
-#ifdef WITH_RUNTIME_COUNTERS
-  tstart = clock();
-#endif
 
   if (b->weighted) {
     if (loc != OUTSIDE) {
@@ -9707,21 +9714,19 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
                         insertpt[3]);
       if (sign > 0) {
         // This new vertex does not lie below the lower hull. Skip it.
-        if (b->verbose > 2) {
-          printf("      The point is above the lower hull, skipped.\n");
-        }
-        return OUTSIDE;
+        if (b->verbose > 1) {
+	  printf("    Point #%d is non-regular, skipped.\n",
+                 pointmark(insertpt));
+	}
+        setpointtype(insertpt, NREGULARVERTEX);
+        nonregularcount++;
+        return NONREGULAR;
       }
     }
   }
 
   // Create the initial cavity C(p) which contains all tetrahedra directly
   //   intersect with p.
-  // If 'bowywat > 2' and p lies on a segment or subface, also create the 
-  //   initial sub-cavity sC(p) which contains all subfaces (and segment)
-  //   which directly intersect with p.
-  // If 'bowywat > 2', the initial C(p) is validated, i.e., all boundary
-  //   faces of C(p) should be visible by p.
 
   // Remember the current hullsize. It is used to restore the hullsize
   //   if the new point is rejected for insertion.
@@ -9897,9 +9902,39 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
     return (int) loc;
   } else if (loc == ENCSUBFACE) {
     if (b->verbose > 3) {
-      printf("        Encroached.\n");
+      printf("        Beyond boundary.\n");
     }
     // The vertex lies outside of the region boundary.
+    if (ivf->rejflag & 2) {
+      // Check if this vertex lies very close to the boundary face.
+      // This case needs to be handled due to the rounding off error.
+      tspivot(*searchtet, checksh);
+      assert(checksh.sh != NULL);
+      pa = sorg(checksh);
+      pb = sdest(checksh);
+      pc = sapex(checksh);
+      ori = orient3d(pa, pb, pc, insertpt);
+      // Re-use cent[3].
+      cent[0] = distance(pa, insertpt);
+      cent[1] = distance(pb, insertpt);
+      cent[2] = distance(pb, insertpt);
+      // Choose the largest distance.
+      if (cent[0] < cent[1]) cent[0] = cent[1];
+      if (cent[0] < cent[2]) cent[0] = cent[2];
+      if (fabs(ori) / (cent[0] * cent[0] * cent[0]) < b->epsilon) {
+        // A nearly co-planar subface. We treat this case as coplanar, so
+        //   the insertion point does not lie outside of the domain. 
+        // Queue an encroached subface.
+        // Calculate the circumcenter of this subface (for refinement).
+        circumsphere(pa, pb, pc, NULL, cent, &rd);
+        encshlist->newindex((void **) &bface);
+        bface->ss = checksh;
+        bface->forg = pa; // Not a dad one.
+        for (j = 0; j < 3; j++) bface->cent[j] = cent[j];
+        bface->key = rd;
+        return (int) ENCSUBFACE;
+      }
+    }
     // Treated it as outside
     loc = OUTSIDE;
     return (int) loc;
@@ -9916,13 +9951,12 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
       bgm->decode(point2bgmtet(pa), neightet); // neightet is in 'bgm'!
       bgmloc = bgm->scoutpoint(insertpt, &neightet, 0); // randflag = 0
       if (bgmloc != (int) OUTSIDE) {
-        insertpt[pointmtrindex] =  // posflag = 1
-          bgm->getpointmeshsize(insertpt, &neightet, bgmloc, 1);
+        insertpt[pointmtrindex] =  
+          bgm->getpointmeshsize(insertpt, &neightet, bgmloc);
         setpoint2bgmtet(insertpt, bgm->encode(neightet));
       }
     } else {
-      insertpt[pointmtrindex] = // posflag = 1
-        getpointmeshsize(insertpt, searchtet, (int) loc, 1);
+      insertpt[pointmtrindex] = getpointmeshsize(insertpt,searchtet,(int)loc);
     }
   } // if (assignmeshsize)
 
@@ -9943,7 +9977,6 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
           ori = orient3d(pa, pb, pc, insertpt); 
           if (ori <= 0) {
             // An invalid face. Enlarge the cavity.
-            //if (oppo(*cavetet) != dummypoint) {
               if (b->verbose > 3) {
                 printf("        Enlarge cavity at (%d, %d, %d)\n",
                        pointmark(pa), pointmark(pb), pointmark(pc));
@@ -9961,11 +9994,6 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
               caveoldtetlist->newindex((void **) &parytet);
               *parytet = *cavetet;
               tetcount++;
-	    //} else {
-            //  printf("Error in insertvertex %d: ", pointmark(insertpt));
-            //  printf("Invalid initial cavity at face %d.\n", i + 1);
-            //  assert(0);
-	    //}
           } else {
             // A valid face.
             cavebdrylist->newindex((void **) &parytet);
@@ -10026,7 +10054,6 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
             if (!nonconvex) {
               // Test if this hull face is visible by the new point. 
               ori = orient3d(pts[4], pts[5], pts[6], insertpt); 
-              orient3dcount++;
               if (ori < 0) {
                 // A visible hull face. 
                 //if (!nonconvex) { 
@@ -10260,7 +10287,7 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
     if (encshlist->objects > 0) {
       if (b->verbose > 3) {
         printf("        Found %ld encroached subfaces. Reject it.\n",
-               caveencshlist->objects);
+               encshlist->objects);
       }
       for (i = 0; i < caveoldtetlist->objects; i++) {
         cavetet = (triface *) fastlookup(caveoldtetlist, i);
@@ -10309,14 +10336,21 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
           spivot(checksh, neighsh);
           assert(neighsh.sh != NULL);
           if (!smarktested(neighsh)) {
-            // Add this subface if it is inside C(p).
             stpivot(neighsh, neightet);
             if (infected(neightet)) {
               fsymself(neightet);
               if (infected(neightet)) {
-                smarktest(neighsh);
-                caveshlist->newindex((void **) &parysh);
-                *parysh = neighsh;
+                // This subface is inside C(p). 
+                // Check if its diametrical circumsphere encloses 'p'.
+                pa = sorg(neighsh);
+                pb = sdest(neighsh);
+                pc = sapex(neighsh);
+                sign = incircle3d(pa, pb, pc, insertpt);
+                if (sign < 0) {
+                  smarktest(neighsh);
+                  caveshlist->newindex((void **) &parysh);
+                  *parysh = neighsh;
+                }
               }
             }
           }
@@ -10500,7 +10534,7 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
             pa = org(*cavetet);
             pb = dest(*cavetet);
             pc = apex(*cavetet);
-            ori = orient3d(pa, pb, pc, insertpt); orient3dcount++;
+            ori = orient3d(pa, pb, pc, insertpt); 
             enqflag = (ori > 0);
             // Comment: if ori == 0 (coplanar case), we also cut the tet.
           } else {
@@ -10581,8 +10615,27 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
 
       // The cavity should contain at least one tet.
       if (caveoldtetlist->objects == 0l) {
-        printf("Invalid cavity of Steiner point %d.\n", pointmark(insertpt));
-        assert(0);
+        assert(cavebdrylist->objects == 0l);
+        cavetetlist->restart();
+        cavebdrylist->restart();
+        caveoldtetlist->restart();
+        cavetetseglist->restart();
+        cavetetshlist->restart();
+        if (ivf->splitbdflag) { //if (bowywat > 2) {
+          if (splitseg != NULL) {
+            sunmarktest(*splitseg);
+          }
+          for (i = 0; i < caveshlist->objects; i++) {
+            parysh = (face *) fastlookup(caveshlist, i);
+            assert(smarktested(*parysh));
+            sunmarktest(*parysh);
+          }
+          caveshlist->restart();
+          cavesegshlist->restart();
+        }
+        // Restore the hullsize.
+        hullsize = bakhullsize;
+        return (int) BADELEMENT;
       }
 
       if (ivf->splitbdflag) { //if (bowywat > 2) { // if (bowywat == 3) {
@@ -11034,15 +11087,6 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
       setdest(newtet, org(neightet));
       setapex(newtet, apex(neightet));
       setoppo(newtet, insertpt);
-      // The new tet inherits attribtes from the old tet.
-      for (j = 0; j < in->numberoftetrahedronattributes; j++) {
-        attrib = elemattribute(oldtet.tet, j);
-        setelemattribute(newtet.tet, j, attrib);
-      }
-      if (b->varvolume) {
-        volume = volumebound(oldtet.tet);
-        setvolumebound(newtet.tet, volume);
-      }
     } else {
       // Create a new hull tet (see Fig. bowyerwatson 2).
       hullsize++;
@@ -11054,6 +11098,15 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
       // Adjust back to the cavity bounday face.
       esymself(newtet);
     }
+    // The new tet inherits attribtes from the old tet.
+    for (j = 0; j < numelemattrib; j++) {
+      attrib = elemattribute(oldtet.tet, j);
+      setelemattribute(newtet.tet, j, attrib);
+    }
+    if (b->varvolume) {
+      volume = volumebound(oldtet.tet);
+      setvolumebound(newtet.tet, volume);
+    }
     // Connect newtet <==> neightet, this also disconnect the old bond.
     bond(newtet, neightet);
     // oldtet still connects to neightet.
@@ -11062,7 +11115,8 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
 
   // Set a handle for speeding point location.
   recenttet = newtet;
-  setpoint2tet(insertpt, encode(newtet));
+  //setpoint2tet(insertpt, encode(newtet));
+  setpoint2tet(insertpt, (tetrahedron) (newtet.tet));
 
   if (ivf->lawson > 1) { // if (lawson == 2 || lawson == 3) {
     // Re-use this list to save new interior cavity faces.
@@ -11098,7 +11152,8 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
           *parytet = neightet;
         }
       }
-      setpoint2tet(org(newtet), encode(newtet));
+      //setpoint2tet(org(newtet), encode(newtet));
+      setpoint2tet(org(newtet), (tetrahedron) (newtet.tet));
       enextself(newtet);
       enextself(oldtet);
     }
@@ -11247,7 +11302,7 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
             pa = sorg(checkseg);
             pb = sdest(checkseg);
             point2tetorg(pa, neightet);
-            finddirection(&neightet, pb, 1);
+            finddirection(&neightet, pb);
             assert(dest(neightet) == pb);
           }
           assert(!infected(neightet));
@@ -11318,11 +11373,12 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
       assert(searchtet->tet != NULL); // No tet has been deleted yet.
       if (infected(*searchtet)) {
         if (b->weighted) {
-          if (b->verbose > 2) {
-            printf("      Point #%d is removed from the hull.\n",
-                   pointmark(*pts));
-          }
-          setpointtype(*pts, UNUSEDVERTEX);
+          if (b->verbose > 1) {
+            printf("    Point #%d is non-regular after the insertion of #%d.\n",
+                   pointmark(*pts), pointmark(insertpt));
+	  }
+          setpointtype(*pts, NREGULARVERTEX);
+          nonregularcount++;
         } else {
           if (b->verbose > 3) {
             printf("        Queue a dangling vertex %d.\n", pointmark(*pts));
@@ -11468,14 +11524,7 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
   // The vertex should already have a type.
   assert(pointtype(insertpt) != UNUSEDVERTEX);
 
-#ifdef WITH_RUNTIME_COUNTERS
-  tend = clock();
-  t_ptinsert += (tend - tstart);
-#endif
 
-  if (b->btree) {
-    btree_insert(insertpt);
-  }
 
   // Clean the working lists.
 
@@ -11518,10 +11567,10 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
 //                                                                           //
 // transfernodes()    Read the vertices from the input (tetgenio).           //
 //                                                                           //
-// Initializing 'this->points'.  Transferring all points from 'in->pointlist'//
-// into it. All points are indexed (start from in->firstnumber).  Each point //
-// is initialized be UNUSEDVERTEX.  The bounding box (xmin, xmax, ymin, ymax,//
-// zmin, zmax) and the diameter (longest) of the point set are calculated.   //
+// Transferring all points from input ('in->pointlist') to TetGen's 'points'.//
+// All points are indexed (the first point index is 'in->firstnumber'). Each //
+// point's type is initialized as UNUSEDVERTEX. The bounding box (xmax, xmin,//
+// ...) and the diameter (longest) of the point set are calculated.          //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -11534,9 +11583,6 @@ void tetgenmesh::transfernodes()
   int mtrindex;
   int i, j;
 
-  if (b->psc) {
-    assert(in->pointparamlist != NULL);
-  }
 
   // Read the points.
   coordindex = 0;
@@ -11547,30 +11593,32 @@ void tetgenmesh::transfernodes()
     // Read the point coordinates.
     x = pointloop[0] = in->pointlist[coordindex++];
     y = pointloop[1] = in->pointlist[coordindex++];
-    z = pointloop[2] = in->pointlist[coordindex++];    
+    z = pointloop[2] = in->pointlist[coordindex++];
+    // Read the point attributes. (Including point weights.)
+    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++];
+    }
     if (b->weighted) { // -w option
       if (in->numberofpointattributes > 0) {
-        // The first point attribute is weight.
-        w = in->pointattributelist[in->numberofpointattributes * i];
+        // The first point attribute is its weight.
+        //w = in->pointattributelist[in->numberofpointattributes * i];
+        w = pointloop[3];
       } else {
-        // No given weight available.
-        w = 0;
+        // No given weight available. Default choose the maximum
+        //   absolute value among its coordinates.        
+        w = fabs(x);
+        if (w < fabs(y)) w = fabs(y);
+        if (w < fabs(z)) w = fabs(z);
       }
       if (b->weighted_param == 0) {
         pointloop[3] = x * x + y * y + z * z - w; // Weighted DT.
       } else { // -w1 option
         pointloop[3] = w;  // Regular tetrahedralization.
       }
-    } else {
-      pointloop[3] = 0;
-    }
-    // Read the point attributes.
-    for (j = 0; j < in->numberofpointattributes; j++) {
-      pointloop[4 + 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) {
@@ -11620,293 +11668,239 @@ void tetgenmesh::transfernodes()
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// btree_sort()    Sort vertices using a binary space partition (bsp) tree.  //
+// hilbert_init()    Initialize the Gray code permutation table.             //
+//                                                                           //
+// The table 'transgc' has 8 x 3 x 8 entries. It contains all possible Gray  //
+// code sequences traveled by the 1st order Hilbert curve in 3 dimensions.   //
+// The first column is the Gray code of the entry point of the curve, and    //
+// the second column is the direction (0, 1, or 2, 0 means the x-axis) where //
+// the exit point of curve lies.                                             //
+//                                                                           //
+// The table 'tsb1mod3' contains the numbers of trailing set '1' bits of the //
+// indices from 0 to 7, modulo by '3'. The code for generating this table is //
+// from: http://graphics.stanford.edu/~seander/bithacks.html.                //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::hilbert_init(int n)
+{
+  int gc[8], N, mask, travel_bit;
+  int e, d, f, k, g;
+  int v, c;
+  int i;
+
+  N = (n == 2) ? 4 : 8;
+  mask = (n == 2) ? 3 : 7;
+
+  // Generate the Gray code sequence.
+  for (i = 0; i < N; i++) {
+    gc[i] = i ^ (i >> 1);
+  }
+
+  for (e = 0; e < N; e++) {
+    for (d = 0; d < n; d++) {
+      // Calculate the end point (f).
+      f = e ^ (1 << d);  // Toggle the d-th bit of 'e'.
+      // travel_bit = 2**p, the bit we want to travel. 
+      travel_bit = e ^ f;
+      for (i = 0; i < N; i++) {
+        // // Rotate gc[i] left by (p + 1) % n bits.
+        k = gc[i] * (travel_bit * 2);
+        g = ((k | (k / N)) & mask);
+        // Calculate the permuted Gray code by xor with the start point (e).
+        transgc[e][d][i] = (g ^ e);
+      }
+      assert(transgc[e][d][0] == e);
+      assert(transgc[e][d][N - 1] == f);
+    } // d
+  } // e
+
+  // Count the consecutive '1' bits (trailing) on the right.
+  tsb1mod3[0] = 0;
+  for (i = 1; i < N; i++) {
+    v = ~i; // Count the 0s.
+    v = (v ^ (v - 1)) >> 1; // Set v's trailing 0s to 1s and zero rest
+    for (c = 0; v; c++) {
+      v >>= 1;
+    }
+    tsb1mod3[i] = c % n;
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// hilbert_sort3()    Sort points using the 3d Hilbert curve.                //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-void tetgenmesh::btree_sort(point* vertexarray, int arraysize, int axis, 
-                            REAL bxmin, REAL bxmax, REAL bymin, REAL bymax, 
-                            REAL bzmin, REAL bzmax, int depth)
+int tetgenmesh::hilbert_split(point* vertexarray,int arraysize,int gc0,int gc1,
+                              REAL bxmin, REAL bxmax, REAL bymin, REAL bymax, 
+                              REAL bzmin, REAL bzmax)
 {
-  point *leftarray, *rightarray;
-  point **pptary, swapvert;
+  point swapvert;
+  int axis, d;
   REAL split;
-  bool lflag, rflag;
-  int i, j, k; // *iptr,
+  int i, j;
 
-  if (b->verbose > 3) {
-    printf("  Depth %d, %d verts. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
-           depth, arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
-           axis == 0 ? "x" : (axis == 1 ? "y" : "z"));
-  }
 
-  if (depth > max_btree_depth) {
-    max_btree_depth = depth;
-  }
+  // Find the current splitting axis. 'axis' is a value 0, or 1, or 2, which 
+  //   correspoding to x-, or y- or z-axis.
+  axis = (gc0 ^ gc1) >> 1; 
 
+  // Calulate the split position along the axis.
   if (axis == 0) {
-    // Split along x-axis.
     split = 0.5 * (bxmin + bxmax);
   } else if (axis == 1) {
-    // Split along y-axis.
     split = 0.5 * (bymin + bymax);
-  } else {
-    // Split along z-axis.
+  } else { // == 2
     split = 0.5 * (bzmin + bzmax);
   }
 
+  // Find the direction (+1 or -1) of the axis. If 'd' is +1, the direction
+  //   of the axis is to the positive of the axis, otherwise, it is -1.
+  d = ((gc0 & (1<<axis)) == 0) ? 1 : -1;
 
+
+  // Partition the vertices into left- and right-arraies such that left points
+  //   have Hilbert indices lower than the right points.
   i = 0;
   j = arraysize - 1;
 
   // Partition the vertices into left- and right-arraies.
-  do {
-    for (; i < arraysize; i++) {
-      if (vertexarray[i][axis] >= split) {
-        break;
-      }
-    }
-    for (; j >= 0; j--) {
-      if (vertexarray[j][axis] < split) {
-        break;
-      }
-    }
-    // Is the partition finished?
-    if (i == (j + 1)) {
-      break;
-    }
-    // Swap i-th and j-th vertices.
-    swapvert = vertexarray[i];
-    vertexarray[i] = vertexarray[j];
-    vertexarray[j] = swapvert;
-    // Continue patitioning the array;
-  } while (true);
-
-  if (b->verbose > 3) {
-    printf("        leftsize = %d, rightsize = %d\n", i, arraysize - i);
-  }
-  lflag = rflag = false;
-
-  // Do not continue the partition if one of the array sizes is 0.
-  // if (depth < max_tree_depth) {
-  if (!((i == 0) || (i == arraysize))) {
-    if (i > b->max_btreenode_size) {
-      // Recursively partition the left array (length = i).
-      if (axis == 0) { // x
-        btree_sort(vertexarray, i, (axis + 1) % 3, bxmin, split, bymin, 
-                   bymax, bzmin, bzmax, depth + 1);
-      } else if (axis == 1) { // y
-        btree_sort(vertexarray, i, (axis + 1) % 3, bxmin, bxmax, bymin, 
-                   split, bzmin, bzmax, depth + 1);
-      } else { // z
-        btree_sort(vertexarray, i, (axis + 1) % 3, bxmin, bxmax, bymin, 
-                   bymax, bzmin, split, depth + 1);
+  if (d > 0) {
+    do {
+      for (; i < arraysize; i++) {      
+        if (vertexarray[i][axis] >= split) break;
+      }
+      for (; j >= 0; j--) {
+        if (vertexarray[j][axis] < split) break;
+      }
+      // Is the partition finished?
+      if (i == (j + 1)) break;
+      // Swap i-th and j-th vertices.
+      swapvert = vertexarray[i];
+      vertexarray[i] = vertexarray[j];
+      vertexarray[j] = swapvert;
+      // Continue patitioning the array;
+    } while (true);
+  } else {
+    do {
+      for (; i < arraysize; i++) {      
+        if (vertexarray[i][axis] <= split) break;
       }
-    } else {
-      lflag = true;
-    }
-    if ((arraysize - i) > b->max_btreenode_size) {
-      // Recursively partition the right array (length = arraysize - i).
-      if (axis == 0) { // x
-        btree_sort(&(vertexarray[i]), arraysize - i, (axis + 1) % 3, split, 
-                   bxmax, bymin, bymax, bzmin, bzmax, depth + 1);
-      } else if (axis == 1) { // y
-        btree_sort(&(vertexarray[i]), arraysize - i, (axis + 1) % 3, bxmin, 
-                   bxmax, split, bymax, bzmin, bzmax, depth + 1);
-      } else { // z
-        btree_sort(&(vertexarray[i]), arraysize - i, (axis + 1) % 3, bxmin, 
-                   bxmax, bymin, bymax, split, bzmax, depth + 1);
+      for (; j >= 0; j--) {
+        if (vertexarray[j][axis] > split) break;
       }
-    } else {
-      rflag = true;
-    }
-  } else {
-    // Both left and right are done.
-    lflag = rflag = true;
-  }
-
-  if (lflag && (i > 0)) {
-    // Remember the maximal length of the partitions.
-    if (i > max_btreenode_size) {
-      max_btreenode_size = i;
-    }
-    // Allocate space for the left array (use the first entry to save
-    //   the length of this array).
-    leftarray = new point[i + 1]; 
-    leftarray[0] = (point) i; // The array lenth.
-    //iptr = (int *) &(leftarray[0]);
-    //*iptr = i; // Save the array lenth in the first entry.
-    // Put all points in this array.
-    for (k = 0; k < i; k++) {
-      leftarray[k + 1] = vertexarray[k];
-      setpoint2ppt(leftarray[k + 1], (point) leftarray);
-    }
-    // Save this array in list.
-    btreenode_list->newindex((void **) &pptary);
-    *pptary = leftarray;
-  }
-
-  // Get the length of the right array.
-  j = arraysize - i;
-  if (rflag && (j > 0)) {
-    if (j > max_btreenode_size) {
-      max_btreenode_size = j;
-    }
-    // Allocate space for the right array (use the first entry to save
-    //   the length of this array).
-    rightarray = new point[j + 1];
-    rightarray[0] = (point) j; // The array lenth.
-    //iptr = (int *) &(rightarray[0]);
-    //*iptr = j; // Save the array length in the first entry.
-    // Put all points in this array.
-    for (k = 0; k < j; k++) {
-      rightarray[k + 1] = vertexarray[i + k];
-      setpoint2ppt(rightarray[k + 1], (point) rightarray);
-    }
-    // Save this array in list.
-    btreenode_list->newindex((void **) &pptary);
-    *pptary = rightarray;
+      // Is the partition finished?
+      if (i == (j + 1)) break;
+      // Swap i-th and j-th vertices.
+      swapvert = vertexarray[i];
+      vertexarray[i] = vertexarray[j];
+      vertexarray[j] = swapvert;
+      // Continue patitioning the array;
+    } while (true);
   }
-}
 
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// btree_insert()    Add a vertex into a tree node.                          //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::btree_insert(point insertpt)
-{
-  point *ptary;
-  long arylen; // The array lenhgth is saved in ptary[0].
-
-  // Get the tree node (save in this point).
-  ptary = (point *) point2ppt(insertpt);
-  // Get the current array length.
-  arylen = (long long) ptary[0];
-  // Insert the point into the node.
-  ptary[arylen + 1] = insertpt;
-  // Increase the array length by 1.
-  ptary[0] = (point) (arylen + 1);
+  return i;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// btree_search()    Search a near point for an inserting point.             //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::btree_search(point insertpt, triface* searchtet)
+void tetgenmesh::hilbert_sort3(point* vertexarray, int arraysize, int e, int d, 
+                               REAL bxmin, REAL bxmax, REAL bymin, REAL bymax, 
+                               REAL bzmin, REAL bzmax, int depth)
 {
-  point *ptary;
-  point nearpt, candpt;
-  REAL dist2, mindist2;
-  int ptsamples, ptidx;
-  long arylen;
-  int i;
-
-  // Get the tree node (save in this point).
-  ptary = (point *) point2ppt(insertpt);
-  // Get the current array length.
-  arylen = (long long) ptary[0];
-
-  if (arylen == 0) {
-    searchtet->tet = NULL;
-    return;
-  }
-
-  if (1) {
-
-    if (arylen < 5) { //if (arylen < 10) {
-      ptsamples = arylen;
-    } else {
-      ptsamples = 5; // Take at least 10 samples.
-      //   The number of random samples taken is proportional to the third root
-      //   of the number of points in the cell.
-      while (ptsamples * ptsamples * ptsamples < arylen) {
-        ptsamples++;
+  REAL x1, x2, y1, y2, z1, z2;
+  int p[9], w, e_w, d_w, k, ei, di;
+  int n = 3, mask = 7;
+
+
+  // Record the highest order of the curve.
+  if (depth + 1 > max_hcurve_depth_count) {
+    max_hcurve_depth_count = depth + 1;
+  }
+
+  p[0] = 0;
+  p[8] = arraysize;
+
+  // Sort the points according to the 1st order Hilbert curve in 3d.
+  p[4] = hilbert_split(vertexarray, p[8], transgc[e][d][3], transgc[e][d][4], 
+                       bxmin, bxmax, bymin, bymax, bzmin, bzmax);
+  p[2] = hilbert_split(vertexarray, p[4], transgc[e][d][1], transgc[e][d][2], 
+                       bxmin, bxmax, bymin, bymax, bzmin, bzmax);
+  p[1] = hilbert_split(vertexarray, p[2], transgc[e][d][0], transgc[e][d][1], 
+                       bxmin, bxmax, bymin, bymax, bzmin, bzmax);
+  p[3] = hilbert_split(&(vertexarray[p[2]]), p[4] - p[2], 
+                       transgc[e][d][2], transgc[e][d][3], 
+                       bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[2];
+  p[6] = hilbert_split(&(vertexarray[p[4]]), p[8] - p[4], 
+                       transgc[e][d][5], transgc[e][d][6], 
+                       bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[4];
+  p[5] = hilbert_split(&(vertexarray[p[4]]), p[6] - p[4], 
+                       transgc[e][d][4], transgc[e][d][5], 
+                       bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[4];
+  p[7] = hilbert_split(&(vertexarray[p[6]]), p[8] - p[6], 
+                       transgc[e][d][6], transgc[e][d][7], 
+                       bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[6];
+
+  if (b->hilbert_order > 0) {
+    // A maximum order is prescribed. 
+    if ((depth + 1) == b->hilbert_order) {
+      // The maximum prescribed order is reached.
+      return;
+    }
+  }
+
+  // Recursivly sort the points in sub-boxes.
+  for (w = 0; w < 8; w++) {
+    // w is the local Hilbert index (NOT Gray code).
+    // Sort into the sub-box either there are more than 2 points in it, or
+    //   the prescribed order of the curve is not reached yet.
+    if ((p[w+1] - p[w] > b->hilbert_limit) || (b->hilbert_order > 0)) {
+      // Calulcate the start point (ei) of the curve in this sub-box.
+      //   update e = e ^ (e(w) left_rotate (d+1)).
+      if (w == 0) {
+        e_w = 0;
+      } else {
+        //   calculate e(w) = gc(2 * floor((w - 1) / 2)).
+        k = 2 * ((w - 1) / 2); 
+        e_w = k ^ (k >> 1); // = gc(k).
+      }
+      k = e_w;
+      e_w = ((k << (d+1)) & mask) | ((k >> (n-d-1)) & mask);
+      ei = e ^ e_w;
+      // Calulcate the direction (di) of the curve in this sub-box.
+      //   update d = (d + d(w) + 1) % n
+      if (w == 0) {
+        d_w = 0;
+      } else {
+        d_w = ((w % 2) == 0) ? tsb1mod3[w - 1] : tsb1mod3[w];
       }
-    }
-
-    // Select "good" candidate using k random samples, taking the closest one.
-    mindist2 = 1.79769E+308; // The largest double value (8 byte).
-    nearpt = NULL;
-
-    for (i = 0; i < ptsamples; i++) {
-      ptidx = randomnation((unsigned long) arylen);
-      candpt = ptary[ptidx + 1];
-      dist2 = (candpt[0] - insertpt[0]) * (candpt[0] - insertpt[0])
-            + (candpt[1] - insertpt[1]) * (candpt[1] - insertpt[1])
-            + (candpt[2] - insertpt[2]) * (candpt[2] - insertpt[2]);
-      if (dist2 < mindist2) {
-        mindist2 = dist2;
-        nearpt = candpt;
+      di = (d + d_w + 1) % n;
+      // Calculate the bounding box of the sub-box.
+      if (transgc[e][d][w] & 1) { // x-axis
+        x1 = 0.5 * (bxmin + bxmax);
+        x2 = bxmax;
+      } else {
+        x1 = bxmin;
+        x2 = 0.5 * (bxmin + bxmax);
       }
-    }
-
-  } else {
-
-    // TEST, randomly select a point.
-    ptidx = randomnation((unsigned long) arylen);
-    nearpt = ptary[ptidx + 1];
-
-  }
-
-  if (b->verbose > 2) {
-    printf("      Get point %d (cell size %ld).\n", pointmark(nearpt), arylen);
-  }
-
-  decode(point2tet(nearpt), *searchtet);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-// ordervertices()    Order the vertices for incremental inserting.          //
-//                                                                           //
-// We assume the vertices have been sorted by a binary tree.                 //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
-
-void tetgenmesh::ordervertices(point* vertexarray, int arraysize)
-{
-  point **ipptary, **jpptary, *swappptary; 
-  point *ptary;
-  long arylen;
-  int index, i, j;
-
-  // First pick one vertex from each tree node.
-  for (i = 0; i < (int) btreenode_list->objects; i++) {
-    ipptary = (point **) fastlookup(btreenode_list, i);
-    ptary = *ipptary;
-    vertexarray[i] = ptary[1]; // Skip the first entry.
-  }
-
-  index = i;
-  // Then put all other points in the array node by node.
-  for (i = (int) btreenode_list->objects - 1; i >= 0; i--) {
-    // Randomly pick a tree node.
-    j = randomnation(i + 1);
-    // Save the i-th node.
-    ipptary = (point **) fastlookup(btreenode_list, i);
-    // Get the j-th node.
-    jpptary = (point **) fastlookup(btreenode_list, j);
-    // Order the points in the node.
-    ptary = *jpptary;
-    arylen = (long long) ptary[0];
-    for (j = 2; j <= arylen; j++) { // Skip the first point.
-      vertexarray[index] = ptary[j];
-      index++;
-    }
-    // Clear this tree node.
-    ptary[0] = (point) 0;
-    // Swap i-th node to j-th node.
-    swappptary = *ipptary;
-    *ipptary = *jpptary; // [i] <= [j]
-    *jpptary = swappptary; // [j] <= [i]
-  }
-
-  // Make sure we've done correctly.
-  assert(index == arraysize);
+      if (transgc[e][d][w] & 2) { // y-axis
+        y1 = 0.5 * (bymin + bymax);
+        y2 = bymax;
+      } else {
+        y1 = bymin;
+        y2 = 0.5 * (bymin + bymax);
+      }
+      if (transgc[e][d][w] & 4) { // z-axis
+        z1 = 0.5 * (bzmin + bzmax);
+        z2 = bzmax;
+      } else {
+        z1 = bzmin;
+        z2 = 0.5 * (bzmin + bzmax);
+      }
+      hilbert_sort3(&(vertexarray[p[w]]), p[w+1] - p[w], ei, di, 
+                    x1, x2, y1, y2, z1, z2, depth+1);
+    } // if (p[w+1] - p[w] > 1)
+  } // w
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -11938,13 +11932,10 @@ unsigned long tetgenmesh::randomnation(unsigned int choices)
 //                                                                           //
 // randomsample()    Randomly sample the tetrahedra for point loation.       //
 //                                                                           //
-// This routine implements Muecke's Jump-and-walk point location algorithm.  //
-// It improves the simple walk-through by "jumping" to a good starting point //
-// via random sampling.  Searching begins from one of handles:  the input    //
-// 'searchtet', a recently encountered tetrahedron 'recenttet',  or from one //
-// chosen from a random sample.  The choice is made by determining which one //
-// 's origin is closest to the point we are searcing for.  Having chosen the //
-// starting tetrahedron, the simple Walk-through algorithm is executed.      //
+// Searching begins from one of handles:  the input 'searchtet', a recently  //
+// encountered tetrahedron 'recenttet',  or from one chosen from a random    //
+// sample.  The choice is made by determining which one's origin is closest  //
+// to the point we are searcing for.                                         //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -12071,19 +12062,15 @@ void tetgenmesh::randomsample(point searchpt, triface *searchtet)
 //   - ONFACE, the search point lies on a face of 'searchtet'.               //
 //   - INTET, the search point lies in the interior of 'searchtet'.          //
 //   - OUTSIDE, the search point lies outside the mesh. 'searchtet' is a     //
-//     hull tetrahedron whose base face is visible by the search point.      //
+//              hull face which is visible by the search point.              //
 //                                                                           //
 // WARNING: This routine is designed for convex triangulations, and will not //
 // generally work after the holes and concavities have been carved.          //
 //                                                                           //
-// If 'randflag' is set (> 0). Randomly choose a tetrahedron when there are  //
-// multiple choices in the path.                                             // 
-//                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
 enum tetgenmesh::locateresult 
-  tetgenmesh::locate(point searchpt, triface* searchtet, int chkencflag, 
-                     int randflag)
+  tetgenmesh::locate(point searchpt, triface* searchtet, int chkencflag)
 {
   triface neightet; 
   face checksh;
@@ -12091,8 +12078,7 @@ enum tetgenmesh::locateresult
   enum {ORGMOVE, DESTMOVE, APEXMOVE} nextmove;
   REAL ori, oriorg, oridest, oriapex;
   enum locateresult loc;
-  int s; // i;
-
+  int s;
 
   if (searchtet->tet == NULL) {
     // A null tet. Choose the recenttet as the starting tet.
@@ -12114,13 +12100,11 @@ enum tetgenmesh::locateresult
     torg = org(*searchtet);
     tdest = dest(*searchtet);
     tapex = apex(*searchtet);
-    ori = orient3d(torg, tdest, tapex, searchpt); orient3dcount++;
+    ori = orient3d(torg, tdest, tapex, searchpt); 
     if (ori < 0.0) break;
   }
-  if (searchtet->ver == 4) {
-    // Either 'searchtet' is a very flat tet, or the 'searchpt' lies in
-    //   infinity, or both of them. Return OUTSIDE.
-    assert(0); // return OUTSIDE;
+  if (searchtet->ver == 4) { // SELF_CHECK
+    assert(0);
   }
 
   loc = OUTSIDE; // Set a default return value.
@@ -12128,7 +12112,7 @@ enum tetgenmesh::locateresult
   // Walk through tetrahedra to locate the point.
   while (true) {
 
-    ptloc_count++;  // Algorithimic count.
+    ptloc_count++;  // Count the number of visited tets.
 
     toppo = oppo(*searchtet);
     
@@ -12141,58 +12125,43 @@ enum tetgenmesh::locateresult
       break;
     }
 
-    // We enter from serarchtet's base face. There are three other faces in
-    //   searchtet (all connecting to toppo), which one is the exit?
+    // We enter from one of serarchtet's faces, which face do we exit?
     oriorg = orient3d(tdest, tapex, toppo, searchpt); 
     oridest = orient3d(tapex, torg, toppo, searchpt);
     oriapex = orient3d(torg, tdest, toppo, searchpt);
-    orient3dcount+=3;
 
     // Now decide which face to move. It is possible there are more than one
-    //   faces are viable moves. Use the opposite points of thier neighbors
-    //   to discriminate, i.e., we choose the face whose opposite point has
-    //   the shortest distance to searchpt.
+    //   faces are viable moves. If so, randomly choose one.
     if (oriorg < 0) {
       if (oridest < 0) {
         if (oriapex < 0) {
-          if (0) { //if (!randflag) {
+          // All three faces are possible.
+          s = randomnation(3); // 's' is in {0,1,2}.
+          if (s == 0) {
+            nextmove = ORGMOVE;
+          } else if (s == 1) {
+            nextmove = DESTMOVE;
           } else {
-            // Randomly choose a direction.
-            s = randomnation(3); // 's' is in {0,1,2}.
-            if (s == 0) {
-              nextmove = ORGMOVE;
-            } else if (s == 1) {
-              nextmove = DESTMOVE;
-            } else {
-              nextmove = APEXMOVE;
-            }
-          } // if (randflag)
+            nextmove = APEXMOVE;
+          }
         } else {
           // Two faces, opposite to origin and destination, are viable.
-          if (0) { // if (!randflag) {
+          s = randomnation(2); // 's' is in {0,1}.
+          if (s == 0) {
+            nextmove = ORGMOVE;
           } else {
-            // Randomly choose a direction.
-            s = randomnation(2); // 's' is in {0,1}.
-            if (s == 0) {
-              nextmove = ORGMOVE;
-            } else {
-              nextmove = DESTMOVE;
-            }
-          } // if (randflag)
+            nextmove = DESTMOVE;
+          }
         }
       } else {
         if (oriapex < 0) {
           // Two faces, opposite to origin and apex, are viable.
-          if (0) { // if (!randflag) {
+          s = randomnation(2); // 's' is in {0,1}.
+          if (s == 0) {
+            nextmove = ORGMOVE;
           } else {
-            // Randomly choose a direction.
-            s = randomnation(2); // 's' is in {0,1}.
-            if (s == 0) {
-              nextmove = ORGMOVE;
-            } else {
-              nextmove = APEXMOVE;
-            }
-          } // if (randflag)
+            nextmove = APEXMOVE;
+          }
         } else {
           // Only the face opposite to origin is viable.
           nextmove = ORGMOVE;
@@ -12202,16 +12171,12 @@ enum tetgenmesh::locateresult
       if (oridest < 0) {
         if (oriapex < 0) {
           // Two faces, opposite to destination and apex, are viable.
-          if (0) { // if (!randflag) {
+          s = randomnation(2); // 's' is in {0,1}.
+          if (s == 0) {
+            nextmove = DESTMOVE;
           } else {
-            // Randomly choose a direction.
-            s = randomnation(2); // 's' is in {0,1}.
-            if (s == 0) {
-              nextmove = DESTMOVE;
-            } else {
-              nextmove = APEXMOVE;
-            }
-          } // if (randflag)
+            nextmove = APEXMOVE;
+          }
         } else {
           // Only the face opposite to destination is viable.
           nextmove = DESTMOVE;
@@ -12306,7 +12271,6 @@ enum tetgenmesh::locateresult
   return loc;
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // initialdelaunay()    Create an initial Delaunay tetrahedralization.       //
@@ -12383,13 +12347,6 @@ void tetgenmesh::initialdelaunay(point pa, point pb, point pc, point pd)
     setpointtype(pd, VOLVERTEX);
   }
 
-  if (b->btree) {
-    btree_insert(pa);
-    btree_insert(pb);
-    btree_insert(pc);
-    btree_insert(pd);
-  }
-
   setpoint2tet(pa, encode(firsttet));
   setpoint2tet(pb, encode(firsttet));
   setpoint2tet(pc, encode(firsttet));
@@ -12414,56 +12371,45 @@ void tetgenmesh::incrementaldelaunay(clock_t& tv)
   REAL v1[3], v2[3], n[3];
   REAL bboxsize, bboxsize2, bboxsize3, ori;
   int randindex, loc; 
+  int ngroup, nstart, nend;
   int i, j;
 
   if (!b->quiet) {
     printf("Delaunizing vertices...\n");
   }
 
-  if (b->max_btreenode_size > 0) { // not -u0.
-    b->btree = 1;
-    btreenode_list = new arraypool(sizeof(point*), 10);
-    max_btreenode_size = 0;
-    max_btree_depth = 0;
-  }
-
-
   // Form a random permuation (uniformly at random) of the set of vertices.
   permutarray = new point[in->numberofpoints];
   points->traversalinit();
-  if (b->btree) { // -u option
-    for (i = 0; i < in->numberofpoints; i++) {
-      permutarray[i] = (point) points->traverse();
-    }
-    if (b->verbose) {
-      printf("  Sorting vertices by a bsp-tree.\n");
-    }
-    // Sort the points using a binary tree recursively.
-    btree_sort(permutarray, in->numberofpoints, 0, xmin, xmax, ymin, ymax,
-               zmin, zmax, 0);
-    if (b->verbose) {
-      printf("  Number of tree nodes: %ld.\n", btreenode_list->objects);
-      printf("  Maximum tree node size: %d.\n", max_btreenode_size);
-      printf("  Maximum tree depth: %d.\n", max_btree_depth);
-    }
-    // Order the sorted points.
-    ordervertices(permutarray, in->numberofpoints);
-  } else if (b->hilbertcurve) {
+
+  if (b->verbose) {
+    printf("  Permuting vertices.\n"); 
+  }
+  srand(in->numberofpoints);
+  for (i = 0; i < in->numberofpoints; i++) {
+    randindex = rand() % (i + 1); // randomnation(i + 1);
+    permutarray[i] = permutarray[randindex];
+    permutarray[randindex] = (point) points->traverse();
+  }
+  if (b->brio_hilbert) { // -b option
     if (b->verbose) {
-      printf("  Sorting vertices by hilbert curve.\n"); 
+      printf("  Sort the points using simple BRIO and Hilbert curve L(%d).\n",
+             b->hilbert_limit); 
     }
-    // To be done...
-    for (i = 0; i < in->numberofpoints; i++) {
-      permutarray[i] = (point) points->traverse();
+    hilbert_init(in->mesh_dim);
+    max_hcurve_depth_count = 0;
+
+    ngroup = (int) log((double) in->numberofpoints); 
+    nstart = 0;
+    for (i = 0; i < ngroup; i++) {
+      nend = in->numberofpoints >> (ngroup - 1 - i);
+      hilbert_sort3(&(permutarray[nstart]), nend - nstart, 0, 0, // e, d
+                    xmin, xmax, ymin, ymax, zmin, zmax, 0);
+      nstart = nend;
     }
-  } else {
     if (b->verbose) {
-      printf("  Permuting vertices.\n"); 
-    }
-    for (i = 0; i < in->numberofpoints; i++) {
-      randindex = randomnation(i + 1);
-      permutarray[i] = permutarray[randindex];
-      permutarray[randindex] = (point) points->traverse();
+      printf("  Number of sorted subsets: %d.\n", ngroup);
+      printf("  Maximum curve order: %d.\n", max_hcurve_depth_count);
     }
   }
 
@@ -12555,7 +12501,7 @@ void tetgenmesh::incrementaldelaunay(clock_t& tv)
     printf("  Incrementally inserting vertices.\n");
   }
 
-  // Choose algorithm: Bowyer-Watson (default) or Incremental Flip (-l).
+  // Choose algorithm: Bowyer-Watson (default) or Incremental Flip
   if (b->incrflip) {
     ivf.bowywat = 0;
     ivf.lawson = 1;
@@ -12564,6 +12510,7 @@ void tetgenmesh::incrementaldelaunay(clock_t& tv)
     ivf.lawson = 0;
   }
 
+
   for (i = 4; i < in->numberofpoints; i++) {
     if (b->verbose > 2) printf("      #%d", i);
     if (pointtype(permutarray[i]) == UNUSEDVERTEX) {
@@ -12588,22 +12535,20 @@ void tetgenmesh::incrementaldelaunay(clock_t& tv)
       setpointtype(permutarray[i], DUPLICATEDVERTEX);
       dupverts++;
       continue;
+    } else if (loc == (int) NREGULARVERTEX) {
+      // The point is non-regular. Skipped.
+      continue;
     }
     if (ivf.lawson) {
-      // If -l option. Perform flip to recover Delaunayness.
+      // Perform flip to recover Delaunayness.
       lawsonflip3d(permutarray[i], ivf.lawson, 0, 0, 0);
     }
   }
 
-  if (b->btree) {
-    // Bsp-tree is used only in DT construction.
-    point **pptary;
-    for (i = 0; i < (int) btreenode_list->objects; i++) {
-      pptary = (point **) fastlookup(btreenode_list, i);
-      delete [] *pptary;
-    }
-    delete btreenode_list;
-    b->btree = 0; // Disable it.
+
+
+  if (b->brio_hilbert) {
+    b->brio_hilbert = 0; // Disable it.
   }
 
   delete [] permutarray;
@@ -13522,7 +13467,7 @@ if (bowywat < 3) { // if (bowywat == 1 || bowywat == 2) {
       setshelltype(aseg, shelltype(*splitseg));
       setshelltype(bseg, shelltype(*splitseg));
       if (checkconstraints) {
-        setareabound(bseg, areabound(*splitseg));
+        setareabound(aseg, areabound(*splitseg));
         setareabound(bseg, areabound(*splitseg));
       }
 
@@ -14481,6 +14426,9 @@ void tetgenmesh::triangulate(int shmark, arraypool* ptlist, arraypool* conlist,
   int iloc;
   int i, j;
 
+  int idx, fmarker;
+  REAL area;
+
   if (b->verbose > 2) {
     printf("      f%d:  %ld vertices, %ld segments", shmark, ptlist->objects,
            conlist->objects);
@@ -14566,6 +14514,19 @@ void tetgenmesh::triangulate(int shmark, arraypool* ptlist, arraypool* conlist,
     setpointtype(pc, FACETVERTEX);
   }
 
+  // Are there area constraints?
+  if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
+    idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker.
+    for (i = 0; i < in->numberoffacetconstraints; i++) {
+      fmarker = (int) in->facetconstraintlist[i * 2];
+      if (fmarker == idx) {
+        area = in->facetconstraintlist[i * 2 + 1];
+        setareabound(newsh, area);
+        break;
+      }
+    }
+  }
+
   // Incrementally build the triangulation.
   pinfect(pa);
   pinfect(pb);
@@ -14633,14 +14594,9 @@ void tetgenmesh::unifysubfaces(face *f1, face *f2)
   point pa, pb, pc, pd;
   int i;
 
-  assert(f1->sh != f2->sh); // SELF_CHECK
-
   pa = sorg(*f1);
   pb = sdest(*f1);
   pc = sapex(*f1);
-
-  assert(sorg(*f2) == pa); // SELF_CHECK
-  assert(sdest(*f2) == pb); // SELF_CHECK
   pd = sapex(*f2);
 
   if (pc != pd) {
@@ -14687,10 +14643,6 @@ void tetgenmesh::unifysubfaces(face *f1, face *f2)
     sspivot(*f2, sseg); 
     if (sseg.sh != NULL) {
       // f2 has a segment. It must be different to f1's.
-      sspivot(*f1, checkseg); // SELF_CHECK
-      if (checkseg.sh != NULL) { // SELF_CHECK
-        assert(checkseg.sh != sseg.sh); // SELF_CHECK
-      }
       // Disconnect bonds of subfaces to this segment.
       spivot(*f2, casout);
       if (casout.sh != NULL) {
@@ -14743,6 +14695,9 @@ void tetgenmesh::unifysegments()
   int *idx2faclist;
   int idx, k, m;
 
+  int e1, e2;
+  REAL len;
+
   if (b->verbose > 1) {
     printf("  Unifying segments.\n");
   }
@@ -14940,11 +14895,23 @@ void tetgenmesh::unifysegments()
       }
     }
 
-    // // All identified segments has a marker "-1".
-    //setshellmark(subsegloop, -1);
     // All identified segments has an init marker "0".
     flippool->restart();
 
+    // Are there length constraints?
+    if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
+      for (k = 0; k < in->numberofsegmentconstraints; k++) {
+        e1 = (int) in->segmentconstraintlist[k * 3];
+        e2 = (int) in->segmentconstraintlist[k * 3 + 1];
+        if (((pointmark(torg) == e1) && (pointmark(tdest) == e2)) ||
+            ((pointmark(torg) == e2) && (pointmark(tdest) == e1))) {
+          len = in->segmentconstraintlist[k * 3 + 2];
+          setareabound(subsegloop, len);
+          break;
+        }
+      }
+    }
+
     subsegloop.sh = shellfacetraverse(subsegs);
   }
 
@@ -15063,12 +15030,13 @@ void tetgenmesh::identifypscedges(point *idx2verlist)
   int edgemarker;
   int idx, i, j;
 
+  int e1, e2;
+  REAL len;
+
   if (!b->quiet) {
     printf("Inserting edges ...\n");
   }
 
-  //assert(in->numberofedges > 0); // SELF_CHECK
-  //assert(in->edgemarkerlist != NULL); // SELF_CHECK
   // All identified segments have the initial marker '0'.
   // All segments inserted here should have a non-zero marker.
 
@@ -15079,6 +15047,7 @@ void tetgenmesh::identifypscedges(point *idx2verlist)
   for (i = 0; i < in->numberofedges; i++) {
     endpts = &(in->edgelist[(i << 1)]);
     // Find a face contains the edge.
+    newseg.sh = NULL;
     searchsh.sh = NULL;
     idx = endpts[0] - in->firstnumber;
     for (j = idx2shlist[idx]; j < idx2shlist[idx + 1]; j++) {
@@ -15151,6 +15120,21 @@ void tetgenmesh::identifypscedges(point *idx2verlist)
         setpointtype(pb, RIDGEVERTEX);
       //}
     }
+
+    if (newseg.sh != NULL) {
+      if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
+        for (i = 0; i < in->numberofsegmentconstraints; i++) {
+          e1 = (int) in->segmentconstraintlist[i * 3];
+          e2 = (int) in->segmentconstraintlist[i * 3 + 1];
+          if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
+              ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
+            len = in->segmentconstraintlist[i * 3 + 2];
+            setareabound(newseg, len);
+            break;
+          }
+        }
+      }
+    }
   } // i
 
   if (b->psc) {
@@ -15442,9 +15426,7 @@ void tetgenmesh::interecursive(shellface** subfacearray, int arraysize,
       toright = true;
     }
     // At least one is true;
-#ifdef SELF_CHECK
     assert(!(toleft == false && toright == false));
-#endif
     if (toleft) {
       leftarray[leftsize] = sface1.sh;
       leftsize++;
@@ -15644,7 +15626,7 @@ void tetgenmesh::markacutevertices()
     printf("  Marking acute vertices.\n");
   }
   anglimit = PI / 3.0;  // 60 degree.
-  sharpanglimit = 10.0 / 180.0 * PI; // 10 degree. 
+  sharpanglimit = 5.0 / 180.0 * PI; // 5 degree. 
   minfaceang = PI; // 180 degree.
   acutecount = sharpsegcount = 0;
 
@@ -15669,11 +15651,9 @@ void tetgenmesh::markacutevertices()
       // Do a brute-force pair-pair check.
       for (i=idx2seglist[idx]; i<idx2seglist[idx + 1]; i++) {
         pb = sdest(segperverlist[i]);
-        //for (j = i + 1; j < idx2seglist[idx + 1] && !acuteflag; j++) {
         for (j = i + 1; j < idx2seglist[idx + 1]; j++) {
           pc = sdest(segperverlist[j]);
           ang = interiorangle(pa, pb, pc, NULL); 
-          //acuteflag = ang < anglimit;
           if (!acuteflag) {
             acuteflag = ang < anglimit;
           }
@@ -15771,7 +15751,7 @@ void tetgenmesh::reportselfintersect(face *checkseg, face *checksh)
 ///////////////////////////////////////////////////////////////////////////////
 
 enum tetgenmesh::interresult 
-  tetgenmesh::finddirection(triface* searchtet, point endpt, int randflag)
+  tetgenmesh::finddirection(triface* searchtet, point endpt)
 {
   triface neightet;
   point pa, pb, pc, pd;
@@ -15779,7 +15759,6 @@ enum tetgenmesh::interresult
   REAL hori, rori, lori;
   int s;
 
-
   // The origin is fixed.
   pa = org(*searchtet);
   if ((point) searchtet->tet[7] == dummypoint) {
@@ -15794,7 +15773,7 @@ enum tetgenmesh::interresult
     } else if ((point) searchtet->tet[6] == pa) {
       searchtet->ver = 7;
     } else {
-      assert((point) searchtet->tet[7] == pa); // SELF_CHECK
+      assert((point) searchtet->tet[7] == pa); 
       searchtet->ver = 0;
     }
   }
@@ -15846,54 +15825,39 @@ enum tetgenmesh::interresult
     hori = orient3d(pa, pb, pc, endpt);
     rori = orient3d(pb, pa, pd, endpt);
     lori = orient3d(pa, pc, pd, endpt);
-    orient3dcount += 3;
 
     // Now decide the tet to move.  It is possible there are more than one
-    //   tet are viable moves. Use the opposite points of thier neighbors
-    //   to discriminate, i.e., we choose the tet whose opposite point has
-    //   the shortest distance to 'endpt'.
+    //   tets are viable moves. Is so, randomly choose one. 
     if (hori > 0) {
       if (rori > 0) {
         if (lori > 0) {
           // Any of the three neighbors is a viable move.
-          if (0) { // if (!randflag) {
+          s = randomnation(3); 
+          if (s == 0) {
+            nextmove = HMOVE;
+          } else if (s == 1) {
+            nextmove = RMOVE;
           } else {
-            // Randomly choose a direction.
-            s = randomnation(3); // 's' is in {0,1,2}.
-            if (s == 0) {
-              nextmove = HMOVE;
-            } else if (s == 1) {
-              nextmove = RMOVE;
-            } else {
-              nextmove = LMOVE;
-            }
-          } // if (randflag)
+            nextmove = LMOVE;
+          }
         } else {
           // Two tets, below horizon and below right, are viable.
-          if (0) { // if (!randflag) {
+          s = randomnation(2); 
+          if (s == 0) {
+            nextmove = HMOVE;
           } else {
-            // Randomly choose a direction.
-            s = randomnation(2); // 's' is in {0,1}.
-            if (s == 0) {
-              nextmove = HMOVE;
-            } else {
-              nextmove = RMOVE;
-            }
-          } // if (randflag)
+            nextmove = RMOVE;
+          }
         }
       } else {
         if (lori > 0) {
           // Two tets, below horizon and below left, are viable.
-          if (0) { // if (!randflag) {
+          s = randomnation(2); 
+          if (s == 0) {
+            nextmove = HMOVE;
           } else {
-            // Randomly choose a direction.
-            s = randomnation(2); // 's' is in {0,1}.
-            if (s == 0) {
-              nextmove = HMOVE;
-            } else {
-              nextmove = LMOVE;
-            }
-          } // if (randflag)
+            nextmove = LMOVE;
+          }
         } else {
           // The tet below horizon is chosen.
           nextmove = HMOVE;
@@ -15903,16 +15867,12 @@ enum tetgenmesh::interresult
       if (rori > 0) {
         if (lori > 0) {
           // Two tets, below right and below left, are viable.
-          if (0) { // if (!randflag) {
+          s = randomnation(2); 
+          if (s == 0) {
+            nextmove = RMOVE;
           } else {
-            // Randomly choose a direction.
-            s = randomnation(2); // 's' is in {0,1}.
-            if (s == 0) {
-              nextmove = RMOVE;
-            } else {
-              nextmove = LMOVE;
-            }
-          } // if (randflag)
+            nextmove = LMOVE;
+          }
         } else {
           // The tet below right is chosen.
           nextmove = RMOVE;
@@ -15972,7 +15932,7 @@ enum tetgenmesh::interresult
       fsymself(*searchtet);
       enextself(*searchtet);
     }
-    assert(org(*searchtet) == pa); // SELF_CHECK
+    assert(org(*searchtet) == pa); 
     pb = dest(*searchtet);
     pc = apex(*searchtet);
 
@@ -16023,7 +15983,7 @@ enum tetgenmesh::interresult
   }
 
   point2tetorg(startpt, *searchtet);
-  dir = finddirection(searchtet, endpt, 0);
+  dir = finddirection(searchtet, endpt);
 
   if (dir == ACROSSVERT) {
     pd = dest(*searchtet);
@@ -16489,13 +16449,12 @@ void tetgenmesh::delaunizesegments()
     psseg = (face *) fastlookup(subsegstack, subsegstack->objects);
     sseg = *psseg;
 
-    assert(!sinfected(sseg)); // FOR DEBUG
+    assert(!sinfected(sseg)); 
     // Check if this segment has been recovered.
     sstpivot1(sseg, searchtet);
     if (searchtet.tet != NULL) {
-      // FOR DEBUG
       // Check if the tet contains the same segment.
-      tsspivot1(searchtet, checkseg);
+      tsspivot1(searchtet, checkseg); // SELF_CHECK
       assert(checkseg.sh == sseg.sh);
       continue; // Not a missing segment.
     }
@@ -16538,7 +16497,7 @@ void tetgenmesh::delaunizesegments()
         ivf.splitbdflag = 0;
         // ivf.validflag
         ivf.respectbdflag = 0;
-        ivf.assignmeshsize = 0;
+        ivf.assignmeshsize = b->metric;
         // Insert the new point into the tetrahedralization T.
         //   Missing segments and subfaces are queued for recovery.
         //   Note that T is convex (nonconvex = 0).
@@ -16551,7 +16510,7 @@ void tetgenmesh::delaunizesegments()
             // For CDT, use flips to reocver Delaunayness.
             lawsonflip3d(newpt, ivf.lawson, 0, 0, 0);
           }
-          st_segref_count++; //st_segpro_count++;
+          st_segref_count++;
           if (steinerleft > 0) steinerleft--;
         } else {
           // The new point is either ON or VERY CLOSE to an existing point.
@@ -16696,7 +16655,7 @@ enum tetgenmesh::interresult
   // Get a tet whose origin is a.
   point2tetorg(pa, *searchtet);
   // Search the edge [a,b].
-  dir = finddirection(searchtet, pb, 0);
+  dir = finddirection(searchtet, pb);
   if (dir == ACROSSVERT) {
     // Check validity of a PLC.
     if (dest(*searchtet) != pb) {
@@ -16792,7 +16751,7 @@ void tetgenmesh::formmissingregion(face* missh, arraypool* missingshs,
       // Get a tet whose origin is a.
       point2tetorg(pa, searchtet);
       // Search the edge [a,b].
-      dir = finddirection(&searchtet, pb, 0);
+      dir = finddirection(&searchtet, pb);
       if (dir != ACROSSVERT) {
         // This edge is missing. Its neighbor is a missing subface.
         spivot(*missh, neighsh);
@@ -16857,7 +16816,6 @@ void tetgenmesh::formmissingregion(face* missh, arraypool* missingshs,
 }
 
 
-
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // scoutcrossedge()    Search an edge that crosses the missing region.       //
@@ -16969,22 +16927,6 @@ int tetgenmesh::scoutcrossedge(triface& crosstet, arraypool* adjtets,
 // #] which intersects R in its interior, where the edge [d,e] intersects R, //
 // and d lies below R.                                                       //
 //                                                                           //
-// By knowing a crossing edge [d,e], all tetrahedra sharing at [d,e] must    //
-// cross R. They are added into the list 'crosstets'. From this set of tets, //
-// new crossing edges (if there exist) can be detected.  The key is how to   //
-// detect them correctly.  The approach used here is described as follows:   //
-// Suppose [d,e,a,b] is a crossing tet, where [d,e] intersects R and d lies  //
-// below R. We look at the face [d,e,a]. If the apex a is not pmarktested,   //
-// i.e., it is not a vertex of R, then either edge [e,a] or [a,d] intersects //
-// R. A simple way is to perform above/below test between [a] and R.  But it //
-// is not clear which subface of R is the best for this test. Also, this is  //
-// not safe when R is not strictly planar.  A second way is to test if [e,a] //
-// intersects one of the subfaces of R. If an intersection is found, then [e,//
-// a] is a crossing edge. Otherwise, the edge [a,d] must be a crossing edge  //
-// of R. NOTE: This statement is correct if the input PLC is correct. We can //
-// also detect the incorrectness of the input, e.g., if [a] only touches a   //
-// subface of R. The second approach is implemented here. It is slow, but is //
-// more robust.                                                              //
 //                                                                           //
 // 'crosstets' returns the set of crossing tets. Every tet in it has the     //
 // form [d,e,#,#] where [d,e] is a crossing edge, and d lies below R.  The   //
@@ -17017,8 +16959,6 @@ bool tetgenmesh::formcavity(triface* searchtet, arraypool* missingshs,
   face checkseg; // *paryseg;
   point pa, pd, pe, *parypt;
   enum interresult dir; 
-  //REAL ori;
-  //REAL elen[3];
   bool testflag, invalidflag;
   int types[2], poss[4];
   int i, j, k;
@@ -17042,8 +16982,6 @@ bool tetgenmesh::formcavity(triface* searchtet, arraypool* missingshs,
   // Collect all crossing tets.  Each cross tet is saved in the standard
   //   form [d,e,#,#], where [d,e] is a corossing edge, d lies below R.
   //   NEITHER d NOR e is a vertex of R (!pmarktested). 
-  // NOTE: hull tets may be collected. See fig/dump-cavity-case2a(b).lua.
-  //   Make sure that neither d nor e is dummypoint.
   for (i = 0; i < crossedges->objects; i++) {
     // Get a crossing edge [d,e,#,#].
     searchtet = (triface *) fastlookup(crossedges, i);
@@ -18294,12 +18232,7 @@ void tetgenmesh::flipcertify(triface *chkface, badface **pqueue)
   //     p[1], p[0], p[2], p[3].
 
   insph = insphere(p[1], p[0], p[2], p[3], p[4]);
-
-  if (b->flipinsert_ori4dexact) {
-    ori4 = orient4dexact(p[1], p[0], p[2], p[3], p[4],w[1],w[0],w[2],w[3],w[4]);
-  } else {
-    ori4 = orient4d(p[1], p[0], p[2], p[3], p[4], w[1], w[0], w[2], w[3], w[4]);
-  }
+  ori4 = orient4d(p[1], p[0], p[2], p[3], p[4], w[1], w[0], w[2], w[3], w[4]);
 
   if (b->verbose > 2) {
     printf("      Heights: (%g, %g, %g, %g, %g)\n", w[0],w[1],w[2],w[3],w[4]);
@@ -18332,7 +18265,7 @@ void tetgenmesh::flipcertify(triface *chkface, badface **pqueue)
       // Search an item whose key is larger or equal to current key.
       prevbf = NULL;
       nextbf = *pqueue;
-      if (!b->flipinsert_random) { // Default use a priority queue.
+      //if (!b->flipinsert_random) { // Default use a priority queue.
         // Insert the item into priority queue.
         while (nextbf != NULL) {
           if (nextbf->key < parybf->key) {
@@ -18342,7 +18275,7 @@ void tetgenmesh::flipcertify(triface *chkface, badface **pqueue)
             break;
           }
         }
-      } // if (!b->flipinsert_random) // -L1
+      //} // if (!b->flipinsert_random)
       // Insert the new item between prev and next items.
       if (prevbf == NULL) {
         *pqueue = parybf;
@@ -18456,7 +18389,6 @@ void tetgenmesh::flipinsertfacet(arraypool *crosstets, arraypool *toppoints,
   // The list for temporarily storing unflipable faces.
   bfacearray = new arraypool(sizeof(triface), 4);
 
- fliploop:
 
   fcount = 0;  // Count the number of flips.
 
@@ -18545,9 +18477,19 @@ void tetgenmesh::flipinsertfacet(arraypool *crosstets, arraypool *toppoints,
             assert(checkseg.sh == NULL);
 
             // Collect tets sharing at this edge.
+            // NOTE: This operation may collect tets which lie outside the
+            //   cavity, e.g., when the edge lies on the boundary of the
+            //   cavity. Do not flip if there are outside tets at this edge.
+            //   2012-07-27.
             esym(fliptet, fliptets[0]); // [b,a,d,c]
             n = 0;
             do {
+              p1 = apex(fliptets[n]);
+              if (!(pmarktested(p1) || pmarktest2ed(p1) || pmarktest3ed(p1))) {
+                // This apex is not on the cavity. Hence the face does not
+                //   lie inside the cavity. Do not flip this edge.
+                n = 1000; break;
+              }
               fnext(fliptets[n], fliptets[n + 1]);
               n++;
             } while ((fliptets[n].tet != fliptet.tet) && (n < 5));
@@ -18655,7 +18597,7 @@ void tetgenmesh::flipinsertfacet(arraypool *crosstets, arraypool *toppoints,
               flipcertify(parytet, &pqueue);
             }
             crossfaces->restart();
-            if (!b->flipinsert_random) {
+            if (1) { // if (!b->flipinsert_random) {
               // Insert all queued unflipped faces.
               for (i = 0; i < bfacearray->objects; i++) {
                 parytet = (triface *) fastlookup(bfacearray, i);
@@ -18683,18 +18625,6 @@ void tetgenmesh::flipinsertfacet(arraypool *crosstets, arraypool *toppoints,
       printf("!! No flip is found in %ld faces.\n", bfacearray->objects);
       assert(0);
     }
-    if (b->flipinsert_random) {
-      // Insert all queued unflipped faces.
-      for (i = 0; i < bfacearray->objects; i++) {
-        parytet = (triface *) fastlookup(bfacearray, i);
-        // This face may be changed.
-        if (!isdeadtet(*parytet)) {
-          flipcertify(parytet, &pqueue);
-        }
-      }
-      bfacearray->restart();
-      goto fliploop;
-    }
   }
 
   // 'bfacearray' may be not empty (for what reason ??).
@@ -18778,7 +18708,7 @@ bool tetgenmesh::fillregion(arraypool* missingshs, arraypool* missingshbds,
   ppt[0] = sorg(oldsh);
   ppt[1] = sdest(oldsh);
   point2tetorg(ppt[0], searchtet);
-  dir = finddirection(&searchtet, ppt[1], 0);
+  dir = finddirection(&searchtet, ppt[1]);
   assert(dir == ACROSSVERT); // SELF_CHECK
 
   insideflag = false;
@@ -18926,7 +18856,7 @@ bool tetgenmesh::fillregion(arraypool* missingshs, arraypool* missingshbds,
     ppt[0] = sorg(*parysh);
     ppt[1] = sdest(*parysh);
     point2tetorg(ppt[0], searchtet);
-    dir = finddirection(&searchtet, ppt[1], 0);
+    dir = finddirection(&searchtet, ppt[1]);
     assert(dir == ACROSSVERT); // SELF_CHECK
     tsspivot1(searchtet, checkseg);
     if (checkseg.sh == NULL) {
@@ -19196,7 +19126,7 @@ void tetgenmesh::refineregion()
   ivf.splitbdflag = 0;
   ivf.validflag = 1;
   ivf.respectbdflag = 0;
-  ivf.assignmeshsize = 0;
+  ivf.assignmeshsize = b->metric;
   loc = insertvertex(steinpt, &searchtet, &splitsh, NULL, &ivf);
 
   assert((loc != OUTSIDE) && (loc != ONVERTEX));
@@ -19243,7 +19173,7 @@ void tetgenmesh::refineregion()
     ivf.splitbdflag = 0;
     ivf.validflag = 1;
     ivf.respectbdflag = 0;
-    ivf.assignmeshsize = 0;
+    ivf.assignmeshsize = b->metric;
     loc = insertvertex(steinpt, &searchtet, &splitsh, &sseg, &ivf);
 
     if (loc == NEARVERTEX) {
@@ -19595,10 +19525,8 @@ void tetgenmesh::constraineddelaunay(clock_t& tv)
     printf("Constrained Delaunay...\n");
   }
 
-  //if (!b->psc) {
-    // Only identify acute vertex for PLC inputs.
-    markacutevertices();
-  //}
+  // Identify acute vertex for PLC inputs.
+  markacutevertices();
 
   if (b->verbose) {
     printf("  Delaunizing segments.\n");
@@ -19607,16 +19535,6 @@ void tetgenmesh::constraineddelaunay(clock_t& tv)
   checksubsegflag = 1;
 
   // Put all segments into the list.
-  if (0) { //if (b->order == 4) {  // '-o4' option (for debug)
-    // In sequential order.
-    subsegs->traversalinit();
-    for (i = 0; i < subsegs->items; i++) {
-      searchseg.sh = shellfacetraverse(subsegs);
-      //sinfect(searchseg);  // Only save it once.
-      subsegstack->newindex((void **) &paryseg);
-      *paryseg = searchseg;
-    }
-  } else {
     // In random order.
     subsegs->traversalinit();
     for (i = 0; i < subsegs->items; i++) {
@@ -19630,7 +19548,6 @@ void tetgenmesh::constraineddelaunay(clock_t& tv)
       paryseg = (face *) fastlookup(subsegstack, s);
       *paryseg = searchseg;
     }
-  }
 
   // Recover non-Delaunay segments.
   delaunizesegments();
@@ -19711,10 +19628,6 @@ void tetgenmesh::constraineddelaunay(clock_t& tv)
 // the flip face, and [d,e] is the flip edge. NOTE: 'pc' may be 'dummypoint',//
 // other points must not be 'dummypoint'.                                    //
 //                                                                           //
-// For avoiding mutually flipping, once a crossing face is flipped, it will  //
-// never be re-created again. Also, we never create a face or edge which is  //
-// intersecting the current recovering segment or subface.                   //
-//                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
 int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb, 
@@ -19746,20 +19659,6 @@ int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb,
         tmppts[0] = pa;
         tmppts[1] = pb;
         tmppts[2] = pc;
-        if (0) {
-          // Make sure that the three new faces are not degenerate.
-          for (i = 0; i < 3 && !rejflag; i++) {
-            facenormal(pe, pd, tmppts[i], normal, 1, &len);
-            area = sqrt(DOT(normal, normal));
-            if (area == 0) {
-              rejflag = 1; // A degenerate face.
-            } else {
-              if ((area / (len * len)) < b->epsilon) {
-                rejflag = 1; // A nearly degenerate face.
-              }
-            }
-          } // i
-        }
         for (i = 0; i < 3 && !rejflag; i++) {
           intflag = tri_edge_test(pe, pd, tmppts[i], fc->seg[0], fc->seg[1], 
                                   NULL, 1, types, poss);
@@ -19775,12 +19674,7 @@ int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb,
                 // Since [e,d] is the newly created edge. Reject this flip.
                 rejflag = 1; 
               }
-            } else {
-              if ((dir == ACROSSVERT) || (dir == TOUCHEDGE) || 
-                  (dir == TOUCHFACE)) {
-                assert(0); // Check this case.
-              }
-            } // dir
+            }
           } else if (intflag == 4) {
             // They may intersect at either a point or a line segment.
             dir = (enum interresult) types[0];
@@ -19790,11 +19684,6 @@ int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb,
                 // Since [e,d] is the newly created edge. Reject this flip.
                 rejflag = 1;
               }
-            } else {
-              if ((dir == ACROSSVERT) || (dir == TOUCHEDGE) || 
-                  (dir == TOUCHFACE)) {
-                assert(0); // Check this case.
-              }
             }
           } // if (intflag == 4)
         } // i
@@ -19834,12 +19723,7 @@ int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb,
                 // Since [e,d] is the newly created edge. Reject this flip.
                 rejflag = 1;
               }
-            } else {
-              if ((dir == ACROSSVERT) || (dir == TOUCHEDGE) || 
-                  (dir == TOUCHFACE)) {
-                assert(0); // Check this case.
-              }
-            }
+            } 
           } else if (intflag == 4) {
             // [e,d,abovept] is coplanar with the constraining edge 'fc'.
             // This is poissible if the edge in 'fc' is just the edge [e,d]
@@ -19848,11 +19732,6 @@ int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb,
             if (dir == ACROSSEDGE) {
               // This case can only happen if [e,d] is coplanar with 'fc'.
               assert(0);  // Not possible.
-            } else {
-              if ((dir == ACROSSVERT) || (dir == TOUCHEDGE) || 
-                  (dir == TOUCHFACE)) {
-                assert(0); // Check this case.
-              }
             }
           }
         }
@@ -19860,18 +19739,6 @@ int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb,
     } else if (fliptype == 2) {
       // A 3-to-2 flip: [e,d,a], [e,d,b], [e,d,c] => [a,b,c]
       if (pc != dummypoint) {
-        if (0) {
-          // Make sure that [a,b,c] is a valid face.      
-          facenormal(pa, pb, pc, normal, 1, &len);
-          area = sqrt(DOT(normal, normal));
-          if (area == 0) {
-            rejflag = 1; // A degenerate face.
-          } else {
-            if ((area / (len * len)) < b->epsilon) {
-              rejflag = 1; // A nearly degenerate face.
-            }
-          }
-        }
         if (!rejflag) {
           // Check if the new face [a,b,c] intersect the edge in its interior.
           intflag = tri_edge_test(pa, pb, pc, fc->seg[0], fc->seg[1], NULL, 
@@ -19885,11 +19752,6 @@ int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb,
             } else if (dir == ACROSSEDGE) {
               // This case is possible since we allow a previous 2-to-3 flip
               //   even it will create a degenerate tet at edge [a,b].
-            } else {
-              if ((dir == ACROSSVERT) || (dir == TOUCHEDGE) || 
-                  (dir == TOUCHFACE)) {
-                assert(0); // Check this case.
-              }
             }
           } else if (intflag == 4) {
             // [a,b,c] is coplanar with the edge. 
@@ -19936,11 +19798,6 @@ int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb,
             if (dir == ACROSSEDGE) {
               assert(0); // Check this case.
               rejflag = 1; // Do not flip.
-            } else {
-              if ((dir == ACROSSVERT) || (dir == TOUCHEDGE) || 
-                  (dir == TOUCHFACE)) {
-                assert(0); // Check this case.
-              }
             }
           } else if (intflag == 4) {
             // The edge 'fc' is coplanar with [a,b,abovept]. 
@@ -19950,11 +19807,6 @@ int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb,
             if (dir == ACROSSEDGE) {
               // This case can only happen if [a,b] is coplanar with 'fc'.
               assert(0);  // Not possible.
-            } else {
-              if ((dir == ACROSSVERT) || (dir == TOUCHEDGE) || 
-                  (dir == TOUCHFACE)) {
-                assert(0); // Check this case.
-              }
             }
           }
         } // if (ori1 == 0 && ori2 == 0)
@@ -19978,11 +19830,7 @@ int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb,
           rejflag = 1;
         } else if (dir == ACROSSEDGE) {
           rejflag = 1;
-        } else {
-          if ((dir == ACROSSVERT) || (dir == TOUCHEDGE) || (dir == TOUCHFACE)) {
-            assert(0); // Check this case.
-          }
-        }
+        } 
       } else if (intflag == 4) {
         // The edge [e,d] is coplanar with the face.
         // There may be two intersections.
@@ -20123,7 +19971,7 @@ int tetgenmesh::checkflipeligibility(int fliptype, point pa, point pb,
 //                                                                           //
 // removeedgebyflips()    Remove an edge by flips.                           //
 //                                                                           //
-// 'flipedge' is a non-convex or flat edge [a,b,#,#].                        //
+// 'flipedge' is a non-convex or flat edge [a,b,#,#] to be removed.          //
 //                                                                           //
 // The return value is a positive integer, it indicates whether the edge is  //
 // removed or not.  A value "2" means the edge is removed, othereise, the    //
@@ -20136,23 +19984,15 @@ int tetgenmesh::removeedgebyflips(triface *flipedge, flipconstraints* fc)
 {
   triface *abtets, spintet;
   face checkseg, *paryseg;
-  int counter; // DEBUG
   int n, nn, i;
 
 
-  // Bakup valuses (for free spaces in flipnm_post()).
-  int bakunflip = fc->unflip;
-  int bakcollectnewtets = fc->collectnewtets;
-
-
   if (b->verbose > 2) {
     printf("      Removing edge (%d, %d)\n", pointmark(org(*flipedge)), 
            pointmark(dest(*flipedge)));
   }
 
-  //if (fc != NULL) {
-    fc->clearcounters();
-  //}
+  fc->clearcounters();
 
   if (checksubsegflag) {
     // Do not flip a segment.
@@ -20162,24 +20002,22 @@ int tetgenmesh::removeedgebyflips(triface *flipedge, flipconstraints* fc)
         printf("      Can't flip a segment (%d, %d).\n", 
                pointmark(sorg(checkseg)), pointmark(sdest(checkseg))); 
       }
-      //if (fc != NULL) {
-        fc->encsegcount++;
-        if (fc->collectencsegflag) {
-          if (!sinfected(checkseg)) {
-            // Queue this segment in list.
-            sinfect(checkseg);                
-            caveencseglist->newindex((void **) &paryseg);
-            *paryseg = checkseg;
-          }
+      fc->encsegcount++;
+      if (fc->collectencsegflag) {
+        if (!sinfected(checkseg)) {
+          // Queue this segment in list.
+          sinfect(checkseg);                
+          caveencseglist->newindex((void **) &paryseg);
+          *paryseg = checkseg;
         }
-      //}
+      }
       return 0;
     }
   }
 
   // Count the number of tets at edge [a,b].
   n = 0;
-  counter = 0; // Sum of star counters;
+  int counter = 0; // Sum of star counters. // SELF_CHECK.
   spintet = *flipedge;
   i = 0;
   while (1) {
@@ -20204,7 +20042,7 @@ int tetgenmesh::removeedgebyflips(triface *flipedge, flipconstraints* fc)
     maxflipstarsize = n;
   }
   if ((b->flipstarsize > 0) && (n > b->flipstarsize)) {
-    // The star size exceeds the given limit (-YY__).
+    // The star size exceeds the limit.
     skpflipstarcount++;
     return 0; // Do not flip it.
   }
@@ -20216,8 +20054,7 @@ int tetgenmesh::removeedgebyflips(triface *flipedge, flipconstraints* fc)
   i = 0;
   while (1) {
     abtets[i] = spintet;
-    //marktest(abtets[i]); // Marktest it (in Star(ab)).
-    setelemcounter(abtets[i], 1);
+    setelemcounter(abtets[i], 1); // Marktest it (in Star(ab)).
     i++;
     fnextself(spintet);
     if (spintet.tet == flipedge->tet) break;
@@ -20234,29 +20071,26 @@ int tetgenmesh::removeedgebyflips(triface *flipedge, flipconstraints* fc)
       printf("      Edge is removed.\n");
     }
   } else {
+    if (b->verbose > 2) {
+      printf("      Edge is not removed. n(%d), nn(%d).\n", n, nn);
+    }
     // Edge is not flipped. Unmarktest the remaining tets in Star(ab).
     for (i = 0; i < nn; i++) {
-      //assert(marktested(abtets[i]));
-      //unmarktest(abtets[i]);
       assert(elemcounter(abtets[i]) == 1);
       setelemcounter(abtets[i], 0);
     }
-    if (b->verbose > 2) {
-      printf("      Edge is not removed. n(%d), nn(%d).\n", n, nn);
-    }
     // Restore the input edge (needed by Lawson's flip).
     *flipedge = abtets[0];
   }
 
   // Release the temporary allocated spaces.
   // NOTE: fc->unflip must be 0.
+  int bakunflip = fc->unflip;
   fc->unflip = 0;
-  fc->collectnewtets = 0;
 
   flipnm_post(abtets, n, nn, 0, fc);
 
   fc->unflip = bakunflip;
-  fc->collectnewtets = bakcollectnewtets;
 
   delete [] abtets;
 
@@ -20277,12 +20111,8 @@ int tetgenmesh::removefacebyflips(triface *flipface, flipconstraints* fc)
   triface fliptets[3], flipedge;
   face checksh;
   point pa, pb, pc, pd, pe;
-  point pts[3];
-  enum interresult dir;
-  int types[2], poss[4], pos;
   REAL ori;
   int reducflag, rejflag;
-  int i, j;
 
   if (checksubfaceflag) {
     tspivot(*flipface, checksh);
@@ -20296,10 +20126,6 @@ int tetgenmesh::removefacebyflips(triface *flipface, flipconstraints* fc)
 
   fliptets[0] = *flipface;
   fsym(*flipface, fliptets[1]);
-
-  assert(!ishulltet(fliptets[0]));
-  assert(!ishulltet(fliptets[1]));
-
   pa = org(fliptets[0]);
   pb = dest(fliptets[0]);
   pc = apex(fliptets[0]);
@@ -20343,99 +20169,14 @@ int tetgenmesh::removefacebyflips(triface *flipface, flipconstraints* fc)
         printf("      Face is removed by a 2-to-3 flip.\n");
       }
       return 1;
-    } else {
-      if (b->verbose > 2) {
-        printf("      -- Reject a 2-to-3 flip at face (%d, %d, %d)\n",
-               pointmark(pa), pointmark(pb), pointmark(pc));
-      }
-      if (fc != NULL) {
-        fc->rejf23count++;
-      }
     }
   } else {
-    if (0) {
-      // Try to flip one of the edges of this face.
-      pts[0] = org(flipedge);
-      pts[1] = dest(flipedge);
-      pts[2] = apex(flipedge);
-      // Start from the recorded locally non-convex edge 'flipedge'.
-      for (i = 0; i < 3; i++) {
-        if (removeedgebyflips(&flipedge, fc) == 2) {
-          if (b->verbose > 2) {
-            printf("      Face is removed by removing edge (%d, %d).\n",
-                   pointmark(pts[i]), pointmark(pts[(i+1)%3]));
-          }
-          return 1;
-        }
-        // The 'flipedge' may be dead in above call.
-        point2tetorg(pts[i], flipedge);
-        finddirection(&flipedge, pts[(i+1)%3], 1);
-        if (dest(flipedge) != pts[(i+1)%3]) {
-          if (b->verbose > 2) {
-            printf("      Face is removed during removing edge (%d, %d).\n",
-                   pointmark(pts[i]), pointmark(pts[(i+1)%3]));
-          }
-          return 1;
-        }
-      } // i
-    } else {
-      if (0) { //if (fc->seg[0] != NULL) {
-        // The face is intersecting a segment.
-        // Find the edge shared by three corssing faces.
-        // We assume that the 'flipface' is facing to 'fc->seg[0]'. It is the
-        //   case when the function is called from 'recoveredgebyflips()'.
-        // DEBUG BEGIN
-        pa = org(*flipface);
-        pb = dest(*flipface);
-        pc = apex(*flipface);
-        ori = orient3d(pa, pb, pc, fc->seg[0]);
-        assert(ori < 0);
-        // DEBUG END
-        fsym(*flipface, flipedge);
-        pc = oppo(flipedge);
-        for (i = 0; i < 3; i++) {
-          pa = org(flipedge);
-          pb = dest(flipedge);
-          if (tri_edge_test(pa, pb, pc, fc->seg[0], fc->seg[1], NULL, 1, 
-                            types, poss)) {
-            dir = (enum interresult) types[0];
-            if (dir == ACROSSFACE) {
-              break; // Found the crossing face.
-            } else if (dir == ACROSSEDGE) {
-              // Found an edge intersects the segment.
-              esymself(flipedge);
-              pos = poss[0];
-              for (j = 0; j < pos; j++) {
-                eprevself(flipedge);
-              }
-              // Flip this edge.
-              break;
-            } else if (dir == SHAREVERT) {
-              // We have reached the endpoint of the segment.
-              assert(pc == fc->seg[1]);
-              // The face is not flippable.
-              return 0;
-            } else {
-              assert(0);  // Not possible.
-            }
-          }
-          enextself(flipedge);
-        }
-        assert(i < 3);
-      } else {
-        if (b->verbose > 2) {
-          pa = org(flipedge);
-          pb = dest(flipedge);
-        }
-      }
-      // Try to flip the selected edge of this face.
-      if (removeedgebyflips(&flipedge, fc) == 2) {
-        if (b->verbose > 2) {
-          printf("      Face is removed by removing edge (%d, %d).\n",
-                 pointmark(pa), pointmark(pb));
-        }
-        return 1;
+    // Try to flip the selected edge of this face.
+    if (removeedgebyflips(&flipedge, fc) == 2) {
+      if (b->verbose > 2) {
+        printf("      Face is removed by removing an edge.\n");
       }
+      return 1;
     }
   }
 
@@ -20461,22 +20202,19 @@ int tetgenmesh::removefacebyflips(triface *flipface, flipconstraints* fc)
 int tetgenmesh::recoveredgebyflips(point startpt, point endpt, 
                                    triface* searchtet, int fullsearch)
 {
-  triface neightet, spintet; // *abtets;
+  triface neightet, spintet;
   point pa, pb, pc, pd;
   badface bakface;
   enum interresult dir, dir1;
   flipconstraints fc;
   int types[2], poss[4], pos = 0;
   int success;
-  //int n, endi;
-  int i, j; //, k;
+  int i, j;
 
   if (b->verbose > 2) {
     printf("      Recovering edge (%d, %d)\n", pointmark(startpt), 
            pointmark(endpt));
   }
-
-
   fc.seg[0] = startpt;
   fc.seg[1] = endpt;
 
@@ -20485,14 +20223,13 @@ int tetgenmesh::recoveredgebyflips(point startpt, point endpt,
 
     // Search the edge from 'startpt'.
     point2tetorg(startpt, *searchtet);
-    assert(org(*searchtet) == startpt); // SELF_CHECK
-    dir = finddirection(searchtet, endpt, 1);
+    dir = finddirection(searchtet, endpt);
     if (dir == ACROSSVERT) {
       if (dest(*searchtet) == endpt) {
         return 1; // Edge is recovered.
       } else {
         // A PLC problem, or there is a Steiner point.
-        terminatetetgen(3); //assert(0); // Debug
+        terminatetetgen(3); 
       }
     }
 
@@ -20518,168 +20255,165 @@ int tetgenmesh::recoveredgebyflips(point startpt, point endpt,
 
     if (fullsearch) {
 
-      if (1) {
-        // Try to flip one of the faces/edges which intersects the edge.
-        success = 0;
+      // Try to flip one of the faces/edges which intersects the edge.
+      success = 0;
 
-        // Loop through the sequence of intersecting faces/edges from
-        //   'startpt' to 'endpt'.
-        point2tetorg(startpt, *searchtet);
-        assert(org(*searchtet) == startpt); // SELF_CHECK
-        dir = finddirection(searchtet, endpt, 1);
-        assert(dir != ACROSSVERT);
+      // Loop through the sequence of intersecting faces/edges from
+      //   'startpt' to 'endpt'.
+      point2tetorg(startpt, *searchtet);
+      dir = finddirection(searchtet, endpt);
+      //assert(dir != ACROSSVERT);
 
-        // Go to the face/edge intersecting the searching edge.
-        enextesymself(*searchtet); // Go to the opposite face.
-        // This face/edge has been tried in previous step.
+      // Go to the face/edge intersecting the searching edge.
+      enextesymself(*searchtet); // Go to the opposite face.
+      // This face/edge has been tried in previous step.
 
-        while (1) { // Loop I-I
+      while (1) { // Loop I-I
 
-          // Find the next intersecting face/edge.
-          fsymself(*searchtet);
-          if (dir == ACROSSFACE) {
-            neightet = *searchtet;
-            j = (neightet.ver & 3); // j is the current face number.
-            for (i = j + 1; i < j + 4; i++) {
-              neightet.ver = (i % 4);
+        // Find the next intersecting face/edge.
+        fsymself(*searchtet);
+        if (dir == ACROSSFACE) {
+          neightet = *searchtet;
+          j = (neightet.ver & 3); // j is the current face number.
+          for (i = j + 1; i < j + 4; i++) {
+            neightet.ver = (i % 4);
+            pa = org(neightet);
+            pb = dest(neightet);
+            pc = apex(neightet);
+            pd = oppo(neightet); // The above point.
+            if (tri_edge_test(pa,pb,pc,startpt,endpt, pd, 1, types, poss)) {
+              dir = (enum interresult) types[0];
+              pos = poss[0];
+              break;
+            } else {
+              dir = DISJOINT;
+              pos = 0;
+            }
+          } // i
+          // There must be an intersection face/edge.
+          assert(dir != DISJOINT);  // SELF_CHECK
+        } else {
+          assert(dir == ACROSSEDGE);
+          while (1) { // Loop I-I-I
+            // Check the two opposite faces (of the edge) in 'searchtet'.  
+            for (i = 0; i < 2; i++) {
+              if (i == 0) {
+                enextesym(*searchtet, neightet);
+              } else {
+                eprevesym(*searchtet, neightet);
+              }
               pa = org(neightet);
               pb = dest(neightet);
               pc = apex(neightet);
               pd = oppo(neightet); // The above point.
-              if (tri_edge_test(pa,pb,pc,startpt,endpt, pd, 1, types, poss)) {
+              if (tri_edge_test(pa,pb,pc,startpt,endpt,pd,1, types, poss)) {
                 dir = (enum interresult) types[0];
                 pos = poss[0];
-                break;
+                break; // for loop
               } else {
                 dir = DISJOINT;
                 pos = 0;
               }
             } // i
-            // There must be an intersection face/edge.
-            assert(dir != DISJOINT);  // SELF_CHECK
-          } else {
-            assert(dir == ACROSSEDGE);
-            while (1) { // Loop I-I-I
-              // Check the two opposite faces (of the edge) in 'searchtet'.  
-              for (i = 0; i < 2; i++) {
-                if (i == 0) {
-                  enextesym(*searchtet, neightet);
-                } else {
-                  eprevesym(*searchtet, neightet);
-                }
-                pa = org(neightet);
-                pb = dest(neightet);
-                pc = apex(neightet);
-                pd = oppo(neightet); // The above point.
-                if (tri_edge_test(pa,pb,pc,startpt,endpt,pd,1, types, poss)) {
-                  dir = (enum interresult) types[0];
-                  pos = poss[0];
-                  break; // for loop
-                } else {
-                  dir = DISJOINT;
-                  pos = 0;
-                }
-              } // i
-              if (dir != DISJOINT) {
-                // Find an intersection face/edge.
-                break;  // Loop I-I-I
-              }
-              // No intersection. Rotate to the next tet at the edge.
-              fnextself(*searchtet);
-            } // while (1) // Loop I-I-I
-          }
+            if (dir != DISJOINT) {
+              // Find an intersection face/edge.
+              break;  // Loop I-I-I
+            }
+            // No intersection. Rotate to the next tet at the edge.
+            fnextself(*searchtet);
+          } // while (1) // Loop I-I-I
+        }
 
-          // Adjust to the intersecting edge/vertex.
-          for (i = 0; i < pos; i++) {
-            enextself(neightet);
-          }
+        // Adjust to the intersecting edge/vertex.
+        for (i = 0; i < pos; i++) {
+          enextself(neightet);
+        }
 
-          if (dir == SHAREVERT) {
-            // Check if we have reached the 'endpt'.
-            pd = org(neightet);
-            if (pd == endpt) {
-              // Failed to recover the edge.
-              break; // Loop I-I
-            } else {
-              // We need to further check this case. It might be a PLC problem
-              //   or a Steiner point that was added at a bad location.
-              assert(0);
-            }
+        if (dir == SHAREVERT) {
+          // Check if we have reached the 'endpt'.
+          pd = org(neightet);
+          if (pd == endpt) {
+            // Failed to recover the edge.
+            break; // Loop I-I
+          } else {
+            // We need to further check this case. It might be a PLC problem
+            //   or a Steiner point that was added at a bad location.
+            assert(0);
           }
+        }
 
-          // The next to be flipped face/edge.
-          *searchtet = neightet;
+        // The next to be flipped face/edge.
+        *searchtet = neightet;
 
-          // Bakup this face (tetrahedron).
-          bakface.forg = org(*searchtet);
-          bakface.fdest = dest(*searchtet);
-          bakface.fapex = apex(*searchtet);
-          bakface.foppo = oppo(*searchtet);
+        // Bakup this face (tetrahedron).
+        bakface.forg = org(*searchtet);
+        bakface.fdest = dest(*searchtet);
+        bakface.fapex = apex(*searchtet);
+        bakface.foppo = oppo(*searchtet);
 
-          // Try to flip this intersecting face/edge.
-          if (dir == ACROSSFACE) {
-            if (removefacebyflips(searchtet, &fc)) {
-              success = 1;
-              break; // Loop I-I 
-            }
-          } else if (dir == ACROSSEDGE) {
-            if (removeedgebyflips(searchtet, &fc) == 2) {
-              success = 1;
-              break; // Loop I-I
-            }
-          } else {
-            assert(0); // A PLC problem.
-          }
-
-          // The face/edge is not flipped.
-          if ((searchtet->tet == NULL) ||
-              (org(*searchtet) != bakface.forg) ||
-              (dest(*searchtet) != bakface.fdest) ||
-              (apex(*searchtet) != bakface.fapex) ||
-              (oppo(*searchtet) != bakface.foppo)) {
-            // 'searchtet' was flipped. We must restore it.
-            point2tetorg(bakface.forg, *searchtet);
-            dir1 = finddirection(searchtet, bakface.fdest, 1);
-            if (dir1 == ACROSSVERT) {
-              assert(dest(*searchtet) == bakface.fdest);
-              spintet = *searchtet;
-              while (1) {
-                if (apex(spintet) == bakface.fapex) {
-                  // Found the face.
-                  *searchtet = spintet;
-                  break;
-                }
-                fnextself(spintet);
-                if (spintet.tet == searchtet->tet) {
+        // Try to flip this intersecting face/edge.
+        if (dir == ACROSSFACE) {
+          if (removefacebyflips(searchtet, &fc)) {
+            success = 1;
+            break; // Loop I-I 
+          }
+        } else if (dir == ACROSSEDGE) {
+          if (removeedgebyflips(searchtet, &fc) == 2) {
+            success = 1;
+            break; // Loop I-I
+          }
+        } else {
+          assert(0); // A PLC problem.
+        }
+
+        // The face/edge is not flipped.
+        if ((searchtet->tet == NULL) ||
+            (org(*searchtet) != bakface.forg) ||
+            (dest(*searchtet) != bakface.fdest) ||
+            (apex(*searchtet) != bakface.fapex) ||
+            (oppo(*searchtet) != bakface.foppo)) {
+          // 'searchtet' was flipped. We must restore it.
+          point2tetorg(bakface.forg, *searchtet);
+          dir1 = finddirection(searchtet, bakface.fdest);
+          if (dir1 == ACROSSVERT) {
+            assert(dest(*searchtet) == bakface.fdest);
+            spintet = *searchtet;
+            while (1) {
+              if (apex(spintet) == bakface.fapex) {
+                // Found the face.
+                *searchtet = spintet;
+                break;
+              }
+              fnextself(spintet);
+              if (spintet.tet == searchtet->tet) {
+                searchtet->tet = NULL;
+                break; // Not find.
+              }
+	    } // while (1)
+            if (searchtet->tet != NULL) {
+              if (oppo(*searchtet) != bakface.foppo) {
+                fsymself(*searchtet);
+                if (oppo(*searchtet) != bakface.foppo) {
+                  assert(0); // Check this case.
                   searchtet->tet = NULL;
                   break; // Not find.
                 }
-	      } // while (1)
-              if (searchtet->tet != NULL) {
-                if (oppo(*searchtet) != bakface.foppo) {
-                  fsymself(*searchtet);
-                  if (oppo(*searchtet) != bakface.foppo) {
-                    assert(0); // Check this case.
-                    searchtet->tet = NULL;
-                    break; // Not find.
-                  }
-                }
               }
-            } else {
-              searchtet->tet = NULL; // Not find.
-            }
-            if (searchtet->tet == NULL) {
-              success = 0; // This face/edge has been destroed.
-              break; // Loop I-I 
             }
+          } else {
+            searchtet->tet = NULL; // Not find.
+          }
+          if (searchtet->tet == NULL) {
+            success = 0; // This face/edge has been destroed.
+            break; // Loop I-I 
           }
-        } // while (1) // Loop I-I
-
-        if (success) {
-          // One of intersecting faces/edges is flipped.
-          continue;
         }
-      } // if (0)
+      } // while (1) // Loop I-I
+
+      if (success) {
+        // One of intersecting faces/edges is flipped.
+        continue;
+      }
 
     } // if (fullsearch)
 
@@ -20701,24 +20435,13 @@ int tetgenmesh::recoveredgebyflips(point startpt, point endpt,
 // tets are [a,b,p0,p1], [a,b,p1,p2], ..., [a,b,p_(n-2),p_(n-1)].  Moreover, //
 // the edge [p0,p_(n-1)] intersects all of the tets in 'abtets'.  A special  //
 // case is that the edge [p0,p_(n-1)] is coplanar with the edge [a,b].       //
+// Such set of tets arises when we want to recover an edge from 'p0' to 'p_  //
+// (n-1)', and the number of tets at [a,b] can not be reduced by any flip.   //
 //                                                                           //
-// These set of tets arises when we want to recover an edge from 'p0' to 'p_ //
-// (n-1)', and the recoveredgenbyflips() routine fails.  Note that the outer //
-// faces of these tets defines a polyhedron P, and the set of tets gives the //
-// ONLY tetrahedralization of P.  If we replace the two boundary faces [a,b, //
-// p0] and [a,b,p_(n-1)] by [p0,p_(n-1),a] and [p0,p_(n-1),b], and call the  //
-// new polyhedron P'. In this routine, we think P' is not tetrahedralizable  //
-// (since the routine recoveredgenbyflips() fails!! AND no flip is possible  //
-// on any of these edges: [a,p1], [b,p1], [a,p2], [b,p2], ..., [a,p_(n-2)],  //
-// and [b,p_(n-1)]). If n = 3, P' is just the famous Schoenhardt polyhedron. //
-// For n > 3, we call P' the generalized Schoenhardt polyhedron, it includes //
-// the Bagemihl's polyhedron as a special case.                              //
-//                                                                           //
-// It is obvious that P is a Star-shaped polyhedron. The mid-point of [a,b]  //
-// is visible by all boundary faces of P, push it slightly inside P does not //
-// change the visibilty. Indeed every interior point of [a,b] is visible by  //
-// the boundary faces of P.                                                  //
-//                                                                           //
+// The union of these tets is a polyhedron P. Obviously that P is a star-    //
+// shaped polyhedron. The midpoint of [a,b] is visible by all boundary faces //
+// of P, push it slightly inside P does not change the visibilty. Indeed     //
+// every interior point of [a,b] is visible by the boundary faces of P.      //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -20874,7 +20597,7 @@ int tetgenmesh::add_steinerpt_in_schoenhardtpoly(triface *abtets, int n,
   ivf.splitbdflag = 0;
   ivf.validflag = 0;
   ivf.respectbdflag = 0;
-  ivf.assignmeshsize = 0; 
+  ivf.assignmeshsize = b->metric; 
 
   // Insert the new point into the tetrahedralization T.
   // Note that T is convex (nonconvex = 0).
@@ -20882,7 +20605,7 @@ int tetgenmesh::add_steinerpt_in_schoenhardtpoly(triface *abtets, int n,
 
   if (loc == (int) INSTAR) {
     // The vertex has been inserted.
-    st_volref_count++; //st_inpoly_count++;
+    st_volref_count++; 
     if (steinerleft > 0) steinerleft--;
     return 1;
   } else {
@@ -20923,8 +20646,7 @@ int tetgenmesh::addsteiner4recoversegment(face* misseg, int splitsegflag)
 
   // Try to recover the edge by adding Steiner points.
   point2tetorg(startpt, searchtet);
-  assert(org(searchtet) == startpt); // SELF_CHECK
-  dir = finddirection(&searchtet, endpt, 1);
+  dir = finddirection(&searchtet, endpt);
   assert(dir != ACROSSVERT);
 
   // Get the first intersecting face/edge.
@@ -21131,7 +20853,7 @@ int tetgenmesh::addsteiner4recoversegment(face* misseg, int splitsegflag)
     ivf.splitbdflag = 0;
     ivf.validflag = 1;
     ivf.respectbdflag = 1;
-    ivf.assignmeshsize = 0;
+    ivf.assignmeshsize = b->metric;
     loc = insertvertex(steinerpt, &searchtet, &splitsh, misseg, &ivf);
 
     if (loc != ivf.iloc) {
@@ -21167,7 +20889,7 @@ int tetgenmesh::addsteiner4recoversegment(face* misseg, int splitsegflag)
     ivf.splitbdflag = 0;
     ivf.validflag = 1;
     ivf.respectbdflag = 1;
-    ivf.assignmeshsize = 0; 
+    ivf.assignmeshsize = b->metric; 
     loc = insertvertex(steinerpt, &searchtet, &splitsh, misseg, &ivf);
 
     assert(loc != (int) ONVERTEX);
@@ -21189,17 +20911,11 @@ int tetgenmesh::addsteiner4recoversegment(face* misseg, int splitsegflag)
 //                                                                           //
 // recoversegments()    Recover all segments.                                //
 //                                                                           //
-// All segments need to be recovered are in 'subsegstack' (Q).  They will be //
-// be recovered one by one.                                                  //
-//                                                                           //
-// Each segment is first tried to be recovered by a sequence of flips which  //
-// removes faces intersecting this segment. However, it is not always possi- //
-// ble to recover it by only this way. Then, Steiner points will be added to //
-// help the recovery of it by flips.                                         // 
+// All segments need to be recovered are in 'subsegstack'.                   //
 //                                                                           //
-// If 'steinerflag' is set, Steiner points will be added if a segment is not //
-// able to recovered by flips.  Otherwise, the segment is not recovered, and //
-// it is returned in 'misseglist'.                                           //
+// This routine first tries to recover each segment by only using flips. If  //
+// no flip is possible, and the flag 'steinerflag' is set, it then tries to  //
+// insert Steiner points near or in the segment.                             //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -21211,7 +20927,7 @@ int tetgenmesh::recoversegments(arraypool *misseglist, int fullsearch,
   point startpt, endpt;
   int success;
 
-  long bak_inpoly_count = st_volref_count; //st_inpoly_count;
+  long bak_inpoly_count = st_volref_count; 
 
   if (b->verbose > 1) {
     printf("    Recover segments [%s level = %2d] #:  %ld.\n",
@@ -21334,7 +21050,6 @@ int tetgenmesh::recoverfacebyflips(point pa, point pb, point pc,
            pointmark(pb), pointmark(pc));
   }
 
-
   fc.fac[0] = pa;
   fc.fac[1] = pb;
   fc.fac[2] = pc;
@@ -21344,8 +21059,7 @@ int tetgenmesh::recoverfacebyflips(point pa, point pb, point pc,
     while (1) {
       // Get a tet containing the edge [a,b].
       point2tetorg(fc.fac[i], *searchtet);
-      assert(org(*searchtet) == fc.fac[i]); // SELF_CHECK
-      dir = finddirection(searchtet, fc.fac[(i+1)%3], 1);
+      dir = finddirection(searchtet, fc.fac[(i+1)%3]);
       //assert(dir == ACROSSVERT);
       assert(dest(*searchtet) == fc.fac[(i+1)%3]);
       // Search the face [a,b,c]
@@ -21553,7 +21267,7 @@ int tetgenmesh::recoversubfaces(arraypool *misshlist, int steinerflag)
         endpt = sdest(searchsh);
         point2tetorg(startpt, searchtet);
         assert(org(searchtet) == startpt); // SELF_CHECK
-        dir = finddirection(&searchtet, endpt, 1);
+        dir = finddirection(&searchtet, endpt);
         if (dir == ACROSSVERT) {
           if (dest(searchtet) == endpt) {
             success = 1;  
@@ -21653,7 +21367,7 @@ int tetgenmesh::recoversubfaces(arraypool *misshlist, int steinerflag)
             ivf.splitbdflag = 0;
             ivf.validflag = 1;
             ivf.respectbdflag = 1;
-            ivf.assignmeshsize = 0;
+            ivf.assignmeshsize = b->metric;
             loc = insertvertex(steinerpt, &searchtet, &searchsh, NULL, &ivf);
             assert(loc != (int) OUTSIDE);
 
@@ -21743,7 +21457,7 @@ int tetgenmesh::recoversubfaces(arraypool *misshlist, int steinerflag)
           ivf.splitbdflag = 0;
           ivf.validflag = 1;
           ivf.respectbdflag = 1;
-          ivf.assignmeshsize = 0; 
+          ivf.assignmeshsize = b->metric; 
           loc = insertvertex(steinerpt, &searchtet, &searchsh, NULL, &ivf);
           assert(loc != (int) OUTSIDE);
 
@@ -21982,13 +21696,13 @@ int tetgenmesh::getedge(point e1, point e2, triface *tedge)
 
   // Search for the edge [e1, e2].
   point2tetorg(e1, *tedge);
-  finddirection(tedge, e2, 1);
+  finddirection(tedge, e2);
   if (dest(*tedge) == e2) {
     return 1;
   } else {
     // Search for the edge [e2, e1].
     point2tetorg(e2, *tedge);
-    finddirection(tedge, e1, 1);
+    finddirection(tedge, e1);
     if (dest(*tedge) == e1) {
       esymself(*tedge);
       return 1;
@@ -22121,7 +21835,7 @@ int tetgenmesh::reduceedgesatvertex(point startpt, arraypool* endptlist)
         }
       } else {
         point2tetorg(startpt, searchtet);
-        dir = finddirection(&searchtet, *pendpt, 1);
+        dir = finddirection(&searchtet, *pendpt);
       }
       if (dir == ACROSSVERT) {
         if (dest(searchtet) == *pendpt) {
@@ -22176,21 +21890,6 @@ int tetgenmesh::reduceedgesatvertex(point startpt, arraypool* endptlist)
 // n edges connected at p. We try to reduce the number of edges by flipping  //
 // any edge (not a segment) that is connecting at p.                         //
 //                                                                           //
-// The original location of 'p' in the tetrahedralization without 'p' is ind-//
-// icated by 'iloc'. 'searchtet' (t) is a tet in the current tetrahedralizat-//
-// ion which contains 'p'. Depending on 'iloc', it means the followig:       //
-//   - INTET:  the origin of 't' is 'p';                                     //
-//   - ONFACE: the origin of 't' is 'p', the face of 't' was split by 'p';   //
-//   - ONEDGE: the origin of 't' is 'p', the edge of 't' was split by 'p';   //
-//                                                                           //
-// If 'parentsh' (s) is given (not NULL), it indicates that 'p' is a Steiner //
-// point on a facet, and 's' was a subface created by the insertion of 'p'.  //
-// 'iloc' must be either ONFACE or 'OEDGE'. The origin of 's' is 'p'.        //
-//                                                                           //
-// If 'parentseg' (seg) is given (not NULL), it indicated that 'p' is a      //
-// Steiner point on a segment, and 'seg' was a subsegment created by 'p'.    //
-// 'iloc' must be ONEDGE. The original of 'seg' is 'p'.                      // 
-//                                                                           //
 // Unless T is a Delaunay tetrahedralization, there is no guarantee that 'p' //
 // can be successfully removed.                                              //
 //                                                                           //
@@ -22241,13 +21940,11 @@ int tetgenmesh::removevertexbyflips(point steinerpt)
     if (b->verbose > 2) {
       printf("      Removing Steiner point %d in facet.\n",
              pointmark(steinerpt));
-
     }
   } else if (vt == FREEVOLVERTEX) {
     if (b->verbose > 2) {
       printf("      Removing Steiner point %d in volume.\n",
              pointmark(steinerpt));
-
     }
   } else {
     // It is not a Steiner point.
@@ -22276,7 +21973,7 @@ int tetgenmesh::removevertexbyflips(point steinerpt)
     //   Inverted elements.
     getvertexstar(1, steinerpt, cavetetlist, NULL, NULL);
     if (cavetetlist->objects == 2) {
-      printf("to be continued...");
+      printf("to be continued...\n");
       assert(0);
     } else {
       assert(0); // Unknown cases.
@@ -22399,7 +22096,7 @@ int tetgenmesh::removevertexbyflips(point steinerpt)
 
   if (!removeflag) {
     if (vt == FREESEGVERTEX) {
-      // Check if the edge [lpr, rpt] exists.
+      // Check if the edge [lpt, rpt] exists.
       if (getedge(lpt, rpt, &searchtet)) {
         // We have recovered this edge. Shift the vertex into the volume.
         // We can recover this edge if the subfaces are not recovered yet.
@@ -22536,14 +22233,6 @@ int tetgenmesh::removevertexbyflips(point steinerpt)
     //   degenerate (has zero volume). It will be deleted in the followed
     //   4-to-1 flip.
     flip32(&(fliptets[3]), 1, 0, 0);
-    // DEBUG BEGIN
-    // fliptets[3] is [a,b,c,p], check it.
-    assert(org(fliptets[3]) == apex(fliptets[0]));  // a
-    assert(dest(fliptets[3]) == apex(fliptets[1])); // b
-    assert(apex(fliptets[3]) == apex(fliptets[2])); // c
-    assert(oppo(fliptets[3]) == steinerpt);
-    // fliptets[4] is [b,a,c,e].
-    // DEBUG END
     // Second do a 4-to-1 flip on [p,d,a,b],[p,d,b,c],[p,d,c,a],[a,b,c,p].
     //   This creates a new tet [a,b,c,d].
     flip41(fliptets, 1, 0, 0);
@@ -22664,7 +22353,7 @@ int tetgenmesh::removevertexbyflips(point steinerpt)
 
     // Insert the new segment.
     point2tetorg(lpt, searchtet);
-    finddirection(&searchtet, rpt, 1);
+    finddirection(&searchtet, rpt);
     assert(dest(searchtet) == rpt);
     sstbond1(rightseg, searchtet);
     spintet = searchtet;
@@ -23249,7 +22938,6 @@ void tetgenmesh::recoverboundary(clock_t& tv)
     printf("  Flip link level = %d\n", b->fliplinklevel);
   }
 
-  //markacutevertices();
 
   if (b->verbose) {
     printf("  Recovering segments.\n");
@@ -23261,16 +22949,6 @@ void tetgenmesh::recoverboundary(clock_t& tv)
   misseglist = new arraypool(sizeof(face), 8);
   bdrysteinerptlist = new arraypool(sizeof(point), 8);
 
-  if (0) { //if (b->order == 4) {  // '-o4' option (for debug)
-    // In sequential order.
-    subsegs->traversalinit();
-    for (i = 0; i < subsegs->items; i++) {
-      searchseg.sh = shellfacetraverse(subsegs);
-      //sinfect(searchseg);  // Only save it once.
-      subsegstack->newindex((void **) &paryseg);
-      *paryseg = searchseg;
-    }
-  } else {
     // In random order.
     subsegs->traversalinit();
     for (i = 0; i < subsegs->items; i++) {
@@ -23284,7 +22962,6 @@ void tetgenmesh::recoverboundary(clock_t& tv)
       paryseg = (face *) fastlookup(subsegstack, s);
       *paryseg = searchseg;
     }
-  }
 
   // The init number of missing segments.
   ms = subsegs->items;
@@ -23294,7 +22971,6 @@ void tetgenmesh::recoverboundary(clock_t& tv)
   }
 
   while (1) {
-
     recoversegments(misseglist, 0, 0);
 
     if (misseglist->objects > 0) {
@@ -23599,10 +23275,11 @@ void tetgenmesh::recoverboundary(clock_t& tv)
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
+
 void tetgenmesh::carveholes()
 {
-  arraypool *tetarray;
-  triface tetloop, neightet, hulltet, *parytet;
+  arraypool *tetarray, *hullarray;
+  triface tetloop, neightet, hulltet, *parytet, *parytet1;
   triface openface, casface;
   triface *regiontets;
   face checksh, casingout, casingin, *parysh;
@@ -23614,20 +23291,27 @@ void tetgenmesh::carveholes()
   int regioncount;
   int attrnum, attr, maxattr;
   int remflag;
-  int i, j;
+  int i, j, k;
 
   tetrahedron ptr;
+  shellface sptr;
 
   if (!b->quiet) {
     printf("Removing exterior tetrahedra ...\n");
   }
 
+
   // Initialize the pool of exterior tets.
   tetarray = new arraypool(sizeof(triface), 10);
-  regiontets = NULL;
+  hullarray = new arraypool(sizeof(triface), 10);
 
+  regiontets = NULL;
+  regioncount = 0;
   maxattr = 0; // Choose a small number here.
-  attrnum = in->numberoftetrahedronattributes;
+  //attrnum = in->numberoftetrahedronattributes;
+  attrnum = numelemattrib - (b->regionattrib > 0); 
+  // Comment: The element region marker is at the end of the list of
+  //   the element attributes.
 
   // Mark as infected any unprotected hull tets.
   tetrahedrons->traversalinit();
@@ -23641,24 +23325,73 @@ void tetgenmesh::carveholes()
         infect(tetloop);
         tetarray->newindex((void **) &parytet);
         *parytet = tetloop;
+        hullsize--;
+        // Add the adjacent tet (not a hull tet) as well.
+        // tetloop's face number is 11 & 3 = 3.
+        decode(tetloop.tet[3], neightet);
+        if (!infected(neightet)) {
+          infect(neightet);
+          tetarray->newindex((void **) &parytet);
+          *parytet = neightet;
+        }
       }
     }
     tetloop.tet = alltetrahedrontraverse();
   }
 
-  hullsize -= tetarray->objects;
-
   if (in->numberofholes > 0) {
     // Mark as infected any tets inside volume holes.
     for (i = 0; i < 3 * in->numberofholes; i += 3) {
       // Search a tet containing the i-th hole point.
       neightet.tet = NULL;
       randomsample(&(in->holelist[i]), &neightet);
-      loc = locate(&(in->holelist[i]), &neightet, 0, 1); // randflag = 1;
+      loc = locate(&(in->holelist[i]), &neightet, 0); 
       if (loc != OUTSIDE) {
-        infect(neightet);
-        tetarray->newindex((void **) &parytet);
-        *parytet = neightet;
+        // The tet 'neightet' contain this point.
+        if (!infected(neightet)) {
+          infect(neightet);
+          tetarray->newindex((void **) &parytet);
+          *parytet = neightet;
+          // Add its adjacent tet if it is not protected.
+          tspivot(neightet, checksh);
+          if (checksh.sh == NULL) {
+            decode(neightet.tet[neightet.ver & 3], tetloop);
+            if (!infected(tetloop)) {
+              infect(tetloop);
+              tetarray->newindex((void **) &parytet);
+              *parytet = tetloop;
+            }
+          } else {
+            // It is protected. Check if its adjacent tet is a hull tet.
+            decode(neightet.tet[neightet.ver & 3], tetloop);
+            if (!infected(tetloop)) {
+              if (ishulltet(tetloop)) {
+                // It is hull tet, add it into the list. Moreover, the subface
+                //   is dead, i.e., both sides are in exterior.
+                infect(tetloop);
+                tetarray->newindex((void **) &parytet);
+                *parytet = tetloop;
+                stdissolve(checksh);
+                assert(!sinfected(checksh));
+                //if (!sinfected(checksh)) {
+                  sinfect(checksh); // Only queue it once.
+                  subfacstack->newindex((void **) &parysh);
+                  *parysh = checksh;
+	        //}
+                hullsize--;              
+              }
+            } else {
+              // Both sides of this subface are in exterior.
+              stdissolve(checksh);
+              assert(!sinfected(checksh));
+              //if (!sinfected(checksh)) {
+                sinfect(checksh); // Only queue it once.
+                subfacstack->newindex((void **) &parysh);
+                *parysh = checksh;
+	      //}
+            }
+          }
+        } // if (!infected(neightet))
       } else {
         // A hole point locates outside of the convex hull.
         if (!b->quiet) {
@@ -23666,7 +23399,7 @@ void tetgenmesh::carveholes()
           printf("lies outside the convex hull.\n");
         }
       }
-    }
+    } // i
   }
 
   if (b->regionattrib && (in->numberofregions > 0)) { // If has -A option.
@@ -23678,7 +23411,7 @@ void tetgenmesh::carveholes()
       // Search a tet containing the i-th region point.
       neightet.tet = NULL;
       randomsample(&(in->regionlist[i]), &neightet);
-      loc = locate(&(in->regionlist[i]), &neightet, 0, 1); // randflag = 1;
+      loc = locate(&(in->regionlist[i]), &neightet, 0); 
       if (loc != OUTSIDE) {
         regiontets[i/5] = neightet;
         if ((int) in->regionlist[i + 3] > maxattr) {
@@ -23694,58 +23427,62 @@ void tetgenmesh::carveholes()
     }
   }
 
+
   // Find and infect all exterior tets (in concave place and in holes).
   for (i = 0; i < tetarray->objects; i++) {
     parytet = (triface *) fastlookup(tetarray, i);
-    tetloop = *parytet;
-    for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
-      fsym(tetloop, neightet);
-      // Is this side protected by a subface?
-      tspivot(tetloop, checksh);
-      if (checksh.sh == NULL) {
-        // Not protected. Infect it if it is not a hull tet.
-        if ((point) neightet.tet[7] != dummypoint) {
-          if (!infected(neightet)) {
+    // Check its three neighbors if it is not a hull tet.
+    if ((point) parytet->tet[7] != dummypoint) {
+      j = (parytet->ver & 3); // j is the current face number.
+      // Check the neighbors of the other three faces.
+      for (k = 0, j++; k < 3; k++, j++) {
+        decode(parytet->tet[j % 4], neightet); // neightet may be a hull tet.
+        if (!infected(neightet)) {
+          // Is neightet protected by a subface.
+          tspivot(neightet, checksh);
+          if (checksh.sh == NULL) {
+            // Not proected. Add it into the list.
+            // It should not be a hull tet. Since all unproected hull tets
+            //   should have already been added into the list.
+            assert(!ishulltet(neightet)); // SELF_CHECK
             infect(neightet);
-            tetarray->newindex((void **) &parytet);
-            *parytet = neightet;
-          }
-        }
-      } else {
-        // Its adjacent tet is protected.
-        if ((point) neightet.tet[7] == dummypoint) {
-          // A hull tet. It is dead.
-          assert(!infected(neightet));
-          infect(neightet);
-          tetarray->newindex((void **) &parytet);
-          *parytet = neightet;
-          // Both sides of this subface are exterior.
-          stdissolve(checksh);
-          // Queue this subface (to be deleted later).
-          if (!sinfected(checksh)) {
-            sinfect(checksh); // Only queue it once.
-            subfacstack->newindex((void **) &parysh);
-            *parysh = checksh;
+            tetarray->newindex((void **) &parytet1);
+            *parytet1 = neightet;
+          } else {
+            // It is protected. However, if neightet is a hull tet, it is
+            //   also an exterior tet. Moverover, the subface is dead, i.e.,
+            //   both sides of it are exterior.
+            if ((point) neightet.tet[7] == dummypoint) {
+              infect(neightet);
+              tetarray->newindex((void **) &parytet1);
+              *parytet1 = neightet;
+              // Both sides of this subface are exterior.
+              stdissolve(checksh);
+              // Queue this subface (to be deleted later).
+              assert(!sinfected(checksh));
+              //if (!sinfected(checksh)) {
+                sinfect(checksh); // Only queue it once.
+                subfacstack->newindex((void **) &parysh);
+                *parysh = checksh;
+	      //}
+              hullsize--;
+            }
           }
-          hullsize--;
         } else {
-          if (!infected(neightet)) {
-            // The subface is still connect to a "live" tet - it survived.
-            // tsbond(neightet, checksh);
-          } else {
-            // Both sides of this subface are exterior.
-            stdissolve(checksh);
-            // Queue this subface (to be deleted later).
+          // Both sides of this face are in exterior.
+          // Check if there is a subface.
+          tspivot(neightet, checksh);
+          if (checksh.sh != NULL) {
             if (!sinfected(checksh)) {
               sinfect(checksh); // Only queue it once.
               subfacstack->newindex((void **) &parysh);
               *parysh = checksh;
-            }
+	    }
           }
         }
-      }
+      } // j, k
     }
-  }
+  } // i
 
   if (b->regionattrib && (in->numberofregions > 0)) {
     // Re-check saved region tets to see if they lie outside.
@@ -23760,65 +23497,76 @@ void tetgenmesh::carveholes()
     }
   }
 
-  // Remove all exterior tetrahedra (including infected hull tets).
-  for (i = 0; i < tetarray->objects; i++) {
-    parytet = (triface *) fastlookup(tetarray, i);
-    tetloop = *parytet;
-    for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
-      fsym(tetloop, neightet);
-      if (!infected(neightet)) {
-        // A "live" tet (may be a hull tet). Clear its adjacent tet.
-        neightet.tet[neightet.ver & 3] = NULL;
-      }
-    }
-    tetrahedrondealloc(parytet->tet);
-  } // i
 
-  tetarray->restart(); // Re-use it for new hull tets.
+if (!b->convex) {
 
   // Create new hull tets. 
   // Update point-to-tet map, segment-to-tet map, and subface-to-tet map.
-  tetrahedrons->traversalinit();
-  tetloop.tet = tetrahedrontraverse();
-  while (tetloop.tet != (tetrahedron *) NULL) {
-    for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
-      if (tetloop.tet[tetloop.ver] == NULL) {
-        tspivot(tetloop, checksh);
-        assert(checksh.sh != NULL); // SELF_CHECK
-        // Create a new hull tet.
-        maketetrahedron(&hulltet);
-        pa = org(tetloop);
-        pb = dest(tetloop);
-        pc = apex(tetloop);
-        setvertices(hulltet, pb, pa, pc, dummypoint);
-        bond(tetloop, hulltet);
-        // Update the subface-to-tet map.
-        sesymself(checksh);
-        tsbond(hulltet, checksh);
-        // Update the segment-to-tet map.
-        for (i = 0; i < 3; i++) {
-          tsspivot1(tetloop, checkseg);
-          if (checkseg.sh != NULL) {
-            tssbond1(hulltet, checkseg);
-            sstbond1(checkseg, hulltet);
+  for (i = 0; i < tetarray->objects; i++) {
+    parytet = (triface *) fastlookup(tetarray, i);
+    if ((point) parytet->tet[7] != dummypoint) {
+      // We must check all four adjacent tets.
+      for (j = 0; j < 4; j++) {
+        decode(parytet->tet[j], tetloop);
+        if (!infected(tetloop)) {
+          // This face becomes a hull face.
+          tspivot(tetloop, checksh);
+          assert(checksh.sh != NULL); // SELF_CHECK
+          maketetrahedron(&hulltet);
+          pa = org(tetloop);
+          pb = dest(tetloop);
+          pc = apex(tetloop);
+          setvertices(hulltet, pb, pa, pc, dummypoint);
+          bond(tetloop, hulltet);
+          // Update the subface-to-tet map.
+          sesymself(checksh);
+          tsbond(hulltet, checksh);
+          // Update the segment-to-tet map.
+          for (k = 0; k < 3; k++) {
+            tsspivot1(tetloop, checkseg);
+            if (checkseg.sh != NULL) {
+              tssbond1(hulltet, checkseg);
+              sstbond1(checkseg, hulltet);
+            }
+            enextself(tetloop);
+            eprevself(hulltet);
+          }
+          // Update the point-to-tet map.
+          ptr = encode(tetloop);
+          setpoint2tet(pa, ptr);
+          setpoint2tet(pb, ptr);
+          setpoint2tet(pc, ptr);
+          // Save this hull tet in list.
+          hullarray->newindex((void **) &parytet1);
+          *parytet1 = hulltet;
+        }
+      } // j
+    } else {
+      // It is a hull tet. Clear the adjacent hull tets' connections to it.
+      // Our data structure ensures that the 3rd face opposites dummypoint.
+      for (j = 0; j < 3; j++) {
+        decode(parytet->tet[j], neightet);
+        if (neightet.tet != NULL) {
+          assert(ishulltet(neightet));
+          if (!infected(neightet)) {
+            neightet.tet[neightet.ver & 3] = NULL;
           }
-          enextself(tetloop);
-          eprevself(hulltet);
         }
-        // Save this hull tet in list.
-        tetarray->newindex((void **) &parytet);
-        *parytet = hulltet;
-      }
-    }
-    // Update the point-to-tet map.
-    tetloop.ver = 0;
-    ptr = encode(tetloop);
-    ppt = (point *) tetloop.tet;
-    for (i = 4; i < 8; i++) {
-      setpoint2tet(ppt[i], ptr);
+      } // j
     }
-    tetloop.tet = tetrahedrontraverse();
-  }
+  } // i
+
+  // Update the hull size.
+  hullsize += hullarray->objects;
+
+  // Remove all exterior tetrahedra (including infected hull tets).
+  for (i = 0; i < tetarray->objects; i++) {
+    parytet = (triface *) fastlookup(tetarray, i);
+    tetrahedrondealloc(parytet->tet);
+  } // i
+
+  tetarray->restart(); 
+
 
   if (subfacstack->objects > 0) {
     // Remove all subfaces which do not attach to any tetrahedron.
@@ -23883,6 +23631,7 @@ void tetgenmesh::carveholes()
     subfacstack->restart();
   }
 
+
   // Some vertices may be not belong to any tet. Mark them.
   delvertcount = unuverts;
   delsteinercount = 0l;
@@ -23950,12 +23699,10 @@ void tetgenmesh::carveholes()
     }
   }
 
-  // Update the hull size.
-  hullsize += tetarray->objects;
 
   // Connect new hull tets.
-  for (i = 0; i < tetarray->objects; i++) {
-    parytet = (triface *) fastlookup(tetarray, i);
+  for (i = 0; i < hullarray->objects; i++) {
+    parytet = (triface *) fastlookup(hullarray, i);
     hulltet = *parytet;
     for (j = 0; j < 3; j++) {
       esym(hulltet, neightet);
@@ -23980,13 +23727,118 @@ void tetgenmesh::carveholes()
     }
   }
 
-  // Set region attributes (when has -A and -AA options).
+} else {  // '-c' option is set.
+
+
+  long bak_subface_count = subfaces->items;
+  long bak_segment_count = subsegs->items;
+
+  // In this case, we regard every hull face/edge is a subface/segment.
+  for (i = 0; i < tetarray->objects; i++) {
+    parytet = (triface *) fastlookup(tetarray, i);
+    // Only need the hull tet to find convex hull faces.
+    if ((point) parytet->tet[7] == dummypoint) {
+      hulltet.tet = parytet->tet;
+      hulltet.ver = 3; // The hull face.
+      tspivot(hulltet, checksh); // SELF_CHECK
+      if (checksh.sh == NULL) {
+        // Create a subface.
+        makeshellface(subfaces, &checksh);
+        pa = org(hulltet);
+        pb = dest(hulltet);
+        pc = apex(hulltet);
+        setsorg(checksh, pa);
+        setsdest(checksh, pb);
+        setsapex(checksh, pc);
+        // Create the point-to-subface map.
+        sptr = sencode(checksh);
+        setpoint2sh(pa, sptr);
+        setpoint2sh(pb, sptr);
+        setpoint2sh(pc, sptr);
+      }
+      // Insert this subface. 
+      // Note: Even the subface is already exist, it may have been 
+      //   disconnected from its adjacent tets.
+      tsbond(hulltet, checksh);
+      fsym(hulltet, neightet);
+      assert(infected(neightet));
+      sesymself(checksh);
+      tsbond(neightet, checksh);
+      sesymself(checksh);
+      // Create three segments.
+      for (j = 0; j < 3; j++) {
+        tsspivot1(hulltet, checkseg);
+        if (checkseg.sh == NULL) {
+          // Create a segment.
+          makeshellface(subsegs, &checkseg);
+          pa = org(hulltet);
+          pb = dest(hulltet);
+          setshvertices(checkseg, pa, pb, NULL);
+          // Insert the segment into the mesh.
+          tetloop = hulltet;
+          pc = apex(hulltet);
+          checksh.sh = NULL;
+          while (1) {
+            tssbond1(tetloop, checkseg);
+            tspivot(tetloop, checksh);
+            if (checksh.sh != NULL) {
+              ssbond1(checksh, checkseg);
+              sbond1(checkseg, checksh);
+            }
+            fnextself(tetloop);
+            if (apex(tetloop) == pc) break;
+          }
+          sstbond1(checkseg, tetloop);
+        }
+        enextself(hulltet);
+      }
+      // Save this hull tet in list.
+      hullarray->newindex((void **) &parytet1);
+      *parytet1 = hulltet;
+    }
+  } // i
+
+  hullsize += hullarray->objects;
+
+  if (subfacstack->objects > 0) {
+    // Uninfect the collected exterior subfaces.
+    for (i = 0; i < subfacstack->objects; i++) {
+      parysh = (face *) fastlookup(subfacstack, i);
+      suninfect(*parysh);
+    }
+  }
+
   if (b->regionattrib) {
+    // Only the hull tets need to be uninfected.
+    for (i = 0; i < hullarray->objects; i++) {
+      parytet = (triface *) fastlookup(hullarray, i);
+      uninfect(*parytet);
+    }
+  } else {
+    // Uninfect all collected tets.
+    for (i = 0; i < tetarray->objects; i++) {
+      parytet = (triface *) fastlookup(tetarray, i);
+      uninfect(*parytet);
+    }
+  }
+
+  tetarray->restart();
+
+  if (b->verbose) {
+    printf("  Created %ld convex hull boundary faces.\n", 
+           subfaces->items - bak_subface_count);
+    printf("  Created %ld convex hull boundary edges.\n", 
+           subsegs->items - bak_segment_count);
+  }
+
+} // if (b->convex)
+
 
+  // Set region attributes (the -A option).
+  if (b->regionattrib) {
     if (!b->quiet) {
       printf("Spreading region attributes.\n");
     }
-    regioncount = 0;
 
     // If has user-defined region attributes.
     if (in->numberofregions > 0) {
@@ -24007,81 +23859,61 @@ void tetgenmesh::carveholes()
             if (b->varvolume) { // If has -a option.
               setvolumebound(tetloop.tet, volume);
             }
-            for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
-              fsym(tetloop, neightet);
-              // Is this side protected by a subface?
-              tspivot(tetloop, checksh);
-              if (checksh.sh == NULL) {
-                // Not protected. It must not be a hull tet.
-                // assert((point) neightet.tet[7] != dummypoint);
-                if ((point) neightet.tet[7] == dummypoint) {
-                  assert(0);
-                }
-                if (!infected(neightet)) {
+            for (k = 0; k < 4; k++) {
+              decode(tetloop.tet[k], neightet);
+              // Is the adjacent already checked?
+              if (!infected(neightet)) {
+                // Is this side protected by a subface?
+                tspivot(neightet, checksh);
+                if (checksh.sh == NULL) {
                   infect(neightet);
                   tetarray->newindex((void **) &parytet);
                   *parytet = neightet;
                 }
-              } else {
-                // Protected. Set attribute for hull tet as well.
-                if ((point) neightet.tet[7] == dummypoint) {
-                  setelemattribute(neightet.tet, attrnum, attr);
-                  if (b->varvolume) { // If has -a option.
-                    setvolumebound(neightet.tet, volume);
-                  }
-                }
               }
-            } // ver
+            } // k
           } // j
           regioncount++;
         } // if (regiontets[i/5].tet != NULL)
       } // i
     }
 
-    if (b->regionattrib > 1) { // If has -AA option.
-      // Set attributes for all tetrahedra.
-      attr = maxattr + 1;
-      tetrahedrons->traversalinit();
-      tetloop.tet = tetrahedrontraverse();
-      while (tetloop.tet != (tetrahedron *) NULL) {
-        if (!infected(tetloop)) {
-          // An unmarked region.
-          tetarray->restart(); // Re-use this array.
-          infect(tetloop);
-          tetarray->newindex((void **) &parytet);
-          *parytet = tetloop;
-          // Find and mark all tets.
-          for (j = 0; j < tetarray->objects; j++) {
-            parytet = (triface *) fastlookup(tetarray, j);
-            tetloop = *parytet;
-            setelemattribute(tetloop.tet, attrnum, attr);
-            for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
-              fsym(tetloop, neightet);
+    // Set attributes for all tetrahedra.
+    attr = maxattr + 1;
+    tetrahedrons->traversalinit();
+    tetloop.tet = tetrahedrontraverse();
+    while (tetloop.tet != (tetrahedron *) NULL) {
+      if (!infected(tetloop)) {
+        // An unmarked region.
+        tetarray->restart(); // Re-use this array.
+        infect(tetloop);
+        tetarray->newindex((void **) &parytet);
+        *parytet = tetloop;
+        // Find and mark all tets.
+        for (j = 0; j < tetarray->objects; j++) {
+          parytet = (triface *) fastlookup(tetarray, j);
+          tetloop = *parytet;
+          setelemattribute(tetloop.tet, attrnum, attr);
+          for (k = 0; k < 4; k++) {
+            decode(tetloop.tet[k], neightet);
+            // Is the adjacent tet already checked?
+            if (!infected(neightet)) {
               // Is this side protected by a subface?
-              tspivot(tetloop, checksh);
+              tspivot(neightet, checksh);
               if (checksh.sh == NULL) {
-                // Not protected. It must not be a hull tet.
-                assert((point) neightet.tet[7] != dummypoint);
-                if (!infected(neightet)) {
-                  infect(neightet);
-                  tetarray->newindex((void **) &parytet);
-                  *parytet = neightet;
-                }
-              } else {
-                // Protected. Set attribute for hull tet as well.
-                if ((point) neightet.tet[7] == dummypoint) {
-                  setelemattribute(neightet.tet, attrnum, attr);
-                }
+                infect(neightet);
+                tetarray->newindex((void **) &parytet);
+                *parytet = neightet;
               }
-            } // loc
-          }
-          attr++; // Increase the attribute.
-          regioncount++;
-        } // if (!infected(tetloop))
-        tetloop.tet = tetrahedrontraverse();
+            }
+          } // k
+        } // j
+        attr++; // Increase the attribute.
+        regioncount++;
       }
-      // Until here, every tet has a region attribute.
+      tetloop.tet = tetrahedrontraverse();
     }
+    // Until here, every tet has a region attribute.
 
     // Uninfect processed tets.
     tetrahedrons->traversalinit();
@@ -24091,8 +23923,6 @@ void tetgenmesh::carveholes()
       tetloop.tet = tetrahedrontraverse();
     }
 
-    // Mesh elements contain region attributes now.
-    in->numberoftetrahedronattributes++;
 
     if (b->verbose) {
       assert(regioncount > 0);
@@ -24102,17 +23932,20 @@ void tetgenmesh::carveholes()
         printf("  Found 1 domain.\n");
       }
     }
-
   } // if (b->regionattrib)
 
   if (b->regionattrib && (in->numberofregions > 0)) { // If has -A option.
     delete [] regiontets;
   }
   delete tetarray;
+  delete hullarray;
+
+if (!b->convex) {
 
   // The mesh is non-convex now.
   nonconvex = 1;
 
+
   // Push all hull tets into 'flipstack'.
   tetrahedrons->traversalinit();
   tetloop.ver = 11; // The face opposite to dummypoint.
@@ -24130,6 +23963,9 @@ void tetgenmesh::carveholes()
   if (b->verbose && (opt_sliver_peels > 0l)) {
     printf("  Peeled %ld hull slivers.\n", opt_sliver_peels);
   }
+
+}
+
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -24672,7 +24508,7 @@ int tetgenmesh::scoutpoint(point searchpt, triface *searchtet, int randflag)
     if (randflag) {
       randomsample(searchpt, searchtet);
     }
-    loc = locate(searchpt, searchtet, 0, 1);
+    loc = locate(searchpt, searchtet, 0);
     if (loc == OUTSIDE) {
       // Not found. This happens when the mesh is not convex.
       if (!randflag) break;
@@ -24824,13 +24660,9 @@ int tetgenmesh::scoutpoint(point searchpt, triface *searchtet, int randflag)
 // 'iloc' indicates the location of the point w.r.t. 'searchtet'.  The size  //
 // is obtained by linear interpolation on the vertices of the tet.           //
 //                                                                           //
-// If 'posflag' is set, only do interpolation when all vertices have a posi- //
-// tive value.                                                               //
-//                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc,
-                                  int posflag)
+REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc)
 {
   point *pts, pa, pb, pc;
   REAL volume, vol[4], wei[4];
@@ -24842,9 +24674,9 @@ REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc,
   if (iloc == (int) INTETRAHEDRON) {
     pts = (point *) &(searchtet->tet[4]);
     assert(pts[3] != dummypoint);
-    if (!posflag || 
-        ((pts[0][pointmtrindex] > 0) && (pts[1][pointmtrindex] > 0) &&
-         (pts[2][pointmtrindex] > 0) && (pts[3][pointmtrindex] > 0))) {
+    // Only do interpolation if all vertices have non-zero sizes.
+    if ((pts[0][pointmtrindex] > 0) && (pts[1][pointmtrindex] > 0) &&
+        (pts[2][pointmtrindex] > 0) && (pts[3][pointmtrindex] > 0)) {
       // P1 interpolation.
       volume = orient3d(pts[0], pts[1], pts[2], pts[3]);
       vol[0] = orient3d(searchpt, pts[1], pts[2], pts[3]);
@@ -24860,9 +24692,8 @@ REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc,
     pa = org(*searchtet);
     pb = dest(*searchtet);
     pc = apex(*searchtet);
-    if (!posflag ||
-        ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0) &&
-         (pc[pointmtrindex] > 0))) {
+    if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0) &&
+        (pc[pointmtrindex] > 0)) {
       volume = triarea(pa, pb, pc);
       vol[0] = triarea(searchpt, pb, pc);
       vol[1] = triarea(pa, searchpt, pc);
@@ -24874,7 +24705,7 @@ REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc,
   } else if (iloc == (int) ONEDGE) {
     pa = org(*searchtet);
     pb = dest(*searchtet);
-    if (!posflag || ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0))) {
+    if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0)) {
       volume = distance(pa, pb);
       vol[0] = distance(searchpt, pb);
       vol[1] = distance(pa, searchpt);
@@ -24883,7 +24714,7 @@ REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc,
     }
   } else if (iloc == (int) ONVERTEX) {
     pa = org(*searchtet);
-    if (!posflag || (pa[pointmtrindex] > 0)) {
+    if (pa[pointmtrindex] > 0) {
       size = pa[pointmtrindex];
     }
   }
@@ -24919,8 +24750,8 @@ void tetgenmesh::interpolatemeshsize()
     searchtet.tet = NULL;
     iloc = bgm->scoutpoint(ploop, &searchtet, 1); // randflag = 1
     if (iloc != (int) OUTSIDE) {
-      // Interpolate the mesh size (posflag = 0)
-      ploop[pointmtrindex] = bgm->getpointmeshsize(ploop, &searchtet, iloc, 0);
+      // Interpolate the mesh size.
+      ploop[pointmtrindex] = bgm->getpointmeshsize(ploop, &searchtet, iloc);
       setpoint2bgmtet(ploop, bgm->encode(searchtet));
       if (count == 0) {
         // This is the first interpolated point.
@@ -24962,7 +24793,8 @@ void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
   face checkseg, *splitseg;
   point newpt;
   insertvertexflags ivf;
-  REAL *attr, x, y, z, w;
+  REAL x, y, z, w;
+  int attribindex, mtrindex;
   int randflag;
   int count, index;
   int loc;
@@ -24975,42 +24807,39 @@ void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
   randflag = 1; // Randomly select start tet for point location. 
   count = 0;
   index = 0;
+  attribindex = 0;
+  mtrindex = 0;
 
   for (i = 0; i < addio->numberofpoints; i++) {
-    makepoint(&newpt, VOLVERTEX);
+    makepoint(&newpt, UNUSEDVERTEX);
     x = newpt[0] = addio->pointlist[index++];
     y = newpt[1] = addio->pointlist[index++];
     z = newpt[2] = addio->pointlist[index++];
+    // Read the point attributes. (Including point weights.)
+    for (j = 0; j < addio->numberofpointattributes; j++) {
+      newpt[3 + j] = addio->pointattributelist[attribindex++];
+    }
+    // Read the point metric tensor.
+    for (j = 0; j < addio->numberofpointmtrs; j++) {
+      newpt[pointmtrindex + j] = addio->pointmtrlist[mtrindex++];
+    }
     if (b->weighted) { // -w option
       if (addio->numberofpointattributes > 0) {
-        // The first point attribute is weight.
-        w = addio->pointattributelist[addio->numberofpointattributes * i];
+        // The first point attribute is its weight.
+        w = newpt[3];
       } else {
-        // No given weight available.
-        w = 0;
+        // No given weight available. Default choose the maximum
+        //   absolute value among its coordinates.        
+        w = fabs(x);
+        if (w < fabs(y)) w = fabs(y);
+        if (w < fabs(z)) w = fabs(z);
       }
       if (b->weighted_param == 0) {
         newpt[3] = x * x + y * y + z * z - w; // Weighted DT.
       } else { // -w1 option
         newpt[3] = w;  // Regular tetrahedralization.
       }
-    } else {
-      newpt[3] = 0;
     }
-    // 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) {
-          newpt[4 + j] = attr[j];
-        }
-      }
-    }
-    // Read the point metric tensor.
-    //for (j = 0; j < in->numberofpointmtrs; j++) {
-    //  pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
-    //}
 
     // Find the location of the inserted point.
     searchtet.tet = NULL;
@@ -25025,14 +24854,14 @@ void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
         ivf.bowywat = 3;   // Use the "Bowyer-Watson" algorithm to form cavity.
         ivf.validflag = 1; // Validate the B-W cavity.
       }
-      ivf.lawson = 3;
-      ivf.rejflag = 0;
+      ivf.lawson = 3;    // ???
+      ivf.rejflag = 0;   // ???
       ivf.chkencflag = 0;
       ivf.sloc = ivf.iloc;
       ivf.sbowywat = ivf.bowywat;  // Surface mesh options.
       ivf.splitbdflag = 1;
       ivf.respectbdflag = 1;
-      ivf.assignmeshsize = 1;
+      ivf.assignmeshsize = b->metric;
 
       splitsh = NULL;
       splitseg = NULL;
@@ -25065,6 +24894,8 @@ void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
           setpointtype(newpt, FACETVERTEX);
           splitsh = &checksh;
         }
+      } else {
+        setpointtype(newpt, VOLVERTEX);
       }
 
       // Insert the vertex.
@@ -25105,8 +24936,6 @@ void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
 //                                                                           //
 // marksharpsegments()    Mark sharp segments.                               //
 //                                                                           //
-// All segments are initialized as type NSHARP.                              //
-//                                                                           //
 // A segment is SHARP if there are two facets intersecting at it with an     //
 // internal dihedral angle (*) less than an angle \theta.                    //
 //                                                                           //
@@ -25139,7 +24968,7 @@ void tetgenmesh::marksharpsegments()
 
   minfacetdihed = PI;
   smallang = 65.0 * PI / 180.0; // 65 degree.
-  exsmallang = 15.0 * PI / 180.0; // 15 degree.
+  exsmallang = 5.0 * PI / 180.0; // 5 degree.
   sharpcount = exsharpcount = 0;
 
   // A segment s may have been split into many subsegments. Operate the one
@@ -25297,13 +25126,8 @@ void tetgenmesh::marksharpsegments()
 //   (4) the square root of a maximal area constraint in a .var file;        //
 //   (5) a maximal length constraint in a .var file;                         //
 //                                                                           //
-// If 'b->nobisect' ('-Y' option) is set, every input vertex has a feature   //
-// size.                                                                     //
-//                                                                           //
-// The feature size of a Steiner point is linearly interpolated from its adj-//
-// acent vertices which belong to the "carrier" (the boundary of the lowrest //
-// dimension) of this Steiner point.  For example, a Steiner point on a seg- //
-// ment gets its size from the two endpoints of the segment.                 //
+// If 'b->nobisect' ('-Y' option) is set, every input vertex has a size. It  //
+// is used to prevent creating too close Steiner points.                     //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -25334,9 +25158,8 @@ void tetgenmesh::decidefeaturepointsizes()
     maxlen = pow(6.0 * b->maxvolume, 1.0 / 3.0);
   }
 
-  // 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. 
+  // First, assign a size of p if p is a feature point or an input point and 
+  //   the -Y option is used.
   featurecount = 0;
   points->traversalinit();
   ploop = pointtraverse();
@@ -25509,9 +25332,9 @@ void tetgenmesh::decidefeaturepointsizes()
     printf("  %d feature points.\n", featurecount);
   }
 
-  // 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.
+  // Second only assign sizes for all Steiner points which were inserted on
+  //   sharp segments. The sizes are interpolated from the endpoints of
+  //   the segments.
   featurecount = 0;
   points->traversalinit();
   ploop = pointtraverse();
@@ -25541,67 +25364,7 @@ void tetgenmesh::decidefeaturepointsizes()
             + (lfs_0 / len) * (e2[pointmtrindex] - e1[pointmtrindex]);
           featurecount++;
         } // if (featureflag)
-      } else if (pointtype(ploop) == FREEFACETVERTEX) {
-        if (b->nobisect) { // -Y option.
-          // Collect vertices in the Star(p) which are also in the facet
-          //   containing p.
-          point2shorg(ploop, parentsh);
-          checksh = parentsh;
-          while (1) {
-            assert(sorg(checksh) == ploop);
-            adjpt = sdest(checksh);
-            // Collect this vertex.
-            verlist->newindex((void **) &parypt);
-            *parypt = adjpt;
-            // Go to the next subface at p. (counterclockwise) 
-            senext2self(checksh);
-            spivotself(checksh);
-            assert(checksh.sh != NULL);
-            if (checksh.sh == parentsh.sh) break;
-            if (sorg(checksh) != ploop) sesymself(checksh);          
-          }
-          assert(verlist->objects > 0);
-          // Using Shepard interpolation (p=1) to interpolate the size for 'p'.
-          //   Re-use len, lfs_0, lfs_1, lfs_2;
-          lfs_1 = lfs_2 = 0;
-          for (i = 0; i < verlist->objects; i++) {
-            parypt = (point *) fastlookup(verlist, i);
-            adjpt = *parypt;
-            if (adjpt[pointmtrindex] > 0) {
-              len = distance(adjpt, ploop);
-              lfs_0 = 1.0 / len;
-              lfs_1 += lfs_0 * adjpt[pointmtrindex];
-              lfs_2 += lfs_0;
-            }
-          }
-          assert(lfs_2 > 0);
-          ploop[pointmtrindex] = lfs_1 / lfs_2;
-          verlist->restart();
-          featurecount++;
-        } // if (b->nobisect)
-      } else if (pointtype(ploop) == FREEVOLVERTEX) {
-        if (b->nobisect) { // -Y option.
-          getvertexstar(1, ploop, tetlist, verlist, NULL);
-          // Using Shepard interpolation to interpolate the size for 'p'.
-          //   Re-use len, lfs_0, lfs_1, lfs_2;
-          lfs_1 = lfs_2 = 0;
-          for (i = 0; i < verlist->objects; i++) {
-            parypt = (point *) fastlookup(verlist, i);
-            adjpt = *parypt;
-            if (adjpt[pointmtrindex] > 0) {
-              len = distance(adjpt, ploop);
-              lfs_0 = 1.0 / len;
-              lfs_1 += lfs_0 * adjpt[pointmtrindex];
-              lfs_2 += lfs_0;
-            }
-          }
-          assert(lfs_2 > 0);
-          ploop[pointmtrindex] = lfs_1 / lfs_2;
-          tetlist->restart();
-          verlist->restart();
-          featurecount++;
-        } // if (b->nobisect)
-      }
+      } 
     } // if (ploop[pointmtrindex] == 0.0)
     ploop = pointtraverse();
   }
@@ -25611,7 +25374,8 @@ void tetgenmesh::decidefeaturepointsizes()
   }
 
   if (checkconstraints) {
-    // A .var file exists. Adjust feature sizes.
+    // A .var file exists. Adjust feature sizes. And make sure that every
+    //   corner of a constraining facet get a size.
     if (in->facetconstraintlist) {
       // Have facet area constrains.
       subfaces->traversalinit();
@@ -25627,6 +25391,9 @@ void tetgenmesh::decidefeaturepointsizes()
               if (ploop[pointmtrindex] > varlen) {
                 ploop[pointmtrindex] = varlen;
               }
+            } else {
+              // This corner has no size yet. Set it.
+              ploop[pointmtrindex] = varlen;
             }
           } // j
         }
@@ -25647,6 +25414,8 @@ void tetgenmesh::decidefeaturepointsizes()
               if (ploop[pointmtrindex] > varlen) {
                 ploop[pointmtrindex] = varlen;
               }
+            } else {
+              ploop[pointmtrindex] = varlen;
             }
           } // j
         }
@@ -25656,6 +25425,7 @@ void tetgenmesh::decidefeaturepointsizes()
   } // if (checkconstraints)
 }
 
+
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // checkseg4encroach()    Check if an edge is encroached upon by a point.    //
@@ -25707,6 +25477,7 @@ int tetgenmesh::checkseg4encroach(point pa, point pb, point checkpt)
 // A segment needs to be split if it is in the following case:               //
 //  (1) It is encroached by an existing vertex.                              //
 //  (2) It has bad quality (too long).                                       //
+//  (3) Its length is larger than the mesh sizes at its endpoints.           //
 //                                                                           //
 // Return 1 if it needs to be split, otherwise, return 0.  'pencpt' returns  //
 // an encroaching point if there exists. 'qflag' returns '1' if the segment  //
@@ -25860,21 +25631,19 @@ int tetgenmesh::splitsegment(face *splitseg, point encpt, int qflag,
     printf("      Split segment (%d, %d).\n", pointmark(pa), pointmark(pb));
   }
 
-
   if (qflag == 0) {
     if (shelltype(*splitseg) == SHARP) {
       // Do not split it (due to a very small angle) even it is encroached.
       // Avoid creating too many Steiner points.
       return 0;
     }
-  }
-
-  // Quickly check if we CAN split this segment.
-  if ((encpt == NULL) && (qflag == 0)) {
-    // Do not split this segment if the length is smaller than the mesh
-    //   size at one of its endpoints.    
-    if ((len < pa[pointmtrindex]) || (len < pb[pointmtrindex])) {
-      return 0;
+    // Quickly check if we CAN split this segment.
+    if (encpt == NULL) {
+      // Do not split this segment if the length is smaller than the mesh
+      //   size at one of its endpoints.    
+      if ((len < pa[pointmtrindex]) || (len < pb[pointmtrindex])) {
+        return 0;
+      }
     }
   }
 
@@ -25882,26 +25651,20 @@ int tetgenmesh::splitsegment(face *splitseg, point encpt, int qflag,
   getsteinerptonsegment(splitseg, encpt, newpt);
 
 
-  // Split the segment by the "Bowyer-Watson" algorithm.
-  // Parameters are chosen as follows: 
-  //   - bowywat = 3, preserve subsegments and subfaces;
-  //   - flipflag = 3, check star & link facets for flipping;
-  //   - rejflag = 0, do insertion even if it encoraches upon
-  //                  other subsegments or subfaces.
+  // Split the segment by the Bowyer-Watson algorithm.
   sstpivot1(*splitseg, searchtet);
   ivf.iloc = (int) ONEDGE;
   if (b->psc) {
     ivf.bowywat = 0;   // Do not enlarge the initial cavity.
     ivf.validflag = 0; // Do not validate the initial cavity.
   } else {
-    ivf.bowywat = 3;   // Use the "Bowyer-Watson" algorithm to form cavity.
+    ivf.bowywat = 3;   // Preserve subsegments and subfaces;
     ivf.validflag = 1; // Validate the B-W cavity.
   }
-  ivf.lawson = 3;
-  ivf.rejflag = 0;
+  ivf.lawson = b->conforming ? 3 : 1; // Check flip for internal new faces?.
+  ivf.rejflag = 0;     // Do not check encroachment of new segments/facets.
   if ((encpt == NULL) && (qflag == 0)) {
-    // Do not insert the point if it lies inside some protecting balls.
-    ivf.rejflag |= 4; 
+    ivf.rejflag |= 4;  // Do check encroachment of protecting balls.
   }
   ivf.chkencflag = chkencflag;
   ivf.sloc = ivf.iloc;
@@ -25909,35 +25672,22 @@ int tetgenmesh::splitsegment(face *splitseg, point encpt, int qflag,
   ivf.splitbdflag = 1;
   ivf.respectbdflag = 1;
   ivf.assignmeshsize = 1;
+
   loc = insertvertex(newpt, &searchtet, &searchsh, splitseg, &ivf);
 
-  // The new vertex should not too close to an existing point.
-  if (loc == (int) NEARVERTEX) {
-    outnodes(0);
-    outsubfaces(0);
-    outsubsegments(0);
-    assert(0);
-  } else if (loc == ENCVERTEX) {
-    // The point lies in some protecting balls. Rejected.
-    pointdealloc(newpt);
-  } else if (loc == (int) BADELEMENT) {
-    // Failed to create a valid sub-cavity in surface mesh.
-    pointdealloc(newpt);
-    //prob_subseg_count++;
-  } else if (loc == (int) ONEDGE) {
-    // Flip not locally Delaunay link facets by the 'Lawson's algo'.
+  if (loc == (int) ONEDGE) {
+    if (b->verbose > 2) {
+      printf("      Point inserted successfully on segment.\n");
+    }
+    // Flip non-locally Delaunay faces at the link of its star.
     lawsonflip3d(newpt, 4, 0, chkencflag, 0);
     st_segref_count++;
     if (steinerleft > 0) steinerleft--;
     return 1;
   } else {
-    // The vertex was not inserted. For unknown reasons.
-    //pointdealloc(newpt);
-    assert(0);
+    pointdealloc(newpt);
+    return 0;
   }
-
-  // Should not be here.
-  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -26123,9 +25873,9 @@ int tetgenmesh::checkfac4split(face *chkfac, point& encpt, int& qflag,
     cent[2] = pa[2] + rhs[2];
     rd = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
 
-    if (b->verbose > 2) {
-      printf("      circent: (%g, %g, %g)\n", cent[0], cent[1], cent[2]);
-      printf("      cirradi: %g\n", rd);
+    if (b->verbose > 3) {
+      printf("        circent: (%g, %g, %g)\n", cent[0], cent[1], cent[2]);
+      printf("        cirradi: %g\n", rd);
     }
 
     // Check the quality (radius-edge ratio) of this subface.
@@ -26142,8 +25892,8 @@ int tetgenmesh::checkfac4split(face *chkfac, point& encpt, int& qflag,
 
 
     D = sqrt(D);
-    if (b->verbose > 2) {
-      printf("      shortest edge length = %g\n", D);
+    if (b->verbose > 3) {
+      printf("        shortest edge length = %g\n", D);
     }
 
     rhs[3] = rd / D; // The radius-edge ratio.
@@ -26199,9 +25949,7 @@ int tetgenmesh::checkfac4split(face *chkfac, point& encpt, int& qflag,
       }
       sesymself(*chkfac);
     }
-  } else {
-    assert(0);
-  } // if (!lu_decomp)
+  } 
 
   return 0;
 }
@@ -26258,9 +26006,6 @@ int tetgenmesh::splitsubface(face *splitfac, point encpt, int qflag,
     rd = distance(ccent, pa);
     if ((rd <= pa[pointmtrindex]) || (rd <= pb[pointmtrindex]) ||
         (rd <= pc[pointmtrindex])) {
-      if (b->verbose > 2) {
-        printf("      Encroaching a protecting ball. Rejected.\n");
-      }
       return 0;
     }
   }
@@ -26268,8 +26013,6 @@ int tetgenmesh::splitsubface(face *splitfac, point encpt, int qflag,
   // Initialize the inserting point.
   makepoint(&newpt, FREEFACETVERTEX);
 
-  if (0) {
-  } else {
     // Split the subface at its circumcenter.
     for (i = 0; i < 3; i++) newpt[i] = ccent[i];
     // Search a subface which contains 'newpt'.
@@ -26288,15 +26031,15 @@ int tetgenmesh::splitsubface(face *splitfac, point encpt, int qflag,
       pointdealloc(newpt);
       return 0;
     }
-  }
+
 
   // Insert the point.
   stpivot(searchsh, searchtet);
   //assert((ivf.iloc == (int) ONFACE) || (ivf.iloc == (int) ONEDGE));
-  // Split the subface by the "Bowyer-Watson" algorithm.
-  ivf.bowywat = 3; // Form B-W cavity.
-  ivf.lawson = 3; // Queue faces of the cavity for flipping.
-  ivf.rejflag = 1; // Reject it if it encroached upon any segment.
+  // Split the subface by the Bowyer-Watson algorithm.
+  ivf.bowywat = 3; // Preserve segments and subfaces.
+  ivf.lawson = b->conforming ? 3 : 1;
+  ivf.rejflag = 1; // Do check the encroachment of segments.
   if (qflag == 0) {
     ivf.rejflag |= 4; // Reject it if it encroached upon any vertex.
   }
@@ -26313,57 +26056,54 @@ int tetgenmesh::splitsubface(face *splitfac, point encpt, int qflag,
 
   loc = insertvertex(newpt, &searchtet, &searchsh, NULL, &ivf);
 
-  if (loc == (int) ENCSEGMENT) {
-    // The new point encroaches upon some segments.
-    pointdealloc(newpt);
-    assert(encseglist->objects > 0);
-    // Select an encroached segment and split it.
-    splitflag = 0;
-    for (i = 0; i < encseglist->objects; i++) {
-      paryseg = (face *) fastlookup(encseglist, i);
-      if (splitsegment(paryseg, NULL, qflag, chkencflag | 1)) {
-        splitflag = 1; // A point is inserted on a segment.
-        break;
-      }
-    }
-    encseglist->restart();
-    if (splitflag) {
-      // Some segments may need to be repaired.
-      repairencsegs(chkencflag | 1);
-      // Queue this subface if it is still alive and not queued.
-      if (splitfac->sh[3] != NULL) {
-        if (!smarktest2ed(*splitfac)) {
-          bface = (badface *) badsubfacs->alloc();
-          bface->ss = *splitfac;
-          smarktest2(bface->ss); // Only queue it once.
-          bface->forg = sorg(*splitfac); // An alive badface.
-        }
-      }
+  if (loc == (int) ivf.iloc) {
+    if (b->verbose > 2) {
+      printf("      Point inserted successfully on facet.\n");
     }
-    return splitflag;
-  } else if (loc == (int) ENCVERTEX) {
-    // The point lies inside some protecting balls. Rejected.
-    pointdealloc(newpt);
-  } else if (loc == (int) ONVERTEX) {
-    pointdealloc(newpt);
-  } else if (loc == (int) NEARVERTEX) {
-    pointdealloc(newpt);
-  } else if (loc == (int) BADELEMENT) {
-    // Failed to create a valid sub-cavity in surface mesh.
-    pointdealloc(newpt);
-  } else if (loc == (int) ivf.iloc) {
     // Flip not locally Delaunay link facets.
     lawsonflip3d(newpt, 4, 0, chkencflag, 0);
     st_facref_count++;
     if (steinerleft > 0) steinerleft--;
-    return 1; // A point is inserted on facet.
+    return 1;
   } else {
-    // Unknown error.
-    assert(0);
+    // Point was not inserted.
+    if (loc == (int) ENCSEGMENT) {
+      if (b->verbose > 2) {
+        printf("      Point encroached upon %ld segments.\n", 
+               encseglist->objects);
+      }
+      assert(encseglist->objects > 0);
+      pointdealloc(newpt);
+      // Select an encroached segment and split it.
+      splitflag = 0;
+      for (i = 0; i < encseglist->objects; i++) {
+        paryseg = (face *) fastlookup(encseglist, i);
+        if (splitsegment(paryseg, NULL, qflag, chkencflag | 1)) {
+          splitflag = 1; // A point is inserted on a segment.
+          break;
+        }
+      }
+      encseglist->restart();
+      if (splitflag) {
+        // Some segments may need to be repaired.
+        repairencsegs(chkencflag | 1);
+        // Queue this subface if it is still alive and not queued.
+        if (splitfac->sh[3] != NULL) {
+          if (!smarktest2ed(*splitfac)) {
+            bface = (badface *) badsubfacs->alloc();
+            bface->ss = *splitfac;
+            smarktest2(bface->ss); // Only queue it once.
+            bface->forg = sorg(*splitfac); // An alive badface.
+          }
+        }
+      }
+      return splitflag;
+    } else {
+      pointdealloc(newpt);
+      return 0;
+    }
   }
 
-  // Should not be here.
-  return 0;  
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -26428,6 +26168,7 @@ void tetgenmesh::repairencfacs(int chkencflag)
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
+
 int tetgenmesh::checktet4split(triface *chktet, int &qflag, REAL *ccent) 
 {
   point pa, pb, pc, pd, *ppt;
@@ -26468,8 +26209,8 @@ int tetgenmesh::checktet4split(triface *chktet, int &qflag, REAL *ccent)
 
   if (!lu_decmp(A, 3, indx, &D, 0)) {
     // A degenerated tet (vol = 0).
-    if (b->verbose > 2) {
-      printf("      Min dihed = 0 (degree)\n");
+    if (b->verbose > 3) {
+      printf("        Min dihed = 0 (degree)\n");
     }
     // Return its barycenter.
     for (i = 0; i < 3; i++) {
@@ -26481,8 +26222,8 @@ int tetgenmesh::checktet4split(triface *chktet, int &qflag, REAL *ccent)
   // Check volume if '-a#' and '-a' options are used.
   if (b->varvolume || b->fixedvolume) {
     vol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
-    if (b->verbose > 2) {
-      printf("      volume = %g.\n", vol);
+    if (b->verbose > 3) {
+      printf("        volume = %g.\n", vol);
     }
     if (b->fixedvolume) {
       if (vol > b->maxvolume) {
@@ -26545,8 +26286,8 @@ int tetgenmesh::checktet4split(triface *chktet, int &qflag, REAL *ccent)
     }
     smlen = sqrt(smlen);
     D = rd / smlen;
-    if (b->verbose > 2) {
-      printf("      Ratio-edge ratio = %g, smlen = %g\n", D, smlen);
+    if (b->verbose > 3) {
+      printf("        Ratio-edge ratio = %g, smlen = %g\n", D, smlen);
     }
     if (D > b->minratio) {
       // A bad radius-edge ratio.
@@ -26586,8 +26327,8 @@ int tetgenmesh::checktet4split(triface *chktet, int &qflag, REAL *ccent)
       maxcosd = (cosd[i] > maxcosd ? cosd[i] : maxcosd);
       //mincosd = (cosd[i] < mincosd ? cosd[i] : maxcosd);
     }
-    if (b->verbose > 2) {
-      printf("      Min dihed = %g (degree)\n", acos(maxcosd) / PI * 180.0);
+    if (b->verbose > 3) {
+      printf("        Min dihed = %g (degree)\n", acos(maxcosd) / PI * 180.0);
     }
     if (maxcosd > cosmindihed) {
       // Calculate the circumcenter of this tet.
@@ -26672,17 +26413,12 @@ int tetgenmesh::splittetrahedron(triface* splittet, int qflag, REAL *ccent,
   makepoint(&newpt, FREEVOLVERTEX);
   for (i = 0; i < 3; i++) newpt[i] = ccent[i];
 
+
   searchtet = *splittet;
   ivf.iloc = (int) OUTSIDE;
-  // Parameters are chosen as follows: 
-  //   - bowywat = 3, preserve subsegments and subfaces;
-  //   - flipflag = 3, check star & link facets for flipping;
-  //   - rejflag = 3, do not insert the point if it encroaches upon
-  //                  any segment or subface.
-  //   - chkencflag = 4, (as input), only check tetrahedra.
-  ivf.bowywat = 3;
-  ivf.lawson = 3;
-  ivf.rejflag = 3;
+  ivf.bowywat = 3;  // Preserve subsegments and subfaces;
+  ivf.lawson = b->conforming ? 3 : 1;
+  ivf.rejflag = 3;  // Do check for encroached segments and subfaces.
   if (qflag == 0) {
     ivf.rejflag |= 4; // Reject it if it lies in some protecting balls.
   }
@@ -26699,7 +26435,10 @@ int tetgenmesh::splittetrahedron(triface* splittet, int qflag, REAL *ccent,
   loc = insertvertex(newpt, &searchtet, NULL, NULL, &ivf);
 
   if (loc == (int) ENCSEGMENT) {
-    // There are encroached segments.
+    if (b->verbose > 2) {
+      printf("      Point encroached upon %ld segments.\n", 
+             encseglist->objects);
+    }
     pointdealloc(newpt);
     assert(encseglist->objects > 0);
     splitflag = 0;
@@ -26731,7 +26470,10 @@ int tetgenmesh::splittetrahedron(triface* splittet, int qflag, REAL *ccent,
     }
     return splitflag;
   } else if (loc == (int) ENCSUBFACE) {
-    // There are encroached subfaces.
+    if (b->verbose > 2) {
+      printf("      Point encroached upon %ld subfaces.\n", 
+             encshlist->objects);
+    }
     pointdealloc(newpt);
     assert(encshlist->objects > 0);
     splitflag = 0;
@@ -26782,6 +26524,9 @@ int tetgenmesh::splittetrahedron(triface* splittet, int qflag, REAL *ccent,
   } else if (loc == (int) BADELEMENT) {
     pointdealloc(newpt);
   } else {
+    if (b->verbose > 2) {
+      printf("      Point inserted successfully.\n");
+    }
     // Recover Delaunayness.
     lawsonflip3d(newpt, 4, 0, chkencflag, 0);
     // Vertex is inserted.
@@ -26850,6 +26595,7 @@ void tetgenmesh::repairbadtets(int chkencflag)
   }
 }
 
+
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // enforcequality()    Refine the mesh.                                      //
@@ -26866,13 +26612,16 @@ void tetgenmesh::delaunayrefinement()
   int chkencflag;
 
   long bak_segref_count, bak_facref_count, bak_volref_count;
+  long bak_flipcount = flip23count + flip32count + flip44count;
 
   if (!b->quiet) {
     printf("Refining mesh...\n");
   }
 
   if (b->verbose) {
-    printf("  Edge length limit = %g.\n", b->minedgelength);
+    printf("  Min radiu-edge ratio = %g.\n", b->minratio);
+    printf("  Min dihedral   angle = %g.\n", b->mindihedral);
+    //printf("  Min Edge length = %g.\n", b->minedgelength);
   }
 
   steinerleft = b->steinerleft;  // Upperbound of # Steiner points (by -S#).
@@ -26884,7 +26633,7 @@ void tetgenmesh::delaunayrefinement()
     } else {
       if (!b->quiet) {
         printf("\nWarning:  ");
-        printf("The desired number of Steiner points (%d) is reached.\n\n",
+        printf("The desired number of Steiner points (%d) has reached.\n\n",
                b->steinerleft);
       }
       return; // No more Steiner points.
@@ -26899,6 +26648,7 @@ void tetgenmesh::delaunayrefinement()
 
   decidefeaturepointsizes();
 
+
   encseglist = new arraypool(sizeof(face), 8);
   encshlist = new arraypool(sizeof(badface), 8);
 
@@ -27008,6 +26758,8 @@ void tetgenmesh::delaunayrefinement()
              st_segref_count - bak_segref_count,
              st_facref_count - bak_facref_count,
              st_volref_count - bak_volref_count);
+      printf("  Performed %ld flips.\n", flip23count + flip32count +
+             flip44count - bak_flipcount);
     }
   } // if (b->reflevel > 2)
 
@@ -27060,10 +26812,10 @@ void tetgenmesh::recoverdelaunay()
     printf("Recovering Delaunayness...\n");
   }
 
-  if (b->verbose) {
-    printf("  max_flipstarsize = %d.\n", b->optmaxflipstarsize);
-    printf("  max_fliplinklevel = %d.\n", b->delmaxfliplevel);
-  }
+  //if (b->verbose) {
+  //  printf("  max_flipstarsize = %d.\n", b->optmaxflipstarsize);
+  //  printf("  max_fliplinklevel = %d.\n", b->delmaxfliplevel);
+  //}
 
   calc_tetprism_vol = 1;
   tetprism_vol_sum = 0.0; // Initialize it.
@@ -27121,7 +26873,7 @@ void tetgenmesh::recoverdelaunay()
   // For efficiency reason, we limit the maximium size of the edge star.
   // 'b->optmaxflipstarsize' is set by -OOOOO (5 Os), default is 10.
   int bakmaxflipstarsize = b->flipstarsize;
-  b->flipstarsize = b->optmaxflipstarsize;
+  b->flipstarsize = 10; //b->optmaxflipstarsize;
 
   flipqueue = new arraypool(sizeof(badface), 10);
   nextflipqueue = new arraypool(sizeof(badface), 10);
@@ -27286,14 +27038,15 @@ long tetgenmesh::improvequalitybyflips()
   flipqueue = new arraypool(sizeof(badface), 10);
   nextflipqueue = new arraypool(sizeof(badface), 10);
 
-  // Flip edge options.
-  b->fliplinklevel = -1;
-  autofliplinklevel = 1; // Init value.
+  // Backup flip edge options.
+  int bakautofliplinklevel = autofliplinklevel;
+  int bakfliplinklevel = b->fliplinklevel;
+  int bakmaxflipstarsize = b->flipstarsize;
 
-  // For efficiency reason, we limit the maximium size of the edge star.
-  // 'b->optmaxflipstarsize' is set by -OOOOO (5 Os), default is 10.
-  int bakmaxflipstarsize = b->flipstarsize; 
-  b->flipstarsize = b->optmaxflipstarsize; 
+  // Set flip edge options.
+  autofliplinklevel = 1; 
+  b->fliplinklevel = -1;
+  b->flipstarsize = 10; // b->optmaxflipstarsize;
 
   fc.remove_large_angle = 1;
   fc.unflip = 1;
@@ -27320,6 +27073,7 @@ long tetgenmesh::improvequalitybyflips()
         bface  = (badface *) fastlookup(flipqueue, k);
         if (gettetrahedron(bface->forg, bface->fdest, bface->fapex,
                            bface->foppo, &bface->tt)) {
+          //assert(!ishulltet(bface->tt));
           // There are bad dihedral angles in this tet.
           if (bface->tt.ver != 11) {
             // The dihedral angles are permuted.
@@ -27413,12 +27167,12 @@ long tetgenmesh::improvequalitybyflips()
     totalremcount += remcount;
 
     if (unflipqueue->objects > 0l) {
-      // 'b->optmaxfliplevel' is set by -OOO, default is 2.
-      if (autofliplinklevel >= b->optmaxfliplevel) {
-        // For efficiency reason, we do not search too far.
+      //if (autofliplinklevel >= b->optmaxfliplevel) {
+      if (autofliplinklevel >= b->optlevel) {
         break;
       }
       autofliplinklevel+=b->fliplinklevelinc;
+      //b->flipstarsize = 10 + (1 << (b->optlevel - 1));
     }
 
     // Swap the two flip queues.
@@ -27427,6 +27181,9 @@ long tetgenmesh::improvequalitybyflips()
     unflipqueue = swapqueue;
   } // while (flipqueues->objects > 0)
 
+  // Restore original flip edge options.
+  autofliplinklevel = bakautofliplinklevel;
+  b->fliplinklevel = bakfliplinklevel;
   b->flipstarsize = bakmaxflipstarsize;
 
   delete flipqueue;
@@ -27855,7 +27612,7 @@ int tetgenmesh::splitsliver(triface *slitet, REAL cosd, int chkencflag)
   int loc;
   int n, i;
 
-  // 'slitet' is [c,d,a,b], where [c,d] has a big hihedral angle. 
+  // 'slitet' is [c,d,a,b], where [c,d] has a big dihedral angle. 
   // Go to the opposite edge [a,b].
   eprev(*slitet, searchtet);
   esymself(searchtet);
@@ -27868,13 +27625,18 @@ int tetgenmesh::splitsliver(triface *slitet, REAL cosd, int chkencflag)
   }
 
   // Count the number of tets shared at [a,b].
+  // Do not split it if it is a hull edge.
   spintet = searchtet;
   n = 0; 
   while (1) {
+    if (ishulltet(spintet)) break;
     n++;
     fnextself(spintet);
     if (spintet.tet == searchtet.tet) break;
   }
+  if (ishulltet(spintet)) {
+    return 0; // It is a hull edge.
+  }
   assert(n >= 3);
 
   // Get all tets at edge [a,b].
@@ -28121,11 +27883,12 @@ long tetgenmesh::removeslivers(int chkencflag)
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-void tetgenmesh::optimizemesh(int optflag)
+void tetgenmesh::optimizemesh()
 {
   badface *parybface;
   triface checktet;
   point *ppt;
+  int optpasses;
   optparameters opm;
   REAL ncosdd[6], maxdd;
   long totalremcount, remcount;
@@ -28139,17 +27902,15 @@ void tetgenmesh::optimizemesh(int optflag)
     printf("Optimizing mesh...\n");
   }
 
-  if (b->verbose > 1) {
-    printf("    min_max_dihedral = %g.\n", b->optmaxdihedral);
-    printf("    max_flipstarsize = %d.\n", b->optmaxflipstarsize);
-    printf("    max_fliplinklevel = %d.\n", b->optmaxfliplevel);
-    printf("    number of passes = %d.\n", b->optpasses);
+  if (b->verbose) {
+    printf("  Optimization level  = %d.\n", b->optlevel);
+    printf("  Optimization scheme = %d.\n", b->optscheme);
+    printf("  Min_Max dihed angle = %g.\n", b->optmaxdihedral);
   }
-  totalsmtcount = totalsptcount = totalremcount = 0l;
 
-  if (b->verbose > 1) {
-    printf("    Removing large angles (> %g degree).\n", b->optmaxdihedral);
-  }
+  optpasses = ((1 << b->optlevel) - 1);
+
+  totalsmtcount = totalsptcount = totalremcount = 0l;
 
   cosmaxdihed = cos(b->optmaxdihedral / 180.0 * PI);
   cossmtdihed = cos(b->optminsmtdihed / 180.0 * PI);
@@ -28181,7 +27942,7 @@ void tetgenmesh::optimizemesh(int optflag)
   totalremcount = improvequalitybyflips();
 
   if ((unflipqueue->objects > 0l) && 
-      ((b->optlevel & 2) || (b->optlevel & 4))) { // -O2 | -O4
+      ((b->optscheme & 2) || (b->optscheme & 4))) {
 
     badtetrahedrons = new memorypool(sizeof(badface), b->tetrahedraperblock,
                                      memorypool::POINTER, 0);
@@ -28195,9 +27956,9 @@ void tetgenmesh::optimizemesh(int optflag)
     chkencflag = 4; // Queue affected tets after splitting a sliver.
     iter = 0;
 
-    while (iter < b->optpasses) {
+    while (iter < optpasses) {
       smtcount = sptcount = remcount = 0l;
-      if (b->optlevel & 2) {
+      if (b->optscheme & 2) {
         smtcount += improvequalitybysmoothing(&opm);
         totalsmtcount += smtcount;
         if (smtcount > 0l) {
@@ -28206,7 +27967,7 @@ void tetgenmesh::optimizemesh(int optflag)
         }
       }
       if (unflipqueue->objects > 0l) {
-        if (b->optlevel & 4) {
+        if (b->optscheme & 4) {
           sptcount += removeslivers(chkencflag);
           totalsptcount += sptcount;
           if (sptcount > 0l) {
@@ -28228,7 +27989,7 @@ void tetgenmesh::optimizemesh(int optflag)
 
     delete badtetrahedrons;
 
-  } // // -O2 | -O4
+  }
 
   if (unflipqueue->objects > 0l) {
     if (b->verbose > 1) {
@@ -28436,10 +28197,10 @@ int tetgenmesh::checkshells(/*int sub2tet*/)
       while ((nextsh.sh != NULL) && (nextsh.sh != shloop.sh)) {
         if (nextsh.sh[3] == NULL) {
           printf("  !! !! Wrong subface-subface connection (Dead subface).\n");
-          printf("    First: x%lx (%d, %d, %d).\n", (unsigned long long) spinsh.sh,
+          printf("    First: x%lx (%d, %d, %d).\n", (unsigned long) spinsh.sh,
                  pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), 
                  pointmark(sapex(spinsh)));
-          printf("    Second: x%lx (DEAD)\n", (unsigned long long) nextsh.sh);
+          printf("    Second: x%lx (DEAD)\n", (unsigned long) nextsh.sh);
           horrors++;
           break;
         }
@@ -28447,10 +28208,10 @@ int tetgenmesh::checkshells(/*int sub2tet*/)
         if (!(((sorg(nextsh) == pa) && (sdest(nextsh) == pb)) ||
               ((sorg(nextsh) == pb) && (sdest(nextsh) == pa)))) {
            printf("  !! !! Wrong subface-subface connection.\n");
-           printf("    First: x%lx (%d, %d, %d).\n", (unsigned long long) spinsh.sh,
+           printf("    First: x%lx (%d, %d, %d).\n", (unsigned long) spinsh.sh,
                   pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), 
                   pointmark(sapex(spinsh)));
-           printf("    Scond: x%lx (%d, %d, %d).\n", (unsigned long long) nextsh.sh,
+           printf("    Scond: x%lx (%d, %d, %d).\n", (unsigned long) nextsh.sh,
                   pointmark(sorg(nextsh)), pointmark(sdest(nextsh)), 
                   pointmark(sapex(nextsh)));
            horrors++;
@@ -28459,10 +28220,10 @@ int tetgenmesh::checkshells(/*int sub2tet*/)
         // Check they should not have the same apex.
         if (sapex(nextsh) == sapex(spinsh)) {
            printf("  !! !! Existing two duplicated subfaces.\n");
-           printf("    First: x%lx (%d, %d, %d).\n", (unsigned long long) spinsh.sh,
+           printf("    First: x%lx (%d, %d, %d).\n", (unsigned long) spinsh.sh,
                   pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), 
                   pointmark(sapex(spinsh)));
-           printf("    Scond: x%lx (%d, %d, %d).\n", (unsigned long long) nextsh.sh,
+           printf("    Scond: x%lx (%d, %d, %d).\n", (unsigned long) nextsh.sh,
                   pointmark(sorg(nextsh)), pointmark(sdest(nextsh)), 
                   pointmark(sapex(nextsh)));
            horrors++;
@@ -28476,19 +28237,19 @@ int tetgenmesh::checkshells(/*int sub2tet*/)
       if (checkseg.sh != NULL) {
         if (checkseg.sh[3] == NULL) {
           printf("  !! !! Wrong subface-subseg connection (Dead subseg).\n");
-          printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) shloop.sh,
+          printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long) shloop.sh,
                  pointmark(sorg(shloop)), pointmark(sdest(shloop)), 
                  pointmark(sapex(shloop)));
-          printf("    Sub: x%lx (Dead)\n", (unsigned long long) checkseg.sh);
+          printf("    Sub: x%lx (Dead)\n", (unsigned long) checkseg.sh);
           horrors++;
         } else {
           if (!(((sorg(checkseg) == pa) && (sdest(checkseg) == pb)) ||
                 ((sorg(checkseg) == pb) && (sdest(checkseg) == pa)))) {
             printf("  !! !! Wrong subface-subseg connection.\n");
-            printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) shloop.sh,
+            printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long) shloop.sh,
                    pointmark(sorg(shloop)), pointmark(sdest(shloop)), 
                    pointmark(sapex(shloop)));
-            printf("    Seg: x%lx (%d, %d).\n", (unsigned long long) checkseg.sh,
+            printf("    Seg: x%lx (%d, %d).\n", (unsigned long) checkseg.sh,
                    pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
             horrors++;
           }
@@ -28502,20 +28263,20 @@ int tetgenmesh::checkshells(/*int sub2tet*/)
     if (neightet.tet != NULL) {
       if (neightet.tet[4] == NULL) {
         printf("  !! !! Wrong sub-to-tet connection (Dead tet)\n");
-        printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) shloop.sh,
+        printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long) shloop.sh,
                pointmark(sorg(shloop)), pointmark(sdest(shloop)), 
                pointmark(sapex(shloop)));
-        printf("    Tet: x%lx (DEAD)\n", (unsigned long long) neightet.tet);
+        printf("    Tet: x%lx (DEAD)\n", (unsigned long) neightet.tet);
         horrors++;
       } else {
         if (!((sorg(shloop) == org(neightet)) && 
               (sdest(shloop) == dest(neightet)))) {
           printf("  !! !! Wrong sub-to-tet connection\n");
-          printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) shloop.sh,
+          printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long) shloop.sh,
                  pointmark(sorg(shloop)), pointmark(sdest(shloop)), 
                  pointmark(sapex(shloop)));
           printf("    Tet: x%lx (%d, %d, %d, %d).\n",
-                 (unsigned long long) neightet.tet, pointmark(org(neightet)), 
+                 (unsigned long) neightet.tet, pointmark(org(neightet)), 
                  pointmark(dest(neightet)), pointmark(apex(neightet)),
                  pointmark(oppo(neightet)));
           horrors++;
@@ -28524,11 +28285,11 @@ int tetgenmesh::checkshells(/*int sub2tet*/)
         if (!((sorg(spinsh) == org(neightet)) && 
               (sdest(spinsh) == dest(neightet)))) {
           printf("  !! !! Wrong tet-sub connection.\n");
-          printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) spinsh.sh,
+          printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long) spinsh.sh,
                  pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), 
                  pointmark(sapex(spinsh)));
           printf("    Tet: x%lx (%d, %d, %d, %d).\n", 
-                 (unsigned long long) neightet.tet, pointmark(org(neightet)), 
+                 (unsigned long) neightet.tet, pointmark(org(neightet)), 
                  pointmark(dest(neightet)), pointmark(apex(neightet)), 
                  pointmark(oppo(neightet)));
           horrors++;
@@ -28539,11 +28300,11 @@ int tetgenmesh::checkshells(/*int sub2tet*/)
           if (!((sorg(spinsh) == org(symtet)) && 
                 (sdest(spinsh) == dest(symtet)))) {
             printf("  !! !! Wrong tet-sub connection.\n");
-            printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) spinsh.sh,
+            printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long) spinsh.sh,
                    pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), 
                    pointmark(sapex(spinsh)));
             printf("    Tet: x%lx (%d, %d, %d, %d).\n", 
-                   (unsigned long long) symtet.tet, pointmark(org(symtet)), 
+                   (unsigned long) symtet.tet, pointmark(org(symtet)), 
                    pointmark(dest(symtet)), pointmark(apex(symtet)), 
                    pointmark(oppo(symtet)));
             horrors++;
@@ -28623,9 +28384,9 @@ int tetgenmesh::checksegments()
                 ((org(tetloop) == pb) && (dest(tetloop) == pa)))) {
             printf("  !! Wrong tet-seg connection.\n");
             printf("    Tet: x%lx (%d, %d, %d, %d) - Seg: x%lx (%d, %d).\n", 
-                   (unsigned long long) tetloop.tet, pointmark(org(tetloop)),
+                   (unsigned long) tetloop.tet, pointmark(org(tetloop)),
                    pointmark(dest(tetloop)), pointmark(apex(tetloop)),
-                   pointmark(oppo(tetloop)), (unsigned long long) sseg.sh,
+                   pointmark(oppo(tetloop)), (unsigned long) sseg.sh,
                    pointmark(pa), pointmark(pb));
             horrors++;
           } else {
@@ -28636,11 +28397,11 @@ int tetgenmesh::checksegments()
               if (checkseg.sh != sseg.sh) {
                 printf("  !! Wrong tet->seg connection.\n");
                 printf("    Tet: x%lx (%d, %d, %d, %d) - ", 
-                       (unsigned long long) neightet.tet, pointmark(org(neightet)),
+                       (unsigned long) neightet.tet, pointmark(org(neightet)),
                        pointmark(dest(neightet)), pointmark(apex(neightet)),
                        pointmark(oppo(neightet)));
                 if (checkseg.sh != NULL) {
-                  printf("Seg x%lx (%d, %d).\n", (unsigned long long) checkseg.sh,
+                  printf("Seg x%lx (%d, %d).\n", (unsigned long) checkseg.sh,
                          pointmark(sorg(checkseg)),pointmark(sdest(checkseg))); 
                 } else {
                   printf("Seg: NULL.\n");
@@ -28660,9 +28421,9 @@ int tetgenmesh::checksegments()
                 ((org(neightet) == pb) && (dest(neightet) == pa)))) {
               printf("  !! Wrong seg->tet connection (Wrong edge).\n");
               printf("    Tet: x%lx (%d, %d, %d, %d) - Seg: x%lx (%d, %d).\n", 
-                     (unsigned long long) neightet.tet, pointmark(org(neightet)),
+                     (unsigned long) neightet.tet, pointmark(org(neightet)),
                      pointmark(dest(neightet)), pointmark(apex(neightet)),
-                     pointmark(oppo(neightet)), (unsigned long long) sseg.sh,
+                     pointmark(oppo(neightet)), (unsigned long) sseg.sh,
                      pointmark(pa), pointmark(pb));
               horrors++;
             }
@@ -28679,7 +28440,7 @@ int tetgenmesh::checksegments()
         printf("  !! A marked edge: (%d, %d, %d, %d) -- x%lx %d.\n",
                pointmark(org(neightet)), pointmark(dest(neightet)),
                pointmark(apex(neightet)), pointmark(oppo(neightet)),
-               (unsigned long long) neightet.tet, neightet.ver);
+               (unsigned long) neightet.tet, neightet.ver);
         // Check if all tets at the edge are marked.
         spintet = neightet;
         while (1) {
@@ -28688,7 +28449,7 @@ int tetgenmesh::checksegments()
             printf("  !! !! An unmarked edge (%d, %d, %d, %d) -- x%lx %d.\n",
                    pointmark(org(spintet)), pointmark(dest(spintet)),
                    pointmark(apex(spintet)), pointmark(oppo(spintet)),
-                   (unsigned long long) spintet.tet, spintet.ver);
+                   (unsigned long) spintet.tet, spintet.ver);
             horrors++;
           }
           if (spintet.tet == neightet.tet) break;
@@ -28721,7 +28482,7 @@ int tetgenmesh::checksegments()
           //  sesymself(spinsh);
           //  printf("  !! Wrong ori at subface (%d, %d, %d) -- x%lx %d\n",
           //         pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
-          //         pointmark(sapex(spinsh)), (unsigned long long) spinsh.sh,
+          //         pointmark(sapex(spinsh)), (unsigned long) spinsh.sh,
           //         spinsh.shver);
           //  horrors++;
           //}
@@ -28734,7 +28495,7 @@ int tetgenmesh::checksegments()
                 printf("  !! !! No seg at tet (%d, %d, %d, %d) -- x%lx %d\n",
                        pointmark(org(spintet)), pointmark(dest(spintet)),
                        pointmark(apex(spintet)), pointmark(oppo(spintet)),
-                       (unsigned long long) spintet.tet, spintet.ver);
+                       (unsigned long) spintet.tet, spintet.ver);
                 horrors++;
               }
               if (checkseg.sh != sseg.sh) {
@@ -28753,7 +28514,7 @@ int tetgenmesh::checksegments()
         } else { 
           printf("  !! Wrong seg-subface (%d, %d, %d) -- x%lx %d connect\n",
                  pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
-                 pointmark(sapex(spinsh)), (unsigned long long) spinsh.sh,
+                 pointmark(sapex(spinsh)), (unsigned long) spinsh.sh,
                  spinsh.shver);
           horrors++;
           break;
@@ -29575,7 +29336,11 @@ void tetgenmesh::statistics()
   tetnumber = tetrahedrons->items - hullsize;
   facenumber = (tetnumber * 4l + hullsize) / 2l;
 
-  printf("\n  Mesh points: %ld\n", points->items);
+  if (b->weighted) { // -w option
+    printf("\n  Mesh points: %ld\n", points->items - nonregularcount);
+  } else {
+    printf("\n  Mesh points: %ld\n", points->items);
+  }
   printf("  Mesh tetrahedra: %ld\n", tetnumber);
   printf("  Mesh faces: %ld\n", facenumber);
   printf("  Mesh edges: %ld\n", meshedges);
@@ -29584,10 +29349,10 @@ void tetgenmesh::statistics()
     printf("  Mesh boundary faces: %ld\n", subfaces->items);
     printf("  Mesh boundary edges: %ld\n", subsegs->items);
     if (st_segref_count > 0l) {
-      printf("  Steiner points in boundary edges: %ld\n", st_segref_count);
+      printf("  Steiner points on boundary edges: %ld\n", st_segref_count);
     }
     if (st_facref_count > 0l) {
-      printf("  Steiner points in boundary faces: %ld\n", st_facref_count);
+      printf("  Steiner points on boundary faces: %ld\n", st_facref_count);
     }
     if (st_volref_count > 0l) {
       printf("  Steiner points in mesh domain: %ld\n", st_volref_count);
@@ -29596,6 +29361,9 @@ void tetgenmesh::statistics()
     printf("  Convex hull faces: %ld\n", hullsize);
     printf("  Convex hull edges: %ld\n", meshhulledges);
   }
+  if (b->weighted) { // -w option
+    printf("  Skipped non-regular points: %ld\n", nonregularcount);
+  }
   printf("\n");
 
 
@@ -29647,7 +29415,7 @@ void tetgenmesh::jettisonnodes()
     jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) || 
       (pointtype(pointloop) == UNUSEDVERTEX);
     if (jetflag) {
-      // It is a duplicated point, delete it.
+      // It is a duplicated or unused point, delete it.
       pointdealloc(pointloop);
       remcount++;
     } else {
@@ -29662,12 +29430,6 @@ void tetgenmesh::jettisonnodes()
       newidx++;
     }
     oldidx++;
-    //if (oldidx == in->numberofpoints) {
-    //  // Update the numbe of input points (Because some were removed).
-    //  in->numberofpoints -= remcount;
-    //  // Remember this number for output original input nodes.
-    //  jettisoninverts = remcount;
-    //}
     pointloop = pointtraverse();
   }
   if (b->verbose) {
@@ -29683,6 +29445,100 @@ void tetgenmesh::jettisonnodes()
   points->deaditemstack = (void *) NULL;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// highorder()   Create extra nodes for quadratic subparametric elements.    //
+//                                                                           //
+// 'highordertable' is an array (size = numberoftetrahedra * 6) for storing  //
+// high-order nodes of each tetrahedron.  This routine is used only when -o2 //
+// switch is used.                                                           //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::highorder()
+{
+  triface tetloop, worktet, spintet;
+  point *extralist, *adjextralist;
+  point torg, tdest, newpoint;
+  int highorderindex;
+  int i, j;
+
+  if (!b->quiet) {
+    printf("Adding vertices for second-order tetrahedra.\n");
+  }
+
+  // Initialize the 'highordertable'.
+  highordertable = new point[tetrahedrons->items * 6];
+  if (highordertable == (point *) NULL) {
+    terminatetetgen(1);
+  }
+
+  // This will overwrite the slot for element markers.
+  highorderindex = 11;
+
+  // The following line ensures that dead items in the pool of nodes cannot
+  //   be allocated for the extra nodes associated with high order elements.
+  //   This ensures that the primary nodes (at the corners of elements) will
+  //   occur earlier in the output files, and have lower indices, than the
+  //   extra nodes.
+  points->deaditemstack = (void *) NULL;
+
+  // Assign an entry for each tetrahedron to find its extra nodes. At the
+  //   mean while, initialize all extra nodes be NULL.
+  i = 0;
+  tetrahedrons->traversalinit();
+  tetloop.tet = tetrahedrontraverse();
+  while (tetloop.tet != (tetrahedron *) NULL) {
+    tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
+    for (j = 0; j < 6; j++) {
+      highordertable[i + j] = (point) NULL;
+    }
+    i += 6;
+    tetloop.tet = tetrahedrontraverse();
+  }
+
+  // To create a unique node on each edge. Loop over all tetrahedra, and
+  //   look at the six edges of each tetrahedron.  If the extra node in
+  //   the tetrahedron corresponding to this edge is NULL, create a node
+  //   for this edge, at the same time, set the new node into the extra
+  //   node lists of all other tetrahedra sharing this edge.  
+  tetrahedrons->traversalinit();
+  tetloop.tet = tetrahedrontraverse();
+  while (tetloop.tet != (tetrahedron *) NULL) {
+    // Get the list of extra nodes.
+    extralist = (point *) tetloop.tet[highorderindex];
+    worktet.tet = tetloop.tet;
+    for (i = 0; i < 6; i++) {
+      if (extralist[i] == (point) NULL) {
+        // Go to the ith-edge.
+        worktet.ver = edge2ver[i];
+        // Create a new point in the middle of this edge.
+        torg = org(worktet);
+        tdest = dest(worktet);
+        makepoint(&newpoint, FREEVOLVERTEX);
+        for (j = 0; j < 3 + numpointattrib; j++) {
+          newpoint[j] = 0.5 * (torg[j] + tdest[j]);
+        }
+        // Interpolate its metrics.
+        for (j = 0; j < in->numberofpointmtrs; j++) {
+          newpoint[pointmtrindex + j] = 
+            0.5 * (torg[pointmtrindex + j] + tdest[pointmtrindex + j]);
+        }
+        // Set this point into all extra node lists at this edge.
+        spintet = worktet;
+        while (1) {
+          if (!ishulltet(spintet)) {
+            adjextralist = (point *) spintet.tet[highorderindex];
+            adjextralist[ver2edge[spintet.ver]] = newpoint;
+          }
+          fnextself(spintet);
+          if (spintet.tet == worktet.tet) break;
+        }
+      } // if (!extralist[i])
+    } // i
+    tetloop.tet = tetrahedrontraverse();
+  }
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
@@ -29758,7 +29614,7 @@ void tetgenmesh::outnodes(tetgenio* out)
   char outnodefilename[FILENAMESIZE];
   face parentsh;
   point pointloop;
-  int nextras, bmark, marker = 0;
+  int nextras, bmark, marker = 0, weightDT = 0; 
   int coordindex, attribindex;
   int pointnumber, firstindex;
   int index, i;
@@ -29776,7 +29632,11 @@ void tetgenmesh::outnodes(tetgenio* out)
     }
   }
 
-  nextras = in->numberofpointattributes;
+  nextras = numpointattrib;
+  if (b->weighted) { // -w
+    if (b->weighted_param == 0) weightDT = 1; // Weighted DT.
+  }
+
   bmark = !b->nobound && in->pointmarkerlist;
 
   if (out == (tetgenio *) NULL) {
@@ -29860,7 +29720,13 @@ void tetgenmesh::outnodes(tetgenio* out)
               pointloop[0], pointloop[1], pointloop[2]);
       for (i = 0; i < nextras; i++) {
         // Write an attribute.
-        fprintf(outfile, "  %.17g", pointloop[4 + i]);
+        if ((i == 0) && weightDT) {          
+          fprintf(outfile, "  %.17g", pointloop[0] * pointloop[0] +
+             pointloop[1] * pointloop[1] + pointloop[2] * pointloop[2] 
+             - pointloop[3 + i]);
+        } else { 
+          fprintf(outfile, "  %.17g", pointloop[3 + i]);
+        }
       }
       if (bmark) {
         // Write the boundary marker.
@@ -29892,7 +29758,13 @@ void tetgenmesh::outnodes(tetgenio* out)
       // Point attributes.
       for (i = 0; i < nextras; i++) {
         // Output an attribute.
-        out->pointattributelist[attribindex++] = pointloop[4 + i];
+        if ((i == 0) && weightDT) {
+          out->pointattributelist[attribindex++] = 
+            pointloop[0] * pointloop[0] + pointloop[1] * pointloop[1] + 
+            pointloop[2] * pointloop[2] - pointloop[3 + i];
+        } else {
+          out->pointattributelist[attribindex++] = pointloop[3 + i];
+        }
       }
       if (bmark) {
         // Output the boundary marker.  
@@ -30020,7 +29892,7 @@ void tetgenmesh::outelements(tetgenio* out)
   long ntets;
   int firstindex, shift;
   int pointindex, attribindex;
-  int highorderindex = 10; // The reserved pointer.
+  int highorderindex = 11; 
   int elementnumber;
   int eextras;
   int ishulledge;
@@ -30042,7 +29914,7 @@ void tetgenmesh::outelements(tetgenio* out)
   // The number of tets excluding hull tets.
   ntets = tetrahedrons->items - hullsize;
 
-  eextras = in->numberoftetrahedronattributes;
+  eextras = numelemattrib;
   if (out == (tetgenio *) NULL) {
     outfile = fopen(outelefilename, "w");
     if (outfile == (FILE *) NULL) {
@@ -30086,8 +29958,13 @@ void tetgenmesh::outelements(tetgenio* out)
   tptr = tetrahedrontraverse();
   elementnumber = firstindex; // in->firstnumber;
   while (tptr != (tetrahedron *) NULL) {
-    p1 = (point) tptr[4];
-    p2 = (point) tptr[5];
+    if (!b->reversetetori) {
+      p1 = (point) tptr[4];
+      p2 = (point) tptr[5];
+    } else {
+      p1 = (point) tptr[5];
+      p2 = (point) tptr[4];
+    }
     p3 = (point) tptr[6];
     p4 = (point) tptr[7];
     if (out == (tetgenio *) NULL) {
@@ -30095,9 +29972,9 @@ void tetgenmesh::outelements(tetgenio* out)
       fprintf(outfile, "%5d   %5d %5d %5d %5d", elementnumber,
               pointmark(p1) - shift, pointmark(p2) - shift,
               pointmark(p3) - shift, pointmark(p4) - shift);
-      if (0) { // if (b->order == 2) {
+      if (b->order == 2) {
         extralist = (point *) tptr[highorderindex];
-        // Tetrahedron number, indices for four points plus six extra points.
+        // indices for six extra points.
         fprintf(outfile, "  %5d %5d %5d %5d %5d %5d",
           pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
           pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
@@ -30112,7 +29989,7 @@ void tetgenmesh::outelements(tetgenio* out)
       tlist[pointindex++] = pointmark(p2) - shift;
       tlist[pointindex++] = pointmark(p3) - shift;
       tlist[pointindex++] = pointmark(p4) - shift;
-      if (0) { // if (b->order == 2) {
+      if (b->order == 2) {
         extralist = (point *) tptr[highorderindex];
         tlist[pointindex++] = pointmark(extralist[0]) - shift;
         tlist[pointindex++] = pointmark(extralist[1]) - shift;
@@ -30125,10 +30002,8 @@ void tetgenmesh::outelements(tetgenio* out)
         talist[attribindex++] = elemattribute(tptr, i);
       }
     }
-    //if (b->neighout) {
-      // Remember the index of this element.
-      setelemindex(tptr, elementnumber);
-    //}
+    // Remember the index of this element (for counting edges).
+    setelemindex(tptr, elementnumber);
     tptr = tetrahedrontraverse();
     elementnumber++;
   }
@@ -30174,11 +30049,6 @@ void tetgenmesh::outelements(tetgenio* out)
 //                                                                           //
 // outfaces()    Output all faces to a .face file or a tetgenio object.      //
 //                                                                           //
-// The total number of faces f can be calculated as following:  Let t be the //
-// total number of tets. Since each tet has 4 faces, the number t * 4 counts //
-// each interior face twice and each hull face once. So f = (t * 4 + h) / 2, //
-// where h is the total number of hull faces (which is known).               //
-//                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
 void tetgenmesh::outfaces(tetgenio* out)
@@ -30196,6 +30066,12 @@ void tetgenmesh::outfaces(tetgenio* out)
   int facenumber;
   int index;
 
+  // For -o2 option.
+  triface workface;
+  point *extralist, pp[3] = {0,0,0}; 
+  int highorderindex = 11; 
+  int i;
+
   if (out == (tetgenio *) NULL) {
     strcpy(facefilename, b->outfilename);
     strcat(facefilename, ".face");
@@ -30211,7 +30087,6 @@ void tetgenmesh::outfaces(tetgenio* out)
 
   ntets = tetrahedrons->items - hullsize;
   faces = (ntets * 4l + hullsize) / 2l;
-  //bmark = !b->nobound && in->facetmarkerlist;
 
   if (out == (tetgenio *) NULL) {
     outfile = fopen(facefilename, "w");
@@ -30222,7 +30097,8 @@ void tetgenmesh::outfaces(tetgenio* out)
     fprintf(outfile, "%ld  %d\n", faces, !b->nobound);
   } else {
     // Allocate memory for 'trifacelist'.
-    out->trifacelist = new int[faces * 3];
+    //out->trifacelist = new int[faces * 3];
+    out->trifacelist = new int[faces * (b->order == 1 ? 3 : 6)];
     if (out->trifacelist == (int *) NULL) {
       printf("Error:  Out of memory.\n");
       terminatetetgen(1);
@@ -30271,6 +30147,15 @@ void tetgenmesh::outfaces(tetgenio* out)
         torg = org(tface);
         tdest = dest(tface);
         tapex = apex(tface);
+        if (b->order == 2) { // -o2
+          // Get the three extra vertices on edges.
+          extralist = (point *) (tface.tet[highorderindex]);
+          workface = tface;
+          for (i = 0; i < 3; i++) {
+            pp[i] = extralist[ver2edge[workface.ver]];
+            enextself(workface);
+          }
+        }
         if (!b->nobound) {
           // Get the boundary marker of this face.
           if (b->plc || b->refine) { 
@@ -30306,6 +30191,10 @@ void tetgenmesh::outfaces(tetgenio* out)
           fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
                   pointmark(torg) - shift, pointmark(tdest) - shift,
                   pointmark(tapex) - shift);
+          if (b->order == 2) { // -o2
+            fprintf(outfile, "  %4d  %4d  %4d", pointmark(pp[0]) - shift, 
+                    pointmark(pp[1]) - shift, pointmark(pp[2]) - shift);
+          }
           if (!b->nobound) {
             // Output a boundary marker.
             fprintf(outfile, "  %d", marker);
@@ -30319,6 +30208,11 @@ void tetgenmesh::outfaces(tetgenio* out)
           elist[index++] = pointmark(torg) - shift;
           elist[index++] = pointmark(tdest) - shift;
           elist[index++] = pointmark(tapex) - shift;
+          if (b->order == 2) { // -o2
+            elist[index++] = pointmark(pp[0]) - shift;
+            elist[index++] = pointmark(pp[1]) - shift;
+            elist[index++] = pointmark(pp[2]) - shift;
+          }
           if (!b->nobound) {
             emlist[facenumber - in->firstnumber] = marker;
           }
@@ -30454,6 +30348,12 @@ void tetgenmesh::outsubfaces(tetgenio* out)
   int neigh1 = 0, neigh2 = 0;
   int facenumber;
 
+  // For -o2 option.
+  triface workface;
+  point *extralist, pp[3]; 
+  int highorderindex = 11;
+  int i;
+
   if (out == (tetgenio *) NULL) {
     strcpy(facefilename, b->outfilename);
     strcat(facefilename, ".face");
@@ -30467,8 +30367,6 @@ void tetgenmesh::outsubfaces(tetgenio* out)
     }
   }
 
-  //bmark = !b->nobound && in->facetmarkerlist;
-
   if (out == (tetgenio *) NULL) {
     outfile = fopen(facefilename, "w");
     if (outfile == (FILE *) NULL) {
@@ -30479,7 +30377,8 @@ void tetgenmesh::outsubfaces(tetgenio* out)
     fprintf(outfile, "%ld  %d\n", subfaces->items, !b->nobound);
   } else {
     // Allocate memory for 'trifacelist'.
-    out->trifacelist = new int[subfaces->items * 3];
+    //out->trifacelist = new int[subfaces->items * 3];
+    out->trifacelist = new int[subfaces->items * (b->order == 1 ? 3 : 6)];
     if (out->trifacelist == (int *) NULL) {
       terminatetetgen(1);
     }
@@ -30514,18 +30413,39 @@ void tetgenmesh::outsubfaces(tetgenio* out)
   facenumber = firstindex; // in->firstnumber;
   while (faceloop.sh != (shellface *) NULL) {
     stpivot(faceloop, abuttingtet);
+    // If there is a tetrahedron containing this subface, orient it so
+    //   that the normal of this face points to inside of the volume by
+    //   right-hand rule.
+    if (abuttingtet.tet != NULL) {
+      if (ishulltet(abuttingtet)) {
+        fsymself(abuttingtet);
+        assert(!ishulltet(abuttingtet));
+      }
+    }
     if (abuttingtet.tet != NULL) {
-      // If there is a tetrahedron containing this subface, orient it so
-      //   that the normal of this face points to inside of the volume by
-      //   right-hand rule.
       torg = org(abuttingtet);
       tdest = dest(abuttingtet);
       tapex = apex(abuttingtet);
+      if (b->order == 2) { // -o2
+        // Get the three extra vertices on edges.
+        extralist = (point *) (abuttingtet.tet[highorderindex]);
+        workface = abuttingtet;
+        for (i = 0; i < 3; i++) {
+          pp[i] = extralist[ver2edge[workface.ver]];
+          enextself(workface);
+        }
+      }
     } else {
       // This may happen when only a surface mesh be generated.
       torg = sorg(faceloop);
       tdest = sdest(faceloop);
       tapex = sapex(faceloop);
+      if (b->order == 2) { // -o2
+        // There is no extra node list available.
+        pp[0] = torg;
+        pp[1] = tdest;
+        pp[2] = tapex;
+      }
     }
     if (!b->nobound) {
       if (in->facetmarkerlist) {
@@ -30552,6 +30472,10 @@ void tetgenmesh::outsubfaces(tetgenio* out)
       fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
               pointmark(torg) - shift, pointmark(tdest) - shift,
               pointmark(tapex) - shift);
+      if (b->order == 2) { // -o2
+        fprintf(outfile, "  %4d  %4d  %4d", pointmark(pp[0]) - shift, 
+                pointmark(pp[1]) - shift, pointmark(pp[2]) - shift);
+      }
       if (!b->nobound) {
         fprintf(outfile, "    %d", marker);
       }
@@ -30564,6 +30488,11 @@ void tetgenmesh::outsubfaces(tetgenio* out)
       elist[index++] = pointmark(torg) - shift;
       elist[index++] = pointmark(tdest) - shift;
       elist[index++] = pointmark(tapex) - shift;
+      if (b->order == 2) { // -o2
+        elist[index++] = pointmark(pp[0]) - shift;
+        elist[index++] = pointmark(pp[1]) - shift;
+        elist[index++] = pointmark(pp[2]) - shift;
+      }
       if (!b->nobound) {
         emlist[index1++] = marker;
       }
@@ -30605,6 +30534,10 @@ void tetgenmesh::outedges(tetgenio* out)
   int index, index1;
   int i;
 
+  // For -o2 option.
+  point *extralist, pp = NULL; 
+  int highorderindex = 11;
+
   if (out == (tetgenio *) NULL) {
     strcpy(edgefilename, b->outfilename);
     strcat(edgefilename, ".edge");
@@ -30628,7 +30561,8 @@ void tetgenmesh::outedges(tetgenio* out)
     fprintf(outfile, "%ld  %d\n", meshedges, !b->nobound);
   } else {
     // Allocate memory for 'edgelist'.
-    out->edgelist = new int[meshedges * 2];
+    //out->edgelist = new int[meshedges * 2];
+    out->edgelist = new int[meshedges * (b->order == 1 ? 2 : 3)];
     if (out->edgelist == (int *) NULL) {
       printf("Error:  Out of memory.\n");
       terminatetetgen(1);
@@ -30674,13 +30608,24 @@ void tetgenmesh::outedges(tetgenio* out)
       if (spintet.tet == worktet.tet) {
         torg = org(worktet);
         tdest = dest(worktet);
+        if (b->order == 2) { // -o2
+          // Get the extra vertex on this edge.
+          extralist = (point *) worktet.tet[highorderindex];
+          pp = extralist[ver2edge[worktet.ver]];
+        }
         if (out == (tetgenio *) NULL) {
           fprintf(outfile, "%5d   %4d  %4d", edgenumber,
                   pointmark(torg) - shift, pointmark(tdest) - shift);
+          if (b->order == 2) { // -o2
+            fprintf(outfile, "  %4d", pointmark(pp) - shift);
+          }
         } else {
           // Output three vertices of this face;
           elist[index++] = pointmark(torg) - shift;
           elist[index++] = pointmark(tdest) - shift;
+          if (b->order == 2) { // -o2
+            elist[index++] = pointmark(pp) - shift;
+          }
         }
         if (!b->nobound) {
           if (b->plc || b->refine) {
@@ -30737,6 +30682,11 @@ void tetgenmesh::outsubsegments(tetgenio* out)
   int marker;
   int edgenumber;
 
+  // For -o2 option.
+  triface workface, spintet;
+  point *extralist, pp = NULL; 
+  int highorderindex = 11;
+
   if (out == (tetgenio *) NULL) {
     strcpy(edgefilename, b->outfilename);
     strcat(edgefilename, ".edge");
@@ -30760,7 +30710,8 @@ void tetgenmesh::outsubsegments(tetgenio* out)
     fprintf(outfile, "%ld  1\n", subsegs->items);
   } else {
     // Allocate memory for 'edgelist'.
-    out->edgelist = new int[subsegs->items * 2];
+    //out->edgelist = new int[subsegs->items * 2];
+    out->edgelist = new int[subsegs->items * (b->order == 1 ? 2 : 3)];
     if (out->edgelist == (int *) NULL) {
       terminatetetgen(1);
     }
@@ -30787,17 +30738,45 @@ void tetgenmesh::outsubsegments(tetgenio* out)
   while (edgeloop.sh != (shellface *) NULL) {
     torg = sorg(edgeloop);
     tdest = sdest(edgeloop);
+    if (b->order == 2) { // -o2
+      // Get the extra vertex on this edge.
+      sstpivot1(edgeloop, workface);
+      if (workface.tet != NULL) {
+        // We must find a non-hull tet.
+        if (ishulltet(workface)) {
+          spintet = workface;
+          while (1) {
+            fnextself(spintet);
+            if (!ishulltet(spintet)) break;
+            if (spintet.tet == workface.tet) break;
+          }
+          assert(!ishulltet(spintet));
+          workface = spintet;
+        }
+        extralist = (point *) workface.tet[highorderindex];
+        pp = extralist[ver2edge[workface.ver]];
+      } else {
+        pp = torg; // There is no extra node available.
+      }
+    }
     marker = shellmark(edgeloop);
     if (marker == 0) {
       marker = 1; // Default marker of a boundary edge is 1. 
     }
     if (out == (tetgenio *) NULL) {
-      fprintf(outfile, "%5d   %4d  %4d  %d\n", edgenumber,
-              pointmark(torg) - shift, pointmark(tdest) - shift, marker);
+      fprintf(outfile, "%5d   %4d  %4d", edgenumber,
+              pointmark(torg) - shift, pointmark(tdest) - shift);
+      if (b->order == 2) { // -o2
+        fprintf(outfile, "  %4d", pointmark(pp) - shift);
+      }
+      fprintf(outfile, "  %d\n", marker);
     } else {
       // Output three vertices of this face;
       elist[index++] = pointmark(torg) - shift;
       elist[index++] = pointmark(tdest) - shift;
+      if (b->order == 2) { // -o2
+        elist[index++] = pointmark(pp) - shift;
+      }
       out->edgemarkerlist[i++] = marker;
     }
     edgenumber++;
@@ -30912,6 +30891,12 @@ void tetgenmesh::outneighbors(tetgenio* out)
 // internal Delaunay vertex. It is an unbounded polyhedron for a Delaunay    //
 // vertex belonging to the convex hull.                                      //
 //                                                                           //
+// aunay tetrahedralization - the power diagram - of the weighted point set. //
+// Note that the vertices of the power disgram are the centers of the ortho- //
+// spheres of the tetrahedra.                                                //
+//                                                                           //
+// NOTE: This routine is only used when the input is only a set of point.    //
+//                                                                           //
 // Comment: Special thanks to Victor Liu for finding and fixing few bugs.    //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
@@ -31004,7 +30989,12 @@ void tetgenmesh::outvoronoi(tetgenio* out)
       pt[i] = (point) tetloop.tet[4 + i];
       setpoint2tet(pt[i], encode(tetloop));
     }
-    circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
+    if (b->weighted) {
+      orthosphere(pt[0], pt[1], pt[2], pt[3], pt[0][3], pt[1][3], pt[2][3], 
+                  pt[3][3], ccent, NULL);
+    } else {
+      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]);
@@ -31277,7 +31267,8 @@ void tetgenmesh::outvoronoi(tetgenio* out)
   vpointcount = 0;
   while (ploop != (point) NULL) {
     if ((pointtype(ploop) != UNUSEDVERTEX) &&
-        (pointtype(ploop) != DUPLICATEDVERTEX)) { 
+        (pointtype(ploop) != DUPLICATEDVERTEX) &&
+        (pointtype(ploop) != NREGULARVERTEX)) { 
       getvertexstar(1, ploop, tetlist, ptlist, NULL);
       // Mark all vertices. Check if it is a hull vertex.
       ishullvert = 0;
@@ -31337,14 +31328,6 @@ void tetgenmesh::outvoronoi(tetgenio* out)
       if (out == (tetgenio *) NULL) {
         fprintf(outfile, "\n");
       }
-      // DEBUG BEGIN
-      for (i = 0; i < ptlist->objects; i++) {
-        neipt = * (point *) fastlookup(ptlist, i);
-        if (neipt != dummypoint) {
-          assert(!pinfected(neipt));
-        }
-      }
-      // DEBUG END
       tetlist->restart();
       ptlist->restart();
       vpointcount++;
@@ -31583,13 +31566,18 @@ void tetgenmesh::outmesh2medit(char* mfilename)
   tetrahedrons->traversalinit();
   tetptr = tetrahedrontraverse();
   while (tetptr != (tetrahedron *) NULL) {
-    p1 = (point) tetptr[4];
-    p2 = (point) tetptr[5];
+    if (!b->reversetetori) {
+      p1 = (point) tetptr[4];
+      p2 = (point) tetptr[5];
+    } else {
+      p1 = (point) tetptr[5];
+      p2 = (point) tetptr[4];
+    }
     p3 = (point) tetptr[6];
     p4 = (point) tetptr[7];
     fprintf(outfile, "%5d  %5d  %5d  %5d",
             pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
-    if (in->numberoftetrahedronattributes > 0) {
+    if (numelemattrib > 0) {
       fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
     } else {
       fprintf(outfile, "  0");
@@ -31639,7 +31627,7 @@ void tetgenmesh::outmesh2vtk(char* ofilename)
 {
   FILE *outfile;
   char vtkfilename[FILENAMESIZE];
-  point pointloop;
+  point pointloop, p1, p2, p3, p4;
   tetrahedron* tptr;
   double x, y, z;
   int n1, n2, n3, n4;
@@ -31698,10 +31686,15 @@ void tetgenmesh::outmesh2vtk(char* ofilename)
     return;
   }
   while (tptr != (tetrahedron *) NULL) {
-    point p1 = (point) tptr[4];
-    point p2 = (point) tptr[5];
-    point p3 = (point) tptr[6];
-    point p4 = (point) tptr[7];
+    if (!b->reversetetori) {
+      p1 = (point) tptr[4];
+      p2 = (point) tptr[5];
+    } else {
+      p1 = (point) tptr[5];
+      p2 = (point) tptr[4];
+    }
+    p3 = (point) tptr[6];
+    p4 = (point) tptr[7];
     n1 = pointmark(p1) - in->firstnumber;
     n2 = pointmark(p2) - in->firstnumber;
     n3 = pointmark(p3) - in->firstnumber;
@@ -31756,186 +31749,149 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
                     tetgenio *addin, tetgenio *bgmin)
 {
   tetgenmesh m;
-  clock_t tv[17]; // Timing informations (defined in time.h)
+  clock_t tv[10], ts[5]; // Timing informations (defined in time.h)
+  REAL cps = (REAL) CLOCKS_PER_SEC;
 
   tv[0] = clock();
  
   m.b = b;
   m.in = in;
+  m.addin = addin;
 
-  if ((bgmin != NULL) && 
-      ((bgmin->numberofpoints > 0) && (bgmin->pointmtrlist != NULL))) {
+  if ((b->metric) && (bgmin->numberofpoints > 0)) {
     m.bgm = new tetgenmesh(); // Create an empty background mesh.
     m.bgm->b = b;
     m.bgm->in = bgmin;
   }
 
-#ifdef INEXACT_GEOM_PRED
-  if (!b->quiet) {
-    printf("Using inexact geometric predicates.\n");
-  }
-#else
-  exactinit();
-#endif
-
   m.initializepools();
   m.transfernodes();
 
+  exactinit(b->noexact, b->nostaticfilter, m.xmax - m.xmin,
+            m.ymax - m.ymin, m.zmax - m.zmin);
+
   tv[1] = clock();
 
   if (b->refine) {
     m.reconstructmesh();
   } else { // b->plc
-    if (!b->diagnose) {
-      m.incrementaldelaunay(tv[16]);
-    }
+    m.incrementaldelaunay(ts[0]);
   }
 
   tv[2] = clock();
 
   if (!b->quiet) {
     if (b->refine) {
-      printf("Mesh reconstruction seconds:  %g\n", 
-             (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
+      printf("Mesh reconstruction seconds:  %g\n", ((REAL)(tv[2]-tv[1])) / cps);
     } else {
-      if (!b->diagnose) {
-        printf("Delaunay seconds:  %g\n", 
-               (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
-        if (b->verbose) {
-          printf("  Point sorting seconds:  %g\n",
-                 (tv[16] - tv[1]) / (REAL) CLOCKS_PER_SEC);
-#ifdef WITH_RUNTIME_COUNTERS
-          printf("  Point location seconds:  %g\n", 
-                 m.t_ptloc / (REAL) CLOCKS_PER_SEC);
-          printf("  Point insertion seconds:  %g\n", 
-                 m.t_ptinsert / (REAL) CLOCKS_PER_SEC);
-#endif
-        }
+      printf("Delaunay seconds:  %g\n", ((REAL)(tv[2]-tv[1])) / cps);
+      if (b->verbose) {
+        printf("  Point sorting seconds:  %g\n", ((REAL)(ts[0]-tv[1])) / cps);
       }
     }
   }
 
-  if (b->plc) {
+  if (b->plc) { // -p
     m.meshsurface();
-  }
 
-  tv[3] = clock();
+    ts[0] = clock();
 
-  if (!b->quiet) {
-    if (b->plc) {
-      printf("Surface mesh seconds:  %g\n",
-             (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
+    if (!b->quiet) {
+      printf("Surface mesh seconds:  %g\n", ((REAL)(ts[0]-tv[2])) / cps);
+    }
+
+    if (b->diagnose) { // -d
+      m.detectinterfaces();
+
+      ts[1] = clock();
+
+      if (!b->quiet) {
+        printf("Self-intersection seconds:  %g\n", ((REAL)(ts[1]-ts[0])) / cps);
+      }
+
+      // Only output when self-intersecting faces exist.
+      if (m.subfaces->items > 0l) {
+        m.outnodes(out);
+        m.outsubfaces(out);
+      }
+
+      return;
     }
   }
 
-  if (b->plc && b->diagnose) { // -d
-    m.detectinterfaces();
+  tv[3] = clock();
+
+  if ((b->metric) && (m.bgm != NULL)) { // -m
+    m.bgm->initializepools();
+    m.bgm->transfernodes();
+    m.bgm->reconstructmesh();
 
-    tv[4] = clock();
+    ts[0] = clock();
 
     if (!b->quiet) {
-      printf("Self-intersection seconds:  %g\n",
-             (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
+      printf("Background mesh reconstruct seconds:  %g\n",
+             ((REAL)(ts[0] - tv[3])) / cps);
     }
 
-    // Only output when self-intersecting faces exist.
-    if (m.subfaces->items > 0l) {
-      m.outnodes(out);
-      m.outsubfaces(out);
-    }
+    if (b->metric) { // -m
+      m.interpolatemeshsize();
 
-    return;
-  }
+      ts[1] = clock();
 
-  if (b->plc) {
-    if (b->nobisect) { // with -Y option
-      m.recoverboundary(tv[15]);
-    } else {
-      m.constraineddelaunay(tv[15]);
+      if (!b->quiet) {
+        printf("Size interpolating seconds:  %g\n",((REAL)(ts[1]-ts[0])) / cps);
+      }
     }
   }
 
   tv[4] = clock();
 
-  if (!b->quiet) {
-    if (b->plc) {
-      printf("Boundary recovery seconds:  %g\n",  
-             (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
+  if (b->plc) { // -p
+    if (b->nobisect) { // -Y
+      m.recoverboundary(ts[0]);
+    } else {
+      m.constraineddelaunay(ts[0]);
+    }
+
+    ts[1] = clock();
+
+    if (!b->quiet) {
+      printf("Boundary recovery seconds:  %g\n", ((REAL)(ts[1]-tv[4])) / cps);
       if (b->verbose) {
-        printf("  Segment recovery seconds:  %g\n",
-               (tv[15] - tv[3]) / (REAL) CLOCKS_PER_SEC);
-        printf("  Facet recovery seconds:  %g\n",
-               (tv[4] - tv[15]) / (REAL) CLOCKS_PER_SEC);
+        printf("  Segment recovery seconds:  %g\n",((REAL)(ts[0]-tv[4]))/ cps);
+        printf("  Facet recovery seconds:  %g\n", ((REAL)(ts[1]-ts[0])) / cps);
       }
     }
-  }
 
-  if (b->plc && !b->convex) {
     m.carveholes();
-  }
 
-  tv[5] = clock();
+    ts[2] = clock();
 
-  if (!b->quiet) {
-    if (b->plc && !b->convex) {
+    if (!b->quiet) {
       printf("Exterior tets removal seconds:  %g\n", 
-             (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
-
-  if (b->plc && b->nobisect) { 
-    m.suppresssteinerpoints();
-  }
-
-  tv[6] = clock();
-
-  if (!b->quiet) {
-    if (b->plc && b->nobisect) {
-      printf("Steiner suppression seconds:  %g\n",
-             (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
+             ((REAL)(ts[2]-ts[1])) / cps);
     }
-  }
 
-  if (b->plc && b->nobisect) {
-    m.recoverdelaunay(); 
-  }
+    if (b->nobisect) { // -Y
+      m.suppresssteinerpoints();
 
-  tv[7] = clock();
+      ts[3] = clock();
 
-  if (!b->quiet) {
-    if (b->plc && b->nobisect) {
-      printf("Delaunay recovery seconds:  %g\n", 
-             (tv[7] - tv[6]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
+      if (!b->quiet) {
+        printf("Steiner suppression seconds:  %g\n",((REAL)(ts[3]-ts[2]))/cps);
+      }
 
-  if ((b->plc || b->refine) && (b->metric && (m.bgm != NULL))) {
-    m.bgm->initializepools();
-    m.bgm->transfernodes();
-    m.bgm->reconstructmesh();
-  }
+      m.recoverdelaunay(); 
 
-  tv[8] = clock();
+      ts[4] = clock();
 
-  if (!b->quiet) {
-    if ((b->plc || b->refine) && (b->metric && (m.bgm != NULL))) {
-      printf("Background mesh reconstruct seconds:  %g\n",
-             (tv[8] - tv[7]) / (REAL) CLOCKS_PER_SEC);
+      if (!b->quiet) {
+        printf("Delaunay recovery seconds:  %g\n", ((REAL)(ts[4]-ts[3])) / cps);
+      }
     }
   }
 
-  if ((b->plc || b->refine) && (b->metric && (m.bgm != NULL))) {
-    m.interpolatemeshsize();
-  }
-
-  tv[9] = clock();
-
-  if (!b->quiet) {
-    if ((b->plc || b->refine) && (b->metric && (m.bgm != NULL))) {
-      printf("Size interpolating seconds:  %g\n",
-             (tv[9] - tv[8]) / (REAL) CLOCKS_PER_SEC);
-    }
-  }
+  tv[5] = clock();
 
   if ((b->plc || b->refine) && b->insertaddpoints) { // -i
     if ((addin != NULL) && (addin->numberofpoints > 0)) {
@@ -31943,44 +31899,38 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
     }
   }
 
-  tv[10] = clock();
+  tv[6] = clock();
 
   if (!b->quiet) {
     if ((b->plc || b->refine) && b->insertaddpoints) {
       if ((addin != NULL) && (addin->numberofpoints > 0)) {
-        printf("Constrained points seconds:  %g\n", 
-               (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
+        printf("Constrained points seconds:  %g\n", ((REAL)(tv[6]-tv[5]))/cps);
       }
     }
   }
 
 
-  tv[11] = clock();
-
-
-  if ((b->plc || b->refine) && b->quality) {
+  if (b->quality) {
     m.delaunayrefinement();
   }
 
-  tv[12] = clock();
+  tv[7] = clock();
 
   if (!b->quiet) {
-    if ((b->plc || b->refine) && b->quality) {
-      printf("Refinement seconds:  %g\n",
-             (tv[12] - tv[11]) / (REAL) CLOCKS_PER_SEC);
+    if (b->quality) {
+      printf("Refinement seconds:  %g\n", ((REAL)(tv[7] - tv[6])) / cps);
     }
   }
 
-  if ((b->plc || b->refine) && (b->optlevel > 0)) {
-    m.optimizemesh(1);
+  if ((b->plc || b->refine) && (b->optlevel > 0) && !b->conforming) {
+    m.optimizemesh();
   }
 
-  tv[13] = clock();
+  tv[8] = clock();
 
   if (!b->quiet) {
-    if ((b->plc || b->refine) && (b->optlevel > 0)) {
-      printf("Optimization seconds:  %g\n",
-             (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
+    if ((b->plc || b->refine) && (b->optlevel > 0) && !b->conforming) {
+      printf("Optimization seconds:  %g\n", ((REAL)(tv[8] - tv[7])) / cps);
     }
   }
 
@@ -31989,6 +31939,9 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
     m.jettisonnodes();
   }
 
+  if (b->order == 2) {
+    m.highorder();
+  }
 
   if (!b->quiet) {
     printf("\n");
@@ -32007,7 +31960,7 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
     m.outnodes(out);
   }
 
-  if (b->noelewritten == 1) {
+  if (b->noelewritten) {
     if (!b->quiet) {
       printf("NOT writing an .ele file.\n");
     }
@@ -32041,11 +31994,17 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
   }
 
 
-  if (b->edgesout) {
-    if (b->edgesout > 1) {
-      m.outedges(out); // -ee, output all mesh edges. 
+  if (b->nofacewritten) {
+    if (!b->quiet) {
+      printf("NOT writing an .edge file.\n");
+    }
+  } else {
+    if (b->edgesout) { // -e
+      m.outedges(out); // output all mesh edges. 
     } else {
-      m.outsubsegments(out); // -e, only output subsegments.
+      if (b->plc || b->refine) {
+        m.outsubsegments(out); // output subsegments.
+      }
     }
   }
 
@@ -32078,13 +32037,11 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
   }
 
 
-  tv[14] = clock();
+  tv[9] = clock();
 
   if (!b->quiet) {
-    printf("\nOutput seconds:  %g\n",
-           (tv[14] - tv[13]) / (REAL) CLOCKS_PER_SEC);
-    printf("Total running seconds:  %g\n",
-           (tv[14] - tv[0]) / (REAL) CLOCKS_PER_SEC);
+    printf("\nOutput seconds:  %g\n", ((REAL)(tv[9] - tv[8])) / cps);
+    printf("Total running seconds:  %g\n", ((REAL)(tv[9] - tv[0])) / cps);
   }
 
   if (b->docheck) {
diff --git a/contrib/Tetgen1.5/tetgen.h b/contrib/Tetgen1.5/tetgen.h
index 41634d03f49ee9d805eb18e5511c672f8d23478a..e02cbefa45c0b1b4e275a04869d725849b35b8b0 100644
--- a/contrib/Tetgen1.5/tetgen.h
+++ b/contrib/Tetgen1.5/tetgen.h
@@ -5,11 +5,7 @@
 // A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
 //                                                                           //
 // Version 1.5                                                               //
-// February 21, 2012                                                         //
-//                                                                           //
-// PRE-RELEASE TEST CODE.                                                    //
-// PLEASE DO NOT DISTRIBUTE !!                                               //
-// PLEASE HELP ME TO IMPROVE IT !!                                           //
+// October 06, 2012                                                          //
 //                                                                           //
 // Copyright (C) 2002--2012                                                  //
 // Hang Si                                                                   //
@@ -40,34 +36,27 @@
 
 // #define TETLIBRARY
 
-// Uncomment the following line to disable assert macros. These macros are
-//   inserted in places where I hope to catch bugs.
+// Uncomment the following line to disable assert macros. These macros were
+//   inserted in the code where I hoped to catch bugs. They may slow down the
+//   speed of TetGen.
 
 // #define NDEBUG
 
-// To insert lots of self-checks for internal errors, define the SELF_CHECK
-//   symbol.  This will slow down the program a bit. 
-
-// #define SELF_CHECK
-
-// Default, TetGen uses the double precision for a real number.
+// TetGen uses the double precision for a real number. 
 
 #define REAL double
 
 // The types 'intptr_t' and 'uintptr_t' are signed and unsigned integer types,
 //   respectively. They are guaranteed to be the same width as a pointer.
-//   They are defined in <stdint.h> by the C99 Standard.
-//   However, Microsoft Visual C++ doesn't ship with this header file yet. We
-//   need to define them. 
-//   Thanks to Steven G. Johnson (MIT) for the following code. 
-
-// Define the _MSC_VER symbol if you are using Microsoft Visual C++.
-
-// #define _MSC_VER
+//   They are defined in <stdint.h> by the C99 Standard. However, Microsoft 
+//   Visual C++ 2003 -- 2008 (Visual C++ 7.1 - 9) doesn't ship with this header
+//   file. In such case, we can define them by ourself. 
+// Update (learned from Stack Overflow): Visual Studio 2010 and Visual C++ 2010
+//   Express both have stdint.h
 
-// Define the _WIN64 symbol if you are running TetGen on Win64.
-
-// #define _WIN64
+// The following piece of code was provided by Steven Johnson (MIT). Define the
+//   symbol _MSC_VER if you are using Microsoft Visual C++. Moreover, define 
+//   the _WIN64 symbol if you are running TetGen on Win64 systems.
 
 #ifdef _MSC_VER // Microsoft Visual C++
 #  ifdef _WIN64
@@ -93,7 +82,7 @@
 //                                                                           //
 // tetgenio                                                                  //
 //                                                                           //
-// A structure for transfering data into and out of TetGen.                  //
+// A structure for transfering data into and out of TetGen's mesh structure. //
 //                                                                           //
 // It holds a collection of arrays of data, i.e., points, facets, tetrahedra,//
 // and so forth. It contains functions to read and write (input and output)  //
@@ -114,18 +103,18 @@ class tetgenio {
 public:
 
   // A "polygon" describes a simple polygon (no holes). It is not necessarily
-  //   convex.  Each polygon contains number of corners (points) and the same
-  //   number of sides (edges).
-  // Note that the points of the polygon must be given in either counter-
-  //   clockwise or clockwise order and they form a ring, so every two
-  //   consective points forms an edge of the polygon.
+  //   convex. Each polygon contains a number of corners (points) and the same
+  //   number of sides (edges).  The points of the polygon must be given in
+  //   either counterclockwise or clockwise order and they form a ring, so 
+  //   every two consective points forms an edge of the polygon.
   typedef struct {
     int *vertexlist;
     int numberofvertices;
   } polygon;
 
-  // A "facet" describes a facet. Each facet is a polygonal region possibly 
-  //   with holes, edges, and points in it.
+  // A "facet" describes a polygonal region possibly with holes, edges, and 
+  //   points floating in it.  Each facet consists of a list of polygons and
+  //   a list of hole points (which lie strictly inside holes).
   typedef struct {
     polygon *polygonlist;
     int numberofpolygons;
@@ -206,68 +195,73 @@ public:
   //   attributes occupy 'numberofpointattributes' REALs.
   // 'pointmtrlist': An array of metric tensors at points. Each point's
   //   tensor occupies 'numberofpointmtr' REALs.
-  // `pointmarkerlist':  An array of point markers; one integer per point.
+  // 'pointmarkerlist':  An array of point markers; one integer per point.
   REAL *pointlist;
   REAL *pointattributelist;
   REAL *pointmtrlist;
-  int *pointmarkerlist;
+  int  *pointmarkerlist;
   pointparam *pointparamlist;
   int numberofpoints;
   int numberofpointattributes;
   int numberofpointmtrs;
  
-  // `elementlist':  An array of element (triangle or tetrahedron) corners.
-  //   The first element's first corner is at index [0], followed by its
-  //   other corners in counterclockwise order, followed by any other
-  //   nodes if the element represents a nonlinear element.  Each element
-  //   occupies `numberofcorners' ints.
-  // `elementattributelist':  An array of element attributes.  Each
-  //   element's attributes occupy `numberofelementattributes' REALs.
-  // `elementconstraintlist':  An array of constraints, i.e. triangle's
-  //   area or tetrahedron's volume; one REAL per element.  Input only.
-  // `neighborlist':  An array of element neighbors; 3 or 4 ints per
-  //   element.  Output only.
-  int *tetrahedronlist;
+  // 'elementlist':  An array of element (tetrahedron) corners.  The first 
+  //   element's first corner is at index [0], followed by its other corners,
+  //   followed by any other nodes if the element represents a nonlinear 
+  //   element.  Each element occupies 'numberofcorners' ints.
+  // 'elementattributelist':  An array of element attributes.  Each
+  //   element's attributes occupy 'numberofelementattributes' REALs.
+  // 'elementconstraintlist':  An array of constraints, i.e. tetrahedron's
+  //   volume; one REAL per element.  Input only.
+  // 'neighborlist':  An array of element neighbors; 4 ints per element. 
+  //   Output only.
+  int  *tetrahedronlist;
   REAL *tetrahedronattributelist;
   REAL *tetrahedronvolumelist;
-  int *neighborlist;
+  int  *neighborlist;
   int numberoftetrahedra;
   int numberofcorners;
   int numberoftetrahedronattributes;
 
-  // `facetlist':  An array of facets.  Each entry is a structure of facet.
-  // `facetmarkerlist':  An array of facet markers; one int per facet.
+  // 'facetlist':  An array of facets.  Each entry is a structure of facet.
+  // 'facetmarkerlist':  An array of facet markers; one int per facet.
   facet *facetlist;
   int *facetmarkerlist;
   int numberoffacets;
 
-  // `holelist':  An array of holes.  The first hole's x, y and z
-  //   coordinates  are at indices [0], [1] and [2], followed by the
-  //   remaining holes. Three REALs per hole. 
+  // 'holelist':  An array of holes (in volume).  Each hole is given by a
+  //   seed (point) which lies strictly inside it. The first seed's x, y and z
+  //   coordinates are at indices [0], [1] and [2], followed by the
+  //   remaining seeds.  Three REALs per hole. 
   REAL *holelist;
   int numberofholes;
 
-  // `regionlist': An array of regional attributes and volume constraints.
-  //   The first constraint's x, y and z coordinates are at indices [0],
-  //   [1] and [2], followed by the regional attribute at index [3], foll-
-  //   owed by the maximum volume at index [4]. Five REALs per constraint.
-  // Note that each regional attribute is used only if you select the `A'
+  // 'regionlist': An array of regions (subdomains).  Each region is given by
+  //   a seed (point) which lies strictly inside it. The first seed's x, y and
+  //   z coordinates are at indices [0], [1] and [2], followed by the regional
+  //   attribute at index [3], followed by the maximum volume at index [4]. 
+  //   Five REALs per region.
+  // Note that each regional attribute is used only if you select the 'A'
   //   switch, and each volume constraint is used only if you select the
-  //   `a' switch (with no number following).
+  //   'a' switch (with no number following).
   REAL *regionlist;
   int numberofregions;
 
-  // `facetconstraintlist': An array of facet maximal area constraints.
-  //   Two REALs per constraint. The first (at index [0]) is the facet
-  //   marker (cast it to int), the second (at index [1]) is its maximum
-  //   area bound.
+  // 'facetconstraintlist':  An array of facet constraints.  Each constraint
+  //   specifies a maximum area bound on the subfaces of that facet.  The
+  //   first facet constraint is given by a facet marker at index [0] and its
+  //   maximum area bound at index [1], followed by the remaining facet con-
+  //   straints. Two REALs per facet constraint.  Note: the facet marker is
+  //   actually an integer.
   REAL *facetconstraintlist;
   int numberoffacetconstraints;
 
-  // `segmentconstraintlist': An array of segment max. length constraints.
-  //   Three REALs per constraint. The first two (at indcies [0] and [1]) 
-  //   are the indices of the endpoints of the segment, the third (at index
-  //   [2]) is its maximum length bound.
+  // 'segmentconstraintlist': An array of segment constraints. Each constraint 
+  //   specifies a maximum length bound on the subsegments of that segment.
+  //   The first constraint is given by the two endpoints of the segment at
+  //   index [0] and [1], and the maximum length bound at index [2], followed
+  //   by the remaining segment constraints.  Three REALs per constraint. 
+  //   Note the segment endpoints are actually integers.
   REAL *segmentconstraintlist;
   int numberofsegmentconstraints;
 
@@ -275,15 +269,14 @@ public:
   pbcgroup *pbcgrouplist;
   int numberofpbcgroups;
 
-  // `trifacelist':  An array of triangular face endpoints.  The first
-  //   face's endpoints are at indices [0], [1] and [2], followed by the
-  //   remaining faces.  Three ints per face.
-  // `adjtetlist':  An array of adjacent tetrahedra to the faces of
-  //   trifacelist. Each face has at most two adjacent tets, the first
-  //   face's adjacent tets are at [0], [1]. Two ints per face. A '-1'
-  //   indicates outside (no adj. tet). This list is output when '-nn'
-  //   switch is used.
-  // `trifacemarkerlist':  An array of face markers; one int per face.
+  // 'trifacelist':  An array of face (triangle) corners.  The first face's
+  //   corners are at indices [0], [1] and [2], followed by the remaining 
+  //   faces.  Three ints per face.
+  // 'adjtetlist':  An array of adjacent tetrahedra to the faces. The first
+  //   face's two adjacent tetrahedra are at indices [0] and [1], followed by
+  //   the remaining faces.  A '-1' indicates outside (no adj. tet). This list
+  //   is output when '-nn' switch is used. Output only.
+  // 'trifacemarkerlist':  An array of face markers; one int per face.
   int *trifacelist;
   int *adjtetlist;
   int *trifacemarkerlist;
@@ -445,7 +438,7 @@ public:
     pbcgroup *pg;
     int i, j;
 
-    // Notince that this routine assumes that the memory was allocated by 
+    // Notice that this routine assumes that the memory was allocated by 
     //   C++ memory allocation operator 'new'.
 
     if (pointlist != (REAL *) NULL) {
@@ -563,12 +556,13 @@ public:
 //                                                                           //
 // tetgenbehavior                                                            //
 //                                                                           //
-// A structure to maintain the switches and parameters of TetGen.            //
+// A structure for maintaining the switches and parameters used by TetGen's  //
+// meshing algorithms.  They are specified by the command line arguments.    //
 //                                                                           //
-// parse_commandline() provides an simple interface to set the vaules of the //
-// variables.  It accepts the standard parameters (e.g., 'argc' and 'argv')  //
-// that pass to C/C++ main() function. Alternatively a string which contains //
-// the command line options can be used as its parameter.                    //
+// NOTE: Some of the switches are incompatinle to each other, while some are //
+// depend on others.  The routine parse_commandline() sets the switches from //
+// the command line (a list of strings). Morover, it checks the consistency  //
+// of the applied switches.                                                  //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -576,94 +570,81 @@ class tetgenbehavior {
 
 public:
 
-  // Switches of TetGen. They are briefly described in the function syntax().
-  //   Plerase consult the user's manual for complete explanations. The last
-  //   column indicates their initial values. 
-  int plc;                                                 // '-p' switch, 0.
-  int psc;                                                 // '-s' switch, 0.
-  int quality;                                             // '-q' switch, 0.
-  int refine;                                              // '-r' switch, 0.
-  int metric;                                              // '-m' switch, 0.
-  int nobisect;                                            // '-Y' switch, 0.
-  int weighted;                                            // '-w' switch, 0.
-  int varvolume;                            // '-a' switch without number, 0.
-  int fixedvolume;                             // '-a' switch with number, 0.
-  int incrflip;                                            // '-l' switch, 0.
-  int flipinsert;                                          // '-L' switch, 0.
-  int btree;                                               // '-u' switch, 0.
-  int hilbertcurve;                                        // '-U' switch, 0.
-  int insertaddpoints;                                     // '-i' switch, 0.
-  int regionattrib;                                        // '-A' switch, 0.
-  int conforming;                                          // '-D' switch, 0.
-  int diagnose;                                            // '-d' switch, 0.
-  int convex;                                              // '-c' switch, 0.
-  int zeroindex;                                           // '-z' switch, 0.
-  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 vtkview;                                             // '-K' switch, 0.
-  int nobound;                                             // '-B' switch, 0.
-  int nonodewritten;                                       // '-N' switch, 0.
-  int noelewritten;                                        // '-E' switch, 0.
-  int nofacewritten;                                       // '-F' switch, 0.
-  int noiterationnum;                                      // '-I' switch, 0.
-  int nomerge;                                             // '-M' switch, 0.
-  int nojettison;                                          // '-J' switch, 0.
-  int docheck;                                             // '-C' switch, 0.
-  int quiet;                                               // '-Q' switch, 0.
-  int verbose;                                             // '-V' switch, 0.
-
-  // Parameters of TetGen.  They are numbers specified after switches.  The
-  //   last colume indicates their initial values.
-  int vertexperblock;                                    // after '-b', 4092.
-  int tetrahedraperblock;                                // after '-b', 8188.
-  int shellfaceperblock;                                 // after '-b', 4092.
-  int nobisect_param;                                       // after '-Y', 1.
-  int weighted_param;                                       // after '-w', 0.
-  int flipinsert_random;                                    // after '-L', 0.
-  int flipinsert_ori4dexact;                                // after '-L', 0.
-  int fliplinklevel;                                       // after '-L', -1.
-  int flipstarsize;                                       // after '-LL', -1.
-  int fliplinklevelinc;                                  // after '-LLLL', 1.
-  int max_btreenode_size;                                 // after '-u', 100.
-  int reflevel;                                             // after '-D', 3.
-  int optlevel;                                             // after '-O', 7.
-  int optpasses;                                           // after '-OO', 3.
-  int optmaxfliplevel;                                    // after '-OOO', 2.
-  int delmaxfliplevel;                                   // after '-OOOO', 1.
-  int optmaxflipstarsize;                              // after '-OOOOO', 10.
-  int order;                                                // after '-o', 1.
-  int steinerleft;                                          // after '-S', 0.
-  REAL facet_ang_tol;                                   // after '-p', 179.9.
-  REAL maxvolume;                                        // after '-a', -1.0.
-  REAL minratio;                                          // after '-q', 0.0.
-  REAL mindihedral;                                      // after '-qq', 5.0.
-  REAL optmaxdihedral;                                  // after '-o', 165.0.
-  REAL optminsmtdihed;                                 // after '-oo', 175.0.
-  REAL optminslidihed;                                // after '-ooo', 179.0.  
-  REAL epsilon;                                        // after '-T', 1.0e-8.
-  REAL minedgelength;     // The shortest length of an edge, after '-l', 0.0.
-
-  // Variables used to save command line switches and in/out file names.
+  // The list of switches of TetGen. 
+  int plc;                                                         // '-p', 0.
+  int psc;                                                         // '-s', 0.
+  int refine;                                                      // '-r', 0.
+  int quality;                                                     // '-q', 0.
+  int nobisect;                                                    // '-Y', 0.
+  int weighted;                                                    // '-w', 0.
+  int brio_hilbert;                                                // '-b', 1.
+  int incrflip;                                                    // '-l', 0.
+  int flipinsert;                                                  // '-L', 0.
+  int metric;                                                      // '-m', 0.
+  int varvolume;                                                   // '-a', 0.
+  int fixedvolume;                                                 // '-a', 0.
+  int regionattrib;                                                // '-A', 0.
+  int conforming;                                                  // '-D', 0.
+  int insertaddpoints;                                             // '-i', 0.
+  int diagnose;                                                    // '-d', 0.
+  int convex;                                                      // '-c', 0.
+  int nomerge;                                                     // '-M', 0.
+  int noexact;                                                     // '-X', 0.
+  int nostaticfilter;                                              // '-X', 0.
+  int zeroindex;                                                   // '-z', 0.
+  int facesout;                                                    // '-f', 0.
+  int edgesout;                                                    // '-e', 0.
+  int neighout;                                                    // '-n', 0.
+  int voroout;                                                     // '-v', 0.
+  int meditview;                                                   // '-g', 0.
+  int vtkview;                                                     // '-k', 0.
+  int nobound;                                                     // '-B', 0.
+  int nonodewritten;                                               // '-N', 0.
+  int noelewritten;                                                // '-E', 0.
+  int nofacewritten;                                               // '-F', 0.
+  int noiterationnum;                                              // '-I', 0.
+  int nojettison;                                                  // '-J', 0.
+  int reversetetori;                                               // '-R', 0.
+  int docheck;                                                     // '-C', 0.
+  int quiet;                                                       // '-Q', 0.
+  int verbose;                                                     // '-V', 0.
+
+  // The list of parameters of TetGen. 
+  int vertexperblock;                                                 // 4092.
+  int tetrahedraperblock;                                             // 8188.
+  int shellfaceperblock;                                              // 4092.
+  int nobisect_param;                                              // '-Y', 1.
+  int weighted_param;                                              // '-w', 0.
+  int hilbert_order;                                                    // -1.
+  int hilbert_limit;                                                    //  8.
+  int fliplinklevel;                                                    // -1.
+  int flipstarsize;                                                     // -1.
+  int fliplinklevelinc;                                                 //  1.
+  int reflevel;                                                    // '-D', 3.
+  int optlevel;                                                    // '-O', 2.
+  int optscheme;                                                   // '-O', 7.
+  int delmaxfliplevel;                                                   // 1.
+  int order;                                                       // '-o', 1.
+  int steinerleft;                                                 // '-S', 0.
+  REAL facet_ang_tol;                                          // '-p', 179.9.
+  REAL maxvolume;                                               // '-a', -1.0.
+  REAL minratio;                                                 // '-q', 0.0.
+  REAL mindihedral;                                              // '-q', 5.0.
+  REAL optmaxdihedral;                                               // 165.0.
+  REAL optminsmtdihed;                                               // 179.0.
+  REAL optminslidihed;                                               // 179.0.  
+  REAL epsilon;                                               // '-T', 1.0e-8.
+  REAL minedgelength;                                                  // 0.0.
+
+  // Strings of command line arguments and input/output file names.
   char commandline[1024];
   char infilename[1024];
   char outfilename[1024];
   char addinfilename[1024];
   char bgmeshfilename[1024];
 
-  // The input object type of TetGen. They are recognized by the input file
-  //   extensions. Currently the following objects are supported:
-  //   - NODES, a list of nodes (.node); 
-  //   - POLY, a piecewise linear complex (.poly or .smesh); 
-  //   - OFF, a polyhedron (.off, Geomview's file format); 
-  //   - PLY, a polyhedron (.ply, file format from gatech);
-  //   - STL, a surface mesh (.stl, stereolithography format);
-  //   - MEDIT, a surface mesh (.mesh, Medit's file format); 
-  //   - MESH, a tetrahedral mesh (.ele).
-  //   If no extension is available, the imposed commandline switch
-  //   (-p or -r) implies the object. 
+  // The input object of TetGen. They are recognized by either the input 
+  //   file extensions or by the specified options. 
   enum objecttype {NODES, POLY, OFF, PLY, STL, MEDIT, VTK, MESH} object;
 
 
@@ -681,17 +662,18 @@ public:
   {
     plc = 0;
     psc = 0;
-    quality = 0;
     refine = 0;
-    metric = 0;
+    quality = 0;
     nobisect = 0;
+    metric = 0;
     weighted = 0;
-    varvolume = 0;
-    fixedvolume = 0;
+    brio_hilbert = 1;
     incrflip = 0;
     flipinsert = 0;
-    btree = 0;
-    hilbertcurve = 0;
+    varvolume = 0;
+    fixedvolume = 0;
+    noexact = 0;
+    nostaticfilter = 0;
     insertaddpoints = 0;
     regionattrib = 0;
     conforming = 0;
@@ -711,6 +693,7 @@ public:
     noiterationnum = 0;
     nomerge = 0;
     nojettison = 0;
+    reversetetori = 0;
     docheck = 0;
     quiet = 0;
     verbose = 0;
@@ -720,24 +703,21 @@ public:
     shellfaceperblock = 4092;
     nobisect_param = 1;
     weighted_param = 0;
-    flipinsert_random = 0;
-    flipinsert_ori4dexact = 0;
+    hilbert_order = -1;
+    hilbert_limit = 8;
     fliplinklevel = -1; // No limit on linklevel.
     flipstarsize = -1;  // No limit on flip star size.
     fliplinklevelinc = 1;
-    max_btreenode_size = 100; // Default use b-tree sorting.
     reflevel = 3;
-    optlevel = 7;  // 1 & 2 & 4, // min_max_dihedral.
-    optpasses = 3;
-    optmaxfliplevel = 2;
+    optscheme = 7;  // 1 & 2 & 4, // min_max_dihedral.
+    optlevel = 2;
     delmaxfliplevel = 1;
-    optmaxflipstarsize = 10;
     order = 1;
     steinerleft = -1;
     facet_ang_tol = 179.9;
     maxvolume = -1.0;
     minratio = 2.0;
-    mindihedral = 0.0; // 5.0;
+    mindihedral = 5.0; 
     optmaxdihedral = 165.00; // without -q, default is 179.0
     optminsmtdihed = 179.00; // without -q, default is 179.999
     optminslidihed = 179.00; // without -q, default is 179.999
@@ -757,45 +737,44 @@ public:
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// Geometric predicates                                                      //
-//                                                                           //
-// 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.                //
-//                                                                           //
-// 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 //
-// separated by H, which are defined as follows (using the left-hand rule):  //
-// make a fist using your left hand in such a way that your fingers follow   //
-// the order of a, b and c, then your thumb is pointing to H+.  Given any    //
-// point d in R^3, the orientation test returns +1 if d lies in H+, -1 if d  //
-// lies in H-, or 0 if d lies on H.                                          //
-//                                                                           //
-// In-sphere test:  let a, b, c, d be 4 non-coplanar points in R^3.  They    //
-// defines a unique circumsphere S.  Given any point e in R^3, the in-sphere //
-// test returns +1 if e lies inside S, or -1 if e lies outside S, or 0 if e  //
-// lies on S.                                                                //
-//                                                                           //
-// The following routines use arbitrary precision floating-point arithmetic. //
-// They are provided by J. R. Schewchuk in public domain (http://www.cs.cmu. //
-// edu/~quake/robust.html). The source code are in "predicates.cxx".         //
+// Robust Geometric predicates                                               //
+//                                                                           //
+// Geometric predicates are simple tests of spatial relations of a set of d- //
+// dimensional points, such as the orientation test and the point-in-sphere  //
+// test. Each of these tests is performed by evaluating the sign of a deter- //
+// minant of a matrix whose entries are the coordinates of these points.  If //
+// the computation is performed by using the floating-point numbers, e.g.,   //
+// the single or double numbers in C/C++, roundoff error may cause an incor- //
+// rect result. This may either lead to a wrong result or eventually lead to //
+// a failure of the program.                                                 //
+//                                                                           //
+// Various techniques are developed to avoid roundoff errors, such as exact  //
+// multi-precision computations, interval arthmetics, adaptive exact arthme- //
+// tics, and filtered exact arthmetics, etc. Devillers and Pion give a nice  //
+// discussion and comparisons of these techniques for robustly computing the //
+// Delaunay triangulations [Devillers and Pion 2002].                        //
+//                                                                           //
+// The following routines implemented the orientation test and the point-in- //
+// sphere test use the adaptive exact floating-point arithmetics [Shewchuk   //
+// 1997]. They are generously provided by Jonathan Schewchuk in the public   //
+// domain, http://www.cs.cmu.edu/~quake/robust.html. The source code are in  //
+// file "predicates.cxx".                                                    //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-REAL exactinit();
+void exactinit(int, int, REAL, REAL, REAL);
 REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd);
 REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe);
 REAL orient4d(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe,
               REAL ah, REAL bh, REAL ch, REAL dh, REAL eh);
-REAL orient4dexact(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe,
-                   REAL ah, REAL bh, REAL ch, REAL dh, REAL eh);
+void predicates_statistics(int weighted);
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // tetgenmesh                                                                //
 //                                                                           //
-// The object to generate tetrahedral meshes.                                //
+// A structure containing the mesh data structure and the implementations of //
+// tetrahedral meshing algorithms of TetGen.                                 //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -806,7 +785,7 @@ public:
   // Labels that signify the type of a vertex. 
   enum verttype {UNUSEDVERTEX, DUPLICATEDVERTEX, RIDGEVERTEX, ACUTEVERTEX,
                  FACETVERTEX, VOLVERTEX, FREESEGVERTEX, FREEFACETVERTEX, 
-                 FREEVOLVERTEX, HIDDENVERTEX, DEADVERTEX};
+                 FREEVOLVERTEX, NREGULARVERTEX, DEADVERTEX};
  
   // Labels that signify the type of a subsegment.
   enum shestype {NSHARP, SHARP, FAKESH};
@@ -818,7 +797,8 @@ public:
 
   // Labels that signify the result of point location.
   enum locateresult {OUTSIDE, INTETRAHEDRON, ONFACE, ONEDGE, ONVERTEX, INSTAR,
-                     ENCVERTEX, ENCSEGMENT, ENCSUBFACE, NEARVERTEX,BADELEMENT};
+                     ENCVERTEX, ENCSEGMENT, ENCSUBFACE, NEARVERTEX,
+                     NONREGULAR, BADELEMENT};
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
@@ -831,25 +811,23 @@ public:
 // and edges in S and L are respectivly called subfaces and segments to dis- //
 // tinguish them from others in T.                                           //
 //                                                                           //
-// The data structure to represent a tetrahedral mesh stores the tetrahedra  //
-// and vertices of T. Each tetrahedron is a structure including informations //
-// of its vertices and adjacencies. Each vertex carries its geometric coord- //
-// inates. The faces and edges of T are implicitly represented by tetrahedra.//
-// This representation has a clear separation between combinatoric and geom- //
-// etric data of a tetrahedral mesh.                                         //
-//                                                                           //
-// A hull face of T is the face on the exterior domain boundary, i.e., it is //
-// contained by only one tetrahedron in T. TetGen adds fictitious tetrahedra //
-// (one-to-one) at the hull faces of T, and connects them to an "infinite    //
-// vertex" which has no geometric coordinates. One can imagine such a vertex //
-// lies in 4D space and is visible by all tetrahedra containing hull faces.  //
-// The extended set of tetrahedra with the infinite vertex is a tetrahedral- //
-// ization of a compact 3-manifold without bounday. It has the property that //
-// every face is shared by exactly two tetrahedra.                           //
-//                                                                           //
-// The data structure stores explicitly the subfaces and segments (which are //
-// in surface mesh S and the linear mesh L, respectively. Additional inform- //
-// ations are stored in tetrahedra and subfaces to remember their relations. //
+// TetGen stores the tetrahedra and vertices of T. Each tetrahedron contains //
+// pointers to its vertices and adjacent tetrahedra.  Each vertex stores its //
+// x-, y-, and z-coordinates. The faces and edges of T are implicitly repre- //
+// sented by tetrahedra. 
+//                                                                           //
+// Each face of T belongs to either two tetrahedra or one tetrahedron. In    //
+// the latter case, the face is an exterior boundary face of T.  TetGen adds //
+// fictitious tetrahedra (one-to-one) at such faces, and connects them to an //
+// "infinite vertex" (which has no geometric coordinates).  One can imagine  //
+// such a vertex lies in 4D space and is visible by all exterior boundary    //
+// faces.  The extended set of tetrahedra (including the infinite vertex) is //
+// a tetrahedralization of a compact 3-manifold without bounday.  It has the //
+// property that every face is shared by exactly two tetrahedra.             // 
+//                                                                           //
+// TetGen stores explicitly the subfaces and segments (which are in surface  //
+// mesh S and the linear mesh L, respectively. Additional informations are   //
+// stored in tetrahedra and subfaces to remember their relations.            //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -860,7 +838,7 @@ public:
   //   - a list of  six segments (optional, for -p switch);
   //   - a list of user-defined floating-point attributes (optional);
   //   - a volume constraint (optional, for -a switch);
-  //   - an integer of element marker;
+  //   - an integer of element marker (and flags);
   // The structure of a tetrahedron is an array of pointers.  Its actual size
   //   (the length of the array) is determined at runtime.
 
@@ -884,11 +862,11 @@ public:
   //   - u, v coordinates (optional, for -s switch);
   //   - a metric tensor (optional, for -q or -m switch);
   //   - a pointer to an adjacent tetrahedron;
-  //   - a pointer to a parent (or a duplicate) point, or a bsp_tree node;
+  //   - a pointer to a parent (or a duplicate) point;
   //   - a pointer to an adjacent subface or segment (optional, -p switch);
   //   - a pointer to a tet in background mesh (optional, for -m switch);
   //   - an integer for boundary marker (point index);
-  //   - an integer for point type.
+  //   - an integer for point type (and flags).
   //   - an integer for geometry tag (optional, for -s switch).
   // The structure of a point is an array of REALs.  Its acutal size is 
   //   determined at the runtime.
@@ -912,8 +890,8 @@ public:
 // to the tetrahedron and v is a four-bit integer, in the range from 0 to 11,//
 // identifying the ordered version of the tetrahedron.  Assume the faces of  //
 // the tetrahedron is numbered from 0 to 3, and the edges in a face is numb- //
-// ered from 0 to 2. The first two bits of v is used to identify the face of //
-// the tetrahedron. The other two bits of v identify the edge in the face.   //
+// ered from 0 to 2.  Then the two lower bits of v encode the face number,   //
+// and the two higher bits of v encode the edge number in that face.         //
 //                                                                           //
 // The four vertices of a tetrahedron are indexed from 0 to 3 (accodring to  //
 // their storage in the data structure).  Give each face the same index as   //
@@ -950,6 +928,9 @@ public:
 //   ccw orieation |   0        2        4                                   //
 //    cw orieation |   1        3        5                                   //
 //                                                                           //
+// In the following, a 'triface' is an order tetrahedron, and a 'face' is an //
+// orider triangle.                                                          //
+//                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
   class triface {
@@ -1051,9 +1032,7 @@ public:
 
     point seg[2];  // A constraining edge to be recovered.
     point fac[3];  // A constraining face to be recovered.
-
     point remvert; // A vertex to be removed.
-    //point remedge[2]; // A non-Delaunay edge to be removed.
 
     // Control flags
     int unflip;  // Undo the performed flips.
@@ -1062,16 +1041,12 @@ public:
 
     // Optimization flags.
     int remove_ndelaunay_edge; // Remove a non-Delaunay edge.
-                      // remedge[0] and remedge[1] store the endpoints of a
-                      // non-Delaunay edge to be removed.
     REAL bak_tetprism_vol; // The value to be minimized.
-
     int remove_large_angle; // Remove a large dihedral angle at edge.
     REAL cosdihed_in; // The input cosine of the dihedral angle (> 0).
-                      // Only perform a flip if new angles are less than it.
     REAL cosdihed_out; // The improved cosine of the dihedral angle.
 
-    // Counters.
+    // Internal counters.
     int maxflippedlinklevelcount; // Maximal flipped link levels.
     int misfliplinklevelcount; // Number of missed flip possibilities.
     int chrismastreecount; // Number of Chrismas trees (unflippable case).
@@ -1092,7 +1067,6 @@ public:
       seg[0] = NULL;
       fac[0] = NULL;
       remvert = NULL;
-      //remedge[0] = NULL;
 
       unflip = 0;
       collectnewtets = 0;
@@ -1100,7 +1074,6 @@ public:
 
       remove_ndelaunay_edge = 0;
       bak_tetprism_vol = 0.0;
-
       remove_large_angle = 0;
       cosdihed_in = 0.0;
       cosdihed_out = 0.0;
@@ -1166,8 +1139,8 @@ public:
 // Arraypool                                                                 //
 //                                                                           //
 // A dynamic linear array.                                                   //
-// (It is simply copied from Shewchuk's Starbase.c, which is provided as     //
-//  part of Stellar, a program for improving tetrahedral meshes.)            //
+// (It is from Shewchuk's Starbase.c, which is provided as part of Stellar,  //
+// a program for improving tetrahedral meshes.)                              //
 //                                                                           //
 // Each arraypool contains an array of pointers to a number of blocks.  Each //
 // block contains the same fixed number of objects.  Each index of the array //
@@ -1216,7 +1189,7 @@ public:
 // Memorypool                                                                //
 //                                                                           //
 // A type used to allocate memory.                                           //
-// (It is simply copied from Shewchuk's triangle.c.)                         //
+// (It is from Shewchuk's triangle.c.)                                       //
 //                                                                           //
 // firstblock is the first block of items. nowblock is the block from which  //
 //   items are currently being allocated. nextitem points to the next slab   //
@@ -1283,7 +1256,7 @@ public:
 ///////////////////////////////////////////////////////////////////////////////
 
   // Pointer to the input data (a set of nodes, a PLC, or a mesh).
-  tetgenio *in;
+  tetgenio *in, *addin;
 
   // Pointer to the switches and parameters.
   tetgenbehavior *b;
@@ -1304,15 +1277,8 @@ public:
   memorypool *flippool;
   // A stack of faces to be flipped.
   badface *flipstack;
-  // Two queues for handling unflippable edges.
-  arraypool *unflipqueue; //, *flipqueue;
-
-  // Entry to find the binary tree nodes (-u option).
-  arraypool *btreenode_list;
-  // The maximum size of a btree node (number after -u option) is
-  int max_btreenode_size; // <= b->max_btreenode_size.
-  // The maximum btree depth (for bookkeeping).
-  int max_btree_depth; 
+  // A queue to store unflippable elements.
+  arraypool *unflipqueue; 
 
   // Arrays used for point insertion (the Bowyer-Watson algorithm).
   arraypool *cavetetlist, *cavebdrylist, *caveoldtetlist;
@@ -1329,7 +1295,6 @@ public:
 
   // Two handles used for facet recovery in CDT.
   triface firsttopface, firstbotface;
-
   // Three points define a plane (used in formcavity()).
   point plane_pa, plane_pb, plane_pc;
 
@@ -1343,12 +1308,9 @@ public:
   // PI is the ratio of a circle's circumference to its diameter.
   static REAL PI;
 
-  // The increasement of link levels, default is 1.
-  int autofliplinklevel;
-
-  // The volume of tetrahedral-prisms (in 4D).
-  REAL tetprism_vol_sum;
-  int calc_tetprism_vol;
+  // Array (size = numberoftetrahedra * 6) for storing high-order nodes of
+  //   tetrahedra (only used when -o2 switch is selected).
+  point *highordertable;
 
   // Other variables.
   REAL xmax, xmin, ymax, ymin, zmax, zmin;         // Bounding box of points.
@@ -1358,12 +1320,13 @@ public:
   long meshedges;                             // Number of output mesh edges.
   long meshhulledges;                           // Number of hull mesh edges.
   int steinerleft;                  // Number of Steiner points not yet used.
+  int numpointattrib;                          // Number of point attributes.
   int sizeoftensor;                     // Number of REALs per metric tensor.
   int pointmtrindex;           // Index to find the metric tensor of a point.
   int pointparamindex;       // Index to find the u,v coordinates of a point.
   int point2simindex;         // Index to find a simplex adjacent to a point.
   int pointmarkindex;            // Index to find boundary marker of a point.
-  int point2pbcptindex;              // Index to find a pbc point to a point.
+  int numelemattrib;                     // Number of tetrahedron attributes.
   int elemattribindex;          // Index to find attributes of a tetrahedron.
   int volumeboundindex;       // Index to find volume bound of a tetrahedron.
   int elemmarkerindex;              // Index to find marker of a tetrahedron.
@@ -1372,7 +1335,6 @@ public:
   int checksubsegflag;   // Are there segments in the tetrahedralization yet?
   int checksubfaceflag;  // Are there subfaces in the tetrahedralization yet?
   int checkinverttetflag;       // Are there inverted (degenerated) tets yet?
-  int checkpbcs;                   // Are there periodic boundary conditions?
   int checkconstraints;  // Are there variant (node, seg, facet) constraints?
   int nonconvex;                               // Is current mesh non-convex?
   int dupverts;                             // Are there duplicated vertices?
@@ -1380,14 +1342,18 @@ public:
   long samples;               // Number of random samples for point location.
   unsigned long randomseed;                    // Current random number seed.
   REAL cosmaxdihed, cosmindihed;    // The cosine values of max/min dihedral.
-  REAL cossmtdihed;
-  REAL cosslidihed;          // The cosine value of max dihedral of a sliver.
+  REAL cossmtdihed;      // The cosine value of a bad dihedral tobe smoothed.
+  REAL cosslidihed;      // The cosine value of the max dihedral of a sliver.
   REAL minfaceang, minfacetdihed;     // The minimum input (dihedral) angles.
   REAL sintheta_tol;                   // The tolerance for sin(small angle).
+  int autofliplinklevel;    // The increasement of link levels, default is 1.
+  int calc_tetprism_vol;   // Flag to calculate the tetrahedral-prism'volume.
+  REAL tetprism_vol_sum;   // The total volume of tetrahedral-prisms (in 4D).
 
   // Algorithm statistical counters.
+  int  max_hcurve_depth_count;
   long ptloc_count, ptloc_max_count;
-  long orient3dcount, inspherecount, insphere_sos_count;
+  long insphere_sos_count, orient4d_sos_count;
   long flip14count, flip26count, flipn2ncount;
   long flip23count, flip32count, flip44count, flip22count;
   long maxbowatcavsize, totalbowatcavsize, totaldeadtets;
@@ -1403,42 +1369,27 @@ public:
   long maxfliplinklevel, maxflipstarsize;
   long flipstarcount, sucflipstarcount, skpflipstarcount;
   long st_segref_count, st_facref_count, st_volref_count; 
-
+  long nonregularcount;
   long rejrefinetetcount, rejrefineshcount;
 
-#ifdef WITH_RUNTIME_COUNTERS
-  clock_t t_ptloc, t_ptinsert;   // Time counters for DT operations.
-#endif
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // Mesh manipulation primitives                                              //
 //                                                                           //
-// A serial of mesh operations such as topological maintenance,  navigation, //
-// local modification, etc.,  is accomplished through a set of mesh manipul- //
-// ation primitives. These primitives are indeed very simple functions which //
-// take one or two handles ('triface's and 'face's) as parameters,  perform  //
-// basic operations such as "glue two tetrahedra at a face",  "return the    //
-// origin of a tetrahedron", "return the subface adjoining at the face of a  //
-// tetrahedron", and so on.                                                  //
+// Mesh manipulation primitives are indeed very simple functions which take  //
+// one or two handles as parameters,  perform basic operations such as "glue //
+// two tetrahedra at a face",  "return the origin of a tetrahedron", "return //
+// the subface adjoining at the face of a tetrahedron", and so on.           //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
   // Fast lookup tables for mesh manipulation primitives.
-  static int mod12[36];
-  static int mod6[18];
-  static int edgepivot[12];
-  static int orgpivot [12];
-  static int destpivot[12];
-  static int apexpivot[12];
-  static int oppopivot[12];
-  static int ver2edge[12];
-  static int edge2ver[6];
-  static int snextpivot[6];
-  static int sorgpivot [6];
-  static int sdestpivot[6];
-  static int sapexpivot[6];
-  static int epivot[4];
+  static int mod12[36], mod6[18]; 
+  static int orgpivot[12], destpivot[12], apexpivot[12], oppopivot[12];
+  static int edgepivot[12], ver2edge[12], edge2ver[6];
+  static int sorgpivot [6], sdestpivot[6], sapexpivot[6];
+  static int snextpivot[6], epivot[4];
 
   // Primitives for tetrahedra.
   inline void decode(tetrahedron ptr, triface& t);
@@ -1460,8 +1411,6 @@ public:
   inline void eprevesymself(triface& t);
   inline void fnext(triface& t1, triface& t2);
   inline void fnextself(triface& t);
-  inline void fprev(triface& t1, triface& t2);
-  inline void fprevself(triface& t);
   inline point org (triface& t);
   inline point dest(triface& t);
   inline point apex(triface& t);
@@ -1529,8 +1478,6 @@ public:
   inline void setshellmark(face& s, int value);
   inline enum shestype shelltype(face& s);
   inline void setshelltype(face& s, enum shestype value); 
-  inline int shellpbcgroup(face& s);
-  inline void setshellpbcgroup(face& s, int value);
   inline void sinfect(face& s);
   inline void suninfect(face& s);
   inline bool sinfected(face& s);
@@ -1594,8 +1541,6 @@ public:
   inline void setpoint2ppt(point pt, point value);
   inline tetrahedron point2bgmtet(point pt);
   inline void setpoint2bgmtet(point pt, tetrahedron value);
-  inline point point2pbcpt(point pt);
-  inline void setpoint2pbcpt(point pt, point value);
 
   // Advanced primitives.
   inline void point2tetorg(point pt, triface& t);
@@ -1618,12 +1563,12 @@ public:
   badface *badfacetraverse(memorypool*);
   void pointdealloc(point);
   point pointtraverse();
-  void maketetrahedron(triface*);
-  void makeshellface(memorypool*, face*);
-  void makepoint(point*, enum verttype);
 
   void makeindex2pointmap(point*&);
   void makepoint2submap(memorypool*, int*&, face*&);
+  void maketetrahedron(triface*);
+  void makeshellface(memorypool*, face*);
+  void makepoint(point*, enum verttype);
 
   void initializepools();
 
@@ -1668,6 +1613,7 @@ public:
   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);
+  bool orthosphere(REAL*,REAL*,REAL*,REAL*,REAL,REAL,REAL,REAL,REAL*,REAL*);
   void planelineint(REAL*, REAL*, REAL*, REAL*, REAL*, REAL*, REAL*);
   REAL tetprismvol(REAL* pa, REAL* pb, REAL* pc, REAL* pd);
 
@@ -1704,15 +1650,17 @@ public:
   void transfernodes();
 
   // Point sorting.
-  void btree_sort(point*, int, int, REAL, REAL, REAL, REAL, REAL, REAL, int);
-  void btree_insert(point insertpt);
-  void btree_search(point searchpt, triface* searchtet);
-  void ordervertices(point* vertexarray, int arraysize);
+  int  transgc[8][3][8], tsb1mod3[8];
+  void hilbert_init(int n);
+  int  hilbert_split(point* vertexarray, int arraysize, int gc0, int gc1,
+                     REAL, REAL, REAL, REAL, REAL, REAL);
+  void hilbert_sort3(point* vertexarray, int arraysize, int e, int d,
+                     REAL, REAL, REAL, REAL, REAL, REAL, int depth);
 
   // Point location.
   unsigned long randomnation(unsigned int choices);
   void randomsample(point searchpt, triface *searchtet);
-  enum locateresult locate(point searchpt, triface*, int, int);
+  enum locateresult locate(point searchpt, triface *searchtet, int);
 
   // Incremental Delaunay construction.
   void initialdelaunay(point pa, point pb, point pc, point pd);
@@ -1746,8 +1694,7 @@ public:
   void meshsurface();
 
   void interecursive(shellface** subfacearray, int arraysize, int axis,
-                     REAL bxmin, REAL bxmax, REAL bymin, REAL bymax,
-                     REAL bzmin, REAL bzmax, int* internum);
+                     REAL, REAL, REAL, REAL, REAL, REAL, int* internum);
   void detectinterfaces();
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1760,36 +1707,27 @@ public:
 
   void reportselfintersect(face *seg, face *shface);
 
-  enum interresult finddirection(triface* searchtet, point endpt, int);
+  enum interresult finddirection(triface* searchtet, point endpt);
   enum interresult scoutsegment(point, point, triface*, point*, arraypool*);
   void getsteinerptonsegment(face* seg, point refpt, point steinpt);
   void delaunizesegments();
 
   enum interresult scoutsubface(face* searchsh, triface* searchtet);
-  void formmissingregion(face* missh, arraypool* missingshs, 
-                         arraypool* missingshbds, arraypool* missingshverts, 
-                         arraypool *adjtets);
-  int scoutcrossedge(triface& crosstet, arraypool*, arraypool* missingshs);
-  bool formcavity(triface* searchtet, arraypool* missingshs, 
-                  arraypool* crosstets, arraypool* topfaces, 
-                  arraypool* botfaces, arraypool* toppoints, 
-                  arraypool* botpoints);
+  void formmissingregion(face*, arraypool*, arraypool*, arraypool*, arraypool*);
+  int scoutcrossedge(triface& crosstet, arraypool*, arraypool*);
+  bool formcavity(triface*, arraypool*, arraypool*, arraypool*, arraypool*, 
+                  arraypool*, arraypool*);
 
   // Facet recovery by local re-tetrahedralization [Si and Gaertner'05,'11].
-  void delaunizecavity(arraypool *cavpoints, arraypool *cavfaces, 
-                       arraypool *cavshells, arraypool *newtets, 
-                       arraypool *crosstets, arraypool *misfaces);
-  bool fillcavity(arraypool* topshells, arraypool* botshells,
-                  arraypool* midfaces, arraypool* missingshs);
-  void carvecavity(arraypool *crosstets, arraypool *topnewtets,
-                   arraypool *botnewtets);
-  void restorecavity(arraypool *crosstets, arraypool *topnewtets,
-                     arraypool *botnewtets);
+  void delaunizecavity(arraypool*, arraypool*, arraypool*, arraypool*, 
+                       arraypool*, arraypool*);
+  bool fillcavity(arraypool*, arraypool*, arraypool*, arraypool*);
+  void carvecavity(arraypool*, arraypool*, arraypool*);
+  void restorecavity(arraypool*, arraypool*, arraypool*);
 
   // Facet recovery by flips [Shewchuk'03].
   void flipcertify(triface *chkface, badface **pqueue);
-  void flipinsertfacet(arraypool *crosstets, arraypool *toppoints, 
-                       arraypool *botpoints, arraypool *midpoints);
+  void flipinsertfacet(arraypool*, arraypool*, arraypool*, arraypool*);
 
   bool fillregion(arraypool* missingshs, arraypool*, arraypool* newshs);
   void refineregion();
@@ -1804,7 +1742,6 @@ public:
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-  // A call back function.
   int checkflipeligibility(int fliptype, point, point, point, point, point,
                            int level, int edgepivot, flipconstraints* fc);
 
@@ -1840,7 +1777,7 @@ public:
   void reconstructmesh();
 
   int  scoutpoint(point, triface*, int randflag);
-  REAL getpointmeshsize(point, triface*, int iloc, int posflag);
+  REAL getpointmeshsize(point, triface*, int iloc);
   void interpolatemeshsize();
 
   void insertconstrainedpoints(tetgenio *addio);
@@ -1868,6 +1805,7 @@ public:
   int checktet4split(triface *chktet, int& qflag, REAL *ccent);
   int splittetrahedron(triface* splittet,int qflag,REAL *ccent,int chkencflag);
   void repairbadtets(int chkencflag);
+  void insertsinks();
 
   void delaunayrefinement();
 
@@ -1888,7 +1826,7 @@ public:
   int  splitsliver(triface *, REAL, int);
   long removeslivers(int);
 
-  void optimizemesh(int optflag);
+  void optimizemesh();
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
@@ -1940,8 +1878,8 @@ public:
 
   tetgenmesh()
   {
+    in  = addin = NULL;
     b   = NULL;
-    in  = NULL;
     bgm = NULL;
 
     tetrahedrons = subfaces = subsegs = points = NULL;
@@ -1952,7 +1890,6 @@ public:
     dummypoint = NULL;
     flipstack = NULL;
     unflipqueue = NULL;
-    btreenode_list = NULL;
 
     cavetetlist = cavebdrylist = caveoldtetlist = NULL;
     cavetetshlist = cavetetseglist = cavetetvertlist = NULL;
@@ -1963,6 +1900,8 @@ public:
     suppsteinerptlist = NULL;
     encseglist = encshlist = NULL;
 
+    highordertable = NULL;
+
     plane_pa = plane_pb = plane_pc = (point) NULL;
 
     xmax = xmin = ymax = ymin = zmax = zmin = 0.0; 
@@ -1971,11 +1910,13 @@ public:
     insegments = 0l;
     meshedges = meshhulledges = 0l;
     steinerleft = -1;
+    numpointattrib = 0;
+    sizeoftensor = 0;
     pointmtrindex = 0;
     pointparamindex = 0;
     pointmarkindex = 0;
     point2simindex = 0;
-    point2pbcptindex = 0;
+    numelemattrib = 0;
     elemattribindex = 0;
     volumeboundindex = 0;
     shmarkindex = 0;
@@ -1983,7 +1924,6 @@ public:
     checksubsegflag = 0;
     checksubfaceflag = 0;
     checkinverttetflag = 0;
-    checkpbcs = 0;
     checkconstraints = 0;
     nonconvex = 0;
     dupverts = 0;
@@ -1992,15 +1932,12 @@ public:
     randomseed = 1l;
     minfaceang = minfacetdihed = PI;
     sintheta_tol = sin(0.001 * PI / 180.0);
-
     autofliplinklevel = 1;
-
-    tetprism_vol_sum = 0.0;
     calc_tetprism_vol = 0;
+    tetprism_vol_sum = 0.0;
 
     ptloc_count = ptloc_max_count = 0l;
-    orient3dcount = 0l;
-    inspherecount = insphere_sos_count = 0l;
+    insphere_sos_count = orient4d_sos_count = 0l;
     flip14count = flip26count = flipn2ncount = 0l;
     flip23count = flip32count = flip44count = flip22count = 0l;
     maxbowatcavsize = totalbowatcavsize = totaldeadtets = 0l;
@@ -2015,15 +1952,12 @@ public:
     opt_sliver_peels = 0l;
     r1count = r2count = r3count = 0l;
     st_segref_count = st_facref_count = st_volref_count = 0l;
+    nonregularcount = 0l;
 
     maxfliplinklevel = maxflipstarsize = 0l;
     flipstarcount = sucflipstarcount = skpflipstarcount = 0l;
 
     rejrefinetetcount = rejrefineshcount = 0l;
-
-#ifdef WITH_RUNTIME_COUNTERS
-    t_ptloc = t_ptinsert = (clock_t) 0;
-#endif
   } // tetgenmesh()
 
   ~tetgenmesh()
@@ -2084,6 +2018,10 @@ public:
     if (suppsteinerptlist != NULL) {
       delete suppsteinerptlist;
     }
+
+    if (highordertable != NULL) {
+      delete [] highordertable;
+    }
   } // ~tetgenmesh()
 
 };                                               // End of class tetgenmesh.
@@ -2188,17 +2126,26 @@ inline tetgenmesh::tetrahedron tetgenmesh::encode2(tetrahedron* ptr, int ver) {
 //   choose to bond the edge of t2 which is symmetric to the 0-th edge of
 //   t1, and vice versa. Now assume t1 is at i-th edge and t2 is at j-th
 //   edge, where i, j in {0, 1, 2}. The edge in t2 symmetric to 0-th edge
-//   of t1 is mod3[i + j].
-// Since the edge number is coded in the two higher bits of the version, 
-//   both i, j are in {0, 4, 8}. The edge in t2 symmetric to 0-th edge
-//   of t1 is mod12[i + j].
-
+//   of t1 is (i + j) modulo 3, and vice versa.  Since the edge number is 
+//   coded in the two higher bits of the version, i.e., i, j in {0, 4, 8}.
+//   Therefore the edge in t2 symmetric to 0-th edge of t1 becomes
+//   (i + j) modulo 12, and vice versa.
+/*
 inline void tetgenmesh::bond(triface& t1, triface& t2) {
   (t1).tet[(t1).ver & 3] = encode2((t2).tet,
     ((t2).ver & 3) + mod12[((t1).ver & 12) + ((t2).ver & 12)]);
   (t2).tet[(t2).ver & 3] = encode2((t1).tet,
     ((t1).ver & 3) + mod12[((t1).ver & 12) + ((t2).ver & 12)]);
 }
+*/
+// Comment:  The following code seems faster than the above code when
+//   it is compiled with the optimization option, e.g., -O3.
+inline void tetgenmesh::bond(triface& t1, triface& t2) {
+  (t1).tet[(t1).ver & 3] = encode2((t2).tet,
+    ((t2).ver & 3) + (((t1).ver & 12) + ((t2).ver & 12)) % 12);
+  (t2).tet[(t2).ver & 3] = encode2((t1).tet,
+    ((t1).ver & 3) + (((t1).ver & 12) + ((t2).ver & 12)) % 12);
+}
 
 // dissolve()  a bond (from one side).
 
@@ -2209,20 +2156,17 @@ inline void tetgenmesh::dissolve(triface& t) {
 // fsym()  finds the adjacent tetrahedron at the same face and the same edge.
 
 inline void tetgenmesh::fsym(triface& t1, triface& t2) {
-  tetrahedron ptr = (t1).tet[(t1).ver & 3];
-  int offset = 12 - ((t1).ver & 12);
-  decode(ptr, t2);
-  (t2).ver = mod12[(t2).ver + offset];
+  decode((t1).tet[(t1).ver & 3], t2);
+  (t2).ver = mod12[(t2).ver + 12 - ((t1).ver & 12)];
 }
 
 inline void tetgenmesh::fsymself(triface& t) {
-  tetrahedron ptr = (t).tet[(t).ver & 3];
   int offset = 12 - ((t).ver & 12);
-  decode(ptr, t);
+  decode((t).tet[(t).ver & 3], t);
   (t).ver = mod12[(t).ver + offset];
 }
 
-// enext()  finds the next edge (counterclockwise) on the same face.
+// enext()  finds the next edge (counterclockwise) in the same face.
 
 inline void tetgenmesh::enext(triface& t1, triface& t2) {
   (t2).tet = (t1).tet;
@@ -2233,7 +2177,7 @@ inline void tetgenmesh::enextself(triface& t) {
   (t).ver = mod12[(t).ver + 4];
 }
 
-// eprev()   finds the next edge (clockwise) on the same face.
+// eprev()   finds the next edge (clockwise) in the same face.
 
 inline void tetgenmesh::eprev(triface& t1, triface& t2) {
   (t2).tet = (t1).tet;
@@ -2244,7 +2188,7 @@ inline void tetgenmesh::eprevself(triface& t) {
   (t).ver = mod12[(t).ver + 8];
 }
 
-// esym()  finds the reversed edge.  It is on the other face of the
+// esym()  finds the reversed edge.  It is in the other face of the
 //   same tetrahedron.
 
 inline void tetgenmesh::esym(triface& t1, triface& t2) {
@@ -2256,8 +2200,8 @@ inline void tetgenmesh::esymself(triface& t) {
   (t).ver = edgepivot[(t).ver];
 }
 
-// enextesym()  finds the reversed edge of the next edge. It is on the other
-//   face of the same tetrahedron.
+// enextesym()  finds the reversed edge of the next edge. It is in the other
+//   face of the same tetrahedron. It is the combination esym() * enext(). 
 
 inline void tetgenmesh::enextesym(triface& t1, triface& t2) {
   enext(t1, t2);
@@ -2269,8 +2213,7 @@ inline void tetgenmesh::enextesymself(triface& t) {
   esymself(t);
 }
 
-// eprevesym()  finds the reversed edge of the previous edge. It is on the
-//   other face of the same tetrahedron.
+// eprevesym()  finds the reversed edge of the previous edge.
 
 inline void tetgenmesh::eprevesym(triface& t1, triface& t2) {
   eprev(t1, t2);
@@ -2284,7 +2227,7 @@ inline void tetgenmesh::eprevesymself(triface& t) {
 
 // fnext()  finds the next face while rotating about an edge according to
 //   a right-hand rule. The face is in the adjacent tetrahedron.  It is
-//   equivalent to the combination: fsym() * esym().
+//   the combination: fsym() * esym().
 
 inline void tetgenmesh::fnext(triface& t1, triface& t2) {
   esym(t1, t2);
@@ -2296,19 +2239,6 @@ inline void tetgenmesh::fnextself(triface& t) {
   fsymself(t);
 }
 
-// fprev()  finds the next face while rotating about an edge according to
-//   a left-hand rule. The face is in the adjacent tetrahedron.  It is
-//   equivalent to the combination: esym() * fsym().
-
-inline void tetgenmesh::fprev(triface& t1, triface& t2) {
-  fsym(t1, t2);
-  esymself(t2);
-}
-
-inline void tetgenmesh::fprevself(triface& t) {
-  fsymself(t);
-  esymself(t);
-}
 
 // The following primtives get or set the origin, destination, face apex,
 //   or face opposite of an ordered tetrahedron.
@@ -2415,10 +2345,7 @@ inline bool tetgenmesh::infected(triface& t) {
 }
 
 // marktest(), marktested(), unmarktest() -- primitives to flag or unflag a
-//   tetrahedron.  The last second bit of the element marker is marked (1)
-//   or unmarked (0).
-// One needs them in forming Bowyer-Watson cavity, to mark a tetrahedron if
-//   it has been checked (for Delaunay case) so later check can be avoided.
+//   tetrahedron.  Use the second lowerest bit of the element marker.
 
 inline void tetgenmesh::marktest(triface& t) {
   ((int *) (t.tet))[elemmarkerindex] |= 2;
@@ -2435,8 +2362,6 @@ inline bool tetgenmesh::marktested(triface& t) {
 // markface(), unmarkface(), facemarked() -- primitives to flag or unflag a
 //   face of a tetrahedron.  From the last 3rd to 6th bits are used for
 //   face markers, e.g., the last third bit corresponds to loc = 0. 
-// One use of the face marker is in flip algorithm. Each queued face (check
-//   for locally Delaunay) is marked.
 
 inline void tetgenmesh::markface(triface& t) {
   ((int *) (t.tet))[elemmarkerindex] |= (4 << (t.ver & 3));
@@ -2453,7 +2378,7 @@ inline bool tetgenmesh::facemarked(triface& t) {
 // markedge(), unmarkedge(), edgemarked() -- primitives to flag or unflag an
 //   edge of a tetrahedron.  From the last 7th to 12th bits are used for
 //   edge markers, e.g., the last 7th bit corresponds to the 0th edge, etc. 
-// Remark: The last 7th bit is marked by 2^6 = 64.
+//   Remark: The last 7th bit is marked by 2^6 = 64.
 
 inline void tetgenmesh::markedge(triface& t) {
   ((int *) (t.tet))[elemmarkerindex] |= (int) (64 << ver2edge[(t).ver]);
@@ -2540,7 +2465,7 @@ inline bool tetgenmesh::isdeadtet(triface& t) {
 
 inline void tetgenmesh::sdecode(shellface sptr, face& s) {
   s.shver = (int) ((uintptr_t) (sptr) & (uintptr_t) 7);
-  s.sh = (shellface *) ((uintptr_t) (sptr) & ~ (uintptr_t) 7);
+  s.sh = (shellface *) ((uintptr_t) (sptr) ^ (uintptr_t) (s.shver));
 }
 
 inline tetgenmesh::shellface tetgenmesh::sencode(face& s) {
@@ -2775,17 +2700,6 @@ inline void tetgenmesh::setshelltype(face& s, enum shestype value)
     ((((int *) ((s).sh))[shmarkindex + 1]) & 255);
 }
 
-// These two primitives set or read the pbc group of the subface.
-
-inline int tetgenmesh::shellpbcgroup(face& s) 
-{
-  return ((int *) (s.sh))[shmarkindex + 2];
-}
-
-inline void tetgenmesh::setshellpbcgroup(face& s, int value) 
-{
-  ((int *) (s.sh))[shmarkindex + 2] = value;
-}
 
 // sinfect(), sinfected(), suninfect() -- primitives to flag or unflag a
 //   subface. The last bit of ((int *) ((s).sh))[shmarkindex+1] is flaged.
@@ -2810,8 +2724,7 @@ inline bool tetgenmesh::sinfected(face& s)
 }
 
 // smarktest(), smarktested(), sunmarktest() -- primitives to flag or unflag
-//   a subface. 
-// The last 2nd bit of ((int *) ((s).sh))[shmarkindex+1] is flaged.
+//   a subface.The last 2nd bit of the integer is flaged.
 
 inline void tetgenmesh::smarktest(face& s) 
 {
@@ -2831,8 +2744,7 @@ inline bool tetgenmesh::smarktested(face& s)
 }
 
 // smarktest2(), smarktest2ed(), sunmarktest2() -- primitives to flag or 
-//   unflag a subface. 
-// The last 3rd bit of ((int *) ((s).sh))[shmarkindex+1] is flaged.
+//   unflag a subface. The last 3rd bit of the integer is flaged.
 
 inline void tetgenmesh::smarktest2(face& s) 
 {
@@ -3213,15 +3125,6 @@ inline void tetgenmesh::setpoint2bgmtet(point pt, tetrahedron value) {
   ((tetrahedron *) (pt))[point2simindex + 3] = value;
 }
 
-// These primitives set and read a pointer to its pbc point.
-
-inline tetgenmesh::point tetgenmesh::point2pbcpt(point pt) {
-  return (point) ((tetrahedron *) (pt))[point2pbcptindex];
-}
-
-inline void tetgenmesh::setpoint2pbcpt(point pt, point value) {
-  ((tetrahedron *) (pt))[point2pbcptindex] = (tetrahedron) value;
-}
 
 // point2tetorg()    Get the tetrahedron whose origin is the point.