diff --git a/contrib/Tetgen1.5/predicates.cxx b/contrib/Tetgen1.5/predicates.cxx
index a4b77b69fe546cf1cf43491ab064963dfc842a60..4120704c3521a80f27aa144feb1387ccf78c66a2 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,24 +375,6 @@ 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.                */
@@ -678,7 +660,7 @@ float uniformfloatrand()
 /*                                                                           */
 /*****************************************************************************/
 
-void exactinit(int noexact, int nofilter, REAL maxx, REAL maxy, REAL maxz)
+REAL exactinit()
 {
   REAL half;
   REAL check, lastcheck;
@@ -740,36 +722,7 @@ void exactinit(int noexact, int nofilter, REAL maxx, REAL maxy, REAL maxz)
   isperrboundB = (5.0 + 72.0 * epsilon) * epsilon;
   isperrboundC = (71.0 + 1408.0 * epsilon) * epsilon * epsilon;
 
-  _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
+  return epsilon; /* Added by H. Si 30 Juli, 2004. */
 }
 
 /*****************************************************************************/
@@ -1916,6 +1869,16 @@ 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;
@@ -1953,10 +1916,6 @@ 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]);
@@ -2304,6 +2263,31 @@ 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;
@@ -2311,10 +2295,6 @@ 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];
@@ -2338,19 +2318,6 @@ 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);
@@ -2362,6 +2329,8 @@ 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.               */
@@ -3393,10 +3362,6 @@ 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]);
@@ -3973,10 +3938,6 @@ 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]);
@@ -4153,6 +4114,52 @@ 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;
@@ -4163,11 +4170,12 @@ 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;
-
-#ifndef NDEBUG
-  insphcount++;
-#endif // #ifndef NDEBUG
+  REAL permanent, errbound;
 
   aex = pa[0] - pe[0];
   bex = pb[0] - pe[0];
@@ -4214,25 +4222,6 @@ 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);
@@ -4273,6 +4262,8 @@ 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      */
@@ -4336,10 +4327,6 @@ 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]);
@@ -4553,10 +4540,6 @@ 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]);
@@ -4716,135 +4699,108 @@ 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;
-
-#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);
-}
+  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++;
 
-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);
-  }
-  if (!_use_inexact_arith) {
-    printf("  Number of orient3dadapt tests: %ld\n", ori3dadaptcount);
+  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);
+
+  if (0) { //if (noexact) {
+    return det;
   }
-  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);
+
+  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;
   }
-#endif // #ifndef NDEBUG
-}
 
+  return orient4dadapt(pa, pb, pc, pd, pe,
+                       aheight, bheight, cheight, dheight, eheight, permanent);
+}
diff --git a/contrib/Tetgen1.5/tetgen.cxx b/contrib/Tetgen1.5/tetgen.cxx
index 305d61b60a420fa4be0c1064abc5375a5b2d3aac..0a66de153c7e2825e01c02a2f1fdb01be35381ed 100644
--- a/contrib/Tetgen1.5/tetgen.cxx
+++ b/contrib/Tetgen1.5/tetgen.cxx
@@ -5,7 +5,11 @@
 // A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
 //                                                                           //
 // Version 1.5                                                               //
-// October 06, 2012                                                          //
+// February 21, 2012                                                         //
+//                                                                           //
+// PRE-RELEASE TEST CODE.                                                    //
+// PLEASE DO NOT DISTRIBUTE !!                                               //
+// PLEASE HELP ME TO IMPROVE IT !!                                           //
 //                                                                           //
 // Copyright (C) 2002--2012                                                  //
 // Hang Si                                                                   //
@@ -331,10 +335,6 @@ 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,12 +419,6 @@ 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);
@@ -633,6 +627,7 @@ 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;
   }
 
@@ -745,6 +740,7 @@ bool tetgenio::load_mtr(char* filebasename)
   if (infile != (FILE *) NULL) {
     printf("Opening %s.\n", mtrfilename);
   } else {
+    // No such file. Return.
     return false;
   }
 
@@ -1385,11 +1381,14 @@ 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);
@@ -1604,11 +1603,14 @@ 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);
@@ -2387,7 +2389,6 @@ 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);
@@ -2414,7 +2415,6 @@ 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,7 +2422,6 @@ bool tetgenio::load_tetmesh(char* filebasename, int object)
   }
 
   if (success) {
-    // Try to load the following files (.var, .mtr).
     load_var(filebasename);
     load_mtr(filebasename);
   }
@@ -2903,22 +2902,16 @@ char* tetgenio::findnextnumber(char *string)
 
 void tetgenbehavior::syntax()
 {
-  printf("  tetgen [-pYq_Aa_mriO_S_T_XMwcdzfenvgKJBNEFICQVh] input_file\n");
+  printf("  tetgen [-pYrq_a_AiS_T_dzfenvgKJBNEFICQVh] input_file\n");
   printf("    -p  Tetrahedralizes a piecewise linear complex (PLC).\n");
-  printf("    -Y  Preserves the input surface mesh (does not modify it).\n");
+  printf("    -Y  No splitting of input boundaries (facets and segments).\n");
+  printf("    -r  Reconstructs a previously generated mesh.\n");
   printf("    -q  Refines mesh (to improve mesh quality).\n");
-  printf("    -A  Assigns attributes to tetrahedra in different regions.\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("    -A  Assigns attributes to tetrahedra in different regions.\n");
+  printf("    -i  Inserts a list of additional points into mesh.\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");
@@ -3011,6 +3004,19 @@ 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)
@@ -3018,6 +3024,7 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
   int startindex;
   int increment;
   int meshnumber;
+  int scount, ocount;
   int i, j, k;
   char workstring[1024];
 
@@ -3031,9 +3038,12 @@ 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 for output.
+    // Remember the command line switches.
     strcat(commandline, argv[i]);
     strcat(commandline, " ");
     if (startindex == 1) {
@@ -3041,6 +3051,7 @@ 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;                     
       }
     }
@@ -3061,17 +3072,11 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
           facet_ang_tol = (REAL) strtod(workstring, (char **) NULL);
         }
       } else if (argv[i][j] == 's') {
-        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++;
-        }
+        psc = 1;        
       } else if (argv[i][j] == 'r') {
-        refine = 1;
+        refine++;
       } else if (argv[i][j] == 'q') {
-        quality = 1;
+        quality++;
         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
             (argv[i][j + 1] == '.')) {
           k = 0;
@@ -3082,56 +3087,42 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
             k++;
           }
           workstring[k] = '\0';
-          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';
+          if (quality == 1) { // -q#
+            minratio = (REAL) strtod(workstring, (char **) NULL);
+          } else if (quality == 2) { // -qq#
             mindihedral = (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';
-            optmaxdihedral = (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++;
           }
+          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')) {
-          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++;
+        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);
         }
-      } 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] == '.')) {
@@ -3150,32 +3141,71 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
           varvolume = 1;
         }
       } else if (argv[i][j] == 'A') {
-        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++;
+        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;
+        }
+      } 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++;
+        facesout = 1;
       } else if (argv[i][j] == 'e') {
         edgesout++;
       } else if (argv[i][j] == 'n') {
@@ -3184,8 +3214,10 @@ 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') {
@@ -3194,6 +3226,10 @@ 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') {
@@ -3213,36 +3249,65 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
           steinerleft = (int) strtol(workstring, (char **) NULL, 0);
         }
       } else if (argv[i][j] == '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);
+        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#
+            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') {
-        if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
-          optlevel = (argv[i][j + 1] - '0');
-          j++;
+        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] == '/') || (argv[i][j + 1] == ',')) {
-          j++;
-          if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '7')) {
-            optscheme = (argv[i][j + 1] - '0');
+      } 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] == '+')) {
             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')) ||
@@ -3258,8 +3323,6 @@ 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') {
@@ -3332,10 +3395,6 @@ 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) {
@@ -3371,16 +3430,18 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
       }
     }
   }
-  // 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;
+  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;
+      }
     }
   }
 
@@ -3439,8 +3500,10 @@ 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.
@@ -3479,6 +3542,8 @@ 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.                         //
@@ -3961,6 +4026,8 @@ void* tetgenmesh::memorypool::traverse()
   return newitem;
 }
 
+
+
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // makeindex2pointmap()    Create a map from index to vertices.              //
@@ -3992,6 +4059,7 @@ void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
   }
 }
 
+
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // makesubfacemap()    Create a map from vertex to subfaces incident at it.  //
@@ -4095,13 +4163,15 @@ void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
   //   dead tetrahedra when traversing the list of all tetrahedra.
   dyingtetrahedron[4] = (tetrahedron) NULL;
 
-  // Dealloc the space to subfaces/subsegments.
-  if (dyingtetrahedron[8] != NULL) {
-    tet2segpool->dealloc((shellface *) dyingtetrahedron[8]);
-  }
-  if (dyingtetrahedron[9] != NULL) {
-    tet2subpool->dealloc((shellface *) dyingtetrahedron[9]);
-  }
+  //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]);
+    }
+  //}
 
   tetrahedrons->dealloc((void *) dyingtetrahedron);
 }
@@ -4249,7 +4319,6 @@ 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;
@@ -4263,9 +4332,9 @@ void tetgenmesh::maketetrahedron(triface *newtet)
   // No attached segments and sbfaces yet.
   newtet->tet[8] = NULL; 
   newtet->tet[9] = NULL; 
-  // Initialize the marker (clear all flags).
+  // Initialize the marker (for flags).
   setelemmarker(newtet->tet, 0);
-  for (int i = 0; i < numelemattrib; i++) {
+  for (int i = 0; i < in->numberoftetrahedronattributes; i++) {
     setelemattribute(newtet->tet, i, 0.0);
   }
   if (b->varvolume) {
@@ -4286,7 +4355,6 @@ 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;
@@ -4314,7 +4382,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;
 }
 
@@ -4326,14 +4394,9 @@ void tetgenmesh::makeshellface(memorypool *pool, face *newface)
 
 void tetgenmesh::makepoint(point* pnewpoint, enum verttype vtype)
 {
-  int i;
+  int ptmark, 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;
@@ -4348,8 +4411,8 @@ void tetgenmesh::makepoint(point* pnewpoint, enum verttype vtype)
     }
   }
   // Initialize the point marker (starting from in->firstnumber).
-  i = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
-  setpointmark(*pnewpoint, i);
+  ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
+  setpointmark(*pnewpoint, ptmark);
   // Initialize the point type.
   setpointtype(*pnewpoint, vtype);
   // Clear the point flags.
@@ -4384,43 +4447,22 @@ 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) {
-    // '-s' option (PSC), the u,v coordinates are provided.
-    pointmtrindex = 5 + numpointattrib;
+    // For '-s' option (PSC), the u,v coordinates are provided. It is
+    //   saved directly after the list of point attributes.
+    pointmtrindex = 6 + in->numberofpointattributes;
   } else {
-    pointmtrindex = 3 + numpointattrib;
+    pointmtrindex = 4 + in->numberofpointattributes;
   }
   // The index within each point at which its u, v coordinates are found.
-  pointparamindex = 3 + (numpointattrib > 0);
+  pointparamindex = pointmtrindex - 2; 
   // 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.
@@ -4449,11 +4491,19 @@ 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 into the background mesh, point2bgmtet().
+      // Increase one pointer to 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();
@@ -4467,6 +4517,7 @@ 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.
@@ -4507,21 +4558,19 @@ 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.
-  volumeboundindex = elemattribindex + numelemattrib;
+  //   found, where the index is measured in REALs.  Note that if the
+  //   `b->regionattrib' flag is set, an additional attribute will be added.
+  volumeboundindex = elemattribindex + in->numberoftetrahedronattributes
+                   + (b->regionattrib > 0);
   // If element attributes or an constraint are needed, increase the number
   //   of bytes occupied by an element.
   if (b->varvolume) {
     elesize = (volumeboundindex + 1) * sizeof(REAL);
-  } else if (numelemattrib > 0) {
+  } else if (in->numberoftetrahedronattributes + b->regionattrib > 0) {
     elesize = volumeboundindex * sizeof(REAL);
   }
 
@@ -4555,7 +4604,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) * sizeof(shellface);
+    shsize = (shmarkindex + 2 + checkpbcs) * 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
@@ -4599,7 +4648,7 @@ void tetgenmesh::initializepools()
     caveencseglist = new arraypool(sizeof(face), 8);
   }
 
-  // Initialize the pools for flips.
+  // Initialize the pool for flips.
   flippool = new memorypool(sizeof(badface), 1024, memorypool::POINTER, 0);
   unflipqueue = new arraypool(sizeof(badface), 10);
 
@@ -5823,6 +5872,8 @@ 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;
@@ -5896,13 +5947,15 @@ 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;
   }
 
-  orient4d_sos_count++;
+  insphere_sos_count++;
 
   // Symbolic perturbation.
   point pt[5], swappt;
@@ -5947,6 +6000,7 @@ REAL tetgenmesh::orient4d_s(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
   return oriB;
 }
 
+
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // facenormal()    Calculate the normal of the face.                         //
@@ -6054,6 +6108,7 @@ 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.                               //
@@ -6150,7 +6205,9 @@ 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;
@@ -6192,6 +6249,7 @@ 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       //
@@ -6501,59 +6559,7 @@ 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;
-}
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
@@ -6601,6 +6607,8 @@ void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
   }
 }
 
+
+
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // tetprismvol()    Calculate the volume of a tetrahedral prism in 4D.       //
@@ -6703,7 +6711,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 ([Edelsbrunner & Shah'1996] and [M\"ucke'1998]).    //
+// e] needs to be queued, see [Edelsbrunner & Shah'1996] and [M\"ucke'1998]. //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -6717,7 +6725,6 @@ 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;
 
@@ -6772,7 +6779,6 @@ 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) {
@@ -6797,15 +6803,6 @@ 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.
@@ -7042,13 +7039,17 @@ 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);
       }
     }
@@ -7081,18 +7082,8 @@ 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 ( [Edelsbrunner & Shah'1996] and [M\"ucke'1998]).               //
+// be queued, refer to [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).                          //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -7106,9 +7097,8 @@ 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, j;
+  int i;
 
   // For 2-to-2 flip (subfaces).
   face flipshs[3], flipfaces[2];
@@ -7196,28 +7186,6 @@ 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) {
@@ -7718,7 +7686,6 @@ 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) {
@@ -8710,7 +8677,9 @@ int tetgenmesh::flipnm(triface* abtets, int n, int level, int abedgepivot,
         }
       }
       if (!rejflag && (fc != NULL)) {
-        // Here we must exchange 'a' and 'b'. Since in the check... function,
+        //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,
         //   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]. 
@@ -8839,7 +8808,9 @@ 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++) {
@@ -9054,6 +9025,11 @@ 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) {
@@ -9085,6 +9061,8 @@ 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]
@@ -9214,7 +9192,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); 
+          ori = orient3d(ppt[4], ppt[5], ppt[6], newpt); orient3dcount++;
           if (ori < 0) {
             // Visible. Perform a 2-to-3 flip on the flip face.
             fliptets[0] = fliptet;  // [a,b,c,d], d = newpt.
@@ -9318,7 +9296,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); 
+          ori = orient3d(p1, p2, pd, pe); orient3dcount++;
           if (ori < 0) {
             // A locally non-convex edge.
             convflag = -1;
@@ -9626,14 +9604,14 @@ long tetgenmesh::lawsonflip3d(point newpt, int flipflag, int peelsliverflag,
 //                                                                           //
 // insertvertex()    Insert a point into current tetrahedralization.         //
 //                                                                           //
-// 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.                                  //
+// 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.                                 //
 //                                                                           //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
@@ -9660,6 +9638,9 @@ 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));
@@ -9674,12 +9655,17 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
   }
 
   if (loc == OUTSIDE) {
-    tetcount = ptloc_count; // Count the number of visited tets.
+#ifdef WITH_RUNTIME_COUNTERS
+    tstart = clock();
+#endif
+    tetcount = ptloc_count; // Count the number of walked tets.
     if (searchtet->tet == NULL) {
       if (!b->weighted) {
-        if (b->brio_hilbert) { // -b
+        if (b->btree) {
+          btree_search(insertpt, searchtet);
+        } else if (b->hilbertcurve) { // -U
           *searchtet = recenttet;
-        } else { // -b0
+        } else { // -u0
           randomsample(insertpt, searchtet);
         }
       } else {
@@ -9687,14 +9673,18 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
         *searchtet = recenttet;
       }
     }
-    // Locate the point.
-    loc = locate(insertpt, searchtet, ivf->chkencflag); 
+    // Locate the point.  Use 'randflag' if the mesh is non-convex.
+    loc = locate(insertpt, searchtet, ivf->chkencflag, checksubfaceflag); 
     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) {
@@ -9703,6 +9693,9 @@ 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) {
@@ -9714,19 +9707,21 @@ 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 > 1) {
-	  printf("    Point #%d is non-regular, skipped.\n",
-                 pointmark(insertpt));
-	}
-        setpointtype(insertpt, NREGULARVERTEX);
-        nonregularcount++;
-        return NONREGULAR;
+        if (b->verbose > 2) {
+          printf("      The point is above the lower hull, skipped.\n");
+        }
+        return OUTSIDE;
       }
     }
   }
 
   // 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.
@@ -9902,39 +9897,9 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
     return (int) loc;
   } else if (loc == ENCSUBFACE) {
     if (b->verbose > 3) {
-      printf("        Beyond boundary.\n");
+      printf("        Encroached.\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;
@@ -9951,12 +9916,13 @@ 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] =  
-          bgm->getpointmeshsize(insertpt, &neightet, bgmloc);
+        insertpt[pointmtrindex] =  // posflag = 1
+          bgm->getpointmeshsize(insertpt, &neightet, bgmloc, 1);
         setpoint2bgmtet(insertpt, bgm->encode(neightet));
       }
     } else {
-      insertpt[pointmtrindex] = getpointmeshsize(insertpt,searchtet,(int)loc);
+      insertpt[pointmtrindex] = // posflag = 1
+        getpointmeshsize(insertpt, searchtet, (int) loc, 1);
     }
   } // if (assignmeshsize)
 
@@ -9977,6 +9943,7 @@ 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));
@@ -9994,6 +9961,11 @@ 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);
@@ -10054,6 +10026,7 @@ 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) { 
@@ -10287,7 +10260,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",
-               encshlist->objects);
+               caveencshlist->objects);
       }
       for (i = 0; i < caveoldtetlist->objects; i++) {
         cavetet = (triface *) fastlookup(caveoldtetlist, i);
@@ -10336,21 +10309,14 @@ 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)) {
-                // 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;
-                }
+                smarktest(neighsh);
+                caveshlist->newindex((void **) &parysh);
+                *parysh = neighsh;
               }
             }
           }
@@ -10534,7 +10500,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); 
+            ori = orient3d(pa, pb, pc, insertpt); orient3dcount++;
             enqflag = (ori > 0);
             // Comment: if ori == 0 (coplanar case), we also cut the tet.
           } else {
@@ -10615,27 +10581,8 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
 
       // The cavity should contain at least one tet.
       if (caveoldtetlist->objects == 0l) {
-        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;
+        printf("Invalid cavity of Steiner point %d.\n", pointmark(insertpt));
+        assert(0);
       }
 
       if (ivf->splitbdflag) { //if (bowywat > 2) { // if (bowywat == 3) {
@@ -11087,6 +11034,15 @@ 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++;
@@ -11098,15 +11054,6 @@ 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.
@@ -11115,8 +11062,7 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
 
   // Set a handle for speeding point location.
   recenttet = newtet;
-  //setpoint2tet(insertpt, encode(newtet));
-  setpoint2tet(insertpt, (tetrahedron) (newtet.tet));
+  setpoint2tet(insertpt, encode(newtet));
 
   if (ivf->lawson > 1) { // if (lawson == 2 || lawson == 3) {
     // Re-use this list to save new interior cavity faces.
@@ -11152,8 +11098,7 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
           *parytet = neightet;
         }
       }
-      //setpoint2tet(org(newtet), encode(newtet));
-      setpoint2tet(org(newtet), (tetrahedron) (newtet.tet));
+      setpoint2tet(org(newtet), encode(newtet));
       enextself(newtet);
       enextself(oldtet);
     }
@@ -11302,7 +11247,7 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
             pa = sorg(checkseg);
             pb = sdest(checkseg);
             point2tetorg(pa, neightet);
-            finddirection(&neightet, pb);
+            finddirection(&neightet, pb, 1);
             assert(dest(neightet) == pb);
           }
           assert(!infected(neightet));
@@ -11373,12 +11318,11 @@ 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 > 1) {
-            printf("    Point #%d is non-regular after the insertion of #%d.\n",
-                   pointmark(*pts), pointmark(insertpt));
-	  }
-          setpointtype(*pts, NREGULARVERTEX);
-          nonregularcount++;
+          if (b->verbose > 2) {
+            printf("      Point #%d is removed from the hull.\n",
+                   pointmark(*pts));
+          }
+          setpointtype(*pts, UNUSEDVERTEX);
         } else {
           if (b->verbose > 3) {
             printf("        Queue a dangling vertex %d.\n", pointmark(*pts));
@@ -11524,7 +11468,14 @@ 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.
 
@@ -11567,10 +11518,10 @@ int tetgenmesh::insertvertex(point insertpt, triface *searchtet, face *splitsh,
 //                                                                           //
 // transfernodes()    Read the vertices from the input (tetgenio).           //
 //                                                                           //
-// 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.          //
+// 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.   //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -11583,6 +11534,9 @@ void tetgenmesh::transfernodes()
   int mtrindex;
   int i, j;
 
+  if (b->psc) {
+    assert(in->pointparamlist != NULL);
+  }
 
   // Read the points.
   coordindex = 0;
@@ -11593,32 +11547,30 @@ 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++];
-    // 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++];
-    }
+    z = pointloop[2] = in->pointlist[coordindex++];    
     if (b->weighted) { // -w option
       if (in->numberofpointattributes > 0) {
-        // The first point attribute is its weight.
-        //w = in->pointattributelist[in->numberofpointattributes * i];
-        w = pointloop[3];
+        // The first point attribute is weight.
+        w = in->pointattributelist[in->numberofpointattributes * i];
       } else {
-        // 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);
+        // No given weight available.
+        w = 0;
       }
       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) {
@@ -11668,239 +11620,293 @@ void tetgenmesh::transfernodes()
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// 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.                //
+// btree_sort()    Sort vertices using a binary space partition (bsp) tree.  //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-int tetgenmesh::hilbert_split(point* vertexarray,int arraysize,int gc0,int gc1,
-                              REAL bxmin, REAL bxmax, REAL bymin, REAL bymax, 
-                              REAL bzmin, REAL bzmax)
+void tetgenmesh::btree_sort(point* vertexarray, int arraysize, int axis, 
+                            REAL bxmin, REAL bxmax, REAL bymin, REAL bymax, 
+                            REAL bzmin, REAL bzmax, int depth)
 {
-  point swapvert;
-  int axis, d;
+  point *leftarray, *rightarray;
+  point **pptary, swapvert;
   REAL split;
-  int i, j;
+  bool lflag, rflag;
+  int i, j, k; // *iptr,
 
+  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"));
+  }
 
-  // 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; 
+  if (depth > max_btree_depth) {
+    max_btree_depth = depth;
+  }
 
-  // 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 { // == 2
+  } else {
+    // Split along z-axis.
     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.
-  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;
+  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);
       }
-      for (; j >= 0; j--) {
-        if (vertexarray[j][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);
       }
-      // 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 {
+      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;
   }
+}
 
-  return i;
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// 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);
 }
 
-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)
+///////////////////////////////////////////////////////////////////////////////
+//                                                                           //
+// btree_search()    Search a near point for an inserting point.             //
+//                                                                           //
+///////////////////////////////////////////////////////////////////////////////
+
+void tetgenmesh::btree_search(point insertpt, triface* searchtet)
 {
-  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];
-      }
-      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);
-      }
-      if (transgc[e][d][w] & 2) { // y-axis
-        y1 = 0.5 * (bymin + bymax);
-        y2 = bymax;
-      } else {
-        y1 = bymin;
-        y2 = 0.5 * (bymin + bymax);
+  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++;
       }
-      if (transgc[e][d][w] & 4) { // z-axis
-        z1 = 0.5 * (bzmin + bzmax);
-        z2 = bzmax;
-      } else {
-        z1 = bzmin;
-        z2 = 0.5 * (bzmin + bzmax);
+    }
+
+    // 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;
       }
-      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
+    }
+
+  } 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);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -11932,10 +11938,13 @@ unsigned long tetgenmesh::randomnation(unsigned int choices)
 //                                                                           //
 // randomsample()    Randomly sample the tetrahedra for point loation.       //
 //                                                                           //
-// 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.                                         //
+// 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.      //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -12062,15 +12071,19 @@ 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 face which is visible by the search point.              //
+//     hull tetrahedron whose base face is visible by the search point.      //
 //                                                                           //
 // WARNING: This routine is designed for convex triangulations, and will not //
 // generally work after the holes and concavities have been carved.          //
 //                                                                           //
+// 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)
+  tetgenmesh::locate(point searchpt, triface* searchtet, int chkencflag, 
+                     int randflag)
 {
   triface neightet; 
   face checksh;
@@ -12078,7 +12091,8 @@ enum tetgenmesh::locateresult
   enum {ORGMOVE, DESTMOVE, APEXMOVE} nextmove;
   REAL ori, oriorg, oridest, oriapex;
   enum locateresult loc;
-  int s;
+  int s; // i;
+
 
   if (searchtet->tet == NULL) {
     // A null tet. Choose the recenttet as the starting tet.
@@ -12100,11 +12114,13 @@ enum tetgenmesh::locateresult
     torg = org(*searchtet);
     tdest = dest(*searchtet);
     tapex = apex(*searchtet);
-    ori = orient3d(torg, tdest, tapex, searchpt); 
+    ori = orient3d(torg, tdest, tapex, searchpt); orient3dcount++;
     if (ori < 0.0) break;
   }
-  if (searchtet->ver == 4) { // SELF_CHECK
-    assert(0);
+  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;
   }
 
   loc = OUTSIDE; // Set a default return value.
@@ -12112,7 +12128,7 @@ enum tetgenmesh::locateresult
   // Walk through tetrahedra to locate the point.
   while (true) {
 
-    ptloc_count++;  // Count the number of visited tets.
+    ptloc_count++;  // Algorithimic count.
 
     toppo = oppo(*searchtet);
     
@@ -12125,43 +12141,58 @@ enum tetgenmesh::locateresult
       break;
     }
 
-    // We enter from one of serarchtet's faces, which face do we exit?
+    // We enter from serarchtet's base face. There are three other faces in
+    //   searchtet (all connecting to toppo), which one is the exit?
     oriorg = orient3d(tdest, tapex, toppo, searchpt); 
     oridest = orient3d(tapex, torg, toppo, searchpt);
     oriapex = orient3d(torg, tdest, toppo, searchpt);
+    orient3dcount+=3;
 
     // Now decide which face to move. It is possible there are more than one
-    //   faces are viable moves. If so, randomly choose one.
+    //   faces are viable moves. Use the opposite points of thier neighbors
+    //   to discriminate, i.e., we choose the face whose opposite point has
+    //   the shortest distance to searchpt.
     if (oriorg < 0) {
       if (oridest < 0) {
         if (oriapex < 0) {
-          // 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;
+          if (0) { //if (!randflag) {
           } else {
-            nextmove = APEXMOVE;
-          }
+            // 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)
         } else {
           // Two faces, opposite to origin and destination, are viable.
-          s = randomnation(2); // 's' is in {0,1}.
-          if (s == 0) {
-            nextmove = ORGMOVE;
+          if (0) { // if (!randflag) {
           } else {
-            nextmove = DESTMOVE;
-          }
+            // Randomly choose a direction.
+            s = randomnation(2); // 's' is in {0,1}.
+            if (s == 0) {
+              nextmove = ORGMOVE;
+            } else {
+              nextmove = DESTMOVE;
+            }
+          } // if (randflag)
         }
       } else {
         if (oriapex < 0) {
           // Two faces, opposite to origin and apex, are viable.
-          s = randomnation(2); // 's' is in {0,1}.
-          if (s == 0) {
-            nextmove = ORGMOVE;
+          if (0) { // if (!randflag) {
           } else {
-            nextmove = APEXMOVE;
-          }
+            // Randomly choose a direction.
+            s = randomnation(2); // 's' is in {0,1}.
+            if (s == 0) {
+              nextmove = ORGMOVE;
+            } else {
+              nextmove = APEXMOVE;
+            }
+          } // if (randflag)
         } else {
           // Only the face opposite to origin is viable.
           nextmove = ORGMOVE;
@@ -12171,12 +12202,16 @@ enum tetgenmesh::locateresult
       if (oridest < 0) {
         if (oriapex < 0) {
           // Two faces, opposite to destination and apex, are viable.
-          s = randomnation(2); // 's' is in {0,1}.
-          if (s == 0) {
-            nextmove = DESTMOVE;
+          if (0) { // if (!randflag) {
           } else {
-            nextmove = APEXMOVE;
-          }
+            // Randomly choose a direction.
+            s = randomnation(2); // 's' is in {0,1}.
+            if (s == 0) {
+              nextmove = DESTMOVE;
+            } else {
+              nextmove = APEXMOVE;
+            }
+          } // if (randflag)
         } else {
           // Only the face opposite to destination is viable.
           nextmove = DESTMOVE;
@@ -12271,6 +12306,7 @@ enum tetgenmesh::locateresult
   return loc;
 }
 
+
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // initialdelaunay()    Create an initial Delaunay tetrahedralization.       //
@@ -12347,6 +12383,13 @@ 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));
@@ -12371,45 +12414,56 @@ 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->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->btree) { // -u option
+    for (i = 0; i < in->numberofpoints; i++) {
+      permutarray[i] = (point) points->traverse();
+    }
     if (b->verbose) {
-      printf("  Sort the points using simple BRIO and Hilbert curve L(%d).\n",
-             b->hilbert_limit); 
+      printf("  Sorting vertices by a bsp-tree.\n");
     }
-    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;
+    // 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("  Sorting vertices by hilbert curve.\n"); 
     }
+    // To be done...
+    for (i = 0; i < in->numberofpoints; i++) {
+      permutarray[i] = (point) points->traverse();
+    }
+  } else {
     if (b->verbose) {
-      printf("  Number of sorted subsets: %d.\n", ngroup);
-      printf("  Maximum curve order: %d.\n", max_hcurve_depth_count);
+      printf("  Permuting vertices.\n"); 
+    }
+    for (i = 0; i < in->numberofpoints; i++) {
+      randindex = randomnation(i + 1);
+      permutarray[i] = permutarray[randindex];
+      permutarray[randindex] = (point) points->traverse();
     }
   }
 
@@ -12501,7 +12555,7 @@ void tetgenmesh::incrementaldelaunay(clock_t& tv)
     printf("  Incrementally inserting vertices.\n");
   }
 
-  // Choose algorithm: Bowyer-Watson (default) or Incremental Flip
+  // Choose algorithm: Bowyer-Watson (default) or Incremental Flip (-l).
   if (b->incrflip) {
     ivf.bowywat = 0;
     ivf.lawson = 1;
@@ -12510,7 +12564,6 @@ 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) {
@@ -12535,20 +12588,22 @@ 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) {
-      // Perform flip to recover Delaunayness.
+      // If -l option. Perform flip to recover Delaunayness.
       lawsonflip3d(permutarray[i], ivf.lawson, 0, 0, 0);
     }
   }
 
-
-
-  if (b->brio_hilbert) {
-    b->brio_hilbert = 0; // Disable it.
+  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.
   }
 
   delete [] permutarray;
@@ -13467,7 +13522,7 @@ if (bowywat < 3) { // if (bowywat == 1 || bowywat == 2) {
       setshelltype(aseg, shelltype(*splitseg));
       setshelltype(bseg, shelltype(*splitseg));
       if (checkconstraints) {
-        setareabound(aseg, areabound(*splitseg));
+        setareabound(bseg, areabound(*splitseg));
         setareabound(bseg, areabound(*splitseg));
       }
 
@@ -14426,9 +14481,6 @@ 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);
@@ -14514,19 +14566,6 @@ 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);
@@ -14594,9 +14633,14 @@ 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) {
@@ -14643,6 +14687,10 @@ 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) {
@@ -14695,9 +14743,6 @@ void tetgenmesh::unifysegments()
   int *idx2faclist;
   int idx, k, m;
 
-  int e1, e2;
-  REAL len;
-
   if (b->verbose > 1) {
     printf("  Unifying segments.\n");
   }
@@ -14895,23 +14940,11 @@ 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);
   }
 
@@ -15030,13 +15063,12 @@ 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.
 
@@ -15047,7 +15079,6 @@ 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++) {
@@ -15120,21 +15151,6 @@ 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) {
@@ -15426,7 +15442,9 @@ 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++;
@@ -15626,7 +15644,7 @@ void tetgenmesh::markacutevertices()
     printf("  Marking acute vertices.\n");
   }
   anglimit = PI / 3.0;  // 60 degree.
-  sharpanglimit = 5.0 / 180.0 * PI; // 5 degree. 
+  sharpanglimit = 10.0 / 180.0 * PI; // 10 degree. 
   minfaceang = PI; // 180 degree.
   acutecount = sharpsegcount = 0;
 
@@ -15651,9 +15669,11 @@ 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;
           }
@@ -15751,7 +15771,7 @@ void tetgenmesh::reportselfintersect(face *checkseg, face *checksh)
 ///////////////////////////////////////////////////////////////////////////////
 
 enum tetgenmesh::interresult 
-  tetgenmesh::finddirection(triface* searchtet, point endpt)
+  tetgenmesh::finddirection(triface* searchtet, point endpt, int randflag)
 {
   triface neightet;
   point pa, pb, pc, pd;
@@ -15759,6 +15779,7 @@ enum tetgenmesh::interresult
   REAL hori, rori, lori;
   int s;
 
+
   // The origin is fixed.
   pa = org(*searchtet);
   if ((point) searchtet->tet[7] == dummypoint) {
@@ -15773,7 +15794,7 @@ enum tetgenmesh::interresult
     } else if ((point) searchtet->tet[6] == pa) {
       searchtet->ver = 7;
     } else {
-      assert((point) searchtet->tet[7] == pa); 
+      assert((point) searchtet->tet[7] == pa); // SELF_CHECK
       searchtet->ver = 0;
     }
   }
@@ -15825,39 +15846,54 @@ 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
-    //   tets are viable moves. Is so, randomly choose one. 
+    //   tet are viable moves. Use the opposite points of thier neighbors
+    //   to discriminate, i.e., we choose the tet whose opposite point has
+    //   the shortest distance to 'endpt'.
     if (hori > 0) {
       if (rori > 0) {
         if (lori > 0) {
           // Any of the three neighbors is a viable move.
-          s = randomnation(3); 
-          if (s == 0) {
-            nextmove = HMOVE;
-          } else if (s == 1) {
-            nextmove = RMOVE;
+          if (0) { // if (!randflag) {
           } else {
-            nextmove = LMOVE;
-          }
+            // 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)
         } else {
           // Two tets, below horizon and below right, are viable.
-          s = randomnation(2); 
-          if (s == 0) {
-            nextmove = HMOVE;
+          if (0) { // if (!randflag) {
           } else {
-            nextmove = RMOVE;
-          }
+            // Randomly choose a direction.
+            s = randomnation(2); // 's' is in {0,1}.
+            if (s == 0) {
+              nextmove = HMOVE;
+            } else {
+              nextmove = RMOVE;
+            }
+          } // if (randflag)
         }
       } else {
         if (lori > 0) {
           // Two tets, below horizon and below left, are viable.
-          s = randomnation(2); 
-          if (s == 0) {
-            nextmove = HMOVE;
+          if (0) { // if (!randflag) {
           } else {
-            nextmove = LMOVE;
-          }
+            // Randomly choose a direction.
+            s = randomnation(2); // 's' is in {0,1}.
+            if (s == 0) {
+              nextmove = HMOVE;
+            } else {
+              nextmove = LMOVE;
+            }
+          } // if (randflag)
         } else {
           // The tet below horizon is chosen.
           nextmove = HMOVE;
@@ -15867,12 +15903,16 @@ enum tetgenmesh::interresult
       if (rori > 0) {
         if (lori > 0) {
           // Two tets, below right and below left, are viable.
-          s = randomnation(2); 
-          if (s == 0) {
-            nextmove = RMOVE;
+          if (0) { // if (!randflag) {
           } else {
-            nextmove = LMOVE;
-          }
+            // Randomly choose a direction.
+            s = randomnation(2); // 's' is in {0,1}.
+            if (s == 0) {
+              nextmove = RMOVE;
+            } else {
+              nextmove = LMOVE;
+            }
+          } // if (randflag)
         } else {
           // The tet below right is chosen.
           nextmove = RMOVE;
@@ -15932,7 +15972,7 @@ enum tetgenmesh::interresult
       fsymself(*searchtet);
       enextself(*searchtet);
     }
-    assert(org(*searchtet) == pa); 
+    assert(org(*searchtet) == pa); // SELF_CHECK
     pb = dest(*searchtet);
     pc = apex(*searchtet);
 
@@ -15983,7 +16023,7 @@ enum tetgenmesh::interresult
   }
 
   point2tetorg(startpt, *searchtet);
-  dir = finddirection(searchtet, endpt);
+  dir = finddirection(searchtet, endpt, 0);
 
   if (dir == ACROSSVERT) {
     pd = dest(*searchtet);
@@ -16449,12 +16489,13 @@ void tetgenmesh::delaunizesegments()
     psseg = (face *) fastlookup(subsegstack, subsegstack->objects);
     sseg = *psseg;
 
-    assert(!sinfected(sseg)); 
+    assert(!sinfected(sseg)); // FOR DEBUG
     // 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); // SELF_CHECK
+      tsspivot1(searchtet, checkseg);
       assert(checkseg.sh == sseg.sh);
       continue; // Not a missing segment.
     }
@@ -16497,7 +16538,7 @@ void tetgenmesh::delaunizesegments()
         ivf.splitbdflag = 0;
         // ivf.validflag
         ivf.respectbdflag = 0;
-        ivf.assignmeshsize = b->metric;
+        ivf.assignmeshsize = 0;
         // Insert the new point into the tetrahedralization T.
         //   Missing segments and subfaces are queued for recovery.
         //   Note that T is convex (nonconvex = 0).
@@ -16510,7 +16551,7 @@ void tetgenmesh::delaunizesegments()
             // For CDT, use flips to reocver Delaunayness.
             lawsonflip3d(newpt, ivf.lawson, 0, 0, 0);
           }
-          st_segref_count++;
+          st_segref_count++; //st_segpro_count++;
           if (steinerleft > 0) steinerleft--;
         } else {
           // The new point is either ON or VERY CLOSE to an existing point.
@@ -16655,7 +16696,7 @@ enum tetgenmesh::interresult
   // Get a tet whose origin is a.
   point2tetorg(pa, *searchtet);
   // Search the edge [a,b].
-  dir = finddirection(searchtet, pb);
+  dir = finddirection(searchtet, pb, 0);
   if (dir == ACROSSVERT) {
     // Check validity of a PLC.
     if (dest(*searchtet) != pb) {
@@ -16751,7 +16792,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);
+      dir = finddirection(&searchtet, pb, 0);
       if (dir != ACROSSVERT) {
         // This edge is missing. Its neighbor is a missing subface.
         spivot(*missh, neighsh);
@@ -16816,6 +16857,7 @@ void tetgenmesh::formmissingregion(face* missh, arraypool* missingshs,
 }
 
 
+
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // scoutcrossedge()    Search an edge that crosses the missing region.       //
@@ -16927,6 +16969,22 @@ 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   //
@@ -16959,6 +17017,8 @@ 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;
@@ -16982,6 +17042,8 @@ 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);
@@ -18232,7 +18294,12 @@ 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]);
-  ori4 = orient4d(p[1], p[0], p[2], p[3], p[4], w[1], w[0], w[2], w[3], w[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]);
+  }
 
   if (b->verbose > 2) {
     printf("      Heights: (%g, %g, %g, %g, %g)\n", w[0],w[1],w[2],w[3],w[4]);
@@ -18265,7 +18332,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) {
@@ -18275,7 +18342,7 @@ void tetgenmesh::flipcertify(triface *chkface, badface **pqueue)
             break;
           }
         }
-      //} // if (!b->flipinsert_random)
+      } // if (!b->flipinsert_random) // -L1
       // Insert the new item between prev and next items.
       if (prevbf == NULL) {
         *pqueue = parybf;
@@ -18389,6 +18456,7 @@ 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.
 
@@ -18477,19 +18545,9 @@ 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));
@@ -18597,7 +18655,7 @@ void tetgenmesh::flipinsertfacet(arraypool *crosstets, arraypool *toppoints,
               flipcertify(parytet, &pqueue);
             }
             crossfaces->restart();
-            if (1) { // if (!b->flipinsert_random) {
+            if (!b->flipinsert_random) {
               // Insert all queued unflipped faces.
               for (i = 0; i < bfacearray->objects; i++) {
                 parytet = (triface *) fastlookup(bfacearray, i);
@@ -18625,6 +18683,18 @@ 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 ??).
@@ -18708,7 +18778,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]);
+  dir = finddirection(&searchtet, ppt[1], 0);
   assert(dir == ACROSSVERT); // SELF_CHECK
 
   insideflag = false;
@@ -18856,7 +18926,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]);
+    dir = finddirection(&searchtet, ppt[1], 0);
     assert(dir == ACROSSVERT); // SELF_CHECK
     tsspivot1(searchtet, checkseg);
     if (checkseg.sh == NULL) {
@@ -19126,7 +19196,7 @@ void tetgenmesh::refineregion()
   ivf.splitbdflag = 0;
   ivf.validflag = 1;
   ivf.respectbdflag = 0;
-  ivf.assignmeshsize = b->metric;
+  ivf.assignmeshsize = 0;
   loc = insertvertex(steinpt, &searchtet, &splitsh, NULL, &ivf);
 
   assert((loc != OUTSIDE) && (loc != ONVERTEX));
@@ -19173,7 +19243,7 @@ void tetgenmesh::refineregion()
     ivf.splitbdflag = 0;
     ivf.validflag = 1;
     ivf.respectbdflag = 0;
-    ivf.assignmeshsize = b->metric;
+    ivf.assignmeshsize = 0;
     loc = insertvertex(steinpt, &searchtet, &splitsh, &sseg, &ivf);
 
     if (loc == NEARVERTEX) {
@@ -19525,8 +19595,10 @@ void tetgenmesh::constraineddelaunay(clock_t& tv)
     printf("Constrained Delaunay...\n");
   }
 
-  // Identify acute vertex for PLC inputs.
-  markacutevertices();
+  //if (!b->psc) {
+    // Only identify acute vertex for PLC inputs.
+    markacutevertices();
+  //}
 
   if (b->verbose) {
     printf("  Delaunizing segments.\n");
@@ -19535,6 +19607,16 @@ 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++) {
@@ -19548,6 +19630,7 @@ void tetgenmesh::constraineddelaunay(clock_t& tv)
       paryseg = (face *) fastlookup(subsegstack, s);
       *paryseg = searchseg;
     }
+  }
 
   // Recover non-Delaunay segments.
   delaunizesegments();
@@ -19628,6 +19711,10 @@ 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, 
@@ -19659,6 +19746,20 @@ 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);
@@ -19674,7 +19775,12 @@ 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];
@@ -19684,6 +19790,11 @@ 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
@@ -19723,7 +19834,12 @@ 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]
@@ -19732,6 +19848,11 @@ 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.
+              }
             }
           }
         }
@@ -19739,6 +19860,18 @@ 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, 
@@ -19752,6 +19885,11 @@ 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. 
@@ -19798,6 +19936,11 @@ 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]. 
@@ -19807,6 +19950,11 @@ 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)
@@ -19830,7 +19978,11 @@ 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.
@@ -19971,7 +20123,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,#,#] to be removed.          //
+// 'flipedge' is a non-convex or flat edge [a,b,#,#].                        //
 //                                                                           //
 // 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    //
@@ -19984,15 +20136,23 @@ 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)));
   }
 
-  fc->clearcounters();
+  //if (fc != NULL) {
+    fc->clearcounters();
+  //}
 
   if (checksubsegflag) {
     // Do not flip a segment.
@@ -20002,22 +20162,24 @@ int tetgenmesh::removeedgebyflips(triface *flipedge, flipconstraints* fc)
         printf("      Can't flip a segment (%d, %d).\n", 
                pointmark(sorg(checkseg)), pointmark(sdest(checkseg))); 
       }
-      fc->encsegcount++;
-      if (fc->collectencsegflag) {
-        if (!sinfected(checkseg)) {
-          // Queue this segment in list.
-          sinfect(checkseg);                
-          caveencseglist->newindex((void **) &paryseg);
-          *paryseg = 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;
+          }
         }
-      }
+      //}
       return 0;
     }
   }
 
   // Count the number of tets at edge [a,b].
   n = 0;
-  int counter = 0; // Sum of star counters. // SELF_CHECK.
+  counter = 0; // Sum of star counters;
   spintet = *flipedge;
   i = 0;
   while (1) {
@@ -20042,7 +20204,7 @@ int tetgenmesh::removeedgebyflips(triface *flipedge, flipconstraints* fc)
     maxflipstarsize = n;
   }
   if ((b->flipstarsize > 0) && (n > b->flipstarsize)) {
-    // The star size exceeds the limit.
+    // The star size exceeds the given limit (-YY__).
     skpflipstarcount++;
     return 0; // Do not flip it.
   }
@@ -20054,7 +20216,8 @@ int tetgenmesh::removeedgebyflips(triface *flipedge, flipconstraints* fc)
   i = 0;
   while (1) {
     abtets[i] = spintet;
-    setelemcounter(abtets[i], 1); // Marktest it (in Star(ab)).
+    //marktest(abtets[i]); // Marktest it (in Star(ab)).
+    setelemcounter(abtets[i], 1);
     i++;
     fnextself(spintet);
     if (spintet.tet == flipedge->tet) break;
@@ -20071,26 +20234,29 @@ 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;
 
@@ -20111,8 +20277,12 @@ 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);
@@ -20126,6 +20296,10 @@ 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]);
@@ -20169,14 +20343,99 @@ 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 {
-    // 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");
+    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;
       }
-      return 1;
     }
   }
 
@@ -20202,19 +20461,22 @@ int tetgenmesh::removefacebyflips(triface *flipface, flipconstraints* fc)
 int tetgenmesh::recoveredgebyflips(point startpt, point endpt, 
                                    triface* searchtet, int fullsearch)
 {
-  triface neightet, spintet;
+  triface neightet, spintet; // *abtets;
   point pa, pb, pc, pd;
   badface bakface;
   enum interresult dir, dir1;
   flipconstraints fc;
   int types[2], poss[4], pos = 0;
   int success;
-  int i, j;
+  //int n, endi;
+  int i, j; //, k;
 
   if (b->verbose > 2) {
     printf("      Recovering edge (%d, %d)\n", pointmark(startpt), 
            pointmark(endpt));
   }
+
+
   fc.seg[0] = startpt;
   fc.seg[1] = endpt;
 
@@ -20223,13 +20485,14 @@ int tetgenmesh::recoveredgebyflips(point startpt, point endpt,
 
     // Search the edge from 'startpt'.
     point2tetorg(startpt, *searchtet);
-    dir = finddirection(searchtet, endpt);
+    assert(org(*searchtet) == startpt); // SELF_CHECK
+    dir = finddirection(searchtet, endpt, 1);
     if (dir == ACROSSVERT) {
       if (dest(*searchtet) == endpt) {
         return 1; // Edge is recovered.
       } else {
         // A PLC problem, or there is a Steiner point.
-        terminatetetgen(3); 
+        terminatetetgen(3); //assert(0); // Debug
       }
     }
 
@@ -20255,165 +20518,168 @@ int tetgenmesh::recoveredgebyflips(point startpt, point endpt,
 
     if (fullsearch) {
 
-      // Try to flip one of the faces/edges which intersects the edge.
-      success = 0;
+      if (1) {
+        // 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);
-      dir = finddirection(searchtet, endpt);
-      //assert(dir != ACROSSVERT);
+        // 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);
 
-      // 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);
-            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);
-              }
+          // 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)) {
+              if (tri_edge_test(pa,pb,pc,startpt,endpt, pd, 1, types, poss)) {
                 dir = (enum interresult) types[0];
                 pos = poss[0];
-                break; // for loop
+                break;
               } 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
-        }
+            // 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
+          }
 
-        // 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);
-          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.
+          // 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) {
                   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
+        } // while (1) // Loop I-I
 
-      if (success) {
-        // One of intersecting faces/edges is flipped.
-        continue;
-      }
+        if (success) {
+          // One of intersecting faces/edges is flipped.
+          continue;
+        }
+      } // if (0)
 
     } // if (fullsearch)
 
@@ -20435,13 +20701,24 @@ 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.   //
 //                                                                           //
-// 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.      //
+// 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.                                                  //
+//                                                                           //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -20597,7 +20874,7 @@ int tetgenmesh::add_steinerpt_in_schoenhardtpoly(triface *abtets, int n,
   ivf.splitbdflag = 0;
   ivf.validflag = 0;
   ivf.respectbdflag = 0;
-  ivf.assignmeshsize = b->metric; 
+  ivf.assignmeshsize = 0; 
 
   // Insert the new point into the tetrahedralization T.
   // Note that T is convex (nonconvex = 0).
@@ -20605,7 +20882,7 @@ int tetgenmesh::add_steinerpt_in_schoenhardtpoly(triface *abtets, int n,
 
   if (loc == (int) INSTAR) {
     // The vertex has been inserted.
-    st_volref_count++; 
+    st_volref_count++; //st_inpoly_count++;
     if (steinerleft > 0) steinerleft--;
     return 1;
   } else {
@@ -20646,7 +20923,8 @@ int tetgenmesh::addsteiner4recoversegment(face* misseg, int splitsegflag)
 
   // Try to recover the edge by adding Steiner points.
   point2tetorg(startpt, searchtet);
-  dir = finddirection(&searchtet, endpt);
+  assert(org(searchtet) == startpt); // SELF_CHECK
+  dir = finddirection(&searchtet, endpt, 1);
   assert(dir != ACROSSVERT);
 
   // Get the first intersecting face/edge.
@@ -20853,7 +21131,7 @@ int tetgenmesh::addsteiner4recoversegment(face* misseg, int splitsegflag)
     ivf.splitbdflag = 0;
     ivf.validflag = 1;
     ivf.respectbdflag = 1;
-    ivf.assignmeshsize = b->metric;
+    ivf.assignmeshsize = 0;
     loc = insertvertex(steinerpt, &searchtet, &splitsh, misseg, &ivf);
 
     if (loc != ivf.iloc) {
@@ -20889,7 +21167,7 @@ int tetgenmesh::addsteiner4recoversegment(face* misseg, int splitsegflag)
     ivf.splitbdflag = 0;
     ivf.validflag = 1;
     ivf.respectbdflag = 1;
-    ivf.assignmeshsize = b->metric; 
+    ivf.assignmeshsize = 0; 
     loc = insertvertex(steinerpt, &searchtet, &splitsh, misseg, &ivf);
 
     assert(loc != (int) ONVERTEX);
@@ -20911,11 +21189,17 @@ int tetgenmesh::addsteiner4recoversegment(face* misseg, int splitsegflag)
 //                                                                           //
 // recoversegments()    Recover all segments.                                //
 //                                                                           //
-// All segments need to be recovered are in 'subsegstack'.                   //
+// 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.                                         // 
 //                                                                           //
-// 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.                             //
+// 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'.                                           //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -20927,7 +21211,7 @@ int tetgenmesh::recoversegments(arraypool *misseglist, int fullsearch,
   point startpt, endpt;
   int success;
 
-  long bak_inpoly_count = st_volref_count; 
+  long bak_inpoly_count = st_volref_count; //st_inpoly_count;
 
   if (b->verbose > 1) {
     printf("    Recover segments [%s level = %2d] #:  %ld.\n",
@@ -21050,6 +21334,7 @@ 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;
@@ -21059,7 +21344,8 @@ int tetgenmesh::recoverfacebyflips(point pa, point pb, point pc,
     while (1) {
       // Get a tet containing the edge [a,b].
       point2tetorg(fc.fac[i], *searchtet);
-      dir = finddirection(searchtet, fc.fac[(i+1)%3]);
+      assert(org(*searchtet) == fc.fac[i]); // SELF_CHECK
+      dir = finddirection(searchtet, fc.fac[(i+1)%3], 1);
       //assert(dir == ACROSSVERT);
       assert(dest(*searchtet) == fc.fac[(i+1)%3]);
       // Search the face [a,b,c]
@@ -21267,7 +21553,7 @@ int tetgenmesh::recoversubfaces(arraypool *misshlist, int steinerflag)
         endpt = sdest(searchsh);
         point2tetorg(startpt, searchtet);
         assert(org(searchtet) == startpt); // SELF_CHECK
-        dir = finddirection(&searchtet, endpt);
+        dir = finddirection(&searchtet, endpt, 1);
         if (dir == ACROSSVERT) {
           if (dest(searchtet) == endpt) {
             success = 1;  
@@ -21367,7 +21653,7 @@ int tetgenmesh::recoversubfaces(arraypool *misshlist, int steinerflag)
             ivf.splitbdflag = 0;
             ivf.validflag = 1;
             ivf.respectbdflag = 1;
-            ivf.assignmeshsize = b->metric;
+            ivf.assignmeshsize = 0;
             loc = insertvertex(steinerpt, &searchtet, &searchsh, NULL, &ivf);
             assert(loc != (int) OUTSIDE);
 
@@ -21457,7 +21743,7 @@ int tetgenmesh::recoversubfaces(arraypool *misshlist, int steinerflag)
           ivf.splitbdflag = 0;
           ivf.validflag = 1;
           ivf.respectbdflag = 1;
-          ivf.assignmeshsize = b->metric; 
+          ivf.assignmeshsize = 0; 
           loc = insertvertex(steinerpt, &searchtet, &searchsh, NULL, &ivf);
           assert(loc != (int) OUTSIDE);
 
@@ -21696,13 +21982,13 @@ int tetgenmesh::getedge(point e1, point e2, triface *tedge)
 
   // Search for the edge [e1, e2].
   point2tetorg(e1, *tedge);
-  finddirection(tedge, e2);
+  finddirection(tedge, e2, 1);
   if (dest(*tedge) == e2) {
     return 1;
   } else {
     // Search for the edge [e2, e1].
     point2tetorg(e2, *tedge);
-    finddirection(tedge, e1);
+    finddirection(tedge, e1, 1);
     if (dest(*tedge) == e1) {
       esymself(*tedge);
       return 1;
@@ -21835,7 +22121,7 @@ int tetgenmesh::reduceedgesatvertex(point startpt, arraypool* endptlist)
         }
       } else {
         point2tetorg(startpt, searchtet);
-        dir = finddirection(&searchtet, *pendpt);
+        dir = finddirection(&searchtet, *pendpt, 1);
       }
       if (dir == ACROSSVERT) {
         if (dest(searchtet) == *pendpt) {
@@ -21890,6 +22176,21 @@ 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.                                              //
 //                                                                           //
@@ -21940,11 +22241,13 @@ 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.
@@ -21973,7 +22276,7 @@ int tetgenmesh::removevertexbyflips(point steinerpt)
     //   Inverted elements.
     getvertexstar(1, steinerpt, cavetetlist, NULL, NULL);
     if (cavetetlist->objects == 2) {
-      printf("to be continued...\n");
+      printf("to be continued...");
       assert(0);
     } else {
       assert(0); // Unknown cases.
@@ -22096,7 +22399,7 @@ int tetgenmesh::removevertexbyflips(point steinerpt)
 
   if (!removeflag) {
     if (vt == FREESEGVERTEX) {
-      // Check if the edge [lpt, rpt] exists.
+      // Check if the edge [lpr, 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.
@@ -22233,6 +22536,14 @@ 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);
@@ -22353,7 +22664,7 @@ int tetgenmesh::removevertexbyflips(point steinerpt)
 
     // Insert the new segment.
     point2tetorg(lpt, searchtet);
-    finddirection(&searchtet, rpt);
+    finddirection(&searchtet, rpt, 1);
     assert(dest(searchtet) == rpt);
     sstbond1(rightseg, searchtet);
     spintet = searchtet;
@@ -22938,6 +23249,7 @@ void tetgenmesh::recoverboundary(clock_t& tv)
     printf("  Flip link level = %d\n", b->fliplinklevel);
   }
 
+  //markacutevertices();
 
   if (b->verbose) {
     printf("  Recovering segments.\n");
@@ -22949,6 +23261,16 @@ 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++) {
@@ -22962,6 +23284,7 @@ void tetgenmesh::recoverboundary(clock_t& tv)
       paryseg = (face *) fastlookup(subsegstack, s);
       *paryseg = searchseg;
     }
+  }
 
   // The init number of missing segments.
   ms = subsegs->items;
@@ -22971,6 +23294,7 @@ void tetgenmesh::recoverboundary(clock_t& tv)
   }
 
   while (1) {
+
     recoversegments(misseglist, 0, 0);
 
     if (misseglist->objects > 0) {
@@ -23275,11 +23599,10 @@ void tetgenmesh::recoverboundary(clock_t& tv)
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-
 void tetgenmesh::carveholes()
 {
-  arraypool *tetarray, *hullarray;
-  triface tetloop, neightet, hulltet, *parytet, *parytet1;
+  arraypool *tetarray;
+  triface tetloop, neightet, hulltet, *parytet;
   triface openface, casface;
   triface *regiontets;
   face checksh, casingout, casingin, *parysh;
@@ -23291,27 +23614,20 @@ void tetgenmesh::carveholes()
   int regioncount;
   int attrnum, attr, maxattr;
   int remflag;
-  int i, j, k;
+  int i, j;
 
   tetrahedron ptr;
-  shellface sptr;
 
   if (!b->quiet) {
     printf("Removing exterior tetrahedra ...\n");
   }
 
-
   // Initialize the pool of exterior tets.
   tetarray = new arraypool(sizeof(triface), 10);
-  hullarray = new arraypool(sizeof(triface), 10);
-
   regiontets = NULL;
-  regioncount = 0;
+
   maxattr = 0; // Choose a small number here.
-  //attrnum = in->numberoftetrahedronattributes;
-  attrnum = numelemattrib - (b->regionattrib > 0); 
-  // Comment: The element region marker is at the end of the list of
-  //   the element attributes.
+  attrnum = in->numberoftetrahedronattributes;
 
   // Mark as infected any unprotected hull tets.
   tetrahedrons->traversalinit();
@@ -23325,73 +23641,24 @@ 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); 
+      loc = locate(&(in->holelist[i]), &neightet, 0, 1); // randflag = 1;
       if (loc != OUTSIDE) {
-        // 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))
+        infect(neightet);
+        tetarray->newindex((void **) &parytet);
+        *parytet = neightet;
       } else {
         // A hole point locates outside of the convex hull.
         if (!b->quiet) {
@@ -23399,7 +23666,7 @@ void tetgenmesh::carveholes()
           printf("lies outside the convex hull.\n");
         }
       }
-    } // i
+    }
   }
 
   if (b->regionattrib && (in->numberofregions > 0)) { // If has -A option.
@@ -23411,7 +23678,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); 
+      loc = locate(&(in->regionlist[i]), &neightet, 0, 1); // randflag = 1;
       if (loc != OUTSIDE) {
         regiontets[i/5] = neightet;
         if ((int) in->regionlist[i + 3] > maxattr) {
@@ -23427,62 +23694,58 @@ 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);
-    // 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
+    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)) {
             infect(neightet);
-            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--;
-            }
+            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;
+          }
+          hullsize--;
         } else {
-          // Both sides of this face are in exterior.
-          // Check if there is a subface.
-          tspivot(neightet, checksh);
-          if (checksh.sh != NULL) {
+          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).
             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.
@@ -23497,76 +23760,65 @@ void tetgenmesh::carveholes()
     }
   }
 
-
-if (!b->convex) {
-
-  // Create new hull tets. 
-  // Update point-to-tet map, segment-to-tet map, and subface-to-tet map.
-  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;
-          }
-        }
-      } // j
-    }
-  } // 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);
+    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(); 
+  tetarray->restart(); // Re-use it for new hull tets.
 
+  // 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);
+          }
+          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);
+    }
+    tetloop.tet = tetrahedrontraverse();
+  }
 
   if (subfacstack->objects > 0) {
     // Remove all subfaces which do not attach to any tetrahedron.
@@ -23631,7 +23883,6 @@ if (!b->convex) {
     subfacstack->restart();
   }
 
-
   // Some vertices may be not belong to any tet. Mark them.
   delvertcount = unuverts;
   delsteinercount = 0l;
@@ -23699,10 +23950,12 @@ if (!b->convex) {
     }
   }
 
+  // Update the hull size.
+  hullsize += tetarray->objects;
 
   // Connect new hull tets.
-  for (i = 0; i < hullarray->objects; i++) {
-    parytet = (triface *) fastlookup(hullarray, i);
+  for (i = 0; i < tetarray->objects; i++) {
+    parytet = (triface *) fastlookup(tetarray, i);
     hulltet = *parytet;
     for (j = 0; j < 3; j++) {
       esym(hulltet, neightet);
@@ -23727,118 +23980,13 @@ if (!b->convex) {
     }
   }
 
-} 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);
-    }
-  }
-
+  // Set region attributes (when has -A and -AA options).
   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) {
@@ -23859,61 +24007,81 @@ if (!b->convex) {
             if (b->varvolume) { // If has -a option.
               setvolumebound(tetloop.tet, volume);
             }
-            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) {
+            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)) {
                   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);
+                  }
+                }
               }
-            } // k
+            } // ver
           } // j
           regioncount++;
         } // if (regiontets[i/5].tet != NULL)
       } // i
     }
 
-    // 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)) {
+    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);
               // Is this side protected by a subface?
-              tspivot(neightet, checksh);
+              tspivot(tetloop, checksh);
               if (checksh.sh == NULL) {
-                infect(neightet);
-                tetarray->newindex((void **) &parytet);
-                *parytet = neightet;
+                // 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);
+                }
               }
-            }
-          } // k
-        } // j
-        attr++; // Increase the attribute.
-        regioncount++;
+            } // loc
+          }
+          attr++; // Increase the attribute.
+          regioncount++;
+        } // if (!infected(tetloop))
+        tetloop.tet = tetrahedrontraverse();
       }
-      tetloop.tet = tetrahedrontraverse();
+      // Until here, every tet has a region attribute.
     }
-    // Until here, every tet has a region attribute.
 
     // Uninfect processed tets.
     tetrahedrons->traversalinit();
@@ -23923,6 +24091,8 @@ if (!b->convex) {
       tetloop.tet = tetrahedrontraverse();
     }
 
+    // Mesh elements contain region attributes now.
+    in->numberoftetrahedronattributes++;
 
     if (b->verbose) {
       assert(regioncount > 0);
@@ -23932,20 +24102,17 @@ if (!b->convex) {
         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.
@@ -23963,9 +24130,6 @@ if (!b->convex) {
   if (b->verbose && (opt_sliver_peels > 0l)) {
     printf("  Peeled %ld hull slivers.\n", opt_sliver_peels);
   }
-
-}
-
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -24508,7 +24672,7 @@ int tetgenmesh::scoutpoint(point searchpt, triface *searchtet, int randflag)
     if (randflag) {
       randomsample(searchpt, searchtet);
     }
-    loc = locate(searchpt, searchtet, 0);
+    loc = locate(searchpt, searchtet, 0, 1);
     if (loc == OUTSIDE) {
       // Not found. This happens when the mesh is not convex.
       if (!randflag) break;
@@ -24660,9 +24824,13 @@ 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)
+REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc,
+                                  int posflag)
 {
   point *pts, pa, pb, pc;
   REAL volume, vol[4], wei[4];
@@ -24674,9 +24842,9 @@ REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc)
   if (iloc == (int) INTETRAHEDRON) {
     pts = (point *) &(searchtet->tet[4]);
     assert(pts[3] != dummypoint);
-    // 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)) {
+    if (!posflag || 
+        ((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]);
@@ -24692,8 +24860,9 @@ REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc)
     pa = org(*searchtet);
     pb = dest(*searchtet);
     pc = apex(*searchtet);
-    if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0) &&
-        (pc[pointmtrindex] > 0)) {
+    if (!posflag ||
+        ((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);
@@ -24705,7 +24874,7 @@ REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc)
   } else if (iloc == (int) ONEDGE) {
     pa = org(*searchtet);
     pb = dest(*searchtet);
-    if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0)) {
+    if (!posflag || ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0))) {
       volume = distance(pa, pb);
       vol[0] = distance(searchpt, pb);
       vol[1] = distance(pa, searchpt);
@@ -24714,7 +24883,7 @@ REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet, int iloc)
     }
   } else if (iloc == (int) ONVERTEX) {
     pa = org(*searchtet);
-    if (pa[pointmtrindex] > 0) {
+    if (!posflag || (pa[pointmtrindex] > 0)) {
       size = pa[pointmtrindex];
     }
   }
@@ -24750,8 +24919,8 @@ void tetgenmesh::interpolatemeshsize()
     searchtet.tet = NULL;
     iloc = bgm->scoutpoint(ploop, &searchtet, 1); // randflag = 1
     if (iloc != (int) OUTSIDE) {
-      // Interpolate the mesh size.
-      ploop[pointmtrindex] = bgm->getpointmeshsize(ploop, &searchtet, iloc);
+      // Interpolate the mesh size (posflag = 0)
+      ploop[pointmtrindex] = bgm->getpointmeshsize(ploop, &searchtet, iloc, 0);
       setpoint2bgmtet(ploop, bgm->encode(searchtet));
       if (count == 0) {
         // This is the first interpolated point.
@@ -24793,8 +24962,7 @@ void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
   face checkseg, *splitseg;
   point newpt;
   insertvertexflags ivf;
-  REAL x, y, z, w;
-  int attribindex, mtrindex;
+  REAL *attr, x, y, z, w;
   int randflag;
   int count, index;
   int loc;
@@ -24807,39 +24975,42 @@ 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, UNUSEDVERTEX);
+    makepoint(&newpt, VOLVERTEX);
     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 its weight.
-        w = newpt[3];
+        // The first point attribute is weight.
+        w = addio->pointattributelist[addio->numberofpointattributes * i];
       } else {
-        // 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);
+        // No given weight available.
+        w = 0;
       }
       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;
@@ -24854,14 +25025,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 = b->metric;
+      ivf.assignmeshsize = 1;
 
       splitsh = NULL;
       splitseg = NULL;
@@ -24894,8 +25065,6 @@ void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
           setpointtype(newpt, FACETVERTEX);
           splitsh = &checksh;
         }
-      } else {
-        setpointtype(newpt, VOLVERTEX);
       }
 
       // Insert the vertex.
@@ -24936,6 +25105,8 @@ 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.                    //
 //                                                                           //
@@ -24968,7 +25139,7 @@ void tetgenmesh::marksharpsegments()
 
   minfacetdihed = PI;
   smallang = 65.0 * PI / 180.0; // 65 degree.
-  exsmallang = 5.0 * PI / 180.0; // 5 degree.
+  exsmallang = 15.0 * PI / 180.0; // 15 degree.
   sharpcount = exsharpcount = 0;
 
   // A segment s may have been split into many subsegments. Operate the one
@@ -25126,8 +25297,13 @@ 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 size. It  //
-// is used to prevent creating too close Steiner points.                     //
+// 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.                 //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -25158,8 +25334,9 @@ void tetgenmesh::decidefeaturepointsizes()
     maxlen = pow(6.0 * b->maxvolume, 1.0 / 3.0);
   }
 
-  // First, assign a size of p if p is a feature point or an input point and 
-  //   the -Y option is used.
+  // First only assign a size of p if p is not a Steiner point. The size of
+  //   a Steiner point will be interpolated later from the endpoints of the
+  //   segment on which it lies. 
   featurecount = 0;
   points->traversalinit();
   ploop = pointtraverse();
@@ -25332,9 +25509,9 @@ void tetgenmesh::decidefeaturepointsizes()
     printf("  %d feature points.\n", featurecount);
   }
 
-  // Second only assign sizes for all Steiner points which were inserted on
-  //   sharp segments. The sizes are interpolated from the endpoints of
-  //   the segments.
+  // Second only assign sizes for all Steiner points. A Steiner point p
+  //   inserted on a sharp segment s is assigned a size by interpolating
+  //   the sizes of the original endpoints of s.
   featurecount = 0;
   points->traversalinit();
   ploop = pointtraverse();
@@ -25364,7 +25541,67 @@ 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();
   }
@@ -25374,8 +25611,7 @@ void tetgenmesh::decidefeaturepointsizes()
   }
 
   if (checkconstraints) {
-    // A .var file exists. Adjust feature sizes. And make sure that every
-    //   corner of a constraining facet get a size.
+    // A .var file exists. Adjust feature sizes.
     if (in->facetconstraintlist) {
       // Have facet area constrains.
       subfaces->traversalinit();
@@ -25391,9 +25627,6 @@ void tetgenmesh::decidefeaturepointsizes()
               if (ploop[pointmtrindex] > varlen) {
                 ploop[pointmtrindex] = varlen;
               }
-            } else {
-              // This corner has no size yet. Set it.
-              ploop[pointmtrindex] = varlen;
             }
           } // j
         }
@@ -25414,8 +25647,6 @@ void tetgenmesh::decidefeaturepointsizes()
               if (ploop[pointmtrindex] > varlen) {
                 ploop[pointmtrindex] = varlen;
               }
-            } else {
-              ploop[pointmtrindex] = varlen;
             }
           } // j
         }
@@ -25425,7 +25656,6 @@ void tetgenmesh::decidefeaturepointsizes()
   } // if (checkconstraints)
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // checkseg4encroach()    Check if an edge is encroached upon by a point.    //
@@ -25477,7 +25707,6 @@ 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  //
@@ -25631,19 +25860,21 @@ 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) {
-      // 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) && (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;
     }
   }
 
@@ -25651,20 +25882,26 @@ int tetgenmesh::splitsegment(face *splitseg, point encpt, int qflag,
   getsteinerptonsegment(splitseg, encpt, newpt);
 
 
-  // Split the segment by the Bowyer-Watson algorithm.
+  // 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.
   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;   // Preserve subsegments and subfaces;
+    ivf.bowywat = 3;   // Use the "Bowyer-Watson" algorithm to form cavity.
     ivf.validflag = 1; // Validate the B-W cavity.
   }
-  ivf.lawson = b->conforming ? 3 : 1; // Check flip for internal new faces?.
-  ivf.rejflag = 0;     // Do not check encroachment of new segments/facets.
+  ivf.lawson = 3;
+  ivf.rejflag = 0;
   if ((encpt == NULL) && (qflag == 0)) {
-    ivf.rejflag |= 4;  // Do check encroachment of protecting balls.
+    // Do not insert the point if it lies inside some protecting balls.
+    ivf.rejflag |= 4; 
   }
   ivf.chkencflag = chkencflag;
   ivf.sloc = ivf.iloc;
@@ -25672,22 +25909,35 @@ 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);
 
-  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.
+  // 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'.
     lawsonflip3d(newpt, 4, 0, chkencflag, 0);
     st_segref_count++;
     if (steinerleft > 0) steinerleft--;
     return 1;
   } else {
-    pointdealloc(newpt);
-    return 0;
+    // The vertex was not inserted. For unknown reasons.
+    //pointdealloc(newpt);
+    assert(0);
   }
+
+  // Should not be here.
+  return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -25873,9 +26123,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 > 3) {
-      printf("        circent: (%g, %g, %g)\n", cent[0], cent[1], cent[2]);
-      printf("        cirradi: %g\n", rd);
+    if (b->verbose > 2) {
+      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.
@@ -25892,8 +26142,8 @@ int tetgenmesh::checkfac4split(face *chkfac, point& encpt, int& qflag,
 
 
     D = sqrt(D);
-    if (b->verbose > 3) {
-      printf("        shortest edge length = %g\n", D);
+    if (b->verbose > 2) {
+      printf("      shortest edge length = %g\n", D);
     }
 
     rhs[3] = rd / D; // The radius-edge ratio.
@@ -25949,7 +26199,9 @@ int tetgenmesh::checkfac4split(face *chkfac, point& encpt, int& qflag,
       }
       sesymself(*chkfac);
     }
-  } 
+  } else {
+    assert(0);
+  } // if (!lu_decomp)
 
   return 0;
 }
@@ -26006,6 +26258,9 @@ 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;
     }
   }
@@ -26013,6 +26268,8 @@ 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'.
@@ -26031,15 +26288,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; // Preserve segments and subfaces.
-  ivf.lawson = b->conforming ? 3 : 1;
-  ivf.rejflag = 1; // Do check the encroachment of segments.
+  // 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.
   if (qflag == 0) {
     ivf.rejflag |= 4; // Reject it if it encroached upon any vertex.
   }
@@ -26056,54 +26313,57 @@ int tetgenmesh::splitsubface(face *splitfac, point encpt, int qflag,
 
   loc = insertvertex(newpt, &searchtet, &searchsh, NULL, &ivf);
 
-  if (loc == (int) ivf.iloc) {
-    if (b->verbose > 2) {
-      printf("      Point inserted successfully on facet.\n");
-    }
-    // Flip not locally Delaunay link facets.
-    lawsonflip3d(newpt, 4, 0, chkencflag, 0);
-    st_facref_count++;
-    if (steinerleft > 0) steinerleft--;
-    return 1;
-  } else {
-    // 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;
-        }
+  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.
-          }
+    }
+    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;
     }
+    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.
+  } else {
+    // Unknown error.
+    assert(0);
   }
 
+  // Should not be here.
+  return 0;  
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -26168,7 +26428,6 @@ void tetgenmesh::repairencfacs(int chkencflag)
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-
 int tetgenmesh::checktet4split(triface *chktet, int &qflag, REAL *ccent) 
 {
   point pa, pb, pc, pd, *ppt;
@@ -26209,8 +26468,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 > 3) {
-      printf("        Min dihed = 0 (degree)\n");
+    if (b->verbose > 2) {
+      printf("      Min dihed = 0 (degree)\n");
     }
     // Return its barycenter.
     for (i = 0; i < 3; i++) {
@@ -26222,8 +26481,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 > 3) {
-      printf("        volume = %g.\n", vol);
+    if (b->verbose > 2) {
+      printf("      volume = %g.\n", vol);
     }
     if (b->fixedvolume) {
       if (vol > b->maxvolume) {
@@ -26286,8 +26545,8 @@ int tetgenmesh::checktet4split(triface *chktet, int &qflag, REAL *ccent)
     }
     smlen = sqrt(smlen);
     D = rd / smlen;
-    if (b->verbose > 3) {
-      printf("        Ratio-edge ratio = %g, smlen = %g\n", D, smlen);
+    if (b->verbose > 2) {
+      printf("      Ratio-edge ratio = %g, smlen = %g\n", D, smlen);
     }
     if (D > b->minratio) {
       // A bad radius-edge ratio.
@@ -26327,8 +26586,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 > 3) {
-      printf("        Min dihed = %g (degree)\n", acos(maxcosd) / PI * 180.0);
+    if (b->verbose > 2) {
+      printf("      Min dihed = %g (degree)\n", acos(maxcosd) / PI * 180.0);
     }
     if (maxcosd > cosmindihed) {
       // Calculate the circumcenter of this tet.
@@ -26413,12 +26672,17 @@ 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;
-  ivf.bowywat = 3;  // Preserve subsegments and subfaces;
-  ivf.lawson = b->conforming ? 3 : 1;
-  ivf.rejflag = 3;  // Do check for encroached segments and subfaces.
+  // 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;
   if (qflag == 0) {
     ivf.rejflag |= 4; // Reject it if it lies in some protecting balls.
   }
@@ -26435,10 +26699,7 @@ int tetgenmesh::splittetrahedron(triface* splittet, int qflag, REAL *ccent,
   loc = insertvertex(newpt, &searchtet, NULL, NULL, &ivf);
 
   if (loc == (int) ENCSEGMENT) {
-    if (b->verbose > 2) {
-      printf("      Point encroached upon %ld segments.\n", 
-             encseglist->objects);
-    }
+    // There are encroached segments.
     pointdealloc(newpt);
     assert(encseglist->objects > 0);
     splitflag = 0;
@@ -26470,10 +26731,7 @@ int tetgenmesh::splittetrahedron(triface* splittet, int qflag, REAL *ccent,
     }
     return splitflag;
   } else if (loc == (int) ENCSUBFACE) {
-    if (b->verbose > 2) {
-      printf("      Point encroached upon %ld subfaces.\n", 
-             encshlist->objects);
-    }
+    // There are encroached subfaces.
     pointdealloc(newpt);
     assert(encshlist->objects > 0);
     splitflag = 0;
@@ -26524,9 +26782,6 @@ 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.
@@ -26595,7 +26850,6 @@ void tetgenmesh::repairbadtets(int chkencflag)
   }
 }
 
-
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // enforcequality()    Refine the mesh.                                      //
@@ -26612,16 +26866,13 @@ 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("  Min radiu-edge ratio = %g.\n", b->minratio);
-    printf("  Min dihedral   angle = %g.\n", b->mindihedral);
-    //printf("  Min Edge length = %g.\n", b->minedgelength);
+    printf("  Edge length limit = %g.\n", b->minedgelength);
   }
 
   steinerleft = b->steinerleft;  // Upperbound of # Steiner points (by -S#).
@@ -26633,7 +26884,7 @@ void tetgenmesh::delaunayrefinement()
     } else {
       if (!b->quiet) {
         printf("\nWarning:  ");
-        printf("The desired number of Steiner points (%d) has reached.\n\n",
+        printf("The desired number of Steiner points (%d) is reached.\n\n",
                b->steinerleft);
       }
       return; // No more Steiner points.
@@ -26648,7 +26899,6 @@ void tetgenmesh::delaunayrefinement()
 
   decidefeaturepointsizes();
 
-
   encseglist = new arraypool(sizeof(face), 8);
   encshlist = new arraypool(sizeof(badface), 8);
 
@@ -26758,8 +27008,6 @@ 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)
 
@@ -26812,10 +27060,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.
@@ -26873,7 +27121,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 = 10; //b->optmaxflipstarsize;
+  b->flipstarsize = b->optmaxflipstarsize;
 
   flipqueue = new arraypool(sizeof(badface), 10);
   nextflipqueue = new arraypool(sizeof(badface), 10);
@@ -27038,15 +27286,14 @@ long tetgenmesh::improvequalitybyflips()
   flipqueue = new arraypool(sizeof(badface), 10);
   nextflipqueue = new arraypool(sizeof(badface), 10);
 
-  // Backup flip edge options.
-  int bakautofliplinklevel = autofliplinklevel;
-  int bakfliplinklevel = b->fliplinklevel;
-  int bakmaxflipstarsize = b->flipstarsize;
-
-  // Set flip edge options.
-  autofliplinklevel = 1; 
+  // Flip edge options.
   b->fliplinklevel = -1;
-  b->flipstarsize = 10; // b->optmaxflipstarsize;
+  autofliplinklevel = 1; // Init value.
+
+  // 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; 
 
   fc.remove_large_angle = 1;
   fc.unflip = 1;
@@ -27073,7 +27320,6 @@ 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.
@@ -27167,12 +27413,12 @@ long tetgenmesh::improvequalitybyflips()
     totalremcount += remcount;
 
     if (unflipqueue->objects > 0l) {
-      //if (autofliplinklevel >= b->optmaxfliplevel) {
-      if (autofliplinklevel >= b->optlevel) {
+      // 'b->optmaxfliplevel' is set by -OOO, default is 2.
+      if (autofliplinklevel >= b->optmaxfliplevel) {
+        // For efficiency reason, we do not search too far.
         break;
       }
       autofliplinklevel+=b->fliplinklevelinc;
-      //b->flipstarsize = 10 + (1 << (b->optlevel - 1));
     }
 
     // Swap the two flip queues.
@@ -27181,9 +27427,6 @@ long tetgenmesh::improvequalitybyflips()
     unflipqueue = swapqueue;
   } // while (flipqueues->objects > 0)
 
-  // Restore original flip edge options.
-  autofliplinklevel = bakautofliplinklevel;
-  b->fliplinklevel = bakfliplinklevel;
   b->flipstarsize = bakmaxflipstarsize;
 
   delete flipqueue;
@@ -27612,7 +27855,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 dihedral angle. 
+  // 'slitet' is [c,d,a,b], where [c,d] has a big hihedral angle. 
   // Go to the opposite edge [a,b].
   eprev(*slitet, searchtet);
   esymself(searchtet);
@@ -27625,18 +27868,13 @@ 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].
@@ -27883,12 +28121,11 @@ long tetgenmesh::removeslivers(int chkencflag)
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-void tetgenmesh::optimizemesh()
+void tetgenmesh::optimizemesh(int optflag)
 {
   badface *parybface;
   triface checktet;
   point *ppt;
-  int optpasses;
   optparameters opm;
   REAL ncosdd[6], maxdd;
   long totalremcount, remcount;
@@ -27902,16 +28139,18 @@ void tetgenmesh::optimizemesh()
     printf("Optimizing mesh...\n");
   }
 
-  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);
+  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);
   }
-
-  optpasses = ((1 << b->optlevel) - 1);
-
   totalsmtcount = totalsptcount = totalremcount = 0l;
 
+  if (b->verbose > 1) {
+    printf("    Removing large angles (> %g degree).\n", b->optmaxdihedral);
+  }
+
   cosmaxdihed = cos(b->optmaxdihedral / 180.0 * PI);
   cossmtdihed = cos(b->optminsmtdihed / 180.0 * PI);
   cosslidihed = cos(b->optminslidihed / 180.0 * PI);
@@ -27942,7 +28181,7 @@ void tetgenmesh::optimizemesh()
   totalremcount = improvequalitybyflips();
 
   if ((unflipqueue->objects > 0l) && 
-      ((b->optscheme & 2) || (b->optscheme & 4))) {
+      ((b->optlevel & 2) || (b->optlevel & 4))) { // -O2 | -O4
 
     badtetrahedrons = new memorypool(sizeof(badface), b->tetrahedraperblock,
                                      memorypool::POINTER, 0);
@@ -27956,9 +28195,9 @@ void tetgenmesh::optimizemesh()
     chkencflag = 4; // Queue affected tets after splitting a sliver.
     iter = 0;
 
-    while (iter < optpasses) {
+    while (iter < b->optpasses) {
       smtcount = sptcount = remcount = 0l;
-      if (b->optscheme & 2) {
+      if (b->optlevel & 2) {
         smtcount += improvequalitybysmoothing(&opm);
         totalsmtcount += smtcount;
         if (smtcount > 0l) {
@@ -27967,7 +28206,7 @@ void tetgenmesh::optimizemesh()
         }
       }
       if (unflipqueue->objects > 0l) {
-        if (b->optscheme & 4) {
+        if (b->optlevel & 4) {
           sptcount += removeslivers(chkencflag);
           totalsptcount += sptcount;
           if (sptcount > 0l) {
@@ -27989,7 +28228,7 @@ void tetgenmesh::optimizemesh()
 
     delete badtetrahedrons;
 
-  }
+  } // // -O2 | -O4
 
   if (unflipqueue->objects > 0l) {
     if (b->verbose > 1) {
@@ -28197,10 +28436,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) spinsh.sh,
+          printf("    First: x%lx (%d, %d, %d).\n", (unsigned long long) spinsh.sh,
                  pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), 
                  pointmark(sapex(spinsh)));
-          printf("    Second: x%lx (DEAD)\n", (unsigned long) nextsh.sh);
+          printf("    Second: x%lx (DEAD)\n", (unsigned long long) nextsh.sh);
           horrors++;
           break;
         }
@@ -28208,10 +28447,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) spinsh.sh,
+           printf("    First: x%lx (%d, %d, %d).\n", (unsigned long long) spinsh.sh,
                   pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), 
                   pointmark(sapex(spinsh)));
-           printf("    Scond: x%lx (%d, %d, %d).\n", (unsigned long) nextsh.sh,
+           printf("    Scond: x%lx (%d, %d, %d).\n", (unsigned long long) nextsh.sh,
                   pointmark(sorg(nextsh)), pointmark(sdest(nextsh)), 
                   pointmark(sapex(nextsh)));
            horrors++;
@@ -28220,10 +28459,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) spinsh.sh,
+           printf("    First: x%lx (%d, %d, %d).\n", (unsigned long long) spinsh.sh,
                   pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), 
                   pointmark(sapex(spinsh)));
-           printf("    Scond: x%lx (%d, %d, %d).\n", (unsigned long) nextsh.sh,
+           printf("    Scond: x%lx (%d, %d, %d).\n", (unsigned long long) nextsh.sh,
                   pointmark(sorg(nextsh)), pointmark(sdest(nextsh)), 
                   pointmark(sapex(nextsh)));
            horrors++;
@@ -28237,19 +28476,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) shloop.sh,
+          printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) shloop.sh,
                  pointmark(sorg(shloop)), pointmark(sdest(shloop)), 
                  pointmark(sapex(shloop)));
-          printf("    Sub: x%lx (Dead)\n", (unsigned long) checkseg.sh);
+          printf("    Sub: x%lx (Dead)\n", (unsigned long 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) shloop.sh,
+            printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) shloop.sh,
                    pointmark(sorg(shloop)), pointmark(sdest(shloop)), 
                    pointmark(sapex(shloop)));
-            printf("    Seg: x%lx (%d, %d).\n", (unsigned long) checkseg.sh,
+            printf("    Seg: x%lx (%d, %d).\n", (unsigned long long) checkseg.sh,
                    pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
             horrors++;
           }
@@ -28263,20 +28502,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) shloop.sh,
+        printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) shloop.sh,
                pointmark(sorg(shloop)), pointmark(sdest(shloop)), 
                pointmark(sapex(shloop)));
-        printf("    Tet: x%lx (DEAD)\n", (unsigned long) neightet.tet);
+        printf("    Tet: x%lx (DEAD)\n", (unsigned long 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) shloop.sh,
+          printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) shloop.sh,
                  pointmark(sorg(shloop)), pointmark(sdest(shloop)), 
                  pointmark(sapex(shloop)));
           printf("    Tet: x%lx (%d, %d, %d, %d).\n",
-                 (unsigned long) neightet.tet, pointmark(org(neightet)), 
+                 (unsigned long long) neightet.tet, pointmark(org(neightet)), 
                  pointmark(dest(neightet)), pointmark(apex(neightet)),
                  pointmark(oppo(neightet)));
           horrors++;
@@ -28285,11 +28524,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) spinsh.sh,
+          printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) spinsh.sh,
                  pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), 
                  pointmark(sapex(spinsh)));
           printf("    Tet: x%lx (%d, %d, %d, %d).\n", 
-                 (unsigned long) neightet.tet, pointmark(org(neightet)), 
+                 (unsigned long long) neightet.tet, pointmark(org(neightet)), 
                  pointmark(dest(neightet)), pointmark(apex(neightet)), 
                  pointmark(oppo(neightet)));
           horrors++;
@@ -28300,11 +28539,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) spinsh.sh,
+            printf("    Sub: x%lx (%d, %d, %d).\n", (unsigned long long) spinsh.sh,
                    pointmark(sorg(spinsh)), pointmark(sdest(spinsh)), 
                    pointmark(sapex(spinsh)));
             printf("    Tet: x%lx (%d, %d, %d, %d).\n", 
-                   (unsigned long) symtet.tet, pointmark(org(symtet)), 
+                   (unsigned long long) symtet.tet, pointmark(org(symtet)), 
                    pointmark(dest(symtet)), pointmark(apex(symtet)), 
                    pointmark(oppo(symtet)));
             horrors++;
@@ -28384,9 +28623,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) tetloop.tet, pointmark(org(tetloop)),
+                   (unsigned long long) tetloop.tet, pointmark(org(tetloop)),
                    pointmark(dest(tetloop)), pointmark(apex(tetloop)),
-                   pointmark(oppo(tetloop)), (unsigned long) sseg.sh,
+                   pointmark(oppo(tetloop)), (unsigned long long) sseg.sh,
                    pointmark(pa), pointmark(pb));
             horrors++;
           } else {
@@ -28397,11 +28636,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) neightet.tet, pointmark(org(neightet)),
+                       (unsigned long 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) checkseg.sh,
+                  printf("Seg x%lx (%d, %d).\n", (unsigned long long) checkseg.sh,
                          pointmark(sorg(checkseg)),pointmark(sdest(checkseg))); 
                 } else {
                   printf("Seg: NULL.\n");
@@ -28421,9 +28660,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) neightet.tet, pointmark(org(neightet)),
+                     (unsigned long long) neightet.tet, pointmark(org(neightet)),
                      pointmark(dest(neightet)), pointmark(apex(neightet)),
-                     pointmark(oppo(neightet)), (unsigned long) sseg.sh,
+                     pointmark(oppo(neightet)), (unsigned long long) sseg.sh,
                      pointmark(pa), pointmark(pb));
               horrors++;
             }
@@ -28440,7 +28679,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) neightet.tet, neightet.ver);
+               (unsigned long long) neightet.tet, neightet.ver);
         // Check if all tets at the edge are marked.
         spintet = neightet;
         while (1) {
@@ -28449,7 +28688,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) spintet.tet, spintet.ver);
+                   (unsigned long long) spintet.tet, spintet.ver);
             horrors++;
           }
           if (spintet.tet == neightet.tet) break;
@@ -28482,7 +28721,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) spinsh.sh,
+          //         pointmark(sapex(spinsh)), (unsigned long long) spinsh.sh,
           //         spinsh.shver);
           //  horrors++;
           //}
@@ -28495,7 +28734,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) spintet.tet, spintet.ver);
+                       (unsigned long long) spintet.tet, spintet.ver);
                 horrors++;
               }
               if (checkseg.sh != sseg.sh) {
@@ -28514,7 +28753,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) spinsh.sh,
+                 pointmark(sapex(spinsh)), (unsigned long long) spinsh.sh,
                  spinsh.shver);
           horrors++;
           break;
@@ -29336,11 +29575,7 @@ void tetgenmesh::statistics()
   tetnumber = tetrahedrons->items - hullsize;
   facenumber = (tetnumber * 4l + hullsize) / 2l;
 
-  if (b->weighted) { // -w option
-    printf("\n  Mesh points: %ld\n", points->items - nonregularcount);
-  } else {
-    printf("\n  Mesh points: %ld\n", points->items);
-  }
+  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);
@@ -29349,10 +29584,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 on boundary edges: %ld\n", st_segref_count);
+      printf("  Steiner points in boundary edges: %ld\n", st_segref_count);
     }
     if (st_facref_count > 0l) {
-      printf("  Steiner points on boundary faces: %ld\n", st_facref_count);
+      printf("  Steiner points in boundary faces: %ld\n", st_facref_count);
     }
     if (st_volref_count > 0l) {
       printf("  Steiner points in mesh domain: %ld\n", st_volref_count);
@@ -29361,9 +29596,6 @@ 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");
 
 
@@ -29415,7 +29647,7 @@ void tetgenmesh::jettisonnodes()
     jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) || 
       (pointtype(pointloop) == UNUSEDVERTEX);
     if (jetflag) {
-      // It is a duplicated or unused point, delete it.
+      // It is a duplicated point, delete it.
       pointdealloc(pointloop);
       remcount++;
     } else {
@@ -29430,6 +29662,12 @@ 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) {
@@ -29445,100 +29683,6 @@ 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();
-  }
-}
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
@@ -29614,7 +29758,7 @@ void tetgenmesh::outnodes(tetgenio* out)
   char outnodefilename[FILENAMESIZE];
   face parentsh;
   point pointloop;
-  int nextras, bmark, marker = 0, weightDT = 0; 
+  int nextras, bmark, marker = 0;
   int coordindex, attribindex;
   int pointnumber, firstindex;
   int index, i;
@@ -29632,11 +29776,7 @@ void tetgenmesh::outnodes(tetgenio* out)
     }
   }
 
-  nextras = numpointattrib;
-  if (b->weighted) { // -w
-    if (b->weighted_param == 0) weightDT = 1; // Weighted DT.
-  }
-
+  nextras = in->numberofpointattributes;
   bmark = !b->nobound && in->pointmarkerlist;
 
   if (out == (tetgenio *) NULL) {
@@ -29720,13 +29860,7 @@ void tetgenmesh::outnodes(tetgenio* out)
               pointloop[0], pointloop[1], pointloop[2]);
       for (i = 0; i < nextras; i++) {
         // Write an attribute.
-        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]);
-        }
+        fprintf(outfile, "  %.17g", pointloop[4 + i]);
       }
       if (bmark) {
         // Write the boundary marker.
@@ -29758,13 +29892,7 @@ void tetgenmesh::outnodes(tetgenio* out)
       // Point attributes.
       for (i = 0; i < nextras; i++) {
         // Output an attribute.
-        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];
-        }
+        out->pointattributelist[attribindex++] = pointloop[4 + i];
       }
       if (bmark) {
         // Output the boundary marker.  
@@ -29892,7 +30020,7 @@ void tetgenmesh::outelements(tetgenio* out)
   long ntets;
   int firstindex, shift;
   int pointindex, attribindex;
-  int highorderindex = 11; 
+  int highorderindex = 10; // The reserved pointer.
   int elementnumber;
   int eextras;
   int ishulledge;
@@ -29914,7 +30042,7 @@ void tetgenmesh::outelements(tetgenio* out)
   // The number of tets excluding hull tets.
   ntets = tetrahedrons->items - hullsize;
 
-  eextras = numelemattrib;
+  eextras = in->numberoftetrahedronattributes;
   if (out == (tetgenio *) NULL) {
     outfile = fopen(outelefilename, "w");
     if (outfile == (FILE *) NULL) {
@@ -29958,13 +30086,8 @@ void tetgenmesh::outelements(tetgenio* out)
   tptr = tetrahedrontraverse();
   elementnumber = firstindex; // in->firstnumber;
   while (tptr != (tetrahedron *) NULL) {
-    if (!b->reversetetori) {
-      p1 = (point) tptr[4];
-      p2 = (point) tptr[5];
-    } else {
-      p1 = (point) tptr[5];
-      p2 = (point) tptr[4];
-    }
+    p1 = (point) tptr[4];
+    p2 = (point) tptr[5];
     p3 = (point) tptr[6];
     p4 = (point) tptr[7];
     if (out == (tetgenio *) NULL) {
@@ -29972,9 +30095,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 (b->order == 2) {
+      if (0) { // if (b->order == 2) {
         extralist = (point *) tptr[highorderindex];
-        // indices for six extra points.
+        // Tetrahedron number, indices for four points plus six extra points.
         fprintf(outfile, "  %5d %5d %5d %5d %5d %5d",
           pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
           pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
@@ -29989,7 +30112,7 @@ void tetgenmesh::outelements(tetgenio* out)
       tlist[pointindex++] = pointmark(p2) - shift;
       tlist[pointindex++] = pointmark(p3) - shift;
       tlist[pointindex++] = pointmark(p4) - shift;
-      if (b->order == 2) {
+      if (0) { // if (b->order == 2) {
         extralist = (point *) tptr[highorderindex];
         tlist[pointindex++] = pointmark(extralist[0]) - shift;
         tlist[pointindex++] = pointmark(extralist[1]) - shift;
@@ -30002,8 +30125,10 @@ void tetgenmesh::outelements(tetgenio* out)
         talist[attribindex++] = elemattribute(tptr, i);
       }
     }
-    // Remember the index of this element (for counting edges).
-    setelemindex(tptr, elementnumber);
+    //if (b->neighout) {
+      // Remember the index of this element.
+      setelemindex(tptr, elementnumber);
+    //}
     tptr = tetrahedrontraverse();
     elementnumber++;
   }
@@ -30049,6 +30174,11 @@ 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)
@@ -30066,12 +30196,6 @@ 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");
@@ -30087,6 +30211,7 @@ 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");
@@ -30097,8 +30222,7 @@ 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 * (b->order == 1 ? 3 : 6)];
+    out->trifacelist = new int[faces * 3];
     if (out->trifacelist == (int *) NULL) {
       printf("Error:  Out of memory.\n");
       terminatetetgen(1);
@@ -30147,15 +30271,6 @@ 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) { 
@@ -30191,10 +30306,6 @@ 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);
@@ -30208,11 +30319,6 @@ 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;
           }
@@ -30348,12 +30454,6 @@ 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");
@@ -30367,6 +30467,8 @@ void tetgenmesh::outsubfaces(tetgenio* out)
     }
   }
 
+  //bmark = !b->nobound && in->facetmarkerlist;
+
   if (out == (tetgenio *) NULL) {
     outfile = fopen(facefilename, "w");
     if (outfile == (FILE *) NULL) {
@@ -30377,8 +30479,7 @@ 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 * (b->order == 1 ? 3 : 6)];
+    out->trifacelist = new int[subfaces->items * 3];
     if (out->trifacelist == (int *) NULL) {
       terminatetetgen(1);
     }
@@ -30413,39 +30514,18 @@ 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) {
@@ -30472,10 +30552,6 @@ 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);
       }
@@ -30488,11 +30564,6 @@ 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;
       }
@@ -30534,10 +30605,6 @@ 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");
@@ -30561,8 +30628,7 @@ 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 * (b->order == 1 ? 2 : 3)];
+    out->edgelist = new int[meshedges * 2];
     if (out->edgelist == (int *) NULL) {
       printf("Error:  Out of memory.\n");
       terminatetetgen(1);
@@ -30608,24 +30674,13 @@ 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) {
@@ -30682,11 +30737,6 @@ 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");
@@ -30710,8 +30760,7 @@ 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 * (b->order == 1 ? 2 : 3)];
+    out->edgelist = new int[subsegs->items * 2];
     if (out->edgelist == (int *) NULL) {
       terminatetetgen(1);
     }
@@ -30738,45 +30787,17 @@ 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", edgenumber,
-              pointmark(torg) - shift, pointmark(tdest) - shift);
-      if (b->order == 2) { // -o2
-        fprintf(outfile, "  %4d", pointmark(pp) - shift);
-      }
-      fprintf(outfile, "  %d\n", marker);
+      fprintf(outfile, "%5d   %4d  %4d  %d\n", edgenumber,
+              pointmark(torg) - shift, pointmark(tdest) - shift, 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++;
@@ -30891,12 +30912,6 @@ 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.    //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
@@ -30989,12 +31004,7 @@ void tetgenmesh::outvoronoi(tetgenio* out)
       pt[i] = (point) tetloop.tet[4 + i];
       setpoint2tet(pt[i], encode(tetloop));
     }
-    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);
-    }
+    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]);
@@ -31267,8 +31277,7 @@ void tetgenmesh::outvoronoi(tetgenio* out)
   vpointcount = 0;
   while (ploop != (point) NULL) {
     if ((pointtype(ploop) != UNUSEDVERTEX) &&
-        (pointtype(ploop) != DUPLICATEDVERTEX) &&
-        (pointtype(ploop) != NREGULARVERTEX)) { 
+        (pointtype(ploop) != DUPLICATEDVERTEX)) { 
       getvertexstar(1, ploop, tetlist, ptlist, NULL);
       // Mark all vertices. Check if it is a hull vertex.
       ishullvert = 0;
@@ -31328,6 +31337,14 @@ 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++;
@@ -31566,18 +31583,13 @@ void tetgenmesh::outmesh2medit(char* mfilename)
   tetrahedrons->traversalinit();
   tetptr = tetrahedrontraverse();
   while (tetptr != (tetrahedron *) NULL) {
-    if (!b->reversetetori) {
-      p1 = (point) tetptr[4];
-      p2 = (point) tetptr[5];
-    } else {
-      p1 = (point) tetptr[5];
-      p2 = (point) tetptr[4];
-    }
+    p1 = (point) tetptr[4];
+    p2 = (point) tetptr[5];
     p3 = (point) tetptr[6];
     p4 = (point) tetptr[7];
     fprintf(outfile, "%5d  %5d  %5d  %5d",
             pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
-    if (numelemattrib > 0) {
+    if (in->numberoftetrahedronattributes > 0) {
       fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
     } else {
       fprintf(outfile, "  0");
@@ -31627,7 +31639,7 @@ void tetgenmesh::outmesh2vtk(char* ofilename)
 {
   FILE *outfile;
   char vtkfilename[FILENAMESIZE];
-  point pointloop, p1, p2, p3, p4;
+  point pointloop;
   tetrahedron* tptr;
   double x, y, z;
   int n1, n2, n3, n4;
@@ -31686,15 +31698,10 @@ void tetgenmesh::outmesh2vtk(char* ofilename)
     return;
   }
   while (tptr != (tetrahedron *) NULL) {
-    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];
+    point p1 = (point) tptr[4];
+    point p2 = (point) tptr[5];
+    point p3 = (point) tptr[6];
+    point p4 = (point) tptr[7];
     n1 = pointmark(p1) - in->firstnumber;
     n2 = pointmark(p2) - in->firstnumber;
     n3 = pointmark(p3) - in->firstnumber;
@@ -31749,149 +31756,186 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
                     tetgenio *addin, tetgenio *bgmin)
 {
   tetgenmesh m;
-  clock_t tv[10], ts[5]; // Timing informations (defined in time.h)
-  REAL cps = (REAL) CLOCKS_PER_SEC;
+  clock_t tv[17]; // Timing informations (defined in time.h)
 
   tv[0] = clock();
  
   m.b = b;
   m.in = in;
-  m.addin = addin;
 
-  if ((b->metric) && (bgmin->numberofpoints > 0)) {
+  if ((bgmin != NULL) && 
+      ((bgmin->numberofpoints > 0) && (bgmin->pointmtrlist != NULL))) {
     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
-    m.incrementaldelaunay(ts[0]);
+    if (!b->diagnose) {
+      m.incrementaldelaunay(tv[16]);
+    }
   }
 
   tv[2] = clock();
 
   if (!b->quiet) {
     if (b->refine) {
-      printf("Mesh reconstruction seconds:  %g\n", ((REAL)(tv[2]-tv[1])) / cps);
+      printf("Mesh reconstruction seconds:  %g\n", 
+             (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
     } else {
-      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->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
+        }
       }
     }
   }
 
-  if (b->plc) { // -p
+  if (b->plc) {
     m.meshsurface();
+  }
 
-    ts[0] = clock();
-
-    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);
-      }
+  tv[3] = clock();
 
-      return;
+  if (!b->quiet) {
+    if (b->plc) {
+      printf("Surface mesh seconds:  %g\n",
+             (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
     }
   }
 
-  tv[3] = clock();
-
-  if ((b->metric) && (m.bgm != NULL)) { // -m
-    m.bgm->initializepools();
-    m.bgm->transfernodes();
-    m.bgm->reconstructmesh();
+  if (b->plc && b->diagnose) { // -d
+    m.detectinterfaces();
 
-    ts[0] = clock();
+    tv[4] = clock();
 
     if (!b->quiet) {
-      printf("Background mesh reconstruct seconds:  %g\n",
-             ((REAL)(ts[0] - tv[3])) / cps);
+      printf("Self-intersection seconds:  %g\n",
+             (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
     }
 
-    if (b->metric) { // -m
-      m.interpolatemeshsize();
-
-      ts[1] = clock();
-
-      if (!b->quiet) {
-        printf("Size interpolating 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);
     }
-  }
 
-  tv[4] = clock();
+    return;
+  }
 
-  if (b->plc) { // -p
-    if (b->nobisect) { // -Y
-      m.recoverboundary(ts[0]);
+  if (b->plc) {
+    if (b->nobisect) { // with -Y option
+      m.recoverboundary(tv[15]);
     } else {
-      m.constraineddelaunay(ts[0]);
+      m.constraineddelaunay(tv[15]);
     }
+  }
 
-    ts[1] = clock();
+  tv[4] = clock();
 
-    if (!b->quiet) {
-      printf("Boundary recovery seconds:  %g\n", ((REAL)(ts[1]-tv[4])) / cps);
+  if (!b->quiet) {
+    if (b->plc) {
+      printf("Boundary recovery seconds:  %g\n",  
+             (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
       if (b->verbose) {
-        printf("  Segment recovery seconds:  %g\n",((REAL)(ts[0]-tv[4]))/ cps);
-        printf("  Facet recovery seconds:  %g\n", ((REAL)(ts[1]-ts[0])) / cps);
+        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);
       }
     }
+  }
 
+  if (b->plc && !b->convex) {
     m.carveholes();
+  }
 
-    ts[2] = clock();
+  tv[5] = clock();
 
-    if (!b->quiet) {
+  if (!b->quiet) {
+    if (b->plc && !b->convex) {
       printf("Exterior tets removal seconds:  %g\n", 
-             ((REAL)(ts[2]-ts[1])) / cps);
+             (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
     }
+  }
 
-    if (b->nobisect) { // -Y
-      m.suppresssteinerpoints();
+  if (b->plc && b->nobisect) { 
+    m.suppresssteinerpoints();
+  }
 
-      ts[3] = clock();
+  tv[6] = clock();
 
-      if (!b->quiet) {
-        printf("Steiner suppression seconds:  %g\n",((REAL)(ts[3]-ts[2]))/cps);
-      }
+  if (!b->quiet) {
+    if (b->plc && b->nobisect) {
+      printf("Steiner suppression seconds:  %g\n",
+             (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
+    }
+  }
 
-      m.recoverdelaunay(); 
+  if (b->plc && b->nobisect) {
+    m.recoverdelaunay(); 
+  }
 
-      ts[4] = clock();
+  tv[7] = clock();
 
-      if (!b->quiet) {
-        printf("Delaunay recovery seconds:  %g\n", ((REAL)(ts[4]-ts[3])) / cps);
-      }
+  if (!b->quiet) {
+    if (b->plc && b->nobisect) {
+      printf("Delaunay recovery seconds:  %g\n", 
+             (tv[7] - tv[6]) / (REAL) CLOCKS_PER_SEC);
     }
   }
 
-  tv[5] = clock();
+  if ((b->plc || b->refine) && (b->metric && (m.bgm != NULL))) {
+    m.bgm->initializepools();
+    m.bgm->transfernodes();
+    m.bgm->reconstructmesh();
+  }
+
+  tv[8] = 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->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);
+    }
+  }
 
   if ((b->plc || b->refine) && b->insertaddpoints) { // -i
     if ((addin != NULL) && (addin->numberofpoints > 0)) {
@@ -31899,38 +31943,44 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
     }
   }
 
-  tv[6] = clock();
+  tv[10] = clock();
 
   if (!b->quiet) {
     if ((b->plc || b->refine) && b->insertaddpoints) {
       if ((addin != NULL) && (addin->numberofpoints > 0)) {
-        printf("Constrained points seconds:  %g\n", ((REAL)(tv[6]-tv[5]))/cps);
+        printf("Constrained points seconds:  %g\n", 
+               (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
       }
     }
   }
 
 
-  if (b->quality) {
+  tv[11] = clock();
+
+
+  if ((b->plc || b->refine) && b->quality) {
     m.delaunayrefinement();
   }
 
-  tv[7] = clock();
+  tv[12] = clock();
 
   if (!b->quiet) {
-    if (b->quality) {
-      printf("Refinement seconds:  %g\n", ((REAL)(tv[7] - tv[6])) / cps);
+    if ((b->plc || b->refine) && b->quality) {
+      printf("Refinement seconds:  %g\n",
+             (tv[12] - tv[11]) / (REAL) CLOCKS_PER_SEC);
     }
   }
 
-  if ((b->plc || b->refine) && (b->optlevel > 0) && !b->conforming) {
-    m.optimizemesh();
+  if ((b->plc || b->refine) && (b->optlevel > 0)) {
+    m.optimizemesh(1);
   }
 
-  tv[8] = clock();
+  tv[13] = clock();
 
   if (!b->quiet) {
-    if ((b->plc || b->refine) && (b->optlevel > 0) && !b->conforming) {
-      printf("Optimization seconds:  %g\n", ((REAL)(tv[8] - tv[7])) / cps);
+    if ((b->plc || b->refine) && (b->optlevel > 0)) {
+      printf("Optimization seconds:  %g\n",
+             (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
     }
   }
 
@@ -31939,9 +31989,6 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
     m.jettisonnodes();
   }
 
-  if (b->order == 2) {
-    m.highorder();
-  }
 
   if (!b->quiet) {
     printf("\n");
@@ -31960,7 +32007,7 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
     m.outnodes(out);
   }
 
-  if (b->noelewritten) {
+  if (b->noelewritten == 1) {
     if (!b->quiet) {
       printf("NOT writing an .ele file.\n");
     }
@@ -31994,17 +32041,11 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
   }
 
 
-  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. 
+  if (b->edgesout) {
+    if (b->edgesout > 1) {
+      m.outedges(out); // -ee, output all mesh edges. 
     } else {
-      if (b->plc || b->refine) {
-        m.outsubsegments(out); // output subsegments.
-      }
+      m.outsubsegments(out); // -e, only output subsegments.
     }
   }
 
@@ -32037,11 +32078,13 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
   }
 
 
-  tv[9] = clock();
+  tv[14] = clock();
 
   if (!b->quiet) {
-    printf("\nOutput seconds:  %g\n", ((REAL)(tv[9] - tv[8])) / cps);
-    printf("Total running seconds:  %g\n", ((REAL)(tv[9] - tv[0])) / cps);
+    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);
   }
 
   if (b->docheck) {
diff --git a/contrib/Tetgen1.5/tetgen.h b/contrib/Tetgen1.5/tetgen.h
index e02cbefa45c0b1b4e275a04869d725849b35b8b0..41634d03f49ee9d805eb18e5511c672f8d23478a 100644
--- a/contrib/Tetgen1.5/tetgen.h
+++ b/contrib/Tetgen1.5/tetgen.h
@@ -5,7 +5,11 @@
 // A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
 //                                                                           //
 // Version 1.5                                                               //
-// October 06, 2012                                                          //
+// February 21, 2012                                                         //
+//                                                                           //
+// PRE-RELEASE TEST CODE.                                                    //
+// PLEASE DO NOT DISTRIBUTE !!                                               //
+// PLEASE HELP ME TO IMPROVE IT !!                                           //
 //                                                                           //
 // Copyright (C) 2002--2012                                                  //
 // Hang Si                                                                   //
@@ -36,27 +40,34 @@
 
 // #define TETLIBRARY
 
-// 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.
+// Uncomment the following line to disable assert macros. These macros are
+//   inserted in places where I hope to catch bugs.
 
 // #define NDEBUG
 
-// TetGen uses the double precision for a real number. 
+// 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.
 
 #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++ 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
+//   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
 
-// 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.
+// Define the _WIN64 symbol if you are running TetGen on Win64.
+
+// #define _WIN64
 
 #ifdef _MSC_VER // Microsoft Visual C++
 #  ifdef _WIN64
@@ -82,7 +93,7 @@
 //                                                                           //
 // tetgenio                                                                  //
 //                                                                           //
-// A structure for transfering data into and out of TetGen's mesh structure. //
+// A structure for transfering data into and out of TetGen.                  //
 //                                                                           //
 // 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)  //
@@ -103,18 +114,18 @@ class tetgenio {
 public:
 
   // A "polygon" describes a simple polygon (no holes). It is not necessarily
-  //   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.
+  //   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.
   typedef struct {
     int *vertexlist;
     int numberofvertices;
   } polygon;
 
-  // 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).
+  // A "facet" describes a facet. Each facet is a polygonal region possibly 
+  //   with holes, edges, and points in it.
   typedef struct {
     polygon *polygonlist;
     int numberofpolygons;
@@ -195,73 +206,68 @@ 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 (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;
+  // `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;
   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 (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. 
+  // `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. 
   REAL *holelist;
   int numberofholes;
 
-  // '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'
+  // `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'
   //   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 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.
+  // `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.
   REAL *facetconstraintlist;
   int numberoffacetconstraints;
 
-  // '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.
+  // `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.
   REAL *segmentconstraintlist;
   int numberofsegmentconstraints;
 
@@ -269,14 +275,15 @@ public:
   pbcgroup *pbcgrouplist;
   int numberofpbcgroups;
 
-  // '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.
+  // `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.
   int *trifacelist;
   int *adjtetlist;
   int *trifacemarkerlist;
@@ -438,7 +445,7 @@ public:
     pbcgroup *pg;
     int i, j;
 
-    // Notice that this routine assumes that the memory was allocated by 
+    // Notince that this routine assumes that the memory was allocated by 
     //   C++ memory allocation operator 'new'.
 
     if (pointlist != (REAL *) NULL) {
@@ -556,13 +563,12 @@ public:
 //                                                                           //
 // tetgenbehavior                                                            //
 //                                                                           //
-// A structure for maintaining the switches and parameters used by TetGen's  //
-// meshing algorithms.  They are specified by the command line arguments.    //
+// A structure to maintain the switches and parameters of TetGen.            //
 //                                                                           //
-// 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.                                                  //
+// 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.                    //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -570,81 +576,94 @@ class tetgenbehavior {
 
 public:
 
-  // 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.
+  // 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.
   char commandline[1024];
   char infilename[1024];
   char outfilename[1024];
   char addinfilename[1024];
   char bgmeshfilename[1024];
 
-  // The input object of TetGen. They are recognized by either the input 
-  //   file extensions or by the specified options. 
+  // 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. 
   enum objecttype {NODES, POLY, OFF, PLY, STL, MEDIT, VTK, MESH} object;
 
 
@@ -662,18 +681,17 @@ public:
   {
     plc = 0;
     psc = 0;
-    refine = 0;
     quality = 0;
-    nobisect = 0;
+    refine = 0;
     metric = 0;
+    nobisect = 0;
     weighted = 0;
-    brio_hilbert = 1;
-    incrflip = 0;
-    flipinsert = 0;
     varvolume = 0;
     fixedvolume = 0;
-    noexact = 0;
-    nostaticfilter = 0;
+    incrflip = 0;
+    flipinsert = 0;
+    btree = 0;
+    hilbertcurve = 0;
     insertaddpoints = 0;
     regionattrib = 0;
     conforming = 0;
@@ -693,7 +711,6 @@ public:
     noiterationnum = 0;
     nomerge = 0;
     nojettison = 0;
-    reversetetori = 0;
     docheck = 0;
     quiet = 0;
     verbose = 0;
@@ -703,21 +720,24 @@ public:
     shellfaceperblock = 4092;
     nobisect_param = 1;
     weighted_param = 0;
-    hilbert_order = -1;
-    hilbert_limit = 8;
+    flipinsert_random = 0;
+    flipinsert_ori4dexact = 0;
     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;
-    optscheme = 7;  // 1 & 2 & 4, // min_max_dihedral.
-    optlevel = 2;
+    optlevel = 7;  // 1 & 2 & 4, // min_max_dihedral.
+    optpasses = 3;
+    optmaxfliplevel = 2;
     delmaxfliplevel = 1;
+    optmaxflipstarsize = 10;
     order = 1;
     steinerleft = -1;
     facet_ang_tol = 179.9;
     maxvolume = -1.0;
     minratio = 2.0;
-    mindihedral = 5.0; 
+    mindihedral = 0.0; // 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
@@ -737,44 +757,45 @@ public:
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
-// 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".                                                    //
+// 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".         //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
-void exactinit(int, int, REAL, REAL, REAL);
+REAL exactinit();
 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);
-void predicates_statistics(int weighted);
+REAL orient4dexact(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe,
+                   REAL ah, REAL bh, REAL ch, REAL dh, REAL eh);
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
 // tetgenmesh                                                                //
 //                                                                           //
-// A structure containing the mesh data structure and the implementations of //
-// tetrahedral meshing algorithms of TetGen.                                 //
+// The object to generate tetrahedral meshes.                                //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -785,7 +806,7 @@ public:
   // Labels that signify the type of a vertex. 
   enum verttype {UNUSEDVERTEX, DUPLICATEDVERTEX, RIDGEVERTEX, ACUTEVERTEX,
                  FACETVERTEX, VOLVERTEX, FREESEGVERTEX, FREEFACETVERTEX, 
-                 FREEVOLVERTEX, NREGULARVERTEX, DEADVERTEX};
+                 FREEVOLVERTEX, HIDDENVERTEX, DEADVERTEX};
  
   // Labels that signify the type of a subsegment.
   enum shestype {NSHARP, SHARP, FAKESH};
@@ -797,8 +818,7 @@ public:
 
   // Labels that signify the result of point location.
   enum locateresult {OUTSIDE, INTETRAHEDRON, ONFACE, ONEDGE, ONVERTEX, INSTAR,
-                     ENCVERTEX, ENCSEGMENT, ENCSUBFACE, NEARVERTEX,
-                     NONREGULAR, BADELEMENT};
+                     ENCVERTEX, ENCSEGMENT, ENCSUBFACE, NEARVERTEX,BADELEMENT};
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
@@ -811,23 +831,25 @@ public:
 // and edges in S and L are respectivly called subfaces and segments to dis- //
 // tinguish them from others in T.                                           //
 //                                                                           //
-// 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.            //
+// 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. //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -838,7 +860,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 (and flags);
+  //   - an integer of element marker;
   // The structure of a tetrahedron is an array of pointers.  Its actual size
   //   (the length of the array) is determined at runtime.
 
@@ -862,11 +884,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;
+  //   - a pointer to a parent (or a duplicate) point, or a bsp_tree node;
   //   - 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 (and flags).
+  //   - an integer for point type.
   //   - 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.
@@ -890,8 +912,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.  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.         //
+// 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.   //
 //                                                                           //
 // 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   //
@@ -928,9 +950,6 @@ 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 {
@@ -1032,7 +1051,9 @@ 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.
@@ -1041,12 +1062,16 @@ 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.
 
-    // Internal counters.
+    // Counters.
     int maxflippedlinklevelcount; // Maximal flipped link levels.
     int misfliplinklevelcount; // Number of missed flip possibilities.
     int chrismastreecount; // Number of Chrismas trees (unflippable case).
@@ -1067,6 +1092,7 @@ public:
       seg[0] = NULL;
       fac[0] = NULL;
       remvert = NULL;
+      //remedge[0] = NULL;
 
       unflip = 0;
       collectnewtets = 0;
@@ -1074,6 +1100,7 @@ public:
 
       remove_ndelaunay_edge = 0;
       bak_tetprism_vol = 0.0;
+
       remove_large_angle = 0;
       cosdihed_in = 0.0;
       cosdihed_out = 0.0;
@@ -1139,8 +1166,8 @@ public:
 // Arraypool                                                                 //
 //                                                                           //
 // A dynamic linear array.                                                   //
-// (It is from Shewchuk's Starbase.c, which is provided as part of Stellar,  //
-// a program for improving tetrahedral meshes.)                              //
+// (It is simply copied 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 //
@@ -1189,7 +1216,7 @@ public:
 // Memorypool                                                                //
 //                                                                           //
 // A type used to allocate memory.                                           //
-// (It is from Shewchuk's triangle.c.)                                       //
+// (It is simply copied 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   //
@@ -1256,7 +1283,7 @@ public:
 ///////////////////////////////////////////////////////////////////////////////
 
   // Pointer to the input data (a set of nodes, a PLC, or a mesh).
-  tetgenio *in, *addin;
+  tetgenio *in;
 
   // Pointer to the switches and parameters.
   tetgenbehavior *b;
@@ -1277,8 +1304,15 @@ public:
   memorypool *flippool;
   // A stack of faces to be flipped.
   badface *flipstack;
-  // A queue to store unflippable elements.
-  arraypool *unflipqueue; 
+  // 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; 
 
   // Arrays used for point insertion (the Bowyer-Watson algorithm).
   arraypool *cavetetlist, *cavebdrylist, *caveoldtetlist;
@@ -1295,6 +1329,7 @@ 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;
 
@@ -1308,9 +1343,12 @@ public:
   // PI is the ratio of a circle's circumference to its diameter.
   static REAL PI;
 
-  // Array (size = numberoftetrahedra * 6) for storing high-order nodes of
-  //   tetrahedra (only used when -o2 switch is selected).
-  point *highordertable;
+  // 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;
 
   // Other variables.
   REAL xmax, xmin, ymax, ymin, zmax, zmin;         // Bounding box of points.
@@ -1320,13 +1358,12 @@ 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 numelemattrib;                     // Number of tetrahedron attributes.
+  int point2pbcptindex;              // Index to find a pbc point to a point.
   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.
@@ -1335,6 +1372,7 @@ 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?
@@ -1342,18 +1380,14 @@ 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;      // The cosine value of a bad dihedral tobe smoothed.
-  REAL cosslidihed;      // The cosine value of the max dihedral of a sliver.
+  REAL cossmtdihed;
+  REAL cosslidihed;          // The cosine value of 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 insphere_sos_count, orient4d_sos_count;
+  long orient3dcount, inspherecount, insphere_sos_count;
   long flip14count, flip26count, flipn2ncount;
   long flip23count, flip32count, flip44count, flip22count;
   long maxbowatcavsize, totalbowatcavsize, totaldeadtets;
@@ -1369,27 +1403,42 @@ 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                                              //
 //                                                                           //
-// 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.           //
+// 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.                                                  //
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
   // Fast lookup tables for mesh manipulation primitives.
-  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];
+  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];
 
   // Primitives for tetrahedra.
   inline void decode(tetrahedron ptr, triface& t);
@@ -1411,6 +1460,8 @@ 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);
@@ -1478,6 +1529,8 @@ 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);
@@ -1541,6 +1594,8 @@ 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);
@@ -1563,13 +1618,13 @@ public:
   badface *badfacetraverse(memorypool*);
   void pointdealloc(point);
   point pointtraverse();
-
-  void makeindex2pointmap(point*&);
-  void makepoint2submap(memorypool*, int*&, face*&);
   void maketetrahedron(triface*);
   void makeshellface(memorypool*, face*);
   void makepoint(point*, enum verttype);
 
+  void makeindex2pointmap(point*&);
+  void makepoint2submap(memorypool*, int*&, face*&);
+
   void initializepools();
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1613,7 +1668,6 @@ 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);
 
@@ -1650,17 +1704,15 @@ public:
   void transfernodes();
 
   // Point sorting.
-  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);
+  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);
 
   // Point location.
   unsigned long randomnation(unsigned int choices);
   void randomsample(point searchpt, triface *searchtet);
-  enum locateresult locate(point searchpt, triface *searchtet, int);
+  enum locateresult locate(point searchpt, triface*, int, int);
 
   // Incremental Delaunay construction.
   void initialdelaunay(point pa, point pb, point pc, point pd);
@@ -1694,7 +1746,8 @@ public:
   void meshsurface();
 
   void interecursive(shellface** subfacearray, int arraysize, int axis,
-                     REAL, REAL, REAL, REAL, REAL, REAL, int* internum);
+                     REAL bxmin, REAL bxmax, REAL bymin, REAL bymax,
+                     REAL bzmin, REAL bzmax, int* internum);
   void detectinterfaces();
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1707,27 +1760,36 @@ public:
 
   void reportselfintersect(face *seg, face *shface);
 
-  enum interresult finddirection(triface* searchtet, point endpt);
+  enum interresult finddirection(triface* searchtet, point endpt, int);
   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*, arraypool*, arraypool*, arraypool*, arraypool*);
-  int scoutcrossedge(triface& crosstet, arraypool*, arraypool*);
-  bool formcavity(triface*, arraypool*, arraypool*, arraypool*, arraypool*, 
-                  arraypool*, arraypool*);
+  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);
 
   // Facet recovery by local re-tetrahedralization [Si and Gaertner'05,'11].
-  void delaunizecavity(arraypool*, arraypool*, arraypool*, arraypool*, 
-                       arraypool*, arraypool*);
-  bool fillcavity(arraypool*, arraypool*, arraypool*, arraypool*);
-  void carvecavity(arraypool*, arraypool*, arraypool*);
-  void restorecavity(arraypool*, arraypool*, arraypool*);
+  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);
 
   // Facet recovery by flips [Shewchuk'03].
   void flipcertify(triface *chkface, badface **pqueue);
-  void flipinsertfacet(arraypool*, arraypool*, arraypool*, arraypool*);
+  void flipinsertfacet(arraypool *crosstets, arraypool *toppoints, 
+                       arraypool *botpoints, arraypool *midpoints);
 
   bool fillregion(arraypool* missingshs, arraypool*, arraypool* newshs);
   void refineregion();
@@ -1742,6 +1804,7 @@ public:
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
+  // A call back function.
   int checkflipeligibility(int fliptype, point, point, point, point, point,
                            int level, int edgepivot, flipconstraints* fc);
 
@@ -1777,7 +1840,7 @@ public:
   void reconstructmesh();
 
   int  scoutpoint(point, triface*, int randflag);
-  REAL getpointmeshsize(point, triface*, int iloc);
+  REAL getpointmeshsize(point, triface*, int iloc, int posflag);
   void interpolatemeshsize();
 
   void insertconstrainedpoints(tetgenio *addio);
@@ -1805,7 +1868,6 @@ 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();
 
@@ -1826,7 +1888,7 @@ public:
   int  splitsliver(triface *, REAL, int);
   long removeslivers(int);
 
-  void optimizemesh();
+  void optimizemesh(int optflag);
 
 ///////////////////////////////////////////////////////////////////////////////
 //                                                                           //
@@ -1878,8 +1940,8 @@ public:
 
   tetgenmesh()
   {
-    in  = addin = NULL;
     b   = NULL;
+    in  = NULL;
     bgm = NULL;
 
     tetrahedrons = subfaces = subsegs = points = NULL;
@@ -1890,6 +1952,7 @@ public:
     dummypoint = NULL;
     flipstack = NULL;
     unflipqueue = NULL;
+    btreenode_list = NULL;
 
     cavetetlist = cavebdrylist = caveoldtetlist = NULL;
     cavetetshlist = cavetetseglist = cavetetvertlist = NULL;
@@ -1900,8 +1963,6 @@ public:
     suppsteinerptlist = NULL;
     encseglist = encshlist = NULL;
 
-    highordertable = NULL;
-
     plane_pa = plane_pb = plane_pc = (point) NULL;
 
     xmax = xmin = ymax = ymin = zmax = zmin = 0.0; 
@@ -1910,13 +1971,11 @@ public:
     insegments = 0l;
     meshedges = meshhulledges = 0l;
     steinerleft = -1;
-    numpointattrib = 0;
-    sizeoftensor = 0;
     pointmtrindex = 0;
     pointparamindex = 0;
     pointmarkindex = 0;
     point2simindex = 0;
-    numelemattrib = 0;
+    point2pbcptindex = 0;
     elemattribindex = 0;
     volumeboundindex = 0;
     shmarkindex = 0;
@@ -1924,6 +1983,7 @@ public:
     checksubsegflag = 0;
     checksubfaceflag = 0;
     checkinverttetflag = 0;
+    checkpbcs = 0;
     checkconstraints = 0;
     nonconvex = 0;
     dupverts = 0;
@@ -1932,12 +1992,15 @@ public:
     randomseed = 1l;
     minfaceang = minfacetdihed = PI;
     sintheta_tol = sin(0.001 * PI / 180.0);
+
     autofliplinklevel = 1;
-    calc_tetprism_vol = 0;
+
     tetprism_vol_sum = 0.0;
+    calc_tetprism_vol = 0;
 
     ptloc_count = ptloc_max_count = 0l;
-    insphere_sos_count = orient4d_sos_count = 0l;
+    orient3dcount = 0l;
+    inspherecount = insphere_sos_count = 0l;
     flip14count = flip26count = flipn2ncount = 0l;
     flip23count = flip32count = flip44count = flip22count = 0l;
     maxbowatcavsize = totalbowatcavsize = totaldeadtets = 0l;
@@ -1952,12 +2015,15 @@ 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()
@@ -2018,10 +2084,6 @@ public:
     if (suppsteinerptlist != NULL) {
       delete suppsteinerptlist;
     }
-
-    if (highordertable != NULL) {
-      delete [] highordertable;
-    }
   } // ~tetgenmesh()
 
 };                                               // End of class tetgenmesh.
@@ -2126,26 +2188,17 @@ 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 (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.
-/*
+//   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].
+
 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).
 
@@ -2156,17 +2209,20 @@ 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) {
-  decode((t1).tet[(t1).ver & 3], t2);
-  (t2).ver = mod12[(t2).ver + 12 - ((t1).ver & 12)];
+  tetrahedron ptr = (t1).tet[(t1).ver & 3];
+  int offset = 12 - ((t1).ver & 12);
+  decode(ptr, t2);
+  (t2).ver = mod12[(t2).ver + offset];
 }
 
 inline void tetgenmesh::fsymself(triface& t) {
+  tetrahedron ptr = (t).tet[(t).ver & 3];
   int offset = 12 - ((t).ver & 12);
-  decode((t).tet[(t).ver & 3], t);
+  decode(ptr, t);
   (t).ver = mod12[(t).ver + offset];
 }
 
-// enext()  finds the next edge (counterclockwise) in the same face.
+// enext()  finds the next edge (counterclockwise) on the same face.
 
 inline void tetgenmesh::enext(triface& t1, triface& t2) {
   (t2).tet = (t1).tet;
@@ -2177,7 +2233,7 @@ inline void tetgenmesh::enextself(triface& t) {
   (t).ver = mod12[(t).ver + 4];
 }
 
-// eprev()   finds the next edge (clockwise) in the same face.
+// eprev()   finds the next edge (clockwise) on the same face.
 
 inline void tetgenmesh::eprev(triface& t1, triface& t2) {
   (t2).tet = (t1).tet;
@@ -2188,7 +2244,7 @@ inline void tetgenmesh::eprevself(triface& t) {
   (t).ver = mod12[(t).ver + 8];
 }
 
-// esym()  finds the reversed edge.  It is in the other face of the
+// esym()  finds the reversed edge.  It is on the other face of the
 //   same tetrahedron.
 
 inline void tetgenmesh::esym(triface& t1, triface& t2) {
@@ -2200,8 +2256,8 @@ inline void tetgenmesh::esymself(triface& t) {
   (t).ver = edgepivot[(t).ver];
 }
 
-// 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(). 
+// enextesym()  finds the reversed edge of the next edge. It is on the other
+//   face of the same tetrahedron.
 
 inline void tetgenmesh::enextesym(triface& t1, triface& t2) {
   enext(t1, t2);
@@ -2213,7 +2269,8 @@ inline void tetgenmesh::enextesymself(triface& t) {
   esymself(t);
 }
 
-// eprevesym()  finds the reversed edge of the previous edge.
+// eprevesym()  finds the reversed edge of the previous edge. It is on the
+//   other face of the same tetrahedron.
 
 inline void tetgenmesh::eprevesym(triface& t1, triface& t2) {
   eprev(t1, t2);
@@ -2227,7 +2284,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
-//   the combination: fsym() * esym().
+//   equivalent to the combination: fsym() * esym().
 
 inline void tetgenmesh::fnext(triface& t1, triface& t2) {
   esym(t1, t2);
@@ -2239,6 +2296,19 @@ 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.
@@ -2345,7 +2415,10 @@ inline bool tetgenmesh::infected(triface& t) {
 }
 
 // marktest(), marktested(), unmarktest() -- primitives to flag or unflag a
-//   tetrahedron.  Use the second lowerest bit of the element marker.
+//   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.
 
 inline void tetgenmesh::marktest(triface& t) {
   ((int *) (t.tet))[elemmarkerindex] |= 2;
@@ -2362,6 +2435,8 @@ 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));
@@ -2378,7 +2453,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]);
@@ -2465,7 +2540,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) (s.shver));
+  s.sh = (shellface *) ((uintptr_t) (sptr) & ~ (uintptr_t) 7);
 }
 
 inline tetgenmesh::shellface tetgenmesh::sencode(face& s) {
@@ -2700,6 +2775,17 @@ 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.
@@ -2724,7 +2810,8 @@ inline bool tetgenmesh::sinfected(face& s)
 }
 
 // smarktest(), smarktested(), sunmarktest() -- primitives to flag or unflag
-//   a subface.The last 2nd bit of the integer is flaged.
+//   a subface. 
+// The last 2nd bit of ((int *) ((s).sh))[shmarkindex+1] is flaged.
 
 inline void tetgenmesh::smarktest(face& s) 
 {
@@ -2744,7 +2831,8 @@ inline bool tetgenmesh::smarktested(face& s)
 }
 
 // smarktest2(), smarktest2ed(), sunmarktest2() -- primitives to flag or 
-//   unflag a subface. The last 3rd bit of the integer is flaged.
+//   unflag a subface. 
+// The last 3rd bit of ((int *) ((s).sh))[shmarkindex+1] is flaged.
 
 inline void tetgenmesh::smarktest2(face& s) 
 {
@@ -3125,6 +3213,15 @@ 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.