tetgen.cpp

Go to the documentation of this file.
00001 
00008 // This include is here so that the chaste_libs=0 build correctly links predicates.o.
00009 #include "predicates.hpp"
00010  
00012 //                                                                           //
00013 // TetGen                                                                    //
00014 //                                                                           //
00015 // A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
00016 //                                                                           //
00017 // Version 1.4                                                               //
00018 // April 16, 2007                                                            //
00019 //                                                                           //
00020 // Copyright (C) 2002--2007                                                  //
00021 // Hang Si                                                                   //
00022 // Research Group Numerical Mathematics and Scientific Computing             //
00023 // Weierstrass Institute for Applied Analysis and Stochastics                //
00024 // Mohrenstr. 39, 10117 Berlin, Germany                                      //
00025 // si@wias-berlin.de                                                         //
00026 //                                                                           //
00027 // TetGen is freely available through the website: http://tetgen.berlios.de. //
00028 //   It may be copied, modified, and redistributed for non-commercial use.   //
00029 //   Please consult the file LICENSE for the detailed copyright notices.     //
00030 //                                                                           //
00032 
00034 //                                                                           //
00035 // tetgen.cxx                                                                //
00036 //                                                                           //
00037 // The TetGen library and program.                                           //
00038 //                                                                           //
00040 
00041 #include "tetgen.h"
00042 namespace tetgen
00043 { //Added namespace to avoid clash with triangle
00044 
00046 //                                                                           //
00047 // terminatetetgen()    Terminate TetGen with a given exit code.             //
00048 //                                                                           //
00050 
00051 void terminatetetgen(int x)
00052 {
00053 #ifdef TETLIBRARY
00054   throw x;
00055 #else
00056   exit(x);
00057 #endif // #ifdef TETLIBRARY
00058 }
00059 
00060 //
00061 // Begin of class 'tetgenio' implementation
00062 //
00063 
00065 //                                                                           //
00066 // initialize()    Initialize all variables of 'tetgenio'.                   //
00067 //                                                                           //
00068 // It is called by the only class constructor 'tetgenio()' implicitly. Thus, //
00069 // all variables are guaranteed to be initialized. Each array is initialized //
00070 // to be a 'NULL' pointer, and its length is equal zero. Some variables have //
00071 // their default value, 'firstnumber' equals zero, 'mesh_dim' equals 3,  and //
00072 // 'numberofcorners' equals 4.  Another possible use of this routine is to   //
00073 // call it before to re-use an object.                                       //
00074 //                                                                           //
00076 
00077 void tetgenio::initialize()
00078 {
00079   firstnumber = 0;              // Default item index is numbered from Zero.
00080   mesh_dim = 3;                              // Default mesh dimension is 3.
00081   useindex = true;
00082 
00083   pointlist = (REAL *) NULL;
00084   pointattributelist = (REAL *) NULL;
00085   pointmtrlist = (REAL *) NULL;
00086   pointmarkerlist = (int *) NULL;
00087   numberofpoints = 0;
00088   numberofpointattributes = 0;
00089   numberofpointmtrs = 0;
00090 
00091   tetrahedronlist = (int *) NULL;
00092   tetrahedronattributelist = (REAL *) NULL;
00093   tetrahedronvolumelist = (REAL *) NULL;
00094   neighborlist = (int *) NULL;
00095   numberoftetrahedra = 0;
00096   numberofcorners = 4;                   // Default is 4 nodes per element.
00097   numberoftetrahedronattributes = 0;
00098 
00099   trifacelist = (int *) NULL;
00100   adjtetlist = (int *) NULL;
00101   trifacemarkerlist = (int *) NULL;
00102   numberoftrifaces = 0; 
00103 
00104   facetlist = (facet *) NULL;
00105   facetmarkerlist = (int *) NULL;
00106   numberoffacets = 0; 
00107 
00108   edgelist = (int *) NULL;
00109   edgemarkerlist = (int *) NULL;
00110   numberofedges = 0;
00111 
00112   holelist = (REAL *) NULL;
00113   numberofholes = 0;
00114 
00115   regionlist = (REAL *) NULL;
00116   numberofregions = 0;
00117 
00118   facetconstraintlist = (REAL *) NULL;
00119   numberoffacetconstraints = 0;
00120   segmentconstraintlist = (REAL *) NULL;
00121   numberofsegmentconstraints = 0;
00122 
00123   pbcgrouplist = (pbcgroup *) NULL;
00124   numberofpbcgroups = 0;
00125 
00126   vpointlist = (REAL *) NULL;
00127   vedgelist = (voroedge *) NULL;
00128   vfacetlist = (vorofacet *) NULL; 
00129   vcelllist = (int **) NULL; 
00130   numberofvpoints = 0;
00131   numberofvedges = 0;
00132   numberofvfacets = 0;
00133   numberofvcells = 0;
00134 }
00135 
00137 //                                                                           //
00138 // deinitialize()    Free the memory allocated in 'tetgenio'.                //
00139 //                                                                           //
00140 // It is called by the class destructor '~tetgenio()' implicitly. Hence, the //
00141 // occupied memory by arrays of an object will be automatically released on  //
00142 // the deletion of the object. However, this routine assumes that the memory //
00143 // is allocated by C++ memory allocation operator 'new', thus it is freed by //
00144 // the C++ array deletor 'delete []'. If one uses the C/C++ library function //
00145 // 'malloc()' to allocate memory for arrays, one has to free them with the   //
00146 // 'free()' function, and call routine 'initialize()' once to disable this   //
00147 // routine on deletion of the object.                                        //
00148 //                                                                           //
00150 
00151 void tetgenio::deinitialize()
00152 {
00153   facet *f;
00154   polygon *p;
00155   pbcgroup *pg;
00156   int i, j;
00157 
00158   if (pointlist != (REAL *) NULL) {
00159     delete [] pointlist;
00160   }
00161   if (pointattributelist != (REAL *) NULL) {
00162     delete [] pointattributelist;
00163   }
00164   if (pointmtrlist != (REAL *) NULL) {
00165     delete [] pointmtrlist;
00166   }
00167   if (pointmarkerlist != (int *) NULL) {
00168     delete [] pointmarkerlist;
00169   }
00170 
00171   if (tetrahedronlist != (int *) NULL) {
00172     delete [] tetrahedronlist;
00173   }
00174   if (tetrahedronattributelist != (REAL *) NULL) {
00175     delete [] tetrahedronattributelist;
00176   }
00177   if (tetrahedronvolumelist != (REAL *) NULL) {
00178     delete [] tetrahedronvolumelist;
00179   }
00180   if (neighborlist != (int *) NULL) {
00181     delete [] neighborlist;
00182   }
00183 
00184   if (trifacelist != (int *) NULL) {
00185     delete [] trifacelist;
00186   }
00187   if (adjtetlist != (int *) NULL) {
00188     delete [] adjtetlist;
00189   }
00190   if (trifacemarkerlist != (int *) NULL) {
00191     delete [] trifacemarkerlist;
00192   }
00193 
00194   if (edgelist != (int *) NULL) {
00195     delete [] edgelist;
00196   }
00197   if (edgemarkerlist != (int *) NULL) {
00198     delete [] edgemarkerlist;
00199   }
00200 
00201   if (facetlist != (facet *) NULL) {
00202     for (i = 0; i < numberoffacets; i++) {
00203       f = &facetlist[i];
00204       for (j = 0; j < f->numberofpolygons; j++) {
00205         p = &f->polygonlist[j];
00206         delete [] p->vertexlist;
00207       }
00208       delete [] f->polygonlist;
00209       if (f->holelist != (REAL *) NULL) {
00210         delete [] f->holelist;
00211       }
00212     }
00213     delete [] facetlist;
00214   }
00215   if (facetmarkerlist != (int *) NULL) {
00216     delete [] facetmarkerlist;
00217   }
00218 
00219   if (holelist != (REAL *) NULL) {
00220     delete [] holelist;
00221   }
00222   if (regionlist != (REAL *) NULL) {
00223     delete [] regionlist;
00224   }
00225   if (facetconstraintlist != (REAL *) NULL) {
00226     delete [] facetconstraintlist;
00227   }
00228   if (segmentconstraintlist != (REAL *) NULL) {
00229     delete [] segmentconstraintlist;
00230   }
00231   if (pbcgrouplist != (pbcgroup *) NULL) {
00232     for (i = 0; i < numberofpbcgroups; i++) {
00233       pg = &(pbcgrouplist[i]);
00234       if (pg->pointpairlist != (int *) NULL) {
00235         delete [] pg->pointpairlist;
00236       }
00237     }
00238     delete [] pbcgrouplist;
00239   }
00240   if (vpointlist != (REAL *) NULL) {
00241     delete [] vpointlist;
00242   }
00243   if (vedgelist != (voroedge *) NULL) {
00244     delete [] vedgelist;
00245   }
00246   if (vfacetlist != (vorofacet *) NULL) {
00247     for (i = 0; i < numberofvfacets; i++) {
00248       delete [] vfacetlist[i].elist;
00249     }
00250     delete [] vfacetlist;
00251   }
00252   if (vcelllist != (int **) NULL) {
00253     for (i = 0; i < numberofvcells; i++) {
00254       delete [] vcelllist[i];
00255     }
00256     delete [] vcelllist;
00257   }
00258 }
00259 
00261 //                                                                           //
00262 // load_node_call()    Load a list of nodes.                                 //
00263 //                                                                           //
00264 // It is a support routine for routines: 'load_nodes()', 'load_poly()', and  //
00265 // 'load_tetmesh()'.  'infile' is the file handle contains the node list. It //
00266 // may point to a .node, or .poly or .smesh file.  'markers' indicates each  //
00267 // node contains an additional marker (integer) or not. 'infilename' is the  //
00268 // name of the file being read,  it is only appeared in error message.       //
00269 //                                                                           //
00270 // The 'firstnumber' (0 or 1) is automatically determined by the number of   //
00271 // the first index of the first point.                                       //
00272 //                                                                           //
00274 
00275 bool tetgenio::load_node_call(FILE* infile, int markers, char* infilename)
00276 {
00277   char inputline[INPUTLINESIZE];
00278   char *stringptr;
00279   REAL x, y, z, attrib;
00280   int firstnode, currentmarker;
00281   int index, attribindex;
00282   int i, j;
00283 
00284   // Initialize 'pointlist', 'pointattributelist', and 'pointmarkerlist'.
00285   pointlist = new REAL[numberofpoints * 3];
00286   if (pointlist == (REAL *) NULL) {
00287     printf("Error:  Out of memory.\n");
00288     terminatetetgen(1);
00289   }
00290   if (numberofpointattributes > 0) {
00291     pointattributelist = new REAL[numberofpoints * numberofpointattributes];
00292     if (pointattributelist == (REAL *) NULL) {
00293       printf("Error:  Out of memory.\n");
00294       terminatetetgen(1);
00295     }
00296   }
00297   if (markers) {
00298     pointmarkerlist = new int[numberofpoints];
00299     if (pointmarkerlist == (int *) NULL) {
00300       printf("Error:  Out of memory.\n");
00301       terminatetetgen(1);
00302     }
00303   }
00304 
00305   // Read the point section.
00306   index = 0;
00307   attribindex = 0;
00308   for (i = 0; i < numberofpoints; i++) {
00309     stringptr = readnumberline(inputline, infile, infilename);
00310     if (useindex) {
00311       if (i == 0) {
00312         firstnode = (int) strtol (stringptr, &stringptr, 0);
00313         if ((firstnode == 0) || (firstnode == 1)) {
00314           firstnumber = firstnode;
00315         }
00316       }
00317       stringptr = findnextnumber(stringptr);
00318     } // if (useindex)
00319     if (*stringptr == '\0') {
00320       printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
00321       break;
00322     }
00323     x = (REAL) strtod(stringptr, &stringptr);
00324     stringptr = findnextnumber(stringptr);
00325     if (*stringptr == '\0') {
00326       printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
00327       break;
00328     }
00329     y = (REAL) strtod(stringptr, &stringptr);
00330     if (mesh_dim == 3) {
00331       stringptr = findnextnumber(stringptr);
00332       if (*stringptr == '\0') {
00333         printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
00334         break;
00335       }
00336       z = (REAL) strtod(stringptr, &stringptr);
00337     } else {
00338       z = 0.0; // mesh_dim == 2;
00339     }
00340     pointlist[index++] = x;
00341     pointlist[index++] = y;
00342     pointlist[index++] = z;
00343     // Read the point attributes.
00344     for (j = 0; j < numberofpointattributes; j++) {
00345       stringptr = findnextnumber(stringptr);
00346       if (*stringptr == '\0') {
00347         attrib = 0.0;
00348       } else {
00349         attrib = (REAL) strtod(stringptr, &stringptr);
00350       }
00351       pointattributelist[attribindex++] = attrib;
00352     }
00353     if (markers) {
00354       // Read a point marker.
00355       stringptr = findnextnumber(stringptr);
00356       if (*stringptr == '\0') {
00357         currentmarker = 0;
00358       } else {
00359         currentmarker = (int) strtol (stringptr, &stringptr, 0);
00360       }
00361       pointmarkerlist[i] = currentmarker;
00362     }
00363   }
00364   if (i < numberofpoints) {
00365     // Failed to read points due to some error.
00366     delete [] pointlist;
00367     pointlist = (REAL *) NULL;
00368     if (markers) {
00369       delete [] pointmarkerlist;
00370       pointmarkerlist = (int *) NULL;
00371     }
00372     if (numberofpointattributes > 0) {
00373       delete [] pointattributelist;
00374       pointattributelist = (REAL *) NULL;
00375     }
00376     numberofpoints = 0;
00377     return false;
00378   }
00379   return true;
00380 }
00381 
00383 //                                                                           //
00384 // load_node()    Load a list of nodes from a .node file.                    //
00385 //                                                                           //
00386 // 'filename' is the inputfile without suffix. The node list is in 'filename.//
00387 // node'. On completion, the node list is returned in 'pointlist'.           //
00388 //                                                                           //
00390 
00391 bool tetgenio::load_node(char* filename)
00392 {
00393   FILE *infile;
00394   char innodefilename[FILENAMESIZE];
00395   char inputline[INPUTLINESIZE];
00396   char *stringptr;
00397   int markers;
00398   
00399   markers = 0;
00400   // Assembling the actual file names we want to open.
00401   strcpy(innodefilename, filename);
00402   strcat(innodefilename, ".node");
00403 
00404   // Try to open a .node file.
00405   infile = fopen(innodefilename, "r");
00406   if (infile == (FILE *) NULL) {
00407     printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
00408     return false;
00409   }
00410   printf("Opening %s.\n", innodefilename);  
00411   // Read the first line of the file.
00412   stringptr = readnumberline(inputline, infile, innodefilename);
00413   // Is this list of points generated from rbox?
00414   stringptr = strstr(inputline, "rbox");
00415   if (stringptr == NULL) {
00416     // Read number of points, number of dimensions, number of point
00417     //   attributes, and number of boundary markers. 
00418     stringptr = inputline;
00419     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00420     stringptr = findnextnumber(stringptr);
00421     if (*stringptr == '\0') {
00422       mesh_dim = 3;
00423     } else {
00424       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00425     }
00426     stringptr = findnextnumber(stringptr);
00427     if (*stringptr == '\0') {
00428       numberofpointattributes = 0;
00429     } else {
00430       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00431     }
00432     stringptr = findnextnumber(stringptr);
00433     if (*stringptr == '\0') {
00434       markers = 0;
00435     } else {
00436       markers = (int) strtol (stringptr, &stringptr, 0);
00437     }
00438   } else {
00439     // It is a rbox (qhull) input file.
00440     stringptr = inputline;
00441     // Get the dimension.
00442     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00443     // Get the number of points.
00444     stringptr = readnumberline(inputline, infile, innodefilename);
00445     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00446     // There is no index column.
00447     useindex = 0;
00448   }
00449 
00450   // if ((mesh_dim != 3) && (mesh_dim != 2)) {
00451   //   printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
00452   //   fclose(infile);
00453   //   return false;
00454   // }
00455   if (numberofpoints < (mesh_dim + 1)) {
00456     printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
00457     fclose(infile);
00458     return false;
00459   }
00460 
00461   // Load the list of nodes.
00462   if (!load_node_call(infile, markers, innodefilename)) {
00463     fclose(infile);
00464     return false;
00465   }
00466   fclose(infile);
00467   return true;
00468 }
00469 
00471 //                                                                           //
00472 // load_pbc()    Load a list of pbc groups into 'pbcgrouplist'.              //
00473 //                                                                           //
00474 // 'filename' is the filename of the original inputfile without suffix. The  //
00475 // pbc groups are found in file 'filename.pbc'.                              //
00476 //                                                                           //
00477 // This routine will be called both in load_poly() and load_tetmesh().       //
00478 //                                                                           //
00480 
00481 bool tetgenio::load_pbc(char* filename)
00482 {
00483   FILE *infile;
00484   char pbcfilename[FILENAMESIZE];
00485   char inputline[INPUTLINESIZE];
00486   char *stringptr;
00487   pbcgroup *pg;
00488   int index, p1, p2;
00489   int i, j, k;
00490 
00491   // Pbc groups are saved in file "filename.pbc".
00492   strcpy(pbcfilename, filename);
00493   strcat(pbcfilename, ".pbc");
00494   infile = fopen(pbcfilename, "r");
00495   if (infile != (FILE *) NULL) {
00496     printf("Opening %s.\n", pbcfilename);
00497   } else {
00498     // No such file. Return.
00499     return false;
00500   }
00501 
00502   // Read the number of pbc groups.
00503   stringptr = readnumberline(inputline, infile, pbcfilename);
00504   numberofpbcgroups = (int) strtol (stringptr, &stringptr, 0);
00505   if (numberofpbcgroups == 0) {
00506     // It looks this file contains no point.
00507     fclose(infile);
00508     return false; 
00509   }
00510   // Initialize 'pbcgrouplist';
00511   pbcgrouplist = new pbcgroup[numberofpbcgroups];
00512 
00513   // Read the list of pbc groups.
00514   for (i = 0; i < numberofpbcgroups; i++) {
00515     pg = &(pbcgrouplist[i]);
00516     // Initialize pbcgroup i;
00517     pg->numberofpointpairs = 0;
00518     pg->pointpairlist = (int *) NULL;
00519     // Read 'fmark1', 'fmark2'.
00520     stringptr = readnumberline(inputline, infile, pbcfilename);
00521     if (*stringptr == '\0') break;
00522     pg->fmark1 = (int) strtol(stringptr, &stringptr, 0);
00523     stringptr = findnextnumber(stringptr);
00524     if (*stringptr == '\0') break;
00525     pg->fmark2 = (int) strtol(stringptr, &stringptr, 0);
00526     // Read 'transmat'.
00527     do {
00528       stringptr = readline(inputline, infile, NULL);
00529     } while ((*stringptr != '[') && (*stringptr != '\0'));
00530     if (*stringptr == '\0') break;
00531     for (j = 0; j < 4; j++) {
00532       for (k = 0; k < 4; k++) {
00533         // Read the entry of [j, k].
00534         stringptr = findnextnumber(stringptr);
00535         if (*stringptr == '\0') {
00536           // Try to read another line.
00537           stringptr = readnumberline(inputline, infile, pbcfilename);
00538           if (*stringptr == '\0') break;
00539         }
00540         pg->transmat[j][k] = (REAL) strtod(stringptr, &stringptr);
00541       }
00542       if (k < 4) break; // Not complete!
00543     }
00544     if (j < 4) break; // Not complete!
00545     // Read 'numberofpointpairs'.
00546     stringptr = readnumberline(inputline, infile, pbcfilename);
00547     if (*stringptr == '\0') break;
00548     pg->numberofpointpairs = (int) strtol(stringptr, &stringptr, 0);
00549     if (pg->numberofpointpairs > 0) {
00550       pg->pointpairlist = new int[pg->numberofpointpairs * 2];
00551       // Read the point pairs.
00552       index = 0;
00553       for (j = 0; j < pg->numberofpointpairs; j++) {
00554         stringptr = readnumberline(inputline, infile, pbcfilename);
00555         p1 = (int) strtol(stringptr, &stringptr, 0);
00556         stringptr = findnextnumber(stringptr);
00557         p2 = (int) strtol(stringptr, &stringptr, 0);
00558         pg->pointpairlist[index++] = p1;
00559         pg->pointpairlist[index++] = p2;
00560       }
00561     }
00562   }
00563   fclose(infile);
00564 
00565   if (i < numberofpbcgroups) {
00566     // Failed to read to additional points due to some error.
00567     delete [] pbcgrouplist;
00568     pbcgrouplist = (pbcgroup *) NULL;
00569     numberofpbcgroups = 0;
00570     return false;
00571   }
00572   return true;
00573 }
00574 
00576 //                                                                           //
00577 // load_var()    Load variant constraints applied on facets, segments, nodes.//
00578 //                                                                           //
00579 // 'filename' is the filename of the original inputfile without suffix. The  //
00580 // constraints are found in file 'filename.var'.                             //
00581 //                                                                           //
00583 
00584 bool tetgenio::load_var(char* filename)
00585 {
00586   FILE *infile;
00587   char varfilename[FILENAMESIZE];
00588   char inputline[INPUTLINESIZE];
00589   char *stringptr;
00590   int index;
00591   int i;
00592 
00593   // Variant constraints are saved in file "filename.var".
00594   strcpy(varfilename, filename);
00595   strcat(varfilename, ".var");
00596   infile = fopen(varfilename, "r");
00597   if (infile != (FILE *) NULL) {
00598     printf("Opening %s.\n", varfilename);
00599   } else {
00600     // No such file. Return.
00601     return false;
00602   }
00603 
00604   // Read the facet constraint section.
00605   stringptr = readnumberline(inputline, infile, varfilename);
00606   if (*stringptr != '\0') {
00607     numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0);
00608   } else {
00609     numberoffacetconstraints = 0;
00610   }
00611   if (numberoffacetconstraints > 0) {
00612     // Initialize 'facetconstraintlist'.
00613     facetconstraintlist = new REAL[numberoffacetconstraints * 2];
00614     index = 0;
00615     for (i = 0; i < numberoffacetconstraints; i++) {
00616       stringptr = readnumberline(inputline, infile, varfilename);
00617       stringptr = findnextnumber(stringptr);
00618       if (*stringptr == '\0') {
00619         printf("Error:  facet constraint %d has no facet marker.\n",
00620                firstnumber + i);
00621         break;
00622       } else {
00623         facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00624       }
00625       stringptr = findnextnumber(stringptr);
00626       if (*stringptr == '\0') {
00627         printf("Error:  facet constraint %d has no maximum area bound.\n",
00628                firstnumber + i);
00629         break;
00630       } else {
00631         facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00632       }
00633     }
00634     if (i < numberoffacetconstraints) {
00635       // This must be caused by an error.
00636       fclose(infile);
00637       return false;
00638     }
00639   }
00640 
00641   // Read the segment constraint section.
00642   stringptr = readnumberline(inputline, infile, varfilename);
00643   if (*stringptr != '\0') {
00644     numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0);
00645   } else {
00646     numberofsegmentconstraints = 0;
00647   }
00648   if (numberofsegmentconstraints > 0) {
00649     // Initialize 'segmentconstraintlist'.
00650     segmentconstraintlist = new REAL[numberofsegmentconstraints * 3];
00651     index = 0;
00652     for (i = 0; i < numberofsegmentconstraints; i++) {
00653       stringptr = readnumberline(inputline, infile, varfilename);
00654       stringptr = findnextnumber(stringptr);
00655       if (*stringptr == '\0') {
00656         printf("Error:  segment constraint %d has no frist endpoint.\n",
00657                firstnumber + i);
00658         break;
00659       } else {
00660         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00661       }
00662       stringptr = findnextnumber(stringptr);
00663       if (*stringptr == '\0') {
00664         printf("Error:  segment constraint %d has no second endpoint.\n",
00665                firstnumber + i);
00666         break;
00667       } else {
00668         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00669       }
00670       stringptr = findnextnumber(stringptr);
00671       if (*stringptr == '\0') {
00672         printf("Error:  segment constraint %d has no maximum length bound.\n",
00673                firstnumber + i);
00674         break;
00675       } else {
00676         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00677       }
00678     }
00679     if (i < numberofsegmentconstraints) {
00680       // This must be caused by an error.
00681       fclose(infile);
00682       return false;
00683     }
00684   }
00685 
00686   fclose(infile);
00687   return true;
00688 }
00689 
00691 //                                                                           //
00692 // load_mtr()    Load a size specification map from file.                    //
00693 //                                                                           //
00694 // 'filename' is the filename of the original inputfile without suffix. The  //
00695 // size map is found in file 'filename.mtr'.                                 //
00696 //                                                                           //
00698 
00699 bool tetgenio::load_mtr(char* filename)
00700 {
00701   FILE *infile;
00702   char mtrfilename[FILENAMESIZE];
00703   char inputline[INPUTLINESIZE];
00704   char *stringptr;
00705   REAL mtr;
00706   int mtrindex;
00707   int i, j;
00708 
00709   strcpy(mtrfilename, filename);
00710   strcat(mtrfilename, ".mtr");
00711   infile = fopen(mtrfilename, "r");
00712   if (infile != (FILE *) NULL) {
00713     printf("Opening %s.\n", mtrfilename);
00714   } else {
00715     // No such file. Return.
00716     return false;
00717   }
00718 
00719   // Read number of points, number of columns (1, 3, or 6).
00720   stringptr = readnumberline(inputline, infile, mtrfilename);
00721   stringptr = findnextnumber(stringptr); // Skip number of points.
00722   if (*stringptr != '\0') {
00723     numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0);
00724   }
00725   if (numberofpointmtrs == 0) {
00726     // Column number doesn't match. Set a default number (1).
00727     numberofpointmtrs = 1;
00728   }
00729 
00730   // Allocate space for pointmtrlist.
00731   pointmtrlist = new REAL[numberofpoints * numberofpointmtrs];
00732   if (pointmtrlist == (REAL *) NULL) {
00733     printf("Error:  Out of memory.\n");
00734     terminatetetgen(1);
00735   }
00736   mtrindex = 0;
00737   for (i = 0; i < numberofpoints; i++) {
00738     // Read metrics.
00739     stringptr = readnumberline(inputline, infile, mtrfilename);
00740     for (j = 0; j < numberofpointmtrs; j++) {
00741       if (*stringptr == '\0') {
00742         printf("Error:  Metric %d is missing value #%d in %s.\n",
00743                i + firstnumber, j + 1, mtrfilename);
00744         terminatetetgen(1);
00745       }
00746       mtr = (REAL) strtod(stringptr, &stringptr);
00747       pointmtrlist[mtrindex++] = mtr;
00748       stringptr = findnextnumber(stringptr);
00749     }
00750   }
00751 
00752   fclose(infile);
00753   return true;
00754 }
00755 
00757 //                                                                           //
00758 // load_poly()    Load a piecewise linear complex from a .poly or .smesh.    //
00759 //                                                                           //
00760 // 'filename' is the inputfile without suffix. The PLC is in 'filename.poly' //
00761 // or 'filename.smesh', and possibly plus 'filename.node' (when the first    //
00762 // line of the file starts with a zero).                                     //
00763 //                                                                           //
00765 
00766 bool tetgenio::load_poly(char* filename)
00767 {
00768   FILE *infile, *polyfile;
00769   char innodefilename[FILENAMESIZE];
00770   char inpolyfilename[FILENAMESIZE];
00771   char insmeshfilename[FILENAMESIZE];
00772   char inputline[INPUTLINESIZE];
00773   char *stringptr, *infilename;
00774   int smesh, markers, currentmarker;
00775   int readnodefile, index;
00776   int i, j, k;
00777 
00778   // Assembling the actual file names we want to open.
00779   strcpy(innodefilename, filename);
00780   strcpy(inpolyfilename, filename);
00781   strcpy(insmeshfilename, filename);
00782   strcat(innodefilename, ".node");
00783   strcat(inpolyfilename, ".poly");
00784   strcat(insmeshfilename, ".smesh");
00785 
00786   // First assume it is a .poly file.
00787   smesh = 0;
00788   // Try to open a .poly file.
00789   polyfile = fopen(inpolyfilename, "r");
00790   if (polyfile == (FILE *) NULL) {
00791     // .poly doesn't exist! Try to open a .smesh file.
00792     polyfile = fopen(insmeshfilename, "r");
00793     if (polyfile == (FILE *) NULL) {
00794       printf("File I/O Error:  Cannot access file %s and %s.\n",
00795              inpolyfilename, insmeshfilename);
00796       return false;
00797     } else {
00798       printf("Opening %s.\n", insmeshfilename);
00799     }
00800     smesh = 1;
00801   } else {
00802     printf("Opening %s.\n", inpolyfilename);
00803   }
00804   // Initialize the default values.
00805   mesh_dim = 3;  // Three-dimemsional accoordinates.
00806   numberofpointattributes = 0;  // no point attribute.
00807   markers = 0;  // no boundary marker.
00808   // Read number of points, number of dimensions, number of point
00809   //   attributes, and number of boundary markers.
00810   stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00811   numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00812   stringptr = findnextnumber(stringptr);
00813   if (*stringptr != '\0') {
00814     mesh_dim = (int) strtol (stringptr, &stringptr, 0);      
00815   }
00816   stringptr = findnextnumber(stringptr);
00817   if (*stringptr != '\0') {
00818     numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00819   }
00820   stringptr = findnextnumber(stringptr);
00821   if (*stringptr != '\0') {
00822     markers = (int) strtol (stringptr, &stringptr, 0);
00823   }
00824   if (numberofpoints > 0) {
00825     readnodefile = 0;
00826     if (smesh) {
00827       infilename = insmeshfilename;
00828     } else {
00829       infilename = inpolyfilename;
00830     } 
00831     infile = polyfile;
00832   } else {
00833     // If the .poly or .smesh file claims there are zero points, that
00834     //   means the points should be read from a separate .node file.
00835     readnodefile = 1;
00836     infilename = innodefilename;
00837   }
00838 
00839   if (readnodefile) {
00840     // Read the points from the .node file.
00841     printf("Opening %s.\n", innodefilename);
00842     infile = fopen(innodefilename, "r");
00843     if (infile == (FILE *) NULL) {
00844       printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
00845       return false;
00846     }
00847     // Initialize the default values.
00848     mesh_dim = 3;  // Three-dimemsional accoordinates.
00849     numberofpointattributes = 0;  // no point attribute.
00850     markers = 0;  // no boundary marker.
00851     // Read number of points, number of dimensions, number of point
00852     //   attributes, and number of boundary markers.
00853     stringptr = readnumberline(inputline, infile, innodefilename);
00854     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00855     stringptr = findnextnumber(stringptr);
00856     if (*stringptr != '\0') {
00857       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00858     }
00859     stringptr = findnextnumber(stringptr);
00860     if (*stringptr != '\0') {
00861       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00862     }
00863     stringptr = findnextnumber(stringptr);
00864     if (*stringptr != '\0') {
00865       markers = (int) strtol (stringptr, &stringptr, 0);
00866     }
00867   }
00868 
00869   if ((mesh_dim != 3) && (mesh_dim != 2)) {
00870     printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
00871     fclose(infile);
00872     return false;
00873   }
00874   if (numberofpoints < (mesh_dim + 1)) {
00875     printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
00876     fclose(infile);
00877     return false;
00878   }
00879 
00880   // Load the list of nodes.
00881   if (!load_node_call(infile, markers, infilename)) {
00882     fclose(infile);
00883     return false;
00884   }
00885 
00886   if (readnodefile) {
00887     fclose(infile);
00888   }
00889 
00890   facet *f;
00891   polygon *p;
00892 
00893   if (mesh_dim == 3) {
00894 
00895     // Read number of facets and number of boundary markers.
00896     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00897     numberoffacets = (int) strtol (stringptr, &stringptr, 0);
00898     if (numberoffacets <= 0) {
00899       // No facet list, return.
00900       fclose(polyfile);
00901       return true;
00902     }
00903     stringptr = findnextnumber(stringptr);
00904     if (*stringptr == '\0') {
00905       markers = 0;  // no boundary marker.
00906     } else {
00907       markers = (int) strtol (stringptr, &stringptr, 0);
00908     }
00909 
00910     // Initialize the 'facetlist', 'facetmarkerlist'.
00911     facetlist = new facet[numberoffacets];
00912     if (markers == 1) {
00913       facetmarkerlist = new int[numberoffacets];
00914     }
00915 
00916     // Read data into 'facetlist', 'facetmarkerlist'.
00917     if (smesh == 0) {
00918       // Facets are in .poly file format.
00919       for (i = 1; i <= numberoffacets; i++) {
00920         f = &(facetlist[i - 1]);
00921         init(f);
00922         f->numberofholes = 0;
00923         currentmarker = 0;
00924         // Read number of polygons, number of holes, and a boundary marker.
00925         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00926         f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
00927         stringptr = findnextnumber(stringptr);
00928         if (*stringptr != '\0') {
00929           f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
00930           if (markers == 1) {
00931             stringptr = findnextnumber(stringptr);
00932             if (*stringptr != '\0') {
00933               currentmarker = (int) strtol(stringptr, &stringptr, 0);
00934             }
00935           }
00936         }
00937         // Initialize facetmarker if it needs.
00938         if (markers == 1) {
00939           facetmarkerlist[i - 1] = currentmarker; 
00940         }
00941         // Each facet should has at least one polygon.
00942         if (f->numberofpolygons <= 0) {
00943           printf("Error:  Wrong number of polygon in %d facet.\n", i);
00944           break; 
00945         }
00946         // Initialize the 'f->polygonlist'.
00947         f->polygonlist = new polygon[f->numberofpolygons];
00948         // Go through all polygons, read in their vertices.
00949         for (j = 1; j <= f->numberofpolygons; j++) {
00950           p = &(f->polygonlist[j - 1]);
00951           init(p);
00952           // Read number of vertices of this polygon.
00953           stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00954           p->numberofvertices = (int) strtol(stringptr, &stringptr, 0);
00955           if (p->numberofvertices < 1) {
00956             printf("Error:  Wrong polygon %d in facet %d\n", j, i);
00957             break;
00958           }
00959           // Initialize 'p->vertexlist'.
00960           p->vertexlist = new int[p->numberofvertices];
00961           // Read all vertices of this polygon.
00962           for (k = 1; k <= p->numberofvertices; k++) {
00963             stringptr = findnextnumber(stringptr);
00964             if (*stringptr == '\0') {
00965               // Try to load another non-empty line and continue to read the
00966               //   rest of vertices.
00967               stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00968               if (*stringptr == '\0') {
00969                 printf("Error: Missing %d endpoints of polygon %d in facet %d",
00970                        p->numberofvertices - k, j, i);
00971                 break;
00972               }
00973             }
00974             p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
00975           }
00976         } 
00977         if (j <= f->numberofpolygons) {
00978           // This must be caused by an error. However, there're j - 1
00979           //   polygons have been read. Reset the 'f->numberofpolygon'.
00980           if (j == 1) {
00981             // This is the first polygon.
00982             delete [] f->polygonlist;
00983           }
00984           f->numberofpolygons = j - 1;
00985           // No hole will be read even it exists.
00986           f->numberofholes = 0;
00987           break;
00988         }
00989         // If this facet has hole pints defined, read them.
00990         if (f->numberofholes > 0) {
00991           // Initialize 'f->holelist'.
00992           f->holelist = new REAL[f->numberofholes * 3];
00993           // Read the holes' coordinates.
00994           index = 0;
00995           for (j = 1; j <= f->numberofholes; j++) {
00996             stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00997             for (k = 1; k <= 3; k++) {
00998               stringptr = findnextnumber(stringptr);
00999               if (*stringptr == '\0') {
01000                 printf("Error:  Hole %d in facet %d has no coordinates", j, i);
01001                 break;
01002               }
01003               f->holelist[index++] = (REAL) strtod (stringptr, &stringptr);
01004             }
01005             if (k <= 3) {
01006               // This must be caused by an error.
01007               break;
01008             }
01009           }
01010           if (j <= f->numberofholes) {
01011             // This must be caused by an error.
01012             break;
01013           }
01014         }
01015       }
01016       if (i <= numberoffacets) {
01017         // This must be caused by an error.
01018         numberoffacets = i - 1;
01019         fclose(polyfile);
01020         return false;
01021       }
01022     } else { // poly == 0
01023       // Read the facets from a .smesh file.
01024       for (i = 1; i <= numberoffacets; i++) {
01025         f = &(facetlist[i - 1]);
01026         init(f);
01027         // Initialize 'f->facetlist'. In a .smesh file, each facetlist only
01028         //   contains exactly one polygon, no hole.
01029         f->numberofpolygons = 1;
01030         f->polygonlist = new polygon[f->numberofpolygons];
01031         p = &(f->polygonlist[0]);
01032         init(p);
01033         // Read number of vertices of this polygon.
01034         stringptr = readnumberline(inputline, polyfile, insmeshfilename);
01035         p->numberofvertices = (int) strtol (stringptr, &stringptr, 0);
01036         if (p->numberofvertices < 1) {
01037           printf("Error:  Wrong number of vertex in facet %d\n", i);
01038           break;
01039         }
01040         // Initialize 'p->vertexlist'.
01041         p->vertexlist = new int[p->numberofvertices];
01042         for (k = 1; k <= p->numberofvertices; k++) {
01043           stringptr = findnextnumber(stringptr);
01044           if (*stringptr == '\0') {
01045             // Try to load another non-empty line and continue to read the
01046             //   rest of vertices.
01047             stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01048             if (*stringptr == '\0') {
01049               printf("Error:  Missing %d endpoints in facet %d",
01050                      p->numberofvertices - k, i);
01051               break;
01052             }
01053           }
01054           p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
01055         }
01056         if (k <= p->numberofvertices) {
01057           // This must be caused by an error.
01058           break;
01059         }
01060         // Read facet's boundary marker at last.
01061         if (markers == 1) {
01062           stringptr = findnextnumber(stringptr);
01063           if (*stringptr == '\0') {
01064             currentmarker = 0;
01065           } else {
01066             currentmarker = (int) strtol(stringptr, &stringptr, 0);
01067           }
01068           facetmarkerlist[i - 1] = currentmarker;
01069         }
01070       }
01071       if (i <= numberoffacets) {
01072         // This must be caused by an error.
01073         numberoffacets = i - 1;
01074         fclose(polyfile);
01075         return false;
01076       }
01077     }
01078 
01079     // Read the hole section.
01080     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01081     if (*stringptr != '\0') {
01082       numberofholes = (int) strtol (stringptr, &stringptr, 0);
01083     } else {
01084       numberofholes = 0;
01085     }
01086     if (numberofholes > 0) {
01087       // Initialize 'holelist'.
01088       holelist = new REAL[numberofholes * 3];
01089       for (i = 0; i < 3 * numberofholes; i += 3) {
01090         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01091         stringptr = findnextnumber(stringptr);
01092         if (*stringptr == '\0') {
01093           printf("Error:  Hole %d has no x coord.\n", firstnumber + (i / 3));
01094           break;
01095         } else {
01096           holelist[i] = (REAL) strtod(stringptr, &stringptr);
01097         }
01098         stringptr = findnextnumber(stringptr);
01099         if (*stringptr == '\0') {
01100           printf("Error:  Hole %d has no y coord.\n", firstnumber + (i / 3));
01101           break;
01102         } else {
01103           holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
01104         }
01105         stringptr = findnextnumber(stringptr);
01106         if (*stringptr == '\0') {
01107           printf("Error:  Hole %d has no z coord.\n", firstnumber + (i / 3));
01108           break;
01109         } else {
01110           holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
01111         }
01112       }
01113       if (i < 3 * numberofholes) {
01114         // This must be caused by an error.
01115         fclose(polyfile);
01116         return false;
01117       }
01118     }
01119 
01120     // Read the region section.  The 'region' section is optional, if we
01121     //   don't reach the end-of-file, try read it in.
01122     stringptr = readnumberline(inputline, polyfile, NULL);
01123     if (stringptr != (char *) NULL && *stringptr != '\0') {
01124       numberofregions = (int) strtol (stringptr, &stringptr, 0);
01125     } else {
01126       numberofregions = 0;
01127     }
01128     if (numberofregions > 0) {
01129       // Initialize 'regionlist'.
01130       regionlist = new REAL[numberofregions * 5];
01131       index = 0;
01132       for (i = 0; i < numberofregions; i++) {
01133         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01134         stringptr = findnextnumber(stringptr);
01135         if (*stringptr == '\0') {
01136           printf("Error:  Region %d has no x coordinate.\n", firstnumber + i);
01137           break;
01138         } else {
01139           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01140         }
01141         stringptr = findnextnumber(stringptr);
01142         if (*stringptr == '\0') {
01143           printf("Error:  Region %d has no y coordinate.\n", firstnumber + i);
01144           break;
01145         } else {
01146           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01147         }
01148         stringptr = findnextnumber(stringptr);
01149         if (*stringptr == '\0') {
01150           printf("Error:  Region %d has no z coordinate.\n", firstnumber + i);
01151           break;
01152         } else {
01153           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01154         }
01155         stringptr = findnextnumber(stringptr);
01156         if (*stringptr == '\0') {
01157           printf("Error:  Region %d has no region attrib.\n", firstnumber + i);
01158           break;
01159         } else {
01160           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01161         }
01162         stringptr = findnextnumber(stringptr);
01163         if (*stringptr == '\0') {
01164           regionlist[index] = regionlist[index - 1];
01165         } else {
01166           regionlist[index] = (REAL) strtod(stringptr, &stringptr);
01167         }
01168         index++;
01169       }
01170       if (i < numberofregions) {
01171         // This must be caused by an error.
01172         fclose(polyfile);
01173         return false;
01174       }
01175     }
01176 
01177   } else {
01178 
01179     // Read a PSLG from Triangle's poly file.
01180     assert(mesh_dim == 2);
01181     // A PSLG is a facet of a PLC.
01182     numberoffacets = 1;
01183     // Initialize the 'facetlist'.
01184     facetlist = new facet[numberoffacets];
01185     facetmarkerlist = (int *) NULL; // No facet markers.
01186     f = &(facetlist[0]);
01187     init(f);
01188     // Read number of segments.
01189     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01190     // Segments are degenerate polygons.
01191     f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
01192     if (f->numberofpolygons > 0) {
01193       f->polygonlist = new polygon[f->numberofpolygons];
01194     }
01195     // Go through all segments, read in their vertices.
01196     for (j = 0; j < f->numberofpolygons; j++) {
01197       p = &(f->polygonlist[j]);
01198       init(p);
01199       // Read in a segment.
01200       stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01201       stringptr = findnextnumber(stringptr); // Skip its index.
01202       p->numberofvertices = 2; // A segment always has two vertices.
01203       p->vertexlist = new int[p->numberofvertices];
01204       p->vertexlist[0] = (int) strtol (stringptr, &stringptr, 0);
01205       stringptr = findnextnumber(stringptr);
01206       p->vertexlist[1] = (int) strtol (stringptr, &stringptr, 0);
01207     }
01208     // Read number of holes.
01209     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01210     f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
01211     if (f->numberofholes > 0) {
01212       // Initialize 'f->holelist'.
01213       f->holelist = new REAL[f->numberofholes * 3];
01214       // Read the holes' coordinates.
01215       for (j = 0; j < f->numberofholes; j++) {
01216         // Read a 2D hole point.
01217         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01218         stringptr = findnextnumber(stringptr); // Skip its index.
01219         f->holelist[j * 3] = (REAL) strtod (stringptr, &stringptr);
01220         stringptr = findnextnumber(stringptr);
01221         f->holelist[j * 3 + 1] = (REAL) strtod (stringptr, &stringptr);
01222         f->holelist[j * 3 + 2] = 0.0; // The z-coord.
01223       }
01224     }
01225     // The regions are skipped.
01226 
01227   }
01228 
01229   // End of reading poly/smesh file.
01230   fclose(polyfile);
01231 
01232   // Try to load a .var file if it exists.
01233   load_var(filename);
01234   // Try to load a .mtr file if it exists.
01235   load_mtr(filename);
01236   // Try to read a .pbc file if it exists.
01237   load_pbc(filename);
01238 
01239   return true;
01240 }
01241 
01243 //                                                                           //
01244 // load_off()    Load a polyhedron described in a .off file.                 //
01245 //                                                                           //
01246 // The .off format is one of file formats of the Geomview, an interactive    //
01247 // program for viewing and manipulating geometric objects.  More information //
01248 // is available form: http://www.geomview.org.                               //
01249 //                                                                           //
01250 // 'filename' is a input filename with extension .off or without extension ( //
01251 // the .off will be added in this case). On completion, the polyhedron is    //
01252 // returned in 'pointlist' and 'facetlist'.                                  //
01253 //                                                                           //
01255 
01256 bool tetgenio::load_off(char* filename)
01257 {
01258   FILE *fp;
01259   tetgenio::facet *f;
01260   tetgenio::polygon *p;
01261   char infilename[FILENAMESIZE];
01262   char buffer[INPUTLINESIZE];
01263   char *bufferp;
01264   double *coord;
01265   int nverts = 0, iverts = 0;
01266   int nfaces = 0, ifaces = 0;
01267   int nedges = 0;
01268   int line_count = 0, i;
01269 
01270   strncpy(infilename, filename, 1024 - 1);
01271   infilename[FILENAMESIZE - 1] = '\0';
01272   if (infilename[0] == '\0') {
01273     printf("Error:  No filename.\n");
01274     return false;
01275   }
01276   if (strcmp(&infilename[strlen(infilename) - 4], ".off") != 0) {
01277     strcat(infilename, ".off");
01278   }
01279 
01280   if (!(fp = fopen(infilename, "r"))) {
01281     printf("File I/O Error:  Unable to open file %s\n", infilename);
01282     return false;
01283   }
01284   printf("Opening %s.\n", infilename);
01285 
01286   // OFF requires the index starts from '0'.
01287   firstnumber = 0;
01288 
01289   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01290     // Check section
01291     if (nverts == 0) {
01292       // Read header 
01293       bufferp = strstr(bufferp, "OFF");
01294       if (bufferp != NULL) {
01295         // Read mesh counts
01296         bufferp = findnextnumber(bufferp); // Skip field "OFF".
01297         if (*bufferp == '\0') {
01298           // Read a non-empty line.
01299           bufferp = readline(buffer, fp, &line_count);
01300         }
01301         if ((sscanf(bufferp, "%d%d%d", &nverts, &nfaces, &nedges) != 3) 
01302             || (nverts == 0)) {
01303           printf("Syntax error reading header on line %d in file %s\n",
01304                  line_count, infilename);
01305           fclose(fp);
01306           return false;
01307         }
01308         // Allocate memory for 'tetgenio'
01309         if (nverts > 0) {
01310           numberofpoints = nverts;
01311           pointlist = new REAL[nverts * 3];
01312         }
01313         if (nfaces > 0) {        
01314           numberoffacets = nfaces;
01315           facetlist = new tetgenio::facet[nfaces];
01316         }
01317       }
01318     } else if (iverts < nverts) {
01319       // Read vertex coordinates
01320       coord = &pointlist[iverts * 3];
01321       for (i = 0; i < 3; i++) {
01322         if (*bufferp == '\0') {
01323           printf("Syntax error reading vertex coords on line %d in file %s\n",
01324                  line_count, infilename);
01325           fclose(fp);
01326           return false;
01327         }
01328         coord[i] = (REAL) strtod(bufferp, &bufferp);
01329         bufferp = findnextnumber(bufferp);
01330       }
01331       iverts++;
01332     } else if (ifaces < nfaces) {
01333       // Get next face
01334       f = &facetlist[ifaces];
01335       init(f);      
01336       // In .off format, each facet has one polygon, no hole.
01337       f->numberofpolygons = 1;
01338       f->polygonlist = new tetgenio::polygon[1];
01339       p = &f->polygonlist[0];
01340       init(p);
01341       // Read the number of vertices, it should be greater than 0.
01342       p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01343       if (p->numberofvertices == 0) {
01344         printf("Syntax error reading polygon on line %d in file %s\n",
01345                line_count, infilename);
01346         fclose(fp);
01347         return false;
01348       }
01349       // Allocate memory for face vertices
01350       p->vertexlist = new int[p->numberofvertices];
01351       for (i = 0; i < p->numberofvertices; i++) {
01352         bufferp = findnextnumber(bufferp);
01353         if (*bufferp == '\0') {
01354           printf("Syntax error reading polygon on line %d in file %s\n",
01355                  line_count, infilename);
01356           fclose(fp);
01357           return false;
01358         }
01359         p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01360       }
01361       ifaces++;
01362     } else {
01363       // Should never get here
01364       printf("Found extra text starting at line %d in file %s\n", line_count,
01365              infilename);
01366       break;
01367     }
01368   }
01369 
01370   // Close file
01371   fclose(fp);
01372 
01373   // Check whether read all points
01374   if (iverts != nverts) {
01375     printf("Expected %d vertices, but read only %d vertices in file %s\n",
01376            nverts, iverts, infilename);
01377     return false;
01378   }
01379 
01380   // Check whether read all faces
01381   if (ifaces != nfaces) {
01382     printf("Expected %d faces, but read only %d faces in file %s\n",
01383            nfaces, ifaces, infilename);
01384     return false;
01385   }
01386 
01387   return true;
01388 }
01389 
01391 //                                                                           //
01392 // load_ply()    Load a polyhedron described in a .ply file.                 //
01393 //                                                                           //
01394 // 'filename' is the file name with extension .ply or without extension (the //
01395 // .ply will be added in this case).                                         //
01396 //                                                                           //
01397 // This is a simplified version of reading .ply files, which only reads the  //
01398 // set of vertices and the set of faces. Other informations (such as color,  //
01399 // material, texture, etc) in .ply file are ignored. Complete routines for   //
01400 // reading and writing ,ply files are available from: http://www.cc.gatech.  //
01401 // edu/projects/large_models/ply.html.  Except the header section, ply file  //
01402 // format has exactly the same format for listing vertices and polygons as   //
01403 // off file format.                                                          //
01404 //                                                                           //
01405 // On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
01406 //                                                                           //
01408 
01409 bool tetgenio::load_ply(char* filename)
01410 {
01411   FILE *fp;
01412   tetgenio::facet *f;
01413   tetgenio::polygon *p;
01414   char infilename[FILENAMESIZE];
01415   char buffer[INPUTLINESIZE];
01416   char *bufferp, *str;
01417   double *coord;
01418   int endheader = 0, format = 0;
01419   int nverts = 0, iverts = 0;
01420   int nfaces = 0, ifaces = 0;
01421   int line_count = 0, i;
01422 
01423   strncpy(infilename, filename, FILENAMESIZE - 1);
01424   infilename[FILENAMESIZE - 1] = '\0';
01425   if (infilename[0] == '\0') {
01426     printf("Error:  No filename.\n");
01427     return false;
01428   }
01429   if (strcmp(&infilename[strlen(infilename) - 4], ".ply") != 0) {
01430     strcat(infilename, ".ply");
01431   }
01432 
01433   if (!(fp = fopen(infilename, "r"))) {
01434     printf("Error:  Unable to open file %s\n", infilename);
01435     return false;
01436   }
01437   printf("Opening %s.\n", infilename);
01438 
01439   // PLY requires the index starts from '0'.
01440   firstnumber = 0;
01441 
01442   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01443     if (!endheader) {
01444       // Find if it is the keyword "end_header".
01445       str = strstr(bufferp, "end_header");
01446       // strstr() is case sensitive.
01447       if (!str) str = strstr(bufferp, "End_header");
01448       if (!str) str = strstr(bufferp, "End_Header");
01449       if (str) {
01450         // This is the end of the header section.
01451         endheader = 1; 
01452         continue;
01453       }
01454       // Parse the number of vertices and the number of faces.
01455       if (nverts == 0 || nfaces == 0) {
01456         // Find if it si the keyword "element".
01457         str = strstr(bufferp, "element");
01458         if (!str) str = strstr(bufferp, "Element");
01459         if (str) {
01460           bufferp = findnextfield(str);
01461           if (*bufferp == '\0') {
01462             printf("Syntax error reading element type on line%d in file %s\n",
01463                    line_count, infilename);
01464             fclose(fp);
01465             return false;
01466           }
01467           if (nverts == 0) {
01468             // Find if it is the keyword "vertex".
01469             str = strstr(bufferp, "vertex");
01470             if (!str) str = strstr(bufferp, "Vertex");
01471             if (str) {
01472               bufferp = findnextnumber(str);
01473               if (*bufferp == '\0') {
01474                 printf("Syntax error reading vertex number on line");
01475                 printf(" %d in file %s\n", line_count, infilename);
01476                 fclose(fp);
01477                 return false;
01478               }
01479               nverts = (int) strtol(bufferp, &bufferp, 0);
01480               // Allocate memory for 'tetgenio'
01481               if (nverts > 0) {
01482                 numberofpoints = nverts;
01483                 pointlist = new REAL[nverts * 3];
01484               }
01485             }
01486           }
01487           if (nfaces == 0) {
01488             // Find if it is the keyword "face".
01489             str = strstr(bufferp, "face");
01490             if (!str) str = strstr(bufferp, "Face");
01491             if (str) {
01492               bufferp = findnextnumber(str);
01493               if (*bufferp == '\0') {
01494                 printf("Syntax error reading face number on line");
01495                 printf(" %d in file %s\n", line_count, infilename);
01496                 fclose(fp);
01497                 return false;
01498               }
01499               nfaces = (int) strtol(bufferp, &bufferp, 0);
01500               // Allocate memory for 'tetgenio'
01501               if (nfaces > 0) {        
01502                 numberoffacets = nfaces;
01503                 facetlist = new tetgenio::facet[nfaces];
01504               }
01505             }
01506           }
01507         } // It is not the string "element". 
01508       }
01509       if (format == 0) {
01510         // Find the keyword "format".
01511         str = strstr(bufferp, "format");
01512         if (!str) str = strstr(bufferp, "Format");
01513         if (str) {
01514           format = 1;
01515           bufferp = findnextfield(str);
01516           // Find if it is the string "ascii".
01517           str = strstr(bufferp, "ascii");
01518           if (!str) str = strstr(bufferp, "ASCII");
01519           if (!str) {
01520             printf("This routine only reads ascii format of ply files.\n");
01521             printf("Hint: You can convert the binary to ascii format by\n");
01522             printf("  using the provided ply tools:\n");
01523             printf("  ply2ascii < %s > ascii_%s\n", infilename, infilename);
01524             fclose(fp);
01525             return false;
01526           }
01527         }
01528       }
01529     } else if (iverts < nverts) {
01530       // Read vertex coordinates
01531       coord = &pointlist[iverts * 3];
01532       for (i = 0; i < 3; i++) {
01533         if (*bufferp == '\0') {
01534           printf("Syntax error reading vertex coords on line %d in file %s\n",
01535                  line_count, infilename);
01536           fclose(fp);
01537           return false;
01538         }
01539         coord[i] = (REAL) strtod(bufferp, &bufferp);
01540         bufferp = findnextnumber(bufferp);
01541       }
01542       iverts++;
01543     } else if (ifaces < nfaces) {
01544       // Get next face
01545       f = &facetlist[ifaces];
01546       init(f);      
01547       // In .off format, each facet has one polygon, no hole.
01548       f->numberofpolygons = 1;
01549       f->polygonlist = new tetgenio::polygon[1];
01550       p = &f->polygonlist[0];
01551       init(p);
01552       // Read the number of vertices, it should be greater than 0.
01553       p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01554       if (p->numberofvertices == 0) {
01555         printf("Syntax error reading polygon on line %d in file %s\n",
01556                line_count, infilename);
01557         fclose(fp);
01558         return false;
01559       }
01560       // Allocate memory for face vertices
01561       p->vertexlist = new int[p->numberofvertices];
01562       for (i = 0; i < p->numberofvertices; i++) {
01563         bufferp = findnextnumber(bufferp);
01564         if (*bufferp == '\0') {
01565           printf("Syntax error reading polygon on line %d in file %s\n",
01566                  line_count, infilename);
01567           fclose(fp);
01568           return false;
01569         }
01570         p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01571       }
01572       ifaces++;
01573     } else {
01574       // Should never get here
01575       printf("Found extra text starting at line %d in file %s\n", line_count,
01576              infilename);
01577       break;
01578     }
01579   }
01580 
01581   // Close file
01582   fclose(fp);
01583 
01584   // Check whether read all points
01585   if (iverts != nverts) {
01586     printf("Expected %d vertices, but read only %d vertices in file %s\n",
01587            nverts, iverts, infilename);
01588     return false;
01589   }
01590 
01591   // Check whether read all faces
01592   if (ifaces != nfaces) {
01593     printf("Expected %d faces, but read only %d faces in file %s\n",
01594            nfaces, ifaces, infilename);
01595     return false;
01596   }
01597 
01598   return true;
01599 }
01600 
01602 //                                                                           //
01603 // load_stl()    Load a surface mesh described in a .stl file.               //
01604 //                                                                           //
01605 // 'filename' is the file name with extension .stl or without extension (the //
01606 // .stl will be added in this case).                                         //
01607 //                                                                           //
01608 // The .stl or stereolithography format is an ASCII or binary file used in   //
01609 // manufacturing.  It is a list of the triangular surfaces that describe a   //
01610 // computer generated solid model. This is the standard input for most rapid //
01611 // prototyping machines.                                                     //
01612 //                                                                           //
01613 // On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
01614 // Note: After load_stl(), there exist many duplicated points in 'pointlist'.//
01615 // They will be unified during the Delaunay tetrahedralization process.      //
01616 //                                                                           //
01618 
01619 bool tetgenio::load_stl(char* filename)
01620 {
01621   FILE *fp;
01622   tetgenmesh::list *plist;
01623   tetgenio::facet *f;
01624   tetgenio::polygon *p;
01625   char infilename[FILENAMESIZE];
01626   char buffer[INPUTLINESIZE];
01627   char *bufferp, *str;
01628   double *coord;
01629   int solid = 0;
01630   int nverts = 0, iverts = 0;
01631   int nfaces = 0;
01632   int line_count = 0, i;
01633 
01634   strncpy(infilename, filename, FILENAMESIZE - 1);
01635   infilename[FILENAMESIZE - 1] = '\0';
01636   if (infilename[0] == '\0') {
01637     printf("Error:  No filename.\n");
01638     return false;
01639   }
01640   if (strcmp(&infilename[strlen(infilename) - 4], ".stl") != 0) {
01641     strcat(infilename, ".stl");
01642   }
01643 
01644   if (!(fp = fopen(infilename, "r"))) {
01645     printf("Error:  Unable to open file %s\n", infilename);
01646     return false;
01647   }
01648   printf("Opening %s.\n", infilename);
01649 
01650   // STL file has no number of points available. Use a list to read points.
01651   plist = new tetgenmesh::list(sizeof(double) * 3, NULL, 1024); 
01652 
01653   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01654     // The ASCII .stl file must start with the lower case keyword solid and
01655     //   end with endsolid.
01656     if (solid == 0) {
01657       // Read header 
01658       bufferp = strstr(bufferp, "solid");
01659       if (bufferp != NULL) {
01660         solid = 1;
01661       }
01662     } else {
01663       // We're inside the block of the solid.
01664       str = bufferp;
01665       // Is this the end of the solid.
01666       bufferp = strstr(bufferp, "endsolid");
01667       if (bufferp != NULL) {
01668         solid = 0;
01669       } else {
01670         // Read the XYZ coordinates if it is a vertex.
01671         bufferp = str;
01672         bufferp = strstr(bufferp, "vertex");
01673         if (bufferp != NULL) {
01674           coord = (double *) plist->append(NULL);
01675           for (i = 0; i < 3; i++) {
01676             bufferp = findnextnumber(bufferp);
01677             if (*bufferp == '\0') {
01678               printf("Syntax error reading vertex coords on line %d\n",
01679                    line_count);
01680               delete plist;
01681               fclose(fp);
01682               return false;
01683             }
01684             coord[i] = (REAL) strtod(bufferp, &bufferp);
01685           }
01686         }
01687       }
01688     }
01689   }
01690   fclose(fp);
01691 
01692   nverts = plist->len();
01693   // nverts should be an integer times 3 (every 3 vertices denote a face).
01694   if (nverts == 0 || (nverts % 3 != 0)) {
01695     printf("Error:  Wrong number of vertices in file %s.\n", infilename);
01696     delete plist;
01697     return false;
01698   }
01699   numberofpoints = nverts;
01700   pointlist = new REAL[nverts * 3];
01701   for (i = 0; i < nverts; i++) {
01702     coord = (double *) (* plist)[i];
01703     iverts = i * 3;
01704     pointlist[iverts] = (REAL) coord[0];
01705     pointlist[iverts + 1] = (REAL) coord[1];
01706     pointlist[iverts + 2] = (REAL) coord[2];
01707   }
01708 
01709   nfaces = (int) (nverts / 3);
01710   numberoffacets = nfaces;
01711   facetlist = new tetgenio::facet[nfaces];
01712 
01713   // Default use '1' as the array starting index.
01714   firstnumber = 1;
01715   iverts = firstnumber;
01716   for (i = 0; i < nfaces; i++) {
01717     f = &facetlist[i];
01718     init(f);      
01719     // In .stl format, each facet has one polygon, no hole.
01720     f->numberofpolygons = 1;
01721     f->polygonlist = new tetgenio::polygon[1];
01722     p = &f->polygonlist[0];
01723     init(p);
01724     // Each polygon has three vertices.
01725     p->numberofvertices = 3;
01726     p->vertexlist = new int[p->numberofvertices];
01727     p->vertexlist[0] = iverts;
01728     p->vertexlist[1] = iverts + 1;
01729     p->vertexlist[2] = iverts + 2;
01730     iverts += 3;
01731   }
01732 
01733   delete plist;
01734   return true;
01735 }
01736 
01738 //                                                                           //
01739 // load_medit()    Load a surface mesh described in .mesh file.              //
01740 //                                                                           //
01741 // 'filename' is the file name with extension .mesh or without entension (   //
01742 // the .mesh will be added in this case). .mesh is the file format of Medit, //
01743 // a user-friendly interactive mesh viewing program.                         //
01744 //                                                                           //
01745 // This routine ONLY reads the sections containing vertices, triangles, and  //
01746 // quadrilaters. Other sections (such as tetrahedra, edges, ...) are ignored.//
01747 //                                                                           //
01749 
01750 bool tetgenio::load_medit(char* filename)
01751 {
01752   FILE *fp;
01753   tetgenio::facet *tmpflist, *f;
01754   tetgenio::polygon *p;
01755   char infilename[FILENAMESIZE];
01756   char buffer[INPUTLINESIZE];
01757   char *bufferp, *str;
01758   double *coord;
01759   int *tmpfmlist;
01760   int dimension = 0;
01761   int nverts = 0;
01762   int nfaces = 0;
01763   int line_count = 0;
01764   int corners = 0; // 3 (triangle) or 4 (quad).
01765   int i, j;
01766 
01767   strncpy(infilename, filename, FILENAMESIZE - 1);
01768   infilename[FILENAMESIZE - 1] = '\0';
01769   if (infilename[0] == '\0') {
01770     printf("Error:  No filename.\n");
01771     return false;
01772   }
01773   if (strcmp(&infilename[strlen(infilename) - 5], ".mesh") != 0) {
01774     strcat(infilename, ".mesh");
01775   }
01776   
01777   if (!(fp = fopen(infilename, "r"))) {
01778     printf("Error:  Unable to open file %s\n", infilename);
01779     return false;
01780   }
01781   printf("Opening %s.\n", infilename);
01782 
01783   // Default uses the index starts from '1'.
01784   firstnumber = 1;
01785 
01786   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01787     if (*bufferp == '#') continue;  // A comment line is skipped.
01788     if (dimension == 0) {
01789       // Find if it is the keyword "Dimension".
01790       str = strstr(bufferp, "Dimension");
01791       if (!str) str = strstr(bufferp, "dimension");
01792       if (!str) str = strstr(bufferp, "DIMENSION");
01793       if (str) {
01794         // Read the dimensions
01795         bufferp = findnextnumber(str); // Skip field "Dimension".
01796         if (*bufferp == '\0') {
01797           // Read a non-empty line.
01798           bufferp = readline(buffer, fp, &line_count);
01799         }
01800         dimension = (int) strtol(bufferp, &bufferp, 0);
01801         if (dimension != 2 && dimension != 3) {
01802           printf("Unknown dimension in file on line %d in file %s\n",
01803                  line_count, infilename);
01804           fclose(fp);
01805           return false;
01806         }
01807         mesh_dim = dimension;
01808       }
01809     }
01810     if (nverts == 0) {
01811       // Find if it is the keyword "Vertices".
01812       str = strstr(bufferp, "Vertices");
01813       if (!str) str = strstr(bufferp, "vertices");
01814       if (!str) str = strstr(bufferp, "VERTICES");
01815       if (str) {
01816         // Read the number of vertices.
01817         bufferp = findnextnumber(str); // Skip field "Vertices".
01818         if (*bufferp == '\0') {
01819           // Read a non-empty line.
01820           bufferp = readline(buffer, fp, &line_count);
01821         }
01822         nverts = (int) strtol(bufferp, &bufferp, 0);
01823         // Allocate memory for 'tetgenio'
01824         if (nverts > 0) {
01825           numberofpoints = nverts;
01826           pointlist = new REAL[nverts * 3];
01827         }
01828         // Read the follwoing node list.
01829         for (i = 0; i < nverts; i++) {
01830           bufferp = readline(buffer, fp, &line_count);
01831           if (bufferp == NULL) {
01832             printf("Unexpected end of file on line %d in file %s\n",
01833                    line_count, infilename);
01834             fclose(fp);
01835             return false;
01836           }
01837           // Read vertex coordinates
01838           coord = &pointlist[i * 3];
01839           for (j = 0; j < 3; j++) {
01840             if (*bufferp == '\0') {
01841               printf("Syntax error reading vertex coords on line");
01842               printf(" %d in file %s\n", line_count, infilename);
01843               fclose(fp);
01844               return false;
01845             }
01846             if ((j < 2) || (dimension == 3)) {
01847               coord[j] = (REAL) strtod(bufferp, &bufferp);
01848             } else {
01849               assert((j == 2) && (dimension == 2));
01850               coord[j] = 0.0;
01851             }
01852             bufferp = findnextnumber(bufferp);
01853           }
01854         }
01855         continue;
01856       }
01857     } 
01858     if (nfaces == 0) {
01859       // Find if it is the keyword "Triangles" or "Quadrilaterals".
01860       corners = 0;
01861       str = strstr(bufferp, "Triangles");
01862       if (!str) str = strstr(bufferp, "triangles");
01863       if (!str) str = strstr(bufferp, "TRIANGLES");
01864       if (str) {
01865         corners = 3;
01866       } else {
01867         str = strstr(bufferp, "Quadrilaterals");
01868         if (!str) str = strstr(bufferp, "quadrilaterals");
01869         if (!str) str = strstr(bufferp, "QUADRILATERALS");
01870         if (str) {
01871           corners = 4;
01872         }
01873       }
01874       if (corners == 3 || corners == 4) {
01875         // Read the number of triangles (or quadrilaterals).
01876         bufferp = findnextnumber(str); // Skip field "Triangles".
01877         if (*bufferp == '\0') {
01878           // Read a non-empty line.
01879           bufferp = readline(buffer, fp, &line_count);
01880         }
01881         nfaces = strtol(bufferp, &bufferp, 0);
01882         // Allocate memory for 'tetgenio'
01883         if (nfaces > 0) {
01884           if (numberoffacets > 0) {
01885             // facetlist has already been allocated. Enlarge arrays.
01886             tmpflist = new tetgenio::facet[numberoffacets + nfaces];
01887             tmpfmlist = new int[numberoffacets + nfaces];
01888             // Copy the data of old arrays into new arrays.
01889             for (i = 0; i < numberoffacets; i++) {
01890               f = &(tmpflist[i]);
01891               tetgenio::init(f);
01892               *f = facetlist[i];
01893               tmpfmlist[i] = facetmarkerlist[i];
01894             }
01895             // Release old arrays.
01896             delete [] facetlist;
01897             delete [] facetmarkerlist;
01898             // Remember the new arrays.
01899             facetlist = tmpflist;
01900             facetmarkerlist = tmpfmlist;
01901           } else {
01902             // This is the first time to allocate facetlist.
01903             facetlist = new tetgenio::facet[nfaces];
01904             facetmarkerlist = new int[nfaces];
01905           }
01906         }
01907         // Read the following list of faces.
01908         for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
01909           bufferp = readline(buffer, fp, &line_count);
01910           if (bufferp == NULL) {
01911             printf("Unexpected end of file on line %d in file %s\n",
01912                    line_count, infilename);
01913             fclose(fp);
01914             return false;
01915           }
01916           f = &facetlist[i];
01917           tetgenio::init(f);
01918           // In .mesh format, each facet has one polygon, no hole.
01919           f->numberofpolygons = 1;
01920           f->polygonlist = new tetgenio::polygon[1];
01921           p = &f->polygonlist[0];
01922           tetgenio::init(p);
01923           p->numberofvertices = corners;
01924           // Allocate memory for face vertices
01925           p->vertexlist = new int[p->numberofvertices];
01926           // Read the vertices of the face.
01927           for (j = 0; j < corners; j++) {
01928             if (*bufferp == '\0') {
01929               printf("Syntax error reading face on line %d in file %s\n",
01930                      line_count, infilename);
01931               fclose(fp);
01932               return false;
01933             }
01934             p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0);
01935             if (firstnumber == 1) {
01936               // Check if a '0' index appears.
01937               if (p->vertexlist[j] == 0) {
01938                 // The first index is set to be 0.
01939                 firstnumber = 0;
01940               }
01941             }
01942             bufferp = findnextnumber(bufferp);
01943           }
01944           // Read the marker of the face if it exists.
01945           facetmarkerlist[i] = 0;
01946           if (*bufferp != '\0') {
01947             facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
01948           }
01949         }
01950         // Have read in a list of triangles/quads.
01951         numberoffacets += nfaces;
01952         nfaces = 0;
01953       }
01954     }
01955     // if (nverts > 0 && nfaces > 0) break; // Ignore other data.
01956   }
01957 
01958   // Close file
01959   fclose(fp);
01960 
01961   return true;
01962 }
01963 
01965 //                                                                           //
01966 // load_plc()    Load a piecewise linear complex from file.                  //
01967 //                                                                           //
01968 // This is main entrance for loading plcs from different file formats into   //
01969 // tetgenio.  'filename' is the input file name without extention. 'object'  //
01970 // indicates which file format is used to describ the plc.                   //
01971 //                                                                           //
01973 
01974 bool tetgenio::load_plc(char* filename, int object)
01975 {
01976   enum tetgenbehavior::objecttype type;
01977 
01978   type = (enum tetgenbehavior::objecttype) object;
01979   switch (type) {
01980   case tetgenbehavior::NODES:
01981     return load_node(filename);
01982   case tetgenbehavior::POLY:
01983     return load_poly(filename);
01984   case tetgenbehavior::OFF:
01985     return load_off(filename);
01986   case tetgenbehavior::PLY:
01987     return load_ply(filename);
01988   case tetgenbehavior::STL:
01989     return load_stl(filename);
01990   case tetgenbehavior::MEDIT:
01991     return load_medit(filename);
01992   default:
01993     return load_poly(filename);
01994   }
01995 }
01996 
01998 //                                                                           //
01999 // load_tetmesh()    Load a tetrahedral mesh from files.                     //
02000 //                                                                           //
02001 // 'filename' is the inputfile without suffix.  The nodes of the tetrahedral //
02002 // mesh is in "filename.node",  the elements is in "filename.ele", if the    //
02003 // "filename.face" and "filename.vol" exists, they will also be read.        //
02004 //                                                                           //
02006 
02007 bool tetgenio::load_tetmesh(char* filename)
02008 {
02009   FILE *infile;
02010   char innodefilename[FILENAMESIZE];
02011   char inelefilename[FILENAMESIZE];
02012   char infacefilename[FILENAMESIZE];
02013   char inedgefilename[FILENAMESIZE];
02014   char involfilename[FILENAMESIZE];
02015   char inputline[INPUTLINESIZE];
02016   char *stringptr, *infilename;
02017   REAL attrib, volume;
02018   int volelements;
02019   int markers, corner;
02020   int index, attribindex;
02021   int i, j;
02022 
02023   markers = 0;
02024 
02025   // Assembling the actual file names we want to open.
02026   strcpy(innodefilename, filename);
02027   strcpy(inelefilename, filename);
02028   strcpy(infacefilename, filename);
02029   strcpy(inedgefilename, filename);
02030   strcpy(involfilename, filename);
02031   strcat(innodefilename, ".node");
02032   strcat(inelefilename, ".ele");
02033   strcat(infacefilename, ".face");
02034   strcat(inedgefilename, ".edge");
02035   strcat(involfilename, ".vol");
02036 
02037   // Read the points from a .node file.
02038   infilename = innodefilename;
02039   printf("Opening %s.\n", infilename);
02040   infile = fopen(infilename, "r");
02041   if (infile == (FILE *) NULL) {
02042     printf("File I/O Error:  Cannot access file %s.\n", infilename);
02043     return false;
02044   }
02045   // Read the first line of the file.
02046   stringptr = readnumberline(inputline, infile, infilename); 
02047   // Is this list of points generated from rbox?
02048   stringptr = strstr(inputline, "rbox");
02049   if (stringptr == NULL) {
02050     // Read number of points, number of dimensions, number of point
02051     //   attributes, and number of boundary markers.
02052     stringptr = inputline;
02053     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02054     stringptr = findnextnumber(stringptr);
02055     if (*stringptr == '\0') {
02056       mesh_dim = 3;
02057     } else {
02058       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02059     }
02060     stringptr = findnextnumber(stringptr);
02061     if (*stringptr == '\0') {
02062       numberofpointattributes = 0;
02063     } else {
02064       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
02065     }
02066     stringptr = findnextnumber(stringptr);
02067     if (*stringptr == '\0') {
02068       markers = 0;  // Default value.
02069     } else {
02070       markers = (int) strtol (stringptr, &stringptr, 0);
02071     }
02072   } else {
02073     // It is a rbox (qhull) input file.
02074     stringptr = inputline;
02075     // Get the dimension.
02076     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02077     // Get the number of points.
02078     stringptr = readnumberline(inputline, infile, infilename);
02079     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02080     // There is no index column.
02081     useindex = 0;
02082   }
02083 
02084   // Load the list of nodes.
02085   if (!load_node_call(infile, markers, infilename)) {
02086     fclose(infile);
02087     return false;
02088   }
02089   fclose(infile);
02090 
02091   // Read the elements from an .ele file.
02092   if (mesh_dim == 3) {
02093     infilename = inelefilename;
02094     infile = fopen(infilename, "r");
02095     if (infile != (FILE *) NULL) {
02096       printf("Opening %s.\n", infilename);
02097       // Read number of elements, number of corners (4 or 10), number of
02098       //   element attributes.
02099       stringptr = readnumberline(inputline, infile, infilename);
02100       numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0);
02101       stringptr = findnextnumber(stringptr);
02102       if (*stringptr == '\0') {
02103         numberofcorners = 4;  // Default read 4 nodes per element.
02104       } else {
02105         numberofcorners = (int) strtol(stringptr, &stringptr, 0);
02106       }
02107       stringptr = findnextnumber(stringptr);
02108       if (*stringptr == '\0') {
02109         numberoftetrahedronattributes = 0; // Default no attribute.
02110       } else {
02111         numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0);
02112       }
02113       if (numberofcorners != 4 && numberofcorners != 10) {
02114         printf("Error:  Wrong number of corners %d (should be 4 or 10).\n", 
02115                numberofcorners);
02116         fclose(infile);
02117         return false;
02118       }
02119       // Allocate memory for tetrahedra.
02120       if (numberoftetrahedra > 0) {
02121         tetrahedronlist = new int[numberoftetrahedra * numberofcorners]; 
02122         if (tetrahedronlist == (int *) NULL) {
02123           printf("Error:  Out of memory.\n");
02124           terminatetetgen(1);
02125         }
02126         // Allocate memory for output tetrahedron attributes if necessary.
02127         if (numberoftetrahedronattributes > 0) {
02128           tetrahedronattributelist = new REAL[numberoftetrahedra *
02129                                           numberoftetrahedronattributes];
02130           if (tetrahedronattributelist == (REAL *) NULL) {
02131             printf("Error:  Out of memory.\n");
02132             terminatetetgen(1);
02133           }
02134         }
02135       }
02136       // Read the list of tetrahedra.
02137       index = 0;
02138       attribindex = 0;
02139       for (i = 0; i < numberoftetrahedra; i++) {
02140         // Read tetrahedron index and the tetrahedron's corners.
02141         stringptr = readnumberline(inputline, infile, infilename);
02142         for (j = 0; j < numberofcorners; j++) {
02143           stringptr = findnextnumber(stringptr);
02144           if (*stringptr == '\0') {
02145             printf("Error:  Tetrahedron %d is missing vertex %d in %s.\n",
02146                    i + firstnumber, j + 1, infilename);
02147             terminatetetgen(1);
02148           }
02149           corner = (int) strtol(stringptr, &stringptr, 0);
02150           if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02151             printf("Error:  Tetrahedron %d has an invalid vertex index.\n",
02152                    i + firstnumber);
02153             terminatetetgen(1);
02154           }
02155           tetrahedronlist[index++] = corner;
02156         }
02157         // Read the tetrahedron's attributes.
02158         for (j = 0; j < numberoftetrahedronattributes; j++) {
02159           stringptr = findnextnumber(stringptr);
02160           if (*stringptr == '\0') {
02161             attrib = 0.0;
02162           } else {
02163             attrib = (REAL) strtod(stringptr, &stringptr);
02164           }
02165           tetrahedronattributelist[attribindex++] = attrib;
02166         }
02167       }
02168       fclose(infile);
02169     }
02170   } // if (meshdim == 3)
02171   
02172   // Read the hullfaces or subfaces from a .face file if it exists.
02173   if (mesh_dim == 3) {
02174     infilename = infacefilename;
02175   } else {
02176     infilename = inelefilename;
02177   }
02178   infile = fopen(infilename, "r");
02179   if (infile != (FILE *) NULL) {
02180     printf("Opening %s.\n", infilename);
02181     // Read number of faces, boundary markers.
02182     stringptr = readnumberline(inputline, infile, infilename);
02183     numberoftrifaces = (int) strtol (stringptr, &stringptr, 0);
02184     stringptr = findnextnumber(stringptr);
02185     if (mesh_dim == 2) {
02186       // Skip a number.
02187       stringptr = findnextnumber(stringptr);
02188     }
02189     if (*stringptr == '\0') {
02190       markers = 0;  // Default there is no marker per face.
02191     } else {
02192       markers = (int) strtol (stringptr, &stringptr, 0);
02193     }
02194     if (numberoftrifaces > 0) {
02195       trifacelist = new int[numberoftrifaces * 3];
02196       if (trifacelist == (int *) NULL) {
02197         printf("Error:  Out of memory.\n");
02198         terminatetetgen(1);
02199       }
02200       if (markers) {
02201         trifacemarkerlist = new int[numberoftrifaces * 3];
02202         if (trifacemarkerlist == (int *) NULL) {
02203           printf("Error:  Out of memory.\n");
02204           terminatetetgen(1);
02205         }
02206       }
02207     }
02208     // Read the list of faces.
02209     index = 0;
02210     for (i = 0; i < numberoftrifaces; i++) {
02211       // Read face index and the face's three corners.
02212       stringptr = readnumberline(inputline, infile, infilename);
02213       for (j = 0; j < 3; j++) {
02214         stringptr = findnextnumber(stringptr);
02215         if (*stringptr == '\0') {
02216           printf("Error:  Face %d is missing vertex %d in %s.\n",
02217                  i + firstnumber, j + 1, infilename);
02218           terminatetetgen(1);
02219         }
02220         corner = (int) strtol(stringptr, &stringptr, 0);
02221         if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02222           printf("Error:  Face %d has an invalid vertex index.\n",
02223                  i + firstnumber);
02224           terminatetetgen(1);
02225         }
02226         trifacelist[index++] = corner;
02227       }
02228       // Read the boundary marker if it exists.
02229       if (markers) {
02230         stringptr = findnextnumber(stringptr);
02231         if (*stringptr == '\0') {
02232           attrib = 0.0;
02233         } else {
02234           attrib = (REAL) strtod(stringptr, &stringptr);
02235         }
02236         trifacemarkerlist[i] = (int) attrib;
02237       }
02238     }
02239     fclose(infile);
02240   }
02241 
02242   // Read the boundary edges from a .edge file if it exists.
02243   infilename = inedgefilename;
02244   infile = fopen(infilename, "r");
02245   if (infile != (FILE *) NULL) {
02246     printf("Opening %s.\n", infilename);
02247     // Read number of boundary edges.
02248     stringptr = readnumberline(inputline, infile, infilename);
02249     numberofedges = (int) strtol (stringptr, &stringptr, 0);
02250     if (numberofedges > 0) {
02251       edgelist = new int[numberofedges * 2];
02252       if (edgelist == (int *) NULL) {
02253         printf("Error:  Out of memory.\n");
02254         terminatetetgen(1);
02255       }
02256     }
02257     // Read the list of faces.
02258     index = 0;
02259     for (i = 0; i < numberofedges; i++) {
02260       // Read face index and the edge's two endpoints.
02261       stringptr = readnumberline(inputline, infile, infilename);
02262       for (j = 0; j < 2; j++) {
02263         stringptr = findnextnumber(stringptr);
02264         if (*stringptr == '\0') {
02265           printf("Error:  Edge %d is missing vertex %d in %s.\n",
02266                  i + firstnumber, j + 1, infilename);
02267           terminatetetgen(1);
02268         }
02269         corner = (int) strtol(stringptr, &stringptr, 0);
02270         if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02271           printf("Error:  Edge %d has an invalid vertex index.\n",
02272                  i + firstnumber);
02273           terminatetetgen(1);
02274         }
02275         edgelist[index++] = corner;
02276       }
02277     }
02278     fclose(infile);
02279   }
02280 
02281   // Read the volume constraints from a .vol file if it exists.
02282   infilename = involfilename;
02283   infile = fopen(infilename, "r");
02284   if (infile != (FILE *) NULL) {
02285     printf("Opening %s.\n", infilename);
02286     // Read number of tetrahedra.
02287     stringptr = readnumberline(inputline, infile, infilename);
02288     volelements = (int) strtol (stringptr, &stringptr, 0);
02289     if (volelements != numberoftetrahedra) {
02290       printf("Warning:  %s and %s disagree on number of tetrahedra.\n",
02291              inelefilename, involfilename);
02292       volelements = 0;
02293     }
02294     if (volelements > 0) {
02295       tetrahedronvolumelist = new REAL[volelements];
02296       if (tetrahedronvolumelist == (REAL *) NULL) {
02297         printf("Error:  Out of memory.\n");
02298         terminatetetgen(1);
02299       }
02300     }
02301     // Read the list of volume constraints.
02302     for (i = 0; i < volelements; i++) {
02303       stringptr = readnumberline(inputline, infile, infilename);
02304       stringptr = findnextnumber(stringptr);
02305       if (*stringptr == '\0') {
02306         volume = -1.0; // No constraint on this tetrahedron.
02307       } else {
02308         volume = (REAL) strtod(stringptr, &stringptr);
02309       }
02310       tetrahedronvolumelist[i] = volume;
02311     }
02312     fclose(infile);
02313   }
02314 
02315   // Try to load a .mtr file if it exists.
02316   load_mtr(filename);
02317   // Try to read a .pbc file if it exists.
02318   load_pbc(filename);
02319 
02320   return true;
02321 }
02322 
02324 //                                                                           //
02325 // load_voronoi()    Load a Voronoi diagram from files.                      //
02326 //                                                                           //
02327 // 'filename' is the inputfile without suffix.  The Voronoi diagram is read  //
02328 // from files: filename.v.node, filename.v.edge, and filename.v.face.        //
02329 //                                                                           //
02331 
02332 bool tetgenio::load_voronoi(char* filename)
02333 {
02334   FILE *infile;
02335   char innodefilename[FILENAMESIZE];
02336   char inedgefilename[FILENAMESIZE];
02337   char inputline[INPUTLINESIZE];
02338   char *stringptr, *infilename;
02339   voroedge *vedge;
02340   REAL x, y, z;
02341   int firstnode, corner;
02342   int index;
02343   int i, j;
02344 
02345   // Assembling the actual file names we want to open.
02346   strcpy(innodefilename, filename);
02347   strcpy(inedgefilename, filename);
02348   strcat(innodefilename, ".v.node");
02349   strcat(inedgefilename, ".v.edge");
02350 
02351   // Read the points from a .v.node file.
02352   infilename = innodefilename;
02353   printf("Opening %s.\n", infilename);
02354   infile = fopen(infilename, "r");
02355   if (infile == (FILE *) NULL) {
02356     printf("File I/O Error:  Cannot access file %s.\n", infilename);
02357     return false;
02358   }
02359   // Read the first line of the file.
02360   stringptr = readnumberline(inputline, infile, infilename); 
02361   // Is this list of points generated from rbox?
02362   stringptr = strstr(inputline, "rbox");
02363   if (stringptr == NULL) {
02364     // Read number of points, number of dimensions, number of point
02365     //   attributes, and number of boundary markers.
02366     stringptr = inputline;
02367     numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02368     stringptr = findnextnumber(stringptr);
02369     if (*stringptr == '\0') {
02370       mesh_dim = 3;  // Default.
02371     } else {
02372       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02373     }
02374     useindex = 1;  // There is an index column.
02375   } else {
02376     // It is a rbox (qhull) input file.
02377     stringptr = inputline;
02378     // Get the dimension.
02379     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02380     // Get the number of points.
02381     stringptr = readnumberline(inputline, infile, infilename);
02382     numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02383     useindex = 0;  // No index column.
02384   }
02385   // Initialize 'vpointlist'.
02386   vpointlist = new REAL[numberofvpoints * 3];
02387   if (vpointlist == (REAL *) NULL) {
02388     printf("Error:  Out of memory.\n");
02389     terminatetetgen(1);
02390   }
02391   // Read the point section.
02392   index = 0;
02393   for (i = 0; i < numberofvpoints; i++) {
02394     stringptr = readnumberline(inputline, infile, infilename);
02395     if (useindex) {
02396       if (i == 0) {
02397         firstnode = (int) strtol (stringptr, &stringptr, 0);
02398         if ((firstnode == 0) || (firstnode == 1)) {
02399           firstnumber = firstnode;
02400         }
02401       }
02402       stringptr = findnextnumber(stringptr);
02403     } // if (useindex)
02404     if (*stringptr == '\0') {
02405       printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
02406       terminatetetgen(1);
02407     }
02408     x = (REAL) strtod(stringptr, &stringptr);
02409     stringptr = findnextnumber(stringptr);
02410     if (*stringptr == '\0') {
02411       printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
02412       terminatetetgen(1);
02413     }
02414     y = (REAL) strtod(stringptr, &stringptr);
02415     if (mesh_dim == 3) {
02416       stringptr = findnextnumber(stringptr);
02417       if (*stringptr == '\0') {
02418         printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
02419         terminatetetgen(1);
02420       }
02421       z = (REAL) strtod(stringptr, &stringptr);
02422     } else {
02423       z = 0.0; // mesh_dim == 2;
02424     }
02425     vpointlist[index++] = x;
02426     vpointlist[index++] = y;
02427     vpointlist[index++] = z;
02428   }
02429   fclose(infile);
02430 
02431   // Read the Voronoi edges from a .v.edge file if it exists.
02432   infilename = inedgefilename;
02433   infile = fopen(infilename, "r");
02434   if (infile != (FILE *) NULL) {
02435     printf("Opening %s.\n", infilename);
02436     // Read number of boundary edges.
02437     stringptr = readnumberline(inputline, infile, infilename);
02438     numberofvedges = (int) strtol (stringptr, &stringptr, 0);
02439     if (numberofvedges > 0) {
02440       vedgelist = new voroedge[numberofvedges];
02441     }
02442     // Read the list of faces.
02443     index = 0;
02444     for (i = 0; i < numberofvedges; i++) {
02445       // Read edge index and the edge's two endpoints.
02446       stringptr = readnumberline(inputline, infile, infilename);
02447       vedge = &(vedgelist[i]);
02448       for (j = 0; j < 2; j++) {
02449         stringptr = findnextnumber(stringptr);
02450         if (*stringptr == '\0') {
02451           printf("Error:  Edge %d is missing vertex %d in %s.\n",
02452                  i + firstnumber, j + 1, infilename);
02453           terminatetetgen(1);
02454         }
02455         corner = (int) strtol(stringptr, &stringptr, 0);
02456         j == 0 ? vedge->v1 = corner : vedge->v2 = corner;
02457       }
02458       if (vedge->v2 < 0) {
02459         for (j = 0; j < mesh_dim; j++) {
02460           stringptr = findnextnumber(stringptr);
02461           if (*stringptr == '\0') {
02462             printf("Error:  Edge %d is missing normal in %s.\n",
02463                    i + firstnumber, infilename);
02464             terminatetetgen(1);
02465           }
02466           vedge->vnormal[j] = (REAL) strtod(stringptr, &stringptr);
02467         }
02468         if (mesh_dim == 2) {
02469           vedge->vnormal[2] = 0.0;
02470         }
02471       } else {
02472         vedge->vnormal[0] = 0.0;
02473         vedge->vnormal[1] = 0.0;
02474         vedge->vnormal[2] = 0.0;
02475       }
02476     }
02477     fclose(infile);
02478   }
02479 
02480   return true;
02481 }
02482 
02484 //                                                                           //
02485 // save_nodes()    Save points to a .node file.                              //
02486 //                                                                           //
02487 // 'filename' is a string containing the file name without suffix.           //
02488 //                                                                           //
02490 
02491 void tetgenio::save_nodes(char* filename)
02492 {
02493   FILE *fout;
02494   char outnodefilename[FILENAMESIZE];
02495   char outmtrfilename[FILENAMESIZE];
02496   int i, j;
02497 
02498   sprintf(outnodefilename, "%s.node", filename);
02499   printf("Saving nodes to %s\n", outnodefilename);
02500   fout = fopen(outnodefilename, "w");
02501   fprintf(fout, "%d  %d  %d  %d\n", numberofpoints, mesh_dim,
02502           numberofpointattributes, pointmarkerlist != NULL ? 1 : 0);
02503   for (i = 0; i < numberofpoints; i++) {
02504     if (mesh_dim == 2) {
02505       fprintf(fout, "%d  %.16g  %.16g", i + firstnumber, pointlist[i * 2],
02506               pointlist[i * 2 + 1]);
02507     } else {
02508       fprintf(fout, "%d  %.16g  %.16g  %.16g", i + firstnumber,
02509               pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
02510     }
02511     for (j = 0; j < numberofpointattributes; j++) {
02512       fprintf(fout, "  %.16g", 
02513               pointattributelist[i * numberofpointattributes + j]);
02514     }
02515     if (pointmarkerlist != NULL) {
02516       fprintf(fout, "  %d", pointmarkerlist[i]);
02517     }
02518     fprintf(fout, "\n");
02519   }
02520   fclose(fout);
02521 
02522   // If the point metrics exist, output them to a .mtr file.
02523   if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
02524     sprintf(outmtrfilename, "%s.mtr", filename);
02525     printf("Saving metrics to %s\n", outmtrfilename);
02526     fout = fopen(outmtrfilename, "w");
02527     fprintf(fout, "%d  %d\n", numberofpoints, numberofpointmtrs);
02528     for (i = 0; i < numberofpoints; i++) {
02529       for (j = 0; j < numberofpointmtrs; j++) {
02530         fprintf(fout, "%.16g ", pointmtrlist[i * numberofpointmtrs + j]);
02531       }
02532       fprintf(fout, "\n");
02533     }
02534     fclose(fout);
02535   }
02536 }
02537 
02539 //                                                                           //
02540 // save_elements()    Save elements to a .ele file.                          //
02541 //                                                                           //
02542 // 'filename' is a string containing the file name without suffix.           //
02543 //                                                                           //
02545 
02546 void tetgenio::save_elements(char* filename)
02547 {
02548   FILE *fout;
02549   char outelefilename[FILENAMESIZE];
02550   int i, j;
02551 
02552   sprintf(outelefilename, "%s.ele", filename);
02553   printf("Saving elements to %s\n", outelefilename);
02554   fout = fopen(outelefilename, "w");
02555   fprintf(fout, "%d  %d  %d\n", numberoftetrahedra, numberofcorners,
02556           numberoftetrahedronattributes);
02557   for (i = 0; i < numberoftetrahedra; i++) {
02558     fprintf(fout, "%d", i + firstnumber);
02559     for (j = 0; j < numberofcorners; j++) {
02560       fprintf(fout, "  %5d", tetrahedronlist[i * numberofcorners + j]);
02561     }
02562     for (j = 0; j < numberoftetrahedronattributes; j++) {
02563       fprintf(fout, "  %g",
02564         tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
02565     }
02566     fprintf(fout, "\n");
02567   }
02568 
02569   fclose(fout);
02570 }
02571 
02573 //                                                                           //
02574 // save_faces()    Save faces to a .face file.                               //
02575 //                                                                           //
02576 // 'filename' is a string containing the file name without suffix.           //
02577 //                                                                           //
02579 
02580 void tetgenio::save_faces(char* filename)
02581 {
02582   FILE *fout;
02583   char outfacefilename[FILENAMESIZE];
02584   int i;
02585 
02586   sprintf(outfacefilename, "%s.face", filename);
02587   printf("Saving faces to %s\n", outfacefilename);
02588   fout = fopen(outfacefilename, "w");
02589   fprintf(fout, "%d  %d\n", numberoftrifaces, 
02590           trifacemarkerlist != NULL ? 1 : 0);
02591   for (i = 0; i < numberoftrifaces; i++) {
02592     fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber, trifacelist[i * 3],
02593             trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
02594     if (trifacemarkerlist != NULL) {
02595       fprintf(fout, "  %d", trifacemarkerlist[i]);
02596     }
02597     fprintf(fout, "\n");
02598   }
02599 
02600   fclose(fout);
02601 }
02602 
02604 //                                                                           //
02605 // save_edges()    Save egdes to a .edge file.                               //
02606 //                                                                           //
02607 // 'filename' is a string containing the file name without suffix.           //
02608 //                                                                           //
02610 
02611 void tetgenio::save_edges(char* filename)
02612 {
02613   FILE *fout;
02614   char outedgefilename[FILENAMESIZE];
02615   int i;
02616 
02617   sprintf(outedgefilename, "%s.edge", filename);
02618   printf("Saving edges to %s\n", outedgefilename);
02619   fout = fopen(outedgefilename, "w");
02620   fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02621   for (i = 0; i < numberofedges; i++) {
02622     fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
02623             edgelist[i * 2 + 1]);
02624     if (edgemarkerlist != NULL) {
02625       fprintf(fout, "  %d", edgemarkerlist[i]);
02626     }
02627     fprintf(fout, "\n");
02628   }
02629 
02630   fclose(fout);
02631 }
02632 
02634 //                                                                           //
02635 // save_neighbors()    Save egdes to a .neigh file.                          //
02636 //                                                                           //
02637 // 'filename' is a string containing the file name without suffix.           //
02638 //                                                                           //
02640 
02641 void tetgenio::save_neighbors(char* filename)
02642 {
02643   FILE *fout;
02644   char outneighborfilename[FILENAMESIZE];
02645   int i;
02646 
02647   sprintf(outneighborfilename, "%s.neigh", filename);
02648   printf("Saving neighbors to %s\n", outneighborfilename);
02649   fout = fopen(outneighborfilename, "w");
02650   fprintf(fout, "%d  %d\n", numberoftetrahedra, mesh_dim + 1);
02651   for (i = 0; i < numberoftetrahedra; i++) {
02652     if (mesh_dim == 2) {
02653       fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber,  neighborlist[i * 3],
02654               neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]);
02655     } else {
02656       fprintf(fout, "%d  %5d  %5d  %5d  %5d", i + firstnumber,
02657               neighborlist[i * 4], neighborlist[i * 4 + 1],
02658               neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]);
02659     }
02660     fprintf(fout, "\n");
02661   }
02662 
02663   fclose(fout);
02664 }
02665 
02667 //                                                                           //
02668 // save_poly()    Save segments or facets to a .poly file.                   //
02669 //                                                                           //
02670 // 'filename' is a string containing the file name without suffix.  It only  //
02671 // save the facets, holes and regions.  The nodes are saved in a .node file  //
02672 // by routine save_nodes().                                                  //
02673 //                                                                           //
02675 
02676 void tetgenio::save_poly(char* filename)
02677 {
02678   FILE *fout;
02679   facet *f;
02680   polygon *p;
02681   char outpolyfilename[FILENAMESIZE];
02682   int i, j, k;
02683 
02684   sprintf(outpolyfilename, "%s.poly", filename);
02685   printf("Saving poly to %s\n", outpolyfilename);
02686   fout = fopen(outpolyfilename, "w");
02687 
02688   // The zero indicates that the vertices are in a separate .node file.
02689   //   Followed by number of dimensions, number of vertex attributes,
02690   //   and number of boundary markers (zero or one).
02691   fprintf(fout, "%d  %d  %d  %d\n", 0, mesh_dim, numberofpointattributes,
02692           pointmarkerlist != NULL ? 1 : 0);
02693 
02694   // Save segments or facets.
02695   if (mesh_dim == 2) {
02696     // Number of segments, number of boundary markers (zero or one).
02697     fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02698     for (i = 0; i < numberofedges; i++) {
02699       fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
02700               edgelist[i * 2 + 1]);
02701       if (edgemarkerlist != NULL) {
02702         fprintf(fout, "  %d", edgemarkerlist[i]);
02703       }
02704       fprintf(fout, "\n");
02705     }
02706   } else {
02707     // Number of facets, number of boundary markers (zero or one).
02708     fprintf(fout, "%d  %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0);
02709     for (i = 0; i < numberoffacets; i++) {
02710       f = &(facetlist[i]);
02711       fprintf(fout, "%d  %d  %d  # %d\n", f->numberofpolygons,f->numberofholes,
02712             facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber);
02713       // Output polygons of this facet.
02714       for (j = 0; j < f->numberofpolygons; j++) {
02715         p = &(f->polygonlist[j]);
02716         fprintf(fout, "%d  ", p->numberofvertices);
02717         for (k = 0; k < p->numberofvertices; k++) {
02718           if (((k + 1) % 10) == 0) {
02719             fprintf(fout, "\n  ");
02720           }
02721           fprintf(fout, "  %d", p->vertexlist[k]);
02722         }
02723         fprintf(fout, "\n");
02724       }
02725       // Output holes of this facet.
02726       for (j = 0; j < f->numberofholes; j++) {
02727         fprintf(fout, "%d  %.12g  %.12g  %.12g\n", j + firstnumber,
02728            f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]);
02729       }
02730     }
02731   }
02732 
02733   // Save holes.
02734   fprintf(fout, "%d\n", numberofholes);
02735   for (i = 0; i < numberofholes; i++) {
02736     // Output x, y coordinates.
02737     fprintf(fout, "%d  %.12g  %.12g", i + firstnumber, holelist[i * mesh_dim],
02738             holelist[i * mesh_dim + 1]);
02739     if (mesh_dim == 3) {
02740       // Output z coordinate.
02741       fprintf(fout, "  %.12g", holelist[i * mesh_dim + 2]);
02742     }
02743     fprintf(fout, "\n");
02744   }
02745 
02746   // Save regions.
02747   fprintf(fout, "%d\n", numberofregions);
02748   for (i = 0; i < numberofregions; i++) {
02749     if (mesh_dim == 2) {
02750       // Output the index, x, y coordinates, attribute (region number)
02751       //   and maximum area constraint (maybe -1).
02752       fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
02753               regionlist[i * 4], regionlist[i * 4 + 1],
02754               regionlist[i * 4 + 2], regionlist[i * 4 + 3]);
02755     } else {
02756       // Output the index, x, y, z coordinates, attribute (region number)
02757       //   and maximum volume constraint (maybe -1).
02758       fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
02759               regionlist[i * 5], regionlist[i * 5 + 1],
02760               regionlist[i * 5 + 2], regionlist[i * 5 + 3],
02761               regionlist[i * 5 + 4]);
02762     }
02763   }
02764 
02765   fclose(fout);  
02766 }
02767 
02769 //                                                                           //
02770 // readline()   Read a nonempty line from a file.                            //
02771 //                                                                           //
02772 // A line is considered "nonempty" if it contains something more than white  //
02773 // spaces.  If a line is considered empty, it will be dropped and the next   //
02774 // line will be read, this process ends until reaching the end-of-file or a  //
02775 // non-empty line.  Return NULL if it is the end-of-file, otherwise, return  //
02776 // a pointer to the first non-whitespace character of the line.              //
02777 //                                                                           //
02779 
02780 char* tetgenio::readline(char *string, FILE *infile, int *linenumber)
02781 {
02782   char *result;
02783 
02784   // Search for a non-empty line.
02785   do {
02786     result = fgets(string, INPUTLINESIZE - 1, infile);
02787     if (linenumber) (*linenumber)++;
02788     if (result == (char *) NULL) {
02789       return (char *) NULL;
02790     }
02791     // Skip white spaces.
02792     while ((*result == ' ') || (*result == '\t')) result++;
02793     // If it's end of line, read another line and try again.
02794   } while (*result == '\0');
02795   return result;
02796 }
02797 
02799 //                                                                           //
02800 // findnextfield()   Find the next field of a string.                        //
02801 //                                                                           //
02802 // Jumps past the current field by searching for whitespace or a comma, then //
02803 // jumps past the whitespace or the comma to find the next field.            //
02804 //                                                                           //
02806 
02807 char* tetgenio::findnextfield(char *string)
02808 {
02809   char *result;
02810 
02811   result = string;
02812   // Skip the current field.  Stop upon reaching whitespace or a comma.
02813   while ((*result != '\0') && (*result != ' ') &&  (*result != '\t') && 
02814          (*result != ',') && (*result != ';')) {
02815     result++;
02816   }
02817   // Now skip the whitespace or the comma, stop at anything else that looks
02818   //   like a character, or the end of a line. 
02819   while ((*result == ' ') || (*result == '\t') || (*result == ',') ||
02820          (*result == ';')) {
02821     result++;
02822   }
02823   return result;
02824 }
02825 
02827 //                                                                           //
02828 // readnumberline()   Read a nonempty number line from a file.               //
02829 //                                                                           //
02830 // A line is considered "nonempty" if it contains something that looks like  //
02831 // a number.  Comments (prefaced by `#') are ignored.                        //
02832 //                                                                           //
02834 
02835 char* tetgenio::readnumberline(char *string, FILE *infile, char *infilename)
02836 {
02837   char *result;
02838 
02839   // Search for something that looks like a number.
02840   do {
02841     result = fgets(string, INPUTLINESIZE, infile);
02842     if (result == (char *) NULL) {
02843       if (infilename != (char *) NULL) {
02844         printf("  Error:  Unexpected end of file in %s.\n", infilename);
02845         terminatetetgen(1);
02846       }
02847       return result;
02848     }
02849     // Skip anything that doesn't look like a number, a comment, 
02850     //   or the end of a line. 
02851     while ((*result != '\0') && (*result != '#')
02852            && (*result != '.') && (*result != '+') && (*result != '-')
02853            && ((*result < '0') || (*result > '9'))) {
02854       result++;
02855     }
02856     // If it's a comment or end of line, read another line and try again.
02857   } while ((*result == '#') || (*result == '\0'));
02858   return result;
02859 }
02860 
02862 //                                                                           //
02863 // findnextnumber()   Find the next field of a number string.                //
02864 //                                                                           //
02865 // Jumps past the current field by searching for whitespace or a comma, then //
02866 // jumps past the whitespace or the comma to find the next field that looks  //
02867 // like a number.                                                            //
02868 //                                                                           //
02870 
02871 char* tetgenio::findnextnumber(char *string)
02872 {
02873   char *result;
02874 
02875   result = string;
02876   // Skip the current field.  Stop upon reaching whitespace or a comma.
02877   while ((*result != '\0') && (*result != '#') && (*result != ' ') && 
02878          (*result != '\t') && (*result != ',')) {
02879     result++;
02880   }
02881   // Now skip the whitespace and anything else that doesn't look like a
02882   //   number, a comment, or the end of a line. 
02883   while ((*result != '\0') && (*result != '#')
02884          && (*result != '.') && (*result != '+') && (*result != '-')
02885          && ((*result < '0') || (*result > '9'))) {
02886     result++;
02887   }
02888   // Check for a comment (prefixed with `#').
02889   if (*result == '#') {
02890     *result = '\0';
02891   }
02892   return result;
02893 }
02894 
02895 //
02896 // End of class 'tetgenio' implementation
02897 //
02898 
02899 static REAL PI = 3.14159265358979323846264338327950288419716939937510582;
02900 
02901 //
02902 // Begin of class 'tetgenbehavior' implementation
02903 //
02904 
02906 //                                                                           //
02907 // tetgenbehavior()    Initialize veriables of 'tetgenbehavior'.             //
02908 //                                                                           //
02910 
02911 tetgenbehavior::tetgenbehavior()
02912 {
02913   // Initialize command line switches.
02914   plc = 0;
02915   quality = 0;
02916   refine = 0;
02917   coarse = 0;
02918   metric = 0;
02919   minratio = 2.0;
02920   goodratio = 0.0;
02921   minangle = 20.0;
02922   goodangle = 0.0;
02923   maxdihedral = 165.0;
02924   mindihedral = 5.0;
02925   varvolume = 0;
02926   fixedvolume = 0;
02927   maxvolume = -1.0;
02928   regionattrib = 0;
02929   insertaddpoints = 0;
02930   diagnose = 0;
02931   offcenter = 0;
02932   conformdel = 0;
02933   alpha1 = sqrt(2.0);
02934   alpha2 = 1.0;
02935   alpha3 = 0.6;
02936   zeroindex = 0;
02937   facesout = 0;
02938   edgesout = 0;
02939   neighout = 0;
02940   voroout = 0;
02941   meditview = 0;
02942   gidview = 0;
02943   geomview = 0;
02944   optlevel = 3;
02945   optpasses = 3;
02946   order = 1;
02947   nojettison = 0;
02948   nobound = 0;
02949   nonodewritten = 0;
02950   noelewritten = 0;
02951   nofacewritten = 0;
02952   noiterationnum = 0;
02953   nobisect = 0;
02954   noflip = 0;
02955   steiner = -1;
02956   fliprepair = 1;
02957   nomerge = 0;
02958   docheck = 0;
02959   quiet = 0;
02960   verbose = 0;
02961   useshelles = 0;
02962   epsilon = 1.0e-8;
02963   epsilon2 = 1.0e-5;
02964   object = NONE;
02965   // Initialize strings
02966   commandline[0] = '\0';
02967   infilename[0] = '\0';
02968   outfilename[0] = '\0';
02969   addinfilename[0] = '\0';
02970   bgmeshfilename[0] = '\0';
02971 }
02972 
02974 //                                                                           //
02975 // versioninfo()    Print the version information of TetGen.                 //
02976 //                                                                           //
02978 
02979 void tetgenbehavior::versioninfo()
02980 {
02981   printf("Version 1.4.2 (April 16, 2007).\n");
02982   printf("\n");
02983   printf("Copyright (C) 2002 - 2007\n");
02984   printf("Hang Si\n");
02985   printf("Mohrenstr. 39, 10117 Berlin, Germany\n");
02986   printf("si@wias-berlin.de\n");
02987 }
02988 
02990 //                                                                           //
02991 // syntax()    Print list of command line switches and exit the program.     //
02992 //                                                                           //
02994 
02995 void tetgenbehavior::syntax()
02996 {
02997   printf("  tetgen [-prq_Ra_AiMYS_T_dzo_fenvgGOJBNEFICQVh] input_file\n");
02998   printf("    -p  Tetrahedralizes a piecewise linear complex (PLC).\n");
02999   printf("    -r  Reconstructs a previously generated mesh.\n");
03000   printf("    -q  Quality mesh generation (adding new mesh points to ");
03001   printf("improve mesh quality).\n");
03002   printf("    -R  Mesh coarsening (deleting redundant mesh points).\n");
03003   printf("    -a  Applies a maximum tetrahedron volume constraint.\n");
03004   printf("    -A  Assigns attributes to identify tetrahedra in different ");
03005   printf("regions.\n");
03006   printf("    -i  Inserts a list of additional points into mesh.\n");
03007   printf("    -M  Does not merge coplanar facets.\n");
03008   printf("    -Y  Suppresses boundary facets/segments splitting.\n");
03009   printf("    -S  Specifies maximum number of added points.\n");
03010   printf("    -T  Sets a tolerance for coplanar test (default 1e-8).\n");
03011   printf("    -d  Detects self-intersections of facets of the PLC.\n");
03012   printf("    -z  Numbers all output items starting from zero.\n");
03013   printf("    -o2 Generates second-order subparametric elements.\n");
03014   printf("    -f  Outputs all faces to .face file.");
03015   printf("file.\n");
03016   printf("    -e  Outputs all edges to .edge file.\n");
03017   printf("    -n  Outputs tetrahedra neighbors to .neigh file.\n");
03018   printf("    -v  Outputs Voronoi diagram to files.\n");
03019   printf("    -g  Outputs mesh to .mesh file for viewing by Medit.\n");
03020   printf("    -G  Outputs mesh to .msh file for viewing by Gid.\n");
03021   printf("    -O  Outputs mesh to .off file for viewing by Geomview.\n");
03022   printf("    -J  No jettison of unused vertices from output .node file.\n");
03023   printf("    -B  Suppresses output of boundary information.\n");
03024   printf("    -N  Suppresses output of .node file.\n");
03025   printf("    -E  Suppresses output of .ele file.\n");
03026   printf("    -F  Suppresses output of .face file.\n");
03027   printf("    -I  Suppresses mesh iteration numbers.\n");
03028   printf("    -C  Checks the consistency of the final mesh.\n");
03029   printf("    -Q  Quiet:  No terminal output except errors.\n");
03030   printf("    -V  Verbose:  Detailed information, more terminal output.\n");
03031   printf("    -h  Help:  A brief instruction for using TetGen.\n");
03032 }
03033 
03035 //                                                                           //
03036 // usage()    Print a brief instruction for using TetGen.                    //
03037 //                                                                           //
03039 
03040 void tetgenbehavior::usage()
03041 {
03042   printf("TetGen\n");
03043   printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
03044   printf("Triangulator\n");
03045   versioninfo();
03046   printf("\n");
03047   printf("What Can TetGen Do?\n");
03048   printf("\n");
03049   printf("  TetGen generates exact Delaunay tetrahedralizations, exact\n");
03050   printf("  constrained Delaunay tetrahedralizations, and quality ");
03051   printf("tetrahedral\n  meshes. The latter are nicely graded and whose ");
03052   printf("tetrahedra have\n  radius-edge ratio bounded, thus are suitable ");
03053   printf("for finite element and\n  finite volume analysis.\n"); 
03054   printf("\n");
03055   printf("Command Line Syntax:\n");
03056   printf("\n");
03057   printf("  Below is the command line syntax of TetGen with a list of ");
03058   printf("short\n");
03059   printf("  descriptions. Underscores indicate that numbers may optionally\n");
03060   printf("  follow certain switches.  Do not leave any space between a ");
03061   printf("switch\n");
03062   printf("  and its numeric parameter.  \'input_file\' contains input data\n");
03063   printf("  depending on the switches you supplied which may be a ");
03064   printf("  piecewise\n");
03065   printf("  linear complex or a list of nodes.  File formats and detailed\n");
03066   printf("  description of command line switches are found in user's ");
03067   printf("manual.\n");
03068   printf("\n");
03069   syntax();
03070   printf("\n");
03071   printf("Examples of How to Use TetGen:\n");
03072   printf("\n");
03073   printf("  \'tetgen object\' reads vertices from object.node, and writes ");
03074   printf("their\n  Delaunay tetrahedralization to object.1.node and ");
03075   printf("object.1.ele.\n");
03076   printf("\n");
03077   printf("  \'tetgen -p object\' reads a PLC from object.poly or object.");
03078   printf("smesh (and\n  possibly object.node) and writes its constrained ");
03079   printf("Delaunay\n  tetrahedralization to object.1.node, object.1.ele and ");
03080   printf("object.1.face.\n");
03081   printf("\n");
03082   printf("  \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
03083   printf("  object.smesh (and possibly object.node), generates a mesh ");
03084   printf("whose\n  tetrahedra have radius-edge ratio smaller than 1.414 and ");
03085   printf("have volume\n  of 0.1 or less, and writes the mesh to ");
03086   printf("object.1.node, object.1.ele\n  and object.1.face.\n");
03087   printf("\n");
03088   printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
03089 }
03090 
03092 //                                                                           //
03093 // parse_commandline()    Read the command line, identify switches, and set  //
03094 //                        up options and file names.                         //
03095 //                                                                           //
03096 // 'argc' and 'argv' are the same parameters passed to the function main()   //
03097 // of a C/C++ program. They together represent the command line user invoked //
03098 // from an environment in which TetGen is running.                           //
03099 //                                                                           //
03100 // When TetGen is invoked from an environment. 'argc' is nonzero, switches   //
03101 // and input filename should be supplied as zero-terminated strings in       //
03102 // argv[0] through argv[argc - 1] and argv[0] shall be the name used to      //
03103 // invoke TetGen, i.e. "tetgen".  Switches are previously started with a     //
03104 // dash '-' to identify them from the input filename.                        //
03105 //                                                                           //
03106 // When TetGen is called from within another program. 'argc' is set to zero. //
03107 // switches are given in one zero-terminated string (no previous dash is     //
03108 // required.), and 'argv' is a pointer points to this string.  No input      //
03109 // filename is required (usually the input data has been directly created by //
03110 // user in the 'tetgenio' structure).  A default filename 'tetgen-tmpfile'   //
03111 // will be created for debugging output purpose.                             //
03112 //                                                                           //
03114 
03115 bool tetgenbehavior::parse_commandline(int argc, char **argv)
03116 {
03117   int startindex;
03118   int increment;
03119   int meshnumber;
03120   int scount;
03121   int i, j, k;
03122   char workstring[1024];
03123 
03124   // First determine the input style of the switches.
03125   if (argc == 0) {
03126     startindex = 0;                    // Switches are given without a dash.
03127     argc = 1;                    // For running the following for-loop once.
03128     commandline[0] = '\0';
03129   } else {
03130     startindex = 1;
03131     strcpy(commandline, argv[0]);
03132     strcat(commandline, " ");
03133   }
03134   
03135   // Rcount used to count the number of '-R' be used.
03136   scount = 0;
03137 
03138   for (i = startindex; i < argc; i++) {
03139     // Remember the command line switches.
03140     strcat(commandline, argv[i]);
03141     strcat(commandline, " ");
03142     if (startindex == 1) {
03143       // Is this string a filename?
03144       if (argv[i][0] != '-') {
03145         strncpy(infilename, argv[i], 1024 - 1);
03146         infilename[1024 - 1] = '\0';
03147         // Go to the next string directly.
03148         continue;                     
03149       }
03150     }
03151     // Parse the individual switch from the string.
03152     for (j = startindex; argv[i][j] != '\0'; j++) {
03153       if (argv[i][j] == 'p') {
03154         plc = 1;
03155       } else if (argv[i][j] == 'r') {
03156         refine = 1;
03157       } else if (argv[i][j] == 'R') {
03158         coarse = 1;
03159       } else if (argv[i][j] == 'q') {
03160         quality++;
03161         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03162             (argv[i][j + 1] == '.')) {
03163           k = 0;
03164           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03165                  (argv[i][j + 1] == '.')) {
03166             j++;
03167             workstring[k] = argv[i][j];
03168             k++;
03169           }
03170           workstring[k] = '\0';
03171           if (quality == 1) {
03172             minratio = (REAL) strtod(workstring, (char **) NULL);
03173           } else if (quality == 2) {
03174             mindihedral = (REAL) strtod(workstring, (char **) NULL);
03175           } else if (quality == 3) {
03176             maxdihedral = (REAL) strtod(workstring, (char **) NULL);
03177           } else if (quality == 4) {
03178             alpha2 = (REAL) strtod(workstring, (char **) NULL);
03179           } else if (quality == 5) {
03180             alpha1 = (REAL) strtod(workstring, (char **) NULL);
03181           }
03182         }
03183       } else if (argv[i][j] == 'm') {
03184         metric++;
03185         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03186             (argv[i][j + 1] == '.')) {
03187           k = 0;
03188           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03189                  (argv[i][j + 1] == '.')) {
03190             j++;
03191             workstring[k] = argv[i][j];
03192             k++;
03193           }
03194           workstring[k] = '\0';
03195           if (metric == 1) {
03196             alpha1 = (REAL) strtod(workstring, (char **) NULL);
03197           } else if (metric == 2) {
03198             alpha2 = (REAL) strtod(workstring, (char **) NULL);
03199           }
03200         }
03201       } else if (argv[i][j] == 'a') {
03202         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03203             (argv[i][j + 1] == '.')) {
03204           fixedvolume = 1;
03205           k = 0;
03206           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03207                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03208                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03209             j++;
03210             workstring[k] = argv[i][j];
03211             k++;
03212           }
03213           workstring[k] = '\0';
03214           maxvolume = (REAL) strtod(workstring, (char **) NULL);
03215         } else {
03216           varvolume = 1;
03217         }
03218       } else if (argv[i][j] == 'A') {
03219         regionattrib++;
03220       } else if (argv[i][j] == 'i') {
03221         insertaddpoints = 1;
03222       } else if (argv[i][j] == 'd') {
03223         diagnose = 1;
03224       } else if (argv[i][j] == 'z') {
03225         zeroindex = 1;
03226       } else if (argv[i][j] == 'f') {
03227         facesout = 1;
03228       } else if (argv[i][j] == 'e') {
03229         edgesout++;
03230       } else if (argv[i][j] == 'n') {
03231         neighout++;
03232       } else if (argv[i][j] == 'v') {
03233         voroout = 1;
03234       } else if (argv[i][j] == 'g') {
03235         meditview = 1;
03236       } else if (argv[i][j] == 'G') {
03237         gidview = 1;
03238       } else if (argv[i][j] == 'O') {
03239         geomview = 1;
03240       } else if (argv[i][j] == 'M') {
03241         nomerge = 1;
03242       } else if (argv[i][j] == 'Y') {
03243         nobisect++;
03244       } else if (argv[i][j] == 'J') {
03245         nojettison = 1;
03246       } else if (argv[i][j] == 'B') {
03247         nobound = 1;
03248       } else if (argv[i][j] == 'N') {
03249         nonodewritten = 1;
03250       } else if (argv[i][j] == 'E') {
03251         noelewritten = 1;
03252       } else if (argv[i][j] == 'F') {
03253         nofacewritten = 1;
03254       } else if (argv[i][j] == 'I') {
03255         noiterationnum = 1;
03256       } else if (argv[i][j] == 'o') {
03257         if (argv[i][j + 1] == '2') {
03258           j++;
03259           order = 2;
03260         }
03261       } else if (argv[i][j] == 'S') {
03262         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03263             (argv[i][j + 1] == '.')) {
03264           k = 0;
03265           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03266                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03267                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03268             j++;
03269             workstring[k] = argv[i][j];
03270             k++;
03271           }
03272           workstring[k] = '\0';
03273           steiner = (int) strtol(workstring, (char **) NULL, 0);
03274         } 
03275       } else if (argv[i][j] == 's') {
03276         scount++;
03277         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03278             (argv[i][j + 1] == '.')) {
03279           k = 0;
03280           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03281                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03282                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03283             j++;
03284             workstring[k] = argv[i][j];
03285             k++;
03286           }
03287           workstring[k] = '\0';
03288           if (scount == 1) {
03289             optlevel = (int) strtol(workstring, (char **) NULL, 0);
03290           } else if (scount == 2) {
03291             optpasses = (int) strtol(workstring, (char **) NULL, 0);
03292           }
03293         }
03294       } else if (argv[i][j] == 'D') {
03295         conformdel++;
03296       } else if (argv[i][j] == 'T') {
03297         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03298             (argv[i][j + 1] == '.')) {
03299           k = 0;
03300           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03301                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03302                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03303             j++;
03304             workstring[k] = argv[i][j];
03305             k++;
03306           }
03307           workstring[k] = '\0';
03308           epsilon = (REAL) strtod(workstring, (char **) NULL);
03309         } 
03310       } else if (argv[i][j] == 'C') {
03311         docheck++;
03312       } else if (argv[i][j] == 'X') {
03313         fliprepair = 0;
03314       } else if (argv[i][j] == 'Q') {
03315         quiet = 1;
03316       } else if (argv[i][j] == 'V') {
03317         verbose++;
03318       // } else if (argv[i][j] == 'v') {
03319         // versioninfo();
03320         // terminatetetgen(0);
03321       } else if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
03322                  (argv[i][j] == '?')) {
03323         usage();
03324         terminatetetgen(0);
03325       } else {
03326         printf("Warning:  Unknown switch -%c.\n", argv[i][j]);
03327       }
03328     }
03329   }
03330 
03331   if (startindex == 0) {
03332     // Set a temporary filename for debugging output.
03333     strcpy(infilename, "tetgen-tmpfile");
03334   } else {
03335     if (infilename[0] == '\0') {
03336       // No input file name. Print the syntax and exit.
03337       syntax();
03338       terminatetetgen(0);
03339     }
03340     // Recognize the object from file extension if it is available.
03341     if (!strcmp(&infilename[strlen(infilename) - 5], ".node")) {
03342       infilename[strlen(infilename) - 5] = '\0';
03343       object = NODES;
03344     } else if (!strcmp(&infilename[strlen(infilename) - 5], ".poly")) {
03345       infilename[strlen(infilename) - 5] = '\0';
03346       object = POLY;
03347       plc = 1;
03348     } else if (!strcmp(&infilename[strlen(infilename) - 6], ".smesh")) {
03349       infilename[strlen(infilename) - 6] = '\0';
03350       object = POLY;
03351       plc = 1;
03352     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".off")) {
03353       infilename[strlen(infilename) - 4] = '\0';
03354       object = OFF;
03355       plc = 1;
03356     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ply")) {
03357       infilename[strlen(infilename) - 4] = '\0';
03358       object = PLY;
03359       plc = 1;
03360     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".stl")) {
03361       infilename[strlen(infilename) - 4] = '\0';
03362       object = STL;
03363       plc = 1;
03364     } else if (!strcmp(&infilename[strlen(infilename) - 5], ".mesh")) {
03365       infilename[strlen(infilename) - 5] = '\0';
03366       object = MEDIT;
03367       plc = 1;
03368     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ele")) {
03369       infilename[strlen(infilename) - 4] = '\0';
03370       object = MESH;
03371       refine = 1;
03372     }
03373   }
03374   plc = plc || diagnose;
03375   useshelles = plc || refine || coarse || quality;
03376   goodratio = minratio;
03377   goodratio *= goodratio;
03378 
03379   // Detect improper combinations of switches.
03380   if (plc && refine) {
03381     printf("Error:  Switch -r cannot use together with -p.\n");
03382     return false;
03383   }
03384   if (refine && (plc || noiterationnum)) {
03385     printf("Error:  Switches %s cannot use together with -r.\n",
03386            "-p, -d, and -I");
03387     return false;
03388   }
03389   if (diagnose && (quality || insertaddpoints || (order == 2) || neighout
03390       || docheck)) {
03391     printf("Error:  Switches %s cannot use together with -d.\n",
03392            "-q, -i, -o2, -n, and -C");
03393     return false;
03394   }
03395 
03396   // Be careful not to allocate space for element area constraints that 
03397   //   will never be assigned any value (other than the default -1.0).
03398   if (!refine && !plc) {
03399     varvolume = 0;
03400   }
03401   // Be careful not to add an extra attribute to each element unless the
03402   //   input supports it (PLC in, but not refining a preexisting mesh).
03403   if (refine || !plc) {
03404     regionattrib = 0;
03405   }
03406   // If '-a' or '-aa' is in use, enable '-q' option too.
03407   if (fixedvolume || varvolume) {
03408     if (quality == 0) {
03409       quality = 1;
03410     }
03411   }
03412   // Calculate the goodangle for testing bad subfaces.
03413   goodangle = cos(minangle * PI / 180.0);
03414   goodangle *= goodangle;
03415 
03416   increment = 0;
03417   strcpy(workstring, infilename);
03418   j = 1;
03419   while (workstring[j] != '\0') {
03420     if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
03421       increment = j + 1;
03422     }
03423     j++;
03424   }
03425   meshnumber = 0;
03426   if (increment > 0) {
03427     j = increment;
03428     do {
03429       if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
03430         meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
03431       } else {
03432         increment = 0;
03433       }
03434       j++;
03435     } while (workstring[j] != '\0');
03436   }
03437   if (noiterationnum) {
03438     strcpy(outfilename, infilename);
03439   } else if (increment == 0) {
03440     strcpy(outfilename, infilename);
03441     strcat(outfilename, ".1");
03442   } else {
03443     workstring[increment] = '%';
03444     workstring[increment + 1] = 'd';
03445     workstring[increment + 2] = '\0';
03446     sprintf(outfilename, workstring, meshnumber + 1);
03447   }
03448   // Additional input file name has the end ".a".
03449   strcpy(addinfilename, infilename);
03450   strcat(addinfilename, ".a");
03451   // Background filename has the form "*.b.ele", "*.b.node", ...
03452   strcpy(bgmeshfilename, infilename);
03453   strcat(bgmeshfilename, ".b");
03454 
03455   return true;
03456 }
03457 
03458 //
03459 // End of class 'tetgenbehavior' implementation
03460 //
03461 
03462 //
03463 // Begin of class 'tetgenmesh' implementation
03464 //
03465 
03466 //
03467 // Begin of class 'list', 'memorypool' and 'link' implementation
03468 //
03469 
03470 // Following are predefined compare functions for primitive data types. 
03471 //   These functions take two pointers of the corresponding date type,
03472 //   perform the comparation. Return -1, 0 or 1 indicating the default
03473 //   linear order of two operators.
03474 
03475 // Compare two 'integers'.
03476 int tetgenmesh::compare_2_ints(const void* x, const void* y) {
03477   if (* (int *) x < * (int *) y) {
03478     return -1;
03479   } else if (* (int *) x > * (int *) y) {
03480     return 1;
03481   } else {
03482     return 0;
03483   }
03484 }
03485 
03486 // Compare two 'longs'.  Note: in 64-bit machine the 'long' type is 64-bit
03487 //   (8-byte) where the 'int' only 32-bit (4-byte).
03488 int tetgenmesh::compare_2_longs(const void* x, const void* y) {
03489   if (* (long *) x < * (long *) y) {
03490     return -1;
03491   } else if (* (long *) x > * (long *) y) {
03492     return 1;
03493   } else {
03494     return 0;
03495   }
03496 }
03497 
03498 // Compare two 'unsigned longs'.
03499 int tetgenmesh::compare_2_unsignedlongs(const void* x, const void* y) {
03500   if (* (unsigned long *) x < * (unsigned long *) y) {
03501     return -1;
03502   } else if (* (unsigned long *) x > * (unsigned long *) y) {
03503     return 1;
03504   } else {
03505     return 0;
03506   }
03507 }
03508 
03510 //                                                                           //
03511 // set_compfunc()    Determine the size of primitive data types and set the  //
03512 //                   corresponding predefined linear order functions.        //
03513 //                                                                           //
03514 // 'str' is a zero-end string indicating a primitive data type, like 'int',  //
03515 // 'long' or 'unsigned long'.  Every string ending with a '*' is though as a //
03516 // type of pointer and the type 'unsign long' is used for it.                //
03517 //                                                                           //
03518 // When the type of 'str' is determined, the size of this type (in byte) is  //
03519 // returned in 'itbytes', and the pointer of corresponding predefined linear //
03520 // order functions is returned in 'pcomp'.                                   //
03521 //                                                                           //
03523 
03524 void tetgenmesh::set_compfunc(char* str, int* itbytes, compfunc* pcomp)
03525 {
03526   // First figure out whether it is a pointer or not.
03527   if (str[strlen(str) - 1] == '*') {
03528     *itbytes = sizeof(unsigned long);
03529     *pcomp = &compare_2_unsignedlongs;
03530     return;
03531   }
03532   // Then determine other types.
03533   if (strcmp(str, "int") == 0) {
03534     *itbytes = sizeof(int);
03535     *pcomp = &compare_2_ints;
03536   } else if (strcmp(str, "long") == 0) {
03537     *itbytes = sizeof(long);
03538     *pcomp = &compare_2_longs;
03539   } else if (strcmp(str, "unsigned long") == 0) {
03540     *itbytes = sizeof(unsigned long);
03541     *pcomp = &compare_2_unsignedlongs;
03542   } else {
03543     // It is an unknown type.
03544     printf("Error in set_compfunc():  unknown type %s.\n", str);
03545     terminatetetgen(1);
03546   }
03547 }
03548 
03550 //                                                                           //
03551 // listinit()    Initialize a list for storing a data type.                  //
03552 //                                                                           //
03553 // Determine the size of each item, set the maximum size allocated at onece, //
03554 // set the expand size in case the list is full, and set the linear order    //
03555 // function if it is provided (default is NULL).                             //
03556 //                                                                           //
03558 
03559 void tetgenmesh::list::
03560 listinit(int itbytes, compfunc pcomp, int mitems,int exsize)
03561 {
03562 #ifdef SELF_CHECK
03563   assert(itbytes > 0 && mitems > 0 && exsize > 0);
03564 #endif
03565   itembytes = itbytes;
03566   comp = pcomp;
03567   maxitems = mitems;
03568   expandsize = exsize;
03569   base = (char *) malloc(maxitems * itembytes); 
03570   if (base == (char *) NULL) {
03571     printf("Error:  Out of memory.\n");
03572     terminatetetgen(1);
03573   }
03574   items = 0;
03575 }
03576 
03578 //                                                                           //
03579 // append()    Add a new item at the end of the list.                        //
03580 //                                                                           //
03581 // A new space at the end of this list will be allocated for storing the new //
03582 // item. If the memory is not sufficient, reallocation will be performed. If //
03583 // 'appitem' is not NULL, the contents of this pointer will be copied to the //
03584 // new allocated space.  Returns the pointer to the new allocated space.     //
03585 //                                                                           //
03587 
03588 void* tetgenmesh::list::append(void *appitem)
03589 {
03590   // Do we have enough space?
03591   if (items == maxitems) {
03592     char* newbase = (char *) realloc(base, (maxitems + expandsize) * 
03593                                      itembytes);
03594     if (newbase == (char *) NULL) {
03595       printf("Error:  Out of memory.\n");
03596       terminatetetgen(1);
03597     }
03598     base = newbase;
03599     maxitems += expandsize;
03600   }
03601   if (appitem != (void *) NULL) {
03602     memcpy(base + items * itembytes, appitem, itembytes);
03603   }
03604   items++;
03605   return (void *) (base + (items - 1) * itembytes);
03606 }
03607 
03609 //                                                                           //
03610 // insert()    Insert an item before 'pos' (range from 0 to items - 1).      //
03611 //                                                                           //
03612 // A new space will be inserted at the position 'pos', that is, items lie    //
03613 // after pos (including the item at pos) will be moved one space downwords.  //
03614 // If 'insitem' is not NULL, its contents will be copied into the new        //
03615 // inserted space. Return a pointer to the new inserted space.               //
03616 //                                                                           //
03618 
03619 void* tetgenmesh::list::insert(int pos, void* insitem)
03620 {
03621   if (pos >= items) {
03622     return append(insitem);
03623   }
03624   // Do we have enough space.
03625   if (items == maxitems) {
03626     char* newbase = (char *) realloc(base, (maxitems + expandsize) *
03627                                      itembytes);
03628     if (newbase == (char *) NULL) {
03629       printf("Error:  Out of memory.\n");
03630       terminatetetgen(1);
03631     }
03632     base = newbase;
03633     maxitems += expandsize;
03634   }
03635   // Do block move.
03636   memmove(base + (pos + 1) * itembytes,   // dest
03637           base + pos * itembytes,         // src
03638           (items - pos) * itembytes);     // size in bytes
03639   // Insert the item.
03640   if (insitem != (void *) NULL) {
03641     memcpy(base + pos * itembytes, insitem, itembytes);
03642   }
03643   items++;
03644   return (void *) (base + pos * itembytes);
03645 }
03646 
03648 //                                                                           //
03649 // del()    Delete an item at 'pos' (range from 0 to items - 1).             //
03650 //                                                                           //
03651 // The space at 'pos' will be overlapped by other item. If 'order' is 1, the //
03652 // remaining items of the list have the same order as usual, i.e., items lie //
03653 // after pos will be moved one space upwords. If 'order' is 0, the last item //
03654 // of the list will be moved up to pos.                                      //
03655 //                                                                           //
03657 
03658 void tetgenmesh::list::del(int pos, int order)
03659 {
03660   // If 'pos' is the last item of the list, nothing need to do.
03661   if (pos >= 0 && pos < items - 1) {
03662     if (order == 1) {
03663       // Do block move. 
03664       memmove(base + pos * itembytes,       // dest
03665               base + (pos + 1) * itembytes, // src
03666               (items - pos - 1) * itembytes);
03667     } else {
03668       // Use the last item to overlap the del item.
03669       memcpy(base + pos * itembytes, // item at pos
03670              base + (items - 1) * itembytes, // item at last
03671              itembytes);
03672     }
03673   }
03674   if (items > 0) {
03675     items--;
03676   }
03677 }
03678 
03680 //                                                                           //
03681 // hasitem()    Search in this list to find if 'checkitem' exists.           //
03682 //                                                                           //
03683 // This routine assumes that a linear order function has been set.  It loops //
03684 // through the entire list, compares each item to 'checkitem'. If it exists, //
03685 // return its position (between 0 to items - 1), otherwise, return -1.       //
03686 //                                                                           //
03688 
03689 int tetgenmesh::list::hasitem(void* checkitem)
03690 {
03691   int i;
03692 
03693   for (i = 0; i < items; i++) {
03694     if (comp != (compfunc) NULL) {
03695       if ((* comp)((void *)(base + i * itembytes), checkitem) == 0) {
03696         return i;
03697       }
03698     }
03699   }
03700   return -1;
03701 }
03702 
03704 //                                                                           //
03705 // sort()    Sort the items with respect to a linear order function.         //
03706 //                                                                           //
03707 // Uses QuickSort routines (qsort) of the standard C/C++ library (stdlib.h). //
03708 //                                                                           //
03710 
03711 void tetgenmesh::list::sort()
03712 {
03713   qsort((void *) base, (size_t) items, (size_t) itembytes, comp);
03714 }
03715 
03717 //                                                                           //
03718 // memorypool()   The constructors of memorypool.                            //
03719 //                                                                           //
03721 
03722 tetgenmesh::memorypool::memorypool()
03723 {
03724   firstblock = nowblock = (void **) NULL;
03725   nextitem = (void *) NULL;
03726   deaditemstack = (void *) NULL;
03727   pathblock = (void **) NULL;
03728   pathitem = (void *) NULL;
03729   itemwordtype = POINTER;
03730   alignbytes = 0;
03731   itembytes = itemwords = 0;
03732   itemsperblock = 0;
03733   items = maxitems = 0l;
03734   unallocateditems = 0;
03735   pathitemsleft = 0;
03736 }
03737 
03738 tetgenmesh::memorypool::
03739 memorypool(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03740 {
03741   poolinit(bytecount, itemcount, wtype, alignment);
03742 }
03743 
03745 //                                                                           //
03746 // ~memorypool()   Free to the operating system all memory taken by a pool.  //
03747 //                                                                           //
03749 
03750 tetgenmesh::memorypool::~memorypool()
03751 {
03752   while (firstblock != (void **) NULL) {
03753     nowblock = (void **) *(firstblock);
03754     free(firstblock);
03755     firstblock = nowblock;
03756   }
03757 }
03758 
03760 //                                                                           //
03761 // poolinit()    Initialize a pool of memory for allocation of items.        //
03762 //                                                                           //
03763 // A `pool' is created whose records have size at least `bytecount'.  Items  //
03764 // will be allocated in `itemcount'-item blocks.  Each item is assumed to be //
03765 // a collection of words, and either pointers or floating-point values are   //
03766 // assumed to be the "primary" word type.  (The "primary" word type is used  //
03767 // to determine alignment of items.)  If `alignment' isn't zero, all items   //
03768 // will be `alignment'-byte aligned in memory.  `alignment' must be either a //
03769 // multiple or a factor of the primary word size;  powers of two are safe.   //
03770 // `alignment' is normally used to create a few unused bits at the bottom of //
03771 // each item's pointer, in which information may be stored.                  //
03772 //                                                                           //
03774 
03775 void tetgenmesh::memorypool::
03776 poolinit(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03777 {
03778   int wordsize;
03779 
03780   // Initialize values in the pool.
03781   itemwordtype = wtype;
03782   wordsize = (itemwordtype == POINTER) ? sizeof(void *) : sizeof(REAL);
03783   // Find the proper alignment, which must be at least as large as:
03784   //   - The parameter `alignment'.
03785   //   - The primary word type, to avoid unaligned accesses.
03786   //   - sizeof(void *), so the stack of dead items can be maintained
03787   //       without unaligned accesses.
03788   if (alignment > wordsize) {
03789     alignbytes = alignment;
03790   } else {
03791     alignbytes = wordsize;
03792   }
03793   if ((int) sizeof(void *) > alignbytes) {
03794     alignbytes = (int) sizeof(void *);
03795   }
03796   itemwords = ((bytecount + alignbytes - 1) /  alignbytes)
03797             * (alignbytes / wordsize);
03798   itembytes = itemwords * wordsize;
03799   itemsperblock = itemcount;
03800 
03801   // Allocate a block of items.  Space for `itemsperblock' items and one
03802   //   pointer (to point to the next block) are allocated, as well as space
03803   //   to ensure alignment of the items. 
03804   firstblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *)
03805                                 + alignbytes); 
03806   if (firstblock == (void **) NULL) {
03807     printf("Error:  Out of memory.\n");
03808     terminatetetgen(1);
03809   }
03810   // Set the next block pointer to NULL.
03811   *(firstblock) = (void *) NULL;
03812   restart();
03813 }
03814 
03816 //                                                                           //
03817 // restart()   Deallocate all items in this pool.                            //
03818 //                                                                           //
03819 // The pool is returned to its starting state, except that no memory is      //
03820 // freed to the operating system.  Rather, the previously allocated blocks   //
03821 // are ready to be reused.                                                   //
03822 //                                                                           //
03824 
03825 void tetgenmesh::memorypool::restart()
03826 {
03827   unsigned long alignptr;
03828 
03829   items = 0;
03830   maxitems = 0;
03831 
03832   // Set the currently active block.
03833   nowblock = firstblock;
03834   // Find the first item in the pool.  Increment by the size of (void *).
03835   alignptr = (unsigned long) (nowblock + 1);
03836   // Align the item on an `alignbytes'-byte boundary.
03837   nextitem = (void *)
03838     (alignptr + (unsigned long) alignbytes -
03839      (alignptr % (unsigned long) alignbytes));
03840   // There are lots of unallocated items left in this block.
03841   unallocateditems = itemsperblock;
03842   // The stack of deallocated items is empty.
03843   deaditemstack = (void *) NULL;
03844 }
03845 
03847 //                                                                           //
03848 // alloc()   Allocate space for an item.                                     //
03849 //                                                                           //
03851 
03852 void* tetgenmesh::memorypool::alloc()
03853 {
03854   void *newitem;
03855   void **newblock;
03856   unsigned long alignptr;
03857 
03858   // First check the linked list of dead items.  If the list is not 
03859   //   empty, allocate an item from the list rather than a fresh one.
03860   if (deaditemstack != (void *) NULL) {
03861     newitem = deaditemstack;                     // Take first item in list.
03862     deaditemstack = * (void **) deaditemstack;
03863   } else {
03864     // Check if there are any free items left in the current block.
03865     if (unallocateditems == 0) {
03866       // Check if another block must be allocated.
03867       if (*nowblock == (void *) NULL) {
03868         // Allocate a new block of items, pointed to by the previous block.
03869         newblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *) 
03870                                     + alignbytes);
03871         if (newblock == (void **) NULL) {
03872           printf("Error:  Out of memory.\n");
03873           terminatetetgen(1);
03874         }
03875         *nowblock = (void *) newblock;
03876         // The next block pointer is NULL.
03877         *newblock = (void *) NULL;
03878       }
03879       // Move to the new block.
03880       nowblock = (void **) *nowblock;
03881       // Find the first item in the block.
03882       //   Increment by the size of (void *).
03883       alignptr = (unsigned long) (nowblock + 1);
03884       // Align the item on an `alignbytes'-byte boundary.
03885       nextitem = (void *)
03886         (alignptr + (unsigned long) alignbytes -
03887          (alignptr % (unsigned long) alignbytes));
03888       // There are lots of unallocated items left in this block.
03889       unallocateditems = itemsperblock;
03890     }
03891     // Allocate a new item.
03892     newitem = nextitem;
03893     // Advance `nextitem' pointer to next free item in block.
03894     if (itemwordtype == POINTER) {
03895       nextitem = (void *) ((void **) nextitem + itemwords);
03896     } else {
03897       nextitem = (void *) ((REAL *) nextitem + itemwords);
03898     }
03899     unallocateditems--;
03900     maxitems++;
03901   }
03902   items++;
03903   return newitem;
03904 }
03905 
03907 //                                                                           //
03908 // dealloc()   Deallocate space for an item.                                 //
03909 //                                                                           //
03910 // The deallocated space is stored in a queue for later reuse.               //
03911 //                                                                           //
03913 
03914 void tetgenmesh::memorypool::dealloc(void *dyingitem)
03915 {
03916   // Push freshly killed item onto stack.
03917   *((void **) dyingitem) = deaditemstack;
03918   deaditemstack = dyingitem;
03919   items--;
03920 }
03921 
03923 //                                                                           //
03924 // traversalinit()   Prepare to traverse the entire list of items.           //
03925 //                                                                           //
03926 // This routine is used in conjunction with traverse().                      //
03927 //                                                                           //
03929 
03930 void tetgenmesh::memorypool::traversalinit()
03931 {
03932   unsigned long alignptr;
03933 
03934   // Begin the traversal in the first block.
03935   pathblock = firstblock;
03936   // Find the first item in the block.  Increment by the size of (void *).
03937   alignptr = (unsigned long) (pathblock + 1);
03938   // Align with item on an `alignbytes'-byte boundary.
03939   pathitem = (void *)
03940     (alignptr + (unsigned long) alignbytes -
03941      (alignptr % (unsigned long) alignbytes));
03942   // Set the number of items left in the current block.
03943   pathitemsleft = itemsperblock;
03944 }
03945 
03947 //                                                                           //
03948 // traverse()   Find the next item in the list.                              //
03949 //                                                                           //
03950 // This routine is used in conjunction with traversalinit().  Be forewarned  //
03951 // that this routine successively returns all items in the list, including   //
03952 // deallocated ones on the deaditemqueue. It's up to you to figure out which //
03953 // ones are actually dead.  It can usually be done more space-efficiently by //
03954 // a routine that knows something about the structure of the item.           //
03955 //                                                                           //
03957 
03958 void* tetgenmesh::memorypool::traverse()
03959 {
03960   void *newitem;
03961   unsigned long alignptr;
03962 
03963   // Stop upon exhausting the list of items.
03964   if (pathitem == nextitem) {
03965     return (void *) NULL;
03966   }
03967   // Check whether any untraversed items remain in the current block.
03968   if (pathitemsleft == 0) {
03969     // Find the next block.
03970     pathblock = (void **) *pathblock;
03971     // Find the first item in the block.  Increment by the size of (void *).
03972     alignptr = (unsigned long) (pathblock + 1);
03973     // Align with item on an `alignbytes'-byte boundary.
03974     pathitem = (void *)
03975       (alignptr + (unsigned long) alignbytes -
03976        (alignptr % (unsigned long) alignbytes));
03977     // Set the number of items left in the current block.
03978     pathitemsleft = itemsperblock;
03979   }
03980   newitem = pathitem;
03981   // Find the next item in the block.
03982   if (itemwordtype == POINTER) {
03983     pathitem = (void *) ((void **) pathitem + itemwords);
03984   } else {
03985     pathitem = (void *) ((REAL *) pathitem + itemwords);
03986   }
03987   pathitemsleft--;
03988   return newitem;
03989 }
03990 
03992 //                                                                           //
03993 // linkinit()    Initialize a link for storing items.                        //
03994 //                                                                           //
03995 // The input parameters are the size of each item, a pointer of a linear     //
03996 // order function and the number of items allocating in one memory bulk.     //
03997 //                                                                           //
03999 
04000 void tetgenmesh::link::linkinit(int bytecount, compfunc pcomp, int itemcount)
04001 {
04002 #ifdef SELF_CHECK
04003   assert(bytecount > 0 && itemcount > 0);
04004 #endif
04005   // Remember the real size of each item.
04006   linkitembytes = bytecount;
04007   // Set the linear order function for this link.
04008   comp = pcomp;
04009 
04010   // Call the constructor of 'memorypool' to initialize its variables.
04011   //   like: itembytes, itemwords, items, ... Each node has size
04012   //   bytecount + 2 * sizeof(void **), and total 'itemcount + 2' (because
04013   //   link has additional two nodes 'head' and 'tail').
04014   poolinit(bytecount + 2 * sizeof(void **), itemcount + 2, POINTER, 0);
04015   
04016   // Initial state of this link.
04017   head = (void **) alloc();
04018   tail = (void **) alloc();
04019   *head = (void *) tail;
04020   *(head + 1) = NULL;
04021   *tail = NULL;
04022   *(tail + 1) = (void *) head;
04023   nextlinkitem = *head;
04024   curpos = 1;
04025   linkitems = 0;
04026 }
04027 
04029 //                                                                           //
04030 // clear()   Deallocate all nodes in this link.                              //
04031 //                                                                           //
04032 // The link is returned to its starting state, except that no memory is      //
04033 // freed to the operating system.  Rather, the previously allocated blocks   //
04034 // are ready to be reused.                                                   //
04035 //                                                                           //
04037 
04038 void tetgenmesh::link::clear()
04039 {
04040   // Reset the pool.
04041   restart();
04042 
04043   // Initial state of this link.
04044   head = (void **) alloc();
04045   tail = (void **) alloc();
04046   *head = (void *) tail;
04047   *(head + 1) = NULL;
04048   *tail = NULL;
04049   *(tail + 1) = (void *) head;
04050   nextlinkitem = *head;
04051   curpos = 1;
04052   linkitems = 0;
04053 }
04054 
04056 //                                                                           //
04057 // move()    Causes 'nextlinkitem' to traverse the specified number of nodes,//
04058 //           updates 'curpos' to be the node to which 'nextlinkitem' points. //
04059 //                                                                           //
04060 // 'numberofnodes' is a number indicating how many nodes need be traversed   //
04061 // (not counter the current node) need be traversed. It may be positive(move //
04062 // forward) or negative (move backward).  Return TRUE if it is successful.   //
04063 //                                                                           //
04065 
04066 bool tetgenmesh::link::move(int numberofnodes)
04067 {
04068   void **nownode;
04069   int i;
04070 
04071   nownode = (void **) nextlinkitem;
04072   if (numberofnodes > 0) {
04073     // Move forward.
04074     i = 0;
04075     while ((i < numberofnodes) && *nownode) {
04076       nownode = (void **) *nownode;
04077       i++;
04078     }
04079     if (*nownode == NULL) return false;
04080     nextlinkitem = (void *) nownode;
04081     curpos += numberofnodes;
04082   } else if (numberofnodes < 0) {
04083     // Move backward.
04084     i = 0;
04085     numberofnodes = -numberofnodes;
04086     while ((i < numberofnodes) && *(nownode + 1)) {
04087       nownode = (void **) *(nownode + 1);
04088       i++;
04089     }
04090     if (*(nownode + 1) == NULL) return false;
04091     nextlinkitem = (void *) nownode;
04092     curpos -= numberofnodes;
04093   }
04094   return true;
04095 }
04096 
04098 //                                                                           //
04099 // locate()    Locates the node at the specified position.                   //
04100 //                                                                           //
04101 // The number 'pos' (between 1 and 'linkitems') indicates the location. This //
04102 // routine first decides the shortest path traversing from 'curpos' to 'pos',//
04103 // i.e., from head, tail or 'curpos'.   Routine 'move()' is called to really //
04104 // traverse the link. If success, 'nextlinkitem' points to the node, 'curpos'//
04105 // and 'pos' are equal. Otherwise, return FALSE.                             //
04106 //                                                                           //
04108 
04109 bool tetgenmesh::link::locate(int pos)
04110 {
04111   int headdist, taildist, curdist;
04112   int abscurdist, mindist;
04113 
04114   if (pos < 1 || pos > linkitems) return false;
04115 
04116   headdist = pos - 1;
04117   taildist = linkitems - pos;
04118   curdist = pos - curpos;
04119   abscurdist = curdist >= 0 ? curdist : -curdist;
04120 
04121   if (headdist > taildist) {
04122     if (taildist > abscurdist) {
04123       mindist = curdist;
04124     } else {
04125       // taildist <= abs(curdist)
04126       mindist = -taildist;
04127       goend();
04128     }
04129   } else {
04130     // headdist <= taildist
04131     if (headdist > abscurdist) {
04132       mindist = curdist;
04133     } else {
04134       // headdist <= abs(curdist)
04135       mindist = headdist;
04136       rewind();
04137     }
04138   }
04139 
04140   return move(mindist);
04141 }
04142 
04144 //                                                                           //
04145 // add()    Add a node at the end of this link.                              //
04146 //                                                                           //
04147 // A new node is appended to the end of the link.  If 'newitem' is not NULL, //
04148 // its conents will be copied to the data slot of the new node. Returns the  //
04149 // pointer to the newest added node.                                         //
04150 //                                                                           //
04152 
04153 void* tetgenmesh::link::add(void* newitem)
04154 {
04155   void **newnode = tail;
04156   if (newitem != (void *) NULL) {
04157     memcpy((void *)(newnode + 2), newitem, linkitembytes);
04158   }
04159   tail = (void **) alloc();
04160   *tail = NULL;
04161   *newnode = (void*) tail;
04162   *(tail + 1) = (void*) newnode;
04163   linkitems++;
04164   return (void *)(newnode + 2);
04165 }
04166 
04168 //                                                                           //
04169 // insert()    Inserts a node before the specified position.                 //
04170 //                                                                           //
04171 // 'pos' (between 1 and 'linkitems') indicates the inserting position.  This //
04172 // routine inserts a new node before the node of 'pos'.  If 'newitem' is not //
04173 // NULL,  its conents will be copied into the data slot of the new node.  If //
04174 // 'pos' is larger than 'linkitems', it is equal as 'add()'.  A pointer to   //
04175 // the newest inserted item is returned.                                     //
04176 //                                                                           //
04178 
04179 void* tetgenmesh::link::insert(int pos, void* insitem)
04180 {
04181   if (!locate(pos)) {
04182     return add(insitem);
04183   }
04184 
04185   void **nownode = (void **) nextlinkitem;
04186 
04187   // Insert a node before 'nownode'.
04188   void **newnode = (void **) alloc();
04189   if (insitem != (void *) NULL) {
04190     memcpy((void *)(newnode + 2), insitem, linkitembytes);
04191   }
04192 
04193   *(void **)(*(nownode + 1)) = (void *) newnode;
04194   *newnode = (void *) nownode;
04195   *(newnode + 1) = *(nownode + 1);
04196   *(nownode + 1) = (void *) newnode;
04197 
04198   linkitems++;
04199 
04200   nextlinkitem = (void *) newnode;
04201   return (void *)(newnode + 2);
04202 }
04203 
04205 //                                                                           //
04206 // del()    Delete a node.                                                   //
04207 //                                                                           //
04208 // Returns a pointer of the deleted data. If you try to delete a non-existed //
04209 // node (e.g. link is empty or a wrong index is given) return NULL.          //
04210 //                                                                           //
04212 
04213 void* tetgenmesh::link::deletenode(void** deadnode)
04214 {
04215   void **nextnode = (void **) *deadnode;
04216   void **prevnode = (void **) *(deadnode + 1);
04217   *prevnode = (void *) nextnode;
04218   *(nextnode + 1) = (void *) prevnode;
04219 
04220   dealloc((void *) deadnode);
04221   linkitems--;
04222 
04223   nextlinkitem = (void *) nextnode;
04224   return (void *)(deadnode + 2);
04225 }
04226 
04228 //                                                                           //
04229 // del()    Delete a node at the specified position.                         //
04230 //                                                                           //
04231 // 'pos' between 1 and 'linkitems'.  Returns a pointer of the deleted data.  //
04232 // If you try to delete a non-existed node (e.g. link is empty or a wrong    //
04233 // index is given) return NULL.                                              //
04234 //                                                                           //
04236 
04237 void* tetgenmesh::link::del(int pos)
04238 {
04239   if (!locate(pos) || (linkitems == 0)) {
04240     return (void *) NULL;
04241   }
04242   return deletenode((void **) nextlinkitem);
04243 }
04244 
04246 //                                                                           //
04247 // getitem()    The link traversal routine.                                  //
04248 //                                                                           //
04249 // Returns the node to which 'nextlinkitem' points. Returns a 'NULL' if the  //
04250 // end of the link is reaching.  Both 'nextlinkitem' and 'curpos' will be    //
04251 // updated after this operation.                                             //
04252 //                                                                           //
04254 
04255 void* tetgenmesh::link::getitem()
04256 {
04257   if (nextlinkitem == (void *) tail) return NULL;
04258   void **nownode = (void **) nextlinkitem;
04259   nextlinkitem = *nownode;
04260   curpos += 1;
04261   return (void *)(nownode + 2);
04262 }
04263 
04265 //                                                                           //
04266 // getnitem()    Returns the node at a specified position.                   //
04267 //                                                                           //
04268 // 'pos' between 1 and 'linkitems'. After this operation, 'nextlinkitem' and //
04269 // 'curpos' will be updated to indicate this node.                           //
04270 //                                                                           //
04272 
04273 void* tetgenmesh::link::getnitem(int pos)
04274 {
04275   if (!locate(pos)) return NULL;
04276   return (void *)((void **) nextlinkitem + 2);
04277 }
04278 
04280 //                                                                           //
04281 // hasitem()    Search in this link to find if 'checkitem' exists.           //
04282 //                                                                           //
04283 // If 'checkitem' exists, return its position (between 1 to 'linkitems'),    //
04284 // otherwise, return -1. This routine requires the linear order function has //
04285 // been set.                                                                 //
04286 //                                                                           //
04288 
04289 int tetgenmesh::link::hasitem(void* checkitem)
04290 {
04291   void *pathitem;
04292   int count;
04293 
04294   rewind();
04295   pathitem = getitem();
04296   count = 0;
04297   while (pathitem) {
04298     count ++;
04299     if (comp) {
04300       if ((* comp)(pathitem, checkitem) == 0) {
04301         return count;
04302       }
04303     } 
04304     pathitem = getitem();
04305   }
04306   return -1;
04307 }
04308 
04309 //
04310 // End of class 'list', 'memorypool' and 'link' implementation
04311 //
04312 
04313 //
04314 // Begin of mesh manipulation primitives
04315 //
04316 
04317 //
04318 // Begin of tables initialization.
04319 //
04320 
04321 // For enumerating three edges of a triangle.
04322 
04323 int tetgenmesh::plus1mod3[3] = {1, 2, 0};
04324 int tetgenmesh::minus1mod3[3] = {2, 0, 1};
04325 
04326 // Table 've' takes an edge version as input, returns the next edge version
04327 //   in the same edge ring.
04328 
04329 int tetgenmesh::ve[6] = { 2, 5, 4, 1, 0, 3 };
04330 
04331 // Tables 'vo', 'vd' and 'va' take an edge version, return the positions of
04332 //   the origin, destination and apex in the triangle.
04333 
04334 int tetgenmesh::vo[6] = { 0, 1, 1, 2, 2, 0 };
04335 int tetgenmesh::vd[6] = { 1, 0, 2, 1, 0, 2 };
04336 int tetgenmesh::va[6] = { 2, 2, 0, 0, 1, 1 };
04337 
04338 // The following tables are for tetrahedron primitives (operate on trifaces).
04339 
04340 // For 'org()', 'dest()' and 'apex()'.  Use 'loc' as the first index and
04341 //   'ver' as the second index.
04342 
04343 int tetgenmesh::locver2org[4][6]  = {
04344   {0, 1, 1, 2, 2, 0},
04345   {0, 3, 3, 1, 1, 0},
04346   {1, 3, 3, 2, 2, 1},
04347   {2, 3, 3, 0, 0, 2} 
04348 };
04349 int tetgenmesh::locver2dest[4][6] = { 
04350   {1, 0, 2, 1, 0, 2},
04351   {3, 0, 1, 3, 0, 1},
04352   {3, 1, 2, 3, 1, 2},
04353   {3, 2, 0, 3, 2, 0}
04354 };
04355 int tetgenmesh::locver2apex[4][6] = { 
04356   {2, 2, 0, 0, 1, 1},
04357   {1, 1, 0, 0, 3, 3},
04358   {2, 2, 1, 1, 3, 3},
04359   {0, 0, 2, 2, 3, 3}
04360 };
04361 
04362 // For oppo() primitives, use 'loc' as the index.
04363 
04364 int tetgenmesh::loc2oppo[4] = { 3, 2, 0, 1 };
04365 
04366 // For fnext() primitive.  Use 'loc' as the first index and 'ver' as the
04367 //   second index. Returns a new 'loc' and new 'ver' in an array. (It is
04368 //   only valid for edge version equals one of {0, 2, 4}.)
04369 
04370 int tetgenmesh::locver2nextf[4][6][2] = {
04371   { {1, 5}, {-1, -1}, {2, 5}, {-1, -1}, {3, 5}, {-1, -1} },
04372   { {3, 3}, {-1, -1}, {2, 1}, {-1, -1}, {0, 1}, {-1, -1} },
04373   { {1, 3}, {-1, -1}, {3, 1}, {-1, -1}, {0, 3}, {-1, -1} },
04374   { {2, 3}, {-1, -1}, {1, 1}, {-1, -1}, {0, 5}, {-1, -1} }
04375 };
04376 
04377 // The edge number (from 0 to 5) of a tet is defined as follows:
04378 //   0 - (v0, v1), 1 - (v1, v2), 2 - (v2, v0)
04379 //   3 - (v3, v0), 4 - (v3, v1), 5 - (v3, v2).
04380 
04381 int tetgenmesh::locver2edge[4][6] = {
04382   {0, 0, 1, 1, 2, 2},
04383   {3, 3, 4, 4, 0, 0},
04384   {4, 4, 5, 5, 1, 1},
04385   {5, 5, 3, 3, 2, 2}
04386 };
04387 
04388 int tetgenmesh::edge2locver[6][2] = {
04389   {0, 0}, // 0  v0 -> v1
04390   {0, 2}, // 1  v1 -> v2
04391   {0, 4}, // 2  v2 -> v1
04392   {1, 0}, // 3  v0 -> v3
04393   {1, 2}, // 4  v1 -> v3
04394   {2, 2}  // 5  v2 -> v3
04395 };
04396 
04397 //
04398 // End of tables initialization.
04399 //
04400 
04401 // Some macros for convenience
04402 
04403 #define Div2  >> 1
04404 #define Mod2  & 01
04405 
04406 // NOTE: These bit operators should only be used in macros below.
04407 
04408 // Get orient(Range from 0 to 2) from face version(Range from 0 to 5).
04409 
04410 #define Orient(V)   ((V) Div2)
04411 
04412 // Determine edge ring(0 or 1) from face version(Range from 0 to 5).
04413 
04414 #define EdgeRing(V) ((V) Mod2)
04415 
04416 //
04417 // Begin of primitives for tetrahedra
04418 // 
04419 
04420 // Each tetrahedron contains four pointers to its neighboring tetrahedra,
04421 //   with face indices.  To save memory, both information are kept in a
04422 //   single pointer. To make this possible, all tetrahedra are aligned to
04423 //   eight-byte boundaries, so that the last three bits of each pointer are
04424 //   zeros. A face index (in the range 0 to 3) is compressed into the last
04425 //   two bits of each pointer by the function 'encode()'.  The function
04426 //   'decode()' decodes a pointer, extracting a face index and a pointer to
04427 //   the beginning of a tetrahedron.
04428 
04429 inline void tetgenmesh::decode(tetrahedron ptr, triface& t) {
04430   t.loc = (int) ((unsigned long) (ptr) & (unsigned long) 3l);
04431   t.tet = (tetrahedron *) ((unsigned long) (ptr) & ~(unsigned long) 7l);
04432 }
04433 
04434 inline tetgenmesh::tetrahedron tetgenmesh::encode(triface& t) {
04435   return (tetrahedron) ((unsigned long) t.tet | (unsigned long) t.loc);
04436 }
04437 
04438 // sym() finds the abutting tetrahedron on the same face.
04439 
04440 inline void tetgenmesh::sym(triface& t1, triface& t2) {
04441   tetrahedron ptr = t1.tet[t1.loc];
04442   decode(ptr, t2);
04443 }
04444 
04445 inline void tetgenmesh::symself(triface& t) {
04446   tetrahedron ptr = t.tet[t.loc];
04447   decode(ptr, t);
04448 }
04449 
04450 // Bond two tetrahedra together at their faces.
04451 
04452 inline void tetgenmesh::bond(triface& t1, triface& t2) {
04453   t1.tet[t1.loc] = encode(t2);
04454   t2.tet[t2.loc] = encode(t1);
04455 }
04456 
04457 // Dissolve a bond (from one side).  Note that the other tetrahedron will
04458 //   still think it is connected to this tetrahedron.  Usually, however,
04459 //   the other tetrahedron is being deleted entirely, or bonded to another
04460 //   tetrahedron, so it doesn't matter.
04461 
04462 inline void tetgenmesh::dissolve(triface& t) {
04463   t.tet[t.loc] = (tetrahedron) dummytet;
04464 }
04465 
04466 // These primitives determine or set the origin, destination, apex or
04467 //   opposition of a tetrahedron with respect to 'loc' and 'ver'.
04468 
04469 inline tetgenmesh::point tetgenmesh::org(triface& t) {
04470   return (point) t.tet[locver2org[t.loc][t.ver] + 4];
04471 }
04472 
04473 inline tetgenmesh::point tetgenmesh::dest(triface& t) {
04474   return (point) t.tet[locver2dest[t.loc][t.ver] + 4];
04475 }
04476 
04477 inline tetgenmesh::point tetgenmesh::apex(triface& t) {
04478   return (point) t.tet[locver2apex[t.loc][t.ver] + 4];
04479 }
04480 
04481 inline tetgenmesh::point tetgenmesh::oppo(triface& t) {
04482   return (point) t.tet[loc2oppo[t.loc] + 4];
04483 }
04484 
04485 inline void tetgenmesh::setorg(triface& t, point pointptr) {
04486   t.tet[locver2org[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04487 }
04488 
04489 inline void tetgenmesh::setdest(triface& t, point pointptr) {
04490   t.tet[locver2dest[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04491 }
04492 
04493 inline void tetgenmesh::setapex(triface& t, point pointptr) {
04494   t.tet[locver2apex[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04495 }
04496 
04497 inline void tetgenmesh::setoppo(triface& t, point pointptr) {
04498   t.tet[loc2oppo[t.loc] + 4] = (tetrahedron) pointptr;
04499 }
04500 
04501 // These primitives were drived from Mucke's triangle-edge data structure
04502 //   to change face-edge relation in a tetrahedron (esym, enext and enext2)
04503 //   or between two tetrahedra (fnext).
04504 
04505 // If e0 = e(i, j), e1 = e(j, i), that is e0 and e1 are the two directions
04506 //   of the same undirected edge of a face. e0.sym() = e1 and vice versa.
04507 
04508 inline void tetgenmesh::esym(triface& t1, triface& t2) {
04509   t2.tet = t1.tet;
04510   t2.loc = t1.loc;
04511   t2.ver = t1.ver + (EdgeRing(t1.ver) ? -1 : 1);
04512 }
04513 
04514 inline void tetgenmesh::esymself(triface& t) {
04515   t.ver += (EdgeRing(t.ver) ? -1 : 1);
04516 }
04517 
04518 // If e0 and e1 are both in the same edge ring of a face, e1 = e0.enext().
04519 
04520 inline void tetgenmesh::enext(triface& t1, triface& t2) {
04521   t2.tet = t1.tet;
04522   t2.loc = t1.loc;
04523   t2.ver = ve[t1.ver];
04524 }
04525 
04526 inline void tetgenmesh::enextself(triface& t) {
04527   t.ver = ve[t.ver];
04528 }
04529 
04530 // enext2() is equal to e2 = e0.enext().enext()
04531 
04532 inline void tetgenmesh::enext2(triface& t1, triface& t2) {
04533   t2.tet = t1.tet;
04534   t2.loc = t1.loc;
04535   t2.ver = ve[ve[t1.ver]];
04536 }
04537 
04538 inline void tetgenmesh::enext2self(triface& t) {
04539   t.ver = ve[ve[t.ver]];
04540 }
04541 
04542 // If f0 and f1 are both in the same face ring of a face, f1 = f0.fnext().
04543 //   If f1 exists, return true. Otherwise, return false, i.e., f0 is a
04544 //   boundary or hull face.
04545 
04546 inline bool tetgenmesh::fnext(triface& t1, triface& t2) 
04547 {
04548   // Get the next face.
04549   t2.loc = locver2nextf[t1.loc][t1.ver][0];
04550   // Is the next face in the same tet?
04551   if (t2.loc != -1) {
04552     // It's in the same tet. Get the edge version.
04553     t2.ver = locver2nextf[t1.loc][t1.ver][1];
04554     t2.tet = t1.tet;
04555   } else {
04556     // The next face is in the neigbhour of 't1'.
04557     sym(t1, t2);
04558     if (t2.tet != dummytet) {
04559       // Find the corresponding edge in t2.
04560       point torg;
04561       int tloc, tver, i;
04562       t2.ver = 0;
04563       torg = org(t1);
04564       for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04565         enextself(t2);
04566       }
04567       // Go to the next face in t2.
04568       tloc = t2.loc;
04569       tver = t2.ver;
04570       t2.loc = locver2nextf[tloc][tver][0];
04571       t2.ver = locver2nextf[tloc][tver][1];
04572     }
04573   }
04574   return t2.tet != dummytet;
04575 }
04576 
04577 inline bool tetgenmesh::fnextself(triface& t1) 
04578 {
04579   triface t2;
04580 
04581   // Get the next face.
04582   t2.loc = locver2nextf[t1.loc][t1.ver][0];
04583   // Is the next face in the same tet?
04584   if (t2.loc != -1) {
04585     // It's in the same tet. Get the edge version.
04586     t2.ver = locver2nextf[t1.loc][t1.ver][1];
04587     t1.loc = t2.loc;
04588     t1.ver = t2.ver;
04589   } else {
04590     // The next face is in the neigbhour of 't1'.
04591     sym(t1, t2);
04592     if (t2.tet != dummytet) {
04593       // Find the corresponding edge in t2.
04594       point torg;
04595       int i;
04596       t2.ver = 0;
04597       torg = org(t1);
04598       for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04599         enextself(t2);
04600       }
04601       t1.loc = locver2nextf[t2.loc][t2.ver][0];
04602       t1.ver = locver2nextf[t2.loc][t2.ver][1];
04603       t1.tet = t2.tet;
04604     }
04605   }
04606   return t2.tet != dummytet;
04607 }
04608 
04609 // enextfnext() and enext2fnext() are combination primitives of enext(),
04610 //   enext2() and fnext().
04611 
04612 inline void tetgenmesh::enextfnext(triface& t1, triface& t2) {
04613   enext(t1, t2);
04614   fnextself(t2);
04615 }
04616 
04617 inline void tetgenmesh::enextfnextself(triface& t) {
04618   enextself(t);
04619   fnextself(t);
04620 }
04621 
04622 inline void tetgenmesh::enext2fnext(triface& t1, triface& t2) {
04623   enext2(t1, t2);
04624   fnextself(t2);
04625 }
04626 
04627 inline void tetgenmesh::enext2fnextself(triface& t) {
04628   enext2self(t);
04629   fnextself(t);
04630 }
04631 
04632 // Primitives to infect or cure a tetrahedron with the virus.   The last
04633 //   third bit of the pointer is marked for infection.  These rely on the
04634 //   assumption that all tetrahedron are aligned to eight-byte boundaries.
04635 
04636 inline void tetgenmesh::infect(triface& t) {
04637   t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] | (unsigned long) 4l);
04638 }
04639 
04640 inline void tetgenmesh::uninfect(triface& t) {
04641   t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] & ~ (unsigned long) 4l);
04642 }
04643 
04644 // Test a tetrahedron for viral infection.
04645 
04646 inline bool tetgenmesh::infected(triface& t) {
04647   return (((unsigned long) t.tet[0] & (unsigned long) 4l) != 0);
04648 }
04649 
04650 // Check or set a tetrahedron's attributes.
04651 
04652 inline REAL tetgenmesh::elemattribute(tetrahedron* ptr, int attnum) {
04653   return ((REAL *) (ptr))[elemattribindex + attnum];
04654 }
04655 
04656 inline void tetgenmesh::
04657 setelemattribute(tetrahedron* ptr, int attnum, REAL value){
04658   ((REAL *) (ptr))[elemattribindex + attnum] = value;
04659 }
04660 
04661 // Check or set a tetrahedron's maximum volume bound.
04662 
04663 inline REAL tetgenmesh::volumebound(tetrahedron* ptr) {
04664   return ((REAL *) (ptr))[volumeboundindex];
04665 }
04666 
04667 inline void tetgenmesh::setvolumebound(tetrahedron* ptr, REAL value) {
04668   ((REAL *) (ptr))[volumeboundindex] = value;
04669 }
04670 
04671 //
04672 // End of primitives for tetrahedra
04673 //
04674 
04675 //
04676 // Begin of primitives for subfaces/subsegments
04677 //
04678 
04679 // Each subface contains three pointers to its neighboring subfaces, with
04680 //   edge versions.  To save memory, both information are kept in a single
04681 //   pointer. To make this possible, all subfaces are aligned to eight-byte
04682 //   boundaries, so that the last three bits of each pointer are zeros. An
04683 //   edge version (in the range 0 to 5) is compressed into the last three
04684 //   bits of each pointer by 'sencode()'.  'sdecode()' decodes a pointer,
04685 //   extracting an edge version and a pointer to the beginning of a subface.
04686 
04687 inline void tetgenmesh::sdecode(shellface sptr, face& s) {
04688   s.shver = (int) ((unsigned long) (sptr) & (unsigned long) 7l);
04689   s.sh = (shellface *) ((unsigned long) (sptr) & ~ (unsigned long) 7l);
04690 }
04691 
04692 inline tetgenmesh::shellface tetgenmesh::sencode(face& s) {
04693   return (shellface) ((unsigned long) s.sh | (unsigned long) s.shver);
04694 }
04695 
04696 // spivot() finds the other subface (from this subface) that shares the
04697 //   same edge.
04698 
04699 inline void tetgenmesh::spivot(face& s1, face& s2) {
04700   shellface sptr = s1.sh[Orient(s1.shver)];
04701   sdecode(sptr, s2);
04702 }
04703 
04704 inline void tetgenmesh::spivotself(face& s) {
04705   shellface sptr = s.sh[Orient(s.shver)];
04706   sdecode(sptr, s);
04707 }
04708 
04709 // sbond() bonds two subfaces together, i.e., after bonding, both faces
04710 //   are pointing to each other.
04711 
04712 inline void tetgenmesh::sbond(face& s1, face& s2) {
04713   s1.sh[Orient(s1.shver)] = sencode(s2);
04714   s2.sh[Orient(s2.shver)] = sencode(s1);
04715 }
04716 
04717 // sbond1() only bonds s2 to s1, i.e., after bonding, s1 is pointing to s2,
04718 //   but s2 is not pointing to s1.
04719 
04720 inline void tetgenmesh::sbond1(face& s1, face& s2) {
04721   s1.sh[Orient(s1.shver)] = sencode(s2);
04722 }
04723 
04724 // Dissolve a subface bond (from one side).  Note that the other subface
04725 //   will still think it's connected to this subface.
04726 
04727 inline void tetgenmesh::sdissolve(face& s) {
04728   s.sh[Orient(s.shver)] = (shellface) dummysh;
04729 }
04730 
04731 // These primitives determine or set the origin, destination, or apex
04732 //   of a subface with respect to the edge version.
04733 
04734 inline tetgenmesh::point tetgenmesh::sorg(face& s) {
04735   return (point) s.sh[3 + vo[s.shver]];
04736 }
04737 
04738 inline tetgenmesh::point tetgenmesh::sdest(face& s) {
04739   return (point) s.sh[3 + vd[s.shver]];
04740 }
04741 
04742 inline tetgenmesh::point tetgenmesh::sapex(face& s) {
04743   return (point) s.sh[3 + va[s.shver]];
04744 }
04745 
04746 inline void tetgenmesh::setsorg(face& s, point pointptr) {
04747   s.sh[3 + vo[s.shver]] = (shellface) pointptr;
04748 }
04749 
04750 inline void tetgenmesh::setsdest(face& s, point pointptr) {
04751   s.sh[3 + vd[s.shver]] = (shellface) pointptr;
04752 }
04753 
04754 inline void tetgenmesh::setsapex(face& s, point pointptr) {
04755   s.sh[3 + va[s.shver]] = (shellface) pointptr;
04756 }
04757 
04758 // These primitives were drived from Mucke[2]'s triangle-edge data structure
04759 //   to change face-edge relation in a subface (sesym, senext and senext2).
04760 
04761 inline void tetgenmesh::sesym(face& s1, face& s2) {
04762   s2.sh = s1.sh;
04763   s2.shver = s1.shver + (EdgeRing(s1.shver) ? -1 : 1);
04764 }
04765 
04766 inline void tetgenmesh::sesymself(face& s) {
04767   s.shver += (EdgeRing(s.shver) ? -1 : 1);
04768 }
04769 
04770 inline void tetgenmesh::senext(face& s1, face& s2) {
04771   s2.sh = s1.sh;
04772   s2.shver = ve[s1.shver];
04773 }
04774 
04775 inline void tetgenmesh::senextself(face& s) { 
04776   s.shver = ve[s.shver]; 
04777 }
04778 
04779 inline void tetgenmesh::senext2(face& s1, face& s2) {
04780   s2.sh = s1.sh;
04781   s2.shver = ve[ve[s1.shver]];
04782 }
04783 
04784 inline void tetgenmesh::senext2self(face& s) {
04785   s.shver = ve[ve[s.shver]];
04786 }
04787 
04788 // If f0 and f1 are both in the same face ring, then f1 = f0.fnext(),
04789 
04790 inline void tetgenmesh::sfnext(face& s1, face& s2) {
04791   getnextsface(&s1, &s2);
04792 }
04793 
04794 inline void tetgenmesh::sfnextself(face& s) {
04795   getnextsface(&s, NULL);
04796 }
04797 
04798 // These primitives read or set a pointer of the badface structure.  The
04799 //   pointer is stored sh[11].
04800 
04801 inline tetgenmesh::badface* tetgenmesh::shell2badface(face& s) {
04802   return (badface*) s.sh[11];
04803 }
04804 
04805 inline void tetgenmesh::setshell2badface(face& s, badface* value) {
04806   s.sh[11] = (shellface) value;
04807 }
04808 
04809 // Check or set a subface's maximum area bound.
04810 
04811 inline REAL tetgenmesh::areabound(face& s) {
04812   return ((REAL *) (s.sh))[areaboundindex];
04813 }
04814 
04815 inline void tetgenmesh::setareabound(face& s, REAL value) {
04816   ((REAL *) (s.sh))[areaboundindex] = value;
04817 }
04818 
04819 // These two primitives read or set a shell marker.  Shell markers are used
04820 //   to hold user boundary information.
04821 
04822 inline int tetgenmesh::shellmark(face& s) { 
04823   return ((int *) (s.sh))[shmarkindex];
04824 }
04825 
04826 inline void tetgenmesh::setshellmark(face& s, int value) {
04827   ((int *) (s.sh))[shmarkindex] = value;
04828 }
04829 
04830 // These two primitives set or read the type of the subface or subsegment.
04831 
04832 inline enum tetgenmesh::shestype tetgenmesh::shelltype(face& s) {
04833   return (enum shestype) ((int *) (s.sh))[shmarkindex + 1];
04834 }
04835 
04836 inline void tetgenmesh::setshelltype(face& s, enum shestype value) {
04837   ((int *) (s.sh))[shmarkindex + 1] = (int) value;
04838 }
04839 
04840 // These two primitives set or read the pbc group of the subface.
04841 
04842 inline int tetgenmesh::shellpbcgroup(face& s) {
04843   return ((int *) (s.sh))[shmarkindex + 2];
04844 }
04845 
04846 inline void tetgenmesh::setshellpbcgroup(face& s, int value) {
04847   ((int *) (s.sh))[shmarkindex + 2] = value;
04848 }
04849 
04850 // Primitives to infect or cure a subface with the virus. These rely on the
04851 //   assumption that all tetrahedra are aligned to eight-byte boundaries.
04852 
04853 inline void tetgenmesh::sinfect(face& s) {
04854   s.sh[6] = (shellface) ((unsigned long) s.sh[6] | (unsigned long) 4l);
04855 }
04856 
04857 inline void tetgenmesh::suninfect(face& s) {
04858   s.sh[6] = (shellface)((unsigned long) s.sh[6] & ~(unsigned long) 4l);
04859 }
04860 
04861 // Test a subface for viral infection.
04862 
04863 inline bool tetgenmesh::sinfected(face& s) {
04864   return (((unsigned long) s.sh[6] & (unsigned long) 4l) != 0);
04865 }
04866 
04867 //
04868 // End of primitives for subfaces/subsegments
04869 //
04870 
04871 //
04872 // Begin of primitives for interacting between tetrahedra and subfaces
04873 //
04874 
04875 // tspivot() finds a subface abutting on this tetrahdera.
04876 
04877 inline void tetgenmesh::tspivot(triface& t, face& s) {
04878   shellface sptr = (shellface) t.tet[8 + t.loc];
04879   sdecode(sptr, s);
04880 }
04881 
04882 // stpivot() finds a tetrahedron abutting a subface.
04883 
04884 inline void tetgenmesh::stpivot(face& s, triface& t) {
04885   tetrahedron ptr = (tetrahedron) s.sh[6 + EdgeRing(s.shver)];
04886   decode(ptr, t);
04887 }
04888 
04889 // tsbond() bond a tetrahedron to a subface.
04890 
04891 inline void tetgenmesh::tsbond(triface& t, face& s) {
04892   t.tet[8 + t.loc] = (tetrahedron) sencode(s);
04893   s.sh[6 + EdgeRing(s.shver)] = (shellface) encode(t);
04894 }
04895 
04896 // tsdissolve() dissolve a bond (from the tetrahedron side).
04897 
04898 inline void tetgenmesh::tsdissolve(triface& t) {
04899   t.tet[8 + t.loc] = (tetrahedron) dummysh;
04900 }
04901 
04902 // stdissolve() dissolve a bond (from the subface side).
04903 
04904 inline void tetgenmesh::stdissolve(face& s) {
04905   s.sh[6 + EdgeRing(s.shver)] = (shellface) dummytet;
04906 }
04907 
04908 //
04909 // End of primitives for interacting between tetrahedra and subfaces
04910 //
04911 
04912 //
04913 // Begin of primitives for interacting between subfaces and subsegs
04914 //
04915 
04916 // sspivot() finds a subsegment abutting a subface.
04917 
04918 inline void tetgenmesh::sspivot(face& s, face& edge) {
04919   shellface sptr = (shellface) s.sh[8 + Orient(s.shver)];
04920   sdecode(sptr, edge);
04921 }
04922 
04923 // ssbond() bond a subface to a subsegment.
04924 
04925 inline void tetgenmesh::ssbond(face& s, face& edge) {
04926   s.sh[8 + Orient(s.shver)] = sencode(edge);
04927   edge.sh[0] = sencode(s);
04928 }
04929 
04930 // ssdisolve() dissolve a bond (from the subface side)
04931 
04932 inline void tetgenmesh::ssdissolve(face& s) {
04933   s.sh[8 + Orient(s.shver)] = (shellface) dummysh;
04934 }
04935 
04936 //
04937 // End of primitives for interacting between subfaces and subsegs
04938 //
04939 
04940 //
04941 // Begin of primitives for interacting between tet and subsegs.
04942 //
04943 
04944 inline void tetgenmesh::tsspivot1(triface& t, face& seg)
04945 {
04946   shellface sptr = (shellface) t.tet[8 + locver2edge[t.loc][t.ver]];
04947   sdecode(sptr, seg);
04948 }
04949 
04950 // Only bond/dissolve at tet's side, but not vice versa.
04951 
04952 inline void tetgenmesh::tssbond1(triface& t, face& seg)
04953 {
04954   t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) sencode(seg);
04955 }
04956 
04957 inline void tetgenmesh::tssdissolve1(triface& t)
04958 {
04959   t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) dummysh;
04960 }
04961 
04962 //
04963 // End of primitives for interacting between tet and subsegs.
04964 //
04965 
04966 //
04967 // Begin of primitives for points
04968 //
04969 
04970 inline int tetgenmesh::pointmark(point pt) { 
04971   return ((int *) (pt))[pointmarkindex]; 
04972 }
04973 
04974 inline void tetgenmesh::setpointmark(point pt, int value) {
04975   ((int *) (pt))[pointmarkindex] = value;
04976 }
04977 
04978 // These two primitives set and read the type of the point.
04979 
04980 inline enum tetgenmesh::verttype tetgenmesh::pointtype(point pt) {
04981   return (enum verttype) ((int *) (pt))[pointmarkindex + 1];
04982 }
04983 
04984 inline void tetgenmesh::setpointtype(point pt, enum verttype value) {
04985   ((int *) (pt))[pointmarkindex + 1] = (int) value;
04986 }
04987 
04988 // These following primitives set and read a pointer to a tetrahedron
04989 //   a subface/subsegment, a point, or a tet of background mesh.
04990 
04991 inline tetgenmesh::tetrahedron tetgenmesh::point2tet(point pt) {
04992   return ((tetrahedron *) (pt))[point2simindex];
04993 }
04994 
04995 inline void tetgenmesh::setpoint2tet(point pt, tetrahedron value) {
04996   ((tetrahedron *) (pt))[point2simindex] = value;
04997 }
04998 
04999 inline tetgenmesh::shellface tetgenmesh::point2sh(point pt) {
05000   return (shellface) ((tetrahedron *) (pt))[point2simindex + 1];
05001 }
05002 
05003 inline void tetgenmesh::setpoint2sh(point pt, shellface value) {
05004   ((tetrahedron *) (pt))[point2simindex + 1] = (tetrahedron) value;
05005 }
05006 
05007 inline tetgenmesh::point tetgenmesh::point2ppt(point pt) {
05008   return (point) ((tetrahedron *) (pt))[point2simindex + 2];
05009 }
05010 
05011 inline void tetgenmesh::setpoint2ppt(point pt, point value) {
05012   ((tetrahedron *) (pt))[point2simindex + 2] = (tetrahedron) value;
05013 }
05014 
05015 inline tetgenmesh::tetrahedron tetgenmesh::point2bgmtet(point pt) {
05016   return ((tetrahedron *) (pt))[point2simindex + 3];
05017 }
05018 
05019 inline void tetgenmesh::setpoint2bgmtet(point pt, tetrahedron value) {
05020   ((tetrahedron *) (pt))[point2simindex + 3] = value;
05021 }
05022 
05023 // These primitives set and read a pointer to its pbc point.
05024 
05025 inline tetgenmesh::point tetgenmesh::point2pbcpt(point pt) {
05026   return (point) ((tetrahedron *) (pt))[point2pbcptindex];
05027 }
05028 
05029 inline void tetgenmesh::setpoint2pbcpt(point pt, point value) {
05030   ((tetrahedron *) (pt))[point2pbcptindex] = (tetrahedron) value;
05031 }
05032 
05033 //
05034 // End of primitives for points
05035 //
05036 
05037 //
05038 // Begin of advanced primitives
05039 //
05040 
05041 // adjustedgering() adjusts the edge version so that it belongs to the
05042 //   indicated edge ring.  The 'direction' only can be 0(CCW) or 1(CW).
05043 //   If the edge is not in the wanted edge ring, reverse it.
05044 
05045 inline void tetgenmesh::adjustedgering(triface& t, int direction) {
05046   if (EdgeRing(t.ver) != direction) {
05047     esymself(t);
05048   }
05049 }
05050 
05051 inline void tetgenmesh::adjustedgering(face& s, int direction) {
05052   if (EdgeRing(s.shver) != direction) {
05053     sesymself(s);
05054   }
05055 }
05056 
05057 // isdead() returns TRUE if the tetrahedron or subface has been dealloced.
05058 
05059 inline bool tetgenmesh::isdead(triface* t) {
05060   if (t->tet == (tetrahedron *) NULL) return true;
05061   else return t->tet[4] == (tetrahedron) NULL;
05062 }
05063 
05064 inline bool tetgenmesh::isdead(face* s) {
05065   if (s->sh == (shellface *) NULL) return true;
05066   else return s->sh[3] == (shellface) NULL;
05067 }
05068 
05069 // isfacehaspoint() returns TRUE if the 'testpoint' is one of the vertices
05070 //   of the tetface 't' subface 's'.
05071 
05072 inline bool tetgenmesh::isfacehaspoint(triface* t, point testpoint) {
05073   return ((org(*t) == testpoint) || (dest(*t) == testpoint) ||
05074           (apex(*t) == testpoint));
05075 }
05076 
05077 inline bool tetgenmesh::isfacehaspoint(face* s, point testpoint) {
05078   return (s->sh[3] == (shellface) testpoint) || 
05079          (s->sh[4] == (shellface) testpoint) ||
05080          (s->sh[5] == (shellface) testpoint);
05081 }
05082 
05083 // isfacehasedge() returns TRUE if the edge (given by its two endpoints) is
05084 //   one of the three edges of the subface 's'.
05085 
05086 inline bool tetgenmesh::isfacehasedge(face* s, point tend1, point tend2) {
05087   return (isfacehaspoint(s, tend1) && isfacehaspoint(s, tend2));
05088 }
05089 
05090 // issymexist() returns TRUE if the adjoining tetrahedron is not 'duumytet'.
05091 
05092 inline bool tetgenmesh::issymexist(triface* t) {
05093   tetrahedron *ptr = (tetrahedron *) 
05094     ((unsigned long)(t->tet[t->loc]) & ~(unsigned long)7l);
05095   return ptr != dummytet;
05096 }
05097 
05099 //                                                                           //
05100 // getnextsface()    Finds the next subface in the face ring.                //
05101 //                                                                           //
05102 // For saving space in the data structure of subface, there only exists one  //
05103 // face ring around a segment (see programming manual).  This routine imple- //
05104 // ments the double face ring as desired in Muecke's data structure.         //
05105 //                                                                           //
05107 
05108 void tetgenmesh::getnextsface(face* s1, face* s2)
05109 {
05110   face neighsh, spinsh;
05111   face testseg;
05112 
05113   sspivot(*s1, testseg);
05114   if (testseg.sh != dummysh) {
05115     testseg.shver = 0;
05116     if (sorg(testseg) == sorg(*s1)) {
05117       spivot(*s1, neighsh);
05118     } else {
05119       spinsh = *s1;
05120       do {
05121         neighsh = spinsh;
05122         spivotself(spinsh);
05123       } while (spinsh.sh != s1->sh);
05124     }
05125   } else {
05126     spivot(*s1, neighsh);
05127   }
05128   if (sorg(neighsh) != sorg(*s1)) {
05129     sesymself(neighsh);
05130   }
05131   if (s2 != (face *) NULL) {
05132     *s2 = neighsh;
05133   } else {
05134     *s1 = neighsh;
05135   }
05136 }
05137 
05139 //                                                                           //
05140 // tsspivot()    Finds a subsegment abutting on a tetrahderon's edge.        //
05141 //                                                                           //
05142 // The edge is represented in the primary edge of 'checkedge'. If there is a //
05143 // subsegment bonded at this edge, it is returned in handle 'checkseg', the  //
05144 // edge direction of 'checkseg' is conformed to 'checkedge'. If there isn't, //
05145 // set 'checkseg.sh = dummysh' to indicate it is not a subsegment.           //
05146 //                                                                           //
05147 // To find whether an edge of a tetrahedron is a subsegment or not. First we //
05148 // need find a subface around this edge to see if it contains a subsegment.  //
05149 // The reason is there is no direct connection between a tetrahedron and its //
05150 // adjoining subsegments.                                                    //
05151 //                                                                           //
05153 
05154 void tetgenmesh::tsspivot(triface* checkedge, face* checkseg)
05155 {
05156   triface spintet;
05157   face parentsh;
05158   point tapex;
05159   int hitbdry;
05160 
05161   spintet = *checkedge;
05162   tapex = apex(*checkedge);
05163   hitbdry = 0;
05164   do {
05165     tspivot(spintet, parentsh);
05166     // Does spintet have a (non-fake) subface attached? 
05167     if ((parentsh.sh != dummysh) && (sapex(parentsh) != NULL)) {
05168       // Find a subface! Find the edge in it.      
05169       findedge(&parentsh, org(*checkedge), dest(*checkedge));
05170       sspivot(parentsh, *checkseg);
05171       if (checkseg->sh != dummysh) {
05172         // Find a subsegment! Correct its edge direction before return.
05173         if (sorg(*checkseg) != org(*checkedge)) {
05174           sesymself(*checkseg);
05175         }
05176       }
05177       return;
05178     }
05179     if (!fnextself(spintet)) {
05180       hitbdry++;
05181       if (hitbdry < 2) {
05182         esym(*checkedge, spintet);
05183         if (!fnextself(spintet)) {
05184           hitbdry++;
05185         }
05186       }
05187     }
05188   } while ((apex(spintet) != tapex) && (hitbdry < 2));
05189   // Not find.
05190   checkseg->sh = dummysh;
05191 }
05192 
05194 //                                                                           //
05195 // sstpivot()    Finds a tetrahedron abutting a subsegment.                  //
05196 //                                                                           //
05197 // This is the inverse operation of 'tsspivot()'.  One subsegment shared by  //
05198 // arbitrary number of tetrahedron, the returned tetrahedron is not unique.  //
05199 // The edge direction of the returned tetrahedron is conformed to the given  //
05200 // subsegment.                                                               //
05201 //                                                                           //
05203 
05204 void tetgenmesh::sstpivot(face* checkseg, triface* retedge)
05205 {
05206   face parentsh;
05207 
05208   // Get the subface which holds the subsegment.
05209   sdecode(checkseg->sh[0], parentsh);
05210 #ifdef SELF_CHECK
05211   assert(parentsh.sh != dummysh);
05212 #endif
05213   // Get a tetraheron to which the subface attches.
05214   stpivot(parentsh, *retedge);
05215   if (retedge->tet == dummytet) {
05216     sesymself(parentsh);
05217     stpivot(parentsh, *retedge);
05218 #ifdef SELF_CHECK
05219     assert(retedge->tet != dummytet);
05220 #endif
05221   }
05222   // Correct the edge direction before return.
05223   findedge(retedge, sorg(*checkseg), sdest(*checkseg));
05224 }
05225 
05227 //                                                                           //
05228 // findorg()    Finds a point in the given handle (tetrahedron or subface).  //
05229 //                                                                           //
05230 // If 'dorg' is a one of vertices of the given handle,  set the origin of    //
05231 // this handle be that point and return TRUE.  Otherwise, return FALSE and   //
05232 // 'tface' remains unchanged.                                                //
05233 //                                                                           //
05235 
05236 bool tetgenmesh::findorg(triface* tface, point dorg)
05237 {
05238   if (org(*tface) == dorg) {
05239     return true;
05240   } else { 
05241     if (dest(*tface) == dorg) {
05242       enextself(*tface);
05243       return true;
05244     } else {
05245       if (apex(*tface) == dorg) {
05246         enext2self(*tface);
05247         return true;
05248       } else {
05249         if (oppo(*tface) == dorg) {
05250           // Keep 'tface' referring to the same tet after fnext().
05251           adjustedgering(*tface, CCW);
05252           fnextself(*tface);
05253           enext2self(*tface);
05254           return true;
05255         } 
05256       }
05257     }
05258   }
05259   return false;
05260 }
05261 
05262 bool tetgenmesh::findorg(face* sface, point dorg)
05263 {
05264   if (sorg(*sface) == dorg) {
05265     return true;
05266   } else {
05267     if (sdest(*sface) == dorg) {
05268       senextself(*sface);
05269       return true;
05270     } else {
05271       if (sapex(*sface) == dorg) {
05272         senext2self(*sface);
05273         return true;
05274       } 
05275     }
05276   }
05277   return false;
05278 }
05279 
05281 //                                                                           //
05282 // findedge()    Find an edge in the given handle (tetrahedron or subface).  //
05283 //                                                                           //
05284 // The edge is given in two points 'eorg' and 'edest'.  It is assumed that   //
05285 // the edge must exist in the given handle (tetrahedron or subface).  This   //
05286 // routine sets the right edge version for the input handle.                 //
05287 //                                                                           //
05289 
05290 void tetgenmesh::findedge(triface* tface, point eorg, point edest)
05291 {
05292   int i;
05293 
05294   for (i = 0; i < 3; i++) {
05295     if (org(*tface) == eorg) {
05296       if (dest(*tface) == edest) {
05297         // Edge is found, return.
05298         return;
05299       } 
05300     } else {
05301       if (org(*tface) == edest) {
05302         if (dest(*tface) == eorg) {
05303           // Edge is found, inverse the direction and return.
05304           esymself(*tface);
05305           return;
05306         }
05307       }
05308     }
05309     enextself(*tface);
05310   }
05311   // It should never be here.
05312   printf("Internalerror in findedge():  Unable to find an edge in tet.\n");
05313   internalerror();
05314 }
05315 
05316 void tetgenmesh::findedge(face* sface, point eorg, point edest)
05317 {
05318   int i;
05319 
05320   for (i = 0; i < 3; i++) {
05321     if (sorg(*sface) == eorg) {
05322       if (sdest(*sface) == edest) {
05323         // Edge is found, return.
05324         return;
05325       } 
05326     } else {
05327       if (sorg(*sface) == edest) {
05328         if (sdest(*sface) == eorg) {
05329           // Edge is found, inverse the direction and return.
05330           sesymself(*sface);
05331           return;
05332         }
05333       }
05334     }
05335     senextself(*sface);
05336   }
05337   printf("Internalerror in findedge():  Unable to find an edge in subface.\n");
05338   internalerror();
05339 }
05340 
05342 //                                                                           //
05343 // findface()    Find the face has the given origin, destination and apex.   //
05344 //                                                                           //
05345 // On input, 'fface' is a handle which may contain the three corners or may  //
05346 // not or may be dead.  On return, it represents exactly the face with the   //
05347 // given origin, destination and apex.                                       //
05348 //                                                                           //
05350 
05351 void tetgenmesh::findface(triface *fface, point forg, point fdest, point fapex)
05352 {
05353   triface spintet;
05354   enum finddirectionresult collinear;
05355   int hitbdry;
05356 
05357   if (!isdead(fface)) {
05358     // First check the easiest case, that 'fface' is just the right one.
05359     if (org(*fface) == forg && dest(*fface) == fdest && 
05360         apex(*fface) == fapex) return;
05361   } else {
05362     // The input handle is dead, use the 'recenttet' if it is alive.
05363     if (!isdead(&recenttet)) *fface = recenttet;
05364   }
05365 
05366   if (!isdead(fface)) {
05367     if (!findorg(fface, forg)) {
05368       // 'forg' is not a corner of 'fface', locate it.
05369       preciselocate(forg, fface, tetrahedrons->items);
05370     }
05371     // It is possible that forg is not found in a non-convex mesh.
05372     if (org(*fface) == forg) {
05373       collinear = finddirection(fface, fdest, tetrahedrons->items);
05374       if (collinear == RIGHTCOLLINEAR) {
05375         // fdest is just the destination.
05376       } else if (collinear == LEFTCOLLINEAR) {
05377         enext2self(*fface);
05378         esymself(*fface);
05379       } else if (collinear == TOPCOLLINEAR) {
05380         fnextself(*fface);
05381         enext2self(*fface);
05382         esymself(*fface);
05383       }
05384     }
05385     // It is possible taht fdest is not found in a non-convex mesh.
05386     if ((org(*fface) == forg) && (dest(*fface) == fdest)) {
05387       // Find the apex of 'fapex'.
05388       spintet = *fface;
05389       hitbdry = 0;
05390       do {
05391         if (apex(spintet) == fapex) {
05392           // We have done. Be careful the edge direction of 'spintet',
05393           //   it may reversed because of hitting boundary once.
05394           if (org(spintet) != org(*fface)) {
05395             esymself(spintet);
05396           }
05397           *fface = spintet;
05398           return;
05399         }
05400         if (!fnextself(spintet)) {
05401           hitbdry ++;
05402           if (hitbdry < 2) {
05403             esym(*fface, spintet);
05404             if (!fnextself(spintet)) {
05405               hitbdry ++;
05406             }
05407           }
05408         }
05409       } while (hitbdry < 2 && apex(spintet) != apex(*fface));
05410       // It is possible that fapex is not found in a non-convex mesh.
05411     }
05412   }
05413 
05414   if (isdead(fface) || (org(*fface) != forg) || (dest(*fface) != fdest) ||
05415       (apex(*fface) != fapex)) {
05416     // Too bad, the input handle is useless. We have to find a handle
05417     //   for 'fface' contains the 'forg' and 'fdest'. Here a brute force
05418     //   search is performed.
05419     if (b->verbose > 1) {
05420       printf("Warning in findface():  Perform a brute-force searching.\n");
05421     }
05422     enum verttype forgty, fdestty, fapexty;
05423     int share, i;
05424     forgty = pointtype(forg);
05425     fdestty = pointtype(fdest);
05426     fapexty = pointtype(fapex);
05427     setpointtype(forg, DEADVERTEX);
05428     setpointtype(fdest, DEADVERTEX);
05429     setpointtype(fapex, DEADVERTEX);
05430     tetrahedrons->traversalinit();
05431     fface->tet = tetrahedrontraverse();
05432     while (fface->tet != (tetrahedron *) NULL) {
05433       share = 0;
05434       for (i = 0; i < 4; i++) {
05435         if (pointtype((point) fface->tet[4 + i]) == DEADVERTEX) share ++;
05436       }
05437       if (share == 3) {
05438         // Found! Set the correct face and desired corners.
05439         if (pointtype((point) fface->tet[4]) != DEADVERTEX) {
05440           fface->loc = 2;
05441         } else if (pointtype((point) fface->tet[5]) != DEADVERTEX) {
05442           fface->loc = 3;
05443         } else if (pointtype((point) fface->tet[6]) != DEADVERTEX) {
05444           fface->loc = 1;
05445         } else { // pointtype((point) fface->tet[7]) != DEADVERTEX
05446           fface->loc = 0;
05447         }
05448         findedge(fface, forg, fdest);
05449         break;
05450       }
05451       fface->tet = tetrahedrontraverse();
05452     }
05453     setpointtype(forg, forgty);
05454     setpointtype(fdest, fdestty);
05455     setpointtype(fapex, fapexty);
05456     if (fface->tet == (tetrahedron *) NULL) {
05457       // It is impossible to reach here.
05458       printf("Internal error:  Fail to find the indicated face.\n");
05459       internalerror();
05460     }
05461   }
05462 }
05463 
05465 //                                                                           //
05466 // getonextseg()    Get the next SEGMENT counterclockwise with the same org. //
05467 //                                                                           //
05468 // 's' is a subface. This routine reteuns the segment which is counterclock- //
05469 // wise with the origin of s.                                                //
05470 //                                                                           //
05472 
05473 void tetgenmesh::getonextseg(face* s, face* lseg)
05474 {
05475   face checksh, checkseg;
05476   point forg;
05477 
05478   forg = sorg(*s);
05479   checksh = *s;
05480   do {
05481     // Go to the edge at forg's left side.
05482     senext2self(checksh);
05483     // Check if there is a segment attaching this edge.
05484     sspivot(checksh, checkseg);
05485     if (checkseg.sh != dummysh) break;
05486     // No segment! Go to the neighbor of this subface.
05487     spivotself(checksh);
05488 #ifdef SELF_CHECK
05489     // It should always meet a segment before come back.
05490     assert(checksh.sh != s->sh);
05491 #endif
05492     if (sorg(checksh) != forg) {
05493       sesymself(checksh);
05494 #ifdef SELF_CHECK
05495       assert(sorg(checksh) == forg);
05496 #endif
05497     }
05498   } while (true);
05499   if (sorg(checkseg) != forg) sesymself(checkseg);
05500   *lseg = checkseg;
05501 }
05502 
05504 //                                                                           //
05505 // getseghasorg()    Get the segment containing the given point.             //
05506 //                                                                           //
05507 // 'dorg' is an endpoint of a segment S. 'sseg' is a subsegment of S. This   //
05508 // routine search a subsegment (along sseg) of S containing dorg. On return, //
05509 // 'sseg' contains 'dorg' as its origin.                                     //
05510 //                                                                           //
05512 
05513 void tetgenmesh::getseghasorg(face* sseg, point dorg)
05514 {
05515   face nextseg;
05516   point checkpt;
05517 
05518   nextseg = *sseg;
05519   checkpt = sorg(nextseg);
05520   while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05521     // Search dorg along the original direction of sseg.
05522     senext2self(nextseg);
05523     spivotself(nextseg);
05524     nextseg.shver = 0;
05525     if (sdest(nextseg) != checkpt) sesymself(nextseg);
05526     checkpt = sorg(nextseg);
05527   }
05528   if (checkpt == dorg) {
05529     *sseg = nextseg;
05530     return;
05531   }
05532   nextseg = *sseg;
05533   checkpt = sdest(nextseg);
05534   while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05535     // Search dorg along the destinational direction of sseg.
05536     senextself(nextseg);
05537     spivotself(nextseg);
05538     nextseg.shver = 0;
05539     if (sorg(nextseg) != checkpt) sesymself(nextseg);
05540     checkpt = sdest(nextseg);
05541   }
05542   if (checkpt == dorg) {
05543     sesym(nextseg, *sseg);
05544     return;
05545   }
05546   // Should never be here.
05547   printf("Internalerror in getseghasorg():  Unable to find the subseg.\n");
05548   internalerror();
05549 }
05550 
05552 //                                                                           //
05553 // getsubsegfarorg()    Get the origin of the parent segment of a subseg.    //
05554 //                                                                           //
05556 
05557 tetgenmesh::point tetgenmesh::getsubsegfarorg(face* sseg)
05558 {
05559   face prevseg;
05560   point checkpt;
05561 
05562   checkpt = sorg(*sseg);
05563   senext2(*sseg, prevseg);
05564   spivotself(prevseg);
05565   // Search dorg along the original direction of sseg.
05566   while (prevseg.sh != dummysh) {
05567     prevseg.shver = 0;
05568     if (sdest(prevseg) != checkpt) sesymself(prevseg);
05569     checkpt = sorg(prevseg);
05570     senext2self(prevseg);
05571     spivotself(prevseg);
05572   }
05573   return checkpt;
05574 }
05575 
05577 //                                                                           //
05578 // getsubsegfardest()    Get the dest. of the parent segment of a subseg.    //
05579 //                                                                           //
05581 
05582 tetgenmesh::point tetgenmesh::getsubsegfardest(face* sseg)
05583 {
05584   face nextseg;
05585   point checkpt;
05586 
05587   checkpt = sdest(*sseg);
05588   senext(*sseg, nextseg);
05589   spivotself(nextseg);
05590   // Search dorg along the destinational direction of sseg.
05591   while (nextseg.sh != dummysh) {
05592     nextseg.shver = 0;
05593     if (sorg(nextseg) != checkpt) sesymself(nextseg);
05594     checkpt = sdest(nextseg);
05595     senextself(nextseg);
05596     spivotself(nextseg);
05597   }
05598   return checkpt;
05599 }
05600 
05602 //                                                                           //
05603 // printtet()    Print out the details of a tetrahedron on screen.           //
05604 //                                                                           //
05605 // It's also used when the highest level of verbosity (`-VVV') is specified. //
05606 //                                                                           //
05608 
05609 void tetgenmesh::printtet(triface* tface)
05610 {
05611   triface tmpface, prtface;
05612   point tmppt;
05613   face tmpsh;
05614   int facecount;
05615 
05616   printf("Tetra x%lx with loc(%i) and ver(%i):",
05617          (unsigned long)(tface->tet), tface->loc, tface->ver);
05618   if (infected(*tface)) {
05619     printf(" (infected)");
05620   }
05621   printf("\n");
05622 
05623   tmpface = *tface;
05624   facecount = 0;
05625   while(facecount < 4) {
05626     tmpface.loc = facecount;
05627     sym(tmpface, prtface);
05628     if(prtface.tet == dummytet) {
05629       printf("      [%i] Outer space.\n", facecount);
05630     } else {
05631       printf("      [%i] x%lx  loc(%i).", facecount,
05632              (unsigned long)(prtface.tet), prtface.loc);
05633       if (infected(prtface)) {
05634         printf(" (infected)");
05635       }
05636       printf("\n");
05637     }
05638     facecount ++;
05639   }
05640 
05641   tmppt = org(*tface);
05642   if(tmppt == (point) NULL) {
05643     printf("      Org [%i] NULL\n", locver2org[tface->loc][tface->ver]);
05644   } else {
05645     printf("      Org [%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05646            locver2org[tface->loc][tface->ver], (unsigned long)(tmppt),
05647            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05648   }
05649   tmppt = dest(*tface);
05650   if(tmppt == (point) NULL) {
05651     printf("      Dest[%i] NULL\n", locver2dest[tface->loc][tface->ver]);
05652   } else {
05653     printf("      Dest[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05654            locver2dest[tface->loc][tface->ver], (unsigned long)(tmppt),
05655            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05656   }
05657   tmppt = apex(*tface);
05658   if(tmppt == (point) NULL) {
05659     printf("      Apex[%i] NULL\n", locver2apex[tface->loc][tface->ver]);
05660   } else {
05661     printf("      Apex[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05662            locver2apex[tface->loc][tface->ver], (unsigned long)(tmppt),
05663            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05664   }
05665   tmppt = oppo(*tface);
05666   if(tmppt == (point) NULL) {
05667     printf("      Oppo[%i] NULL\n", loc2oppo[tface->loc]);
05668   } else {
05669     printf("      Oppo[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05670            loc2oppo[tface->loc], (unsigned long)(tmppt),
05671            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05672   }
05673 
05674   if (b->useshelles) {
05675     tmpface = *tface;
05676     facecount = 0;
05677     while(facecount < 6) {
05678       tmpface.loc = facecount;
05679       tspivot(tmpface, tmpsh);
05680       if(tmpsh.sh != dummysh) {
05681         printf("      [%i] x%lx  ID(%i) ", facecount,
05682                (unsigned long)(tmpsh.sh), shellmark(tmpsh));
05683         if (sorg(tmpsh) == (point) NULL) {
05684           printf("(fake)");
05685         }
05686         printf("\n");
05687       }
05688       facecount ++;
05689     }
05690   }
05691 }
05692 
05694 //                                                                           //
05695 // printsh()    Print out the details of a subface or subsegment on screen.  //
05696 //                                                                           //
05697 // It's also used when the highest level of verbosity (`-VVV') is specified. //
05698 //                                                                           //
05700 
05701 void tetgenmesh::printsh(face* sface)
05702 {
05703   face prtsh;
05704   triface prttet;
05705   point printpoint;
05706 
05707   if (sapex(*sface) != NULL) {
05708     printf("subface x%lx, ver %d, mark %d:",
05709            (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05710   } else {
05711     printf("Subsegment x%lx, ver %d, mark %d:",
05712            (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05713   }
05714   if (sinfected(*sface)) {
05715     printf(" (infected)");
05716   }
05717   if (shell2badface(*sface)) {
05718     printf(" (queued)");
05719   }
05720   if (sapex(*sface) != NULL) {
05721     if (shelltype(*sface) == SHARP) {
05722       printf(" (sharp)");
05723     }
05724   } else {
05725     if (shelltype(*sface) == SHARP) {
05726       printf(" (sharp)");
05727     }
05728   }
05729   if (checkpbcs) {
05730     if (shellpbcgroup(*sface) >= 0) {
05731       printf(" (pbc %d)", shellpbcgroup(*sface));
05732     }
05733   }
05734   printf("\n");
05735 
05736   sdecode(sface->sh[0], prtsh);
05737   if (prtsh.sh == dummysh) {
05738     printf("      [0] = No shell\n");
05739   } else {
05740     printf("      [0] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05741   }
05742   sdecode(sface->sh[1], prtsh);
05743   if (prtsh.sh == dummysh) {
05744     printf("      [1] = No shell\n");
05745   } else {
05746     printf("      [1] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05747   }
05748   sdecode(sface->sh[2], prtsh);
05749   if (prtsh.sh == dummysh) {
05750     printf("      [2] = No shell\n");
05751   } else {
05752     printf("      [2] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05753   }
05754 
05755   printpoint = sorg(*sface);
05756   if (printpoint == (point) NULL)
05757     printf("      Org [%d] = NULL\n", vo[sface->shver]);
05758   else
05759     printf("      Org [%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05760            vo[sface->shver], (unsigned long)(printpoint), printpoint[0],
05761            printpoint[1], printpoint[2], pointmark(printpoint));
05762   printpoint = sdest(*sface);
05763   if (printpoint == (point) NULL)
05764     printf("      Dest[%d] = NULL\n", vd[sface->shver]);
05765   else
05766     printf("      Dest[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05767             vd[sface->shver], (unsigned long)(printpoint), printpoint[0],
05768             printpoint[1], printpoint[2], pointmark(printpoint));
05769 
05770   if (sapex(*sface) != NULL) {
05771     printpoint = sapex(*sface);
05772     if (printpoint == (point) NULL)
05773       printf("      Apex[%d] = NULL\n", va[sface->shver]);
05774     else
05775       printf("      Apex[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05776              va[sface->shver], (unsigned long)(printpoint), printpoint[0],
05777              printpoint[1], printpoint[2], pointmark(printpoint));
05778 
05779     decode(sface->sh[6], prttet);
05780     if (prttet.tet == dummytet) {
05781       printf("      [6] = Outer space\n");
05782     } else {
05783       printf("      [6] = x%lx  %d\n",
05784              (unsigned long)(prttet.tet), prttet.loc);
05785     }
05786     decode(sface->sh[7], prttet);
05787     if (prttet.tet == dummytet) {
05788       printf("      [7] = Outer space\n");
05789     } else {
05790       printf("      [7] = x%lx  %d\n",
05791              (unsigned long)(prttet.tet), prttet.loc);
05792     }
05793 
05794     sdecode(sface->sh[8], prtsh);
05795     if (prtsh.sh == dummysh) {
05796       printf("      [8] = No subsegment\n");
05797     } else {
05798       printf("      [8] = x%lx  %d\n",
05799              (unsigned long)(prtsh.sh), prtsh.shver);
05800     }
05801     sdecode(sface->sh[9], prtsh);
05802     if (prtsh.sh == dummysh) {
05803       printf("      [9] = No subsegment\n");
05804     } else {
05805       printf("      [9] = x%lx  %d\n",
05806              (unsigned long)(prtsh.sh), prtsh.shver);
05807     }
05808     sdecode(sface->sh[10], prtsh);
05809     if (prtsh.sh == dummysh) {
05810       printf("      [10]= No subsegment\n");
05811     } else {
05812       printf("      [10]= x%lx  %d\n",
05813              (unsigned long)(prtsh.sh), prtsh.shver);
05814     }
05815   } 
05816 }
05817 
05818 //
05819 // End of advanced primitives
05820 //
05821 
05822 //
05823 // End of mesh manipulation primitives
05824 //
05825 
05826 //
05827 // Begin of mesh items searching routines
05828 //
05829 
05831 //                                                                           //
05832 // makepoint2tetmap()    Construct a mapping from points to tetrahedra.      //
05833 //                                                                           //
05834 // Traverses all the tetrahedra,  provides each corner of each tetrahedron   //
05835 // with a pointer to that tetrahedera.  Some pointers will be overwritten by //
05836 // other pointers because each point may be a corner of several tetrahedra,  //
05837 // but in the end every point will point to a tetrahedron that contains it.  //
05838 //                                                                           //
05840 
05841 void tetgenmesh::makepoint2tetmap()
05842 {
05843   triface tetloop;
05844   point pointptr;
05845 
05846   if (b->verbose > 0) {
05847     printf("  Constructing mapping from points to tetrahedra.\n");
05848   }
05849 
05850   // Initialize the point2tet field of each point.
05851   points->traversalinit();
05852   pointptr = pointtraverse();
05853   while (pointptr != (point) NULL) {
05854     setpoint2tet(pointptr, (tetrahedron) NULL);
05855     pointptr = pointtraverse();
05856   }
05857 
05858   tetrahedrons->traversalinit();
05859   tetloop.tet = tetrahedrontraverse();
05860   while (tetloop.tet != (tetrahedron *) NULL) {
05861     // Check all four points of the tetrahedron.
05862     tetloop.loc = 0;
05863     pointptr = org(tetloop);
05864     setpoint2tet(pointptr, encode(tetloop));
05865     pointptr = dest(tetloop);
05866     setpoint2tet(pointptr, encode(tetloop));
05867     pointptr = apex(tetloop);
05868     setpoint2tet(pointptr, encode(tetloop));
05869     pointptr = oppo(tetloop);
05870     setpoint2tet(pointptr, encode(tetloop));
05871     // Get the next tetrahedron in the list.
05872     tetloop.tet = tetrahedrontraverse();
05873   }
05874 }
05875 
05877 //                                                                           //
05878 // makeindex2pointmap()    Create a map from index to vertices.              //
05879 //                                                                           //
05880 // 'idx2verlist' returns the created map.  Traverse all vertices, a pointer  //
05881 // to each vertex is set into the array.  The pointer to the first vertex is //
05882 // saved in 'idx2verlist[0]'.  Don't forget to minus 'in->firstnumber' when  //
05883 // to get the vertex form its index.                                         //
05884 //                                                                           //
05886 
05887 void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
05888 {
05889   point pointloop;
05890   int idx;
05891 
05892   if (b->verbose > 0) {
05893     printf("  Constructing mapping from indices to points.\n");
05894   }
05895 
05896   idx2verlist = new point[points->items];
05897 
05898   points->traversalinit();
05899   pointloop = pointtraverse();
05900   idx = 0;
05901   while (pointloop != (point) NULL) {
05902     idx2verlist[idx] = pointloop;
05903     idx++;
05904     pointloop = pointtraverse();
05905   }
05906 }
05907 
05909 //                                                                           //
05910 // makesegmentmap()    Create a map from vertices (their indices) to         //
05911 //                     segments incident at the same vertices.               //
05912 //                                                                           //
05913 // Two arrays 'idx2seglist' and 'segsperverlist' together return the map.    //
05914 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
05915 // number of segments.  idx2seglist contains row information and             //
05916 // segsperverlist contains all (non-zero) elements.  The i-th entry of       //
05917 // idx2seglist is the starting position of i-th row's (non-zero) elements in //
05918 // segsperverlist.  The number of elements of i-th row is calculated by the  //
05919 // (i+1)-th entry minus i-th entry of idx2seglist.                           //
05920 //                                                                           //
05921 // NOTE: These two arrays will be created inside this routine, don't forget  //
05922 // to free them after using.                                                 //
05923 //                                                                           //
05925 
05926 void tetgenmesh::makesegmentmap(int*& idx2seglist, shellface**& segsperverlist)
05927 {
05928   shellface *shloop;
05929   int i, j, k;
05930 
05931   if (b->verbose > 0) {
05932     printf("  Constructing mapping from points to segments.\n");
05933   }
05934 
05935   // Create and initialize 'idx2seglist'.
05936   idx2seglist = new int[points->items + 1];
05937   for (i = 0; i < points->items + 1; i++) idx2seglist[i] = 0;
05938 
05939   // Loop the set of segments once, counter the number of segments sharing
05940   //   each vertex.
05941   subsegs->traversalinit();
05942   shloop = shellfacetraverse(subsegs);
05943   while (shloop != (shellface *) NULL) {
05944     // Increment the number of sharing segments for each endpoint.
05945     for (i = 0; i < 2; i++) {
05946       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05947       idx2seglist[j]++;
05948     }
05949     shloop = shellfacetraverse(subsegs);
05950   }
05951 
05952   // Calculate the total length of array 'facesperverlist'.
05953   j = idx2seglist[0];
05954   idx2seglist[0] = 0;  // Array starts from 0 element.
05955   for (i = 0; i < points->items; i++) {
05956     k = idx2seglist[i + 1];
05957     idx2seglist[i + 1] = idx2seglist[i] + j;
05958     j = k;
05959   }
05960   // The total length is in the last unit of idx2seglist.
05961   segsperverlist = new shellface*[idx2seglist[i]];
05962   // Loop the set of segments again, set the info. of segments per vertex.
05963   subsegs->traversalinit();
05964   shloop = shellfacetraverse(subsegs);
05965   while (shloop != (shellface *) NULL) {
05966     for (i = 0; i < 2; i++) {
05967       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05968       segsperverlist[idx2seglist[j]] = shloop;
05969       idx2seglist[j]++;
05970     }
05971     shloop = shellfacetraverse(subsegs);
05972   }
05973   // Contents in 'idx2seglist' are shifted, now shift them back.
05974   for (i = points->items - 1; i >= 0; i--) {
05975     idx2seglist[i + 1] = idx2seglist[i];
05976   }
05977   idx2seglist[0] = 0;
05978 }
05979 
05981 //                                                                           //
05982 // makesubfacemap()    Create a map from vertices (their indices) to         //
05983 //                     subfaces incident at the same vertices.               //
05984 //                                                                           //
05985 // Two arrays 'idx2facelist' and 'facesperverlist' together return the map.  //
05986 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
05987 // number of subfaces.  idx2facelist contains row information and            //
05988 // facesperverlist contains all (non-zero) elements.  The i-th entry of      //
05989 // idx2facelist is the starting position of i-th row's(non-zero) elements in //
05990 // facesperverlist.  The number of elements of i-th row is calculated by the //
05991 // (i+1)-th entry minus i-th entry of idx2facelist.                          //
05992 //                                                                           //
05993 // NOTE: These two arrays will be created inside this routine, don't forget  //
05994 // to free them after using.                                                 //
05995 //                                                                           //
05997 
05998 void tetgenmesh::
05999 makesubfacemap(int*& idx2facelist, shellface**& facesperverlist)
06000 {
06001   shellface *shloop;
06002   int i, j, k;
06003 
06004   if (b->verbose > 0) {
06005     printf("  Constructing mapping from points to subfaces.\n");
06006   }
06007 
06008   // Create and initialize 'idx2facelist'.
06009   idx2facelist = new int[points->items + 1];
06010   for (i = 0; i < points->items + 1; i++) idx2facelist[i] = 0;
06011 
06012   // Loop the set of subfaces once, counter the number of subfaces sharing
06013   //   each vertex.
06014   subfaces->traversalinit();
06015   shloop = shellfacetraverse(subfaces);
06016   while (shloop != (shellface *) NULL) {
06017     // Increment the number of sharing segments for each endpoint.
06018     for (i = 0; i < 3; i++) {
06019       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06020       idx2facelist[j]++;
06021     }
06022     shloop = shellfacetraverse(subfaces);
06023   }
06024 
06025   // Calculate the total length of array 'facesperverlist'.
06026   j = idx2facelist[0];
06027   idx2facelist[0] = 0;  // Array starts from 0 element.
06028   for (i = 0; i < points->items; i++) {
06029     k = idx2facelist[i + 1];
06030     idx2facelist[i + 1] = idx2facelist[i] + j;
06031     j = k;
06032   }
06033   // The total length is in the last unit of idx2facelist.
06034   facesperverlist = new shellface*[idx2facelist[i]];
06035   // Loop the set of segments again, set the info. of segments per vertex.
06036   subfaces->traversalinit();
06037   shloop = shellfacetraverse(subfaces);
06038   while (shloop != (shellface *) NULL) {
06039     for (i = 0; i < 3; i++) {
06040       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06041       facesperverlist[idx2facelist[j]] = shloop;
06042       idx2facelist[j]++;
06043     }
06044     shloop = shellfacetraverse(subfaces);
06045   }
06046   // Contents in 'idx2facelist' are shifted, now shift them back.
06047   for (i = points->items - 1; i >= 0; i--) {
06048     idx2facelist[i + 1] = idx2facelist[i];
06049   }
06050   idx2facelist[0] = 0;
06051 }
06052 
06054 //                                                                           //
06055 // maketetrahedronmap()    Create a map from vertices (their indices) to     //
06056 //                         tetrahedra incident at the same vertices.         //
06057 //                                                                           //
06058 // Two arrays 'idx2tetlist' and 'tetsperverlist' together return the map.    //
06059 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
06060 // number of tetrahedra.  idx2tetlist contains row information and           //
06061 // tetsperverlist contains all (non-zero) elements.  The i-th entry of       //
06062 // idx2tetlist is the starting position of i-th row's (non-zero) elements in //
06063 // tetsperverlist.  The number of elements of i-th row is calculated by the  //
06064 // (i+1)-th entry minus i-th entry of idx2tetlist.                           //
06065 //                                                                           //
06066 // NOTE: These two arrays will be created inside this routine, don't forget  //
06067 // to free them after using.                                                 //
06068 //                                                                           //
06070 
06071 void tetgenmesh::
06072 maketetrahedronmap(int*& idx2tetlist, tetrahedron**& tetsperverlist)
06073 {
06074   tetrahedron *tetloop;
06075   int i, j, k;
06076 
06077   if (b->verbose > 0) {
06078     printf("  Constructing mapping from points to tetrahedra.\n");
06079   }
06080 
06081   // Create and initialize 'idx2tetlist'.
06082   idx2tetlist = new int[points->items + 1];
06083   for (i = 0; i < points->items + 1; i++) idx2tetlist[i] = 0;
06084 
06085   // Loop the set of tetrahedra once, counter the number of tetrahedra
06086   //   sharing each vertex.
06087   tetrahedrons->traversalinit();
06088   tetloop = tetrahedrontraverse();
06089   while (tetloop != (tetrahedron *) NULL) {
06090     // Increment the number of sharing tetrahedra for each endpoint.
06091     for (i = 0; i < 4; i++) {
06092       j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06093       idx2tetlist[j]++;
06094     }
06095     tetloop = tetrahedrontraverse();
06096   }
06097 
06098   // Calculate the total length of array 'tetsperverlist'.
06099   j = idx2tetlist[0];
06100   idx2tetlist[0] = 0;  // Array starts from 0 element.
06101   for (i = 0; i < points->items; i++) {
06102     k = idx2tetlist[i + 1];
06103     idx2tetlist[i + 1] = idx2tetlist[i] + j;
06104     j = k;
06105   }
06106   // The total length is in the last unit of idx2tetlist.
06107   tetsperverlist = new tetrahedron*[idx2tetlist[i]];
06108   // Loop the set of tetrahedra again, set the info. of tet. per vertex.
06109   tetrahedrons->traversalinit();
06110   tetloop = tetrahedrontraverse();
06111   while (tetloop != (tetrahedron *) NULL) {
06112     for (i = 0; i < 4; i++) {
06113       j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06114       tetsperverlist[idx2tetlist[j]] = tetloop;
06115       idx2tetlist[j]++;
06116     }
06117     tetloop = tetrahedrontraverse();
06118   }
06119   // Contents in 'idx2tetlist' are shifted, now shift them back.
06120   for (i = points->items - 1; i >= 0; i--) {
06121     idx2tetlist[i + 1] = idx2tetlist[i];
06122   }
06123   idx2tetlist[0] = 0;
06124 }
06125 
06126 //
06127 // End of mesh items searching routines
06128 //
06129 
06130 //
06131 // Begin of linear algebra functions
06132 //
06133 
06134 // dot() returns the dot product: v1 dot v2.
06135 
06136 inline REAL tetgenmesh::dot(REAL* v1, REAL* v2) 
06137 {
06138   return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
06139 }
06140 
06141 // cross() computes the cross product: n = v1 cross v2.
06142 
06143 inline void tetgenmesh::cross(REAL* v1, REAL* v2, REAL* n) 
06144 {
06145   n[0] =   v1[1] * v2[2] - v2[1] * v1[2];
06146   n[1] = -(v1[0] * v2[2] - v2[0] * v1[2]);
06147   n[2] =   v1[0] * v2[1] - v2[0] * v1[1];
06148 }
06149 
06150 // initm44() initializes a 4x4 matrix.
06151 static void initm44(REAL a00, REAL a01, REAL a02, REAL a03,
06152                     REAL a10, REAL a11, REAL a12, REAL a13,
06153                     REAL a20, REAL a21, REAL a22, REAL a23,
06154                     REAL a30, REAL a31, REAL a32, REAL a33,
06155                     REAL M[4][4])
06156 {
06157   M[0][0] = a00; M[0][1] = a01; M[0][2] = a02; M[0][3] = a03;
06158   M[1][0] = a10; M[1][1] = a11; M[1][2] = a12; M[1][3] = a13;
06159   M[2][0] = a20; M[2][1] = a21; M[2][2] = a22; M[2][3] = a23;
06160   M[3][0] = a30; M[3][1] = a31; M[3][2] = a32; M[3][3] = a33;
06161 }
06162 
06163 // m4xm4() multiplies 2 4x4 matrics:  m1 = m1 * m2.
06164 static void m4xm4(REAL m1[4][4], REAL m2[4][4])
06165 {
06166   REAL tmp[4];
06167   int i, j;
06168 
06169   for (i = 0; i < 4; i++) {   // i-th row
06170     for (j = 0; j < 4; j++) { // j-th col
06171       tmp[j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j] 
06172              + m1[i][2] * m2[2][j] + m1[i][3] * m2[3][j];
06173     }
06174     for (j = 0; j < 4; j++) 
06175       m1[i][j] = tmp[j];
06176   }
06177 }
06178 
06179 // m4xv4() multiplies a 4x4 matrix and 4x1 vector: v2 = m * v1
06180 static void m4xv4(REAL v2[4], REAL m[4][4], REAL v1[4])
06181 {
06182   v2[0] = m[0][0]*v1[0] + m[0][1]*v1[1] + m[0][2]*v1[2] + m[0][3]*v1[3];
06183   v2[1] = m[1][0]*v1[0] + m[1][1]*v1[1] + m[1][2]*v1[2] + m[1][3]*v1[3];
06184   v2[2] = m[2][0]*v1[0] + m[2][1]*v1[1] + m[2][2]*v1[2] + m[2][3]*v1[3];
06185   v2[3] = m[3][0]*v1[0] + m[3][1]*v1[1] + m[3][2]*v1[2] + m[3][3]*v1[3];
06186 }
06187 
06189 //                                                                           //
06190 // lu_decmp()    Compute the LU decomposition of a matrix.                   //
06191 //                                                                           //
06192 // Compute the LU decomposition of a (non-singular) square matrix A using    //
06193 // partial pivoting and implicit row exchanges.  The result is:              //
06194 //     A = P * L * U,                                                        //
06195 // where P is a permutation matrix, L is unit lower triangular, and U is     //
06196 // upper triangular.  The factored form of A is used in combination with     //
06197 // 'lu_solve()' to solve linear equations: Ax = b, or invert a matrix.       //
06198 //                                                                           //
06199 // The inputs are a square matrix 'lu[N..n+N-1][N..n+N-1]', it's size is 'n'.//
06200 // On output, 'lu' is replaced by the LU decomposition of a rowwise permuta- //
06201 // tion of itself, 'ps[N..n+N-1]' is an output vector that records the row   //
06202 // permutation effected by the partial pivoting, effectively,  'ps' array    //
06203 // tells the user what the permutation matrix P is; 'd' is output as +1/-1   //
06204 // depending on whether the number of row interchanges was even or odd,      //
06205 // respectively.                                                             //
06206 //                                                                           //
06207 // Return true if the LU decomposition is successfully computed, otherwise,  //
06208 // return false in case that A is a singular matrix.                         //
06209 //                                                                           //
06211 
06212 bool tetgenmesh::lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N)
06213 {
06214   REAL scales[4];
06215   REAL pivot, biggest, mult, tempf;
06216   int pivotindex = 0;
06217   int i, j, k;
06218 
06219   *d = 1.0;                                      // No row interchanges yet.
06220 
06221   for (i = N; i < n + N; i++) {                             // For each row.
06222     // Find the largest element in each row for row equilibration
06223     biggest = 0.0;
06224     for (j = N; j < n + N; j++)
06225       if (biggest < (tempf = fabs(lu[i][j])))
06226         biggest  = tempf;
06227     if (biggest != 0.0)
06228       scales[i] = 1.0 / biggest;
06229     else {
06230       scales[i] = 0.0;
06231       return false;                            // Zero row: singular matrix.
06232     }
06233     ps[i] = i;                                 // Initialize pivot sequence.
06234   }
06235 
06236   for (k = N; k < n + N - 1; k++) {                      // For each column.
06237     // Find the largest element in each column to pivot around.
06238     biggest = 0.0;
06239     for (i = k; i < n + N; i++) {
06240       if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
06241         biggest = tempf;
06242         pivotindex = i;
06243       }
06244     }
06245     if (biggest == 0.0) {
06246       return false;                         // Zero column: singular matrix.
06247     }
06248     if (pivotindex != k) {                         // Update pivot sequence.
06249       j = ps[k];
06250       ps[k] = ps[pivotindex];
06251       ps[pivotindex] = j;
06252       *d = -(*d);                          // ...and change the parity of d.
06253     }
06254 
06255     // Pivot, eliminating an extra variable  each time
06256     pivot = lu[ps[k]][k];
06257     for (i = k + 1; i < n + N; i++) {
06258       lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
06259       if (mult != 0.0) {
06260         for (j = k + 1; j < n + N; j++)
06261           lu[ps[i]][j] -= mult * lu[ps[k]][j];
06262       }
06263     }
06264   }
06265 
06266   // (lu[ps[n + N - 1]][n + N - 1] == 0.0) ==> A is singular.
06267   return lu[ps[n + N - 1]][n + N - 1] != 0.0;
06268 }
06269 
06271 //                                                                           //
06272 // lu_solve()    Solves the linear equation:  Ax = b,  after the matrix A    //
06273 //               has been decomposed into the lower and upper triangular     //
06274 //               matrices L and U, where A = LU.                             //
06275 //                                                                           //
06276 // 'lu[N..n+N-1][N..n+N-1]' is input, not as the matrix 'A' but rather as    //
06277 // its LU decomposition, computed by the routine 'lu_decmp'; 'ps[N..n+N-1]'  //
06278 // is input as the permutation vector returned by 'lu_decmp';  'b[N..n+N-1]' //
06279 // is input as the right-hand side vector, and returns with the solution     //
06280 // vector. 'lu', 'n', and 'ps' are not modified by this routine and can be   //
06281 // left in place for successive calls with different right-hand sides 'b'.   //
06282 //                                                                           //
06284 
06285 void tetgenmesh::lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N)
06286 {
06287   int i, j;
06288   REAL X[4], dot;
06289 
06290   for (i = N; i < n + N; i++) X[i] = 0.0;
06291 
06292   // Vector reduction using U triangular matrix.
06293   for (i = N; i < n + N; i++) {
06294     dot = 0.0;
06295     for (j = N; j < i + N; j++)
06296       dot += lu[ps[i]][j] * X[j];
06297     X[i] = b[ps[i]] - dot;
06298   }
06299 
06300   // Back substitution, in L triangular matrix.
06301   for (i = n + N - 1; i >= N; i--) {
06302     dot = 0.0;
06303     for (j = i + 1; j < n + N; j++)
06304       dot += lu[ps[i]][j] * X[j];
06305     X[i] = (X[i] - dot) / lu[ps[i]][i];
06306   }
06307 
06308   for (i = N; i < n + N; i++) b[i] = X[i];
06309 }
06310 
06311 //
06312 // End of linear algebra functions
06313 //
06314 
06315 //
06316 // Begin of geometric tests
06317 //
06318 
06319 // All the following routines require the input objects are not degenerate.
06320 //   i.e., a triangle must has three non-collinear corners; an edge must
06321 //   has two identical endpoints.  Degenerate cases should have to detect
06322 //   first and then handled as special cases.
06323 
06325 //                                                                           //
06326 // edge_vert_col_inter()    Test whether an edge (ab) and a collinear vertex //
06327 //                          (p) are intersecting or not.                     //
06328 //                                                                           //
06329 // Possible cases are p is coincident to a (p = a), or to b (p = b), or p is //
06330 // inside ab (a < p < b), or outside ab (p < a or p > b). These cases can be //
06331 // quickly determined by comparing the corresponding coords of a, b, and p   //
06332 // (which are not all equal).                                                //
06333 //                                                                           //
06334 // The return value indicates one of the three cases: DISJOINT, SHAREVERTEX  //
06335 // (p = a or p = b), and INTERSECT (a < p < b).                              //
06336 //                                                                           //
06338 
06339 enum tetgenmesh::interresult tetgenmesh::edge_vert_col_inter(REAL* A, REAL* B,
06340   REAL* P)
06341 {
06342   int i = 0;
06343   do {
06344     if (A[i] < B[i]) {
06345       if (P[i] < A[i]) {
06346         return DISJOINT;
06347       } else if (P[i] > A[i]) {
06348         if (P[i] < B[i]) {
06349           return INTERSECT;
06350         } else if (P[i] > B[i]) {
06351           return DISJOINT;
06352         } else {
06353           // assert(P[i] == B[i]);
06354           return SHAREVERTEX;
06355         }
06356       } else {
06357         // assert(P[i] == A[i]);
06358         return SHAREVERTEX;
06359       }
06360     } else if (A[i] > B[i]) {
06361       if (P[i] < B[i]) {
06362         return DISJOINT;
06363       } else if (P[i] > B[i]) {
06364         if (P[i] < A[i]) {
06365           return INTERSECT;
06366         } else if (P[i] > A[i]) {
06367           return DISJOINT;
06368         } else {
06369           // assert(P[i] == A[i]);
06370           return SHAREVERTEX;
06371         }
06372       } else {
06373         // assert(P[i] == B[i]);
06374         return SHAREVERTEX;
06375       }
06376     }
06377     // i-th coordinates are equal, try i+1-th;
06378     i++;
06379   } while (i < 3);
06380   // Should never be here.
06381   return DISJOINT;
06382 }
06383 
06385 //                                                                           //
06386 // edge_edge_cop_inter()    Test whether two coplanar edges (ab, and pq) are //
06387 //                          intersecting or not.                             //
06388 //                                                                           //
06389 // Possible cases are ab and pq are disjointed, or proper intersecting (int- //
06390 // ersect at a point other than their endpoints), or both collinear and int- //
06391 // ersecting, or sharing at a common endpoint, or are coincident.            //
06392 //                                                                           //
06393 // A reference point R is required, which is exactly not coplanar with these //
06394 // two edges.  Since the caller knows these two edges are coplanar, it must  //
06395 // be able to provide (or calculate) such a point.                           //
06396 //                                                                           //
06397 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06398 // SHAREEDGE, and INTERSECT.                                                 //
06399 //                                                                           //
06401 
06402 enum tetgenmesh::interresult tetgenmesh:: edge_edge_cop_inter(REAL* A, REAL* B,
06403   REAL* P, REAL* Q, REAL* R)
06404 {
06405   REAL s1, s2, s3, s4;
06406 
06407 #ifdef SELF_CHECK
06408   assert(R != NULL);
06409 #endif
06410   s1 = orient3d(A, B, R, P);
06411   s2 = orient3d(A, B, R, Q);
06412   if (s1 * s2 > 0.0) {
06413     // Both p and q are at the same side of ab.
06414     return DISJOINT;
06415   }
06416   s3 = orient3d(P, Q, R, A);
06417   s4 = orient3d(P, Q, R, B);
06418   if (s3 * s4 > 0.0) {
06419     // Both a and b are at the same side of pq.
06420     return DISJOINT;
06421   }
06422 
06423   // Possible degenerate cases are:
06424   //   (1) Only one of p and q is collinear with ab;
06425   //   (2) Both p and q are collinear with ab;
06426   //   (3) Only one of a and b is collinear with pq. 
06427   enum interresult abp, abq;
06428   enum interresult pqa, pqb;
06429 
06430   if (s1 == 0.0) {
06431     // p is collinear with ab.
06432     abp = edge_vert_col_inter(A, B, P);
06433     if (abp == INTERSECT) {
06434       // p is inside ab.
06435       return INTERSECT;
06436     }
06437     if (s2 == 0.0) {
06438       // q is collinear with ab. Case (2).
06439       abq = edge_vert_col_inter(A, B, Q);
06440       if (abq == INTERSECT) {
06441         // q is inside ab.
06442         return INTERSECT;
06443       }
06444       if (abp == SHAREVERTEX && abq == SHAREVERTEX) {
06445         // ab and pq are identical.
06446         return SHAREEDGE;
06447       }
06448       pqa = edge_vert_col_inter(P, Q, A);
06449       if (pqa == INTERSECT) {
06450         // a is inside pq.
06451         return INTERSECT;
06452       }
06453       pqb = edge_vert_col_inter(P, Q, B);
06454       if (pqb == INTERSECT) {
06455         // b is inside pq.
06456         return INTERSECT;
06457       }
06458       if (abp == SHAREVERTEX || abq == SHAREVERTEX) {
06459         // either p or q is coincident with a or b.
06460 #ifdef SELF_CHECK
06461         // ONLY one case is possible, otherwise, shoule be SHAREEDGE.
06462         assert(abp ^ abq);
06463 #endif
06464         return SHAREVERTEX;
06465       }
06466       // The last case. They are disjointed.
06467 #ifdef SELF_CHECK
06468       assert((abp == DISJOINT) && (abp == abq && abq == pqa && pqa == pqb));
06469 #endif
06470       return DISJOINT;
06471     } else {
06472       // p is collinear with ab. Case (1).
06473 #ifdef SELF_CHECK
06474       assert(abp == SHAREVERTEX || abp == DISJOINT);
06475 #endif
06476       return abp;
06477     }
06478   }
06479   // p is NOT collinear with ab.
06480   if (s2 == 0.0) {
06481     // q is collinear with ab. Case (1).
06482     abq = edge_vert_col_inter(A, B, Q);
06483 #ifdef SELF_CHECK
06484     assert(abq == SHAREVERTEX || abq == DISJOINT || abq == INTERSECT);
06485 #endif
06486     return abq;
06487   }
06488 
06489   // We have found p and q are not collinear with ab. However, it is still
06490   //   possible that a or b is collinear with pq (ONLY one of a and b).
06491   if (s3 == 0.0) {
06492     // a is collinear with pq. Case (3).
06493 #ifdef SELF_CHECK
06494     assert(s4 != 0.0);
06495 #endif
06496     pqa = edge_vert_col_inter(P, Q, A);
06497 #ifdef SELF_CHECK
06498     // This case should have been detected in above.
06499     assert(pqa != SHAREVERTEX);
06500     assert(pqa == INTERSECT || pqa == DISJOINT);
06501 #endif
06502     return pqa;
06503   }
06504   if (s4 == 0.0) {
06505     // b is collinear with pq. Case (3).
06506 #ifdef SELF_CHECK
06507     assert(s3 != 0.0);
06508 #endif
06509     pqb = edge_vert_col_inter(P, Q, B);
06510 #ifdef SELF_CHECK
06511     // This case should have been detected in above.
06512     assert(pqb != SHAREVERTEX);
06513     assert(pqb == INTERSECT || pqb == DISJOINT);
06514 #endif
06515     return pqb;
06516   }
06517 
06518   // ab and pq are intersecting properly.
06519   return INTERSECT;
06520 }
06521 
06523 //                                                                           //
06524 // Notations                                                                 //
06525 //                                                                           //
06526 // Let ABC be the plane passes through a, b, and c;  ABC+ be the halfspace   //
06527 // including the set of all points x, such that orient3d(a, b, c, x) > 0;    //
06528 // ABC- be the other halfspace, such that for each point x in ABC-,          //
06529 // orient3d(a, b, c, x) < 0.  For the set of x which are on ABC, orient3d(a, //
06530 // b, c, x) = 0.                                                             //
06531 //                                                                           //
06533 
06535 //                                                                           //
06536 // tri_vert_copl_inter()    Test whether a triangle (abc) and a coplanar     //
06537 //                          point (p) are intersecting or not.               //
06538 //                                                                           //
06539 // Possible cases are p is inside abc, or on an edge of, or coincident with  //
06540 // a vertex of, or outside abc.                                              //
06541 //                                                                           //
06542 // A reference point R is required. R is exactly not coplanar with abc and p.//
06543 // Since the caller knows they are coplanar, it must be able to provide (or  //
06544 // calculate) such a point.                                                  //
06545 //                                                                           //
06546 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06547 // and INTERSECT.                                                            //
06548 //                                                                           //
06550 
06551 enum tetgenmesh::interresult tetgenmesh::tri_vert_cop_inter(REAL* A, REAL* B,
06552   REAL* C, REAL* P, REAL* R)
06553 {
06554   REAL s1, s2, s3;
06555   int sign;
06556 
06557 #ifdef SELF_CHECK
06558   assert(R != (REAL *) NULL);
06559 #endif
06560   // Adjust the orientation of a, b, c and r, so that we can assume that
06561   //   r is strictly in ABC- (i.e., r is above ABC wrt. right-hand rule).
06562   s1 = orient3d(A, B, C, R);
06563 #ifdef SELF_CHECK
06564   assert(s1 != 0.0);
06565 #endif
06566   sign = s1 < 0.0 ? 1 : -1;
06567 
06568   // Test starts from here.
06569   s1 = orient3d(A, B, R, P) * sign;
06570   if (s1 < 0.0) {
06571     // p is in ABR-.
06572     return DISJOINT;
06573   }
06574   s2 = orient3d(B, C, R, P) * sign;
06575   if (s2 < 0.0) {
06576     // p is in BCR-.
06577     return DISJOINT;
06578   }
06579   s3 = orient3d(C, A, R, P) * sign;
06580   if (s3 < 0.0) {
06581     // p is in CAR-.
06582     return DISJOINT;
06583   }
06584   if (s1 == 0.0) {
06585     // p is on ABR.
06586     if (s2 == 0.0) {
06587       // p is on BCR.
06588 #ifdef SELF_CHECK
06589       assert(s3 > 0.0);
06590 #endif
06591       // p is coincident with b.
06592       return SHAREVERTEX;
06593     }
06594     if (s3 == 0.0) {
06595       // p is on CAR.
06596       // p is coincident with a.
06597       return SHAREVERTEX;
06598     }
06599     // p is on edge ab.
06600     return INTERSECT;
06601   }
06602   // p is in ABR+.
06603   if (s2 == 0.0) {
06604     // p is on BCR.
06605     if (s3 == 0.0) {
06606       // p is on CAR.
06607       // p is coincident with c.
06608       return SHAREVERTEX;
06609     }
06610     // p is on edge bc.
06611     return INTERSECT;
06612   }
06613   if (s3 == 0.0) {
06614     // p is on CAR.
06615     // p is on edge ca.
06616     return INTERSECT;
06617   }
06618 
06619   // p is strictly inside abc.
06620   return INTERSECT;
06621 }
06622 
06624 //                                                                           //
06625 // tri_edge_cop_inter()    Test whether a triangle (abc) and a coplanar edge //
06626 //                         (pq) are intersecting or not.                     //
06627 //                                                                           //
06628 // A reference point R is required. R is exactly not coplanar with abc and   //
06629 // pq.  Since the caller knows they are coplanar, it must be able to provide //
06630 // (or calculate) such a point.                                              //
06631 //                                                                           //
06632 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06633 // SHAREEDGE, and INTERSECT.                                                 //
06634 //                                                                           //
06636 
06637 enum tetgenmesh::interresult tetgenmesh::tri_edge_cop_inter(REAL* A, REAL* B,
06638   REAL* C, REAL* P, REAL* Q, REAL* R)
06639 {
06640   enum interresult abpq, bcpq, capq;
06641   enum interresult abcp, abcq;
06642 
06643   // Test if pq is intersecting one of edges of abc.
06644   abpq = edge_edge_cop_inter(A, B, P, Q, R);
06645   if (abpq == INTERSECT || abpq == SHAREEDGE) {
06646     return abpq;
06647   }
06648   bcpq = edge_edge_cop_inter(B, C, P, Q, R);
06649   if (bcpq == INTERSECT || bcpq == SHAREEDGE) {
06650     return bcpq;
06651   }
06652   capq = edge_edge_cop_inter(C, A, P, Q, R);
06653   if (capq == INTERSECT || capq == SHAREEDGE) {
06654     return capq;
06655   }
06656   
06657   // Test if p and q is inside abc.
06658   abcp = tri_vert_cop_inter(A, B, C, P, R);
06659   if (abcp == INTERSECT) {
06660     return INTERSECT;
06661   }
06662   abcq = tri_vert_cop_inter(A, B, C, Q, R);
06663   if (abcq == INTERSECT) {
06664     return INTERSECT;
06665   }
06666 
06667   // Combine the test results of edge intersectings and triangle insides
06668   //   to detect whether abc and pq are sharing vertex or disjointed.
06669   if (abpq == SHAREVERTEX) {
06670     // p or q is coincident with a or b.
06671 #ifdef SELF_CHECK
06672     assert(abcp ^ abcq);
06673 #endif
06674     return SHAREVERTEX;
06675   }
06676   if (bcpq == SHAREVERTEX) {
06677     // p or q is coincident with b or c.
06678 #ifdef SELF_CHECK
06679     assert(abcp ^ abcq);
06680 #endif
06681     return SHAREVERTEX;
06682   }
06683   if (capq == SHAREVERTEX) {
06684     // p or q is coincident with c or a.
06685 #ifdef SELF_CHECK
06686     assert(abcp ^ abcq);
06687 #endif
06688     return SHAREVERTEX;
06689   }
06690 
06691   // They are disjointed.
06692   return DISJOINT;
06693 }
06694 
06696 //                                                                           //
06697 // tri_edge_inter_tail()    Test whether a triangle (abc) and an edge (pq)   //
06698 //                          are intersecting or not.                         //
06699 //                                                                           //
06700 // s1 and s2 are results of pre-performed orientation tests. s1 = orient3d(  //
06701 // a, b, c, p); s2 = orient3d(a, b, c, q).  To separate this routine from    //
06702 // tri_edge_inter() can save two orientation tests in tri_tri_inter().       //
06703 //                                                                           //
06704 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06705 // SHAREEDGE, and INTERSECT.                                                 //
06706 //                                                                           //
06708 
06709 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter_tail(REAL* A, REAL* B,
06710   REAL* C, REAL* P, REAL* Q, REAL s1, REAL s2)
06711 {
06712   REAL s3, s4, s5;
06713   int sign;
06714 
06715   if (s1 * s2 > 0.0) {
06716     // p, q are at the same halfspace of ABC, no intersection.
06717     return DISJOINT;
06718   }
06719 
06720   if (s1 * s2 < 0.0) {
06721     // p, q are both not on ABC (and not sharing vertices, edges of abc).
06722     // Adjust the orientation of a, b, c and p, so that we can assume that
06723     //   p is strictly in ABC-, and q is strictly in ABC+.
06724     sign = s1 < 0.0 ? 1 : -1;
06725     s3 = orient3d(A, B, P, Q) * sign;
06726     if (s3 < 0.0) {
06727       // q is at ABP-.
06728       return DISJOINT;
06729     }
06730     s4 = orient3d(B, C, P, Q) * sign;
06731     if (s4 < 0.0) {
06732       // q is at BCP-.
06733       return DISJOINT;
06734     }
06735     s5 = orient3d(C, A, P, Q) * sign;
06736     if (s5 < 0.0) {
06737       // q is at CAP-.
06738       return DISJOINT;
06739     }
06740     if (s3 == 0.0) {
06741       // q is on ABP.
06742       if (s4 == 0.0) {
06743         // q is on BCP (and q must in CAP+).
06744 #ifdef SELF_CHECK
06745         assert(s5 > 0.0); 
06746 #endif
06747         // pq intersects abc at vertex b.
06748         return SHAREVERTEX;
06749       }
06750       if (s5 == 0.0) {
06751         // q is on CAP (and q must in BCP+).
06752         // pq intersects abc at vertex a.
06753         return SHAREVERTEX;
06754       }
06755       // q in both BCP+ and CAP+.
06756       // pq crosses ab properly.
06757       return INTERSECT;
06758     }
06759     // q is in ABP+;
06760     if (s4 == 0.0) {
06761       // q is on BCP.
06762       if (s5 == 0.0) {
06763         // q is on CAP.
06764         // pq intersects abc at vertex c.
06765         return SHAREVERTEX;
06766       }
06767       // pq crosses bc properly.
06768       return INTERSECT;
06769     }
06770     // q is in BCP+;
06771     if (s5 == 0.0) {
06772       // q is on CAP.
06773       // pq crosses ca properly.
06774       return INTERSECT;
06775     }
06776     // q is in CAP+;
06777     // pq crosses abc properly.
06778     return INTERSECT;
06779   }
06780 
06781   if (s1 != 0.0 || s2 != 0.0) {
06782     // Either p or q is coplanar with abc. ONLY one of them is possible.
06783     if (s1 == 0.0) {
06784       // p is coplanar with abc, q can be used as reference point.
06785 #ifdef SELF_CHECK
06786       assert(s2 != 0.0);
06787 #endif
06788       return tri_vert_cop_inter(A, B, C, P, Q);
06789     } else {
06790       // q is coplanar with abc, p can be used as reference point.
06791 #ifdef SELF_CHECK
06792       assert(s2 == 0.0);
06793 #endif
06794       return tri_vert_cop_inter(A, B, C, Q, P);
06795     }
06796   }
06797 
06798   // pq is coplanar with abc.  Calculate a point which is exactly not
06799   //   coplanar with a, b, and c.
06800   REAL R[3], N[3];
06801   REAL ax, ay, az, bx, by, bz;
06802   
06803   ax = A[0] - B[0];
06804   ay = A[1] - B[1];
06805   az = A[2] - B[2];
06806   bx = A[0] - C[0];
06807   by = A[1] - C[1];
06808   bz = A[2] - C[2];
06809   N[0] = ay * bz - by * az;
06810   N[1] = az * bx - bz * ax;
06811   N[2] = ax * by - bx * ay;
06812   // The normal should not be a zero vector (otherwise, abc are collinear).
06813 #ifdef SELF_CHECK
06814   assert((fabs(N[0]) + fabs(N[1]) + fabs(N[2])) > 0.0);
06815 #endif
06816   // The reference point R is lifted from A to the normal direction with
06817   //   a distance d = average edge length of the triangle abc.
06818   R[0] = N[0] + A[0];
06819   R[1] = N[1] + A[1];
06820   R[2] = N[2] + A[2];
06821   // Becareful the case: if the non-zero component(s) in N is smaller than
06822   //   the machine epsilon (i.e., 2^(-16) for double), R will exactly equal
06823   //   to A due to the round-off error.  Do check if it is.
06824   if (R[0] == A[0] && R[1] == A[1] && R[2] == A[2]) {
06825     int i, j;
06826     for (i = 0; i < 3; i++) {
06827 #ifdef SELF_CHECK
06828       assert (R[i] == A[i]);
06829 #endif
06830       j = 2;
06831       do {
06832         if (N[i] > 0.0) {
06833           N[i] += (j * macheps);
06834         } else {
06835           N[i] -= (j * macheps);
06836         }
06837         R[i] = N[i] + A[i];
06838         j *= 2;
06839       } while (R[i] == A[i]);
06840     }
06841   }
06842 
06843   return tri_edge_cop_inter(A, B, C, P, Q, R);
06844 }
06845 
06847 //                                                                           //
06848 // tri_edge_inter()    Test whether a triangle (abc) and an edge (pq) are    //
06849 //                     intersecting or not.                                  //
06850 //                                                                           //
06851 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06852 // SHAREEDGE, and INTERSECT.                                                 //
06853 //                                                                           //
06855 
06856 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter(REAL* A, REAL* B,
06857   REAL* C, REAL* P, REAL* Q)
06858 {
06859   REAL s1, s2;
06860 
06861   // Test the locations of p and q with respect to ABC.
06862   s1 = orient3d(A, B, C, P);
06863   s2 = orient3d(A, B, C, Q);
06864 
06865   return tri_edge_inter_tail(A, B, C, P, Q, s1, s2);
06866 }
06867 
06869 //                                                                           //
06870 // tri_tri_inter()    Test whether two triangle (abc) and (opq) are          //
06871 //                    intersecting or not.                                   //
06872 //                                                                           //
06873 // The return value indicates one of the five cases: DISJOINT, SHAREVERTEX,  //
06874 // SHAREEDGE, SHAREFACE, and INTERSECT.                                      //
06875 //                                                                           //
06877 
06878 enum tetgenmesh::interresult tetgenmesh::tri_tri_inter(REAL* A, REAL* B,
06879   REAL* C, REAL* O, REAL* P, REAL* Q)
06880 {
06881   REAL s_o, s_p, s_q;
06882   REAL s_a, s_b, s_c;
06883 
06884   s_o = orient3d(A, B, C, O);
06885   s_p = orient3d(A, B, C, P);
06886   s_q = orient3d(A, B, C, Q);
06887   if ((s_o * s_p > 0.0) && (s_o * s_q > 0.0)) {
06888     // o, p, q are all in the same halfspace of ABC.
06889     return DISJOINT;
06890   }
06891 
06892   s_a = orient3d(O, P, Q, A);
06893   s_b = orient3d(O, P, Q, B);
06894   s_c = orient3d(O, P, Q, C);
06895   if ((s_a * s_b > 0.0) && (s_a * s_c > 0.0)) {
06896     // a, b, c are all in the same halfspace of OPQ.
06897     return DISJOINT;
06898   }
06899 
06900   enum interresult abcop, abcpq, abcqo;
06901   int shareedge = 0;
06902 
06903   abcop = tri_edge_inter_tail(A, B, C, O, P, s_o, s_p);
06904   if (abcop == INTERSECT) {
06905     return INTERSECT;
06906   } else if (abcop == SHAREEDGE) {
06907     shareedge++;
06908   }
06909   abcpq = tri_edge_inter_tail(A, B, C, P, Q, s_p, s_q);
06910   if (abcpq == INTERSECT) {
06911     return INTERSECT;
06912   } else if (abcpq == SHAREEDGE) {
06913     shareedge++;
06914   }
06915   abcqo = tri_edge_inter_tail(A, B, C, Q, O, s_q, s_o);
06916   if (abcqo == INTERSECT) {
06917     return INTERSECT;
06918   } else if (abcqo == SHAREEDGE) {
06919     shareedge++;
06920   }
06921   if (shareedge == 3) {
06922     // opq are coincident with abc.
06923     return SHAREFACE;
06924   }
06925 #ifdef SELF_CHECK
06926   // It is only possible either no share edge or one.
06927   assert(shareedge == 0 || shareedge == 1);
06928 #endif
06929 
06930   // Continue to detect whether opq and abc are intersecting or not.
06931   enum interresult opqab, opqbc, opqca;
06932 
06933   opqab = tri_edge_inter_tail(O, P, Q, A, B, s_a, s_b);
06934   if (opqab == INTERSECT) {
06935     return INTERSECT;
06936   }
06937   opqbc = tri_edge_inter_tail(O, P, Q, B, C, s_b, s_c);
06938   if (opqbc == INTERSECT) {
06939     return INTERSECT;
06940   }
06941   opqca = tri_edge_inter_tail(O, P, Q, C, A, s_c, s_a);
06942   if (opqca == INTERSECT) {
06943     return INTERSECT;
06944   }
06945 
06946   // At this point, two triangles are not intersecting and not coincident.
06947   //   They may be share an edge, or share a vertex, or disjoint.
06948   if (abcop == SHAREEDGE) {
06949 #ifdef SELF_CHECK
06950     assert(abcpq == SHAREVERTEX && abcqo == SHAREVERTEX);
06951 #endif
06952     // op is coincident with an edge of abc.
06953     return SHAREEDGE;
06954   }
06955   if (abcpq == SHAREEDGE) {
06956 #ifdef SELF_CHECK
06957     assert(abcop == SHAREVERTEX && abcqo == SHAREVERTEX);
06958 #endif
06959     // pq is coincident with an edge of abc.
06960     return SHAREEDGE;
06961   }
06962   if (abcqo == SHAREEDGE) {
06963 #ifdef SELF_CHECK
06964     assert(abcop == SHAREVERTEX && abcpq == SHAREVERTEX);
06965 #endif
06966     // qo is coincident with an edge of abc.
06967     return SHAREEDGE;
06968   }
06969 
06970   // They may share a vertex or disjoint.
06971   if (abcop == SHAREVERTEX) {
06972     // o or p is coincident with a vertex of abc.
06973     if (abcpq == SHAREVERTEX) {
06974       // p is the coincident vertex.
06975 #ifdef SELF_CHECK
06976       assert(abcqo != SHAREVERTEX);
06977 #endif
06978     } else {
06979       // o is the coincident vertex.
06980 #ifdef SELF_CHECK
06981       assert(abcqo == SHAREVERTEX);
06982 #endif
06983     }
06984     return SHAREVERTEX;
06985   }
06986   if (abcpq == SHAREVERTEX) {
06987     // q is the coincident vertex.
06988 #ifdef SELF_CHECK
06989     assert(abcqo == SHAREVERTEX);
06990 #endif
06991     return SHAREVERTEX;
06992   }
06993 
06994   // They are disjoint.
06995   return DISJOINT;
06996 }
06997 
06999 //                                                                           //
07000 // insphere_sos()    Insphere test with symbolic perturbation.               //
07001 //                                                                           //
07002 // The input points a, b, c, and d should be non-coplanar. They must be ord- //
07003 // ered so that they have a positive orientation (as defined by orient3d()), //
07004 // or the sign of the result will be reversed.                               //
07005 //                                                                           //
07006 // Return a positive value if the point e lies inside the circumsphere of a, //
07007 // b, c, and d; a negative value if it lies outside.                         //
07008 //                                                                           //
07010 
07011 REAL tetgenmesh::insphere_sos(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
07012   int ia, int ib, int ic, int id, int ie)
07013 {
07014   REAL det;
07015 
07016   det = insphere(pa, pb, pc, pd, pe);
07017   if (det != 0.0) {
07018     return det;
07019   }
07020   
07021   // det = 0.0, use symbolic perturbation.
07022   REAL *p[5], *tmpp;
07023   REAL sign, det_c, det_d;
07024   int idx[5], perm, tmp; 
07025   int n, i, j; 
07026 
07027   p[0] = pa; idx[0] = ia;
07028   p[1] = pb; idx[1] = ib;
07029   p[2] = pc; idx[2] = ic;
07030   p[3] = pd; idx[3] = id;
07031   p[4] = pe; idx[4] = ie;
07032 
07033   // Bubble sort the points by the increasing order of the indices.
07034   n = 5;
07035   perm = 0; // The number of total swaps.
07036   for (i = 0; i < n - 1; i++) {
07037     for (j = 0; j < n - 1 - i; j++) {
07038       if (idx[j + 1] < idx[j]) {  // compare the two neighbors.
07039         tmp = idx[j];         // swap idx[j] and idx[j + 1]
07040         idx[j] = idx[j + 1];
07041         idx[j + 1] = tmp;
07042         tmpp = p[j];         // swap p[j] and p[j + 1]
07043         p[j] = p[j + 1];
07044         p[j + 1] = tmpp;
07045         perm++;
07046       }
07047     }
07048   }
07049 
07050   sign = (perm % 2 == 0) ? 1.0 : -1.0; 
07051   det_c = orient3d(p[1], p[2], p[3], p[4]); // orient3d(b, c, d, e)
07052   if (det_c != 0.0) {
07053     return sign * det_c;
07054   }
07055   det_d = orient3d(p[0], p[2], p[3], p[4]); // orient3d(a, c, d, e)
07056   return -sign * det_d;
07057 }
07058 
07060 //                                                                           //
07061 // iscollinear()    Check if three points are approximately collinear.       //
07062 //                                                                           //
07063 // 'eps' is a relative error tolerance.  The collinearity is determined by   //
07064 // the value q = cos(theta), where theta is the angle between two vectors    //
07065 // A->B and A->C.  They're collinear if 1.0 - q <= epspp.                    //
07066 //                                                                           //
07068 
07069 bool tetgenmesh::iscollinear(REAL* A, REAL* B, REAL* C, REAL eps)
07070 {
07071   REAL abx, aby, abz;
07072   REAL acx, acy, acz;
07073   REAL Lv, Lw, dd;
07074   REAL d, q;
07075 
07076   // Limit of two closed points.
07077   q = longest * eps;
07078   q *= q;
07079 
07080   abx = A[0] - B[0];
07081   aby = A[1] - B[1];
07082   abz = A[2] - B[2];
07083   acx = A[0] - C[0];
07084   acy = A[1] - C[1];
07085   acz = A[2] - C[2];
07086   Lv = abx * abx + aby * aby + abz * abz;
07087   // Is AB (nearly) indentical?
07088   if (Lv < q) return true;
07089   Lw = acx * acx + acy * acy + acz * acz;
07090   // Is AC (nearly) indentical?
07091   if (Lw < q) return true;
07092   dd = abx * acx + aby * acy + abz * acz;
07093   
07094   d = (dd * dd) / (Lv * Lw);
07095   if (d > 1.0) d = 1.0; // Rounding.
07096   q = 1.0 - sqrt(d); // Notice 0 < q < 1.0.
07097   
07098   return q <= eps;
07099 }
07100 
07102 //                                                                           //
07103 // iscoplanar()    Check if four points are approximately coplanar.          //
07104 //                                                                           //
07105 // 'vol6' is six times of the signed volume of the tetrahedron formed by the //
07106 // four points. 'eps' is the relative error tolerance.  The coplanarity is   //
07107 // determined by the value: q = fabs(vol6) / L^3,  where L is the average    //
07108 // edge length of the tet. They're coplanar if q <= eps.                     //
07109 //                                                                           //
07111 
07112 bool tetgenmesh::
07113 iscoplanar(REAL* k, REAL* l, REAL* m, REAL* n, REAL vol6, REAL eps)
07114 {
07115   REAL L, q;
07116   REAL x, y, z;  
07117 
07118   if (vol6 == 0.0) return true;
07119 
07120   x = k[0] - l[0];
07121   y = k[1] - l[1];
07122   z = k[2] - l[2];
07123   L = sqrt(x * x + y * y + z * z);
07124   x = l[0] - m[0];
07125   y = l[1] - m[1];
07126   z = l[2] - m[2];
07127   L += sqrt(x * x + y * y + z * z);
07128   x = m[0] - k[0];
07129   y = m[1] - k[1];
07130   z = m[2] - k[2];
07131   L += sqrt(x * x + y * y + z * z);
07132   x = k[0] - n[0];
07133   y = k[1] - n[1];
07134   z = k[2] - n[2];
07135   L += sqrt(x * x + y * y + z * z);
07136   x = l[0] - n[0];
07137   y = l[1] - n[1];
07138   z = l[2] - n[2];
07139   L += sqrt(x * x + y * y + z * z);
07140   x = m[0] - n[0];
07141   y = m[1] - n[1];
07142   z = m[2] - n[2];
07143   L += sqrt(x * x + y * y + z * z);
07144 #ifdef SELF_CHECK
07145   assert(L > 0.0);
07146 #endif
07147   L /= 6.0;
07148   q = fabs(vol6) / (L * L * L);
07149   
07150   return q <= eps;
07151 }
07152 
07154 //                                                                           //
07155 // iscospheric()    Check if five points are approximately coplanar.         //
07156 //                                                                           //
07157 // 'vol24' is the 24 times of the signed volume of the 4-dimensional simplex //
07158 // formed by the five points. 'eps' is the relative tolerance. The cosphere  //
07159 // case is determined by the value: q = fabs(vol24) / L^4,  where L is the   //
07160 // average edge length of the simplex. They're cosphere if q <= eps.         //
07161 //                                                                           //
07163 
07164 bool tetgenmesh::
07165 iscospheric(REAL* k, REAL* l, REAL* m, REAL* n, REAL* o, REAL vol24, REAL eps)
07166 {
07167   REAL L, q;
07168 
07169   // A 4D simplex has 10 edges.
07170   L = distance(k, l);
07171   L += distance(l, m);
07172   L += distance(m, k);
07173   L += distance(k, n);
07174   L += distance(l, n);
07175   L += distance(m, n);
07176   L += distance(k, o);
07177   L += distance(l, o);
07178   L += distance(m, o);
07179   L += distance(n, o);
07180 #ifdef SELF_CHECK
07181   assert(L > 0.0);
07182 #endif
07183   L /= 10.0;
07184   q = fabs(vol24) / (L * L * L * L);
07185 
07186   return q < eps;
07187 }
07188 
07189 //
07190 // End of geometric tests
07191 //
07192 
07193 //
07194 // Begin of Geometric quantities calculators
07195 //
07196 
07197 // distance() computs the Euclidean distance between two points.
07198 inline REAL tetgenmesh::distance(REAL* p1, REAL* p2)
07199 {
07200   return sqrt((p2[0] - p1[0]) * (p2[0] - p1[0]) +
07201               (p2[1] - p1[1]) * (p2[1] - p1[1]) +
07202               (p2[2] - p1[2]) * (p2[2] - p1[2]));
07203 }
07204 
07206 //                                                                           //
07207 // shortdistance()    Returns the shortest distance from point p to a line   //
07208 //                    defined by two points e1 and e2.                       //
07209 //                                                                           //
07210 // First compute the projection length l_p of the vector v1 = p - e1 along   //
07211 // the vector v2 = e2 - e1. Then Pythagoras' Theorem is used to compute the  //
07212 // shortest distance.                                                        //
07213 //                                                                           //
07214 // This routine allows that p is collinear with the line. In this case, the  //
07215 // return value is zero. The two points e1 and e2 should not be identical.   //
07216 //                                                                           //
07218 
07219 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2)
07220 {
07221   REAL v1[3], v2[3];
07222   REAL len, l_p;
07223 
07224   v1[0] = e2[0] - e1[0];
07225   v1[1] = e2[1] - e1[1];
07226   v1[2] = e2[2] - e1[2];
07227   v2[0] = p[0] - e1[0];
07228   v2[1] = p[1] - e1[1];
07229   v2[2] = p[2] - e1[2];
07230 
07231   len = sqrt(dot(v1, v1));
07232 #ifdef SELF_CHECK
07233   assert(len != 0.0);
07234 #endif
07235   v1[0] /= len;
07236   v1[1] /= len;
07237   v1[2] /= len;
07238   l_p = dot(v1, v2);
07239 
07240   return sqrt(dot(v2, v2) - l_p * l_p);
07241 }
07242 
07244 //                                                                           //
07245 // shortdistance()    Returns the shortest distance from point p to a face.  //
07246 //                                                                           //
07248 
07249 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2, REAL* e3)
07250 {
07251   REAL prj[3];
07252 
07253   projpt2face(p, e1, e2, e3, prj);
07254   return distance(p, prj);
07255 }
07256 
07258 //                                                                           //
07259 // interiorangle()    Return the interior angle (0 - 2 * PI) between vectors //
07260 //                    o->p1 and o->p2.                                       //
07261 //                                                                           //
07262 // 'n' is the normal of the plane containing face (o, p1, p2).  The interior //
07263 // angle is the total angle rotating from o->p1 around n to o->p2.  Exchange //
07264 // the position of p1 and p2 will get the complement angle of the other one. //
07265 // i.e., interiorangle(o, p1, p2) = 2 * PI - interiorangle(o, p2, p1).  Set  //
07266 // 'n' be NULL if you only want the interior angle between 0 - PI.           //
07267 //                                                                           //
07269 
07270 REAL tetgenmesh::interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n)
07271 {
07272   REAL v1[3], v2[3], np[3];
07273   REAL theta, costheta, lenlen;
07274   REAL ori, len1, len2;
07275 
07276   // Get the interior angle (0 - PI) between o->p1, and o->p2.
07277   v1[0] = p1[0] - o[0];
07278   v1[1] = p1[1] - o[1];
07279   v1[2] = p1[2] - o[2];
07280   v2[0] = p2[0] - o[0];
07281   v2[1] = p2[1] - o[1];
07282   v2[2] = p2[2] - o[2];
07283   len1 = sqrt(dot(v1, v1));
07284   len2 = sqrt(dot(v2, v2));
07285   lenlen = len1 * len2;
07286 #ifdef SELF_CHECK
07287   assert(lenlen != 0.0);
07288 #endif
07289   costheta = dot(v1, v2) / lenlen;
07290   if (costheta > 1.0) {
07291     costheta = 1.0; // Roundoff. 
07292   } else if (costheta < -1.0) {
07293     costheta = -1.0; // Roundoff. 
07294   }
07295   theta = acos(costheta);
07296   if (n != NULL) {
07297     // Get a point above the face (o, p1, p2);
07298     np[0] = o[0] + n[0];
07299     np[1] = o[1] + n[1];
07300     np[2] = o[2] + n[2];
07301     // Adjust theta (0 - 2 * PI).
07302     ori = orient3d(p1, o, np, p2);
07303     if (ori > 0.0) {
07304       theta = 2 * PI - theta;
07305     }
07306   }
07307 
07308   return theta;
07309 }
07310 
07312 //                                                                           //
07313 // projpt2edge()    Return the projection point from a point to an edge.     //
07314 //                                                                           //
07316 
07317 void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj)
07318 {
07319   REAL v1[3], v2[3];
07320   REAL len, l_p;
07321 
07322   v1[0] = e2[0] - e1[0];
07323   v1[1] = e2[1] - e1[1];
07324   v1[2] = e2[2] - e1[2];
07325   v2[0] = p[0] - e1[0];
07326   v2[1] = p[1] - e1[1];
07327   v2[2] = p[2] - e1[2];
07328 
07329   len = sqrt(dot(v1, v1));
07330 #ifdef SELF_CHECK
07331   assert(len != 0.0);
07332 #endif
07333   v1[0] /= len;
07334   v1[1] /= len;
07335   v1[2] /= len;
07336   l_p = dot(v1, v2);
07337 
07338   prj[0] = e1[0] + l_p * v1[0];
07339   prj[1] = e1[1] + l_p * v1[1];
07340   prj[2] = e1[2] + l_p * v1[2];
07341 }
07342 
07344 //                                                                           //
07345 // projpt2face()    Return the projection point from a point to a face.      //
07346 //                                                                           //
07348 
07349 void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj)
07350 {
07351   REAL fnormal[3], v1[3];
07352   REAL len, dist;
07353 
07354   // Get the unit face normal.
07355   facenormal(f1, f2, f3, fnormal, &len);
07356 #ifdef SELF_CHECK
07357   assert(len > 0.0);
07358 #endif
07359   fnormal[0] /= len;
07360   fnormal[1] /= len;
07361   fnormal[2] /= len;
07362   // Get the vector v1 = |p - f1|.
07363   v1[0] = p[0] - f1[0];
07364   v1[1] = p[1] - f1[1];
07365   v1[2] = p[2] - f1[2];
07366   // Get the project distance.
07367   dist = dot(fnormal, v1);
07368   
07369   // Get the project point.
07370   prj[0] = p[0] - dist * fnormal[0];
07371   prj[1] = p[1] - dist * fnormal[1];
07372   prj[2] = p[2] - dist * fnormal[2];
07373 }
07374 
07376 //                                                                           //
07377 // facenormal()    Calculate the normal of a face given by three points.     //
07378 //                                                                           //
07379 // In general, the face normal can be calculate by the cross product of any  //
07380 // pair of the three edge vectors.  However, if the three points are nearly  //
07381 // collinear, the rounding error may harm the result. To choose a good pair  //
07382 // of vectors is helpful to reduce the error.                                //
07383 //                                                                           //
07385 
07386 void tetgenmesh::facenormal(REAL* pa, REAL* pb, REAL* pc, REAL* n, REAL* nlen)
07387 {
07388   REAL v1[3], v2[3];
07389 
07390   v1[0] = pb[0] - pa[0];
07391   v1[1] = pb[1] - pa[1];
07392   v1[2] = pb[2] - pa[2];
07393   v2[0] = pc[0] - pa[0];
07394   v2[1] = pc[1] - pa[1];
07395   v2[2] = pc[2] - pa[2];
07396 
07397   cross(v1, v2, n);
07398   if (nlen != (REAL *) NULL) {
07399     *nlen = sqrt(dot(n, n));
07400   }
07401 }
07402 
07404 //                                                                           //
07405 // edgeorthonormal()    Return the unit normal of an edge in a given plane.  //
07406 //                                                                           //
07407 // The edge is from e1 to e2,  the plane is defined by given an additional   //
07408 // point op, which is non-collinear with the edge.  In addition, the side of //
07409 // the edge in which op lies defines the positive position of the normal.    //
07410 //                                                                           //
07411 // Let v1 be the unit vector from e1 to e2, v2 be the unit edge vector from  //
07412 // e1 to op, fn be the unit face normal calculated by fn = v1 x v2. Then the //
07413 // unit edge normal of e1e2 pointing to op is n = fn x v1.  Note, we should  //
07414 // not change the position of fn and v1, otherwise, we get the edge normal   //
07415 // pointing to the other side of op.                                         //
07416 //                                                                           //
07418 
07419 void tetgenmesh::edgeorthonormal(REAL* e1, REAL* e2, REAL* op, REAL* n)
07420 {
07421   REAL v1[3], v2[3], fn[3];
07422   REAL len;
07423 
07424   // Get the edge vector v1.
07425   v1[0] = e2[0] - e1[0];
07426   v1[1] = e2[1] - e1[1];
07427   v1[2] = e2[2] - e1[2];
07428   // Get the edge vector v2.
07429   v2[0] = op[0] - e1[0];
07430   v2[1] = op[1] - e1[1];
07431   v2[2] = op[2] - e1[2];
07432   // Get the face normal fn = v1 x v2.
07433   cross(v1, v2, fn);
07434   // Get the edge normal n pointing to op. n = fn x v1.
07435   cross(fn, v1, n);
07436   // Normalize the vector.
07437   len = sqrt(dot(n, n));
07438   n[0] /= len;
07439   n[1] /= len;
07440   n[2] /= len;
07441 }
07442 
07444 //                                                                           //
07445 // facedihedral()    Return the dihedral angle (in radian) between two       //
07446 //                   adjoining faces.                                        //
07447 //                                                                           //
07448 // 'pa', 'pb' are the shared edge of these two faces, 'pc1', and 'pc2' are   //
07449 // apexes of these two faces.  Return the angle (between 0 to 2*pi) between  //
07450 // the normal of face (pa, pb, pc1) and normal of face (pa, pb, pc2).        //
07451 //                                                                           //
07453 
07454 REAL tetgenmesh::facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2)
07455 {
07456   REAL n1[3], n2[3];
07457   REAL n1len, n2len;
07458   REAL costheta, ori;
07459   REAL theta;
07460 
07461   facenormal(pa, pb, pc1, n1, &n1len);
07462   facenormal(pa, pb, pc2, n2, &n2len);
07463   costheta = dot(n1, n2) / (n1len * n2len);
07464   // Be careful rounding error!
07465   if (costheta > 1.0) {
07466     costheta = 1.0;
07467   } else if (costheta < -1.0) {
07468     costheta = -1.0;
07469   }
07470   theta = acos(costheta);
07471   ori = orient3d(pa, pb, pc1, pc2);
07472   if (ori > 0.0) {
07473     theta = 2 * PI - theta;
07474   }
07475 
07476   return theta;
07477 }
07478 
07480 //                                                                           //
07481 // tetalldihedral()    Get all (six) dihedral angles of a tet.               //
07482 //                                                                           //
07483 // The tet is given by its four corners a, b, c, and d. If 'cosdd' is not    //
07484 // NULL, it returns the cosines of the 6 dihedral angles, the corresponding  //
07485 // edges are: ab, bc, ca, ad, bd, and cd. If 'cosmaxd' (or 'cosmind') is not //
07486 // NULL, it returns the cosine of the maximal (or minimal) dihedral angle.   //
07487 //                                                                           //
07489 
07490 void tetgenmesh::tetalldihedral(point pa, point pb, point pc, point pd,
07491   REAL* cosdd, REAL* cosmaxd, REAL* cosmind)
07492 {
07493   REAL N[4][3], cosd, len;
07494   int f1, f2, i, j;
07495 
07496   f1=0;
07497   f2=0;
07498   
07499   // Get four normals of faces of the tet.
07500   tetallnormal(pa, pb, pc, pd, N, NULL);
07501   // Normalize the normals.
07502   for (i = 0; i < 4; i++) {
07503     len = sqrt(dot(N[i], N[i]));
07504     if (len != 0.0) {
07505       for (j = 0; j < 3; j++) N[i][j] /= len;
07506     }
07507   }
07508 
07509   for (i = 0; i < 6; i++) {
07510     switch (i) {
07511     case 0: f1 = 2; f2 = 3; break; // edge ab.
07512     case 1: f1 = 0; f2 = 3; break; // edge bc.
07513     case 2: f1 = 1; f2 = 3; break; // edge ca.
07514     case 3: f1 = 1; f2 = 2; break; // edge ad.
07515     case 4: f1 = 2; f2 = 0; break; // edge bd.
07516     case 5: f1 = 0; f2 = 1; break; // edge cd.
07517     }
07518     cosd = -dot(N[f1], N[f2]);
07519     if (cosdd) cosdd[i] = cosd;
07520     if (i == 0) {
07521       if (cosmaxd) *cosmaxd = cosd;
07522       if (cosmind) *cosmind = cosd;
07523     } else {
07524       if (cosmaxd) *cosmaxd = cosd < *cosmaxd ? cosd : *cosmaxd;
07525       if (cosmind) *cosmind = cosd > *cosmind ? cosd : *cosmind;
07526     }
07527   }
07528 }
07529 
07531 //                                                                           //
07532 // tetallnormal()    Get the in-noramls of the four faces of a given tet.    //
07533 //                                                                           //
07534 // Let tet be abcd. N[4][3] returns the four normals, which are: N[0] cbd,   //
07535 // N[1] acd, N[2] bad, N[3] abc. These normals are unnormalized.             //
07536 //                                                                           //
07538 
07539 void tetgenmesh::tetallnormal(point pa, point pb, point pc, point pd,
07540   REAL N[4][3], REAL* volume)
07541 {
07542   REAL A[4][4], rhs[4], D;
07543   int indx[4];
07544   int i, j;
07545 
07546   // get the entries of A[3][3].
07547   for (i = 0; i < 3; i++) A[0][i] = pa[i] - pd[i];  // d->a vec
07548   for (i = 0; i < 3; i++) A[1][i] = pb[i] - pd[i];  // d->b vec
07549   for (i = 0; i < 3; i++) A[2][i] = pc[i] - pd[i];  // d->c vec
07550   // Compute the inverse of matrix A, to get 3 normals of the 4 faces.
07551   lu_decmp(A, 3, indx, &D, 0);     // Decompose the matrix just once.
07552   if (volume != NULL) {
07553     // Get the volume of the tet.
07554     *volume = fabs((A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2])) / 6.0;
07555   }
07556   for (j = 0; j < 3; j++) {
07557     for (i = 0; i < 3; i++) rhs[i] = 0.0;
07558     rhs[j] = 1.0;  // Positive means the inside direction
07559     lu_solve(A, 3, indx, rhs, 0);
07560     for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07561   }
07562   // Get the fourth normal by summing up the first three.
07563   for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07564 }
07565 
07567 //                                                                           //
07568 // tetaspectratio()    Calculate the aspect ratio of the tetrahedron.        //
07569 //                                                                           //
07570 // The aspect ratio of a tet is R/h, where R is the circumradius and h is    //
07571 // the shortest height of the tet.                                           //
07572 //                                                                           //
07574 
07575 REAL tetgenmesh::tetaspectratio(point pa, point pb, point pc, point pd)
07576 {
07577   REAL vda[3], vdb[3], vdc[3];
07578   REAL N[4][3], A[4][4], rhs[4], D;
07579   REAL H[4], volume, radius2, minheightinv;
07580   int indx[4];
07581   int i, j; 
07582 
07583   // Set the matrix A = [vda, vdb, vdc]^T.
07584   for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
07585   for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
07586   for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
07587   // Lu-decompose the matrix A.
07588   lu_decmp(A, 3, indx, &D, 0);
07589   // Get the volume of abcd.
07590   volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
07591   // Check if it is zero.
07592   if (volume == 0.0) return 1.0e+200; // A degenerate tet.
07593   // if (volume < 0.0) volume = -volume;
07594   // Check the radiu-edge ratio of the tet.
07595   rhs[0] = 0.5 * dot(vda, vda);
07596   rhs[1] = 0.5 * dot(vdb, vdb);
07597   rhs[2] = 0.5 * dot(vdc, vdc);
07598   lu_solve(A, 3, indx, rhs, 0);
07599   // Get the circumcenter.
07600   // for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
07601   // Get the square of the circumradius.
07602   radius2 = dot(rhs, rhs);
07603 
07604   // Compute the 4 face normals (N[0], ..., N[3]).
07605   for (j = 0; j < 3; j++) {
07606     for (i = 0; i < 3; i++) rhs[i] = 0.0;
07607     rhs[j] = 1.0;  // Positive means the inside direction
07608     lu_solve(A, 3, indx, rhs, 0);
07609     for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07610   }
07611   // Get the fourth normal by summing up the first three.
07612   for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07613   // Normalized the normals.
07614   for (i = 0; i < 4; i++) {
07615     // H[i] is the inverse of the height of its corresponding face.
07616     H[i] = sqrt(dot(N[i], N[i]));
07617     // if (H[i] > 0.0) {
07618     //   for (j = 0; j < 3; j++) N[i][j] /= H[i];
07619     // }
07620   }
07621   // Get the radius of the inscribed sphere.
07622   // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]);
07623   // Get the biggest H[i] (corresponding to the smallest height).
07624   minheightinv = H[0];
07625   for (i = 1; i < 3; i++) {
07626     if (H[i] > minheightinv) minheightinv = H[i];
07627   }
07628 
07629   return sqrt(radius2) * minheightinv;
07630 }
07631 
07633 //                                                                           //
07634 // circumsphere()    Calculate the smallest circumsphere (center and radius) //
07635 //                   of the given three or four points.                      //
07636 //                                                                           //
07637 // The circumsphere of four points (a tetrahedron) is unique if they are not //
07638 // degenerate. If 'pd = NULL', the smallest circumsphere of three points is  //
07639 // the diametral sphere of the triangle if they are not degenerate.          //
07640 //                                                                           //
07641 // Return TRUE if the input points are not degenerate and the circumcenter   //
07642 // and circumradius are returned in 'cent' and 'radius' respectively if they //
07643 // are not NULLs. Otherwise, return FALSE indicated the points are degenrate.//
07644 //                                                                           //
07646 
07647 bool tetgenmesh::
07648 circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* cent, REAL* radius)
07649 {
07650   REAL A[4][4], rhs[4], D;
07651   int indx[4];
07652 
07653   // Compute the coefficient matrix A (3x3).
07654   A[0][0] = pb[0] - pa[0];
07655   A[0][1] = pb[1] - pa[1];
07656   A[0][2] = pb[2] - pa[2];
07657   A[1][0] = pc[0] - pa[0];
07658   A[1][1] = pc[1] - pa[1];
07659   A[1][2] = pc[2] - pa[2];
07660   if (pd != NULL) {
07661     A[2][0] = pd[0] - pa[0];
07662     A[2][1] = pd[1] - pa[1]; 
07663     A[2][2] = pd[2] - pa[2];
07664   } else {
07665     cross(A[0], A[1], A[2]);
07666   }
07667 
07668   // Compute the right hand side vector b (3x1).
07669   rhs[0] = 0.5 * dot(A[0], A[0]);
07670   rhs[1] = 0.5 * dot(A[1], A[1]);
07671   if (pd != NULL) {
07672     rhs[2] = 0.5 * dot(A[2], A[2]);
07673   } else {
07674     rhs[2] = 0.0;
07675   }
07676 
07677   // Solve the 3 by 3 equations use LU decomposition with partial pivoting
07678   //   and backward and forward substitute..
07679   if (!lu_decmp(A, 3, indx, &D, 0)) {
07680     if (radius != (REAL *) NULL) *radius = 0.0;
07681     return false;
07682   }    
07683   lu_solve(A, 3, indx, rhs, 0);
07684   if (cent != (REAL *) NULL) {
07685     cent[0] = pa[0] + rhs[0];
07686     cent[1] = pa[1] + rhs[1];
07687     cent[2] = pa[2] + rhs[2];
07688   }
07689   if (radius != (REAL *) NULL) {
07690     *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
07691   }
07692   return true;
07693 }
07694 
07696 //                                                                           //
07697 // inscribedsphere()    Compute the radius and center of the biggest         //
07698 //                      inscribed sphere of a given tetrahedron.             //
07699 //                                                                           //
07700 // The tetrahedron is given by its four points, it must not be degenerate.   //
07701 // The center and radius are returned in 'cent' and 'radius' respectively if //
07702 // they are not NULLs.                                                       //
07703 //                                                                           //
07704 // Geometrical fact. For any simplex in d dimension,                         //
07705 //   r/h1 + r/h2 + ... r/hn = 1 (n <= d + 1);                                //
07706 // where r is the radius of inscribed ball, and h is the height of each side //
07707 // of the simplex. The value of 'r/h' is just the barycenter coordinates of  //
07708 // each vertex of the simplex. Therefore, we can compute the radius and      //
07709 // center of the smallest inscribed ball as following equations:             //
07710 //   r = 1.0 / (1/h1 + 1/h2 + ... + 1/hn);          (1)                      //
07711 //   C = r/h1 * P1 + r/h2 * P2 + ... + r/hn * Pn;   (2)                      //
07712 // where C is the vector of center, P1, P2, .. Pn are vectors of vertices.   //
07713 // Here (2) contains n linear equations with n variables.  (h, P) must be a  //
07714 // pair, h is the height from P to its opposite face.                        //
07715 //                                                                           //
07717 
07718 void tetgenmesh::inscribedsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
07719   REAL* cent, REAL* radius)
07720 {
07721   REAL N[4][3], H[4]; // Normals (colume vectors) and heights of each face.
07722   REAL rd;
07723   int i;  
07724 
07725   // Get the all normals of the tet.
07726   tetallnormal(pa, pb, pc, pd, N, NULL);
07727   for (i = 0; i < 4; i++) {
07728     // H[i] is the inverse of height of its corresponding face.
07729     H[i] = sqrt(dot(N[i], N[i]));
07730   }
07731   // Compute the radius use eq. (1).
07732   rd = 1.0 / (H[0] + H[1] + H[2] + H[3]);
07733   if (radius != (REAL*) NULL) *radius = rd;
07734   if (cent != (REAL*) NULL) {
07735     // Compute the center use eq. (2).
07736     cent[0] = rd * (H[0] * pa[0] + H[1] * pb[0] + H[2] * pc[0] + H[3] * pd[0]);
07737     cent[1] = rd * (H[0] * pa[1] + H[1] * pb[1] + H[2] * pc[1] + H[3] * pd[1]);
07738     cent[2] = rd * (H[0] * pa[2] + H[1] * pb[2] + H[2] * pc[2] + H[3] * pd[2]);
07739   }
07740 }
07741 
07743 //                                                                           //
07744 // rotatepoint()    Create a point by rotating an existing point.            //
07745 //                                                                           //
07746 // Create a 3D point by rotating point 'p' with an angle 'rotangle' (in arc  //
07747 // degree) around a rotating axis given by a vector from point 'p1' to 'p2'. //
07748 // The rotation is according with right-hand rule, i.e., use your right-hand //
07749 // to grab the axis with your thumber pointing to its positive direction,    //
07750 // your fingers indicate the rotating direction.                             //
07751 //                                                                           //
07752 // The rotating steps are the following:                                     //
07753 //   1. Translate vector 'p1->p2' to origin, M1;                             //
07754 //   2. Rotate vector around the Y-axis until it lies in the YZ plane, M2;   //
07755 //   3. Rotate vector around the X-axis until it lies on the Z axis, M3;     //
07756 //   4. Perform the rotation of 'p' around the z-axis, M4;                   //
07757 //   5. Undo Step 3, M5;                                                     //
07758 //   6. Undo Step 2, M6;                                                     //
07759 //   7. Undo Step 1, M7;                                                     //
07760 // Use matrix multiplication to combine the above sequences, we get:         //
07761 //   p0' = T * p0, where T = M7 * M6 * M5 * M4 * M3 * M2 * M1                //
07762 //                                                                           //
07764 
07765 void tetgenmesh::rotatepoint(REAL* p, REAL rotangle, REAL* p1, REAL* p2)
07766 {
07767   REAL T[4][4], pp0[4], p0t[4], p2t[4];
07768   REAL roty, rotx, alphaR, projlen;
07769   REAL dx, dy, dz;
07770 
07771   initm44(1, 0, 0, -p1[0],
07772           0, 1, 0, -p1[1],
07773           0, 0, 1, -p1[2],
07774           0, 0, 0, 1, T);
07775   pp0[0] = p[0]; pp0[1] = p[1]; pp0[2] = p[2]; pp0[3] = 1.0;
07776   m4xv4(p0t, T, pp0); // Step 1
07777   pp0[0] = p2[0]; pp0[1] = p2[1]; pp0[2] = p2[2]; pp0[3] = 1.0;
07778   m4xv4(p2t, T, pp0); // Step 1
07779 
07780   // Get the rotation angle around y-axis;
07781   dx = p2t[0];
07782   dz = p2t[2];
07783   projlen = sqrt(dx * dx + dz * dz);
07784   if (projlen <= (b->epsilon * 1e-2) * longest) {
07785     roty = 0;
07786   } else {
07787     roty = acos(dz / projlen);
07788     if (dx < 0) {
07789       roty = -roty;
07790     }
07791   }
07792 
07793   initm44(cos(-roty), 0, sin(-roty), 0,
07794           0, 1, 0, 0,
07795           -sin(-roty), 0, cos(-roty), 0,
07796           0, 0, 0, 1, T);
07797   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07798   m4xv4(p0t, T, pp0); // Step 2
07799   pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
07800   m4xv4(p2t, T, pp0); // Step 2
07801 
07802   // Get the rotation angle around x-axis
07803   dy = p2t[1];
07804   dz = p2t[2];
07805   projlen = sqrt(dy * dy + dz * dz);
07806   if (projlen <= (b->epsilon * 1e-2) * longest) {
07807     rotx = 0;
07808   } else {
07809     rotx = acos(dz / projlen);
07810     if (dy < 0) {
07811       rotx = -rotx;
07812     }
07813   }
07814     
07815   initm44(1, 0, 0, 0,
07816           0, cos(rotx), -sin(rotx), 0,
07817           0, sin(rotx), cos(rotx), 0,
07818           0, 0, 0, 1, T);
07819   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07820   m4xv4(p0t, T, pp0); // Step 3
07821   // pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
07822   // m4xv4(p2t, T, pp0); // Step 3
07823 
07824   alphaR = rotangle;
07825   initm44(cos(alphaR), -sin(alphaR), 0, 0,
07826           sin(alphaR), cos(alphaR), 0, 0,
07827           0, 0, 1, 0,
07828           0, 0, 0, 1, T);
07829   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07830   m4xv4(p0t, T, pp0); // Step 4
07831 
07832   initm44(1, 0, 0, 0,
07833           0, cos(-rotx), -sin(-rotx), 0,
07834           0, sin(-rotx), cos(-rotx), 0,
07835           0, 0, 0, 1, T);
07836   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07837   m4xv4(p0t, T, pp0); // Step 5
07838 
07839   initm44(cos(roty), 0, sin(roty), 0,
07840           0, 1, 0, 0,
07841           -sin(roty), 0, cos(roty), 0,
07842           0, 0, 0, 1, T);
07843   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07844   m4xv4(p0t, T, pp0); // Step 6
07845 
07846   initm44(1, 0, 0, p1[0],
07847           0, 1, 0, p1[1],
07848           0, 0, 1, p1[2],
07849           0, 0, 0, 1, T);
07850   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07851   m4xv4(p0t, T, pp0); // Step 7  
07852 
07853   p[0] = p0t[0];
07854   p[1] = p0t[1];
07855   p[2] = p0t[2];
07856 }
07857 
07859 //                                                                           //
07860 // spherelineint()    3D line sphere (or circle) intersection.               //
07861 //                                                                           //
07862 // The line is given by two points p1, and p2, the sphere is centered at c   //
07863 // with radius r.  This function returns a pointer array p which first index //
07864 // indicates the number of intersection point, followed by coordinate pairs. //
07865 //                                                                           //
07866 // The following code are adapted from: http://astronomy.swin.edu.au/pbourke //
07867 // /geometry/sphereline. Paul Bourke pbourke@swin.edu.au                     //
07868 //                                                                           //
07870 
07871 void tetgenmesh::spherelineint(REAL* p1, REAL* p2, REAL* C, REAL R, REAL p[7])
07872 {
07873   REAL x1, y1, z1; //  P1 coordinates (point of line)
07874   REAL x2, y2, z2; //  P2 coordinates (point of line)
07875   REAL x3, y3, z3, r; //  P3 coordinates and radius (sphere)
07876   REAL a, b, c, mu, i ;
07877 
07878   x1 = p1[0]; y1 = p1[1]; z1 = p1[2];
07879   x2 = p2[0]; y2 = p2[1]; z2 = p2[2];
07880   x3 = C[0];  y3 = C[1];  z3 = C[2];
07881   r = R;
07882   
07883   a =   (x2 - x1) * (x2 - x1) 
07884       + (y2 - y1) * (y2 - y1) 
07885       + (z2 - z1) * (z2 - z1);
07886   b = 2 * ( (x2 - x1) * (x1 - x3)
07887           + (y2 - y1) * (y1 - y3)
07888           + (z2 - z1) * (z1 - z3) ) ;
07889   c =   (x3 * x3) + (y3 * y3) + (z3 * z3)
07890       + (x1 * x1) + (y1 * y1) + (z1 * z1)
07891       - 2 * (x3 * x1 + y3 * y1 + z3 * z1) - (r * r) ;
07892   i = b * b - 4 * a * c ;
07893 
07894   if (i < 0.0) {
07895     // no intersection
07896     p[0] = 0.0;
07897   } else if (i == 0.0) {
07898     // one intersection
07899     p[0] = 1.0;
07900     mu = -b / (2 * a) ;
07901     p[1] = x1 + mu * (x2 - x1);
07902     p[2] = y1 + mu * (y2 - y1);
07903     p[3] = z1 + mu * (z2 - z1);
07904   } else {
07905     // two intersections
07906     p[0] = 2.0;
07907     // first intersection
07908     mu = (-b + sqrt((b * b) - 4 * a * c)) / (2 * a);
07909     p[1] = x1 + mu * (x2 - x1);
07910     p[2] = y1 + mu * (y2 - y1);
07911     p[3] = z1 + mu * (z2 - z1);
07912     // second intersection
07913     mu = (-b - sqrt((b * b) - 4 * a * c)) / (2 * a);
07914     p[4] = x1 + mu * (x2 - x1);
07915     p[5] = y1 + mu * (y2 - y1);
07916     p[6] = z1 + mu * (z2 - z1);
07917   }
07918 }
07919 
07921 //                                                                           //
07922 // linelineint()    Calculate the shortest line between two lines in 3D.     //
07923 //                                                                           //
07924 // Two 3D lines generally don't intersect at a point, they may be parallel ( //
07925 // no intersections), or coincident (infinite intersections) but most often  //
07926 // only their projections onto a plane intersect. If they don't exactly int- //
07927 // ersect at a point they can be connected by a line segment, the shortest   //
07928 // segment is unique and is often considered to be their intersection in 3D. //
07929 //                                                                           //
07930 // The following code are adapted from: http://astronomy.swin.edu.au/pbourke //
07931 // /geometry/lineline3d. Paul Bourke pbourke@swin.edu.au                     //
07932 //                                                                           //
07933 // Calculate the line segment PaPb that is the shortest route between two    //
07934 // lines P1P2 and P3P4. This function returns a pointer array p which first  //
07935 // index indicates there exists solution or not, 0 means no solution, 1 meas //
07936 // has solution followed by two coordinate pairs.                            //
07937 //                                                                           //
07939 
07940 void tetgenmesh::linelineint(REAL *p1,REAL *p2, REAL *p3, REAL *p4, REAL p[7])
07941 {
07942   REAL p13[3], p43[3], p21[3];
07943   REAL d1343, d4321, d1321, d4343, d2121;
07944   REAL numer, denom;
07945   REAL mua, mub;
07946 
07947   p13[0] = p1[0] - p3[0];
07948   p13[1] = p1[1] - p3[1];
07949   p13[2] = p1[2] - p3[2];
07950   p43[0] = p4[0] - p3[0];
07951   p43[1] = p4[1] - p3[1];
07952   p43[2] = p4[2] - p3[2];
07953   if (p43[0] == 0.0 && p43[1] == 0.0 && p43[2] == 0.0) {
07954     p[0] = 0.0;
07955     return;
07956   }
07957 
07958   p21[0] = p2[0] - p1[0];
07959   p21[1] = p2[1] - p1[1];
07960   p21[2] = p2[2] - p1[2];
07961   if (p21[0] == 0.0 && p21[1] == 0.0 && p21[2] == 0.0) {
07962     p[0] = 0.0;
07963     return;
07964   }
07965 
07966   d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
07967   d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
07968   d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
07969   d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
07970   d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
07971 
07972   denom = d2121 * d4343 - d4321 * d4321;
07973   if (denom == 0.0) {
07974     p[0] = 0.0;
07975     return;
07976   }
07977   numer = d1343 * d4321 - d1321 * d4343;
07978   mua = numer / denom;
07979   mub = (d1343 + d4321 * mua) / d4343;
07980 
07981   p[0] = 1.0;
07982   p[1] = p1[0] + mua * p21[0];
07983   p[2] = p1[1] + mua * p21[1];
07984   p[3] = p1[2] + mua * p21[2];
07985   p[4] = p3[0] + mub * p43[0];
07986   p[5] = p3[1] + mub * p43[1];
07987   p[6] = p3[2] + mub * p43[2];
07988 }
07989 
07991 //                                                                           //
07992 // planelineint()    Calculate the intersection of a line and a plane.       //
07993 //                                                                           //
07994 // The equation of a plane (points P are on the plane with normal N and P3   //
07995 // on the plane) can be written as: N dot (P - P3) = 0. The equation of the  //
07996 // line (points P on the line passing through P1 and P2) can be written as:  //
07997 // P = P1 + u (P2 - P1). The intersection of these two occurs when:          //
07998 //   N dot (P1 + u (P2 - P1)) = N dot P3.                                    //
07999 // Solving for u gives:                                                      //
08000 //         N dot (P3 - P1)                                                   //
08001 //   u = ------------------.                                                 //
08002 //         N dot (P2 - P1)                                                   //
08003 // If the denominator is 0 then N (the normal to the plane) is perpendicular //
08004 // to the line.  Thus the line is either parallel to the plane and there are //
08005 // no solutions or the line is on the plane in which case there are an infi- //
08006 // nite number of solutions.                                                 //
08007 //                                                                           //
08008 // The plane is given by three points pa, pb, and pc, e1 and e2 defines the  //
08009 // line. If u is non-zero, The intersection point (if exists) returns in ip. //
08010 //                                                                           //
08012 
08013 void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
08014   REAL* ip, REAL* u)
08015 {
08016   REAL n[3], det, det1;
08017 
08018   // Calculate N.
08019   facenormal(pa, pb, pc, n, NULL);
08020   // Calculate N dot (e2 - e1).
08021   det = n[0] * (e2[0] - e1[0]) + n[1] * (e2[1] - e1[1])
08022       + n[2] * (e2[2] - e1[2]);
08023   if (det != 0.0) {
08024     // Calculate N dot (pa - e1)
08025     det1 = n[0] * (pa[0] - e1[0]) + n[1] * (pa[1] - e1[1])
08026          + n[2] * (pa[2] - e1[2]);
08027     *u = det1 / det;
08028     ip[0] = e1[0] + *u * (e2[0] - e1[0]);
08029     ip[1] = e1[1] + *u * (e2[1] - e1[1]);
08030     ip[2] = e1[2] + *u * (e2[2] - e1[2]);
08031   } else {
08032     *u = 0.0;
08033   }
08034 }
08035 
08036 //
08037 // End of Geometric quantities calculators
08038 //
08039 
08040 //
08041 // Begin of memory management routines
08042 //
08043 
08045 //                                                                           //
08046 // dummyinit()    Initialize the tetrahedron that fills "outer space" and    //
08047 //                the omnipresent subface.                                   //
08048 //                                                                           //
08049 // The tetrahedron that fills "outer space" called 'dummytet', is pointed to //
08050 // by every tetrahedron and subface on a boundary (be it outer or inner) of  //
08051 // the tetrahedralization. Also, 'dummytet' points to one of the tetrahedron //
08052 // on the convex hull(until the holes and concavities are carved), making it //
08053 // possible to find a starting tetrahedron for point location.               //
08054 //                                                                           //
08055 // The omnipresent subface,'dummysh', is pointed to by every tetrahedron or  //
08056 // subface that doesn't have a full complement of real subface to point to.  //
08057 //                                                                           //
08059 
08060 void tetgenmesh::dummyinit(int tetwords, int shwords)
08061 {
08062   unsigned long alignptr;
08063 
08064   // Set up 'dummytet', the 'tetrahedron' that occupies "outer space".
08065   dummytetbase = (tetrahedron *) new char[tetwords * sizeof(tetrahedron)
08066                                           + tetrahedrons->alignbytes];
08067   // Align 'dummytet' on a 'tetrahedrons->alignbytes'-byte boundary.
08068   alignptr = (unsigned long) dummytetbase;
08069   dummytet = (tetrahedron *)
08070     (alignptr + (unsigned long) tetrahedrons->alignbytes
08071      - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08072   // Initialize the four adjoining tetrahedra to be "outer space". These
08073   //   will eventually be changed by various bonding operations, but their
08074   //   values don't really matter, as long as they can legally be
08075   //   dereferenced.
08076   dummytet[0] = (tetrahedron) dummytet;
08077   dummytet[1] = (tetrahedron) dummytet;
08078   dummytet[2] = (tetrahedron) dummytet;
08079   dummytet[3] = (tetrahedron) dummytet;
08080   // Four null vertex points.
08081   dummytet[4] = (tetrahedron) NULL;
08082   dummytet[5] = (tetrahedron) NULL;
08083   dummytet[6] = (tetrahedron) NULL;
08084   dummytet[7] = (tetrahedron) NULL;
08085 
08086   if (b->useshelles) {
08087     // Set up 'dummysh', the omnipresent "subface" pointed to by any
08088     //   tetrahedron side or subface end that isn't attached to a real
08089     //   subface.
08090     dummyshbase = (shellface *) new char[shwords * sizeof(shellface)
08091                                          + subfaces->alignbytes];
08092     // Align 'dummysh' on a 'subfaces->alignbytes'-byte boundary.
08093     alignptr = (unsigned long) dummyshbase;
08094     dummysh = (shellface *)
08095       (alignptr + (unsigned long) subfaces->alignbytes
08096        - (alignptr % (unsigned long) subfaces->alignbytes));
08097     // Initialize the three adjoining subfaces to be the omnipresent
08098     //   subface. These will eventually be changed by various bonding
08099     //   operations, but their values don't really matter, as long as they
08100     //   can legally be dereferenced.
08101     dummysh[0] = (shellface) dummysh;
08102     dummysh[1] = (shellface) dummysh;
08103     dummysh[2] = (shellface) dummysh;
08104     // Three null vertex points.
08105     dummysh[3] = (shellface) NULL;
08106     dummysh[4] = (shellface) NULL;
08107     dummysh[5] = (shellface) NULL;
08108     // Initialize the two adjoining tetrahedra to be "outer space".
08109     dummysh[6] = (shellface) dummytet;
08110     dummysh[7] = (shellface) dummytet;
08111     // Initialize the three adjoining subsegments to be "out boundary".
08112     dummysh[8]  = (shellface) dummysh;
08113     dummysh[9]  = (shellface) dummysh;
08114     dummysh[10] = (shellface) dummysh;
08115     // Initialize the pointer to badface structure.
08116     dummysh[11] = (shellface) NULL;
08117     // Initialize the four adjoining subfaces of 'dummytet' to be the
08118     //   omnipresent subface.
08119     dummytet[8 ] = (tetrahedron) dummysh;
08120     dummytet[9 ] = (tetrahedron) dummysh;
08121     dummytet[10] = (tetrahedron) dummysh;
08122     dummytet[11] = (tetrahedron) dummysh;
08123   }
08124 }
08125 
08127 //                                                                           //
08128 // initializepools()    Calculate the sizes of the point, tetrahedron, and   //
08129 //                      subface. Initialize their memory pools.              //
08130 //                                                                           //
08131 // This routine also computes the indices 'pointmarkindex', 'point2simindex',//
08132 // and 'point2pbcptindex' used to find values within each point;  computes   //
08133 // indices 'highorderindex', 'elemattribindex', and 'volumeboundindex' used  //
08134 // to find values within each tetrahedron.                                   //
08135 //                                                                           //
08136 // There are two types of boundary elements, which are subfaces and subsegs, //
08137 // they are stored in seperate pools. However, the data structures of them   //
08138 // are the same.  A subsegment can be regarded as a degenerate subface, i.e.,//
08139 // one of its three corners is not used. We set the apex of it be 'NULL' to  //
08140 // distinguish it's a subsegment.                                            //
08141 //                                                                           //
08143 
08144 void tetgenmesh::initializepools()
08145 {
08146   enum wordtype wtype;
08147   int pointsize, elesize, shsize;
08148 
08149   // Default checkpbc = 0;
08150   if ((b->plc || b->refine) && (in->pbcgrouplist != NULL)) {
08151     checkpbcs = 1;
08152   }
08153   // Default varconstraint = 0;
08154   if (in->segmentconstraintlist || in->facetconstraintlist) {
08155     varconstraint = 1;
08156   }
08157 
08158   // The index within each point at which its metric tensor is found. It is
08159   //   saved directly after the list of point attributes.
08160   pointmtrindex = 3 + in->numberofpointattributes;
08161   // Decide the size (1, 3, or 6) of the metric tensor.
08162   if (b->metric) {
08163     // For '-m' option. A tensor field is provided (*.mtr or *.b.mtr file).
08164     if (bgm != (tetgenmesh *) NULL) {
08165       // A background mesh is allocated. It may not exist though.
08166       sizeoftensor = (bgm->in != (tetgenio *) NULL) ? 
08167         bgm->in->numberofpointmtrs : in->numberofpointmtrs;
08168     } else {
08169       // No given background mesh - Itself is a background mesh.
08170       sizeoftensor = in->numberofpointmtrs;
08171     }
08172     // Make sure sizeoftensor is at least 1.
08173     sizeoftensor = (sizeoftensor > 0) ? sizeoftensor : 1; 
08174   } else {
08175     // For '-q' option. Make sure to have space for saving a scalar value.
08176     sizeoftensor = b->quality ? 1 : 0;
08177   }
08178   // The index within each point at which an element pointer is found, where
08179   //   the index is measured in pointers. Ensure the index is aligned to a
08180   //   sizeof(tetrahedron)-byte address.
08181   point2simindex = ((pointmtrindex + sizeoftensor) * sizeof(REAL)
08182                  + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08183   if (b->plc || b->refine) {
08184     // Increase the point size by three pointers, which are:
08185     //   - a pointer to a tet, read by point2tet();
08186     //   - a pointer to a subface/subsegment , read by point2sh();
08187     //   - a pointer to a parent point, read by point2ppt()).
08188     if (b->metric) {
08189       // Increase one pointer to a tet of the background mesh.
08190       pointsize = (point2simindex + 4) * sizeof(tetrahedron);
08191     } else {
08192       pointsize = (point2simindex + 3) * sizeof(tetrahedron);
08193     }
08194     // The index within each point at which a pbc point is found.
08195     point2pbcptindex = (pointsize + sizeof(tetrahedron) - 1)
08196                      / sizeof(tetrahedron);
08197     if (checkpbcs) {
08198       // Increase the size by one pointer to a corresponding pbc point,
08199       //   read by point2pbcpt().
08200       pointsize = (point2pbcptindex + 1) * sizeof(tetrahedron);
08201     }
08202   } else {
08203     pointsize = point2simindex * sizeof(tetrahedron);
08204   }
08205   // The index within each point at which the boundary marker is found,
08206   //   Ensure the point marker is aligned to a sizeof(int)-byte address.
08207   pointmarkindex = (pointsize + sizeof(int) - 1) / sizeof(int);
08208   // Now point size is the ints (inidcated by pointmarkindex) plus:
08209   //   - an integer for boundary marker;
08210   //   - an integer for vertex type;
08211   pointsize = (pointmarkindex + 2) * sizeof(int);
08212   // Decide the wordtype used in vertex pool.
08213   wtype = (sizeof(REAL) >= sizeof(tetrahedron)) ? FLOATINGPOINT : POINTER;
08214   // Initialize the pool of vertices.
08215   points = new memorypool(pointsize, VERPERBLOCK, wtype, 0);
08216 
08217   // The number of bytes occupied by a tetrahedron.  There are four pointers
08218   //   to other tetrahedra, four pointers to corners, and possibly four
08219   //   pointers to subfaces.
08220   elesize = (8 + b->useshelles * 6) * sizeof(tetrahedron);
08221   // If Voronoi diagram is wanted, make sure we have additional space.
08222   if (b->voroout && (b->useshelles == 0)) {
08223     elesize = (8 + 4) * sizeof(tetrahedron);
08224   }
08225   // The index within each element at which its attributes are found, where
08226   //   the index is measured in REALs. 
08227   elemattribindex = (elesize + sizeof(REAL) - 1) / sizeof(REAL);
08228   // The index within each element at which the maximum voulme bound is
08229   //   found, where the index is measured in REALs.  Note that if the
08230   //   `b->regionattrib' flag is set, an additional attribute will be added.
08231   volumeboundindex = elemattribindex + in->numberoftetrahedronattributes
08232                    + (b->regionattrib > 0);
08233   // If element attributes or an constraint are needed, increase the number
08234   //   of bytes occupied by an element.
08235   if (b->varvolume) {
08236     elesize = (volumeboundindex + 1) * sizeof(REAL);
08237   } else if (in->numberoftetrahedronattributes + b->regionattrib > 0) {
08238     elesize = volumeboundindex * sizeof(REAL);
08239   }
08240   // If element neighbor graph is requested (-n switch), an additional
08241   //   integer is allocated for each element.
08242   elemmarkerindex = (elesize + sizeof(int) - 1) / sizeof(int);
08243   if (b->neighout || b->voroout) {
08244     elesize = (elemmarkerindex + 1) * sizeof(int);
08245   }
08246   // If -o2 switch is used, an additional pointer pointed to the list of
08247   //   higher order nodes is allocated for each element.
08248   highorderindex = (elesize + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08249   if (b->order == 2) {
08250     elesize = (highorderindex + 1) * sizeof(tetrahedron);
08251   }
08252   // Having determined the memory size of an element, initialize the pool.
08253   tetrahedrons = new memorypool(elesize, ELEPERBLOCK, POINTER, 8);
08254 
08255   if (b->useshelles) {
08256     // The number of bytes occupied by a subface.  The list of pointers
08257     //   stored in a subface are: three to other subfaces, three to corners,
08258     //   three to subsegments, two to tetrahedra, and one to a badface.
08259     shsize = 12 * sizeof(shellface);
08260     // The index within each subface at which the maximum area bound is
08261     //   found, where the index is measured in REALs.
08262     areaboundindex = (shsize + sizeof(REAL) - 1) / sizeof(REAL);
08263     // If -q switch is in use, increase the number of bytes occupied by
08264     //   a subface for saving maximum area bound.
08265     if (b->quality && varconstraint) {
08266       shsize = (areaboundindex + 1) * sizeof(REAL);
08267     } else {
08268       shsize = areaboundindex * sizeof(REAL);
08269     }
08270     // The index within subface at which the facet marker is found. Ensure
08271     //   the marker is aligned to a sizeof(int)-byte address.
08272     shmarkindex = (shsize + sizeof(int) - 1) / sizeof(int);
08273     // Increase the number of bytes by two or three integers, one for facet
08274     //   marker, one for shellface type, and optionally one for pbc group.
08275     shsize = (shmarkindex + 2 + checkpbcs) * sizeof(int);
08276     // Initialize the pool of subfaces. Each subface record is eight-byte
08277     //   aligned so it has room to store an edge version (from 0 to 5) in
08278     //   the least three bits.
08279     subfaces = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08280     // Initialize the pool of subsegments. The subsegment's record is same
08281     //   with subface.
08282     subsegs = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08283     // Initialize the "outer space" tetrahedron and omnipresent subface.
08284     dummyinit(tetrahedrons->itemwords, subfaces->itemwords);
08285   } else {
08286     // Initialize the "outer space" tetrahedron.
08287     dummyinit(tetrahedrons->itemwords, 0);
08288   }
08289 }
08290 
08292 //                                                                           //
08293 // tetrahedrondealloc()    Deallocate space for a tet., marking it dead.     //
08294 //                                                                           //
08296 
08297 void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
08298 {
08299   // Set tetrahedron's vertices to NULL. This makes it possible to detect
08300   //   dead tetrahedra when traversing the list of all tetrahedra.
08301   dyingtetrahedron[4] = (tetrahedron) NULL;
08302   dyingtetrahedron[5] = (tetrahedron) NULL;
08303   dyingtetrahedron[6] = (tetrahedron) NULL;
08304   dyingtetrahedron[7] = (tetrahedron) NULL;
08305   tetrahedrons->dealloc((void *) dyingtetrahedron);
08306 }
08307 
08309 //                                                                           //
08310 // tetrahedrontraverse()    Traverse the tetrahedra, skipping dead ones.     //
08311 //                                                                           //
08313 
08314 tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse()
08315 {
08316   tetrahedron *newtetrahedron;
08317 
08318   do {
08319     newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
08320     if (newtetrahedron == (tetrahedron *) NULL) {
08321       return (tetrahedron *) NULL;
08322     }
08323   } while (newtetrahedron[7] == (tetrahedron) NULL);      // Skip dead ones.
08324   return newtetrahedron;
08325 }
08326 
08328 //                                                                           //
08329 // shellfacedealloc()    Deallocate space for a shellface, marking it dead.  //
08330 //                       Used both for dealloc a subface and subsegment.     //
08331 //                                                                           //
08333 
08334 void tetgenmesh::shellfacedealloc(memorypool *pool, shellface *dyingsh)
08335 {
08336   // Set shellface's vertices to NULL. This makes it possible to detect dead
08337   //   shellfaces when traversing the list of all shellfaces.
08338   dyingsh[3] = (shellface) NULL;
08339   dyingsh[4] = (shellface) NULL;
08340   dyingsh[5] = (shellface) NULL;
08341   pool->dealloc((void *) dyingsh);
08342 }
08343 
08345 //                                                                           //
08346 // shellfacetraverse()    Traverse the subfaces, skipping dead ones. Used    //
08347 //                        for both subfaces and subsegments pool traverse.   //
08348 //                                                                           //
08350 
08351 tetgenmesh::shellface* tetgenmesh::shellfacetraverse(memorypool *pool)
08352 {
08353   shellface *newshellface;
08354 
08355   do {
08356     newshellface = (shellface *) pool->traverse();
08357     if (newshellface == (shellface *) NULL) {
08358       return (shellface *) NULL;
08359     }
08360   } while (newshellface[3] == (shellface) NULL);          // Skip dead ones.
08361   return newshellface;
08362 }
08363 
08365 //                                                                           //
08366 // badfacedealloc()    Deallocate space for a badface, marking it dead.      //
08367 //                                                                           //
08369 
08370 void tetgenmesh::badfacedealloc(memorypool *pool, badface *dying)
08371 {
08372   // Set badface's forg to NULL. This makes it possible to detect dead
08373   //   ones when traversing the list of all items.
08374   dying->forg = (point) NULL;
08375   pool->dealloc((void *) dying);
08376 }
08377 
08379 //                                                                           //
08380 // badfacetraverse()    Traverse the pools, skipping dead ones.              //
08381 //                                                                           //
08383 
08384 tetgenmesh::badface* tetgenmesh::badfacetraverse(memorypool *pool)
08385 {
08386   badface *newsh;
08387 
08388   do {
08389     newsh = (badface *) pool->traverse();
08390     if (newsh == (badface *) NULL) {
08391       return (badface *) NULL;
08392     }
08393   } while (newsh->forg == (point) NULL);               // Skip dead ones.
08394   return newsh;
08395 }
08396 
08398 //                                                                           //
08399 // pointdealloc()    Deallocate space for a point, marking it dead.          //
08400 //                                                                           //
08402 
08403 void tetgenmesh::pointdealloc(point dyingpoint)
08404 {
08405   // Mark the point as dead. This  makes it possible to detect dead points
08406   //   when traversing the list of all points.
08407   setpointtype(dyingpoint, DEADVERTEX);
08408   points->dealloc((void *) dyingpoint);
08409 }
08410 
08412 //                                                                           //
08413 // pointtraverse()    Traverse the points, skipping dead ones.               //
08414 //                                                                           //
08416 
08417 tetgenmesh::point tetgenmesh::pointtraverse()
08418 {
08419   point newpoint;
08420 
08421   do {
08422     newpoint = (point) points->traverse();
08423     if (newpoint == (point) NULL) {
08424       return (point) NULL;
08425     }
08426   } while (pointtype(newpoint) == DEADVERTEX);            // Skip dead ones.
08427   return newpoint;
08428 }
08429 
08431 //                                                                           //
08432 // maketetrahedron()    Create a new tetrahedron.                            //
08433 //                                                                           //
08435 
08436 void tetgenmesh::maketetrahedron(triface *newtet)
08437 {
08438   newtet->tet = (tetrahedron *) tetrahedrons->alloc();
08439   // Initialize the four adjoining tetrahedra to be "outer space".
08440   newtet->tet[0] = (tetrahedron) dummytet;
08441   newtet->tet[1] = (tetrahedron) dummytet;
08442   newtet->tet[2] = (tetrahedron) dummytet;
08443   newtet->tet[3] = (tetrahedron) dummytet;
08444   // Four NULL vertices.
08445   newtet->tet[4] = (tetrahedron) NULL;
08446   newtet->tet[5] = (tetrahedron) NULL;
08447   newtet->tet[6] = (tetrahedron) NULL;
08448   newtet->tet[7] = (tetrahedron) NULL;
08449   // Initialize the four adjoining subfaces to be the omnipresent subface.
08450   if (b->useshelles) {
08451     newtet->tet[8 ] = (tetrahedron) dummysh;
08452     newtet->tet[9 ] = (tetrahedron) dummysh;
08453     newtet->tet[10] = (tetrahedron) dummysh;
08454     newtet->tet[11] = (tetrahedron) dummysh;
08455     newtet->tet[12] = (tetrahedron) dummysh;
08456     newtet->tet[13] = (tetrahedron) dummysh;
08457   }
08458   for (int i = 0; i < in->numberoftetrahedronattributes; i++) {
08459     setelemattribute(newtet->tet, i, 0.0);
08460   }
08461   if (b->varvolume) {
08462     setvolumebound(newtet->tet, -1.0);
08463   }
08464   // Initialize the location and version to be Zero.
08465   newtet->loc = 0;
08466   newtet->ver = 0;
08467 }
08468 
08470 //                                                                           //
08471 // makeshellface()    Create a new shellface with version zero. Used for     //
08472 //                    both subfaces and seusegments.                         //
08473 //                                                                           //
08475 
08476 void tetgenmesh::makeshellface(memorypool *pool, face *newface)
08477 {
08478   newface->sh = (shellface *) pool->alloc();
08479   //Initialize the three adjoining subfaces to be the omnipresent subface.
08480   newface->sh[0] = (shellface) dummysh;
08481   newface->sh[1] = (shellface) dummysh;
08482   newface->sh[2] = (shellface) dummysh;
08483   // Three NULL vertices.
08484   newface->sh[3] = (shellface) NULL;
08485   newface->sh[4] = (shellface) NULL;
08486   newface->sh[5] = (shellface) NULL;
08487   // Initialize the two adjoining tetrahedra to be "outer space".
08488   newface->sh[6] = (shellface) dummytet;
08489   newface->sh[7] = (shellface) dummytet;
08490   // Initialize the three adjoining subsegments to be the omnipresent
08491   //   subsegments.
08492   newface->sh [8] = (shellface) dummysh;
08493   newface->sh [9] = (shellface) dummysh;
08494   newface->sh[10] = (shellface) dummysh;
08495   // Initialize the pointer to badface structure.
08496   newface->sh[11] = (shellface) NULL;
08497   if (b->quality && varconstraint) {
08498     // Initialize the maximum area bound.
08499     setareabound(*newface, 0.0);
08500   }
08501   // Set the boundary marker to zero.
08502   setshellmark(*newface, 0);
08503   // Set the type.
08504   setshelltype(*newface, NSHARP);
08505   if (checkpbcs) {
08506     // Set the pbcgroup be ivalid.
08507     setshellpbcgroup(*newface, -1);
08508   }
08509   // Initialize the version to be Zero.
08510   newface->shver = 0;
08511 }
08512 
08514 //                                                                           //
08515 // makepoint()    Create a new point.                                        //
08516 //                                                                           //
08518 
08519 void tetgenmesh::makepoint(point* pnewpoint)
08520 {
08521   int ptmark, i;
08522 
08523   *pnewpoint = (point) points->alloc();
08524   // Initialize three coordinates.
08525   (*pnewpoint)[0] = 0.0;
08526   (*pnewpoint)[1] = 0.0;
08527   (*pnewpoint)[2] = 0.0;
08528   // Initialize the list of user-defined attributes.
08529   for (i = 0; i < in->numberofpointattributes; i++) {
08530     (*pnewpoint)[3 + i] = 0.0;
08531   }
08532   // Initialize the metric tensor.
08533   for (i = 0; i < sizeoftensor; i++) {
08534     (*pnewpoint)[pointmtrindex + i] = 0.0;
08535   }
08536   if (b->plc || b->refine) {
08537     // Initialize the point-to-simplex filed.
08538     setpoint2tet(*pnewpoint, NULL);
08539     setpoint2sh(*pnewpoint, NULL);
08540     setpoint2ppt(*pnewpoint, NULL);
08541     if (b->metric) {
08542       setpoint2bgmtet(*pnewpoint, NULL);
08543     }
08544     if (checkpbcs) {
08545       // Initialize the other pointer to its pbc point.
08546       setpoint2pbcpt(*pnewpoint, NULL);
08547     }
08548   }
08549   // Initialize the point marker (starting from in->firstnumber).
08550   ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
08551   setpointmark(*pnewpoint, ptmark);
08552   // Initialize the point type.
08553   setpointtype(*pnewpoint, UNUSEDVERTEX);
08554 }
08555 
08556 //
08557 // End of memory management routines
08558 //
08559 
08560 //
08561 // Begin of point location routines
08562 //
08563 
08565 //                                                                           //
08566 // randomnation()    Generate a random number between 0 and 'choices' - 1.   //
08567 //                                                                           //
08569 
08570 unsigned long tetgenmesh::randomnation(unsigned int choices)
08571 {
08572   unsigned long newrandom;
08573 
08574   if (choices >= 714025l) {
08575     newrandom = (randomseed * 1366l + 150889l) % 714025l;
08576     randomseed = (newrandom * 1366l + 150889l) % 714025l;
08577     newrandom = newrandom * (choices / 714025l) + randomseed;
08578     if (newrandom >= choices) {
08579       return newrandom - choices;
08580     } else {
08581       return newrandom;
08582     }
08583   } else {
08584     randomseed = (randomseed * 1366l + 150889l) % 714025l;
08585     return randomseed % choices;
08586   }
08587   // Old function.
08588   // randomseed = (randomseed * 1366l + 150889l) % 714025l;
08589   // return randomseed / (714025l / choices + 1);
08590 }
08591 
08593 //                                                                           //
08594 // distance2()    Returns the square "distance" of a tetrahedron to point p. //
08595 //                                                                           //
08597 
08598 REAL tetgenmesh::distance2(tetrahedron* tetptr, point p)
08599 {
08600   point p1, p2, p3, p4;
08601   REAL dx, dy, dz;
08602 
08603   p1 = (point) tetptr[4];
08604   p2 = (point) tetptr[5];
08605   p3 = (point) tetptr[6];
08606   p4 = (point) tetptr[7];
08607 
08608   dx = p[0] - 0.25 * (p1[0] + p2[0] + p3[0] + p4[0]);
08609   dy = p[1] - 0.25 * (p1[1] + p2[1] + p3[1] + p4[1]);
08610   dz = p[2] - 0.25 * (p1[2] + p2[2] + p3[2] + p4[2]);
08611 
08612   return dx * dx + dy * dy + dz * dz;
08613 }
08614 
08616 //                                                                           //
08617 // preciselocate()    Find a simplex containing a given point.               //
08618 //                                                                           //
08619 // This routine implements the simple Walk-through point location algorithm. //
08620 // Begins its search from 'searchtet', assume there is a line segment L from //
08621 // a vertex of 'searchtet' to the query point 'searchpt', and simply walk    //
08622 // towards 'searchpt' by traversing all faces intersected by L.              //
08623 //                                                                           //
08624 // On completion, 'searchtet' is a tetrahedron that contains 'searchpt'. The //
08625 // returned value indicates one of the following cases:                      //
08626 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchtet' //
08627 //     is a handle whose origin is the existing vertex.                      //
08628 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchtet' is a    //
08629 //     handle whose primary edge is the edge on which the point lies.        //
08630 //   - Returns ONFACE if the point lies strictly within a face. 'searchtet'  //
08631 //     is a handle whose primary face is the face on which the point lies.   //
08632 //   - Returns INTETRAHEDRON if the point lies strictly in a tetrahededron.  //
08633 //     'searchtet' is a handle on the tetrahedron that contains the point.   //
08634 //   - Returns OUTSIDE if the point lies outside the mesh. 'searchtet' is a  //
08635 //     handle whose location is the face the point is to 'above' of.         //
08636 //                                                                           //
08637 // WARNING: This routine is designed for convex triangulations, and will not //
08638 // generally work after the holes and concavities have been carved.          //
08639 //                                                                           //
08640 // If 'maxtetnumber' > 0, stop the searching process if the number of passed //
08641 // tets is larger than it and return OUTSIDE.                                //
08642 //                                                                           //
08644 
08645 enum tetgenmesh::locateresult tetgenmesh::preciselocate(point searchpt,
08646   triface* searchtet, long maxtetnumber)
08647 {
08648   triface backtracetet;
08649   triface walkthroface;
08650   point forg, fdest, fapex, toppo;
08651   REAL ori1, ori2, ori3, ori4;
08652   long tetnumber;
08653   int side;
08654 
08655   if (isdead(searchtet)) searchtet->tet = dummytet;
08656   if (searchtet->tet == dummytet) {
08657     searchtet->loc = 0;
08658     symself(*searchtet);
08659   }
08660   // 'searchtet' should be a valid tetrahedron now.
08661 #ifdef SELF_CHECK
08662   // assert(!isdead(searchtet) && (searchtet->tet != dummytet));
08663 #endif
08664   if (isdead(searchtet)) {
08665     printf("Warning:  Point location failed.\n");
08666     return OUTSIDE;
08667   }
08668 
08669   searchtet->ver = 0; // Keep in CCW edge ring.
08670   // Find a face of 'searchtet' such that the 'searchpt' lies strictly
08671   //   above it.  Such face should always exist.
08672   for (searchtet->loc = 0; searchtet->loc < 4; searchtet->loc++) {
08673     forg = org(*searchtet);
08674     fdest = dest(*searchtet);
08675     fapex = apex(*searchtet);
08676     ori1 = orient3d(forg, fdest, fapex, searchpt);
08677     if (ori1 < 0.0) break;
08678   }
08679 #ifdef SELF_CHECK
08680   assert(searchtet->loc < 4);
08681 #endif
08682 
08683   // Define 'tetnumber' for exit the loop when it's running endless.
08684   tetnumber = 0l;
08685   while ((maxtetnumber > 0l) && (tetnumber <= maxtetnumber)) {
08686     // Check if we are reaching the boundary of the triangulation.
08687     if (searchtet->tet == dummytet) {
08688       *searchtet = backtracetet;
08689       return OUTSIDE;
08690     }
08691     // Initialize the face for returning the walk-through face.
08692     walkthroface.tet = (tetrahedron *) NULL;
08693     // Adjust the edge ring, so that 'ori1 < 0.0' holds.
08694     searchtet->ver = 0;
08695     // 'toppo' remains unchange for the following orientation tests.
08696     toppo = oppo(*searchtet);
08697     // Check the three sides of 'searchtet' to find the face through which
08698     //   we can walk next.
08699     for (side = 0; side < 3; side++) {
08700       forg = org(*searchtet);
08701       fdest = dest(*searchtet);
08702       ori2 = orient3d(forg, fdest, toppo, searchpt);
08703       if (ori2 == 0.0) {
08704         // They are coplanar, check if 'searchpt' lies inside, or on an edge,
08705         //   or coindice with a vertex of face (forg, fdest, toppo). 
08706         fapex = apex(*searchtet);
08707         ori3 = orient3d(fdest, fapex, toppo, searchpt);
08708         if (ori3 < 0.0) {
08709           // Outside the face (fdest, fapex, toppo), walk through it.
08710           enextself(*searchtet);
08711           fnext(*searchtet, walkthroface);
08712           break;
08713         }
08714         ori4 = orient3d(fapex, forg, toppo, searchpt);
08715         if (ori4 < 0.0) {
08716           // Outside the face (fapex, forg, toppo), walk through it.
08717           enext2self(*searchtet);
08718           fnext(*searchtet, walkthroface);
08719           break;
08720         }
08721         // Remember, ori1 < 0.0, which means 'searchpt' will not on edge
08722         //   (forg, fdest) or on vertex forg or fdest.
08723 #ifdef SELF_CHECK
08724         assert(ori1 < 0.0);
08725 #endif
08726         // The rest possible cases are: 
08727         //   (1) 'searchpt' lies on edge (fdest, toppo);
08728         //   (2) 'searchpt' lies on edge (toppo, forg);
08729         //   (3) 'searchpt' coincident with toppo;
08730         //   (4) 'searchpt' lies inside face (forg, fdest, toppo).
08731         fnextself(*searchtet);
08732         if (ori3 == 0.0) {
08733           if (ori4 == 0.0) {
08734             // Case (4).
08735             enext2self(*searchtet);
08736             return ONVERTEX;
08737           } else {
08738             // Case (1).
08739             enextself(*searchtet);
08740             return ONEDGE;
08741           }
08742         }
08743         if (ori4 == 0.0) {
08744           // Case (2).
08745           enext2self(*searchtet);
08746           return ONEDGE;
08747         }
08748         // Case (4).
08749         return ONFACE;
08750       } else if (ori2 < 0.0) {
08751         // Outside the face (forg, fdest, toppo), walk through it.
08752         fnext(*searchtet, walkthroface);
08753         break;
08754       }
08755       // Go to check next side.
08756       enextself(*searchtet);
08757     }
08758     if (side >= 3) {
08759       // Found! Inside tetrahedron.
08760       return INTETRAHEDRON;
08761     }
08762     // We walk through the face 'walkthroface' and continue the searching.
08763 #ifdef SELF_CHECK
08764     assert(walkthroface.tet != (tetrahedron *) NULL);
08765 #endif
08766     // Store the face handle in 'backtracetet' before we take the real walk.
08767     //   So we are able to restore the handle to 'searchtet' if we are
08768     //   reaching the outer boundary.
08769     backtracetet = walkthroface;
08770     sym(walkthroface, *searchtet);    
08771     tetnumber++;
08772   }
08773 
08774   // Should never be here.
08775   // printf("Internal error in preciselocate(): Point location failed.\n");
08776   // internalerror();
08777   return OUTSIDE;
08778 }
08779 
08781 //                                                                           //
08782 // locate()    Find a simplex containing a given point.                      //
08783 //                                                                           //
08784 // This routine implements Muecke's Jump-and-walk point location algorithm.  //
08785 // It improves the simple walk-through by "jumping" to a good starting point //
08786 // via random sampling.  Searching begins from one of handles:  the input    //
08787 // 'searchtet', a recently encountered tetrahedron 'recenttet',  or from one //
08788 // chosen from a random sample.  The choice is made by determining which one //
08789 // 's barycenter is closest to the point we are searcing for.  Having chosen //
08790 // the starting tetrahedron, the simple Walk-through algorithm is used to do //
08791 // the real walking.                                                         //
08792 //                                                                           //
08793 // The return value indicates the location of the 'searchpt' (INTETRAHEDRON, //
08794 // or ONFACE, ...). 'searchtet' is adjusted to a tetrahedron corresponding   //
08795 // to that value. See the introduction part of preciselocate() for detail.   //
08796 //                                                                           //
08797 // WARNING: This routine is designed for convex triangulations, and will not //
08798 // generally work after the holes and concavities have been carved.          //
08799 //                                                                           //
08801 
08802 enum tetgenmesh::locateresult tetgenmesh::locate(point searchpt, 
08803   triface *searchtet)
08804 {
08805   tetrahedron *firsttet, *tetptr;
08806   void **sampleblock;
08807   long sampleblocks, samplesperblock, samplenum;
08808   long tetblocks, i, j;
08809   unsigned long alignptr;
08810   REAL searchdist, dist;
08811 
08812   // 'searchtet' should be a valid tetrahedron.
08813   if (isdead(searchtet)) {
08814     searchtet->tet = dummytet;
08815   }
08816   if (searchtet->tet == dummytet) {
08817     // This is an 'Outer Space' handle, get a hull tetrahedron.
08818     searchtet->loc = 0;
08819     symself(*searchtet);
08820   }
08821 #ifdef SELF_CHECK
08822   // assert(!isdead(searchtet));
08823 #endif
08824   if (isdead(searchtet)) {
08825     printf("Warning:  Point location failed.\n");
08826     return OUTSIDE;
08827   }
08828   
08829   // Get the distance from the suggested starting tet to the point we seek.
08830   searchdist = distance2(searchtet->tet, searchpt);
08831 
08832   // If a recently encountered tetrahedron has been recorded and has not
08833   //   been deallocated, test it as a good starting point.
08834   if (!isdead(&recenttet) && (recenttet.tet != searchtet->tet)) {
08835     dist = distance2(recenttet.tet, searchpt);
08836     if (dist < searchdist) {
08837       *searchtet = recenttet;
08838       searchdist = dist;
08839     }
08840   }
08841 
08842   // Select "good" candidate using k random samples, taking the closest one.
08843   //   The number of random samples taken is proportional to the fourth root
08844   //   of the number of tetrahedra in the mesh. The next bit of code assumes
08845   //   that the number of tetrahedra increases monotonically.
08846   while (SAMPLEFACTOR * samples * samples * samples * samples <
08847          tetrahedrons->items) {
08848     samples++;
08849   }
08850   // Find how much blocks in current tet pool.
08851   tetblocks = (tetrahedrons->maxitems + ELEPERBLOCK - 1) / ELEPERBLOCK;
08852   // Find the average samles per block. Each block at least have 1 sample.
08853   samplesperblock = 1 + (samples / tetblocks);
08854   sampleblocks = samples / samplesperblock;
08855   sampleblock = tetrahedrons->firstblock;
08856   for (i = 0; i < sampleblocks; i++) {
08857     alignptr = (unsigned long) (sampleblock + 1);
08858     firsttet = (tetrahedron *)
08859                (alignptr + (unsigned long) tetrahedrons->alignbytes
08860                - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08861     for (j = 0; j < samplesperblock; j++) {
08862       if (i == tetblocks - 1) {
08863         // This is the last block.
08864         samplenum = randomnation((int)
08865                       (tetrahedrons->maxitems - (i * ELEPERBLOCK)));
08866       } else {
08867         samplenum = randomnation(ELEPERBLOCK);
08868       }
08869       tetptr = (tetrahedron *)
08870                (firsttet + (samplenum * tetrahedrons->itemwords));
08871       if (tetptr[4] != (tetrahedron) NULL) {
08872         dist = distance2(tetptr, searchpt);
08873         if (dist < searchdist) {
08874           searchtet->tet = tetptr;
08875           searchdist = dist;
08876         }
08877       }
08878     }
08879     sampleblock = (void **) *sampleblock;
08880   }
08881   
08882   // Call simple walk-through to locate the point.
08883   return preciselocate(searchpt, searchtet, tetrahedrons->items); 
08884 }
08885 
08887 //                                                                           //
08888 // adjustlocate()    Adjust the precise location of a vertex.                //
08889 //                                                                           //
08890 // 'precise' is the value returned from preciselocate().  It indicates the   //
08891 // exact location of the point 'searchpt' with respect to the tetrahedron    //
08892 // 'searchtet'.  'epspp' is a given relative tolerance.                      //
08893 //                                                                           //
08894 // This routine re-evaluates the orientations of searchpt with respect to    //
08895 // the four sides of searchtet. Detects the coplanarities by additinal tests //
08896 // which are based on the given tolerance. If 'precise' is ONFACE or ONEDGE, //
08897 // we can save one or two orientation tests.                                 //
08898 //                                                                           //
08899 // The return value indicates the location of the 'searchpt' (INTETRAHEDRON, //
08900 // or ONFACE, ...). 'searchtet' is adjusted to a tetrahedron corresponding   //
08901 // to that value. See the introduction part of preciselocate() for detail.   //
08902 //                                                                           //
08903 // WARNING:  This routine detect degenerate case using relative tolerance.   //
08904 // It is better used after locate() or preciselocate().  For general inputs, //
08905 // it may not able to tell the correct location.                             //
08906 //                                                                           //
08908 
08909 enum tetgenmesh::locateresult tetgenmesh::adjustlocate(point searchpt,
08910   triface* searchtet, enum locateresult precise, REAL epspp)
08911 {
08912   point torg, tdest, tapex, toppo;
08913   REAL s1, s2, s3, s4;
08914 
08915   // For the given 'searchtet', the orientations tests are:
08916   //  s1: (tdest, torg, tapex, searchpt);
08917   //  s2: (torg, tdest, toppo, searchpt);
08918   //  s3: (tdest, tapex, toppo, searchpt);
08919   //  s4: (tapex, torg, toppo, searchpt);
08920   adjustedgering(*searchtet, CCW);
08921   torg = org(*searchtet);
08922   tdest = dest(*searchtet);
08923   tapex = apex(*searchtet);
08924   toppo = oppo(*searchtet);
08925 
08926   switch (precise) {
08927   case ONVERTEX:
08928     // This case we don't need do any further test.
08929     return ONVERTEX;
08930   case ONEDGE:
08931     // (torg, tdest);
08932     s1 = 0.0;
08933     s2 = 0.0;
08934     break;
08935   case ONFACE:
08936     // (tdest, torg, tapex);
08937     s1 = 0.0;
08938     s2 = orient3d(torg, tdest, toppo, searchpt);
08939     break;
08940   default: // INTETRAHEDRON or OUTSIDE
08941     s1 = orient3d(tdest, torg, tapex, searchpt);
08942     s2 = orient3d(torg, tdest, toppo, searchpt);
08943   }
08944   
08945   if (s1 != 0.0) {
08946     if (iscoplanar(tdest, torg, tapex, searchpt, s1, epspp)) {
08947       s1 = 0.0;
08948     }
08949   }
08950   if (s1 < 0.0) {
08951     return OUTSIDE;
08952   }
08953 
08954   if (s2 != 0.0) {
08955     if (iscoplanar(torg, tdest, toppo, searchpt, s2, epspp)) {
08956       s2 = 0.0;
08957     }
08958   }
08959   if (s2 < 0.0) {
08960     fnextself(*searchtet);
08961     return OUTSIDE;
08962   }
08963 
08964   s3 = orient3d(tdest, tapex, toppo, searchpt);
08965   if (s3 != 0.0) {
08966     if (iscoplanar(tdest, tapex, toppo, searchpt, s3, epspp)) {
08967       s3 = 0.0;
08968     }
08969   }
08970   if (s3 < 0.0) {
08971     enextfnextself(*searchtet);
08972     return OUTSIDE;
08973   }
08974 
08975   s4 = orient3d(tapex, torg, toppo, searchpt);
08976   if (s4 != 0.0) {
08977     if (iscoplanar(tapex, torg, toppo, searchpt, s4, epspp)) {
08978       s4 = 0.0;
08979     }
08980   }
08981   if (s4 < 0.0) {
08982     enext2fnextself(*searchtet);
08983     return OUTSIDE;
08984   }
08985 
08986   // Determine degenerate cases.
08987   if (s1 == 0.0) {
08988     if (s2 == 0.0) {
08989       if (s3 == 0.0) {
08990         // On tdest.
08991         enextself(*searchtet);
08992         return ONVERTEX;
08993       }
08994       if (s4 == 0.0) {
08995         // On torg.
08996         return ONVERTEX;
08997       }
08998       // On edge (torg, tdest).
08999       return ONEDGE;
09000     }
09001     if (s3 == 0.0) {
09002       if (s4 == 0.0) {
09003         // On tapex.
09004         enext2self(*searchtet);
09005         return ONVERTEX;
09006       }
09007       // On edge (tdest, tapex).
09008       enextself(*searchtet);
09009       return ONEDGE;
09010     }
09011     if (s4 == 0.0) {
09012       // On edge (tapex, torg).
09013       enext2self(*searchtet);
09014       return ONEDGE;
09015     }
09016     // On face (torg, tdest, tapex).
09017     return ONFACE;
09018   }
09019   if (s2 == 0.0) {
09020     fnextself(*searchtet);
09021     if (s3 == 0.0) {
09022       if (s4 == 0.0) {
09023         // On toppo.
09024         enext2self(*searchtet);
09025         return ONVERTEX;
09026       }
09027       // On edge (tdest, toppo).
09028       enextself(*searchtet);
09029       return ONEDGE;
09030     }
09031     if (s4 == 0.0) {
09032       // On edge (toppo, torg).
09033       enext2self(*searchtet);
09034       return ONEDGE;
09035     }
09036     // On face (torg, tdest, toppo).
09037     return ONFACE;
09038   }
09039   if (s3 == 0.0) {
09040     enextfnextself(*searchtet);
09041     if (s4 == 0.0) {
09042       // On edge (tapex, toppo).
09043       enextself(*searchtet);
09044       return ONEDGE;
09045     }
09046     // On face (tdest, tapex, toppo).
09047     return ONFACE;
09048   }
09049   if (s4 == 0.0) {
09050     enext2fnextself(*searchtet);
09051     // On face (tapex, torg, toppo).
09052     return ONFACE;
09053   }
09054 
09055   // Inside tetrahedron.
09056   return INTETRAHEDRON;
09057 }
09058 
09060 //                                                                           //
09061 // hullwalk()    Find a tetrahedron on the hull to continue search.          //
09062 //                                                                           //
09064 
09065 enum tetgenmesh::locateresult tetgenmesh::hullwalk(point searchpt,
09066   triface *hulltet)
09067 {
09068   list* travtetlist;
09069   triface travtet, neightet;
09070   point pa, pb, pc;
09071   enum locateresult loc;
09072   REAL ori;
09073   int i;
09074 
09075   travtetlist = new list(sizeof(triface), NULL, 256);
09076   travtet = *hulltet;
09077   infect(travtet);
09078   travtetlist->append(&travtet);
09079 
09080   loc = OUTSIDE;
09081   for (i = 0; i < travtetlist->len(); i++) {
09082     travtet = * (triface *)(* travtetlist)[i];
09083     // Choose the CCW-edgering in face.
09084     travtet.ver = 0;
09085     // Look for a side where pt lies below it.
09086     for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09087       pa = org(travtet);
09088       pb = dest(travtet);
09089       pc = apex(travtet);
09090       ori = orient3d(pa, pb, pc, searchpt);
09091       if (ori > 0.0) break;
09092     }
09093     // Is pt above all (or coplanar with some of) the four sides?
09094     if (travtet.loc == 4) {
09095       hulltet->tet = travtet.tet;
09096       loc = adjustlocate(searchpt, hulltet, INTETRAHEDRON, b->epsilon);
09097       assert(loc != OUTSIDE);
09098     } else { // ori > 0.0
09099       // pt is below (behind) this side. We want to walk through it.
09100       sym(travtet, neightet);
09101       if (neightet.tet == dummytet) {
09102         // This is a hull side. Is p approximately on this side.
09103         loc = adjustlocate(searchpt, &travtet, OUTSIDE, b->epsilon);
09104       }
09105       if (loc == OUTSIDE) {
09106         // Let's collect all the neighbors for next searching.
09107         for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09108           sym(travtet, neightet);
09109           if ((neightet.tet != dummytet) && !infected(neightet)) {
09110             // Neighbor exists and not visited.
09111             infect(neightet);
09112             travtetlist->append(&neightet);
09113           }
09114         } // for (travtet.loc = 0; 
09115       } // if (loc == OUTSIDE)
09116     } // if (travtet.loc == 4)
09117     if (loc != OUTSIDE) break;
09118   } // for (i = 0; i < travtetlist->len(); i++)
09119   
09120   // Uninfect traversed tets.
09121   for (i = 0; i < travtetlist->len(); i++) {
09122     travtet = * (triface *)(* travtetlist)[i];
09123     uninfect(travtet);
09124   }
09125 
09126   delete travtetlist;
09127   return loc;
09128 }
09129 
09131 //                                                                           //
09132 // locatesub()    Find a point in the surface mesh of a facet.               //
09133 //                                                                           //
09134 // Searching begins from the input 'searchsh', it should be a handle on the  //
09135 // convex hull of the facet triangulation.                                   //
09136 //                                                                           //
09137 // If 'stopatseg' is nonzero, the search will stop if it tries to walk       //
09138 // through a subsegment, and will return OUTSIDE.                            //
09139 //                                                                           //
09140 // On completion, 'searchsh' is a subface that contains 'searchpt'.          //
09141 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchsh'  //
09142 //     is a handle whose origin is the existing vertex.                      //
09143 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchsh' is a     //
09144 //     handle whose primary edge is the edge on which the point lies.        //
09145 //   - Returns ONFACE if the point lies strictly within a subface.           //
09146 //     'searchsh' is a handle on which the point lies.                       //
09147 //   - Returns OUTSIDE if the point lies outside the triangulation.          //
09148 //                                                                           //
09149 // WARNING: This routine is designed for convex triangulations, and will not //
09150 // not generally work after the holes and concavities have been carved.      //
09151 //                                                                           //
09153 
09154 enum tetgenmesh::locateresult tetgenmesh::locatesub(point searchpt,
09155   face* searchsh, int stopatseg, REAL epspp)
09156 {
09157   face backtracksh, spinsh, checkedge;
09158   point forg, fdest, fapex;
09159   REAL orgori, destori;
09160   REAL ori, sign;
09161   int moveleft, i;
09162 
09163   if (searchsh->sh == dummysh) {
09164     searchsh->shver = 0;
09165     spivotself(*searchsh);
09166 #ifdef SELF_CHECK
09167     assert(searchsh->sh != dummysh);
09168 #endif
09169   }
09170   // Find the sign to simulate that abovepoint is 'above' the facet.
09171   adjustedgering(*searchsh, CCW);
09172   forg = sorg(*searchsh);
09173   fdest = sdest(*searchsh);
09174   fapex = sapex(*searchsh);
09175   ori = orient3d(forg, fdest, fapex, abovepoint);
09176   sign = ori > 0.0 ? -1 : 1;
09177 
09178   // Orient 'searchsh' so that 'searchpt' is below it (i.e., searchpt has
09179   //   CCW orientation with respect to searchsh in plane).  Such edge
09180   //   should always exist. Save it as (forg, fdest).
09181   for (i = 0; i < 3; i++) {
09182     forg = sorg(*searchsh);
09183     fdest = sdest(*searchsh);
09184     ori = orient3d(forg, fdest, abovepoint, searchpt) * sign;
09185     if (ori > 0.0) break;
09186     senextself(*searchsh);
09187   }
09188 #ifdef SELF_CHECK
09189   assert(i < 3);
09190 #endif
09191   
09192   while (1) {
09193     fapex = sapex(*searchsh);
09194     // Check whether the apex is the point we seek.
09195     if (fapex[0] == searchpt[0] && fapex[1] == searchpt[1] &&
09196         fapex[2] == searchpt[2]) {
09197       senext2self(*searchsh);
09198       return ONVERTEX;
09199     }
09200     // Does the point lie on the other side of the line defined by the
09201     //   triangle edge opposite the triangle's destination?
09202     destori = orient3d(forg, fapex, abovepoint, searchpt) * sign;
09203     if (epspp > 0.0) {
09204       if (iscoplanar(forg, fapex, abovepoint, searchpt, destori, epspp)) {
09205         destori = 0.0;
09206       }
09207     }
09208     // Does the point lie on the other side of the line defined by the
09209     //   triangle edge opposite the triangle's origin? 
09210     orgori = orient3d(fapex, fdest, abovepoint, searchpt) * sign;
09211     if (epspp > 0.0) {
09212       if (iscoplanar(fapex, fdest, abovepoint, searchpt, orgori, epspp)) {
09213         orgori = 0.0;
09214       }
09215     }
09216     if (destori > 0.0) {
09217       moveleft = 1;
09218     } else {
09219       if (orgori > 0.0) {
09220         moveleft = 0;
09221       } else {
09222         // The point must be on the boundary of or inside this triangle.
09223         if (destori == 0.0) {
09224           senext2self(*searchsh);
09225           return ONEDGE;
09226         } 
09227         if (orgori == 0.0) {
09228           senextself(*searchsh);
09229           return ONEDGE;
09230         }
09231         return ONFACE;
09232       }
09233     }
09234     // Move to another triangle.  Leave a trace `backtracksh' in case
09235     //   walking off a boundary of the triangulation.
09236     if (moveleft) {
09237       senext2(*searchsh, backtracksh);
09238       fdest = fapex;
09239     } else {
09240       senext(*searchsh, backtracksh);
09241       forg = fapex;
09242     }
09243     // Check if we meet a segment.
09244     sspivot(backtracksh, checkedge);
09245     if (checkedge.sh != dummysh) {
09246       if (stopatseg) {
09247         // The flag indicates we should not cross a segment. Stop.
09248         *searchsh = backtracksh;
09249         return OUTSIDE;
09250       }
09251       // Try to walk through a segment. We need to find a coplanar subface
09252       //   sharing this segment to get into.
09253       spinsh = backtracksh;
09254       do {
09255         spivotself(spinsh);
09256         if (spinsh.sh == backtracksh.sh) {
09257           // Turn back, no coplanar subface is found.
09258           break;
09259         }
09260         // Are they belong to the same facet.
09261         if (shellmark(spinsh) == shellmark(backtracksh)) {
09262           // Find a coplanar subface. Walk into it.
09263           *searchsh = spinsh;
09264           break;
09265         }
09266         // Are they (nearly) coplanar?
09267         ori = orient3d(forg, fdest, sapex(backtracksh), sapex(spinsh));
09268         if (iscoplanar(forg, fdest, sapex(backtracksh), sapex(spinsh), ori,
09269                        b->epsilon)) {
09270           // Find a coplanar subface. Walk into it.
09271           *searchsh = spinsh;
09272           break;
09273         }
09274       } while (spinsh.sh != backtracksh.sh);
09275     } else {
09276       spivot(backtracksh, *searchsh);
09277     }
09278     // Check for walking right out of the triangulation.
09279     if ((searchsh->sh == dummysh) || (searchsh->sh == backtracksh.sh)) {
09280       // Go back to the last triangle.
09281       *searchsh = backtracksh;
09282       return OUTSIDE;
09283     }
09284     // To keep the same orientation wrt abovepoint.
09285     if (sorg(*searchsh) != forg) sesymself(*searchsh);
09286 #ifdef SELF_CHECK
09287     assert((sorg(*searchsh) == forg) && (sdest(*searchsh) == fdest));
09288 #endif
09289   }
09290 }
09291 
09293 //                                                                           //
09294 // adjustlocatesub()    Adjust the precise location of a vertex.             //
09295 //                                                                           //
09296 // 'precise' is the precise location (returned from locatesub()) of 'searcht'//
09297 // with respect to 'searchsh'. 'epspp' is the given relative tolerance.      //
09298 //                                                                           //
09299 // This routine re-evaluates the orientations of 'searchpt' with respect to  //
09300 // the three edges of 'searchsh'. Detects the collinearities by additinal    //
09301 // tests based on the given tolerance. If 'precise' is ONEDGE, one can save  //
09302 // one orientation test for the current edge of 'searchsh'.                  //
09303 //                                                                           //
09304 // On completion, 'searchsh' is a subface contains 'searchpt'. The returned  //
09305 // value indicates one of the following cases:                               //
09306 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchsh'  //
09307 //     is a handle whose origin is the existing vertex.                      //
09308 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchsh' is a     //
09309 //     handle whose primary edge is the edge on which the point lies.        //
09310 //   - Returns ONFACE if the point lies strictly within a subface.           //
09311 //     'searchsh' is a handle on which the point lies.                       //
09312 //   - Returns OUTSIDE if the point lies outside 'searchsh'.                 //
09313 //                                                                           //
09315 
09316 enum tetgenmesh::locateresult tetgenmesh::
09317 adjustlocatesub(point searchpt, face* searchsh, enum locateresult precise,
09318                 REAL epspp)
09319 {
09320   point pa, pb, pc;
09321   bool s1, s2, s3;
09322 
09323   pa = sorg(*searchsh);
09324   pb = sdest(*searchsh);
09325   pc = sapex(*searchsh);
09326 
09327   if (precise == ONEDGE) {
09328     s1 = true;
09329   } else {
09330     s1 = iscollinear(pa, pb, searchpt, epspp);
09331   }
09332   s2 = iscollinear(pb, pc, searchpt, epspp);
09333   s3 = iscollinear(pc, pa, searchpt, epspp);
09334   if (s1) {
09335     if (s2) {
09336       // on vertex pb.
09337 #ifdef SELF_CHECK
09338       assert(!s3);
09339 #endif
09340       senextself(*searchsh);
09341       return ONVERTEX;
09342     } else if (s3) {
09343       // on vertex pa.
09344       return ONVERTEX;
09345     } else {
09346       // on edge pa->pb.
09347       return ONEDGE;
09348     }
09349   } else if (s2) {
09350     if (s3) {
09351       // on vertex pc.
09352       senext2self(*searchsh);
09353       return ONVERTEX;
09354     } else {
09355       // on edge pb->pc.
09356       senextself(*searchsh);
09357       return ONEDGE;
09358     }
09359   } else if (s3) {
09360     // on edge pc->pa.
09361     senext2self(*searchsh);
09362     return ONEDGE;
09363   } else {
09364     return precise;
09365   }
09366 }
09367 
09369 //                                                                           //
09370 // locateseg()    Find a point in subsegments.                               //
09371 //                                                                           //
09372 // Searching begins from the input 'searchseg', it should be a subsegment of //
09373 // the whole segment.                                                        //
09374 //                                                                           //
09375 // On completion, 'searchseg' is a subsegment that contains 'searchpt'.      //
09376 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchseg' //
09377 //     is a handle whose origin is the existing vertex.                      //
09378 //   - Returns ONEDGE if the point lies inside 'searchseg'.                  //
09379 //   - Returns OUTSIDE if the point lies outside the segment.                //
09380 //                                                                           //
09382 
09383 enum tetgenmesh::locateresult tetgenmesh::
09384 locateseg(point searchpt, face* searchseg)
09385 {
09386   face backtraceseg;
09387   point pa, pb;
09388   REAL dx, dy, dz;
09389   int moveleft;
09390   int i;
09391 
09392   moveleft = 0;
09393   while (1) {
09394     searchseg->shver = 0;
09395     pa = sorg(*searchseg);
09396     pb = sdest(*searchseg);
09397     // Find the biggest difference in x, y, and z coordinates of a and b.
09398     dx = fabs(pb[0] - pa[0]);
09399     dy = fabs(pb[1] - pa[1]);
09400     dz = fabs(pb[2] - pa[2]);
09401     if (dx > dy) {
09402       if (dx > dz) {
09403         i = 0;
09404       } else {
09405         i = 2;
09406       }
09407     } else {
09408       if (dy > dz) {
09409         i = 1;
09410       } else {
09411         i = 2;
09412       }
09413     }
09414     if (pa[i] < pb[i]) {
09415       if (searchpt[i] < pa[i]) {
09416         moveleft = 1;
09417       } else if (searchpt[i] > pa[i]) {
09418         if (searchpt[i] < pb[i]) {
09419           return ONEDGE;
09420         } else if (searchpt[i] > pb[i]) {
09421           moveleft = 0;
09422         } else {
09423 #ifdef SELF_CHECK
09424           assert(searchpt[i] == pb[i]);
09425 #endif
09426           sesymself(*searchseg);
09427           return ONVERTEX;
09428         }
09429       } else {
09430 #ifdef SELF_CHECK
09431         assert(searchpt[i] == pa[i]);
09432 #endif
09433         return ONVERTEX;
09434       }
09435     } else if (pa[i] > pb[i]) {
09436       if (searchpt[i] < pb[i]) {
09437         moveleft = 0;
09438       } else if (searchpt[i] > pb[i]) {
09439         if (searchpt[i] < pa[i]) {
09440           return ONEDGE;
09441         } else if (searchpt[i] > pa[i]) {
09442           moveleft = 1;
09443         } else {
09444 #ifdef SELF_CHECK
09445           assert(searchpt[i] == pa[i]);
09446 #endif
09447           return ONVERTEX;
09448         }
09449       } else {
09450 #ifdef SELF_CHECK
09451         assert(searchpt[i] == pb[i]);
09452 #endif
09453         sesymself(*searchseg);
09454         return ONVERTEX;
09455       }
09456     }
09457     backtraceseg = *searchseg;
09458     if (moveleft) {
09459       senext2self(*searchseg);
09460     } else {
09461       senextself(*searchseg);
09462     }
09463     spivotself(*searchseg);
09464     if (searchseg->sh == dummysh) {
09465       *searchseg = backtraceseg;
09466       break;
09467     }
09468   }
09469 
09470   return OUTSIDE;
09471 }
09472 
09474 //                                                                           //
09475 // adjustlocateseg()    Adjust the precise location of a vertex on segment.  //
09476 //                                                                           //
09477 // 'searchpt' is either inside or ouside the segment 'searchseg'. It will be //
09478 // adjusted to on vertex if it is very close to an endpoint of 'searchseg'.  //
09479 // 'epspp' is the given relative tolerance.                                  //
09480 //                                                                           //
09482 
09483 enum tetgenmesh::locateresult tetgenmesh::
09484 adjustlocateseg(point searchpt, face* searchseg, enum locateresult precise,
09485                 REAL epspp)
09486 {
09487   point pa, pb;
09488   REAL L, d, r;
09489 
09490   pa = sorg(*searchseg);
09491   pb = sdest(*searchseg);
09492   L = distance(pa, pb);
09493 
09494   // Is searchpt approximate to pa?
09495   d = distance(pa, searchpt);
09496   r = d / L;
09497   if (r <= epspp) {
09498     return ONVERTEX;
09499   }
09500   // Is searchpt approximate to pb?
09501   d = distance(pb, searchpt);
09502   r = d / L;
09503   if (r <= epspp) {
09504     sesymself(*searchseg);
09505     return ONVERTEX;
09506   }
09507 
09508   return precise;
09509 }
09510 
09511 //
09512 // End of point location routines
09513 //
09514 
09515 //
09516 // Begin of mesh transformation routines
09517 //
09518 
09520 //                                                                           //
09521 // Flip operations                                                           //
09522 //                                                                           //
09523 // If abc is a hull face, it is unflipable, and is locally Delaunay.  In the //
09524 // following, we assume abc is an interior face, and the other tetrahedron   //
09525 // adjoining at abc is bace.                                                 //
09526 //                                                                           //
09527 // If the convex hull CH of the set {a, b, c, d, e} only has four vertices,  //
09528 // i.e., one vertex lies inside CH, then abc is unflipable, and is locally   //
09529 // Delaunay. If CH is the vertex set itself, we have the following cases to  //
09530 // determine whether abc is flipable or not.                                 //
09531 //                                                                           //
09532 // If no four points of {a, b, c, d, e} are coplanar, a 2-to-3 flip can be   //
09533 // applied to abc if the edge de crosses the triangle abc; a 3-to-2 flip can //
09534 // be applied to abc if ab crosses cde, and abde exists, otherwise, face abc //
09535 // is unflipable, i.e., the tetrahedron abde is not present.                 //
09536 //                                                                           //
09537 // If four points of {a, b, c, d, e} are coplanar (two faces are coplanar).  //
09538 // Assume faces abd and abe are coplanar (it is impossible be abc). If a, b, //
09539 // d, e form a non-convex quadrilateral, then abc is unflipable, furthermore,//
09540 // it is locally Delaunay.  Assume they are convex quadrilateral, if abd and //
09541 // abe are hull faces, a 2-to-2 flip can be applied to abc;  if abd and abe  //
09542 // are interior faces,  assume two tetrahedra adjoining abd and abe at the   //
09543 // opposite sides are abdg and abef, respectively.  If g = f, a 4-to-4 flip  //
09544 // can be applied to abc, otherwise, abc is unflipable.                      //
09545 //                                                                           //
09546 // There are other cases which can cause abc unflipable. If abc is a subface,//
09547 // a 2-to-3 flip is forbidden;  if ab is a subsegment, flips 3-to-2, 2-to-2, //
09548 // and 4-to-4 are forbidden.                                                 //
09549 //                                                                           //
09551 
09553 //                                                                           //
09554 // categorizeface()    Determine the flip type of a given face.              //
09555 //                                                                           //
09556 // On input, 'horiz' represents the face abc we want to flip (imagine it is  //
09557 // parallel to the horizon).  Let the tet above it be abcd.                  //
09558 //                                                                           //
09559 // This routine determines the suitable type of flip operation for 'horiz'.  //
09560 //   - Returns T23 if a 2-to-3 flip is applicable. 'horiz' is same as input. //
09561 //   - Returns T32 if a 3-to-2 flip is applicable. 'horiz' returns the edge  //
09562 //     of abc which is the flipable.                                         //
09563 //   - Returns T22 if a 2-to-2 or 4-to-4 flip is applicable. 'horiz' returns //
09564 //     the edge of abc which is flipable.                                    //
09565 //   - Returns N32 indicates it is unflipable due to the absence of a tet.   //
09566 //     'horize' returns the unflipable edge.                                 //
09567 //   - Returns N40 indicates it is unflipable and is locally Delaunay.       //
09568 //   - Returns FORBIDDENFACE indicates abc is a subface.                     //
09569 //   - Returns FORBIDDENEDGE indicates the flipable edge of abc is a segment.//
09570 //     'horize' returns the flipable edge.                                   //
09571 //                                                                           //
09572 // Given a face abc, with two adjoining tetrahedra abcd and bace.  If abc is //
09573 // flipable, i.e., T23, T32, T22 or T44, its flip type can be determined by  //
09574 // doing five orientation tests: two tests for determining that d, e lie on  //
09575 // the different sides of abc, three tests for determining if the edge de    //
09576 // intersects the face abc.  However, if we use the neighbor information of  //
09577 // the mesh data structure, we can reduce the five orientation tests to at   //
09578 // most three tests, that is, the two tests for determining whether d and e  //
09579 // lie on the different sides of abc can be saved.                           //
09580 //                                                                           //
09582 
09583 enum tetgenmesh::fliptype tetgenmesh::categorizeface(triface& horiz)
09584 {
09585   triface symhoriz, casing;
09586   face checksh, checkseg;
09587   face cassh1, cassh2;
09588   point pa, pb, pc, pd, pe, pf, pg;
09589   point abdoppo, bcdoppo, cadoppo;
09590   REAL ori1, ori2, ori3;
09591   int adjtet;
09592 
09593   sym(horiz, symhoriz);
09594   if (symhoriz.tet == dummytet) {
09595     // A hull face is unflipable and locally Delaunay.
09596     return N40;
09597   }
09598   
09599   adjustedgering(horiz, CCW);
09600   findedge(&symhoriz, dest(horiz), org(horiz));
09601   pa = org(horiz);
09602   pb = dest(horiz);
09603   pc = apex(horiz);
09604   pd = oppo(horiz);
09605   pe = oppo(symhoriz);
09606 
09607   // Find the number of adjacent tetrahedra of abc, which have d, e, and one
09608   //   of corners of abc as their corners. This number can be 0, 1 and 2.
09609   abdoppo = bcdoppo = cadoppo = (point) NULL;
09610   adjtet = 0;
09611   fnext(horiz, casing); // at edge 'ab'.
09612   symself(casing);
09613   if (casing.tet != dummytet) {
09614     abdoppo = oppo(casing);
09615     if (abdoppo == pe) adjtet++;
09616   }
09617   enextfnext(horiz, casing); // at edge 'bc'.
09618   symself(casing);
09619   if (casing.tet != dummytet) {
09620     bcdoppo = oppo(casing);
09621     if (bcdoppo == pe) adjtet++;
09622   }
09623   enext2fnext(horiz, casing); // at edge 'ca'.
09624   symself(casing);
09625   if (casing.tet != dummytet) {
09626     cadoppo = oppo(casing);
09627     if (cadoppo == pe) adjtet++;
09628   }
09629   
09630   if (adjtet == 0) {
09631     // No adjacent tetrahedron. Types T23, T22 and T44 are possible. 
09632     ori1 = orient3d(pa, pb, pd, pe);
09633     if (checksubfaces && ori1 != 0.0) {
09634       // Check if abd and abe are both boundary faces?
09635       fnext(horiz, casing);
09636       tspivot(casing, cassh1);
09637       fnext(symhoriz, casing);
09638       tspivot(casing, cassh2);
09639       if ((cassh1.sh != dummysh) && (cassh2.sh != dummysh)) {
09640         // abd and abe are both boundary faces. Check if ab is a segment.
09641         findedge(&cassh1, pa, pb);
09642         sspivot(cassh1, checkseg);
09643         if (checkseg.sh == dummysh) {
09644           // ab is not a segment - abd and abe belong to the same facet.
09645           //   The four points are forced to be coplanar.
09646           ori1 = 0.0;
09647         } else {
09648           // ab is a segment - abd and abe belong to two different facets.
09649           //   In principle, a, b, c and d can form a tetrahedron (since
09650           //   ori1 != 0.0).  However, we should avoid to create a very
09651           //   flat one which may form a sequence of extremely badly-shaped
09652           //   or even wrong orientational tets. Test with a larger epsilon.
09653           if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09654         }
09655       } else {
09656         // abd and abe are not both boundary faces. Check if abd and bae
09657         //   are approximately coplanar with respect to the epsilon.
09658         if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon)) ori1 = 0.0;
09659       }
09660     }
09661     if (ori1 < 0.0) {
09662       // e lies above abd, unflipable, tet abde is not present.
09663 #ifdef SELF_CHECK
09664       if (!nonconvex) {
09665         // abd and abe should not be hull faces, check it.
09666         fnext(horiz, casing);
09667         symself(casing);
09668         assert(casing.tet != dummytet);
09669         fnext(symhoriz, casing);
09670         symself(casing);
09671         assert(casing.tet != dummytet);
09672       }
09673 #endif
09674       if (checksubfaces) {
09675         // The nonconvexbility may be casued by existing an subsegment.
09676         tsspivot(&horiz, &checkseg);
09677         if (checkseg.sh != dummysh) {
09678           return FORBIDDENEDGE;
09679         }
09680       }
09681       return N32;
09682     }
09683     ori2 = orient3d(pb, pc, pd, pe);
09684     if (checksubfaces && ori2 != 0.0) {
09685       // Check if bcd and cbe are both boundary faces.
09686       enextfnext(horiz, casing);
09687       tspivot(casing, cassh1);
09688       enext2fnext(symhoriz, casing);
09689       tspivot(casing, cassh2);
09690       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09691         // bcd and cbe are both boundary faces. Check if bc is a segment.
09692         findedge(&cassh1, pb, pc);
09693         sspivot(cassh1, checkseg);
09694         if (checkseg.sh == dummysh) {
09695           // bc is not a segment - bcd and cbe belong to the same facet.
09696           //   The four points are forced to be coplanar.
09697           ori2 = 0.0;
09698         } else {
09699           if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09700         } 
09701       } else {
09702         //  bcd and cbe are not both boundary faces. Check if bcd and cbe
09703         //   are approximately coplanar with respect to the epsilon.
09704         if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon)) ori2 = 0.0;
09705       }
09706     }
09707     if (ori2 < 0.0) {
09708       // e lies above bcd, unflipable, tet bcde is not present.
09709 #ifdef SELF_CHECK
09710       if (!nonconvex) {
09711         // bcd and cbe should not be hull faces, check it.
09712         enextfnext(horiz, casing);
09713         symself(casing);
09714         assert(casing.tet != dummytet);
09715         enext2fnext(symhoriz, casing);
09716         symself(casing);
09717         assert(casing.tet != dummytet);
09718       }
09719 #endif
09720       enextself(horiz);
09721       if (checksubfaces) {
09722         // The nonconvexbility may be casued by existing an subsegment.
09723         tsspivot(&horiz, &checkseg);
09724         if (checkseg.sh != dummysh) {
09725           return FORBIDDENEDGE;
09726         }
09727       }
09728       return N32;
09729     } 
09730     ori3 = orient3d(pc, pa, pd, pe);
09731     if (checksubfaces && ori3 != 0.0) {
09732       // Check if cad and ace are both boundary faces.
09733       enext2fnext(horiz, casing);
09734       tspivot(casing, cassh1);
09735       enextfnext(symhoriz, casing);
09736       tspivot(casing, cassh2);
09737       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09738         // cad and ace are both boundary faces. Check if ca is a segment.
09739         findedge(&cassh1, pc, pa);
09740         sspivot(cassh1, checkseg);
09741         if (checkseg.sh == dummysh) {
09742           // ca is not a segment - cad and ace belong to the same facet.
09743           //   The four points are forced to be coplanar.
09744           ori3 = 0.0;
09745         } else {
09746           // ca is a segment - cad and ace belong to two different facets.
09747           //   In principle, c, a, d and e can form a tetrahedron (since
09748           //   ori3 != 0.0). Use a larger eps to test if they're coplanar.
09749           if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon * 1e+2)) ori3 = 0.0;
09750         } 
09751       } else {
09752         // cad and ace are not both boundary faces. Check if cad and ace
09753         //   are approximately coplanar with respect to the epsilon.
09754         if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon)) ori3 = 0.0;
09755       }
09756     }
09757     if (ori3 < 0.0) {
09758       // e lies above cad, unflipable, tet cade is not present.
09759 #ifdef SELF_CHECK
09760       if (!nonconvex) {
09761         // cad and ace should not be hull faces, check it.
09762         enext2fnext(horiz, casing);
09763         symself(casing);
09764         assert(casing.tet != dummytet);
09765         enextfnext(symhoriz, casing);
09766         symself(casing);
09767         assert(casing.tet != dummytet);
09768       }
09769 #endif
09770       enext2self(horiz);
09771       if (checksubfaces) {
09772         // The nonconvexbility may be casued by existing an subsegment.
09773         tsspivot(&horiz, &checkseg);
09774         if (checkseg.sh != dummysh) {
09775           return FORBIDDENEDGE;
09776         }
09777       }
09778       return N32;
09779     }
09780     if (ori1 == 0.0) {
09781       // e is coplanar with abd.
09782       if (ori2 * ori3 == 0.0) {
09783         // only one zero is possible.
09784         // assert(!(ori2 == 0.0 && ori3 == 0.0));
09785         // Three points (d, e, and a or b) are collinear, abc is unflipable
09786         //   and locally Delaunay.
09787         return N40;
09788       }
09789     } else if (ori2 == 0.0) {
09790       // e is coplanar with bcd.
09791       if (ori1 * ori3 == 0.0) {
09792         // only one zero is possible.
09793         // assert(!(ori1 == 0.0 && ori3 == 0.0));
09794         // Three points (d, e, and b or c) are collinear, abc is unflipable
09795         //   and locally Delaunay.
09796         return N40;
09797       }
09798       // Adjust 'horiz' and 'symhoriz' be the edge bc.
09799       enextself(horiz);
09800       enext2self(symhoriz);
09801     } else if (ori3 == 0.0) {
09802       // e is coplanar with cad.
09803       if (ori1 * ori2 == 0.0) {
09804         // only one zero is possible.
09805         // assert(!(ori1 == 0.0 && ori2 == 0.0));
09806         // Three points (d, e, and c or a) are collinear, abc is unflipable
09807         //   and locally Delaunay.
09808         return N40;
09809       }
09810       // Adjust 'horiz' and 'symhoriz' be the edge ca.
09811       enext2self(horiz);
09812       enextself(symhoriz);
09813     } else {
09814       // e lies below all three faces, flipable.
09815       if (checksubfaces) {
09816         tspivot(horiz, checksh);
09817         if (checksh.sh != dummysh) {
09818           // To flip a subface is forbidden.
09819           return FORBIDDENFACE;
09820         }
09821       }
09822       return T23;
09823     }
09824     // Four points are coplanar, T22 or T44 is possible.
09825     if (checksubfaces) {
09826       tsspivot(&horiz, &checkseg);
09827       if (checkseg.sh != dummysh) {
09828         // To flip a subsegment is forbidden.
09829         return FORBIDDENEDGE;
09830       }
09831       tspivot(horiz, checksh);
09832       if (checksh.sh != dummysh) {
09833         // To flip a subface is forbidden.
09834         return FORBIDDENFACE;
09835       }
09836     }
09837     // Assume the four coplanar points are a, b, d, e, abd and abe are two
09838     //   coplanar faces. If both abd and abe are hull faces, flipable(T22).
09839     //   If they are interior faces, get the opposite tetrahedra abdf and
09840     //   abeg, if f = g, flipable (T44). Otherwise, unflipable.
09841     pf = pg = (point) NULL;
09842     fnext(horiz, casing);
09843     symself(casing);
09844     if (casing.tet != dummytet) {
09845       pf = oppo(casing);
09846     }
09847     fnext(symhoriz, casing);
09848     symself(casing);
09849     if (casing.tet != dummytet) {
09850       pg = oppo(casing);
09851     }
09852     if (pf == pg) {
09853       // Either T22 (pf == pg == NULL) or T44 (pf and pg) is possible.
09854       if (checksubfaces) {
09855         // Retreat the corner points a, b, and c.
09856         pa = org(horiz);
09857         pb = dest(horiz);
09858         pc = apex(horiz);
09859         // Be careful not to create an inverted tetrahedron. Check the case.
09860         ori1 = orient3d(pc, pd, pe, pa);
09861         if (ori1 <= 0) return N40;
09862         ori1 = orient3d(pd, pc, pe, pb);
09863         if (ori1 <= 0) return N40;
09864         if (pf != (point) NULL) {
09865           ori1 = orient3d(pd, pf, pe, pa);
09866           if (ori1 <= 0) return N40;
09867           ori1 = orient3d(pf, pd, pe, pb);
09868           if (ori1 <= 0) return N40;
09869         }
09870       }
09871       if (pf == (point) NULL) {
09872         // abd and abe are hull faces, flipable.
09873         return T22;
09874       } else {
09875         // abd and abe are interior faces, flipable.
09876 #ifdef SELF_CHECK
09877         assert(pf != (point) NULL);
09878 #endif
09879         return T44;
09880       }
09881     } else {
09882       // ab has more than four faces around it, unflipable.
09883       return N32;
09884     }
09885   } else if (adjtet == 1) {
09886     // One of its three edges is locally non-convex. Type T32 is possible.
09887     // Adjust current configuration so that edge ab is non-convex.
09888     if (bcdoppo == pe) {
09889       // Edge bc is non-convex. Adjust 'horiz' and 'symhoriz' be edge bc.
09890       enextself(horiz);
09891       enext2self(symhoriz);
09892       pa = org(horiz);
09893       pb = dest(horiz);
09894       pc = apex(horiz);
09895     } else if (cadoppo == pe) {
09896       // Edge ca is non-convex. Adjust 'horiz' and 'symhoriz' be edge ca.
09897       enext2self(horiz);
09898       enextself(symhoriz);
09899       pa = org(horiz);
09900       pb = dest(horiz);
09901       pc = apex(horiz);
09902     } else {
09903       // Edge ab is non-convex.
09904 #ifdef SELF_CHECK
09905       assert(abdoppo == pe);
09906 #endif
09907     } // Now ab is the non-convex edge.
09908     // In order to be flipable, ab should cross face cde. Check it.
09909     ori1 = orient3d(pc, pd, pe, pa);
09910     if (checksubfaces && ori1 != 0.0) {
09911       // Check if cad and ace are both boundary faces.
09912       enext2fnext(horiz, casing);
09913       tspivot(casing, cassh1);
09914       enextfnext(symhoriz, casing);
09915       tspivot(casing, cassh2);
09916       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09917         // cad and ace are both boundary faces. Check if ca is a segment.
09918         findedge(&cassh1, pc, pa);
09919         sspivot(cassh1, checkseg);
09920         if (checkseg.sh == dummysh) {
09921           // ca is not a segment. cad and ace belong to the same facet.
09922           //   The four points are forced to be coplanar.
09923           ori1 = 0.0;
09924         } else {
09925           // ca is a segment. cad and ace belong to different facets.
09926           //   In principle, c, d, e, and a can form a tetrahedron (since
09927           //   ori1 != 0.0).  However, we should avoid to create a very
09928           //   flat tet. Use a larger epsilon to test if they're coplanar.
09929           if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09930         }
09931       } else {
09932         // Check if c, d, e, and a are approximately coplanar.
09933         if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon)) ori1 = 0.0;
09934       }
09935     }
09936     if (ori1 <= 0.0) {
09937       // a lies above or is coplanar cde, abc is locally Delaunay.
09938       return N40;
09939     }
09940     ori2 = orient3d(pd, pc, pe, pb);
09941     if (checksubfaces && ori2 != 0.0) {
09942       // Check if bcd and cbe are both boundary faces.
09943       enextfnext(horiz, casing);
09944       tspivot(casing, cassh1);
09945       enext2fnext(symhoriz, casing);
09946       tspivot(casing, cassh2);
09947       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09948         // bcd and cbe are both boundary faces. Check if bc is a segment.
09949         findedge(&cassh1, pb, pc);
09950         sspivot(cassh1, checkseg);
09951         if (checkseg.sh == dummysh) {
09952           // bc is not a segment. bcd and cbe belong to the same facet.
09953           //   The four points are forced to be coplanar.
09954           ori2 = 0.0;
09955         } else {
09956           // bc is a segment. bcd and cbe belong to different facets.
09957           //   In principle, d, c, e, and b can form a tetrahedron (since
09958           //   ori2 != 0.0).  However, we should avoid to create a very
09959           //   flat tet. Use a larger epsilon to test if they're coplanar.
09960           if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09961         }
09962       } else {
09963         // Check if d, c, e, and b are approximately coplanar.
09964         if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon)) ori2 = 0.0;
09965       }
09966     }
09967     if (ori2 <= 0.0) {
09968       // b lies above dce, unflipable, and abc is locally Delaunay.
09969       return N40;
09970     }
09971     // Edge ab crosses face cde properly.
09972     if (checksubfaces) {
09973       // If abc is subface, then ab must be a subsegment (because abde is
09974       //   a tetrahedron and ab crosses cde properly). 
09975       tsspivot(&horiz, &checkseg);
09976       if (checkseg.sh != dummysh) {
09977         // To flip a subsegment is forbidden.
09978         return FORBIDDENEDGE;
09979       }
09980       // Both abd and bae should not be subfaces (because they're not
09981       //   coplanar and ab is not a subsegment). However, they may be
09982       //   subfaces and belong to a facet (created during facet recovery),
09983       //   that is, abde is an invalid tetrahedron. Find this case out.
09984       fnext(horiz, casing);
09985       tspivot(casing, cassh1);
09986       fnext(symhoriz, casing);
09987       tspivot(casing, cassh2); 
09988       if (cassh1.sh != dummysh || cassh2.sh != dummysh) {
09989         if (!b->quiet) {
09990           // Unfortunately, they're subfaces. Corrections need be done here.
09991           printf("Warning:  A tetrahedron spans two subfaces of a facet.\n");
09992         }
09993         // Temporarily, let it be there.
09994         return N32;
09995       }
09996     }
09997     return T32;
09998   } else {
09999     // The convex hull of {a, b, c, d, e} has only four vertices, abc is
10000     //   unflipable, furthermore, it is locally Delaunay.
10001     return N40;
10002   }
10003 }
10004 
10006 //                                                                           //
10007 // enqueueflipface(), enqueueflipedge()    Queue a face (or an edge).        //
10008 //                                                                           //
10009 // The face (or edge) may be non-locally Delaunay. It is queued for process- //
10010 // ing in flip() (or flipsub()). The vertices of the face (edge) are stored  //
10011 // seperatly to ensure the face (or edge) is still the same one when we save //
10012 // it since other flips will cause this face (or edge) be changed or dead.   //
10013 //                                                                           //
10015 
10016 void tetgenmesh::enqueueflipface(triface& checkface, queue* flipqueue)
10017 {
10018   badface *queface;
10019   triface symface;
10020 
10021   sym(checkface, symface);
10022   if (symface.tet != dummytet) {
10023     queface = (badface *) flipqueue->push((void *) NULL);
10024     queface->tt = checkface;
10025     queface->foppo = oppo(symface);
10026   }
10027 }
10028 
10029 void tetgenmesh::enqueueflipedge(face& checkedge, queue* flipqueue)
10030 {
10031   badface *queface;
10032 
10033   queface = (badface *) flipqueue->push((void *) NULL);
10034   queface->ss = checkedge;
10035   queface->forg = sorg(checkedge);
10036   queface->fdest = sdest(checkedge);
10037 }
10038 
10040 //                                                                           //
10041 // flip23()    Perform a 2-to-3 flip.                                        //
10042 //                                                                           //
10043 // On input, 'flipface' represents the face will be flipped.  Let it is abc, //
10044 // the two tetrahedra sharing abc are abcd, bace. abc is not a subface.      //
10045 //                                                                           //
10046 // A 2-to-3 flip is to change two tetrahedra abcd, bace to three tetrahedra  //
10047 // edab, edbc, and edca.  As a result, face abc has been removed and three   //
10048 // new faces eda, edb and edc have been created.                             //
10049 //                                                                           //
10050 // On completion, 'flipface' returns edab.  If 'flipqueue' is not NULL, all  //
10051 // possibly non-Delaunay faces are added into it.                            //
10052 //                                                                           //
10054 
10055 void tetgenmesh::flip23(triface* flipface, queue* flipqueue)
10056 {
10057   triface abcd, bace;                                  // Old configuration.
10058   triface oldabd, oldbcd, oldcad;
10059   triface abdcasing, bcdcasing, cadcasing;
10060   triface oldbae, oldcbe, oldace;
10061   triface baecasing, cbecasing, acecasing;
10062   triface worktet;
10063   face abdsh, bcdsh, cadsh;                   // The six subfaces on the CH.
10064   face baesh, cbesh, acesh;
10065   face abseg, bcseg, caseg;                      // The nine segs on the CH.
10066   face adseg, bdseg, cdseg;
10067   face aeseg, beseg, ceseg;
10068   triface edab, edbc, edca;                            // New configuration.
10069   point pa, pb, pc, pd, pe;
10070   REAL attrib, volume;
10071   int i;
10072 
10073   abcd = *flipface;
10074   adjustedgering(abcd, CCW); // abcd represents edge ab.
10075   pa = org(abcd);
10076   pb = dest(abcd);
10077   pc = apex(abcd);
10078   pd = oppo(abcd);
10079   // sym(abcd, bace);
10080   // findedge(&bace, dest(abcd), org(abcd)); // bace represents edge ba.
10081   sym(abcd, bace);
10082   bace.ver = 0; // CCW.
10083   for (i = 0; (i < 3) && (org(bace) != pb); i++) {
10084     enextself(bace);
10085   }
10086   pe = oppo(bace);
10087 
10088   if (b->verbose > 2) {
10089     printf("    Do T23 on face (%d, %d, %d) %d, %d.\n", pointmark(pa),
10090            pointmark(pb), pointmark(pc), pointmark(pd), pointmark(pe));
10091   }
10092   flip23s++;
10093 
10094   // Storing the old configuration outside the convex hull.
10095   fnext(abcd, oldabd);
10096   enextfnext(abcd, oldbcd);
10097   enext2fnext(abcd, oldcad);
10098   fnext(bace, oldbae);
10099   enext2fnext(bace, oldcbe);
10100   enextfnext(bace, oldace);
10101   sym(oldabd, abdcasing);
10102   sym(oldbcd, bcdcasing);
10103   sym(oldcad, cadcasing);
10104   sym(oldbae, baecasing);
10105   sym(oldcbe, cbecasing);
10106   sym(oldace, acecasing);
10107   if (checksubfaces) {
10108     tspivot(oldabd, abdsh);
10109     tspivot(oldbcd, bcdsh);
10110     tspivot(oldcad, cadsh);
10111     tspivot(oldbae, baesh);
10112     tspivot(oldcbe, cbesh);
10113     tspivot(oldace, acesh);
10114   } else if (checksubsegs) {
10115     tsspivot1(abcd, abseg);
10116     enext(abcd, worktet);
10117     tsspivot1(worktet, bcseg);
10118     enext2(abcd, worktet);
10119     tsspivot1(worktet, caseg);
10120     enext2(oldabd, worktet);
10121     tsspivot1(worktet, adseg);
10122     enext2(oldbcd, worktet);
10123     tsspivot1(worktet, bdseg);
10124     enext2(oldcad, worktet);
10125     tsspivot1(worktet, cdseg);
10126     enext(oldbae, worktet);
10127     tsspivot1(worktet, aeseg);
10128     enext(oldcbe, worktet);
10129     tsspivot1(worktet, beseg);
10130     enext(oldace, worktet);
10131     tsspivot1(worktet, ceseg);
10132   }
10133 
10134   // Creating the new configuration inside the convex hull.
10135   edab.tet = abcd.tet; // Update abcd to be edab.
10136   setorg (edab, pe);
10137   setdest(edab, pd);
10138   setapex(edab, pa);
10139   setoppo(edab, pb);
10140   edbc.tet = bace.tet; // Update bace to be edbc.
10141   setorg (edbc, pe);
10142   setdest(edbc, pd);
10143   setapex(edbc, pb);
10144   setoppo(edbc, pc);
10145   maketetrahedron(&edca); // Create edca.
10146   setorg (edca, pe);
10147   setdest(edca, pd);
10148   setapex(edca, pc);
10149   setoppo(edca, pa);
10150   // Set the element attributes of the new tetrahedron 'edca'.
10151   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
10152     attrib = elemattribute(abcd.tet, i);
10153     setelemattribute(edca.tet, i, attrib);
10154   }
10155   // Set the volume constraint of the new tetrahedron 'edca' if the -ra
10156   //   switches are not used together. In -ra case, the various volume
10157   //   constraints can be spreaded very far.
10158   if (b->varvolume && !b->refine) {
10159     volume = volumebound(abcd.tet);
10160     setvolumebound(edca.tet, volume);
10161   }
10162 
10163   // Clear old bonds in edab(was abcd) and edbc(was bace).
10164   for (i = 0; i < 4; i ++) {
10165     edab.tet[i] = (tetrahedron) dummytet;
10166   }
10167   for (i = 0; i < 4; i ++) {
10168     edbc.tet[i] = (tetrahedron) dummytet;
10169   }
10170   // Bond the faces inside the convex hull.
10171   edab.loc = 0;
10172   edca.loc = 1;
10173   bond(edab, edca);
10174   edab.loc = 1;
10175   edbc.loc = 0;
10176   bond(edab, edbc);
10177   edbc.loc = 1;
10178   edca.loc = 0;
10179   bond(edbc, edca);
10180   // Bond the faces on the convex hull.
10181   edab.loc = 2;
10182   bond(edab, abdcasing);
10183   edab.loc = 3;
10184   bond(edab, baecasing);
10185   edbc.loc = 2;
10186   bond(edbc, bcdcasing);
10187   edbc.loc = 3;
10188   bond(edbc, cbecasing);
10189   edca.loc = 2;
10190   bond(edca, cadcasing);
10191   edca.loc = 3;
10192   bond(edca, acecasing);
10193   // There may exist subfaces that need to be bonded to new configuarton.
10194   if (checksubfaces) {
10195     // Clear old flags in edab(was abcd) and edbc(was bace).
10196     for (i = 0; i < 4; i ++) {
10197       edab.loc = i;
10198       tsdissolve(edab);
10199       edbc.loc = i;
10200       tsdissolve(edbc);
10201     }
10202     if (abdsh.sh != dummysh) {
10203       edab.loc = 2; 
10204       tsbond(edab, abdsh);
10205     }
10206     if (baesh.sh != dummysh) {
10207       edab.loc = 3; 
10208       tsbond(edab, baesh);
10209     }
10210     if (bcdsh.sh != dummysh) {
10211       edbc.loc = 2; 
10212       tsbond(edbc, bcdsh);
10213     }
10214     if (cbesh.sh != dummysh) {
10215       edbc.loc = 3; 
10216       tsbond(edbc, cbesh);
10217     }
10218     if (cadsh.sh != dummysh) {
10219       edca.loc = 2; 
10220       tsbond(edca, cadsh);
10221     }
10222     if (acesh.sh != dummysh) {
10223       edca.loc = 3; 
10224       tsbond(edca, acesh);
10225     }
10226   } else if (checksubsegs) {
10227     for (i = 0; i < 6; i++) {
10228       edab.tet[8 + i] = (tetrahedron) dummysh;
10229     }
10230     for (i = 0; i < 6; i++) {
10231       edbc.tet[8 + i] = (tetrahedron) dummysh;
10232     }
10233     edab.loc = edab.ver = 0;
10234     edbc.loc = edab.ver = 0;
10235     edca.loc = edab.ver = 0;
10236     // Operate in tet edab (5 edges).
10237     enext(edab, worktet);
10238     tssbond1(worktet, adseg);
10239     enext2(edab, worktet);
10240     tssbond1(worktet, aeseg);
10241     fnext(edab, worktet);
10242     enextself(worktet);
10243     tssbond1(worktet, bdseg);
10244     enextself(worktet);
10245     tssbond1(worktet, beseg);
10246     enextfnext(edab, worktet);
10247     enextself(worktet);
10248     tssbond1(worktet, abseg);
10249     // Operate in tet edbc (5 edges)
10250     enext(edbc, worktet);
10251     tssbond1(worktet, bdseg);
10252     enext2(edbc, worktet);
10253     tssbond1(worktet, beseg);
10254     fnext(edbc, worktet);
10255     enextself(worktet);
10256     tssbond1(worktet, cdseg);
10257     enextself(worktet);
10258     tssbond1(worktet, ceseg);
10259     enextfnext(edbc, worktet);
10260     enextself(worktet);
10261     tssbond1(worktet, bcseg);
10262     // Operate in tet edca (5 edges)
10263     enext(edca, worktet);
10264     tssbond1(worktet, cdseg);
10265     enext2(edca, worktet);
10266     tssbond1(worktet, ceseg);
10267     fnext(edca, worktet);
10268     enextself(worktet);
10269     tssbond1(worktet, adseg);
10270     enextself(worktet);
10271     tssbond1(worktet, aeseg);
10272     enextfnext(edca, worktet);
10273     enextself(worktet);
10274     tssbond1(worktet, caseg);
10275   }
10276 
10277   edab.loc = 0;
10278   edbc.loc = 0;
10279   edca.loc = 0;
10280   if (b->verbose > 3) {
10281     printf("    Updating edab ");
10282     printtet(&edab);
10283     printf("    Updating edbc ");
10284     printtet(&edbc);
10285     printf("    Creating edca ");
10286     printtet(&edca);
10287   }
10288 
10289   if (flipqueue != (queue *) NULL) {
10290     enextfnext(edab, abdcasing);
10291     enqueueflipface(abdcasing, flipqueue);
10292     enext2fnext(edab, baecasing);
10293     enqueueflipface(baecasing, flipqueue);
10294     enextfnext(edbc, bcdcasing);
10295     enqueueflipface(bcdcasing, flipqueue);
10296     enext2fnext(edbc, cbecasing);
10297     enqueueflipface(cbecasing, flipqueue);
10298     enextfnext(edca, cadcasing);
10299     enqueueflipface(cadcasing, flipqueue);
10300     enext2fnext(edca, acecasing);
10301     enqueueflipface(acecasing, flipqueue);  
10302   }
10303 
10304   // Save a live handle in 'recenttet'.
10305   recenttet = edbc;
10306   // Set the return handle be edab.
10307   *flipface = edab;
10308 }
10309 
10311 //                                                                           //
10312 // flip32()    Perform a 3-to-2 flip.                                        //
10313 //                                                                           //
10314 // On input, 'flipface' represents the face will be flipped.  Let it is eda, //
10315 // where edge ed is locally non-convex. Three tetrahedra sharing ed are edab,//
10316 // edbc, and edca.  ed is not a subsegment.                                  //
10317 //                                                                           //
10318 // A 3-to-2 flip is to change the three tetrahedra edab, edbc, and edca into //
10319 // another two tetrahedra abcd and bace.  As a result, the edge ed has been  //
10320 // removed and the face abc has been created.                                //
10321 //                                                                           //
10322 // On completion, 'flipface' returns abcd.  If 'flipqueue' is not NULL, all  //
10323 // possibly non-Delaunay faces are added into it.                            //
10324 //                                                                           //
10326 
10327 void tetgenmesh::flip32(triface* flipface, queue* flipqueue)
10328 {
10329   triface edab, edbc, edca;                            // Old configuration.
10330   triface oldabd, oldbcd, oldcad;
10331   triface abdcasing, bcdcasing, cadcasing;
10332   triface oldbae, oldcbe, oldace;
10333   triface baecasing, cbecasing, acecasing;
10334   triface worktet;
10335   face abdsh, bcdsh, cadsh;
10336   face baesh, cbesh, acesh;
10337   face abseg, bcseg, caseg;                      // The nine segs on the CH.
10338   face adseg, bdseg, cdseg;
10339   face aeseg, beseg, ceseg;
10340   triface abcd, bace;                                  // New configuration.
10341   point pa, pb, pc, pd, pe;
10342   int i;
10343 
10344   edab = *flipface;
10345   adjustedgering(edab, CCW);
10346   pa = apex(edab);
10347   pb = oppo(edab);
10348   pd = dest(edab);
10349   pe = org(edab);
10350   fnext(edab, edbc);
10351   symself(edbc);
10352   edbc.ver = 0;
10353   for (i = 0; (i < 3) && (org(edbc) != pe); i++) {
10354     enextself(edbc);
10355   }
10356   pc = oppo(edbc);
10357   fnext(edbc, edca);
10358   symself(edca);
10359   edca.ver = 0;
10360   for (i = 0; (i < 3) && (org(edca) != pe); i++) {
10361     enextself(edca);
10362   }
10363 
10364   if (b->verbose > 2) {
10365     printf("    Do T32 on edge (%d, %d) %d, %d, %d.\n", pointmark(pe),
10366            pointmark(pd), pointmark(pa), pointmark(pb), pointmark(pc));
10367   }
10368   flip32s++;
10369 
10370   // Storing the old configuration outside the convex hull.
10371   enextfnext(edab, oldabd);
10372   enext2fnext(edab, oldbae);
10373   enextfnext(edbc, oldbcd);
10374   enext2fnext(edbc, oldcbe);
10375   enextfnext(edca, oldcad);
10376   enext2fnext(edca, oldace);
10377   sym(oldabd, abdcasing);
10378   sym(oldbcd, bcdcasing);
10379   sym(oldcad, cadcasing);
10380   sym(oldbae, baecasing);
10381   sym(oldcbe, cbecasing);
10382   sym(oldace, acecasing);
10383   if (checksubfaces) {
10384     tspivot(oldabd, abdsh);
10385     tspivot(oldbcd, bcdsh);
10386     tspivot(oldcad, cadsh);
10387     tspivot(oldbae, baesh);
10388     tspivot(oldcbe, cbesh);
10389     tspivot(oldace, acesh);
10390   } else if (checksubsegs) {
10391     enext(edab, worktet);
10392     tsspivot1(worktet, adseg);
10393     enext2(edab, worktet);
10394     tsspivot1(worktet, aeseg);
10395     enext(edbc, worktet);
10396     tsspivot1(worktet, bdseg);
10397     enext2(edbc, worktet);
10398     tsspivot1(worktet, beseg);
10399     enext(edca, worktet);
10400     tsspivot1(worktet, cdseg);
10401     enext2(edca, worktet);
10402     tsspivot1(worktet, ceseg);
10403     enextfnext(edab, worktet);
10404     enextself(worktet);
10405     tsspivot1(worktet, abseg);
10406     enextfnext(edbc, worktet);
10407     enextself(worktet);
10408     tsspivot1(worktet, bcseg);
10409     enextfnext(edca, worktet);
10410     enextself(worktet);
10411     tsspivot1(worktet, caseg);
10412   }
10413 
10414   // Creating the new configuration inside the convex hull.
10415   abcd.tet = edab.tet; // Update edab to be abcd.
10416   setorg (abcd, pa);
10417   setdest(abcd, pb);
10418   setapex(abcd, pc);
10419   setoppo(abcd, pd);
10420   bace.tet = edbc.tet; // Update edbc to be bace.
10421   setorg (bace, pb);
10422   setdest(bace, pa);
10423   setapex(bace, pc);
10424   setoppo(bace, pe);
10425   // Dealloc a redundant tetrahedron (edca).
10426   tetrahedrondealloc(edca.tet); 
10427 
10428   // Clear the old bonds in abcd (was edab) and bace (was edbc).
10429   for (i = 0; i < 4; i ++) {
10430     abcd.tet[i] = (tetrahedron) dummytet;
10431   }
10432   for (i = 0; i < 4; i ++) {
10433     bace.tet[i] = (tetrahedron) dummytet;
10434   }
10435   // Bond the inside face of the convex hull.
10436   abcd.loc = 0;
10437   bace.loc = 0;
10438   bond(abcd, bace);
10439   // Bond the outside faces of the convex hull.
10440   abcd.loc = 1;
10441   bond(abcd, abdcasing);
10442   abcd.loc = 2;
10443   bond(abcd, bcdcasing);
10444   abcd.loc = 3;
10445   bond(abcd, cadcasing);
10446   bace.loc = 1;
10447   bond(bace, baecasing);
10448   bace.loc = 3;
10449   bond(bace, cbecasing);
10450   bace.loc = 2;
10451   bond(bace, acecasing);
10452   if (checksubfaces) {
10453     // Clear old bonds in abcd(was edab) and bace(was edbc).
10454     for (i = 0; i < 4; i ++) {
10455       abcd.tet[8 + i] = (tetrahedron) dummysh;
10456     }
10457     for (i = 0; i < 4; i ++) {
10458       bace.tet[8 + i] = (tetrahedron) dummysh;
10459     }
10460     if (abdsh.sh != dummysh) {
10461       abcd.loc = 1;
10462       tsbond(abcd, abdsh);
10463     }
10464     if (bcdsh.sh != dummysh) {
10465       abcd.loc = 2;
10466       tsbond(abcd, bcdsh);
10467     }
10468     if (cadsh.sh != dummysh) {
10469       abcd.loc = 3;
10470       tsbond(abcd, cadsh);
10471     }
10472     if (baesh.sh != dummysh) {
10473       bace.loc = 1;
10474       tsbond(bace, baesh);
10475     }
10476     if (cbesh.sh != dummysh) {
10477       bace.loc = 3;
10478       tsbond(bace, cbesh);
10479     }
10480     if (acesh.sh != dummysh) {
10481       bace.loc = 2;
10482       tsbond(bace, acesh);
10483     }
10484   } else if (checksubsegs) {
10485     for (i = 0; i < 6; i++) {
10486       abcd.tet[8 + i] = (tetrahedron) dummysh;
10487     }
10488     for (i = 0; i < 6; i++) {
10489       bace.tet[8 + i] = (tetrahedron) dummysh;
10490     }
10491     abcd.loc = abcd.ver = 0;
10492     bace.loc = bace.ver = 0;
10493     tssbond1(abcd, abseg);     // 1
10494     enext(abcd, worktet);
10495     tssbond1(worktet, bcseg);  // 2
10496     enext2(abcd, worktet);
10497     tssbond1(worktet, caseg);  // 3
10498     fnext(abcd, worktet);
10499     enext2self(worktet);
10500     tssbond1(worktet, adseg);  // 4
10501     enextfnext(abcd, worktet);
10502     enext2self(worktet);
10503     tssbond1(worktet, bdseg);  // 5
10504     enext2fnext(abcd, worktet);
10505     enext2self(worktet);
10506     tssbond1(worktet, cdseg);  // 6
10507     tssbond1(bace, abseg);
10508     enext2(bace, worktet);
10509     tssbond1(worktet, bcseg);
10510     enext(bace, worktet);
10511     tssbond1(worktet, caseg);
10512     fnext(bace, worktet);
10513     enextself(worktet);
10514     tssbond1(worktet, aeseg);  // 7
10515     enext2fnext(bace, worktet);
10516     enextself(worktet);
10517     tssbond1(worktet, beseg);  // 8
10518     enextfnext(bace, worktet);
10519     enextself(worktet);
10520     tssbond1(worktet, ceseg);  // 9
10521   }
10522 
10523   abcd.loc = 0;
10524   bace.loc = 0;
10525   if (b->verbose > 3) {
10526     printf("    Updating abcd ");
10527     printtet(&abcd);
10528     printf("    Updating bace ");
10529     printtet(&bace);
10530     printf("    Deleting edca ");
10531     // printtet(&edca);
10532   }
10533 
10534   if (flipqueue != (queue *) NULL) { 
10535     fnext(abcd, abdcasing);
10536     enqueueflipface(abdcasing, flipqueue);
10537     fnext(bace, baecasing);
10538     enqueueflipface(baecasing, flipqueue);
10539     enextfnext(abcd, bcdcasing);
10540     enqueueflipface(bcdcasing, flipqueue);
10541     enextfnext(bace, cbecasing);
10542     enqueueflipface(cbecasing, flipqueue);
10543     enext2fnext(abcd, cadcasing);
10544     enqueueflipface(cadcasing, flipqueue);
10545     enext2fnext(bace, acecasing);
10546     enqueueflipface(acecasing, flipqueue);  
10547   }
10548 
10549   // Save a live handle in 'recenttet'.
10550   recenttet = abcd;
10551   // Set the return handle be abcd.
10552   *flipface = abcd;
10553 }
10554 
10556 //                                                                           //
10557 // flip22()    Perform a 2-to-2 (or 4-to-4) flip.                            //
10558 //                                                                           //
10559 // On input, 'flipface' represents the face will be flipped.  Let it is abe, //
10560 // ab is the flipable edge, the two tetrahedra sharing abe are abce and bade,//
10561 // hence a, b, c and d are coplanar. If abc, bad are interior faces, the two //
10562 // tetrahedra opposite to e are bacf and abdf.  ab is not a subsegment.      //
10563 //                                                                           //
10564 // A 2-to-2 flip is to change two tetrahedra abce and bade into another two  //
10565 // tetrahedra dcae and cdbe. If bacf and abdf exist, they're changed to cdaf //
10566 // and dcbf, thus a 4-to-4 flip.  As a result, two or four tetrahedra have   //
10567 // rotated counterclockwise (using right-hand rule with thumb points to e):  //
10568 // abce->dcae, bade->cdbe, and bacf->cdaf, abdf->dcbf.                       //
10569 //                                                                           //
10570 // If abc and bad are subfaces, a 2-to-2 flip is performed simultaneously by //
10571 // calling routine flip22sub(), hence abc->dca, bad->cdb.  The edge rings of //
10572 // the flipped subfaces dca and cdb have the same orientation as abc and bad.//
10573 // Hence, they have the same orientation as other subfaces of the facet with //
10574 // respect to the lift point of this facet.                                  //
10575 //                                                                           //
10576 // On completion, 'flipface' holds edge dc of tetrahedron dcae. 'flipqueue'  //
10577 // contains all possibly non-Delaunay faces if it is not NULL.               //
10578 //                                                                           //
10580 
10581 void tetgenmesh::flip22(triface* flipface, queue* flipqueue)
10582 {
10583   triface abce, bade;
10584   triface oldbce, oldcae, oldade, olddbe;
10585   triface bcecasing, caecasing, adecasing, dbecasing;
10586   face bcesh, caesh, adesh, dbesh;
10587   triface bacf, abdf;
10588   triface oldacf, oldcbf, oldbdf, olddaf;
10589   triface acfcasing, cbfcasing, bdfcasing, dafcasing;
10590   triface worktet;
10591   face acfsh, cbfsh, bdfsh, dafsh;
10592   face abc, bad;
10593   face adseg, dbseg, bcseg, caseg;  // Coplanar segs.
10594   face aeseg, deseg, beseg, ceseg;  // Above segs.
10595   face afseg, dfseg, bfseg, cfseg;  // Below segs.
10596   point pa, pb, pc, pd, pe, pf;
10597   int mirrorflag, i;
10598 
10599   adjustedgering(*flipface, CCW); // 'flipface' is bae.
10600   fnext(*flipface, abce);
10601   esymself(abce);
10602   adjustedgering(*flipface, CW); // 'flipface' is abe.
10603   fnext(*flipface, bade);
10604 #ifdef SELF_CHECK
10605   assert(bade.tet != dummytet);
10606 #endif
10607   esymself(bade);
10608   pa = org(abce);
10609   pb = dest(abce);
10610   pc = apex(abce);
10611   pd = apex(bade);
10612   pe = oppo(bade);
10613 #ifdef SELF_CHECK
10614   assert(oppo(abce) == pe);
10615 #endif
10616   sym(abce, bacf);
10617   mirrorflag = bacf.tet != dummytet;
10618   if (mirrorflag) {
10619     // findedge(&bacf, pb, pa);
10620     bacf.ver = 0;
10621     for (i = 0; (i < 3) && (org(bacf) != pb); i++) {
10622       enextself(bacf);
10623     }
10624     sym(bade, abdf);
10625 #ifdef SELF_CHECK
10626     assert(abdf.tet != dummytet);
10627 #endif
10628     // findedge(&abdf, pa, pb);
10629     abdf.ver = 0;
10630     for (i = 0; (i < 3) && (org(abdf) != pa); i++) {
10631       enextself(abdf);
10632     }
10633     pf = oppo(bacf);
10634 #ifdef SELF_CHECK
10635     assert(oppo(abdf) == pf);
10636 #endif
10637   } 
10638 
10639   if (b->verbose > 2) {
10640     printf("    Do %s on edge (%d, %d).\n", mirrorflag ? "T44" : "T22",
10641            pointmark(pa), pointmark(pb));
10642   }
10643   mirrorflag ? flip44s++ : flip22s++;
10644 
10645   // Save the old configuration at the convex hull.
10646   enextfnext(abce, oldbce);
10647   enext2fnext(abce, oldcae);
10648   enextfnext(bade, oldade);
10649   enext2fnext(bade, olddbe);
10650   sym(oldbce, bcecasing);
10651   sym(oldcae, caecasing);
10652   sym(oldade, adecasing);
10653   sym(olddbe, dbecasing);
10654   if (checksubfaces) {
10655     tspivot(oldbce, bcesh);
10656     tspivot(oldcae, caesh);
10657     tspivot(oldade, adesh);
10658     tspivot(olddbe, dbesh);
10659     tspivot(abce, abc);
10660     tspivot(bade, bad);
10661   } else if (checksubsegs) {
10662     // Coplanar segs: a->d->b->c.
10663     enext(bade, worktet); 
10664     tsspivot1(worktet, adseg);
10665     enext2(bade, worktet);
10666     tsspivot1(worktet, dbseg);
10667     enext(abce, worktet);
10668     tsspivot1(worktet, bcseg);
10669     enext2(abce, worktet);
10670     tsspivot1(worktet, caseg);
10671     // Above segs: a->e, d->e, b->e, c->e.
10672     fnext(bade, worktet);
10673     enextself(worktet);
10674     tsspivot1(worktet, aeseg);
10675     enextfnext(bade, worktet);
10676     enextself(worktet);
10677     tsspivot1(worktet, deseg);
10678     enext2fnext(bade, worktet);
10679     enextself(worktet);
10680     tsspivot1(worktet, beseg);
10681     enextfnext(abce, worktet);
10682     enextself(worktet);
10683     tsspivot1(worktet, ceseg);
10684   }
10685   if (mirrorflag) {
10686     enextfnext(bacf, oldacf);
10687     enext2fnext(bacf, oldcbf);
10688     enextfnext(abdf, oldbdf);
10689     enext2fnext(abdf, olddaf);
10690     sym(oldacf, acfcasing);
10691     sym(oldcbf, cbfcasing);
10692     sym(oldbdf, bdfcasing);
10693     sym(olddaf, dafcasing);
10694     if (checksubfaces) {
10695       tspivot(oldacf, acfsh);
10696       tspivot(oldcbf, cbfsh);
10697       tspivot(oldbdf, bdfsh);
10698       tspivot(olddaf, dafsh);
10699     } else if (checksubsegs) {
10700       // Below segs: a->f, d->f, b->f, c->f.
10701       fnext(abdf, worktet);
10702       enext2self(worktet);
10703       tsspivot1(worktet, afseg);
10704       enext2fnext(abdf, worktet);
10705       enext2self(worktet);
10706       tsspivot1(worktet, dfseg);
10707       enextfnext(abdf, worktet);
10708       enext2self(worktet);
10709       tsspivot1(worktet, bfseg);
10710       enextfnext(bacf, worktet);
10711       enextself(worktet);
10712       tsspivot1(worktet, cfseg);
10713     }
10714   }
10715 
10716   // Rotate abce, bade one-quarter turn counterclockwise.
10717   bond(oldbce, caecasing);
10718   bond(oldcae, adecasing);
10719   bond(oldade, dbecasing);
10720   bond(olddbe, bcecasing);
10721   if (checksubfaces) {
10722     // Check for subfaces and rebond them to the rotated tets.
10723     if (caesh.sh == dummysh) {
10724       tsdissolve(oldbce);
10725     } else {
10726       tsbond(oldbce, caesh);
10727     }
10728     if (adesh.sh == dummysh) {
10729       tsdissolve(oldcae);
10730     } else {
10731       tsbond(oldcae, adesh);
10732     }
10733     if (dbesh.sh == dummysh) {
10734       tsdissolve(oldade);
10735     } else {
10736       tsbond(oldade, dbesh);
10737     }
10738     if (bcesh.sh == dummysh) {
10739       tsdissolve(olddbe);
10740     } else {
10741       tsbond(olddbe, bcesh);
10742     }
10743   } else if (checksubsegs) {
10744     // 5 edges in abce are changed.
10745     enext(abce, worktet);  // fit b->c into c->a.
10746     if (caseg.sh == dummysh) {
10747       tssdissolve1(worktet);
10748     } else {
10749       tssbond1(worktet, caseg);
10750     }
10751     enext2(abce, worktet); // fit c->a into a->d.
10752     if (adseg.sh == dummysh) {
10753       tssdissolve1(worktet);
10754     } else {
10755       tssbond1(worktet, adseg);
10756     }
10757     fnext(abce, worktet); // fit b->e into c->e.
10758     enextself(worktet);
10759     if (ceseg.sh == dummysh) {
10760       tssdissolve1(worktet);
10761     } else {
10762       tssbond1(worktet, ceseg);
10763     }
10764     enextfnext(abce, worktet); // fit c->e into a->e.
10765     enextself(worktet);
10766     if (aeseg.sh == dummysh) {
10767       tssdissolve1(worktet);
10768     } else {
10769       tssbond1(worktet, aeseg);
10770     }
10771     enext2fnext(abce, worktet); // fit a->e into d->e.
10772     enextself(worktet);
10773     if (deseg.sh == dummysh) {
10774       tssdissolve1(worktet);
10775     } else {
10776       tssbond1(worktet, deseg);
10777     }
10778     // 5 edges in bade are changed.
10779     enext(bade, worktet); // fit a->d into d->b.
10780     if (dbseg.sh == dummysh) {
10781       tssdissolve1(worktet);
10782     } else {
10783       tssbond1(worktet, dbseg);
10784     }
10785     enext2(bade, worktet); // fit d->b into b->c.
10786     if (bcseg.sh == dummysh) {
10787       tssdissolve1(worktet);
10788     } else {
10789       tssbond1(worktet, bcseg);
10790     }
10791     fnext(bade, worktet); // fit a->e into d->e.
10792     enextself(worktet);
10793     if (deseg.sh == dummysh) {
10794       tssdissolve1(worktet);
10795     } else {
10796       tssbond1(worktet, deseg);
10797     }
10798     enextfnext(bade, worktet); // fit d->e into b->e.
10799     enextself(worktet);
10800     if (beseg.sh == dummysh) {
10801       tssdissolve1(worktet);
10802     } else {
10803       tssbond1(worktet, beseg);
10804     }
10805     enext2fnext(bade, worktet); // fit b->e into c->e.
10806     enextself(worktet);
10807     if (ceseg.sh == dummysh) {
10808       tssdissolve1(worktet);
10809     } else {
10810       tssbond1(worktet, ceseg);
10811     }
10812   }
10813   if (mirrorflag) {
10814     // Rotate bacf, abdf one-quarter turn counterclockwise.
10815     bond(oldcbf, acfcasing);
10816     bond(oldacf, dafcasing);
10817     bond(olddaf, bdfcasing);
10818     bond(oldbdf, cbfcasing);
10819     if (checksubfaces) {
10820       // Check for subfaces and rebond them to the rotated tets.
10821       if (acfsh.sh == dummysh) {
10822         tsdissolve(oldcbf);
10823       } else {
10824         tsbond(oldcbf, acfsh);
10825       }
10826       if (dafsh.sh == dummysh) {
10827         tsdissolve(oldacf);
10828       } else {
10829         tsbond(oldacf, dafsh);
10830       }
10831       if (bdfsh.sh == dummysh) {
10832         tsdissolve(olddaf);
10833       } else {
10834         tsbond(olddaf, bdfsh);
10835       }
10836       if (cbfsh.sh == dummysh) {
10837         tsdissolve(oldbdf);
10838       } else {
10839         tsbond(oldbdf, cbfsh);
10840       }
10841     } else if (checksubsegs) {
10842       // 5 edges in bacf are changed.
10843       enext2(bacf, worktet); // fit b->c into c->a.
10844       if (caseg.sh == dummysh) {
10845         tssdissolve1(worktet);
10846       } else {
10847         tssbond1(worktet, caseg);
10848       }
10849       enext(bacf, worktet); // fit c->a into a->d.
10850       if (adseg.sh == dummysh) {
10851         tssdissolve1(worktet);
10852       } else {
10853         tssbond1(worktet, adseg);
10854       }
10855       fnext(bacf, worktet); // fit b->f into c->f.
10856       enext2self(worktet);
10857       if (cfseg.sh == dummysh) {
10858         tssdissolve1(worktet);
10859       } else {
10860         tssbond1(worktet, cfseg);
10861       }
10862       enext2fnext(bacf, worktet); // fit c->f into a->f.
10863       enext2self(worktet);
10864       if (afseg.sh == dummysh) {
10865         tssdissolve1(worktet);
10866       } else {
10867         tssbond1(worktet, afseg);
10868       }
10869       enextfnext(bacf, worktet); // fit a->f into d->f.
10870       enext2self(worktet);
10871       if (dfseg.sh == dummysh) {
10872         tssdissolve1(worktet);
10873       } else {
10874         tssbond1(worktet, dfseg);
10875       }
10876       // 5 edges in abdf are changed.
10877       enext2(abdf, worktet); // fit a->d into d->b.
10878       if (dbseg.sh == dummysh) {
10879         tssdissolve1(worktet);
10880       } else {
10881         tssbond1(worktet, dbseg);
10882       }
10883       enext(abdf, worktet); // fit d->b into b->c.
10884       if (bcseg.sh == dummysh) {
10885         tssdissolve1(worktet);
10886       } else {
10887         tssbond1(worktet, bcseg);
10888       }
10889       fnext(abdf, worktet); // fit a->f into d->f.
10890       enext2self(worktet);
10891       if (dfseg.sh == dummysh) {
10892         tssdissolve1(worktet);
10893       } else {
10894         tssbond1(worktet, dfseg);
10895       }
10896       enext2fnext(abdf, worktet); // fit d->f into b->f.
10897       enext2self(worktet);
10898       if (bfseg.sh == dummysh) {
10899         tssdissolve1(worktet);
10900       } else {
10901         tssbond1(worktet, bfseg);
10902       }
10903       enextfnext(abdf, worktet); // fit b->f into c->f.
10904       enext2self(worktet);
10905       if (cfseg.sh == dummysh) {
10906         tssdissolve1(worktet);
10907       } else {
10908         tssbond1(worktet, cfseg);
10909       }
10910     }
10911   }
10912 
10913   // New vertex assignments for the rotated tetrahedra.
10914   setorg(abce, pd); // Update abce to dcae
10915   setdest(abce, pc);
10916   setapex(abce, pa);
10917   setorg(bade, pc); // Update bade to cdbe
10918   setdest(bade, pd);
10919   setapex(bade, pb);
10920   if (mirrorflag) {
10921     setorg(bacf, pc); // Update bacf to cdaf
10922     setdest(bacf, pd);
10923     setapex(bacf, pa);
10924     setorg(abdf, pd); // Update abdf to dcbf
10925     setdest(abdf, pc);
10926     setapex(abdf, pb);
10927   }
10928 
10929   // Are there subfaces need to be flipped?
10930   if (checksubfaces && abc.sh != dummysh) {
10931 #ifdef SELF_CHECK
10932     assert(bad.sh != dummysh);
10933 #endif
10934     // Adjust the edge be ab, so the rotation of subfaces is according with
10935     //   the rotation of tetrahedra.
10936     findedge(&abc, pa, pb);
10937     // Flip an edge of two subfaces, ignore non-Delaunay edges.
10938     flip22sub(&abc, NULL);
10939   }
10940 
10941   if (b->verbose > 3) {
10942     printf("    Updating abce ");
10943     printtet(&abce);
10944     printf("    Updating bade ");
10945     printtet(&bade);
10946     if (mirrorflag) {
10947       printf("    Updating bacf ");
10948       printtet(&bacf);
10949       printf("    Updating abdf ");
10950       printtet(&abdf);
10951     }
10952   }
10953 
10954   if (flipqueue != (queue *) NULL) { 
10955     enextfnext(abce, bcecasing);
10956     enqueueflipface(bcecasing, flipqueue);
10957     enext2fnext(abce, caecasing);
10958     enqueueflipface(caecasing, flipqueue);
10959     enextfnext(bade, adecasing);
10960     enqueueflipface(adecasing, flipqueue);
10961     enext2fnext(bade, dbecasing);
10962     enqueueflipface(dbecasing, flipqueue);
10963     if (mirrorflag) {
10964       enextfnext(bacf, acfcasing);
10965       enqueueflipface(acfcasing, flipqueue);
10966       enext2fnext(bacf, cbfcasing);
10967       enqueueflipface(cbfcasing, flipqueue);
10968       enextfnext(abdf, bdfcasing);
10969       enqueueflipface(bdfcasing, flipqueue);
10970       enext2fnext(abdf, dafcasing);
10971       enqueueflipface(dafcasing, flipqueue);
10972     }
10973     // The two new faces dcae (abce), cdbe (bade) may still not be locally
10974     //   Delaunay, and may need be flipped (flip23).  On the other hand, in
10975     //   conforming Delaunay algorithm, two new subfaces dca (abc), and cdb
10976     //   (bad) may be non-conforming Delaunay, they need be queued if they
10977     //   are locally Delaunay but non-conforming Delaunay.
10978     enqueueflipface(abce, flipqueue);
10979     enqueueflipface(bade, flipqueue);
10980   }
10981 
10982   // Save a live handle in 'recenttet'.
10983   recenttet = abce;
10984 }
10985 
10987 //                                                                           //
10988 // flip22sub()    Perform a 2-to-2 flip on a subface edge.                   //
10989 //                                                                           //
10990 // The flip edge is given by subface 'flipedge'.  Let it is abc, where ab is //
10991 // the flipping edge.  The other subface is bad,  where a, b, c, d form a    //
10992 // convex quadrilateral.  ab is not a subsegment.                            //
10993 //                                                                           //
10994 // A 2-to-2 subface flip is to change two subfaces abc and bad to another    //
10995 // two subfaces dca and cdb.  Hence, edge ab has been removed and dc becomes //
10996 // an edge. If a point e is above abc, this flip is equal to rotate abc and  //
10997 // bad counterclockwise using right-hand rule with thumb points to e. It is  //
10998 // important to know that the edge rings of the flipped subfaces dca and cdb //
10999 // are keeping the same orientation as their original subfaces. So they have //
11000 // the same orientation with respect to the lift point of this facet.        //
11001 //                                                                           //
11002 // During rotating, the face rings of the four edges bc, ca, ad, and de need //
11003 // be re-connected. If the edge is not a subsegment, then its face ring has  //
11004 // only two faces, a sbond() will bond them together. If it is a subsegment, //
11005 // one should use sbond1() twice to bond two different handles to the rotat- //
11006 // ing subface, one is predecssor (-casin), another is successor (-casout).  //
11007 //                                                                           //
11008 // If 'flipqueue' is not NULL, it returns four edges bc, ca, ad, de, which   //
11009 // may be non-Delaunay.                                                      //
11010 //                                                                           //
11012 
11013 void tetgenmesh::flip22sub(face* flipedge, queue* flipqueue)
11014 {
11015   face abc, bad;
11016   face oldbc, oldca, oldad, olddb;
11017   face bccasin, bccasout, cacasin, cacasout;
11018   face adcasin, adcasout, dbcasin, dbcasout;
11019   face bc, ca, ad, db;
11020   face spinsh;
11021   point pa, pb, pc, pd;
11022 
11023   abc = *flipedge;
11024   spivot(abc, bad);
11025   if (sorg(bad) != sdest(abc)) {
11026     sesymself(bad);
11027   }
11028   pa = sorg(abc);
11029   pb = sdest(abc);
11030   pc = sapex(abc);
11031   pd = sapex(bad);
11032 
11033   if (b->verbose > 2) {
11034     printf("    Flip sub edge (%d, %d).\n", pointmark(pa), pointmark(pb));
11035   }
11036 
11037   // Save the old configuration outside the quadrilateral.  
11038   senext(abc, oldbc);
11039   senext2(abc, oldca);
11040   senext(bad, oldad);
11041   senext2(bad, olddb);
11042   // Get the outside connection. Becareful if there is a subsegment on the
11043   //   quadrilateral, two casings (casin and casout) are needed to save for
11044   //   keeping the face link.
11045   spivot(oldbc, bccasout);
11046   sspivot(oldbc, bc);
11047   if (bc.sh != dummysh) {
11048     // 'bc' is a subsegment.
11049     if (bccasout.sh != dummysh) {
11050       if (oldbc.sh != bccasout.sh) {
11051         // 'oldbc' is not self-bonded.
11052         spinsh = bccasout;
11053         do {
11054           bccasin = spinsh;
11055           spivotself(spinsh);
11056         } while (spinsh.sh != oldbc.sh);
11057       } else {
11058         bccasout.sh = dummysh;
11059       }
11060     }
11061     ssdissolve(oldbc);
11062   }
11063   spivot(oldca, cacasout);
11064   sspivot(oldca, ca);
11065   if (ca.sh != dummysh) {
11066     // 'ca' is a subsegment.
11067     if (cacasout.sh != dummysh) {
11068       if (oldca.sh != cacasout.sh) {
11069         // 'oldca' is not self-bonded.
11070         spinsh = cacasout;
11071         do {
11072           cacasin = spinsh;
11073           spivotself(spinsh);
11074         } while (spinsh.sh != oldca.sh);
11075       } else {
11076         cacasout.sh = dummysh;
11077       }
11078     }
11079     ssdissolve(oldca);
11080   }
11081   spivot(oldad, adcasout);
11082   sspivot(oldad, ad);
11083   if (ad.sh != dummysh) {
11084     // 'ad' is a subsegment. 
11085     if (adcasout.sh != dummysh) {
11086       if (oldad.sh != adcasout.sh) {
11087         // 'adcasout' is not self-bonded.
11088         spinsh = adcasout;
11089         do {
11090           adcasin = spinsh;
11091           spivotself(spinsh);
11092         } while (spinsh.sh != oldad.sh);
11093       } else {
11094         adcasout.sh = dummysh;
11095       }
11096     }
11097     ssdissolve(oldad);
11098   }
11099   spivot(olddb, dbcasout);
11100   sspivot(olddb, db);
11101   if (db.sh != dummysh) {
11102     // 'db' is a subsegment.
11103     if (dbcasout.sh != dummysh) {
11104       if (olddb.sh != dbcasout.sh) {
11105         // 'dbcasout' is not self-bonded.
11106         spinsh = dbcasout;
11107         do {
11108           dbcasin = spinsh;
11109           spivotself(spinsh);
11110         } while (spinsh.sh != olddb.sh);
11111       } else {
11112         dbcasout.sh = dummysh;
11113       }
11114     }
11115     ssdissolve(olddb);
11116   }
11117 
11118   // Rotate abc and bad one-quarter turn counterclockwise.
11119   if (ca.sh != dummysh) {
11120     if (cacasout.sh != dummysh) {
11121       sbond1(cacasin, oldbc);
11122       sbond1(oldbc, cacasout);
11123     } else {
11124       // Bond 'oldbc' to itself.
11125       sbond(oldbc, oldbc);
11126       // Make sure that dummysh always correctly bonded.
11127       dummysh[0] = sencode(oldbc);
11128     }
11129     ssbond(oldbc, ca);
11130   } else {
11131     sbond(oldbc, cacasout);
11132   }
11133   if (ad.sh != dummysh) {
11134     if (adcasout.sh != dummysh) {
11135       sbond1(adcasin, oldca);
11136       sbond1(oldca, adcasout);
11137     } else {
11138       // Bond 'oldca' to itself.
11139       sbond(oldca, oldca);
11140       // Make sure that dummysh always correctly bonded.
11141       dummysh[0] = sencode(oldca);
11142     }
11143     ssbond(oldca, ad);
11144   } else {
11145     sbond(oldca, adcasout);
11146   }
11147   if (db.sh != dummysh) {
11148     if (dbcasout.sh != dummysh) {
11149       sbond1(dbcasin, oldad);
11150       sbond1(oldad, dbcasout);
11151     } else {
11152       // Bond 'oldad' to itself.
11153       sbond(oldad, oldad);
11154       // Make sure that dummysh always correctly bonded.
11155       dummysh[0] = sencode(oldad);
11156     }
11157     ssbond(oldad, db);
11158   } else {
11159     sbond(oldad, dbcasout);
11160   }
11161   if (bc.sh != dummysh) {
11162     if (bccasout.sh != dummysh) {
11163       sbond1(bccasin, olddb);
11164       sbond1(olddb, bccasout);
11165     } else {
11166       // Bond 'olddb' to itself.
11167       sbond(olddb, olddb);
11168       // Make sure that dummysh always correctly bonded.
11169       dummysh[0] = sencode(olddb);
11170     }
11171     ssbond(olddb, bc);
11172   } else {
11173     sbond(olddb, bccasout);
11174   }
11175 
11176   // New vertex assignments for the rotated subfaces.
11177   setsorg(abc, pd);  // Update abc to dca.
11178   setsdest(abc, pc);
11179   setsapex(abc, pa);
11180   setsorg(bad, pc);  // Update bad to cdb.
11181   setsdest(bad, pd);
11182   setsapex(bad, pb);
11183 
11184   if (flipqueue != (queue *) NULL) {
11185     enqueueflipedge(bccasout, flipqueue);
11186     enqueueflipedge(cacasout, flipqueue);
11187     enqueueflipedge(adcasout, flipqueue);
11188     enqueueflipedge(dbcasout, flipqueue);
11189   }
11190 }
11191 
11193 //                                                                           //
11194 // flip()    Flips non-locally Delaunay faces in flipqueue until it is empty.//
11195 //                                                                           //
11196 // Assumpation:  Current tetrahedralization is non-Delaunay after inserting  //
11197 // a point or performing a flip operation, all possibly non-Delaunay faces   //
11198 // are in 'flipqueue'.                                                       //
11199 //                                                                           //
11200 // If 'plastflip' is not NULL,  it is used to return a stack of recently     //
11201 // flipped faces.  This stack will be used to reverse the flips done in this //
11202 // routine later for removing a newly inserted point because it encroaches   //
11203 // any subfaces or subsegments.                                              //
11204 //                                                                           //
11205 // The return value is the total number of flips done during this invocation.//
11206 //                                                                           //
11208 
11209 long tetgenmesh::flip(queue* flipqueue, badface **plastflip)
11210 {
11211   badface *qface, *newflip;
11212   triface flipface, symface;
11213   point pa, pb, pc, pd, pe;
11214   enum fliptype fc;
11215   REAL sign, bakepsilon;
11216   long flipcount, maxfaces;
11217   int epscount, fcount;
11218   int ia, ib, ic, id, ie;
11219 
11220   if (b->verbose > 1) {
11221     printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
11222   }
11223 
11224   flipcount = flip23s + flip32s + flip22s + flip44s;
11225   if (checksubfaces) {
11226     maxfaces = (4l * tetrahedrons->items + hullsize) / 2l;
11227     fcount = 0;
11228   }
11229 
11230   if (plastflip != (badface **) NULL) {
11231     // Initialize the stack of the flip sequence.
11232     flipstackers->restart();
11233     *plastflip = (badface *) NULL;
11234   }
11235 
11236   // Loop until the queue is empty.
11237   while (!flipqueue->empty()) {
11238     qface = (badface *) flipqueue->pop();
11239     flipface = qface->tt;
11240     if (isdead(&flipface)) continue;
11241     sym(flipface, symface);
11242     // Only do check when the adjacent tet exists and it's not a "fake" tet.
11243     if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11244       // For positive orientation that insphere() test requires.
11245       adjustedgering(flipface, CW);
11246       pa = org(flipface);
11247       pb = dest(flipface);
11248       pc = apex(flipface);
11249       pd = oppo(flipface);
11250       pe = oppo(symface);
11251       if (symbolic) {
11252         ia = pointmark(pa);
11253         ib = pointmark(pb);
11254         ic = pointmark(pc);
11255         id = pointmark(pd);
11256         ie = pointmark(pe);
11257         sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
11258         assert(sign != 0.0);
11259       } else {  
11260         sign = insphere(pa, pb, pc, pd, pe);
11261       }
11262     } else {
11263       sign = -1.0; // A hull face is locally Delaunay.
11264     }
11265     if (sign > 0.0) {
11266       // 'flipface' is non-locally Delaunay, try to flip it.     
11267       if (checksubfaces) {
11268         fcount++;
11269         bakepsilon = b->epsilon;
11270         epscount = 0;
11271         while (epscount < 32) {
11272           fc = categorizeface(flipface);
11273           if (fc == N40) {
11274             b->epsilon *= 1e-1;
11275             epscount++;
11276             continue;
11277           }
11278           break;
11279         }
11280         b->epsilon = bakepsilon;
11281         if (epscount >= 32) {
11282           if (b->verbose > 0) {
11283             printf("Warning:  Can't flip a degenerate tetrahedron.\n");
11284           }
11285           fc = N40;
11286         }
11287       } else {
11288         fc = categorizeface(flipface);
11289 #ifdef SELF_CHECK
11290         assert(fc != N40);
11291 #endif
11292       }
11293       switch (fc) {
11294       // The following face types are flipable.
11295       case T44:
11296       case T22:
11297         flip22(&flipface, flipqueue); 
11298         break;
11299       case T23:
11300         flip23(&flipface, flipqueue); 
11301         break;
11302       case T32:
11303         flip32(&flipface, flipqueue); 
11304         break;
11305       // The following face types are unflipable.
11306       case N32:
11307         break;
11308       case FORBIDDENFACE:
11309         break;
11310       case FORBIDDENEDGE:
11311         break;
11312       // This case is only possible when the domain is nonconvex.
11313       case N40:
11314         // assert(nonconvex);
11315         break;
11316       }
11317       if (plastflip != (badface **) NULL) {
11318         if ((fc == T44) || (fc == T22) || (fc == T23) || (fc == T32)) { 
11319           // Push the flipped face into stack.
11320           newflip = (badface *) flipstackers->alloc();
11321           newflip->tt = flipface;
11322           newflip->key = (REAL) fc;
11323           newflip->forg = org(flipface);
11324           newflip->fdest = dest(flipface);
11325           newflip->fapex = apex(flipface);
11326           newflip->previtem = *plastflip;
11327           *plastflip = newflip; 
11328         }
11329       }
11330     }
11331   }
11332 
11333   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11334   if (b->verbose > 1) {
11335     printf("    %ld flips.\n", flipcount);
11336   }
11337 
11338   return flipcount;
11339 }
11340 
11342 //                                                                           //
11343 // lawson()    Flip locally non-Delaunay faces by Lawson's algorithm.        //
11344 //                                                                           //
11346 
11347 long tetgenmesh::lawson(list *misseglist, queue* flipqueue)
11348 {
11349   badface *qface, *misseg;
11350   triface flipface, symface;
11351   triface starttet, spintet;
11352   face checksh, checkseg;
11353   point pa, pb, pc, pd, pe;
11354   point swappt;
11355   REAL sign, ori;
11356   long flipcount;
11357   int ia, ib, ic, id, ie;  
11358   int hitbdry, i;
11359 
11360   if (b->verbose > 1) {
11361     printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
11362   }
11363   flipcount = flip23s + flip32s + flip22s + flip44s;
11364 
11365   // Go through the stack of possible flips and decide whether to do them.
11366   //   Note that during the loop new possible flips will be pushed onto
11367   //   this stack, while they popped in this loop.
11368   while (!flipqueue->empty()) {
11369     qface = (badface *) flipqueue->pop();
11370     flipface = qface->tt;
11371     // Check if tet has already been flipped out of existence.
11372     if (!isdead(&flipface)) {
11373       sym(flipface, symface);
11374       // Check if this tet is the same as the one which was stacked.
11375       if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11376         flipface.ver = 0; // Select the CCW ring.
11377         pa = org(flipface);
11378         pb = dest(flipface);
11379         pc = apex(flipface);
11380         pd = oppo(flipface);
11381         pe = oppo(symface);
11382         if (symbolic) {
11383           ia = pointmark(pa);
11384           ib = pointmark(pb);
11385           ic = pointmark(pc);
11386           id = pointmark(pd);
11387           ie = pointmark(pe);
11388           sign = insphere_sos(pb, pa, pc, pd, pe, ib, ia, ic, id, ie);
11389         } else {
11390           sign = insphere(pb, pa, pc, pd, pe);
11391         }
11392         if (sign > 0.0) {
11393           for (i = 0; i < 3; i++) {
11394             ori = orient3d(pa, pb, pd, pe);
11395             if (ori > 0.0) {
11396               // Goto and check the next edge.
11397               swappt = pa;
11398               pa = pb;
11399               pb = pc;
11400               pc = swappt;
11401               enextself(flipface);
11402             } else {
11403               break; // either (ori < 0.0) or (ori == 0.0)
11404             }
11405           } // for (i = 0; ....)
11406           if (ori > 0.0) {
11407             // All three edges are convex, a 2-3 flip is possible.
11408             if (checksubfaces) {
11409               tspivot(flipface, checksh);
11410               if (checksh.sh != dummysh) {
11411                 // A subface is not flipable.
11412                 continue;
11413               }
11414             }
11415             flip23(&flipface, flipqueue);
11416           } else if (ori < 0.0) {
11417             // The edge (a, b) is non-convex, check for a 3-2 flip.
11418             fnext(flipface, symface);
11419             symself(symface);
11420             if (oppo(symface) == pe) {
11421               // Only three tets adjoining this edge.
11422               if (checksubfaces) {
11423                 tsspivot(&flipface, &checkseg);
11424                 if (checkseg.sh != dummysh) {
11425                   // A subsegment is not flipable.
11426                   continue;
11427                 }
11428               } else if (checksubsegs) {
11429                 tsspivot1(flipface, checkseg);
11430                 if (checkseg.sh != dummysh) {
11431                   if (b->verbose > 2) {
11432                     printf("    Queuing missing segment (%d, %d).\n",
11433                       pointmark(org(flipface)), pointmark(dest(flipface)));
11434                   }
11435                   misseg = (badface *) misseglist->append(NULL);
11436                   misseg->ss = checkseg;
11437                   misseg->forg = sorg(checkseg);
11438                   misseg->fdest = sdest(checkseg);
11439                   // Detach all tets having this seg.
11440                   starttet = flipface;
11441                   adjustedgering(starttet, CCW);
11442                   fnextself(starttet);
11443                   spintet = starttet;
11444                   hitbdry = 0;
11445                   do {
11446                     tssdissolve1(spintet);
11447                     if (!fnextself(spintet)) {
11448                       hitbdry++;
11449                       if (hitbdry < 2) {
11450                         esym(starttet, spintet);
11451                         if (!fnextself(spintet)) {
11452                           hitbdry++;
11453                         }
11454                       }
11455                     }
11456                   } while ((apex(spintet) != apex(starttet)) && (hitbdry < 2));
11457                 }
11458               } // if (checksubfaces)
11459               flip32(&flipface, flipqueue);
11460             }
11461           } else {
11462             // Four points (a, b, d, e) are coplanar.
11463             fnext(flipface, symface);
11464             if (fnextself(symface)) {
11465               // Check for a 4-4 flip.
11466               fnextself(symface);
11467               if (apex(symface) == pe) {
11468                 if (checksubfaces) {
11469                   tsspivot(&flipface, &checkseg);
11470                   if (checkseg.sh != dummysh) {
11471                     // A subsegment is not flippable.
11472                     continue;
11473                   }
11474                 } else if (checksubsegs) {
11475                   tsspivot1(flipface, checkseg);
11476                   if (checkseg.sh != dummysh) {
11477                     if (b->verbose > 2) {
11478                       printf("    Queuing missing segment (%d, %d).\n",
11479                         pointmark(org(flipface)), pointmark(dest(flipface)));
11480                     }
11481                     misseg = (badface *) misseglist->append(NULL);
11482                     misseg->ss = checkseg;
11483                     misseg->forg = sorg(checkseg);
11484                     misseg->fdest = sdest(checkseg);
11485                     // Detach all tets having this seg.
11486                     starttet = flipface;
11487                     adjustedgering(starttet, CCW);
11488                     fnextself(starttet);
11489                     spintet = starttet;
11490                     hitbdry = 0;
11491                     do {
11492                       tssdissolve1(spintet);
11493                       if (!fnextself(spintet)) {
11494                         hitbdry++;
11495                         if (hitbdry < 2) {
11496                           esym(starttet, spintet);
11497                           if (!fnextself(spintet)) {
11498                             hitbdry++;
11499                           }
11500                         }
11501                       }
11502                     } while ((apex(spintet) != apex(starttet)) && 
11503                              (hitbdry < 2));
11504                   }
11505                 } // if (checksubfaces) 
11506                 flip22(&flipface, flipqueue);
11507               }
11508             } else {
11509               // Check for a 2-2 flip.
11510               esym(flipface, symface);
11511               fnextself(symface);
11512               symself(symface);
11513               if (symface.tet == dummytet) {
11514                 if (checksubfaces) {
11515                   tsspivot(&flipface, &checkseg);
11516                   if (checkseg.sh != dummysh) {
11517                     // A subsegment is not flipable.
11518                     continue;
11519                   }
11520                 } else if (checksubsegs) {
11521                   tsspivot1(flipface, checkseg);
11522                   if (checkseg.sh != dummysh) {
11523                     if (b->verbose > 2) {
11524                       printf("    Queuing missing segment (%d, %d).\n",
11525                         pointmark(org(flipface)), pointmark(dest(flipface)));
11526                     }
11527                     misseg = (badface *) misseglist->append(NULL);
11528                     misseg->ss = checkseg;
11529                     misseg->forg = sorg(checkseg);
11530                     misseg->fdest = sdest(checkseg);
11531                     // Detach all tets having this seg.
11532                     starttet = flipface;
11533                     adjustedgering(starttet, CCW);
11534                     fnextself(starttet);
11535                     spintet = starttet;
11536                     hitbdry = 0;
11537                     do {
11538                       tssdissolve1(spintet);
11539                       if (!fnextself(spintet)) {
11540                         hitbdry++;
11541                         if (hitbdry < 2) {
11542                           esym(starttet, spintet);
11543                           if (!fnextself(spintet)) {
11544                             hitbdry++;
11545                           }
11546                         }
11547                       }
11548                     } while ((apex(spintet) != apex(starttet)) && 
11549                              (hitbdry < 2));
11550                   }
11551                 } // if (checksubfaces)
11552                 flip22(&flipface, flipqueue);
11553               }
11554             }
11555           } // if (ori > 0.0)
11556         } // if (sign > 0.0)
11557       }
11558     } // !isdead(&qface->tt)
11559   } // while (!flipqueue->empty())
11560 
11561   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11562   if (b->verbose > 1) {
11563     printf("    %ld flips.\n", flipcount);
11564   }
11565   return flipcount;
11566 }
11567 
11569 //                                                                           //
11570 // undoflip()    Undo the most recent flip sequence induced by flip().       //
11571 //                                                                           //
11572 // 'lastflip' is the stack of recently flipped faces. Walks through the list //
11573 // of flips, in the reverse of the order in which they were done, and undoes //
11574 // them.                                                                     //
11575 //                                                                           //
11577 
11578 void tetgenmesh::undoflip(badface *lastflip)
11579 {
11580   enum fliptype fc;
11581 
11582   while (lastflip != (badface *) NULL) {
11583     // Get the right flipped face.
11584     findface(&lastflip->tt, lastflip->forg, lastflip->fdest, lastflip->fapex);
11585     fc = (enum fliptype) (int) lastflip->key;
11586     switch (fc) {
11587     case T23:
11588       // The reverse operation of T23 is T32.
11589       flip32(&lastflip->tt, NULL);
11590       break;
11591     case T32:
11592       // The reverse operation of T32 is T23.
11593       flip23(&lastflip->tt, NULL);
11594       break;
11595     case T22:
11596     case T44:
11597       // The reverse operation of T22 or T44 is again T22 or T44.
11598       flip22(&lastflip->tt, NULL);
11599       break;
11600     default: // To omit compile warnings.
11601       break;
11602     }
11603     // Go on and process the next transformation.
11604     lastflip = lastflip->previtem;
11605   }
11606 }
11607 
11609 //                                                                           //
11610 // flipsub()    Flip non-Delaunay edges in a queue of (coplanar) subfaces.   //
11611 //                                                                           //
11612 // Assumpation:  Current triangulation T contains non-Delaunay edges (after  //
11613 // inserting a point or performing a flip). Non-Delaunay edges are queued in //
11614 // 'facequeue'. Returns the total number of flips done during this call.     //
11615 //                                                                           //
11617 
11618 long tetgenmesh::flipsub(queue* flipqueue)
11619 {
11620   badface *qedge;
11621   face flipedge, symedge;
11622   face checkseg;
11623   point pa, pb, pc, pd;
11624   REAL vab[3], vac[3], vad[3];
11625   REAL dot1, dot2, lac, lad; 
11626   REAL sign, ori;
11627   int edgeflips;
11628   int i;
11629 
11630   if (b->verbose > 1) {
11631     printf("  Start do edge queue: %ld edges.\n", flipqueue->len());
11632   }
11633 
11634   edgeflips = 0;
11635 
11636   while (!flipqueue->empty()) {
11637     qedge = (badface *) flipqueue->pop();
11638     flipedge = qedge->ss;
11639     if (flipedge.sh == dummysh) continue;
11640     if ((sorg(flipedge) != qedge->forg) || 
11641         (sdest(flipedge) != qedge->fdest)) continue; 
11642     sspivot(flipedge, checkseg);
11643     if (checkseg.sh != dummysh) continue;  // Can't flip a subsegment.
11644     spivot(flipedge, symedge);
11645     if (symedge.sh == dummysh) continue; // Can't flip a hull edge.
11646     pa = sorg(flipedge);
11647     pb = sdest(flipedge);
11648     pc = sapex(flipedge);
11649     pd = sapex(symedge);
11650     // Choose the triangle abc or abd as the base depending on the angle1
11651     //   (Vac, Vab) and angle2 (Vad, Vab).
11652     for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
11653     for (i = 0; i < 3; i++) vac[i] = pc[i] - pa[i];
11654     for (i = 0; i < 3; i++) vad[i] = pd[i] - pa[i];
11655     dot1 = dot(vac, vab);
11656     dot2 = dot(vad, vab);
11657     dot1 *= dot1;
11658     dot2 *= dot2;
11659     lac = dot(vac, vac);
11660     lad = dot(vad, vad);
11661     if (lad * dot1 <= lac * dot2) {
11662       // angle1 is closer to 90 than angle2, choose abc (flipedge).
11663       abovepoint = facetabovepointarray[shellmark(flipedge)];
11664       if (abovepoint == (point) NULL) {
11665         getfacetabovepoint(&flipedge);
11666       }
11667       sign = insphere(pa, pb, pc, abovepoint, pd);
11668       ori = orient3d(pa, pb, pc, abovepoint);
11669     } else {
11670       // angle2 is closer to 90 than angle1, choose abd (symedge).
11671       abovepoint = facetabovepointarray[shellmark(symedge)];
11672       if (abovepoint == (point) NULL) {
11673         getfacetabovepoint(&symedge);
11674       }
11675       sign = insphere(pa, pb, pd, abovepoint, pc);
11676       ori = orient3d(pa, pb, pd, abovepoint);
11677     }
11678     // Correct the sign.
11679     sign = ori > 0.0 ? sign : -sign;
11680     if (sign > 0.0) {
11681       // Flip the non-Delaunay edge.
11682       flip22sub(&flipedge, flipqueue);
11683       edgeflips++;
11684     }
11685   }
11686 
11687   if (b->verbose > 1) {
11688     printf("  Total %d flips.\n", edgeflips);
11689   }
11690 
11691   return edgeflips;
11692 }
11693 
11695 //                                                                           //
11696 // removetetbypeeloff()    Remove a boundary tet by peeling it off.          //
11697 //                                                                           //
11698 // 'striptet' (abcd) is on boundary and can be removed by stripping it off.  //
11699 // Let abc and bad are the external boundary faces.                          //
11700 //                                                                           //
11701 // To strip 'abcd' from the mesh is to detach its two interal faces (dca and //
11702 // cdb) from their adjoining tets together with a 2-to-2 flip to transform   //
11703 // two subfaces (abc and bad) into another two (dca and cdb).                //
11704 //                                                                           //
11705 // In mesh optimization. It is possible that ab is a segment and abcd is a   //
11706 // sliver on the hull. Strip abcd will also delete the segment ab.           //
11707 //                                                                           //
11709 
11710 bool tetgenmesh::removetetbypeeloff(triface *striptet)
11711 {
11712   triface abcd, badc;
11713   triface dcacasing, cdbcasing;
11714   face abc, bad;
11715   face abseg;
11716   REAL ang;
11717   
11718   abcd = *striptet;
11719   adjustedgering(abcd, CCW);
11720   // Get the casing tets at the internal sides.
11721   enextfnext(abcd, cdbcasing);
11722   enext2fnext(abcd, dcacasing);
11723   symself(cdbcasing);
11724   symself(dcacasing);  
11725   // Do the neighboring tets exist?  During optimization. It is possible
11726   //   that the neighboring tets are already dead.
11727   if ((cdbcasing.tet == dummytet) || (dcacasing.tet == dummytet)) {
11728     // Do not strip this tet.
11729     return false;
11730   }
11731 
11732   // Are there subfaces?
11733   if (checksubfaces) {
11734     // Get the external subfaces abc, bad.
11735     fnext(abcd, badc);
11736     esymself(badc);
11737     tspivot(abcd, abc);
11738     tspivot(badc, bad);
11739     if (abc.sh != dummysh) { 
11740       assert(bad.sh != dummysh);
11741       findedge(&abc, org(abcd), dest(abcd));
11742       findedge(&bad, org(badc), dest(badc));
11743       // Is ab a segment?
11744       sspivot(abc, abseg);
11745       if (abseg.sh != dummysh) {
11746         // Does a segment allow to be removed?
11747         if ((b->optlevel > 3) && (b->nobisect == 0)) {
11748           // Only remove this segment if the dihedal angle at ab is between
11749           //   [b->maxdihedral-9, 180] (deg).  This avoids mistakely fliping
11750           //   ab when it has actually no big dihedral angle while cd has.
11751           ang = facedihedral(org(abcd), dest(abcd), apex(abcd), oppo(abcd));
11752           ang = ang * 180.0 / PI;
11753           if ((ang + 9.0) > b->maxdihedral) {
11754             if (b->verbose > 1) {
11755               printf("    Remove a segment during peeling.\n");
11756             }
11757             face prevseg, nextseg;
11758             // It is only shared by abc and bad (abcd is a tet).
11759             ssdissolve(abc);
11760             ssdissolve(bad);
11761             abseg.shver = 0;
11762             senext(abseg, nextseg);
11763             spivotself(nextseg);
11764             if (nextseg.sh != dummysh) {
11765               ssdissolve(nextseg);
11766             }
11767             senext2(abseg, prevseg);
11768             spivotself(prevseg);
11769             if (prevseg.sh != dummysh) {
11770               ssdissolve(prevseg);
11771             }
11772             shellfacedealloc(subsegs, abseg.sh);
11773             optcount[1]++;
11774           } else {
11775             return false;
11776           }
11777         } else {
11778           return false;
11779         }
11780       }
11781       // Do a 2-to-2 flip on abc and bad, transform abc->dca, bad->cdb.
11782       flip22sub(&abc, NULL);
11783       // The two internal faces become boundary faces.
11784       tsbond(cdbcasing, bad);
11785       tsbond(dcacasing, abc);
11786     }
11787   }
11788   
11789   // Detach abcd from the two internal faces.
11790   dissolve(cdbcasing);
11791   dissolve(dcacasing);
11792   // Delete abcd.
11793   tetrahedrondealloc(abcd.tet);
11794   return true;
11795 }
11796 
11798 //                                                                           //
11799 // removeedgebyflip22()    Remove an edge by a 2-to-2 (or 4-to-4) flip.      //
11800 //                                                                           //
11801 // 'abtetlist' contains n tets (n is 2 or 4) sharing edge ab,  abtetlist[0]  //
11802 // and abtetlist[1] are tets abec and abde, respectively (NOTE, both are in  //
11803 // CW edge ring), where a, b, c, and d are coplanar.  If n = 4, abtetlist[2] //
11804 // and abtetlist[3] are tets abfd and abcf, respectively.  This routine uses //
11805 // flip22() to replace edge ab with cd, the surrounding tets are rotated.    //
11806 //                                                                           //
11807 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
11808 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
11809 // is the maximum dihedral angle in the old tets.                            //
11810 //                                                                           //
11812 
11813 bool tetgenmesh::removeedgebyflip22(REAL *key, int n, triface *abtetlist,
11814   queue *flipque)
11815 {
11816   point pa, pb, pc, pd, pe, pf;
11817   REAL cosmaxd, d1, d2, d3;
11818   bool doflip;
11819 
11820   cosmaxd = 0.0;
11821   pf = apex(abtetlist[2]);
11822   doflip = true;
11823   adjustedgering(abtetlist[0], CW);
11824   pa = org(abtetlist[0]);
11825   pb = dest(abtetlist[0]);
11826   pe = apex(abtetlist[0]);
11827   pc = oppo(abtetlist[0]);
11828   pd = apex(abtetlist[1]);
11829   if (n == 4) {
11830     pf = apex(abtetlist[2]);
11831   }
11832   if (key && (*key > -1.0)) {
11833     tetalldihedral(pc, pd, pe, pa, NULL, &d1, NULL);
11834     tetalldihedral(pd, pc, pe, pb, NULL, &d2, NULL);
11835     cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11836     if (n == 4) {
11837       tetalldihedral(pd, pc, pf, pa, NULL, &d1, NULL);
11838       tetalldihedral(pc, pd, pf, pb, NULL, &d2, NULL);
11839       d3 = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11840       cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
11841     }
11842     doflip = (*key < cosmaxd); // Can local quality be improved?
11843   }
11844 
11845   if (doflip) {
11846     flip22(&abtetlist[0], NULL);
11847     // Return the improved quality value.
11848     if (key) *key = cosmaxd;
11849   }
11850 
11851   return doflip;
11852 }
11853 
11855 //                                                                           //
11856 // removefacebyflip23()    Remove a face by a 2-to-3 flip.                   //
11857 //                                                                           //
11858 // 'abctetlist' contains 2 tets sharing abc, which are [0]abcd and [1]bace.  //
11859 // This routine forms three new tets that abc is not a face anymore. Save    //
11860 // them in 'newtetlist': [0]edab, [1]edbc, and [2]edca.  Note that the new   //
11861 // tets may not valid if one of them get inverted. return false if so.       //
11862 //                                                                           //
11863 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
11864 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
11865 // is the maximum dihedral angle in the old tets.                            //
11866 //                                                                           //
11867 // If the face is flipped, 'newtetlist' returns the three new tets. The two  //
11868 // tets in 'abctetlist' are NOT deleted.  The caller has the right to either //
11869 // delete them or reverse the operation.                                     //
11870 //                                                                           //
11872 
11873 bool tetgenmesh::removefacebyflip23(REAL *key, triface *abctetlist,
11874   triface *newtetlist, queue *flipque)
11875 {
11876   triface edab, edbc, edca; // new configuration.
11877   triface newfront, oldfront, adjfront;
11878   face checksh;
11879   point pa, pb, pc, pd, pe;
11880   REAL ori, cosmaxd, d1, d2, d3;
11881   REAL attrib, volume;
11882   bool doflip;
11883   int i;
11884 
11885   cosmaxd = 0.0;
11886   
11887   adjustedgering(abctetlist[0], CCW);
11888   pa = org(abctetlist[0]);
11889   pb = dest(abctetlist[0]);
11890   pc = apex(abctetlist[0]);
11891   pd = oppo(abctetlist[0]);  
11892   pe = oppo(abctetlist[1]);
11893 
11894   // Check if the flip creates valid new tets.
11895   ori = orient3d(pe, pd, pa, pb);
11896   if (ori < 0.0) {
11897     ori = orient3d(pe, pd, pb, pc);
11898     if (ori < 0.0) {
11899       ori = orient3d(pe, pd, pc, pa);
11900     }
11901   }
11902   doflip = (ori < 0.0); // Can abc be flipped away?
11903   if (doflip && (key != (REAL *) NULL)) {
11904     if (*key > -1.0) {
11905       // Test if the new tets reduce the maximal dihedral angle.
11906       tetalldihedral(pe, pd, pa, pb, NULL, &d1, NULL);
11907       tetalldihedral(pe, pd, pb, pc, NULL, &d2, NULL);
11908       tetalldihedral(pe, pd, pc, pa, NULL, &d3, NULL);
11909       cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11910       cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
11911       doflip = (*key < cosmaxd); // Can local quality be improved?
11912     }
11913   }
11914 
11915   if (doflip) {
11916     // A valid (2-to-3) flip is found.
11917     flip23s++;
11918     // Create the new tets.
11919     maketetrahedron(&edab);
11920     setorg(edab, pe);
11921     setdest(edab, pd);
11922     setapex(edab, pa);
11923     setoppo(edab, pb);
11924     maketetrahedron(&edbc);
11925     setorg(edbc, pe);
11926     setdest(edbc, pd);
11927     setapex(edbc, pb);
11928     setoppo(edbc, pc);
11929     maketetrahedron(&edca);
11930     setorg(edca, pe);
11931     setdest(edca, pd);
11932     setapex(edca, pc);
11933     setoppo(edca, pa);
11934     // Transfer the element attributes.
11935     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
11936       attrib = elemattribute(abctetlist[0].tet, i);
11937       setelemattribute(edab.tet, i, attrib);
11938       setelemattribute(edbc.tet, i, attrib);
11939       setelemattribute(edca.tet, i, attrib);
11940     }
11941     // Transfer the volume constraints.
11942     if (b->varvolume && !b->refine) {
11943       volume = volumebound(abctetlist[0].tet);
11944       setvolumebound(edab.tet, volume);
11945       setvolumebound(edbc.tet, volume);
11946       setvolumebound(edca.tet, volume);
11947     }
11948     // Return two new tets.
11949     newtetlist[0] = edab;
11950     newtetlist[1] = edbc;
11951     newtetlist[2] = edca;
11952     // Glue the three new tets.
11953     for (i = 0; i < 3; i++) {
11954       fnext(newtetlist[i], newfront);
11955       bond(newfront, newtetlist[(i + 1) % 3]);
11956     }
11957     // Substitute the three new tets into the old cavity.
11958     for (i = 0; i < 3; i++) {
11959       fnext(abctetlist[0], oldfront);
11960       sym(oldfront, adjfront); // may be outside.
11961       enextfnext(newtetlist[i], newfront);
11962       bond(newfront, adjfront);
11963       if (checksubfaces) {
11964         tspivot(oldfront, checksh);
11965         if (checksh.sh != dummysh) {
11966           tsbond(newfront, checksh);
11967         }
11968       }
11969       if (flipque != (queue *) NULL) {
11970         enqueueflipface(newfront, flipque);
11971       }
11972       enextself(abctetlist[0]);
11973     }
11974     findedge(&(abctetlist[1]), pb, pa);
11975     for (i = 0; i < 3; i++) {
11976       fnext(abctetlist[1], oldfront);
11977       sym(oldfront, adjfront); // may be outside.
11978       enext2fnext(newtetlist[i], newfront);
11979       bond(newfront, adjfront);
11980       if (checksubfaces) {
11981         tspivot(oldfront, checksh);
11982         if (checksh.sh != dummysh) {
11983           tsbond(newfront, checksh);
11984         }
11985       }
11986       if (flipque != (queue *) NULL) {
11987         enqueueflipface(newfront, flipque);
11988       }
11989       enext2self(abctetlist[1]);
11990     }
11991     // Do not delete the old tets.
11992     // for (i = 0; i < 2; i++) {
11993     //   tetrahedrondealloc(abctetlist[i].tet);
11994     // }
11995     // Return the improved quality value.
11996     if (key != (REAL *) NULL) *key = cosmaxd;
11997     return true;
11998   }
11999 
12000   return false;
12001 }
12002 
12004 //                                                                           //
12005 // removeedgebyflip32()    Remove an edge by a 3-to-2 flip.                  //
12006 //                                                                           //
12007 // 'abtetlist' contains 3 tets sharing ab. Imaging that ab is perpendicular  //
12008 // to the screen, where a lies in front of and b lies behind it. The 3 tets  //
12009 // of the list are: [0]abce, [1]abdc, and [2]abed, respectively.             //
12010 //                                                                           //
12011 // This routine forms two new tets that ab is not an edge of them. Save them //
12012 // in 'newtetlist', [0]dcea, [1]cdeb. Note that the new tets may not valid   //
12013 // if one of them get inverted. return false if so.                          //
12014 //                                                                           //
12015 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
12016 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
12017 // is the maximum dihedral angle in the old tets.                            //
12018 //                                                                           //
12019 // If the edge is flipped, 'newtetlist' returns the two new tets. The three  //
12020 // tets in 'abtetlist' are NOT deleted.  The caller has the right to either  //
12021 // delete them or reverse the operation.                                     //
12022 //                                                                           //
12024 
12025 bool tetgenmesh::removeedgebyflip32(REAL *key, triface *abtetlist,
12026   triface *newtetlist, queue *flipque)
12027 {
12028   triface dcea, cdeb; // new configuration.
12029   triface newfront, oldfront, adjfront;
12030   face checksh;
12031   point pa, pb, pc, pd, pe;
12032   REAL ori, cosmaxd, d1, d2;
12033   REAL attrib, volume;
12034   bool doflip;
12035   int i;
12036 
12037   pa = org(abtetlist[0]);
12038   pb = dest(abtetlist[0]);
12039   pc = apex(abtetlist[0]);
12040   pd = apex(abtetlist[1]);
12041   pe = apex(abtetlist[2]);
12042 
12043   ori = orient3d(pd, pc, pe, pa);
12044   if (ori < 0.0) {
12045     ori = orient3d(pc, pd, pe, pb);
12046   }
12047   doflip = (ori < 0.0); // Can ab be flipped away?
12048 
12049   // Does the caller ensure a valid configuration?
12050   if (doflip && (key != (REAL *) NULL)) {    
12051     if (*key > -1.0) {
12052       // Test if the new tets reduce the maximal dihedral angle.
12053       tetalldihedral(pd, pc, pe, pa, NULL, &d1, NULL);
12054       tetalldihedral(pc, pd, pe, pb, NULL, &d2, NULL);
12055       cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
12056       doflip = (*key < cosmaxd); // Can local quality be improved?
12057       // Return the key
12058       *key = cosmaxd;
12059     }
12060   }
12061 
12062   if (doflip) {
12063     // Create the new tets.
12064     maketetrahedron(&dcea);
12065     setorg(dcea, pd);
12066     setdest(dcea, pc);
12067     setapex(dcea, pe);
12068     setoppo(dcea, pa);
12069     maketetrahedron(&cdeb);
12070     setorg(cdeb, pc);
12071     setdest(cdeb, pd);
12072     setapex(cdeb, pe);
12073     setoppo(cdeb, pb);
12074     // Transfer the element attributes.
12075     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12076       attrib = elemattribute(abtetlist[0].tet, i);
12077       setelemattribute(dcea.tet, i, attrib);
12078       setelemattribute(cdeb.tet, i, attrib);
12079     }
12080     // Transfer the volume constraints.
12081     if (b->varvolume && !b->refine) {
12082       volume = volumebound(abtetlist[0].tet);
12083       setvolumebound(dcea.tet, volume);
12084       setvolumebound(cdeb.tet, volume);
12085     }
12086     // Return two new tets.
12087     newtetlist[0] = dcea;
12088     newtetlist[1] = cdeb;
12089     // Glue the two new tets.
12090     bond(dcea, cdeb);
12091     // Substitute the two new tets into the old three-tets cavity.
12092     for (i = 0; i < 3; i++) {
12093       fnext(dcea, newfront); // face dca, cea, eda.
12094       esym(abtetlist[(i + 1) % 3], oldfront);
12095       enextfnextself(oldfront);
12096       // Get the adjacent tet at the face (may be a dummytet).
12097       sym(oldfront, adjfront);
12098       bond(newfront, adjfront);
12099       if (checksubfaces) {
12100         tspivot(oldfront, checksh);
12101         if (checksh.sh != dummysh) {
12102           tsbond(newfront, checksh);
12103         }
12104       }
12105       if (flipque != (queue *) NULL) {
12106         enqueueflipface(newfront, flipque);
12107       }
12108       enext2self(dcea);
12109     }
12110     for (i = 0; i < 3; i++) {
12111       fnext(cdeb, newfront); // face cdb, deb, ecb.
12112       esym(abtetlist[(i + 1) % 3], oldfront);
12113       enext2fnextself(oldfront);
12114       // Get the adjacent tet at the face (may be a dummytet).
12115       sym(oldfront, adjfront);
12116       bond(newfront, adjfront);
12117       if (checksubfaces) {
12118         tspivot(oldfront, checksh);
12119         if (checksh.sh != dummysh) {
12120           tsbond(newfront, checksh);
12121         }
12122       }
12123       if (flipque != (queue *) NULL) {
12124         enqueueflipface(newfront, flipque);
12125       }
12126       enextself(cdeb);
12127     }
12128     // Do not delete the old tets.
12129     // for (i = 0; i < 3; i++) {
12130     //   tetrahedrondealloc(abtetlist[i].tet);
12131     // }
12132     return true;
12133   } // if (doflip)
12134 
12135   return false;
12136 }
12137 
12139 //                                                                           //
12140 // removeedgebytranNM()    Remove an edge by transforming n-to-m tets.       //
12141 //                                                                           //
12142 // This routine attempts to remove a given edge (ab) by transforming the set //
12143 // T of tets surrounding ab into another set T' of tets.  T and T' have the  //
12144 // same outer faces and ab is not an edge of T' anymore. Let |T|=n, and |T'| //
12145 // =m, it is actually a n-to-m flip for n > 3.  The relation between n and m //
12146 // depends on the method, ours is found below.                               //
12147 //                                                                           //
12148 // 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
12149 // to the screen, where a lies in front of and b lies behind it.  Let the    //
12150 // projections of the n apexes onto screen in clockwise order are: p_0, ...  //
12151 // p_n-1, respectively. The tets in the list are: [0]abp_0p_n-1,[1]abp_1p_0, //
12152 // ..., [n-1]abp_n-1p_n-2, respectively.                                     //
12153 //                                                                           //
12154 // The principle of the approach is: Recursively reduce the link of ab by    //
12155 // using flip23 until only three faces remain, hence a flip32 can be applied //
12156 // to remove ab. For a given face a.b.p_0, check a flip23 can be applied on  //
12157 // it, i.e, edge p_1.p_n-1 crosses it. NOTE*** We do the flip even p_1.p_n-1 //
12158 // intersects with a.b (they are coplanar). If so, a degenerate tet (a.b.p_1.//
12159 // p_n-1) is temporarily created, but it will be eventually removed by the   //
12160 // final flip32. This relaxation splits a flip44 into flip23 + flip32. *NOTE //
12161 // Now suppose a.b.p_0 gets flipped, p_0 is not on the link of ab anymore.   //
12162 // The link is then reduced (by 1). 2 of the 3 new tets, p_n-1.p_1.p_0.a and //
12163 // p_1.p_n-1.p_0.b, will be part of the new configuration.  The left new tet,//
12164 // a.b.p_1.p_n-1, goes into the new link of ab. A recurrence can be applied. //
12165 //                                                                           //
12166 // If 'e1' and 'e2' are not NULLs, they specify an wanted edge to appear in  //
12167 // the new tet configuration. In such case, only do flip23 if edge e1<->e2   //
12168 // can be recovered. It is used in removeedgebycombNM().                     //
12169 //                                                                           //
12170 // If ab gets removed. 'newtetlist' contains m new tets.  By using the above //
12171 // approach, the pairs (n, m) can be easily enumerated.  For example, (3, 2),//
12172 // (4, 4), (5, 6), (6, 8), (7, 10), (8, 12), (9, 14), (10, 16),  and so on.  //
12173 // It is easy to deduce, that m = (n - 2) * 2, when n >= 3.  The n tets in   //
12174 // 'abtetlist' are NOT deleted in this routine. The caller has the right to  //
12175 // either delete them or reverse this operation.                             //
12176 //                                                                           //
12178 
12179 bool tetgenmesh::removeedgebytranNM(REAL *key, int n, triface *abtetlist,
12180   triface *newtetlist, point e1, point e2, queue *flipque)
12181 {
12182   triface tmpabtetlist[9]; // Temporary max 9 tets configuration.
12183   triface newfront, oldfront, adjfront;
12184   face checksh;
12185   point pa, pb, p[10];
12186   REAL ori, cosmaxd, d1, d2;
12187   REAL tmpkey;
12188   REAL attrib, volume;
12189   bool doflip, copflag, success;
12190   int i, j, k;
12191 
12192   cosmaxd = 0.0;
12193   // Maximum 10 tets.
12194   assert(n <= 10);
12195   // Two points a and b are fixed.
12196   pa = org(abtetlist[0]);
12197   pb = dest(abtetlist[0]);
12198   // The points p_0, p_1, ..., p_n-1 are permuted in each new configuration.
12199   //   These permutations can be easily done in the following loop.
12200   // Loop through all the possible new tets configurations. Stop on finding
12201   //   a valid new tet configuration which also immproves the quality value.
12202   for (i = 0; i < n; i++) {
12203     // Get other n points for the current configuration.
12204     for (j = 0; j < n; j++) {
12205       p[j] = apex(abtetlist[(i + j) % n]);
12206     }
12207     // Is there a wanted edge?
12208     if ((e1 != (point) NULL) && (e2 != (point) NULL)) {
12209       // Yes. Skip this face if p[1]<->p[n-1] is not the edge.
12210       if (!(((p[1] == e1) && (p[n - 1] == e2)) ||
12211         ((p[1] == e2) && (p[n - 1] == e1)))) continue;
12212     }
12213     // Test if face a.b.p_0 can be flipped (by flip23), ie, to check if the
12214     //   edge p_n-1.p_1 crosses face a.b.p_0 properly.
12215     // Note. It is possible that face a.b.p_0 has type flip44, ie, a,b,p_1,
12216     //   and p_n-1 are coplanar. A trick is to split the flip44 into two
12217     //   steps: frist a flip23, then a flip32. The first step creates a
12218     //   degenerate tet (vol=0) which will be removed by the second flip.
12219     ori = orient3d(pa, pb, p[1], p[n - 1]);
12220     copflag = (ori == 0.0); // Are they coplanar?
12221     if (ori >= 0.0) {
12222       // Accept the coplanar case which supports flip44.
12223       ori = orient3d(pb, p[0], p[1], p[n - 1]);
12224       if (ori > 0.0) {
12225         ori = orient3d(p[0], pa, p[1], p[n - 1]);
12226       }
12227     }
12228     // Is face abc flipable?
12229     if (ori > 0.0) {
12230       // A valid (2-to-3) flip (or 4-to-4 flip) is found.
12231       copflag ? flip44s++ : flip23s++;
12232       doflip = true;
12233       if (key != (REAL *) NULL) {
12234         if (*key > -1.0) {
12235           // Test if the new tets reduce the maximal dihedral angle. Only 2
12236           //   tets, p_n-1.p_1.p_0.a and p_1.p_n-1.p_0.b, need to be tested
12237           //   The left one a.b.p_n-1.p_1 goes into the new link of ab.
12238           tetalldihedral(p[n - 1], p[1], p[0], pa, NULL, &d1, NULL);
12239           tetalldihedral(p[1], p[n - 1], p[0], pb, NULL, &d2, NULL);
12240           cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
12241           doflip = *key < cosmaxd; // Can the local quality be improved?
12242         }
12243       }
12244       if (doflip) {
12245         tmpkey = key != NULL ? *key : -1.0;
12246         // Create the two new tets.
12247         maketetrahedron(&(newtetlist[0]));
12248         setorg(newtetlist[0], p[n - 1]);
12249         setdest(newtetlist[0], p[1]);
12250         setapex(newtetlist[0], p[0]);
12251         setoppo(newtetlist[0], pa);
12252         maketetrahedron(&(newtetlist[1]));
12253         setorg(newtetlist[1], p[1]);
12254         setdest(newtetlist[1], p[n - 1]);
12255         setapex(newtetlist[1], p[0]);
12256         setoppo(newtetlist[1], pb);
12257         // Create the n - 1 temporary new tets (the new Star(ab)).
12258         maketetrahedron(&(tmpabtetlist[0]));
12259         setorg(tmpabtetlist[0], pa);
12260         setdest(tmpabtetlist[0], pb);
12261         setapex(tmpabtetlist[0], p[n - 1]);
12262         setoppo(tmpabtetlist[0], p[1]);
12263         for (j = 1; j < n - 1; j++) {
12264           maketetrahedron(&(tmpabtetlist[j]));
12265           setorg(tmpabtetlist[j], pa);
12266           setdest(tmpabtetlist[j], pb);
12267           setapex(tmpabtetlist[j], p[j]);
12268           setoppo(tmpabtetlist[j], p[j + 1]);
12269         }
12270         // Transfer the element attributes.
12271         for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12272           attrib = elemattribute(abtetlist[0].tet, j);
12273           setelemattribute(newtetlist[0].tet, j, attrib);
12274           setelemattribute(newtetlist[1].tet, j, attrib);
12275           for (k = 0; k < n - 1; k++) {
12276             setelemattribute(tmpabtetlist[k].tet, j, attrib);
12277           }
12278         }
12279         // Transfer the volume constraints.
12280         if (b->varvolume && !b->refine) {
12281           volume = volumebound(abtetlist[0].tet);
12282           setvolumebound(newtetlist[0].tet, volume);
12283           setvolumebound(newtetlist[1].tet, volume);
12284           for (k = 0; k < n - 1; k++) {
12285             setvolumebound(tmpabtetlist[k].tet, volume);
12286           }
12287         }
12288         // Glue the new tets at their internal faces: 2 + (n - 1).
12289         bond(newtetlist[0], newtetlist[1]); // p_n-1.p_1.p_0.
12290         fnext(newtetlist[0], newfront);
12291         enext2fnext(tmpabtetlist[0], adjfront);
12292         bond(newfront, adjfront); // p_n-1.p_1.a.
12293         fnext(newtetlist[1], newfront);
12294         enextfnext(tmpabtetlist[0], adjfront);
12295         bond(newfront, adjfront); // p_n-1.p_1.b.
12296         // Glue n - 1 internal faces around ab.
12297         for (j = 0; j < n - 1; j++) {
12298           fnext(tmpabtetlist[j], newfront);
12299           bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
12300         }
12301         // Substitute the old tets with the new tets by connecting the new
12302         //   tets to the adjacent tets in the mesh. There are n * 2 (outer)
12303         //   faces of the new tets need to be operated.
12304         // Note, after the substitution, the old tets still have pointers to
12305         //   their adjacent tets in the mesh.  These pointers can be re-used
12306         //   to inverse the substitution.
12307         for (j = 0; j < n; j++) {
12308           // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
12309           oldfront = abtetlist[(i + j) % n];
12310           esymself(oldfront);
12311           enextfnextself(oldfront);
12312           // Get an adjacent tet at face: [0]a.p_0.p_n-1 or [j]a.p_j.p_j-1.
12313           sym(oldfront, adjfront); // adjfront may be dummy.
12314           // Get the corresponding face from the new tets.
12315           if (j == 0) {
12316             enext2fnext(newtetlist[0], newfront); // a.p_0.n_n-1
12317           } else if (j == 1) {
12318             enextfnext(newtetlist[0], newfront); // a.p_1.p_0
12319           } else { // j >= 2.
12320             enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
12321           }
12322           bond(newfront, adjfront);
12323           if (checksubfaces) {
12324             tspivot(oldfront, checksh); 
12325             if (checksh.sh != dummysh) {
12326               tsbond(newfront, checksh);
12327             }
12328           }
12329           if (flipque != (queue *) NULL) {
12330             // Only queue the faces of the two new tets.
12331             if (j < 2) enqueueflipface(newfront, flipque);
12332           }
12333         }
12334         for (j = 0; j < n; j++) {
12335           // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
12336           oldfront = abtetlist[(i + j) % n];
12337           esymself(oldfront);
12338           enext2fnextself(oldfront);
12339           // Get an adjacent tet at face: [0]b.p_0.p_n-1 or [j]b.p_j.p_j-1.
12340           sym(oldfront, adjfront); // adjfront may be dummy.
12341           // Get the corresponding face from the new tets.
12342           if (j == 0) {
12343             enextfnext(newtetlist[1], newfront); // b.p_0.n_n-1
12344           } else if (j == 1) {
12345             enext2fnext(newtetlist[1], newfront); // b.p_1.p_0
12346           } else { // j >= 2.
12347             enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
12348           }
12349           bond(newfront, adjfront);
12350           if (checksubfaces) {
12351             tspivot(oldfront, checksh); 
12352             if (checksh.sh != dummysh) {
12353               tsbond(newfront, checksh);
12354             }
12355           }
12356           if (flipque != (queue *) NULL) {
12357             // Only queue the faces of the two new tets.
12358             if (j < 2) enqueueflipface(newfront, flipque);
12359           }
12360         }
12361         // Adjust the faces in the temporary new tets at ab for recursively
12362         //   processing on the n-1 tets.(See the description at beginning)
12363         for (j = 0; j < n - 1; j++) {
12364           fnextself(tmpabtetlist[j]);
12365         }
12366         if (n > 4) {
12367           success = removeedgebytranNM(&tmpkey, n-1, tmpabtetlist,
12368             &(newtetlist[2]), NULL, NULL, flipque);
12369         } else { // assert(n == 4);
12370           success = removeedgebyflip32(&tmpkey, tmpabtetlist,
12371             &(newtetlist[2]), flipque);
12372         }
12373         // No matter it was success or not, delete the temporary tets.
12374         for (j = 0; j < n - 1; j++) {
12375           tetrahedrondealloc(tmpabtetlist[j].tet);
12376         }
12377         if (success) {
12378           // The new configuration is good. 
12379           // Do not delete the old tets.
12380           // for (j = 0; j < n; j++) {
12381           //   tetrahedrondealloc(abtetlist[j].tet);
12382           // }
12383           // Save the minimal improved quality value.
12384           if (key != (REAL *) NULL) {
12385             *key = (tmpkey < cosmaxd ? tmpkey : cosmaxd);
12386           }
12387           return true;
12388         } else {
12389           // The new configuration is bad, substitue back the old tets.
12390           for (j = 0; j < n; j++) {
12391             oldfront = abtetlist[(i + j) % n];
12392             esymself(oldfront);
12393             enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
12394             sym(oldfront, adjfront); // adjfront may be dummy.
12395             bond(oldfront, adjfront);
12396             if (checksubfaces) {
12397               tspivot(oldfront, checksh);
12398               if (checksh.sh != dummysh) {
12399                 tsbond(oldfront, checksh);
12400               }
12401             }
12402           }
12403           for (j = 0; j < n; j++) {
12404             oldfront = abtetlist[(i + j) % n];
12405             esymself(oldfront);
12406             enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12407             sym(oldfront, adjfront); // adjfront may be dummy
12408             bond(oldfront, adjfront);
12409             if (checksubfaces) {
12410               tspivot(oldfront, checksh);
12411               if (checksh.sh != dummysh) {
12412                 tsbond(oldfront, checksh);
12413               }
12414             }
12415           }
12416           // Delete the new tets.
12417           tetrahedrondealloc(newtetlist[0].tet);
12418           tetrahedrondealloc(newtetlist[1].tet);
12419           // If tmpkey has been modified, then the failure was not due to
12420           //   unflipable configuration, but the non-improvement.
12421           if (key && (tmpkey < *key)) {
12422             *key = tmpkey;
12423             return false;
12424           }
12425         } // if (success)
12426       } // if (doflip)
12427     } // if (ori > 0.0)
12428   } // for (i = 0; i < n; i++)
12429 
12430   return false;
12431 }
12432 
12434 //                                                                           //
12435 // removeedgebycombNM()    Remove an edge by combining two flipNMs.          //
12436 //                                                                           //
12437 // Given a set T of tets surrounding edge ab. The premise is that ab can not //
12438 // be removed by a flipNM. This routine attempts to remove ab by two flipNMs,//
12439 // i.e., first find and flip an edge af (or bf) by flipNM, then flip ab by   //
12440 // flipNM. If it succeeds, two sets T(ab) and T(af) of tets are replaced by  //
12441 // a new set T' and both ab and af are not edges in T' anymore.              //
12442 //                                                                           //
12443 // 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
12444 // to the screen, such that a lies in front of and b lies behind it. Let the //
12445 // projections of the n apexes on the screen in clockwise order are: p_0,...,//
12446 // p_n-1, respectively. So the list of tets are: [0]abp_0p_n-1, [1]abp_1p_0, //
12447 // ..., [n-1]abp_n-1p_n-2, respectively.                                     //
12448 //                                                                           //
12449 // The principle of the approach is: for a face a.b.p_0, check if edge b.p_0 //
12450 // is of type N32 (or N44). If it is, then try to do a flipNM on it. If the  //
12451 // flip is successful, then try to do another flipNM on a.b.  If one of the  //
12452 // two flipNMs fails, restore the old tets as they have never been flipped.  //
12453 // Then try the next face a.b.p_1.  The process can be looped for all faces  //
12454 // having ab. Stop if ab is removed or all faces have been visited. Note in  //
12455 // the above description only b.p_0 is considered, a.p_0 is done by swapping //
12456 // the position of a and b.                                                  //
12457 //                                                                           //
12458 // Similar operations have been described in [Joe,1995].  My approach checks //
12459 // more cases for finding flips than Joe's.  For instance, the cases (1)-(7) //
12460 // of Joe only consider abf for finding a flip (T23/T32).  My approach looks //
12461 // all faces at ab for finding flips. Moreover, the flipNM can flip an edge  //
12462 // whose star may have more than 3 tets while Joe's only works on 3-tet case.//
12463 //                                                                           //
12464 // If ab is removed, 'newtetlist' contains the new tets. Two sets 'abtetlist'//
12465 // (n tets) and 'bftetlist' (n1 tets) have been replaced.  The number of new //
12466 // tets can be calculated by follows: the 1st flip transforms n1 tets into   //
12467 // (n1 - 2) * 2 new tets, however,one of the new tets goes into the new link //
12468 // of ab, i.e., the reduced tet number in Star(ab) is n - 1;  the 2nd flip   //
12469 // transforms n - 1 tets into (n - 3) * 2 new tets. Hence the number of new  //
12470 // tets are: m = ((n1 - 2) * 2 - 1) + (n - 3) * 2.  The old tets are NOT del-//
12471 // eted. The caller has the right to delete them or reverse the operation.   //
12472 //                                                                           //
12474 
12475 bool tetgenmesh::removeedgebycombNM(REAL *key, int n, triface *abtetlist,
12476   int *n1, triface *bftetlist, triface *newtetlist, queue *flipque)
12477 {
12478   triface tmpabtetlist[11];
12479   triface newfront, oldfront, adjfront;
12480   face checksh;
12481   point pa, pb, p[10];
12482   REAL ori, tmpkey, tmpkey2;
12483   REAL attrib, volume;
12484   bool doflip, success;
12485   int twice, count;
12486   int i, j, k, m;
12487 
12488   // Maximal 10 tets in Star(ab).
12489   assert(n <= 10);
12490 
12491   // Do the following procedure twice, one for flipping edge b.p_0 and the
12492   //   other for p_0.a which is symmetric to the first.
12493   twice = 0;
12494   do {
12495     // Two points a and b are fixed.
12496     pa = org(abtetlist[0]);
12497     pb = dest(abtetlist[0]);
12498     // The points p_0, ..., p_n-1 are permuted in the following loop.
12499     for (i = 0; i < n; i++) {
12500       // Get the n points for the current configuration.
12501       for (j = 0; j < n; j++) {
12502         p[j] = apex(abtetlist[(i + j) % n]);
12503       }
12504       // Check if b.p_0 is of type N32 or N44.
12505       ori = orient3d(pb, p[0], p[1], p[n - 1]);
12506       if ((ori > 0) && (key != (REAL *) NULL)) {
12507         // b.p_0 is not N32. However, it is possible that the tet b.p_0.p_1.
12508         //   p_n-1 has worse quality value than the key. In such case, also
12509         //   try to flip b.p_0.
12510         tetalldihedral(pb, p[0], p[n - 1], p[1], NULL, &tmpkey, NULL);
12511         if (tmpkey < *key) ori = 0.0;
12512       }
12513       if (ori <= 0.0) {
12514         // b.p_0 is either N32 or N44. Try the 1st flipNM.
12515         bftetlist[0] = abtetlist[i];
12516         enextself(bftetlist[0]);// go to edge b.p_0.
12517         adjustedgering(bftetlist[0], CW); // edge p_0.b.
12518         assert(apex(bftetlist[0]) == pa);
12519         // Form Star(b.p_0).
12520         doflip = true;
12521         *n1 = 0;
12522         do {
12523           // Is the list full?
12524           if (*n1 == 10) break;
12525           if (checksubfaces) {
12526             // Stop if a subface appears.
12527             tspivot(bftetlist[*n1], checksh);
12528             if (checksh.sh != dummysh) {
12529               doflip = false; break;
12530             }
12531           }
12532           // Get the next tet at p_0.b.
12533           fnext(bftetlist[*n1], bftetlist[(*n1) + 1]);
12534           (*n1)++;
12535         } while (apex(bftetlist[*n1]) != pa);
12536         // 2 <= n1 <= 10.
12537         if (doflip) {
12538           success = false;
12539           tmpkey = -1.0;  // = acos(pi).
12540           if (key != (REAL *) NULL) tmpkey = *key;
12541           m = 0;
12542           if (*n1 == 3) {
12543             // Three tets case. Try flip32.
12544             success = removeedgebyflip32(&tmpkey,bftetlist,newtetlist,flipque);
12545             m = 2;
12546           } else if ((*n1 > 3) && (*n1 < 7)) {
12547             // Four or more tets case. Try flipNM.
12548             success = removeedgebytranNM(&tmpkey, *n1, bftetlist, newtetlist,
12549                                          p[1], p[n - 1], flipque);
12550             // If success, the number of new tets.
12551             m = ((*n1) - 2) * 2;
12552           } else {
12553             if (b->verbose > 1) {
12554               printf("  !! Unhandled case: n1 = %d.\n", *n1);
12555             }
12556           }
12557           if (success) {
12558             // b.p_0 is flipped. The link of ab is reduced (by 1), i.e., p_0
12559             //   is not on the link of ab. Two old tets a.b.p_0.p_n-1 and
12560             //   a.b.p_1.p_0 have been removed from the Star(ab) and one new
12561             //   tet t = a.b.p_1.p_n-1 belongs to Star(ab). 
12562             // Find t in the 'newtetlist' and remove it from the list.
12563             setpointmark(pa, -pointmark(pa) - 1);
12564             setpointmark(pb, -pointmark(pb) - 1);
12565             assert(m > 0);
12566             for (j = 0; j < m; j++) {
12567               tmpabtetlist[0] = newtetlist[j];
12568               // Does it has ab?
12569               count = 0;
12570               for (k = 0; k < 4; k++) {
12571                 if (pointmark((point)(tmpabtetlist[0].tet[4+k])) < 0) count++;
12572               }
12573               if (count == 2) {
12574                 // It is. Adjust t to be the edge ab.
12575                 for (tmpabtetlist[0].loc = 0; tmpabtetlist[0].loc < 4;
12576                      tmpabtetlist[0].loc++) {
12577                   if ((oppo(tmpabtetlist[0]) != pa) &&
12578                       (oppo(tmpabtetlist[0]) != pb)) break;
12579                 }
12580                 // The face of t must contain ab.
12581                 assert(tmpabtetlist[0].loc < 4);
12582                 findedge(&(tmpabtetlist[0]), pa, pb);
12583                 break;
12584               }
12585             }
12586             assert(j < m); // The tet must exist.
12587             // Remove t from list. Fill t's position by the last tet.
12588             newtetlist[j] = newtetlist[m - 1];
12589             setpointmark(pa, -(pointmark(pa) + 1));
12590             setpointmark(pb, -(pointmark(pb) + 1));
12591             // Create the temporary Star(ab) for the next flipNM.
12592             adjustedgering(tmpabtetlist[0], CCW);
12593             if (org(tmpabtetlist[0]) != pa) {
12594               fnextself(tmpabtetlist[0]);
12595               esymself(tmpabtetlist[0]);
12596             }
12597 #ifdef SELF_CHECK
12598             // Make sure current edge is a->b.
12599             assert(org(tmpabtetlist[0]) == pa);
12600             assert(dest(tmpabtetlist[0]) == pb);
12601             assert(apex(tmpabtetlist[0]) == p[n - 1]);
12602             assert(oppo(tmpabtetlist[0]) == p[1]);
12603 #endif // SELF_CHECK
12604             // There are n - 2 left temporary tets.
12605             for (j = 1; j < n - 1; j++) {
12606               maketetrahedron(&(tmpabtetlist[j]));
12607               setorg(tmpabtetlist[j], pa);
12608               setdest(tmpabtetlist[j], pb);
12609               setapex(tmpabtetlist[j], p[j]);
12610               setoppo(tmpabtetlist[j], p[j + 1]);
12611             }
12612             // Transfer the element attributes.
12613             for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12614               attrib = elemattribute(abtetlist[0].tet, j);
12615               for (k = 0; k < n - 1; k++) {
12616                 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12617               }
12618             }
12619             // Transfer the volume constraints.
12620             if (b->varvolume && !b->refine) {
12621               volume = volumebound(abtetlist[0].tet);
12622               for (k = 0; k < n - 1; k++) {
12623                 setvolumebound(tmpabtetlist[k].tet, volume);
12624               }
12625             }
12626             // Glue n - 1 internal faces of Star(ab).
12627             for (j = 0; j < n - 1; j++) {
12628               fnext(tmpabtetlist[j], newfront);
12629               bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
12630             }
12631             // Substitute the old tets with the new tets by connecting the
12632             //   new tets to the adjacent tets in the mesh. There are (n-2)
12633             //   * 2 (outer) faces of the new tets need to be operated.
12634             // Note that the old tets still have the pointers to their
12635             //   adjacent tets in the mesh.  These pointers can be re-used
12636             //   to inverse the substitution.
12637             for (j = 2; j < n; j++) {
12638               // Get an old tet: [j]a.b.p_j.p_j-1, (j > 1).
12639               oldfront = abtetlist[(i + j) % n];
12640               esymself(oldfront);
12641               enextfnextself(oldfront);
12642               // Get an adjacent tet at face: [j]a.p_j.p_j-1.
12643               sym(oldfront, adjfront); // adjfront may be dummy.
12644               // Get the corresponding face from the new tets.
12645               // j >= 2.
12646               enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
12647               bond(newfront, adjfront);
12648               if (checksubfaces) {
12649                 tspivot(oldfront, checksh); 
12650                 if (checksh.sh != dummysh) {
12651                   tsbond(newfront, checksh);
12652                 }
12653               }
12654             }
12655             for (j = 2; j < n; j++) {
12656               // Get an old tet: [j]a.b.p_j.p_j-1, (j > 2).
12657               oldfront = abtetlist[(i + j) % n];
12658               esymself(oldfront);
12659               enext2fnextself(oldfront);
12660               // Get an adjacent tet at face: [j]b.p_j.p_j-1.
12661               sym(oldfront, adjfront); // adjfront may be dummy.
12662               // Get the corresponding face from the new tets.
12663               // j >= 2.
12664               enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
12665               bond(newfront, adjfront);
12666               if (checksubfaces) {
12667                 tspivot(oldfront, checksh); 
12668                 if (checksh.sh != dummysh) {
12669                   tsbond(newfront, checksh);
12670                 }
12671               }
12672             }
12673             // Adjust the faces in the temporary new tets at ab for
12674             //   recursively processing on the n-1 tets.
12675             for (j = 0; j < n - 1; j++) {
12676               fnextself(tmpabtetlist[j]);
12677             }
12678             tmpkey2 = -1;
12679             if (key) tmpkey2 = *key;
12680             if ((n - 1) == 3) {
12681               success = removeedgebyflip32(&tmpkey2, tmpabtetlist,
12682                 &(newtetlist[m - 1]), flipque);
12683             } else { // assert((n - 1) >= 4);
12684               success = removeedgebytranNM(&tmpkey2, n - 1, tmpabtetlist,
12685                 &(newtetlist[m - 1]), NULL, NULL, flipque);
12686             }
12687             // No matter it was success or not, delete the temporary tets.
12688             for (j = 0; j < n - 1; j++) {
12689               tetrahedrondealloc(tmpabtetlist[j].tet);
12690             }
12691             if (success) {
12692               // The new configuration is good. 
12693               // Do not delete the old tets.
12694               // for (j = 0; j < n; j++) {
12695               //   tetrahedrondealloc(abtetlist[j].tet);
12696               // }
12697               // Return the bigger dihedral in the two sets of new tets.
12698               if (key != (REAL *) NULL) {
12699                 *key = tmpkey2 < tmpkey ? tmpkey2 : tmpkey;
12700               }
12701               return true;
12702             } else {
12703               // The new configuration is bad, substitue back the old tets.
12704               for (j = 0; j < n; j++) {
12705                 oldfront = abtetlist[(i + j) % n];
12706                 esymself(oldfront);
12707                 enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
12708                 sym(oldfront, adjfront); // adjfront may be dummy.
12709                 bond(oldfront, adjfront);
12710                 if (checksubfaces) {
12711                   tspivot(oldfront, checksh);
12712                   if (checksh.sh != dummysh) {
12713                     tsbond(oldfront, checksh);
12714                   }
12715                 }
12716               }
12717               for (j = 0; j < n; j++) {
12718                 oldfront = abtetlist[(i + j) % n];
12719                 esymself(oldfront);
12720                 enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12721                 sym(oldfront, adjfront); // adjfront may be dummy
12722                 bond(oldfront, adjfront);
12723                 if (checksubfaces) {
12724                   tspivot(oldfront, checksh);
12725                   if (checksh.sh != dummysh) {
12726                     tsbond(oldfront, checksh);
12727                   }
12728                 }
12729               }
12730               // Substitute back the old tets of the first flip.
12731               for (j = 0; j < *n1; j++) {
12732                 oldfront = bftetlist[j];
12733                 esymself(oldfront);
12734                 enextfnextself(oldfront);
12735                 sym(oldfront, adjfront); // adjfront may be dummy.
12736                 bond(oldfront, adjfront);
12737                 if (checksubfaces) {
12738                   tspivot(oldfront, checksh);
12739                   if (checksh.sh != dummysh) {
12740                     tsbond(oldfront, checksh);
12741                   }
12742                 }
12743               }
12744               for (j = 0; j < *n1; j++) {
12745                 oldfront = bftetlist[j];
12746                 esymself(oldfront);
12747                 enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12748                 sym(oldfront, adjfront); // adjfront may be dummy
12749                 bond(oldfront, adjfront);
12750                 if (checksubfaces) {
12751                   tspivot(oldfront, checksh);
12752                   if (checksh.sh != dummysh) {
12753                     tsbond(oldfront, checksh);
12754                   }
12755                 }
12756               }
12757               // Delete the new tets of the first flip. Note that one new
12758               //   tet has already been removed from the list.
12759               for (j = 0; j < m - 1; j++) {
12760                 tetrahedrondealloc(newtetlist[j].tet);
12761               }
12762             } // if (success)
12763           } // if (success)
12764         } // if (doflip)
12765       } // if (ori <= 0.0)
12766     } // for (i = 0; i < n; i++)
12767     // Inverse a and b and the tets configuration.
12768     for (i = 0; i < n; i++) newtetlist[i] = abtetlist[i];
12769     for (i = 0; i < n; i++) {
12770       oldfront = newtetlist[n - i - 1];
12771       esymself(oldfront);
12772       fnextself(oldfront);
12773       abtetlist[i] = oldfront;
12774     }
12775     twice++;
12776   } while (twice < 2);
12777 
12778   return false;
12779 }
12780 
12782 //                                                                           //
12783 // splittetrahedron()    Insert a point into a tetrahedron, split it into    //
12784 //                       four tetrahedra.                                    //
12785 //                                                                           //
12786 // The tetrahedron is given by 'splittet'.  Let it is abcd.  The inserting   //
12787 // point 'newpoint' v should lie strictly inside abcd.                       //
12788 //                                                                           //
12789 // Splitting a tetrahedron is to shrink abcd to abcv,  and create three new  //
12790 // tetrahedra badv, cbdv, and acdv.                                          //
12791 //                                                                           //
12792 // On completion, 'splittet' returns abcv.  If 'flipqueue' is not NULL, it   //
12793 // contains all possibly non-locally Delaunay faces.                         //
12794 //                                                                           //
12796 
12797 void tetgenmesh::splittetrahedron(point newpoint, triface* splittet,
12798   queue* flipqueue)
12799 {
12800   triface oldabd, oldbcd, oldcad;                      // Old configuration.
12801   triface abdcasing, bcdcasing, cadcasing;
12802   face abdsh, bcdsh, cadsh;
12803   triface abcv, badv, cbdv, acdv;                      // New configuration.
12804   triface worktet;
12805   face abseg, bcseg, caseg;
12806   face adseg, bdseg, cdseg;
12807   point pa, pb, pc, pd;
12808   REAL attrib, volume;
12809   int i;
12810 
12811   abcv = *splittet;
12812   abcv.ver = 0;
12813   // Set the changed vertices and new tetrahedron.
12814   pa = org(abcv);
12815   pb = dest(abcv);
12816   pc = apex(abcv);
12817   pd = oppo(abcv);
12818 
12819   if (b->verbose > 1) {
12820     printf("  Inserting point %d in tetrahedron (%d, %d, %d, %d).\n",
12821            pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc),
12822            pointmark(pd));
12823   }
12824 
12825   fnext(abcv, oldabd);
12826   enextfnext(abcv, oldbcd);
12827   enext2fnext(abcv, oldcad);
12828   sym(oldabd, abdcasing);
12829   sym(oldbcd, bcdcasing);
12830   sym(oldcad, cadcasing);
12831   maketetrahedron(&badv);
12832   maketetrahedron(&cbdv);
12833   maketetrahedron(&acdv);
12834 
12835   // Set 'badv' vertices.
12836   setorg (badv, pb);
12837   setdest(badv, pa);
12838   setapex(badv, pd);
12839   setoppo(badv, newpoint);
12840   // Set 'cbdv' vertices.
12841   setorg (cbdv, pc);
12842   setdest(cbdv, pb);
12843   setapex(cbdv, pd);
12844   setoppo(cbdv, newpoint);
12845   // Set 'acdv' vertices.
12846   setorg (acdv, pa);
12847   setdest(acdv, pc);
12848   setapex(acdv, pd);
12849   setoppo(acdv, newpoint);
12850   // Set 'abcv' vertices
12851   setoppo(abcv, newpoint);
12852 
12853   // Set the element attributes of the new tetrahedra.
12854   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12855     attrib = elemattribute(abcv.tet, i);
12856     setelemattribute(badv.tet, i, attrib);
12857     setelemattribute(cbdv.tet, i, attrib);
12858     setelemattribute(acdv.tet, i, attrib);
12859   }
12860   // Set the volume constraint of the new tetrahedra.
12861   if (b->varvolume) {
12862     volume = volumebound(abcv.tet);
12863     setvolumebound(badv.tet, volume);
12864     setvolumebound(cbdv.tet, volume);
12865     setvolumebound(acdv.tet, volume);
12866   }
12867 
12868   // Bond the new triangles to the surrounding tetrahedron.
12869   bond(badv, abdcasing);
12870   bond(cbdv, bcdcasing);
12871   bond(acdv, cadcasing);
12872   // There may exist subfaces need to be bonded to the new tetrahedra.
12873   if (checksubfaces) {
12874     tspivot(oldabd, abdsh);
12875     if (abdsh.sh != dummysh) {
12876       tsdissolve(oldabd);
12877       tsbond(badv, abdsh);
12878     }
12879     tspivot(oldbcd, bcdsh);
12880     if (bcdsh.sh != dummysh) {
12881       tsdissolve(oldbcd);
12882       tsbond(cbdv, bcdsh);
12883     }
12884     tspivot(oldcad, cadsh);
12885     if (cadsh.sh != dummysh) {
12886       tsdissolve(oldcad);
12887       tsbond(acdv, cadsh);
12888     }
12889   } else if (checksubsegs) {
12890     tsspivot1(abcv, abseg);
12891     if (abseg.sh != dummysh) {
12892       tssbond1(badv, abseg);
12893     }
12894     enext(abcv, worktet);
12895     tsspivot1(worktet, bcseg);
12896     if (bcseg.sh != dummysh) {
12897       tssbond1(cbdv, bcseg);
12898     }
12899     enext2(abcv, worktet);
12900     tsspivot1(worktet, caseg);
12901     if (caseg.sh != dummysh) {
12902       tssbond1(acdv, caseg);
12903     }
12904     fnext(abcv, worktet);
12905     enext2self(worktet);
12906     tsspivot1(worktet, adseg);
12907     if (adseg.sh != dummysh) {
12908       tssdissolve1(worktet);
12909       enext(badv, worktet);
12910       tssbond1(worktet, adseg);
12911       enext2(acdv, worktet);
12912       tssbond1(worktet, adseg);
12913     }
12914     enextfnext(abcv, worktet);
12915     enext2self(worktet);
12916     tsspivot1(worktet, bdseg);
12917     if (bdseg.sh != dummysh) {
12918       tssdissolve1(worktet);
12919       enext(cbdv, worktet);
12920       tssbond1(worktet, bdseg);
12921       enext2(badv, worktet);
12922       tssbond1(worktet, bdseg);
12923     }
12924     enext2fnext(abcv, worktet);
12925     enext2self(worktet);
12926     tsspivot1(worktet, cdseg);
12927     if (cdseg.sh != dummysh) {
12928       tssdissolve1(worktet);
12929       enext(acdv, worktet);
12930       tssbond1(worktet, cdseg);
12931       enext2(cbdv, worktet);
12932       tssbond1(worktet, cdseg);
12933     }
12934   }
12935   badv.loc = 3; 
12936   cbdv.loc = 2;
12937   bond(badv, cbdv);
12938   cbdv.loc = 3; 
12939   acdv.loc = 2;
12940   bond(cbdv, acdv);
12941   acdv.loc = 3; 
12942   badv.loc = 2;
12943   bond(acdv, badv);
12944   badv.loc = 1; 
12945   bond(badv, oldabd);
12946   cbdv.loc = 1; 
12947   bond(cbdv, oldbcd);
12948   acdv.loc = 1; 
12949   bond(acdv, oldcad);
12950   
12951   badv.loc = 0;
12952   cbdv.loc = 0;
12953   acdv.loc = 0;
12954   if (b->verbose > 3) {
12955     printf("    Updating abcv ");
12956     printtet(&abcv);
12957     printf("    Creating badv ");
12958     printtet(&badv);
12959     printf("    Creating cbdv ");
12960     printtet(&cbdv);
12961     printf("    Creating acdv ");
12962     printtet(&acdv);
12963   }
12964 
12965   if (flipqueue != (queue *) NULL) {
12966     enqueueflipface(abcv, flipqueue);
12967     enqueueflipface(badv, flipqueue);
12968     enqueueflipface(cbdv, flipqueue);
12969     enqueueflipface(acdv, flipqueue);
12970   }
12971 
12972   // Save a handle for quick point location.
12973   recenttet = abcv;
12974   // Set the return handle be abcv.
12975   *splittet = abcv;
12976 }
12977 
12979 //                                                                           //
12980 // unsplittetrahedron()    Reverse the operation of inserting a point into a //
12981 //                         tetrahedron, so as to remove the newly inserted   //
12982 //                         point from the mesh.                              //
12983 //                                                                           //
12984 // Assume the origional tetrahedron is abcd, it was split by v into four     //
12985 // tetrahedra abcv, badv, cbdv, and acdv. 'splittet' represents face abc of  //
12986 // abcv (i.e., its opposite is v).                                           //
12987 //                                                                           //
12988 // Point v is removed by expanding abcv to abcd, deleting three tetrahedra   //
12989 // badv, cbdv and acdv.  On return, point v is not deleted in this routine.  //
12990 //                                                                           //
12992 
12993 void tetgenmesh::unsplittetrahedron(triface* splittet)
12994 {
12995   triface abcv, badv, cbdv, acdv;
12996   triface oldabv, oldbcv, oldcav;
12997   triface badcasing, cbdcasing, acdcasing;
12998   face badsh, cbdsh, acdsh;
12999 
13000   abcv = *splittet;
13001   adjustedgering(abcv, CCW);  // for sure.
13002   fnext(abcv, oldabv);
13003   fnext(oldabv, badv);
13004   esymself(badv);
13005   enextfnext(abcv, oldbcv);
13006   fnext(oldbcv, cbdv);
13007   esymself(cbdv);
13008   enext2fnext(abcv, oldcav);
13009   fnext(oldcav, acdv);
13010   esymself(acdv);
13011 
13012   if (b->verbose > 1) {
13013     printf("  Removing point %d in tetrahedron (%d, %d, %d, %d).\n",
13014            pointmark(oppo(abcv)), pointmark(org(abcv)), pointmark(dest(abcv)),
13015            pointmark(apex(abcv)), pointmark(apex(badv)));
13016   }
13017 
13018   sym(badv, badcasing);
13019   tspivot(badv, badsh);
13020   sym(cbdv, cbdcasing);
13021   tspivot(cbdv, cbdsh);
13022   sym(acdv, acdcasing);
13023   tspivot(acdv, acdsh);
13024 
13025   // Expanding abcv to abcd.
13026   setoppo(abcv, apex(badv));
13027   bond(oldabv, badcasing);
13028   if (badsh.sh != dummysh) {
13029     tsbond(oldabv, badsh);
13030   }
13031   bond(oldbcv, cbdcasing);
13032   if (cbdsh.sh != dummysh) {
13033     tsbond(oldbcv, cbdsh);
13034   }
13035   bond(oldcav, acdcasing);
13036   if (acdsh.sh != dummysh) {
13037     tsbond(oldcav, acdsh);
13038   }
13039 
13040   // Delete the three split-out tetrahedra.
13041   tetrahedrondealloc(badv.tet);
13042   tetrahedrondealloc(cbdv.tet);
13043   tetrahedrondealloc(acdv.tet);
13044 }
13045 
13047 //                                                                           //
13048 // splittetface()    Insert a point on a face of a mesh.                     //
13049 //                                                                           //
13050 // 'splittet' is the splitting face.  Let it is abcd, where abc is the face  //
13051 // will be split. If abc is not a hull face, abce is the tetrahedron at the  //
13052 // opposite of d.                                                            //
13053 //                                                                           //
13054 // To split face abc by a point v is to shrink the tetrahedra abcd to abvd,  //
13055 // create two new tetrahedra bcvd, cavd.  If abc is not a hull face, shrink  //
13056 // the tetrahedra bace to bave, create two new tetrahedra cbve, acve.        //
13057 //                                                                           //
13058 // If abc is a subface, it is split into three subfaces simultaneously by    //
13059 // calling routine splitsubface(), hence, abv, bcv, cav.  The edge rings of  //
13060 // the split subfaces have the same orientation as abc's.                    //
13061 //                                                                           //
13062 // On completion, 'splittet' returns abvd.  If 'flipqueue' is not NULL, it   //
13063 // contains all possibly non-locally Delaunay faces.                         //
13064 //                                                                           //
13066 
13067 void tetgenmesh::splittetface(point newpoint, triface* splittet,
13068   queue* flipqueue)
13069 {
13070   triface abcd, bace;                                  // Old configuration.
13071   triface oldbcd, oldcad, oldace, oldcbe; 
13072   triface bcdcasing, cadcasing, acecasing, cbecasing;
13073   face abcsh, bcdsh, cadsh, acesh, cbesh;
13074   triface abvd, bcvd, cavd, bave, cbve, acve;          // New configuration.
13075   triface worktet;
13076   face bcseg, caseg;
13077   face adseg, bdseg, cdseg;
13078   face aeseg, beseg, ceseg;
13079   point pa, pb, pc, pd, pe;
13080   REAL attrib, volume;
13081   bool mirrorflag;
13082   int i;
13083 
13084   abcd = *splittet;
13085   // abcd.ver = 0; // Adjust to be CCW edge ring.
13086   adjustedgering(abcd, CCW);
13087   pa = org(abcd);
13088   pb = dest(abcd);
13089   pc = apex(abcd);
13090   pd = oppo(abcd);
13091   pe = (point) NULL; // avoid a compile warning.
13092   // Is there a second tetrahderon?
13093   mirrorflag = issymexist(&abcd);
13094   if (mirrorflag) {
13095     // This is an interior face.
13096     sym(abcd, bace);
13097     findedge(&bace, dest(abcd), org(abcd));
13098     pe = oppo(bace);
13099   }
13100   if (checksubfaces) {
13101     // Is there a subface need to be split together?
13102     tspivot(abcd, abcsh);
13103     if (abcsh.sh != dummysh) {
13104       // Exists! Keep the edge ab of both handles be the same.
13105       findedge(&abcsh, org(abcd), dest(abcd));
13106     }
13107   }
13108 
13109   if (b->verbose > 1) {
13110     printf("  Inserting point %d on face (%d, %d, %d).\n", pointmark(newpoint),
13111            pointmark(pa), pointmark(pb), pointmark(pc));
13112   }
13113 
13114   // Save the old configuration at faces bcd and cad.
13115   enextfnext(abcd, oldbcd);
13116   enext2fnext(abcd, oldcad);
13117   sym(oldbcd, bcdcasing);
13118   sym(oldcad, cadcasing);
13119   // Create two new tetrahedra.
13120   maketetrahedron(&bcvd);
13121   maketetrahedron(&cavd);
13122   if (mirrorflag) {
13123     // Save the old configuration at faces bce and cae.
13124     enextfnext(bace, oldace);
13125     enext2fnext(bace, oldcbe);
13126     sym(oldace, acecasing);
13127     sym(oldcbe, cbecasing);
13128     // Create two new tetrahedra.
13129     maketetrahedron(&acve);
13130     maketetrahedron(&cbve);
13131   } else {
13132     // Splitting a boundary face increases the number of boundary faces.
13133     hullsize += 2;
13134   }
13135 
13136   // Set vertices to the changed tetrahedron and new tetrahedra.
13137   abvd = abcd;  // Update 'abcd' to 'abvd'.
13138   setapex(abvd, newpoint);
13139   setorg (bcvd, pb);  // Set 'bcvd'.
13140   setdest(bcvd, pc);
13141   setapex(bcvd, newpoint);
13142   setoppo(bcvd, pd);
13143   setorg (cavd, pc);  // Set 'cavd'.
13144   setdest(cavd, pa);
13145   setapex(cavd, newpoint);
13146   setoppo(cavd, pd);
13147   // Set the element attributes of the new tetrahedra.
13148   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13149     attrib = elemattribute(abvd.tet, i);
13150     setelemattribute(bcvd.tet, i, attrib);
13151     setelemattribute(cavd.tet, i, attrib);
13152   }
13153   if (b->varvolume) {
13154     // Set the area constraint of the new tetrahedra.
13155     volume = volumebound(abvd.tet);
13156     setvolumebound(bcvd.tet, volume);
13157     setvolumebound(cavd.tet, volume);
13158   }
13159   if (mirrorflag) {
13160     bave = bace;  // Update 'bace' to 'bave'.
13161     setapex(bave, newpoint);
13162     setorg (acve, pa);  // Set 'acve'.
13163     setdest(acve, pc);
13164     setapex(acve, newpoint);
13165     setoppo(acve, pe);
13166     setorg (cbve, pc);  // Set 'cbve'.
13167     setdest(cbve, pb);
13168     setapex(cbve, newpoint);
13169     setoppo(cbve, pe);
13170     // Set the element attributes of the new tetrahedra.
13171     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13172       attrib = elemattribute(bave.tet, i);
13173       setelemattribute(acve.tet, i, attrib);
13174       setelemattribute(cbve.tet, i, attrib);
13175     }
13176     if (b->varvolume) {
13177       // Set the area constraint of the new tetrahedra.
13178       volume = volumebound(bave.tet);
13179       setvolumebound(acve.tet, volume);
13180       setvolumebound(cbve.tet, volume);
13181     }
13182   }
13183 
13184   // Bond the new tetrahedra to the surrounding tetrahedra.
13185   bcvd.loc = 1;
13186   bond(bcvd, bcdcasing); 
13187   cavd.loc = 1;
13188   bond(cavd, cadcasing); 
13189   bcvd.loc = 3;
13190   bond(bcvd, oldbcd);
13191   cavd.loc = 2;
13192   bond(cavd, oldcad);
13193   bcvd.loc = 2;
13194   cavd.loc = 3;
13195   bond(bcvd, cavd);  
13196   if (mirrorflag) {
13197     acve.loc = 1;
13198     bond(acve, acecasing);
13199     cbve.loc = 1;
13200     bond(cbve, cbecasing);
13201     acve.loc = 3;
13202     bond(acve, oldace);
13203     cbve.loc = 2;
13204     bond(cbve, oldcbe);
13205     acve.loc = 2;
13206     cbve.loc = 3;
13207     bond(acve, cbve);
13208     // Bond two new coplanar facets.
13209     bcvd.loc = 0;
13210     cbve.loc = 0;
13211     bond(bcvd, cbve);
13212     cavd.loc = 0;
13213     acve.loc = 0;
13214     bond(cavd, acve);
13215   }
13216 
13217   // There may exist subface needed to be bonded to the new tetrahedra.
13218   if (checksubfaces) {
13219     tspivot(oldbcd, bcdsh);
13220     if (bcdsh.sh != dummysh) {
13221       tsdissolve(oldbcd);
13222       bcvd.loc = 1;
13223       tsbond(bcvd, bcdsh);
13224     }
13225     tspivot(oldcad, cadsh);
13226     if (cadsh.sh != dummysh) {
13227       tsdissolve(oldcad);
13228       cavd.loc = 1;
13229       tsbond(cavd, cadsh);
13230     }
13231     if (mirrorflag) {
13232       tspivot(oldace, acesh);
13233       if (acesh.sh != dummysh) {
13234         tsdissolve(oldace);
13235         acve.loc = 1;
13236         tsbond(acve, acesh);
13237       }
13238       tspivot(oldcbe, cbesh);
13239       if (cbesh.sh != dummysh) {
13240         tsdissolve(oldcbe);
13241         cbve.loc = 1;
13242         tsbond(cbve, cbesh);
13243       }
13244     }
13245     // Is there a subface needs to be split together?
13246     if (abcsh.sh != dummysh) {
13247       // Split this subface 'abc' into three i.e, abv, bcv, cav.
13248       splitsubface(newpoint, &abcsh, (queue *) NULL);
13249     }  
13250   } else if (checksubsegs) {
13251     // abvd.loc = abvd.ver = 0;
13252     bcvd.loc = bcvd.ver = 0;
13253     cavd.loc = cavd.ver = 0;
13254     if (mirrorflag) {
13255       // bave.loc = bave.ver = 0;
13256       cbve.loc = cbve.ver = 0;
13257       acve.loc = acve.ver = 0;
13258     }
13259     enext(abvd, worktet);
13260     tsspivot1(worktet, bcseg);
13261     if (bcseg.sh != dummysh) {
13262       tssdissolve1(worktet);
13263       tssbond1(bcvd, bcseg);
13264       if (mirrorflag) {
13265         enext2(bave, worktet);
13266         tssdissolve1(worktet);
13267         tssbond1(cbve, bcseg);
13268       }
13269     }
13270     enext2(abvd, worktet);
13271     tsspivot1(worktet, caseg);
13272     if (caseg.sh != dummysh) {
13273       tssdissolve1(worktet);
13274       tssbond1(cavd, caseg);
13275       if (mirrorflag) {
13276         enext(bave, worktet);
13277         tssdissolve1(worktet);
13278         tssbond1(acve, caseg);
13279       }
13280     }
13281     fnext(abvd, worktet);
13282     enext2self(worktet);
13283     tsspivot1(worktet, adseg);
13284     if (adseg.sh != dummysh) {
13285       fnext(cavd, worktet);
13286       enextself(worktet);
13287       tssbond1(worktet, adseg);
13288     }
13289     fnext(abvd, worktet);
13290     enextself(worktet);
13291     tsspivot1(worktet, bdseg);
13292     if (bdseg.sh != dummysh) {
13293       fnext(bcvd, worktet);
13294       enext2self(worktet);
13295       tssbond1(worktet, bdseg);
13296     }
13297     enextfnext(abvd, worktet);
13298     enextself(worktet);
13299     tsspivot1(worktet, cdseg);
13300     if (cdseg.sh != dummysh) {
13301       tssdissolve1(worktet);
13302       fnext(bcvd, worktet);
13303       enextself(worktet);
13304       tssbond1(worktet, cdseg);
13305       fnext(cavd, worktet);
13306       enext2self(worktet);
13307       tssbond1(worktet, cdseg);
13308     }
13309     if (mirrorflag) {
13310       fnext(bave, worktet);
13311       enextself(worktet);
13312       tsspivot1(worktet, aeseg);
13313       if (aeseg.sh != dummysh) {
13314         fnext(acve, worktet);
13315         enext2self(worktet);
13316         tssbond1(worktet, aeseg);
13317       }
13318       fnext(bave, worktet);
13319       enext2self(worktet);
13320       tsspivot1(worktet, beseg);
13321       if (beseg.sh != dummysh) {
13322         fnext(cbve, worktet);
13323         enextself(worktet);
13324         tssbond1(worktet, beseg);
13325       }
13326       enextfnext(bave, worktet);
13327       enextself(worktet);
13328       tsspivot1(worktet, ceseg);
13329       if (ceseg.sh != dummysh) {
13330         tssdissolve1(worktet);
13331         fnext(cbve, worktet);
13332         enext2self(worktet);
13333         tssbond1(worktet, ceseg);
13334         fnext(acve, worktet);
13335         enextself(worktet);
13336         tssbond1(worktet, ceseg);
13337       }
13338     }
13339   }
13340 
13341   // Save a handle for quick point location.
13342   recenttet = abvd;
13343   // Set the return handle be abvd.
13344   *splittet = abvd;
13345 
13346   bcvd.loc = 0;
13347   cavd.loc = 0;
13348   if (mirrorflag) {
13349     cbve.loc = 0;
13350     acve.loc = 0;
13351   }
13352   if (b->verbose > 3) {
13353     printf("    Updating abvd ");
13354     printtet(&abvd);
13355     printf("    Creating bcvd ");
13356     printtet(&bcvd);
13357     printf("    Creating cavd ");
13358     printtet(&cavd);
13359     if (mirrorflag) {
13360       printf("    Updating bave ");
13361       printtet(&bave);
13362       printf("    Creating cbve ");
13363       printtet(&cbve);
13364       printf("    Creating acve ");
13365       printtet(&acve);
13366     }
13367   }
13368 
13369   if (flipqueue != (queue *) NULL) {
13370     fnextself(abvd);
13371     enqueueflipface(abvd, flipqueue);
13372     fnextself(bcvd);
13373     enqueueflipface(bcvd, flipqueue);
13374     fnextself(cavd);
13375     enqueueflipface(cavd, flipqueue);
13376     if (mirrorflag) {
13377       fnextself(bave);
13378       enqueueflipface(bave, flipqueue);
13379       fnextself(cbve);
13380       enqueueflipface(cbve, flipqueue);
13381       fnextself(acve);
13382       enqueueflipface(acve, flipqueue);
13383     }
13384   }
13385 }
13386 
13388 //                                                                           //
13389 // unsplittetface()    Reverse the operation of inserting a point on a face, //
13390 //                     so as to remove the newly inserted point.             //
13391 //                                                                           //
13392 // Assume the original face is abc, the tetrahedron containing abc is abcd.  //
13393 // If abc is not a hull face, bace is the tetrahedron at the opposite of d.  //
13394 // After face abc was split by a point v, tetrahedron abcd had been split    //
13395 // into three tetrahedra, abvd, bcvd, cavd, and bace (if it exists) had been //
13396 // split into bave, cbve, acve. 'splittet' represents abvd (its apex is v).  //
13397 //                                                                           //
13398 // Point v is removed by expanding abvd to abcd, deleting two tetrahedra     //
13399 // bcvd, cavd. Expanding bave(if it exists) to bace, deleting two tetrahedra //
13400 // cbve, acve.  If abv is a subface, routine unsplitsubface() will be called //
13401 // to reverse the operation of splitting a subface. On completion, point v   //
13402 // is not deleted in this routine.                                           //
13403 //                                                                           //
13405 
13406 void tetgenmesh::unsplittetface(triface* splittet)
13407 {
13408   triface abvd, bcvd, cavd, bave, cbve, acve;
13409   triface oldbvd, oldvad, oldvbe, oldave;
13410   triface bcdcasing, cadcasing, cbecasing, acecasing;
13411   face bcdsh, cadsh, cbesh, acesh;
13412   face abvsh;
13413   bool mirrorflag;
13414 
13415   abvd = *splittet;
13416   adjustedgering(abvd, CCW); // for sure.
13417   enextfnext(abvd, oldbvd);
13418   fnext(oldbvd, bcvd);
13419   esymself(bcvd);
13420   enextself(bcvd);
13421   enext2fnext(abvd, oldvad);
13422   fnext(oldvad, cavd);
13423   esymself(cavd);
13424   enext2self(cavd);
13425   // Is there a second tetrahedron?
13426   sym(abvd, bave);
13427   mirrorflag = bave.tet != dummytet;
13428   if (mirrorflag) {
13429     findedge(&bave, dest(abvd), org(abvd));
13430     enextfnext(bave, oldave);  
13431     fnext(oldave, acve);
13432     esymself(acve);
13433     enextself(acve);
13434     enext2fnext(bave, oldvbe);  
13435     fnext(oldvbe, cbve);
13436     esymself(cbve);
13437     enext2self(cbve);
13438   } else {
13439     // Unsplit a hull face decrease the number of boundary faces.
13440     hullsize -= 2;
13441   }
13442   // Is there a subface at abv.
13443   tspivot(abvd, abvsh);
13444   if (abvsh.sh != dummysh) {
13445     // Exists! Keep the edge ab of both handles be the same.
13446     findedge(&abvsh, org(abvd), dest(abvd));
13447   }
13448 
13449   if (b->verbose > 1) {
13450     printf("  Removing point %d on face (%d, %d, %d).\n",
13451            pointmark(apex(abvd)), pointmark(org(abvd)), pointmark(dest(abvd)),
13452            pointmark(dest(bcvd)));
13453   }
13454 
13455   fnextself(bcvd); // bcvd has changed to bcdv.
13456   sym(bcvd, bcdcasing);
13457   tspivot(bcvd, bcdsh);
13458   fnextself(cavd); // cavd has changed to cadv.
13459   sym(cavd, cadcasing);
13460   tspivot(cavd, cadsh);
13461   if (mirrorflag) {
13462     fnextself(acve); // acve has changed to acev.
13463     sym(acve, acecasing);
13464     tspivot(acve, acesh);
13465     fnextself(cbve); // cbve has changed to cbev.
13466     sym(cbve, cbecasing);
13467     tspivot(cbve, cbesh);
13468   }
13469 
13470   // Expand abvd to abcd.
13471   setapex(abvd, dest(bcvd));
13472   bond(oldbvd, bcdcasing);
13473   if (bcdsh.sh != dummysh) {
13474     tsbond(oldbvd, bcdsh);
13475   }
13476   bond(oldvad, cadcasing);
13477   if (cadsh.sh != dummysh) {
13478     tsbond(oldvad, cadsh);
13479   }
13480   if (mirrorflag) {
13481     // Expanding bave to bace.
13482     setapex(bave, dest(acve));
13483     bond(oldave, acecasing);
13484     if (acesh.sh != dummysh) {
13485       tsbond(oldave, acesh);
13486     }
13487     bond(oldvbe, cbecasing);
13488     if (cbesh.sh != dummysh) {
13489       tsbond(oldvbe, cbesh);
13490     }
13491   }
13492 
13493   // Unsplit a subface if there exists.
13494   if (abvsh.sh != dummysh) {
13495     unsplitsubface(&abvsh);
13496   }
13497 
13498   // Delete the split-out tetrahedra.
13499   tetrahedrondealloc(bcvd.tet);
13500   tetrahedrondealloc(cavd.tet);
13501   if (mirrorflag) {
13502     tetrahedrondealloc(acve.tet);
13503     tetrahedrondealloc(cbve.tet);
13504   }
13505 }
13506 
13508 //                                                                           //
13509 // splitsubface()    Insert a point on a subface, split it into three.       //
13510 //                                                                           //
13511 // The subface is 'splitface'.  Let it is abc. The inserting point 'newpoint'//
13512 // v should lie inside abc.  If the neighbor tetrahedra of abc exist, i.e.,  //
13513 // abcd and bace, they should have been split by routine splittetface()      //
13514 // before calling this routine, so the connection between the new tetrahedra //
13515 // and new subfaces can be correctly set.                                    //
13516 //                                                                           //
13517 // To split subface abc by point v is to shrink abc to abv, create two new   //
13518 // subfaces bcv and cav.  Set the connection between updated and new created //
13519 // subfaces. If there is a subsegment at edge bc or ca, connection of new    //
13520 // subface (bcv or cav) to its casing subfaces is a face link, 'casingin' is //
13521 // the predecessor and 'casingout' is the successor. It is important to keep //
13522 // the orientations of the edge rings of the updated and created subfaces be //
13523 // the same as abc's. So they have the same orientation as other subfaces of //
13524 // this facet with respect to the lift point of this facet.                  //
13525 //                                                                           //
13526 // On completion, 'splitface' returns abv.  If 'flipqueue' is not NULL, it   //
13527 // returns all possibly non-Delaunay edges.                                  //
13528 //                                                                           //
13530 
13531 void tetgenmesh::splitsubface(point newpoint, face* splitface,
13532   queue* flipqueue)
13533 {
13534   triface abvd, bcvd, cavd, bave, cbve, acve;
13535   face abc, oldbc, oldca, bc, ca, spinsh;
13536   face bccasin, bccasout, cacasin, cacasout;
13537   face abv, bcv, cav;
13538   point pa, pb, pc;
13539   
13540   abc = *splitface;
13541   // The newly created subfaces will have the same edge ring as abc.
13542   adjustedgering(abc, CCW);
13543   pa = sorg(abc);
13544   pb = sdest(abc);
13545   pc = sapex(abc);
13546 
13547   if (b->verbose > 1) {
13548     printf("  Inserting point %d on subface (%d, %d, %d).\n",
13549            pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc));
13550   }
13551 
13552   // Save the old configuration at edge bc and ca.  Subsegments may appear
13553   //   at both sides, save the face links and dissolve them.
13554   senext(abc, oldbc);
13555   senext2(abc, oldca);
13556   spivot(oldbc, bccasout);
13557   sspivot(oldbc, bc);
13558   if (bc.sh != dummysh) {
13559     if (oldbc.sh != bccasout.sh) {
13560       // 'oldbc' is not self-bonded.
13561       spinsh = bccasout;
13562       do {
13563         bccasin = spinsh;
13564         spivotself(spinsh);
13565       } while (spinsh.sh != oldbc.sh);
13566     } else {
13567       bccasout.sh = dummysh;
13568     }
13569     ssdissolve(oldbc);
13570   } 
13571   spivot(oldca, cacasout);
13572   sspivot(oldca, ca);
13573   if (ca.sh != dummysh) {
13574     if (oldca.sh != cacasout.sh) {
13575       // 'oldca' is not self-bonded.
13576       spinsh = cacasout;
13577       do {
13578         cacasin = spinsh;
13579         spivotself(spinsh);
13580       } while (spinsh.sh != oldca.sh);
13581     } else {
13582       cacasout.sh = dummysh;
13583     }
13584     ssdissolve(oldca);
13585   }
13586   // Create two new subfaces.
13587   makeshellface(subfaces, &bcv);
13588   makeshellface(subfaces, &cav);
13589 
13590   // Set the vertices of changed and new subfaces.
13591   abv = abc;  // Update 'abc' to 'abv'.
13592   setsapex(abv, newpoint);
13593   setsorg(bcv, pb);  // Set 'bcv'.
13594   setsdest(bcv, pc);
13595   setsapex(bcv, newpoint);
13596   setsorg(cav, pc);  // Set 'cav'.
13597   setsdest(cav, pa);
13598   setsapex(cav, newpoint);
13599   if (b->quality && varconstraint) {
13600     // Copy yhr area bound into the new subfaces.
13601     setareabound(bcv, areabound(abv));
13602     setareabound(cav, areabound(abv));
13603   }
13604   // Copy the boundary mark into the new subfaces.
13605   setshellmark(bcv, shellmark(abv));
13606   setshellmark(cav, shellmark(abv));  
13607   // Copy the subface type into the new subfaces.
13608   setshelltype(bcv, shelltype(abv));
13609   setshelltype(cav, shelltype(abv));
13610   if (checkpbcs) {
13611     // Copy the pbcgroup into the new subfaces.
13612     setshellpbcgroup(bcv, shellpbcgroup(abv));
13613     setshellpbcgroup(cav, shellpbcgroup(abv));
13614   }
13615   // Bond the new subfaces to the surrounding subfaces.
13616   if (bc.sh != dummysh) {
13617     if (bccasout.sh != dummysh) {
13618       sbond1(bccasin, bcv);
13619       sbond1(bcv, bccasout);
13620     } else {
13621       // Bond 'bcv' to itsself.
13622       sbond(bcv, bcv);
13623     }
13624     ssbond(bcv, bc);
13625   } else {
13626     sbond(bcv, bccasout);
13627   }
13628   if (ca.sh != dummysh) {
13629     if (cacasout.sh != dummysh) {
13630       sbond1(cacasin, cav);
13631       sbond1(cav, cacasout);
13632     } else {
13633       // Bond 'cav' to itself.
13634       sbond(cav, cav);
13635     }
13636     ssbond(cav, ca);
13637   } else {
13638     sbond(cav, cacasout);
13639   }
13640   senext2self(bcv);
13641   sbond(bcv, oldbc);
13642   senextself(cav);
13643   sbond(cav, oldca);
13644   senext2self(bcv);
13645   senextself(cav);
13646   sbond(bcv, cav);
13647 
13648   // Bond the new subfaces to the new tetrahedra if they exist.
13649   stpivot(abv, abvd);
13650   if (abvd.tet != dummytet) {
13651     // Get two new tetrahedra and their syms.
13652     findedge(&abvd, sorg(abv), sdest(abv));
13653     enextfnext(abvd, bcvd);
13654 #ifdef SELF_CHECK
13655     assert(bcvd.tet != dummytet);
13656 #endif
13657     fnextself(bcvd);
13658     enext2fnext(abvd, cavd);
13659 #ifdef SELF_CHECK
13660     assert(cavd.tet != dummytet);
13661 #endif
13662     fnextself(cavd);
13663     // Bond two new subfaces to the two new tetrahedra.
13664     tsbond(bcvd, bcv);
13665     tsbond(cavd, cav);
13666   }
13667   // Set the connection at the other sides if the tetrahedra exist.
13668   sesymself(abv);  // bav
13669   stpivot(abv, bave);
13670   if (bave.tet != dummytet) {
13671     sesymself(bcv);  // cbv
13672     sesymself(cav);  // acv
13673     // Get two new tetrahedra and their syms.
13674     findedge(&bave, sorg(abv), sdest(abv));
13675     enextfnext(bave, acve);
13676 #ifdef SELF_CHECK
13677     assert(acve.tet != dummytet);
13678 #endif
13679     fnextself(acve);
13680     enext2fnext(bave, cbve);
13681 #ifdef SELF_CHECK
13682     assert(cbve.tet != dummytet);
13683 #endif
13684     fnextself(cbve);
13685     // Bond two new subfaces to the two new tetrahedra.
13686     tsbond(acve, cav);
13687     tsbond(cbve, bcv);
13688   }
13689 
13690   bcv.shver = 0;
13691   cav.shver = 0;
13692   if (b->verbose > 3) {
13693     printf("    Updating abv ");
13694     printsh(&abv);
13695     printf("    Creating bcv ");
13696     printsh(&bcv);
13697     printf("    Creating cav ");
13698     printsh(&cav);
13699   }
13700 
13701   if (flipqueue != (queue *) NULL) {
13702     enqueueflipedge(abv, flipqueue);
13703     enqueueflipedge(bcv, flipqueue);
13704     enqueueflipedge(cav, flipqueue);
13705   }
13706 
13707   // Set the return handle be abv.
13708   *splitface = abv;
13709 }
13710 
13712 //                                                                           //
13713 // unsplitsubface()    Reverse the operation of inserting a point on a       //
13714 //                     subface, so as to remove the newly inserted point.    //
13715 //                                                                           //
13716 // Assume the original subface is abc, it was split by a point v into three  //
13717 // subfaces abv, bcv and cav.  'splitsh' represents abv.                     //
13718 //                                                                           //
13719 // To remove point v is to expand abv to abc, delete bcv and cav. If edge bc //
13720 // or ca is a subsegment,  the connection at a subsegment is a subface link, //
13721 // '-casin' and '-casout' are used to save the predecessor and successor of  //
13722 // bcv or cav.  On completion, point v is not deleted in this routine.       //
13723 //                                                                           //
13725 
13726 void tetgenmesh::unsplitsubface(face* splitsh)
13727 {
13728   face abv, bcv, cav;
13729   face oldbv, oldva, bc, ca, spinsh;
13730   face bccasin, bccasout, cacasin, cacasout;
13731 
13732   abv = *splitsh;
13733   senext(abv, oldbv);
13734   spivot(oldbv, bcv);
13735   if (sorg(bcv) != sdest(oldbv)) {
13736     sesymself(bcv);
13737   }
13738   senextself(bcv);
13739   senext2(abv, oldva);
13740   spivot(oldva, cav);
13741   if (sorg(cav) != sdest(oldva)) {
13742     sesymself(cav);
13743   }
13744   senext2self(cav);
13745 
13746   if (b->verbose > 1) {
13747     printf("  Removing point %d on subface (%d, %d, %d).\n",
13748            pointmark(sapex(abv)), pointmark(sorg(abv)), pointmark(sdest(abv)),
13749            pointmark(sdest(bcv)));
13750   }
13751 
13752   spivot(bcv, bccasout);
13753   sspivot(bcv, bc);
13754   if (bc.sh != dummysh) {
13755     if (bcv.sh != bccasout.sh) {
13756       // 'bcv' is not self-bonded.
13757       spinsh = bccasout;
13758       do {
13759         bccasin = spinsh;
13760         spivotself(spinsh);
13761       } while (spinsh.sh != bcv.sh);
13762     } else {
13763       bccasout.sh = dummysh;
13764     }
13765   }
13766   spivot(cav, cacasout);
13767   sspivot(cav, ca);
13768   if (ca.sh != dummysh) {
13769     if (cav.sh != cacasout.sh) {
13770       // 'cav' is not self-bonded.
13771       spinsh = cacasout;
13772       do {
13773        cacasin = spinsh;
13774        spivotself(spinsh);
13775       } while (spinsh.sh != cav.sh);
13776     } else {
13777       cacasout.sh = dummysh;
13778     }
13779   }
13780 
13781   // Expand abv to abc.
13782   setsapex(abv, sdest(bcv));
13783   if (bc.sh != dummysh) {
13784     if (bccasout.sh != dummysh) {
13785       sbond1(bccasin, oldbv);
13786       sbond1(oldbv, bccasout);
13787     } else {
13788       // Bond 'oldbv' to itself.
13789       sbond(oldbv, oldbv);
13790     }
13791     ssbond(oldbv, bc);
13792   } else {
13793     sbond(oldbv, bccasout);
13794   } 
13795   if (ca.sh != dummysh) {
13796     if (cacasout.sh != dummysh) {
13797       sbond1(cacasin, oldva);
13798       sbond1(oldva, cacasout);
13799     } else {
13800       // Bond 'oldva' to itself.
13801       sbond(oldva, oldva);
13802     }
13803     ssbond(oldva, ca);
13804   } else {
13805     sbond(oldva, cacasout);
13806   }
13807 
13808   // Delete two split-out subfaces.
13809   shellfacedealloc(subfaces, bcv.sh);
13810   shellfacedealloc(subfaces, cav.sh);
13811 }
13812 
13814 //                                                                           //
13815 // splittetedge()    Insert a point on an edge of the mesh.                  //
13816 //                                                                           //
13817 // The edge is given by 'splittet'. Assume its four corners are a, b, n1 and //
13818 // n2, where ab is the edge will be split. Around ab may exist any number of //
13819 // tetrahedra. For convenience, they're ordered in a sequence following the  //
13820 // right-hand rule with your thumb points from a to b. Let the vertex set of //
13821 // these tetrahedra be {a, b, n1, n2, ..., n(i)}. NOTE the tetrahedra around //
13822 // ab may not connect to each other (can only happen when ab is a subsegment,//
13823 // hence some faces abn(i) are subfaces).  If ab is a subsegment, abn1 must  //
13824 // be a subface.                                                             //
13825 //                                                                           //
13826 // To split edge ab by a point v is to split all tetrahedra containing ab by //
13827 // v.  More specifically, for each such tetrahedron, an1n2b, it is shrunk to //
13828 // an1n2v, and a new tetrahedra bn2n1v is created. If ab is a subsegment, or //
13829 // some faces of the splitting tetrahedra are subfaces, they must be split   //
13830 // either by calling routine 'splitsubedge()'.                               //
13831 //                                                                           //
13832 // On completion, 'splittet' returns avn1n2.  If 'flipqueue' is not NULL, it //
13833 // returns all faces which may become non-Delaunay after this operation.     //
13834 //                                                                           //
13836 
13837 void tetgenmesh::splittetedge(point newpoint, triface* splittet,
13838   queue* flipqueue)
13839 {
13840   triface *bots, *newtops;
13841   triface oldtop, topcasing;
13842   triface spintet, tmpbond0, tmpbond1;
13843   face abseg, splitsh, topsh, spinsh;
13844   triface worktet;
13845   face n1n2seg, n2vseg, n1vseg;
13846   point pa, pb, n1, n2;
13847   REAL attrib, volume;
13848   int wrapcount, hitbdry;
13849   int i, j;
13850 
13851   if (checksubfaces) {
13852     // Is there a subsegment need to be split together?
13853     tsspivot(splittet, &abseg);
13854     if (abseg.sh != dummysh) {
13855       abseg.shver = 0;
13856       // Orient the edge direction of 'splittet' be abseg.
13857       if (org(*splittet) != sorg(abseg)) {
13858         esymself(*splittet);
13859       }
13860     }
13861   } 
13862   spintet = *splittet;
13863   pa = org(spintet);
13864   pb = dest(spintet);
13865 
13866   if (b->verbose > 1) {
13867     printf("  Inserting point %d on edge (%d, %d).\n", 
13868            pointmark(newpoint), pointmark(pa), pointmark(pb));
13869   }
13870 
13871   // Collect the tetrahedra containing the splitting edge (ab).
13872   n1 = apex(spintet);
13873   hitbdry = 0;
13874   wrapcount = 1;
13875   if (checksubfaces && abseg.sh != dummysh) {
13876     // It may happen that some tetrahedra containing ab (a subsegment) are
13877     //   completely disconnected with others. If it happens, use the face
13878     //   link of ab to cross the boundary. 
13879     while (true) {
13880       if (!fnextself(spintet)) {
13881         // Meet a boundary, walk through it.
13882         hitbdry ++;
13883         tspivot(spintet, spinsh);
13884 #ifdef SELF_CHECK
13885         assert(spinsh.sh != dummysh);
13886 #endif
13887         findedge(&spinsh, pa, pb);
13888         sfnextself(spinsh);
13889         stpivot(spinsh, spintet);
13890 #ifdef SELF_CHECK
13891         assert(spintet.tet != dummytet);
13892 #endif
13893         findedge(&spintet, pa, pb);
13894         // Remember this position (hull face) in 'splittet'.
13895         *splittet = spintet;
13896         // Split two hull faces increase the hull size;
13897         hullsize += 2;
13898       }
13899       if (apex(spintet) == n1) break;
13900       wrapcount ++;
13901     }
13902     if (hitbdry > 0) {
13903       wrapcount -= hitbdry;
13904     }
13905   } else {
13906     // All the tetrahedra containing ab are connected together. If there
13907     //   are subfaces, 'splitsh' keeps one of them.
13908     splitsh.sh = dummysh;
13909     while (hitbdry < 2) {
13910       if (checksubfaces && splitsh.sh == dummysh) {
13911         tspivot(spintet, splitsh);
13912       }
13913       if (fnextself(spintet)) {
13914         if (apex(spintet) == n1) break;
13915         wrapcount++;
13916       } else {
13917         hitbdry ++;
13918         if (hitbdry < 2) {
13919           esym(*splittet, spintet);
13920         }
13921       }
13922     }
13923     if (hitbdry > 0) {
13924       // ab is on the hull.
13925       wrapcount -= 1;
13926       // 'spintet' now is a hull face, inverse its edge direction.
13927       esym(spintet, *splittet);
13928       // Split two hull faces increases the number of hull faces.
13929       hullsize += 2;
13930     }
13931   }
13932   
13933   // Make arrays of updating (bot, oldtop) and new (newtop) tetrahedra.
13934   bots = new triface[wrapcount];
13935   newtops = new triface[wrapcount];
13936   // Spin around ab, gather tetrahedra and set up new tetrahedra. 
13937   spintet = *splittet;
13938   for (i = 0; i < wrapcount; i++) {
13939     // Get 'bots[i] = an1n2b'.
13940     enext2fnext(spintet, bots[i]);
13941     esymself(bots[i]);
13942     // Create 'newtops[i]'.
13943     maketetrahedron(&(newtops[i]));
13944     // Go to the next.
13945     fnextself(spintet);
13946     if (checksubfaces && abseg.sh != dummysh) {
13947       if (!issymexist(&spintet)) {
13948         // We meet a hull face, walk through it.
13949         tspivot(spintet, spinsh);
13950 #ifdef SELF_CHECK
13951         assert(spinsh.sh != dummysh);
13952 #endif
13953         findedge(&spinsh, pa, pb);
13954         sfnextself(spinsh);
13955         stpivot(spinsh, spintet);
13956 #ifdef SELF_CHECK
13957         assert(spintet.tet != dummytet);
13958 #endif
13959         findedge(&spintet, pa, pb);
13960       }
13961     }
13962   }
13963   
13964   // Set the vertices of updated and new tetrahedra.
13965   for (i = 0; i < wrapcount; i++) {
13966     // Update 'bots[i] = an1n2v'.
13967     setoppo(bots[i], newpoint);
13968     // Set 'newtops[i] = bn2n1v'.
13969     n1 = dest(bots[i]);
13970     n2 = apex(bots[i]);
13971     // Set 'newtops[i]'.
13972     setorg(newtops[i], pb);
13973     setdest(newtops[i], n2);
13974     setapex(newtops[i], n1);
13975     setoppo(newtops[i], newpoint);
13976     // Set the element attributes of a new tetrahedron.
13977     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
13978       attrib = elemattribute(bots[i].tet, j);
13979       setelemattribute(newtops[i].tet, j, attrib);
13980     }
13981     if (b->varvolume) {
13982       // Set the area constraint of a new tetrahedron.
13983       volume = volumebound(bots[i].tet);
13984       setvolumebound(newtops[i].tet, volume);
13985     }
13986 #ifdef SELF_CHECK
13987     // Make sure no inversed tetrahedron has been created.
13988     // volume = orient3d(pa, n1, n2, newpoint);
13989     // if (volume >= 0.0) {
13990     //   printf("Internal error in splittetedge(): volume = %.12g.\n", volume);
13991     // }
13992     // volume = orient3d(pb, n2, n1, newpoint);
13993     // if (volume >= 0.0) {
13994     //   printf("Internal error in splittetedge(): volume = %.12g.\n", volume);
13995     // }
13996 #endif
13997   }
13998 
13999   // Bond newtops to topcasings and bots.
14000   for (i = 0; i < wrapcount; i++) {
14001     // Get 'oldtop = n1n2va' from 'bots[i]'.
14002     enextfnext(bots[i], oldtop);
14003     sym(oldtop, topcasing);
14004     bond(newtops[i], topcasing);
14005     if (checksubfaces) {
14006       tspivot(oldtop, topsh);
14007       if (topsh.sh != dummysh) {
14008         tsdissolve(oldtop);
14009         tsbond(newtops[i], topsh);
14010       }
14011     }
14012     enextfnext(newtops[i], tmpbond0);
14013     bond(oldtop, tmpbond0);
14014   }
14015   // Bond between newtops.
14016   fnext(newtops[0], tmpbond0);
14017   enext2fnext(bots[0], spintet); 
14018   for (i = 1; i < wrapcount; i ++) {
14019     if (issymexist(&spintet)) {
14020       enext2fnext(newtops[i], tmpbond1);
14021       bond(tmpbond0, tmpbond1);
14022     }
14023     fnext(newtops[i], tmpbond0);
14024     enext2fnext(bots[i], spintet); 
14025   }
14026   // Bond the last to the first if no boundary.
14027   if (issymexist(&spintet)) {
14028     enext2fnext(newtops[0], tmpbond1);
14029     bond(tmpbond0, tmpbond1);
14030   }
14031   if (checksubsegs) {
14032     for (i = 0; i < wrapcount; i++) {
14033       enextfnext(bots[i], worktet); // edge n1->n2.
14034       tsspivot1(worktet, n1n2seg);
14035       if (n1n2seg.sh != dummysh) {
14036         enext(newtops[i], tmpbond0);
14037         tssbond1(tmpbond0, n1n2seg);
14038       }
14039       enextself(worktet); // edge n2->v ==> n2->b
14040       tsspivot1(worktet, n2vseg);
14041       if (n2vseg.sh != dummysh) {
14042         tssdissolve1(worktet);
14043         tssbond1(newtops[i], n2vseg);
14044       }
14045       enextself(worktet); // edge v->n1 ==> b->n1
14046       tsspivot1(worktet, n1vseg);
14047       if (n1vseg.sh != dummysh) {
14048         tssdissolve1(worktet);
14049         enext2(newtops[i], tmpbond0);
14050         tssbond1(tmpbond0, n1vseg);
14051       }
14052     }
14053   }
14054 
14055   // Is there exist subfaces and subsegment need to be split?
14056   if (checksubfaces) {
14057     if (abseg.sh != dummysh) {
14058       // A subsegment needs be split.
14059       spivot(abseg, splitsh);
14060 #ifdef SELF_CHECK
14061       assert(splitsh.sh != dummysh);
14062 #endif
14063     }
14064     if (splitsh.sh != dummysh) {
14065       // Split subfaces (and subsegment).
14066       findedge(&splitsh, pa, pb);
14067       splitsubedge(newpoint, &splitsh, (queue *) NULL);
14068     }
14069   }
14070 
14071   if (b->verbose > 3) {
14072     for (i = 0; i < wrapcount; i++) {
14073       printf("    Updating bots[%i] ", i);
14074       printtet(&(bots[i]));
14075       printf("    Creating newtops[%i] ", i);
14076       printtet(&(newtops[i]));
14077     }
14078   }
14079 
14080   if (flipqueue != (queue *) NULL) {
14081     for (i = 0; i < wrapcount; i++) {
14082       enqueueflipface(bots[i], flipqueue);
14083       enqueueflipface(newtops[i], flipqueue);
14084     }
14085   }
14086 
14087   // Set the return handle be avn1n2.  It is got by transforming from
14088   //   'bots[0]' (which is an1n2v).
14089   fnext(bots[0], spintet); // spintet is an1vn2.
14090   esymself(spintet); // spintet is n1avn2.
14091   enextself(spintet); // spintet is avn1n2.
14092   *splittet = spintet;
14093 
14094   delete [] bots;
14095   delete [] newtops;
14096 }
14097 
14099 //                                                                           //
14100 // unsplittetedge()    Reverse the operation of splitting an edge, so as to  //
14101 //                     remove the newly inserted point.                      //
14102 //                                                                           //
14103 // Assume the original edge is ab, the tetrahedron containing ab is abn1n2.  //
14104 // After ab was split by a point v, every tetrahedron containing ab (e.g.,   //
14105 // abn1n2) has been split into two (e.g., an1n2v and bn2n1v). 'splittet'     //
14106 // represents avn1n2 (i.e., its destination is v).                           //
14107 //                                                                           //
14108 // To remove point v is to expand each split tetrahedron containing ab (e.g.,//
14109 // (avn1n2 to abn1n2), then delete the redundant one(e.g., vbn1n2). If there //
14110 // exists any subface around ab, routine unsplitsubedge() will be called to  //
14111 // reverse the operation of splitting a edge (or a subsegment) of subfaces.  //
14112 // On completion, point v is not deleted in this routine.                    //
14113 //                                                                           //
14115 
14116 void tetgenmesh::unsplittetedge(triface* splittet)
14117 {
14118   triface *bots, *newtops;
14119   triface oldtop, topcasing;
14120   triface spintet;
14121   face avseg, splitsh, topsh, spinsh;
14122   point pa, pv, n1;
14123   int wrapcount, hitbdry;
14124   int i;
14125 
14126   spintet = *splittet;
14127   pa = org(spintet);
14128   pv = dest(spintet);
14129   if (checksubfaces) {
14130     // Is there a subsegment need to be unsplit together?
14131     tsspivot(splittet, &avseg);
14132     if (avseg.sh != dummysh) {
14133       // The subsegment's direction should conform to 'splittet'.
14134       if (sorg(avseg) != pa) {
14135         sesymself(avseg);
14136       }
14137     }
14138   } 
14139 
14140   n1 = apex(spintet);
14141   hitbdry = 0;
14142   wrapcount = 1;
14143   if (checksubfaces && avseg.sh != dummysh) {
14144     // It may happen that some tetrahedra containing ab (a subsegment) are
14145     //   completely disconnected with others. If it happens, use the face
14146     //   link of ab to cross the boundary. 
14147     while (true) {    
14148       if (!fnextself(spintet)) {
14149         // Meet a boundary, walk through it.
14150         hitbdry ++;
14151         tspivot(spintet, spinsh);
14152 #ifdef SELF_CHECK
14153         assert(spinsh.sh != dummysh);
14154 #endif
14155         findedge(&spinsh, pa, pv);
14156         sfnextself(spinsh);
14157         stpivot(spinsh, spintet);
14158 #ifdef SELF_CHECK
14159         assert(spintet.tet != dummytet);
14160 #endif
14161         findedge(&spintet, pa, pv);
14162         // Remember this position (hull face) in 'splittet'.
14163         *splittet = spintet;
14164         // Split two hull faces increase the hull size;
14165         hullsize += 2;
14166       }
14167       if (apex(spintet) == n1) break;
14168       wrapcount ++;
14169     }
14170     if (hitbdry > 0) {
14171       wrapcount -= hitbdry;
14172     }
14173   } else {
14174     // All the tetrahedra containing ab are connected together. If there
14175     //   are subfaces, 'splitsh' keeps one of them.
14176     splitsh.sh = dummysh;
14177     while (hitbdry < 2) {
14178       if (checksubfaces && splitsh.sh == dummysh) {
14179         tspivot(spintet, splitsh);
14180       }
14181       if (fnextself(spintet)) {
14182         if (apex(spintet) == n1) break;
14183         wrapcount++;
14184       } else {
14185         hitbdry ++;
14186         if (hitbdry < 2) {
14187           esym(*splittet, spintet);
14188         }
14189       }
14190     }
14191     if (hitbdry > 0) {
14192       // ab is on the hull.
14193       wrapcount -= 1;
14194       // 'spintet' now is a hull face, inverse its edge direction.
14195       esym(spintet, *splittet);
14196       // Split two hull faces increases the number of hull faces.
14197       hullsize += 2;
14198     }
14199   }
14200   
14201   // Make arrays of updating (bot, oldtop) and new (newtop) tetrahedra.
14202   bots = new triface[wrapcount];
14203   newtops = new triface[wrapcount];
14204   // Spin around av, gather tetrahedra and set up new tetrahedra. 
14205   spintet = *splittet;
14206   for (i = 0; i < wrapcount; i++) {
14207     // Get 'bots[i] = an1n2v'.
14208     enext2fnext(spintet, bots[i]);
14209     esymself(bots[i]);
14210     // Get 'oldtop = n1n2va'.
14211     enextfnext(bots[i], oldtop);
14212     // Get 'newtops[i] = 'bn1n2v'
14213     fnext(oldtop, newtops[i]); // newtop = n1n2bv
14214     esymself(newtops[i]); // newtop = n2n1bv
14215     enext2self(newtops[i]); // newtop = bn2n1v
14216     // Go to the next.
14217     fnextself(spintet);
14218     if (checksubfaces && avseg.sh != dummysh) {
14219       if (!issymexist(&spintet)) {
14220         // We meet a hull face, walk through it.
14221         tspivot(spintet, spinsh);
14222 #ifdef SELF_CHECK
14223         assert(spinsh.sh != dummysh);
14224 #endif
14225         findedge(&spinsh, pa, pv);
14226         sfnextself(spinsh);
14227         stpivot(spinsh, spintet);
14228 #ifdef SELF_CHECK
14229         assert(spintet.tet != dummytet);
14230 #endif
14231         findedge(&spintet, pa, pv);
14232       }
14233     }
14234   }
14235 
14236   if (b->verbose > 1) {
14237     printf("  Removing point %d from edge (%d, %d).\n", 
14238            pointmark(oppo(bots[0])), pointmark(org(bots[0])),
14239            pointmark(org(newtops[0])));
14240   }
14241 
14242   for (i = 0; i < wrapcount; i++) {
14243     // Expand an1n2v to an1n2b.
14244     setoppo(bots[i], org(newtops[i]));
14245     // Get 'oldtop = n1n2va' from 'bot[i]'.
14246     enextfnext(bots[i], oldtop);
14247     // Get 'topcasing' from 'newtop[i]'
14248     sym(newtops[i], topcasing);
14249     // Bond them.
14250     bond(oldtop, topcasing);
14251     if (checksubfaces) {
14252       tspivot(newtops[i], topsh);
14253       if (topsh.sh != dummysh) {
14254         tsbond(oldtop, topsh);
14255       }
14256     }
14257     // Delete the tetrahedron above an1n2v.
14258     tetrahedrondealloc(newtops[i].tet);
14259   }
14260 
14261   // If there exists any subface, unsplit them.
14262   if (checksubfaces) {
14263     if (avseg.sh != dummysh) {
14264       spivot(avseg, splitsh);
14265 #ifdef SELF_CHECK
14266       assert(splitsh.sh != dummysh);
14267 #endif
14268     }
14269     if (splitsh.sh != dummysh) {
14270       findedge(&splitsh, pa, pv);
14271       unsplitsubedge(&splitsh);
14272     }
14273   }
14274 
14275   delete [] bots;
14276   delete [] newtops;
14277 }
14278 
14280 //                                                                           //
14281 // splitsubedge()    Insert a point on an edge of the surface mesh.          //
14282 //                                                                           //
14283 // The splitting edge is given by 'splitsh'. Assume its three corners are a, //
14284 // b, c, where ab is the edge will be split. ab may be a subsegment.         //
14285 //                                                                           //
14286 // To split edge ab is to split all subfaces conatining ab. If ab is not a   //
14287 // subsegment, there are only two subfaces need be split, otherwise, there   //
14288 // may have any number of subfaces need be split. Each splitting subface abc //
14289 // is shrunk to avc, a new subface vbc is created.  It is important to keep  //
14290 // the orientations of edge rings of avc and vbc be the same as abc's. If ab //
14291 // is a subsegment, it is shrunk to av and a new subsegment vb is created.   //
14292 //                                                                           //
14293 // If there are tetrahedra adjoining to the splitting subfaces, they should  //
14294 // be split before calling this routine, so the connection between the new   //
14295 // tetrahedra and the new subfaces can be correctly set.                     //
14296 //                                                                           //
14297 // On completion, 'splitsh' returns avc.  If 'flipqueue' is not NULL, it     //
14298 // returns all edges which may be non-Delaunay.                              //
14299 //                                                                           //
14301 
14302 void tetgenmesh::splitsubedge(point newpoint, face* splitsh, queue* flipqueue)
14303 {
14304   triface abcd, bace, vbcd, bvce;
14305   face startabc, spinabc, spinsh;
14306   face oldbc, bccasin, bccasout;
14307   face ab, bc;
14308   face avc, vbc, vbc1;
14309   face av, vb;
14310   point pa, pb;
14311 
14312   startabc = *splitsh;
14313   // Is there a subsegment?
14314   sspivot(startabc, ab);
14315   if (ab.sh != dummysh) {
14316     ab.shver = 0; 
14317     if (sorg(startabc) != sorg(ab)) {
14318       sesymself(startabc);
14319     }
14320   }
14321   pa = sorg(startabc);
14322   pb = sdest(startabc);
14323   
14324   if (b->verbose > 1) {
14325     printf("  Inserting point %d on subedge (%d, %d) %s.\n",
14326            pointmark(newpoint), pointmark(pa), pointmark(pb),
14327            (ab.sh != dummysh ? "(seg)" : " "));
14328   }
14329   
14330   // Spin arround ab, split every subface containing ab.
14331   spinabc = startabc;
14332   do {
14333     // Adjust spinabc be edge ab.
14334     if (sorg(spinabc) != pa) {
14335       sesymself(spinabc);
14336     }
14337     // Save old configuration at edge bc, if bc has a subsegment, save the
14338     //   face link of it and dissolve it from bc.
14339     senext(spinabc, oldbc);
14340     spivot(oldbc, bccasout);    
14341     sspivot(oldbc, bc);
14342     if (bc.sh != dummysh) {
14343       if (spinabc.sh != bccasout.sh) {
14344         // 'spinabc' is not self-bonded.
14345         spinsh = bccasout;
14346         do {
14347           bccasin = spinsh;
14348           spivotself(spinsh);
14349         } while (spinsh.sh != oldbc.sh);
14350       } else {
14351         bccasout.sh = dummysh;
14352       }
14353       ssdissolve(oldbc);
14354     }
14355     // Create a new subface.
14356     makeshellface(subfaces, &vbc);
14357     // Split abc.
14358     avc = spinabc;  // Update 'abc' to 'avc'.
14359     setsdest(avc, newpoint);
14360     // Make 'vbc' be in the same edge ring as 'avc'. 
14361     vbc.shver = avc.shver; 
14362     setsorg(vbc, newpoint); // Set 'vbc'.
14363     setsdest(vbc, pb);
14364     setsapex(vbc, sapex(avc));
14365     if (b->quality && varconstraint) {
14366       // Copy the area bound into the new subface.
14367       setareabound(vbc, areabound(avc));
14368     }
14369     // Copy the shell marker and shell type into the new subface.
14370     setshellmark(vbc, shellmark(avc));
14371     setshelltype(vbc, shelltype(avc));
14372     if (checkpbcs) {
14373       // Copy the pbcgroup into the new subface.
14374       setshellpbcgroup(vbc, shellpbcgroup(avc));
14375     }
14376     // Set the connection between updated and new subfaces.
14377     senext2self(vbc);
14378     sbond(vbc, oldbc);
14379     // Set the connection between new subface and casings.
14380     senext2self(vbc);
14381     if (bc.sh != dummysh) {
14382       if (bccasout.sh != dummysh) {
14383         // Insert 'vbc' into face link.
14384         sbond1(bccasin, vbc);
14385         sbond1(vbc, bccasout);
14386       } else {
14387         // Bond 'vbc' to itself.
14388         sbond(vbc, vbc);
14389       }
14390       ssbond(vbc, bc);
14391     } else {
14392       sbond(vbc, bccasout);
14393     }
14394     // Go to next subface at edge ab.
14395     spivotself(spinabc);
14396     if (spinabc.sh == dummysh) {
14397       break; // 'ab' is a hull edge.
14398     }
14399   } while (spinabc.sh != startabc.sh);
14400 
14401   // Get the new subface vbc above the updated subface avc (= startabc).
14402   senext(startabc, oldbc);
14403   spivot(oldbc, vbc);
14404   if (sorg(vbc) == newpoint) {
14405     sesymself(vbc);
14406   }
14407 #ifdef SELF_CHECK
14408   assert(sorg(vbc) == sdest(oldbc) && sdest(vbc) == sorg(oldbc));
14409 #endif
14410   senextself(vbc);
14411   // Set the face link for the new created subfaces around edge vb.
14412   spinabc = startabc;
14413   do {
14414     // Go to the next subface at edge av.
14415     spivotself(spinabc);
14416     if (spinabc.sh == dummysh) {
14417       break; // 'ab' is a hull edge.
14418     }
14419     if (sorg(spinabc) != pa) {
14420       sesymself(spinabc);
14421     }
14422     // Get the new subface vbc1 above the updated subface avc (= spinabc).
14423     senext(spinabc, oldbc);
14424     spivot(oldbc, vbc1);
14425     if (sorg(vbc1) == newpoint) {
14426       sesymself(vbc1);
14427     }
14428 #ifdef SELF_CHECK
14429     assert(sorg(vbc1) == sdest(oldbc) && sdest(vbc1) == sorg(oldbc));
14430 #endif
14431     senextself(vbc1);
14432     // Set the connection: vbc->vbc1.
14433     sbond1(vbc, vbc1);
14434     // For the next connection.
14435     vbc = vbc1;
14436   } while (spinabc.sh != startabc.sh);
14437 
14438   // Split ab if it is a subsegment.
14439   if (ab.sh != dummysh) {
14440     // Update subsegment ab to av.
14441     av = ab;
14442     setsdest(av, newpoint);
14443     // Create a new subsegment vb.
14444     makeshellface(subsegs, &vb);
14445     setsorg(vb, newpoint);
14446     setsdest(vb, pb);
14447     // vb gets the same mark and segment type as av.
14448     setshellmark(vb, shellmark(av));
14449     setshelltype(vb, shelltype(av));
14450     if (b->quality && varconstraint) {
14451       // Copy the area bound into the new subsegment.
14452       setareabound(vb, areabound(av));
14453     }
14454     // Save the old connection at ab (re-use the handles oldbc, bccasout).
14455     senext(av, oldbc);
14456     spivot(oldbc, bccasout);
14457     // Bond av and vb (bonded at their "fake" edges).
14458     senext2(vb, bccasin);
14459     sbond(bccasin, oldbc);
14460     if (bccasout.sh != dummysh) {
14461       // There is a subsegment connecting with ab at b. It will connect
14462       //   to vb at b after splitting.
14463       bccasout.shver = 0;
14464       if (sorg(bccasout) != pb) sesymself(bccasout);
14465 #ifdef SELF_CHECK
14466       assert(sorg(bccasout) == pb); 
14467 #endif
14468       senext2self(bccasout);
14469       senext(vb, bccasin);
14470       sbond(bccasin, bccasout);
14471     }
14472     // Bond all new subfaces (vbc) to vb. 
14473     spinabc = startabc;
14474     do {
14475       // Adjust spinabc be edge av.
14476       if (sorg(spinabc) != pa) {
14477         sesymself(spinabc);
14478       }
14479       // Get new subface vbc above the updated subface avc (= spinabc).
14480       senext(spinabc, oldbc);
14481       spivot(oldbc, vbc);
14482       if (sorg(vbc) == newpoint) {
14483         sesymself(vbc);
14484       }
14485       senextself(vbc);
14486       // Bond the new subface and the new subsegment.
14487       ssbond(vbc, vb);
14488       // Go to the next.
14489       spivotself(spinabc);
14490 #ifdef SELF_CHECK
14491       assert(spinabc.sh != dummysh);
14492 #endif
14493     } while (spinabc.sh != startabc.sh);
14494   }
14495 
14496   // Bond the new subfaces to new tetrahedra if they exist.  New tetrahedra
14497   //   should have been created before calling this routine.
14498   spinabc = startabc;
14499   do {
14500     // Adjust spinabc be edge av.
14501     if (sorg(spinabc) != pa) {
14502       sesymself(spinabc);
14503     }
14504     // Get new subface vbc above the updated subface avc (= spinabc).
14505     senext(spinabc, oldbc);
14506     spivot(oldbc, vbc);
14507     if (sorg(vbc) == newpoint) {
14508       sesymself(vbc);
14509     }
14510     senextself(vbc);
14511     // Get the adjacent tetrahedra at 'spinabc'.
14512     stpivot(spinabc, abcd);
14513     if (abcd.tet != dummytet) {
14514       findedge(&abcd, sorg(spinabc), sdest(spinabc));
14515       enextfnext(abcd, vbcd);
14516       fnextself(vbcd);
14517 #ifdef SELF_CHECK
14518       assert(vbcd.tet != dummytet);
14519 #endif
14520       tsbond(vbcd, vbc);
14521       sym(vbcd, bvce);
14522       sesymself(vbc);
14523       tsbond(bvce, vbc);
14524     } else {
14525       // One side is empty, check the other side.
14526       sesymself(spinabc);
14527       stpivot(spinabc, bace);
14528       if (bace.tet != dummytet) {
14529         findedge(&bace, sorg(spinabc), sdest(spinabc));
14530         enext2fnext(bace, bvce);
14531         fnextself(bvce);
14532 #ifdef SELF_CHECK
14533         assert(bvce.tet != dummytet);
14534 #endif
14535         sesymself(vbc); 
14536         tsbond(bvce, vbc);
14537       }
14538     }
14539     // Go to the next.
14540     spivotself(spinabc);
14541     if (spinabc.sh == dummysh) {
14542       break; // 'ab' is a hull edge.
14543     }
14544   } while (spinabc.sh != startabc.sh);
14545   
14546   if (b->verbose > 3) {
14547     spinabc = startabc;
14548     do {
14549       // Adjust spinabc be edge av.
14550       if (sorg(spinabc) != pa) {
14551         sesymself(spinabc);
14552       }
14553       printf("    Updating abc:\n");
14554       printsh(&spinabc);
14555       // Get new subface vbc above the updated subface avc (= spinabc).
14556       senext(spinabc, oldbc);
14557       spivot(oldbc, vbc);
14558       if (sorg(vbc) == newpoint) {
14559         sesymself(vbc);
14560       }
14561       senextself(vbc);
14562       printf("    Creating vbc:\n");
14563       printsh(&vbc);
14564       // Go to the next.
14565       spivotself(spinabc);
14566       if (spinabc.sh == dummysh) {
14567         break; // 'ab' is a hull edge.
14568       }
14569     } while (spinabc.sh != startabc.sh);
14570   }
14571 
14572   if (flipqueue != (queue *) NULL) {
14573     spinabc = startabc;
14574     do {
14575       // Adjust spinabc be edge av.
14576       if (sorg(spinabc) != pa) {
14577         sesymself(spinabc);
14578       }
14579       senext2(spinabc, oldbc); // Re-use oldbc.
14580       enqueueflipedge(oldbc, flipqueue);
14581       // Get new subface vbc above the updated subface avc (= spinabc).
14582       senext(spinabc, oldbc);
14583       spivot(oldbc, vbc);
14584       if (sorg(vbc) == newpoint) {
14585         sesymself(vbc);
14586       }
14587       senextself(vbc);
14588       senext(vbc, oldbc); // Re-use oldbc.
14589       enqueueflipedge(oldbc, flipqueue);
14590       // Go to the next.
14591       spivotself(spinabc);
14592       if (spinabc.sh == dummysh) {
14593         break; // 'ab' is a hull edge.
14594       }
14595     } while (spinabc.sh != startabc.sh);
14596   }
14597 }
14598 
14600 //                                                                           //
14601 // unsplitsubedge()    Reverse the operation of splitting an edge of subface,//
14602 //                     so as to remove a point from the edge.                //
14603 //                                                                           //
14604 // Assume the original edge is ab, the subface containing it is abc. It was  //
14605 // split by a point v into avc, and vbc.  'splitsh' represents avc, further- //
14606 // more, if av is a subsegment, av should be the zero version of the split   //
14607 // subsegment (i.e., av.shver = 0), so we are sure that the destination (v)  //
14608 // of both avc and av is the deleting point.                                 //
14609 //                                                                           //
14610 // To remove point v is to expand avc to abc, delete vbc, do the same for    //
14611 // other subfaces containing av and vb. If av and vb are subsegments, expand //
14612 // av to ab, delete vb.  On completion, point v is not deleted.              //
14613 //                                                                           //
14615 
14616 void tetgenmesh::unsplitsubedge(face* splitsh)
14617 {
14618   face startavc, spinavc, spinbcv;
14619   face oldvc, bccasin, bccasout, spinsh;
14620   face av, vb, bc;
14621   point pa, pv, pb;
14622 
14623   startavc = *splitsh;
14624   sspivot(startavc, av);
14625   if (av.sh != dummysh) {
14626     // Orient the direction of subsegment to conform the subface. 
14627     if (sorg(av) != sorg(startavc)) {
14628       sesymself(av);
14629     }
14630 #ifdef SELF_CHECK
14631     assert(av.shver == 0);
14632 #endif
14633   }
14634   senext(startavc, oldvc);
14635   spivot(oldvc, vb);  // vb is subface vbc
14636   if (sorg(vb) != sdest(oldvc)) {
14637     sesymself(vb);
14638   }
14639   senextself(vb);
14640   pa = sorg(startavc);
14641   pv = sdest(startavc);
14642   pb = sdest(vb);
14643 
14644   if (b->verbose > 1) {
14645     printf("  Removing point %d from subedge (%d, %d).\n",
14646            pointmark(pv), pointmark(pa), pointmark(pb));
14647   }
14648 
14649   // Spin arround av, unsplit every subface containing av.
14650   spinavc = startavc;
14651   do {
14652     // Adjust spinavc be edge av.
14653     if (sorg(spinavc) != pa) {
14654       sesymself(spinavc);
14655     }
14656     // Save old configuration at edge bc, if bc has a subsegment, save the
14657     //   face link of it.
14658     senext(spinavc, oldvc);
14659     spivot(oldvc, spinbcv);
14660     if (sorg(spinbcv) != sdest(oldvc)) {
14661       sesymself(spinbcv);
14662     }
14663     senext2self(spinbcv);
14664     spivot(spinbcv, bccasout);
14665     sspivot(spinbcv, bc);
14666     if (bc.sh != dummysh) {
14667       if (spinbcv.sh != bccasout.sh) {
14668         // 'spinbcv' is not self-bonded.
14669         spinsh = bccasout;
14670         do {
14671           bccasin = spinsh;
14672           spivotself(spinsh);
14673         } while (spinsh.sh != spinbcv.sh);
14674       } else {
14675         bccasout.sh = dummysh;
14676       }
14677     }
14678     // Expand avc to abc.
14679     setsdest(spinavc, pb);
14680     if (bc.sh != dummysh) {
14681       if (bccasout.sh != dummysh) {
14682         sbond1(bccasin, oldvc);
14683         sbond1(oldvc, bccasout);
14684       } else {
14685         // Bond 'oldbc' to itself.
14686         sbond(oldvc, oldvc);
14687       }
14688       ssbond(oldvc, bc);
14689     } else {
14690       sbond(oldvc, bccasout);
14691     }
14692     // Delete bcv.
14693     shellfacedealloc(subfaces, spinbcv.sh);
14694     // Go to next subface at edge av.
14695     spivotself(spinavc);
14696     if (spinavc.sh == dummysh) {
14697       break; // 'av' is a hull edge.
14698     }
14699   } while (spinavc.sh != startavc.sh);
14700 
14701   // Is there a subsegment need to be unsplit?
14702   if (av.sh != dummysh) {
14703     senext(av, oldvc);  // Re-use oldvc.
14704     spivot(oldvc, vb);
14705     vb.shver = 0;
14706 #ifdef SELF_CHECK
14707     assert(sdest(av) == sorg(vb));
14708 #endif
14709     senext(vb, spinbcv); // Re-use spinbcv.
14710     spivot(spinbcv, bccasout);
14711     // Expand av to ab.
14712     setsdest(av, pb);
14713     sbond(oldvc, bccasout);
14714     // Delete vb.
14715     shellfacedealloc(subsegs, vb.sh);
14716   }
14717 }
14718 
14720 //                                                                           //
14721 // insertsite()    Insert a point into the mesh.                             //
14722 //                                                                           //
14723 // The 'newpoint' is located.  If 'searchtet->tet' is not NULL, the search   //
14724 // for the containing tetrahedron begins from 'searchtet', otherwise, a full //
14725 // point location procedure is called.  If 'newpoint' is found inside a      //
14726 // tetrahedron, the tetrahedron is split into four (by splittetrahedron());  //
14727 // if 'newpoint' lies on a face, the face is split into three, thereby       //
14728 // splitting the two adjacent tetrahedra into six (by splittetface()); if    //
14729 // 'newpoint' lies on an edge, the edge is split into two, thereby, every    //
14730 // tetrahedron containing this edge is split into two. If 'newpoint' lies on //
14731 // an existing vertex, no action is taken, and the value DUPLICATEPOINT  is  //
14732 // returned and 'searchtet' is set to a handle whose origin is the vertex.   //
14733 //                                                                           //
14734 // If 'flipqueue' is not NULL, after 'newpoint' is inserted, it returns all  //
14735 // faces which may become non-Delaunay due to the newly inserted point. Flip //
14736 // operations can be performed as necessary on them to maintain the Delaunay //
14737 // property.                                                                 //
14738 //                                                                           //
14740 
14741 enum tetgenmesh::insertsiteresult tetgenmesh::insertsite(point newpoint,
14742   triface* searchtet, bool approx, queue* flipqueue)
14743 {
14744   enum locateresult intersect, exactloc;
14745   point checkpt;
14746   REAL epspp, checklen;
14747   int count;
14748 
14749   if (b->verbose > 1) {
14750     printf("  Insert point to mesh: (%.12g, %.12g, %.12g) %d.\n",
14751            newpoint[0], newpoint[1], newpoint[2], pointmark(newpoint));
14752   }
14753 
14754   if (searchtet->tet == (tetrahedron *) NULL) {
14755     // Search for a tetrahedron containing 'newpoint'.
14756     searchtet->tet = dummytet;
14757     exactloc = locate(newpoint, searchtet);
14758   } else {
14759     // Start searching from the tetrahedron provided by the caller. 
14760     exactloc = preciselocate(newpoint, searchtet, tetrahedrons->items);
14761   }
14762   intersect = exactloc;
14763   if (approx && (exactloc != ONVERTEX)) {
14764     // Adjust the exact location to an approx. location wrt. epsilon.
14765     epspp = b->epsilon;
14766     count = 0;
14767     while (count < 16) {
14768       intersect = adjustlocate(newpoint, searchtet, exactloc, epspp);
14769       if (intersect == ONVERTEX) {
14770         checkpt = org(*searchtet);
14771         checklen = distance(checkpt, newpoint);
14772         if (checklen / longest > b->epsilon) {
14773           epspp *= 1e-2;
14774           count++;
14775           continue;
14776         }
14777       }
14778       break;
14779     }
14780   }
14781   // Keep current search state for next searching.
14782   recenttet = *searchtet; 
14783 
14784   // Insert the point using the right routine
14785   switch (intersect) {
14786   case ONVERTEX:
14787     // There's already a vertex there. Return in 'searchtet' a tetrahedron
14788     //   whose origin is the existing vertex.
14789     if (b->verbose > 1) {
14790       printf("  Not insert for duplicating point.\n");
14791     }
14792     return DUPLICATEPOINT;
14793 
14794   case OUTSIDE:
14795     if (b->verbose > 1) {
14796       printf("  Not insert for locating outside the mesh.\n");
14797     }
14798     return OUTSIDEPOINT;
14799 
14800   case ONEDGE:
14801     // 'newpoint' falls on an edge.
14802     splittetedge(newpoint, searchtet, flipqueue);
14803     return SUCCESSONEDGE;
14804 
14805   case ONFACE:
14806     // 'newpoint' falls on a face.
14807     splittetface(newpoint, searchtet, flipqueue);
14808     return SUCCESSONFACE;
14809 
14810   case INTETRAHEDRON:
14811     // 'newpoint' falls inside a tetrahedron.
14812     splittetrahedron(newpoint, searchtet, flipqueue);
14813     return SUCCESSINTET;
14814   
14815   default:
14816     // Impossible case.
14817     return OUTSIDEPOINT;
14818   }
14819 }
14820 
14822 //                                                                           //
14823 // undosite()    Undo the most recently point insertion.                     //
14824 //                                                                           //
14825 // 'insresult' indicates in where the newpoint has been inserted, i.e., in a //
14826 // tetrahedron, on a face, or on an edge.  A correspoding routine will be    //
14827 // called to undo the point insertion.  'splittet' is a handle represent one //
14828 // of the resulting tetrahedra, but it may be changed after transformation,  //
14829 // even may be dead.  Four points 'torg', ... 'toppo' are the corners which  //
14830 // 'splittet' should have. On finish, 'newpoint' is not removed.             //
14831 //                                                                           //
14833 
14834 void tetgenmesh::undosite(enum insertsiteresult insresult, triface* splittet,
14835   point torg, point tdest, point tapex, point toppo)
14836 {
14837   // Set the four corners of 'splittet' exactly be 'torg', ... 'toppo'.
14838   findface(splittet, torg, tdest, tapex);
14839   if (oppo(*splittet) != toppo) {
14840     symself(*splittet);
14841 #ifdef SELF_CHECK
14842     assert(oppo(*splittet) == toppo);
14843 #endif
14844     // The sym() operation may inverse the edge, correct it if so.
14845     findedge(splittet, torg, tdest);
14846   }
14847   
14848   // Unsplit the tetrahedron according to 'insresult'.  
14849   switch (insresult) {
14850   case SUCCESSINTET:
14851     // 'splittet' should be the face with 'newpoint' as its opposite.
14852     unsplittetrahedron(splittet);
14853     break;
14854   case SUCCESSONFACE:
14855     // 'splittet' should be the one of three splitted face with 'newpoint'
14856     //   as its apex.
14857     unsplittetface(splittet);
14858     break;
14859   case SUCCESSONEDGE:
14860     // 'splittet' should be the tet with destination is 'newpoint'.
14861     unsplittetedge(splittet);
14862     break;
14863   default: // To omit compile warnings.
14864     break;
14865   }
14866 }
14867 
14869 //                                                                           //
14870 // closeopenface()    Close "open" faces recursively.                        //
14871 //                                                                           //
14872 // This is the support routine of inserthullsite(). A point p which lies out-//
14873 // side of CH(T). p is inserted to T by forming a tet t from p and a visible //
14874 // CH face f. The three sides of f which have p as a vertex is called "open" //
14875 // face. Each open face will be closed by either creating a tet on top of it //
14876 // or become a new CH face.                                                  //
14877 //                                                                           //
14879 
14880 void tetgenmesh::closeopenface(triface* openface, queue* flipque)
14881 {
14882   triface newtet, oldhull;
14883   triface newopenface, closeface;
14884   point inspoint, pa, pb, pc;
14885   REAL attrib, volume;
14886   int i;
14887 
14888   // Get the new point p.
14889   inspoint = apex(*openface);
14890   // Find the old CH face f_o (f and f_o share the same edge). 
14891   esym(*openface, oldhull);
14892   while (fnextself(oldhull)) ;
14893   if (apex(oldhull) != inspoint) {
14894     // Is f_o visible by p?
14895     pa = org(oldhull);
14896     pb = dest(oldhull);
14897     pc = apex(oldhull);
14898     if (orient3d(pa, pb, pc, inspoint) < 0.0) {
14899       // Yes. Create a new tet t above f_o.
14900       maketetrahedron(&newtet);
14901       setorg(newtet, pa);
14902       setdest(newtet, pb);
14903       setapex(newtet, pc);
14904       setoppo(newtet, inspoint); 
14905       for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14906         attrib = elemattribute(oldhull.tet, i);
14907         setelemattribute(newtet.tet, i, attrib);
14908       }
14909       if (b->varvolume) {
14910         volume = volumebound(oldhull.tet);
14911         setvolumebound(newtet.tet, volume);
14912       }
14913       // Connect t to T.
14914       bond(newtet, oldhull);
14915       // Close f.
14916       fnext(newtet, newopenface);
14917       bond(newopenface, *openface);
14918       // f_o becomes an interior face.
14919       enqueueflipface(oldhull, flipque);
14920       // Hull face number decreases.
14921       hullsize--; 
14922       // Two faces of t become open face.
14923       enextself(newtet);
14924       for (i = 0; i < 2; i++) {
14925         fnext(newtet, newopenface);
14926         sym(newopenface, closeface);
14927         if (closeface.tet == dummytet) {
14928           closeopenface(&newopenface, flipque);
14929         }
14930         enextself(newtet);
14931       }
14932     } else {
14933       // Inivisible. f becomes a new CH face.
14934       hullsize++;
14935       // Let 'dummytet' holds f for the next point location.
14936       dummytet[0] = encode(*openface);
14937     }
14938   } else {
14939     // f_o is co-incident with f --> f is closed by f_o.
14940     bond(*openface, oldhull);
14941     // f is an interior face.
14942     enqueueflipface(*openface, flipque);
14943   }
14944 }
14945 
14947 //                                                                           //
14948 // inserthullsite()    Insert a point which lies outside the convex hull.    //
14949 //                                                                           //
14950 // The 'inspoint' p lies outside the tetrahedralization T.  The 'horiz' f is //
14951 // on the convex hull of T, CH(T), which is visible by p (Imagine f is para- //
14952 // llel to the horizon). To insert p into T we have to enlarge the CH(T) and //
14953 // update T so that p is on the new CH(T).                                   //
14954 //                                                                           //
14955 // To enlarge the CH(T).  We need to find the set F of faces which are on CH //
14956 // (T) and visible by p (F can be formed by a depth-first search from f).  p //
14957 // is then inserted into T by mounting new tets formed by p and these faces. //
14958 // Faces of F become interior faces and may non-locally Delaunay.  They are  //
14959 // queued in 'flipqueue' for flip tests.                                     //
14960 //                                                                           //
14962 
14963 void tetgenmesh::inserthullsite(point inspoint, triface* horiz, queue* flipque)
14964 {
14965   triface firstnewtet;
14966   triface openface, closeface;
14967   REAL attrib, volume;
14968   int i;
14969 
14970   // Let f face to p.
14971   adjustedgering(*horiz, CW);
14972   // Create the first tet t (from f and p).
14973   maketetrahedron(&firstnewtet);
14974   setorg (firstnewtet, org(*horiz));
14975   setdest(firstnewtet, dest(*horiz));
14976   setapex(firstnewtet, apex(*horiz));
14977   setoppo(firstnewtet, inspoint);
14978   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14979     attrib = elemattribute(horiz->tet, i);
14980     setelemattribute(firstnewtet.tet, i, attrib);
14981   }
14982   if (b->varvolume) {
14983     volume = volumebound(horiz->tet);
14984     setvolumebound(firstnewtet.tet, volume);
14985   }
14986   // Connect t to T.
14987   bond(firstnewtet, *horiz);
14988   // f is not on CH(T) anymore.
14989   enqueueflipface(*horiz, flipque);
14990   // Hull face number decreases.
14991   hullsize--;
14992 
14993   // Call the faces of t which have p as a vertex "open" face.
14994   for (i = 0; i < 3; i++) {
14995     // Get an open face f_i of t.
14996     fnext(firstnewtet, openface);
14997     // Close f_i if it is still open.
14998     sym(openface, closeface);
14999     if (closeface.tet == dummytet) {
15000       closeopenface(&openface, flipque);
15001     }
15002     // Go to the next open face of t.
15003     enextself(firstnewtet);
15004   }
15005 }
15006 
15008 //                                                                           //
15009 // Terminology: BC(p) and CBC(p), B(p) and C(p).                             //
15010 //                                                                           //
15011 // Given an arbitrary point p,  the Bowyer-Watson cavity BC(p) is formed by  //
15012 // tets whose circumspheres containing p.  The outer faces of BC(p) form a   //
15013 // polyhedron B(p).                                                          //
15014 //                                                                           //
15015 // If p is on a facet F, the constrained Bowyer-Watson cavity CBC(p) on F is //
15016 // formed by subfaces of F whose circumspheres containing p. The outer edges //
15017 // of CBC(p) form a polygon C(p).  B(p) is separated into two parts by C(p), //
15018 // denoted as B_1(p) and B_2(p), one of them may be empty (F is on the hull).//
15019 //                                                                           //
15020 // If p is on a segment S which is shared by n facets.  There exist n C(p)s, //
15021 // each one is a non-closed polygon (without S). B(p) is split into n parts, //
15022 // each of them is denoted as B_i(p), some B_i(p) may be empty.              //
15023 //                                                                           //
15025 
15027 //                                                                           //
15028 // formbowatcavitysub()    Form CBC(p) and C(p) on a facet F.                //
15029 //                                                                           //
15030 // Parameters: bp = p, bpseg = S, sublist = CBC(p), subceillist = C(p).      //
15031 //                                                                           //
15032 // CBC(p) contains at least one subface on input; S may be NULL which means  //
15033 // that p is inside a facet. On output, all subfaces of CBC(p) are infected, //
15034 // and the edge rings are oriented to the same halfspace.                    //
15035 //                                                                           //
15037 
15038 void tetgenmesh::formbowatcavitysub(point bp, face* bpseg, list* sublist,
15039   list* subceillist)
15040 {
15041   triface adjtet;
15042   face startsh, neighsh;
15043   face checkseg;
15044   point pa, pb, pc, pd;
15045   REAL sign;
15046   int i, j;  
15047 
15048   // Form CBC(p) and C(p) by a broadth-first searching.
15049   for (i = 0; i < sublist->len(); i++) {
15050     startsh = * (face *)(* sublist)[i]; // startsh = f.
15051     // Look for three neighbors of f.
15052     for (j = 0; j < 3; j++) {
15053       sspivot(startsh, checkseg);
15054       if (checkseg.sh == dummysh) {
15055         // Get its neighbor n.
15056         spivot(startsh, neighsh);
15057         // Is n already in CBC(p)?
15058         if (!sinfected(neighsh)) {
15059           stpivot(neighsh, adjtet);
15060           if (adjtet.tet == dummytet) {
15061             sesymself(neighsh);
15062             stpivot(neighsh, adjtet);
15063           }
15064           // For positive orientation that insphere() test requires.
15065           adjustedgering(adjtet, CW);
15066           pa = org(adjtet);
15067           pb = dest(adjtet);
15068           pc = apex(adjtet);
15069           pd = oppo(adjtet);
15070           sign = insphere(pa, pb, pc, pd, bp);
15071           if (sign >= 0.0) {
15072             // Orient edge ring of n according to that of f.
15073             if (sorg(neighsh) != sdest(startsh)) sesymself(neighsh);
15074             // Collect it into CBC(p).
15075             sinfect(neighsh);
15076             sublist->append(&neighsh);
15077           } else {
15078             subceillist->append(&startsh); // Found an edge of C(p).
15079           }
15080         }
15081       } else {
15082         // Do not cross a segment.
15083         if (bpseg != (face *) NULL) {
15084           if (checkseg.sh != bpseg->sh) {
15085             subceillist->append(&startsh); // Found an edge of C(p).
15086           }
15087         } else {
15088           subceillist->append(&startsh); // Found an edge of C(p).
15089         }
15090       }
15091       senextself(startsh);
15092     }
15093   }
15094 
15095   if (b->verbose > 2) {
15096     printf("    Collect CBC(%d): %d subfaces, %d edges.\n", pointmark(bp),
15097            sublist->len(), subceillist->len());
15098   }
15099 }
15100 
15102 //                                                                           //
15103 // formbowatcavityquad()    Form BC_i(p) and B_i(p) in a quadrant.           //
15104 //                                                                           //
15105 // Parameters: bp = p, tetlist = BC_i(p), ceillist = B_i(p).                 //
15106 //                                                                           //
15107 // BC_i(p) contains at least one tet on input. On finish, all tets collected //
15108 // in BC_i(p) are infected. B_i(p) may not closed when p is on segment or in //
15109 // facet. C(p) must be formed before this routine.  Check the infect flag of //
15110 // a subface to identify the unclosed side of B_i(p).  These sides will be   //
15111 // closed by new subfaces of C(p)s.                                          //
15112 //                                                                           //
15114 
15115 void tetgenmesh::formbowatcavityquad(point bp, list* tetlist, list* ceillist)
15116 {
15117   triface starttet, neightet;
15118   face checksh;
15119   point pa, pb, pc, pd;
15120   REAL sign;
15121   int i;
15122 
15123   // Form BC_i(p) and B_i(p) by a broadth-first searching.
15124   for (i = 0; i < tetlist->len(); i++) {
15125     starttet = * (triface *)(* tetlist)[i];
15126     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15127       // Try to collect the neighbor of the face (f).
15128       tspivot(starttet, checksh);
15129       if (checksh.sh == dummysh) {
15130         // Get its neighbor n.
15131         sym(starttet, neightet);
15132         // Is n already in BC_i(p)?
15133         if (!infected(neightet)) {
15134           // For positive orientation that insphere() test requires.
15135           adjustedgering(neightet, CW);
15136           pa = org(neightet);
15137           pb = dest(neightet);
15138           pc = apex(neightet);
15139           pd = oppo(neightet);
15140           sign = insphere(pa, pb, pc, pd, bp);
15141           if (sign >= 0.0) {
15142             // Collect it into BC_i(p).
15143             infect(neightet);
15144             tetlist->append(&neightet);
15145           } else {
15146             ceillist->append(&starttet); // Found a face of B_i(p).
15147           }
15148         }
15149       } else {
15150         // Do not cross a boundary face.
15151         if (!sinfected(checksh)) {
15152           ceillist->append(&starttet); // Found a face of B_i(p).
15153         }
15154       }
15155     }
15156   }
15157 
15158   if (b->verbose > 2) {
15159     printf("    Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15160            tetlist->len(), ceillist->len());
15161   }
15162 }
15163 
15165 //                                                                           //
15166 // formbowatcavitysegquad()    Form BC_i(p) and B_i(p) in a segment quadrant.//
15167 //                                                                           //
15168 // Parameters: bp = p, tetlist = BC_i(p), ceillist = B_i(p).                 //
15169 //                                                                           //
15170 // BC_i(p) contains at least one tet on input. On finish, all tets collected //
15171 // in BC_i(p) are infected. B_i(p) is not closed. C(p) must be formed before //
15172 // this routine. Check the infect flag of a subface to identify the unclosed //
15173 // sides of B_i(p).  These sides will be closed by new subfaces of C(p)s.    //
15174 //                                                                           //
15175 // During the repair of encroaching subsegments, there may exist locally non-//
15176 // Delaunay faces. These faces are collected in BC_i(p) either.  B_i(p) has  //
15177 // to be formed later than BC_i(p).                                          //
15178 //                                                                           //
15180 
15181 void tetgenmesh::formbowatcavitysegquad(point bp, list* tetlist,list* ceillist)
15182 {
15183   triface starttet, neightet, cavtet;
15184   face checksh;
15185   point pa, pb, pc, pd, pe;
15186   REAL sign;
15187   int i;
15188 
15189   // Form BC_i(p) by a broadth-first searching.
15190   for (i = 0; i < tetlist->len(); i++) {
15191     starttet = * (triface *)(* tetlist)[i];
15192     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15193       // Try to collect the neighbor of the face f.
15194       tspivot(starttet, checksh);
15195       if (checksh.sh == dummysh) {
15196         // Get its neighbor n.
15197         sym(starttet, neightet);
15198         // Is n already in BC_i(p)?
15199         if (!infected(neightet)) {
15200           // For positive orientation that insphere() test requires.
15201           adjustedgering(neightet, CW);
15202           pa = org(neightet);
15203           pb = dest(neightet);
15204           pc = apex(neightet);
15205           pd = oppo(neightet);
15206           sign = insphere(pa, pb, pc, pd, bp);
15207           if (sign >= 0.0) {
15208             // Collect it into BC_i(p).
15209             infect(neightet);
15210             tetlist->append(&neightet);
15211           } else {
15212             // Check if the face is locally non-Delaunay.
15213             pe = oppo(starttet);
15214             sign = insphere(pa, pb, pc, pd, pe);
15215             if (sign >= 0.0) {
15216               // Collect it into BC_i(p).
15217               infect(neightet);
15218               tetlist->append(&neightet);
15219             }
15220           }
15221         }
15222       }
15223     }
15224   }
15225 
15226   // Generate B_i(p).
15227   for (i = 0; i < tetlist->len(); i++) {
15228     cavtet = * (triface *)(* tetlist)[i];
15229     for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15230       tspivot(cavtet, checksh);
15231       if (checksh.sh == dummysh) {
15232         sym(cavtet, neightet);
15233         if (!infected(neightet)) {
15234           ceillist->append(&cavtet); // Found a face of B(p).
15235         }
15236       } else {
15237         // Do not cross a boundary face.
15238         if (!sinfected(checksh)) {
15239           ceillist->append(&cavtet); // Found a face of B(p).
15240         }
15241       }
15242     }
15243   }
15244 
15245   if (b->verbose > 2) {
15246     printf("    Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15247            tetlist->len(), ceillist->len());
15248   }
15249 }
15250 
15252 //                                                                           //
15253 // formbowatcavity()    Form BC(p), B(p), CBC(p)s, and C(p)s.                //
15254 //                                                                           //
15255 // If 'bpseg'(S) != NULL, p is on segment S, else, p is on facet containing  //
15256 // 'bpsh' (F).  'n' returns the number of quadrants in BC(p). 'nmax' is the  //
15257 // maximum pre-allocated array length for the lists.                         //
15258 //                                                                           //
15260 
15261 void tetgenmesh::formbowatcavity(point bp, face* bpseg, face* bpsh, int* n,
15262   int* nmax, list** sublists, list** subceillists, list** tetlists,
15263   list** ceillists)
15264 {
15265   list *sublist;
15266   triface adjtet;
15267   face startsh, spinsh;
15268   point pa, pb;
15269   int i, j;
15270 
15271   *n = 0;
15272   if (bpseg != (face *) NULL) {
15273     // p is on segment S.
15274     bpseg->shver = 0;
15275     pa = sorg(*bpseg);
15276     pb = sdest(*bpseg);
15277     // Count the number of facets sharing at S.
15278     spivot(*bpseg, startsh);
15279     spinsh = startsh;
15280     do {
15281       (*n)++; // spinshlist->append(&spinsh);
15282       spivotself(spinsh);
15283     } while (spinsh.sh != startsh.sh);
15284     // *n is the number of quadrants around S.
15285     if (*n > *nmax) {
15286       // Reallocate arrays. Should not happen very often.
15287       delete [] tetlists;
15288       delete [] ceillists;
15289       delete [] sublists;
15290       delete [] subceillists;
15291       tetlists = new list*[*n];
15292       ceillists = new list*[*n];
15293       sublists = new list*[*n];
15294       subceillists = new list*[*n];
15295       *nmax = *n;
15296     }
15297     // Form CBC(p)s and C(p)s.
15298     spinsh = startsh;
15299     for (i = 0; i < *n; i++) {
15300       sublists[i] = new list(sizeof(face), NULL, 256);
15301       subceillists[i] = new list(sizeof(face), NULL, 256);
15302       // Set a subface f to start search.
15303       startsh = spinsh;
15304       // Let f face to the quadrant of interest (used in forming BC(p)).
15305       findedge(&startsh, pa, pb);
15306       sinfect(startsh);
15307       sublists[i]->append(&startsh);
15308       formbowatcavitysub(bp, bpseg, sublists[i], subceillists[i]);
15309       // Go to the next facet.
15310       spivotself(spinsh);
15311     }
15312   } else if (sublists != (list **) NULL) {
15313     // p is on a facet.
15314     *n = 2;
15315     // Form CBC(p) and C(p).
15316     sublists[0] = new list(sizeof(face), NULL, 256);
15317     subceillists[0] = new list(sizeof(face), NULL, 256);
15318     sinfect(*bpsh);
15319     sublists[0]->append(bpsh);
15320     formbowatcavitysub(bp, NULL, sublists[0], subceillists[0]);
15321   } else {
15322     // p is inside a tet.
15323     *n = 1;
15324   }
15325 
15326   // Form BC_i(p) and B_i(p).
15327   for (i = 0; i < *n; i++) {
15328     tetlists[i] = new list(sizeof(triface), NULL, 256);
15329     ceillists[i] = new list(sizeof(triface), NULL, 256);
15330     if (sublists != (list **) NULL) {
15331       // There are C(p)s.
15332       sublist = ((bpseg == (face *) NULL) ? sublists[0] : sublists[i]);
15333       // Add all adjacent tets of C_i(p) into BC_i(p).
15334       for (j = 0; j < sublist->len(); j++) {    
15335         startsh = * (face *)(* sublist)[j];
15336         // Adjust the side facing to the right quadrant for C(p).
15337         if ((bpseg == (face *) NULL) && (i == 1)) sesymself(startsh);
15338         stpivot(startsh, adjtet);
15339         if (adjtet.tet != dummytet) {
15340           if (!infected(adjtet)) {
15341             infect(adjtet);
15342             tetlists[i]->append(&adjtet);
15343           }
15344         }
15345       }
15346       if (bpseg != (face *) NULL) {
15347         // The quadrant is bounded by another facet.
15348         sublist = ((i < *n - 1) ? sublists[i + 1] : sublists[0]);
15349         for (j = 0; j < sublist->len(); j++) {    
15350           startsh = * (face *)(* sublist)[j];
15351           // Adjust the side facing to the right quadrant for C(p).
15352           sesymself(startsh);
15353           stpivot(startsh, adjtet);
15354           if (adjtet.tet != dummytet) {
15355             if (!infected(adjtet)) {
15356               infect(adjtet);
15357               tetlists[i]->append(&adjtet);
15358             }
15359           }
15360         }
15361       }
15362     }
15363     // It is possible that BC_i(p) is empty.
15364     if (tetlists[i]->len() == 0) continue;
15365     // Collect the rest of tets of BC_i(p) and form B_i(p).
15366     // if (b->conformdel) {
15367       // formbowatcavitysegquad(bp, tetlists[i], ceillists[i]);
15368     // } else {
15369       formbowatcavityquad(bp, tetlists[i], ceillists[i]);
15370     // }
15371   }
15372 }
15373 
15375 //                                                                           //
15376 // releasebowatcavity()    Undo and free the memory allocated in routine     //
15377 //                         formbowatcavity().                                //
15378 //                                                                           //
15380 
15381 void tetgenmesh::releasebowatcavity(face* bpseg, int n, list** sublists,
15382   list** subceillist, list** tetlists, list** ceillists)
15383 {
15384   triface oldtet;
15385   face oldsh;
15386   int i, j;
15387 
15388   if (sublists != (list **) NULL) {
15389     // Release CBC(p)s.
15390     for (i = 0; i < n; i++) {
15391       // Uninfect subfaces of CBC(p).
15392       for (j = 0; j < sublists[i]->len(); j++) {
15393         oldsh = * (face *)(* (sublists[i]))[j];
15394 #ifdef SELF_CHECK
15395         assert(sinfected(oldsh));
15396 #endif
15397         suninfect(oldsh);
15398       }
15399       delete sublists[i];
15400       delete subceillist[i];
15401       sublists[i] = (list *) NULL;
15402       subceillist[i] = (list *) NULL;
15403       if (bpseg == (face *) NULL) break;
15404     }
15405   }
15406   // Release BC(p).
15407   for (i = 0; i < n; i++) {
15408     // Uninfect tets of BC_i(p).
15409     for (j = 0; j < tetlists[i]->len(); j++) {
15410       oldtet = * (triface *)(* (tetlists[i]))[j];
15411 #ifdef SELF_CHECK
15412       assert(infected(oldtet));
15413 #endif
15414       uninfect(oldtet);
15415     }
15416     delete tetlists[i];
15417     delete ceillists[i];
15418     tetlists[i] = (list *) NULL;
15419     ceillists[i] = (list *) NULL;
15420   }
15421 }
15422 
15424 //                                                                           //
15425 // validatebowatcavityquad()    Valid B_i(p).                                //
15426 //                                                                           //
15427 // B_i(p) is valid if all faces of B_i(p) are visible by p, else B_i(p) is   //
15428 // invalid.  Each tet of BC_i(p) which has such a face is marked (uninfect). //
15429 // They will be removed in updatebowatcavityquad().                          //
15430 //                                                                           //
15431 // Return TRUE if B(p) is valid, else, return FALSE.                         //
15432 //                                                                           //
15434 
15435 bool tetgenmesh::validatebowatcavityquad(point bp,list* ceillist,REAL maxcosd)
15436 {
15437   triface ceiltet;
15438   point pa, pb, pc;
15439   REAL ori, cosd;
15440   int remcount, i;
15441 
15442   // Check the validate of B(p), cut tets having invisible faces.
15443   remcount = 0;
15444   for (i = 0; i < ceillist->len(); i++) {
15445     ceiltet = * (triface *)(* ceillist)[i];
15446     if (infected(ceiltet)) {
15447       adjustedgering(ceiltet, CCW);
15448       pa = org(ceiltet);
15449       pb = dest(ceiltet);
15450       pc = apex(ceiltet);
15451       ori = orient3d(pa, pb, pc, bp);
15452       if (ori >= 0.0) {
15453         // Found an invisible face.
15454         uninfect(ceiltet);
15455         remcount++;
15456         continue;
15457       }
15458       // If a non-trival 'maxcosd' is given.
15459       if (maxcosd > -1.0) {
15460         // Get the maximal dihedral angle of tet abcp.
15461         tetalldihedral(pa, pb, pc, bp, NULL, &cosd, NULL);
15462         // Do not form the tet if the maximal dihedral angle is not reduced.
15463         if (cosd < maxcosd) {
15464           uninfect(ceiltet);
15465           remcount++;
15466         }
15467       }
15468     }
15469   }
15470   return remcount == 0;
15471 }
15472 
15474 //                                                                           //
15475 // updatebowatcavityquad()    Update BC_i(p) and reform B_i(p).              //
15476 //                                                                           //
15477 // B_i(p) is invalid and some tets in BC_i(p) have been marked to be removed //
15478 // in validatebowatcavityquad().  This routine actually remove the cut tets  //
15479 // of BC_i(p) and re-form the B_i(p).                                        //
15480 //                                                                           //
15482 
15483 void tetgenmesh::updatebowatcavityquad(list* tetlist, list* ceillist)
15484 {
15485   triface cavtet, neightet;
15486   face checksh;
15487   int remcount, i;
15488 
15489   remcount = 0;
15490   for (i = 0; i < tetlist->len(); i++) {
15491     cavtet = * (triface *)(* tetlist)[i];
15492     if (!infected(cavtet)) {
15493       tetlist->del(i, 1);
15494       remcount++;
15495       i--;
15496     }
15497   }
15498 
15499   // Are there tets have been cut in BC_i(p)?
15500   if (remcount > 0) {
15501     // Re-form B_i(p).
15502     ceillist->clear();
15503     for (i = 0; i < tetlist->len(); i++) {
15504       cavtet = * (triface *)(* tetlist)[i];
15505       for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15506         tspivot(cavtet, checksh);
15507         if (checksh.sh == dummysh) {
15508           sym(cavtet, neightet);
15509           if (!infected(neightet)) {
15510             ceillist->append(&cavtet); // Found a face of B_i(p).
15511           }
15512         } else {
15513           // Do not cross a boundary face.
15514           if (!sinfected(checksh)) {
15515             ceillist->append(&cavtet); // Found a face of B_i(p).
15516           }
15517         }
15518       }
15519     }
15520     if (b->verbose > 2) {
15521       printf("    Update BC_i(p): %d tets, %d faces.\n", tetlist->len(),
15522              ceillist->len());
15523     }
15524   }
15525 }
15526 
15528 //                                                                           //
15529 // updatebowatcavitysub()    Check and update CBC(p) and C(p).               //
15530 //                                                                           //
15531 // A CBC(p) is valid if all its subfaces are inside or on the hull of BC(p). //
15532 // A subface s of CBC(p) is invalid if it is in one of the two cases:        //
15533 //   (1) s is completely outside BC(p);                                      //
15534 //   (2) s has two adjacent tets but only one of them is in BC(p);           //
15535 // s is removed from CBC(p) if it is invalid. If there is an adjacent tet of //
15536 // s which is in BC(p), it gets removed from BC(p) too. If CBC(p) is updated,//
15537 // C(p) is re-formed.                                                        //
15538 //                                                                           //
15539 // A C(p) is valid if all its edges are on the hull of BC(p).  An edge e of  //
15540 // C(p) may be inside BC(p) if e is a segment and belongs to only one facet. //
15541 // To correct C(p), a tet of BC(p) which shields e gets removed.             //
15542 //                                                                           //
15543 // If BC(p) is formed with locally non-Delaunay check (b->conformdel > 0).   //
15544 // A boundary-consistent check is needed for non-segment edges of C(p). Let  //
15545 // e be such an edge, the subface f contains e and outside C(p) may belong   //
15546 // to B(p) due to the non-coplanarity of the facet definition.  The tet of   //
15547 // BC(p) containing f gets removed to avoid creating a degenerate new tet.   //
15548 //                                                                           //
15549 // 'cutcount' accumulates the total number of cuttets(not only by this call).//
15550 //                                                                           //
15552 
15553 void tetgenmesh::updatebowatcavitysub(list* sublist, list* subceillist,
15554   int* cutcount)
15555 {
15556   triface adjtet, rotface;
15557   face checksh, neighsh;
15558   face checkseg;
15559   point pa, pb, pc;
15560   REAL ori1, ori2;
15561   int remcount;
15562   int i, j;
15563 
15564   remcount = 0;
15565   // Check the validity of CBC(p).
15566   for (i = 0; i < sublist->len(); i++) {
15567     checksh = * (face *)(* sublist)[i];
15568     // Check two adjacent tets of s.
15569     for (j = 0; j < 2; j++) {
15570       stpivot(checksh, adjtet);
15571       if (adjtet.tet != dummytet) {
15572         if (!infected(adjtet)) {
15573           // Could be either case (1) or (2).
15574           suninfect(checksh); // s survives.
15575           // If the sym. adjtet exists, it should remove from BC(p) too.
15576           sesymself(checksh);
15577           stpivot(checksh, adjtet);
15578           if (adjtet.tet != dummytet) {
15579             if (infected(adjtet)) {
15580               // Found an adj. tet in BC(p), remove it.
15581               uninfect(adjtet);
15582               (*cutcount)++;
15583             }
15584           }
15585           // Remove s from C(p).
15586           sublist->del(i, 1);
15587           i--;
15588           remcount++;
15589           break;
15590         }
15591       }
15592       sesymself(checksh);
15593     }
15594   }
15595   if (remcount > 0) {
15596     if (b->verbose > 2) {
15597       printf("    Removed %d subfaces from CBC(p).\n", remcount);
15598     }
15599     // Re-generate C(p).
15600     subceillist->clear();
15601     for (i = 0; i < sublist->len(); i++) {
15602       checksh = * (face *)(* sublist)[i];
15603       for (j = 0; j < 3; j++) {
15604         spivot(checksh, neighsh);
15605         if (!sinfected(neighsh)) {
15606           subceillist->append(&checksh);
15607         }
15608         senextself(checksh);
15609       }
15610     }
15611     if (b->verbose > 2) {
15612       printf("    Update CBC(p): %d subs, %d edges.\n", sublist->len(),
15613              subceillist->len());
15614     }
15615   }
15616 
15617   // Check the validity of C(p).
15618   for (i = 0; i < subceillist->len(); i++) {
15619     checksh = * (face *)(* subceillist)[i];
15620     sspivot(checksh, checkseg);
15621     if (checkseg.sh != dummysh) {
15622       // A segment. Check if it is inside BC(p).
15623       stpivot(checksh, adjtet);
15624       if (adjtet.tet == dummytet) {
15625         sesym(checksh, neighsh);
15626         stpivot(neighsh, adjtet);
15627       }
15628       findedge(&adjtet, sorg(checkseg), sdest(checkseg));
15629       adjustedgering(adjtet, CCW);
15630       fnext(adjtet, rotface); // It's the same tet.
15631       // Rotate rotface (f), stop on either of the following cases:
15632       //   (a) meet a subface, or
15633       //   (b) enter an uninfected tet, or
15634       //   (c) rewind back to adjtet.
15635       do {
15636         if (!infected(rotface)) break; // case (b)
15637         tspivot(rotface, neighsh);
15638         if (neighsh.sh != dummysh) break; // case (a)
15639         // Go to the next tet of the facing ring.
15640         fnextself(rotface);
15641       } while (apex(rotface) != apex(adjtet));
15642       // Is it case (c)?
15643       if (apex(rotface) == apex(adjtet)) {
15644         // The segment is enclosed by BC(p), invalid cavity.
15645         pa = org(adjtet);
15646         pb = dest(adjtet);
15647         pc = apex(adjtet);
15648         // Find the shield tet and cut it. Notice that the shield tet may
15649         //   not be unique when there are four coplanar points, ie.,
15650         //   ori1 * ori2 == 0.0. In such case, choose either of them.
15651         fnext(adjtet, rotface);
15652         do {
15653           fnextself(rotface);
15654           assert(infected(rotface));
15655           ori1 = orient3d(pa, pb, pc, apex(rotface));
15656           ori2 = orient3d(pa, pb, pc, oppo(rotface));
15657         } while (ori1 * ori2 > 0.0);
15658         // Cut this tet from BC(p).
15659         uninfect(rotface);
15660         (*cutcount)++;
15661       }
15662     } else {
15663       /*// An edge. Check if boundary-consistency should be enforced.
15664       if (b->conformdel > 0) {
15665         // Get the adj-sub n at e, it must be outside C(p).
15666         spivot(checksh, neighsh);
15667         assert(!sinfected(neighsh));
15668         // Check if n is on B(p).
15669         for (j = 0; j < 2; j++) {
15670           stpivot(neighsh, adjtet);
15671           if (adjtet.tet != dummytet) {
15672             if (infected(adjtet)) {
15673               uninfect(adjtet);
15674               (*cutcount)++;
15675             }
15676           }
15677           sesymself(neighsh);
15678         }
15679       } */
15680     }
15681   }
15682 }
15683 
15685 //                                                                           //
15686 // trimbowatcavity()    Validate B(p), CBC(p)s and C(p)s, update BC(p).      //
15687 //                                                                           //
15688 // A B(p) is valid if all its faces are visible by p. If a face f of B(p) is //
15689 // found invisible by p, the tet of BC(p) containing f gets removed and B(p) //
15690 // is refromed. The new B(p) may still contain invisible faces by p. Iterat- //
15691 // ively do the above procedure until B(p) is satisfied.                     //
15692 //                                                                           //
15693 // A CBC(p) is valid if each subface of CBC(p) is either on the hull of BC(p)//
15694 // or completely inside BC(p). If a subface s of CBC(p) is not valid, it is  //
15695 // removed from CBC(p) and C(p) is reformed. If there exists a tet t of BC(p)//
15696 // containg s, t is removed from BC(p). The process for validating BC(p) and //
15697 // B(p) is re-excuted.                                                       //
15698 //                                                                           //
15699 // A C(p) is valid if each edge of C(p) is on the hull of BC(p). If an edge  //
15700 // e of C(p) is invalid (e should be a subsegment which only belong to one   //
15701 // facet), a tet of BC(p) which contains e and has two other faces shielding //
15702 // e is removed. The process for validating BC(p) and B(p) is re-excuted.    //
15703 //                                                                           //
15704 // If either BC(p) or CBC(p) becomes empty. No valid BC(p) is found, return  //
15705 // FALSE. else, return TRUE.                                                 //
15706 //                                                                           //
15708 
15709 bool tetgenmesh::trimbowatcavity(point bp, face* bpseg, int n, list** sublists,
15710   list** subceillists, list** tetlists, list** ceillists, REAL maxcosd)
15711 {
15712   bool valflag;
15713   int oldnum, cutnum, cutcount;
15714   int i;
15715 
15716   cutnum = 0; // Count the total number of cut-off tets of BC(p).
15717   valflag = true;
15718 
15719   do {
15720     // Validate BC(p), B(p).
15721     for (i = 0; i < n && valflag; i++) {
15722       oldnum = tetlists[i]->len();
15723       // Iteratively validate BC_i(p) and B_i(p).
15724       while (!validatebowatcavityquad(bp, ceillists[i], maxcosd)) {
15725         // Update BC_i(p) and B_i(p).
15726         updatebowatcavityquad(tetlists[i], ceillists[i]);
15727         valflag = tetlists[i]->len() > 0;
15728       }
15729       cutnum += (oldnum - tetlists[i]->len());
15730     }
15731     if (valflag && (sublists != (list **) NULL)) {
15732       // Validate CBC(p), C(p).
15733       cutcount = 0;
15734       for (i = 0; i < n; i++) {
15735         updatebowatcavitysub(sublists[i], subceillists[i], &cutcount);
15736         // Only do once if p is on a facet.
15737         if (bpseg == (face *) NULL) break; 
15738       }
15739       // Are there cut tets?
15740       if (cutcount > 0) {
15741         // Squeeze all cut tets in BC(p), keep valflag once it gets FLASE.
15742         for (i = 0; i < n; i++) {
15743           if (tetlists[i]->len() > 0) {
15744             updatebowatcavityquad(tetlists[i], ceillists[i]);
15745             if (valflag) {
15746               valflag = tetlists[i]->len() > 0;
15747             }
15748           }
15749         }
15750         cutnum += cutcount;
15751         // Go back to valid the updated BC(p).
15752         continue;
15753       }
15754     }
15755     break; // Leave the while-loop.
15756   } while (true);
15757 
15758   // Check if any CBC(p) becomes non-empty.
15759   if (valflag && (sublists != (list **) NULL)) {
15760     for (i = 0; i < n && valflag; i++) {
15761       valflag = (sublists[i]->len() > 0);
15762       if (bpseg == (face *) NULL) break; 
15763     }
15764   }
15765 
15766   if (valflag && (cutnum > 0)) {
15767     // Accumulate counters.
15768     if (bpseg != (face *) NULL) {
15769       updsegcount++;
15770     } else if (sublists != (list **) NULL) {
15771       updsubcount++;
15772     } else {
15773       updvolcount++;
15774     }
15775   }
15776 
15777   if (!valflag) {
15778     // Accumulate counters.
15779     if (bpseg != (face *) NULL) {
15780       failsegcount++;
15781     } else if (sublists != (list **) NULL) {
15782       failsubcount++;
15783     } else {
15784       failvolcount++;
15785     }
15786   }
15787 
15788   return valflag;
15789 }
15790 
15792 //                                                                           //
15793 // bowatinsertsite()    Insert a point using the Bowyer-Watson method.       //
15794 //                                                                           //
15795 // Parameters: 'bp' = p, 'splitseg' = S, 'n' = the number of quadrants,      //
15796 // 'sublists', an array of CBC_i(p)s, 'subceillists', an array of C_i(p)s,   //
15797 // 'tetlists', an array of BC_i(p)s, 'ceillists', an array of B_i(p)s.       //
15798 //                                                                           //
15799 // If p is inside the mesh domain, then S = NULL, n = 1, CBC(p) and C(p) are //
15800 //   NULLs. 'tetlists[0]' = BC(p), 'ceillists[0]' = B(p).                    //
15801 // If p is on a facet F, then S = NULL, n = 2, and 'subceillists[0]' = C(p), //
15802 //  'subceillists[1]' is not needed (set it to NULL). B_1(p) and B_2(p) are  //
15803 //  in 'ceillists[0]' and 'ceillists[1]'.                                    //
15804 // If p is on a segment S, then F(S) is a list of subfaces around S, and n = //
15805 //   len(F(S)), there are n C_i(p)s and B_i(p)s supplied in 'subceillists[i]'//
15806 //   and 'ceillists[i]'.                                                     //
15807 //                                                                           //
15808 // If 'verlist' != NULL, it returns a list of vertices which connect to p.   //
15809 //   This vertices are used for interpolating size of p.                     //
15810 //                                                                           //
15811 // If 'flipque' != NULL, it returns a list of internal faces of new tets in  //
15812 //   BC(p), faces on C(p)s are excluded. These faces may be locally non-     //
15813 //   Delaunay and will be flipped if they are flippable. Such non-Delaunay   //
15814 //   faces may exist when p is inserted to split an encroaching segment.     //
15815 //                                                                           //
15816 // 'chkencseg', 'chkencsub', and 'chkbadtet' are flags that indicate whether //
15817 // or not there should be checks for the creation of encroached subsegments, //
15818 // subfaces, or bad quality tets. If 'chkencseg' = TRUE, the encroached sub- //
15819 // segments are added to the list of subsegments to be split.                //
15820 //                                                                           //
15821 // On return, 'ceillists' returns Star(p).                                   //
15822 //                                                                           //
15824 
15825 void tetgenmesh::bowatinsertsite(point bp,face* splitseg,int n,list** sublists,
15826   list** subceillists, list** tetlists, list** ceillists, list* verlist,
15827   queue* flipque, bool chkencseg, bool chkencsub, bool chkbadtet)
15828 {
15829   list *ceillist, *subceillist; 
15830   triface oldtet, newtet, newface, rotface, neightet; 
15831   face oldsh, newsh, newedge, checksh;
15832   face spinsh, casingin, casingout;
15833   face *apsegshs, *pbsegshs;
15834   face apseg, pbseg, checkseg;
15835   point pa, pb, pc;
15836   REAL attrib, volume;
15837   int idx, i, j, k;
15838 
15839   apsegshs = NULL;
15840   pbsegshs = NULL;
15841 
15842   if (b->verbose > 1) {
15843     printf("    Insert point %d (%.12g, %.12g, %.12g)", pointmark(bp), bp[0],
15844            bp[1], bp[2]);
15845   }
15846   if (splitseg != (face *) NULL) {
15847     if (b->verbose > 1) {
15848       printf(" on segment.\n");
15849     }
15850     bowatsegcount++;
15851   } else {
15852     if (subceillists != (list **) NULL) {
15853       if (b->verbose > 1) {
15854         printf(" on facet.\n");
15855       }
15856       bowatsubcount++;
15857     } else {
15858       if (b->verbose > 1) {
15859         printf(" in volume.\n");
15860       }
15861       bowatvolcount++;
15862     }
15863   }
15864 
15865   // Create new tets to fill B(p).
15866   for (k = 0; k < n; k++) {
15867     // Create new tets from each B_i(p).
15868     ceillist = ceillists[k];
15869     for (i = 0; i < ceillist->len(); i++) {
15870       oldtet = * (triface *)(* ceillist)[i];
15871       adjustedgering(oldtet, CCW);
15872       pa = org(oldtet);
15873       pb = dest(oldtet);
15874       pc = apex(oldtet);
15875       maketetrahedron(&newtet);
15876       setorg(newtet, pa);
15877       setdest(newtet, pb);
15878       setapex(newtet, pc);
15879       setoppo(newtet, bp);
15880       for (j = 0; j < in->numberoftetrahedronattributes; j++) {
15881         attrib = elemattribute(oldtet.tet, j);
15882         setelemattribute(newtet.tet, j, attrib);
15883       }
15884       if (b->varvolume) {
15885         volume = volumebound(oldtet.tet);
15886         if (volume > 0.0) {
15887           if (!b->fixedvolume && b->refine) {
15888             // '-r -a' switches and a .vol file case. Enlarge the maximum
15889             //   volume constraint for the new tets. Hence the new points
15890             //   only spread near the original constrained tet.
15891             volume *= 1.2;
15892           }
15893         }
15894         setvolumebound(newtet.tet, volume);
15895       }
15896       sym(oldtet, neightet);
15897       tspivot(oldtet, checksh);
15898       if (neightet.tet != dummytet) {
15899         bond(newtet, neightet);
15900       }
15901       if (checksh.sh != dummysh) {
15902         tsbond(newtet, checksh);
15903       }
15904       if (verlist != (list *) NULL) {
15905         // Collect vertices connecting to p.
15906         idx = pointmark(pa);
15907         if (idx >= 0) {
15908           setpointmark(pa, -idx - 1);
15909           verlist->append(&pa);
15910         }
15911         idx = pointmark(pb);
15912         if (idx >= 0) {
15913           setpointmark(pb, -idx - 1);
15914           verlist->append(&pb);
15915         }
15916         idx = pointmark(pc);
15917         if (idx >= 0) {
15918           setpointmark(pc, -idx - 1);
15919           verlist->append(&pc);
15920         }
15921       }
15922       // Replace the tet by the newtet for checking the quality.
15923       * (triface *)(* ceillist)[i] = newtet;
15924     }
15925   }
15926   if (verlist != (list *) NULL) {
15927     // Uninfect collected vertices.
15928     for (i = 0; i < verlist->len(); i++) {
15929       pa = * (point *)(* verlist)[i];
15930       idx = pointmark(pa);
15931       setpointmark(pa, -(idx + 1));
15932     }
15933   }
15934 
15935   // Connect new tets of B(p). Not all faces of new tets can be connected,
15936   //   e.g., if there are empty B_i(p)s.
15937   for (k = 0; k < n; k++) {
15938     ceillist = ceillists[k];
15939     for (i = 0; i < ceillist->len(); i++) {
15940       newtet = * (triface *)(* ceillist)[i];
15941       newtet.ver = 0;
15942       for (j = 0; j < 3; j++) {
15943         fnext(newtet, newface);
15944         sym(newface, neightet);
15945         if (neightet.tet == dummytet) {
15946           // Find the neighbor face by rotating the faces at edge ab.
15947           esym(newtet, rotface);
15948           pa = org(rotface);
15949           pb = dest(rotface);
15950           while (fnextself(rotface));
15951           // Do we meet a boundary face?
15952           tspivot(rotface, checksh);
15953           if (checksh.sh != dummysh) {
15954             // Walk through the boundary and continue to rotate faces.
15955             do {
15956               findedge(&checksh, pa, pb);
15957               sfnextself(checksh);
15958               assert((sorg(checksh) == pa) && (sdest(checksh) == pb));
15959               stpivot(checksh, rotface);
15960               if (infected(rotface)) {
15961                 // Meet an old tet of B_i(p). This side is on the hull and
15962                 //   will be connected to a new subface created in C(p).
15963                 break;
15964               }
15965               findedge(&rotface, pa, pb);
15966               while (fnextself(rotface));
15967               tspivot(rotface, checksh);
15968             } while (checksh.sh != dummysh);
15969           }
15970           // The rotface has edge ab, but it may not have newpt.
15971           if (apex(rotface) == apex(newface)) { 
15972             // Bond the two tets together.
15973             bond(newface, rotface);
15974             // Queue (uniquely) this face if 'flipque' is given.
15975             if (flipque != (queue *) NULL) {
15976               enqueueflipface(newface, flipque);
15977             }
15978           }
15979         }
15980         enextself(newtet);
15981       }
15982     }
15983   }
15984 
15985   if (subceillists != (list **) NULL) {
15986     // There are C(p)s.
15987     if (splitseg != (face *) NULL) {
15988       // S (ab) is split by p.
15989       splitseg->shver = 0;
15990       pa = sorg(*splitseg);
15991       pb = sdest(*splitseg);
15992       // Allcate two arrays for saving the subface rings of the two new
15993       //   segments a->p and p->b.
15994       apsegshs = new face[n];
15995       pbsegshs = new face[n];
15996     }
15997 
15998     // For each C_k(p), do the following:
15999     //   (1) Create new subfaces to fill C_k(p), insert them into B(p);
16000     //   (2) Connect new subfaces to each other;
16001     for (k = 0; k < n; k++) {      
16002       subceillist = subceillists[k];
16003 
16004       // Check if 'hullsize' should be updated.
16005       oldsh = * (face *)(* subceillist)[0];
16006       stpivot(oldsh, neightet);
16007       if (neightet.tet != dummytet) {
16008         sesymself(oldsh);
16009         stpivot(oldsh, neightet);
16010       }
16011       if (neightet.tet == dummytet) {
16012         // The hull size changes.
16013         hullsize += (subceillist->len() - sublists[k]->len());
16014       }
16015 
16016       // (1) Create new subfaces to fill C_k(p), insert them into B(p).
16017       for (i = 0; i < subceillist->len(); i++) {
16018         oldsh = * (face *)(* subceillist)[i];
16019         makeshellface(subfaces, &newsh);
16020         setsorg(newsh, sorg(oldsh));
16021         setsdest(newsh, sdest(oldsh));
16022         setsapex(newsh, bp);
16023         if (b->quality && varconstraint) {
16024           setareabound(newsh, areabound(oldsh));
16025         }
16026         setshellmark(newsh, shellmark(oldsh));
16027         setshelltype(newsh, shelltype(oldsh));
16028         if (checkpbcs) {
16029           setshellpbcgroup(newsh, shellpbcgroup(oldsh));
16030         }
16031         // Replace oldsh by newsh at the edge.
16032         spivot(oldsh, casingout);
16033         sspivot(oldsh, checkseg);
16034         if (checkseg.sh != dummysh) {
16035           // A segment. Insert s into the face ring, ie, s_in -> s -> s_out.
16036           if (oldsh.sh != casingout.sh) {
16037             // s is not bonded to itself.
16038             spinsh = casingout;
16039             do {
16040               casingin = spinsh;
16041               spivotself(spinsh);
16042             } while (sapex(spinsh) != sapex(oldsh));
16043             assert(casingin.sh != oldsh.sh); 
16044             // Bond s_in -> s -> s_out (and dissolve s_in -> s_old -> s_out).
16045             sbond1(casingin, newsh);
16046             sbond1(newsh, casingout);
16047           } else {
16048             // Bond newsh -> newsh.
16049             sbond(newsh, newsh);
16050           }
16051           // Bond the segment.
16052           ssbond(newsh, checkseg);
16053         } else {
16054           // Bond s <-> s_out (and dissolve s_out -> s_old).
16055           sbond(newsh, casingout);
16056         }
16057 
16058         // Insert newsh into B(p). Use the coonections of oldsh.
16059         stpivot(oldsh, neightet);
16060         if (neightet.tet == dummytet) {
16061           sesymself(oldsh);
16062           sesymself(newsh); // Keep the same orientation as oldsh.
16063           stpivot(oldsh, neightet);
16064         }
16065         assert(infected(neightet));
16066         // Set on the rotating edge.
16067         findedge(&neightet, sorg(oldsh), sdest(oldsh));
16068         // Choose the rotating direction (to the inside of B(p)).
16069         adjustedgering(neightet, CCW);
16070         rotface = neightet;
16071         // Rotate face. Stop at a non-infected tet t (not in B(p)) or a
16072         //   hull face f (on B(p)). Get the neighbor n of t or f.  n is
16073         //   a new tet that has just been created to fill B(p).
16074         do {
16075           fnextself(rotface);
16076           sym(rotface, neightet);
16077           if (neightet.tet == dummytet) {
16078             tspivot(rotface, checksh);
16079             assert(checksh.sh != dummysh);
16080             stpivot(checksh, newtet);
16081             break;
16082           } else if (!infected(neightet)) {
16083             sym(neightet, newtet);
16084             break;
16085           }
16086         } while (true);
16087         assert(newtet.tet != rotface.tet);
16088         // Set the rotating edge of n.
16089         findedge(&newtet, sorg(oldsh), sdest(oldsh));
16090         // Choose the rotating direction (to the inside of B(p)).
16091         adjustedgering(newtet, CCW);
16092         fnext(newtet, newface);
16093         assert(apex(newface) == bp);
16094         // newsh has already been oriented toward n.
16095         tsbond(newface, newsh);
16096         sym(newface, neightet); // 'neightet' maybe outside.
16097         sesymself(newsh);
16098         tsbond(neightet, newsh); // Bond them anyway.
16099 
16100         // Replace oldsh by newsh in list.
16101         * (face *)(* subceillist)[i] = newsh;
16102       }
16103 
16104       // (2) Connect new subfaces to each other.
16105       for (i = 0; i < subceillist->len(); i++) {
16106         // Get a face cdp.
16107         newsh = * (face *)(* subceillist)[i];
16108         // Get a new tet containing cdp.
16109         stpivot(newsh, newtet);
16110         if (newtet.tet == dummytet) {
16111           sesymself(newsh);
16112           stpivot(newsh, newtet);
16113         }
16114         for (j = 0; j < 2; j++) {
16115           if (j == 0) {
16116             senext(newsh, newedge); // edge dp.
16117           } else {
16118             senext2(newsh, newedge); // edge pc.
16119             sesymself(newedge); // edge cp.
16120           }
16121           if (splitseg != (face *) NULL) {
16122             // Don not operate on newedge if it is ap or pb.
16123             if (sorg(newedge) == pa) {
16124               apsegshs[k] = newedge;
16125               continue;
16126             } else if (sorg(newedge) == pb) {
16127               pbsegshs[k] = newedge;
16128               continue;
16129             }
16130           }
16131           // There should no segment inside the cavity. Check it.
16132           sspivot(newedge, checkseg);
16133           assert(checkseg.sh == dummysh);
16134           spivot(newedge, casingout);
16135           if (casingout.sh == dummysh) {
16136             rotface = newtet;
16137             findedge(&rotface, sorg(newedge), sdest(newedge));
16138             // Rotate newtet until meeting a new subface which contains
16139             //   newedge. It must exist since newedge is not a seg.
16140             adjustedgering(rotface, CCW);
16141             do {
16142               fnextself(rotface);
16143               tspivot(rotface, checksh);
16144               if (checksh.sh != dummysh) break;
16145             } while (true);
16146             findedge(&checksh, sorg(newedge), sdest(newedge));
16147             sbond(newedge, checksh);
16148           }
16149         }
16150       }
16151       // Only do once if p is on a facet.
16152       if (splitseg == (face *) NULL) break;
16153     } // for (k = 0; k < n; k++)
16154 
16155     if (splitseg != (face *) NULL) {
16156       // Update a->b to be a->p.
16157       apseg = *splitseg;
16158       setsdest(apseg, bp);
16159       // Create a new subsegment p->b.
16160       makeshellface(subsegs, &pbseg);
16161       setsorg(pbseg, bp);
16162       setsdest(pbseg, pb);
16163       // p->b gets the same mark and segment type as a->p.
16164       setshellmark(pbseg, shellmark(apseg));
16165       setshelltype(pbseg, shelltype(apseg));
16166       if (b->quality && varconstraint) {
16167         // Copy the area bound into the new subsegment.
16168         setareabound(pbseg, areabound(apseg));
16169       }
16170       senext(apseg, checkseg);
16171       // Get the old connection at b of a->b.
16172       spivot(checkseg, casingout);
16173       // Bond a->p and p->b together.
16174       senext2(pbseg, casingin);
16175       sbond(casingin, checkseg);
16176       if (casingout.sh != dummysh) {
16177         // There is a subsegment connect at b of p->b.
16178         casingout.shver = 0;
16179 #ifdef SELF_CHECK
16180         assert(sorg(casingout) == pb); 
16181 #endif
16182         senext2self(casingout);
16183         senext(pbseg, casingin);
16184         sbond(casingin, casingout);
16185       }
16186 
16187       // Bond all new subfaces to a->p and p->b.
16188       for (i = 0; i < n; i++) {
16189         spinsh = apsegshs[i];
16190         findedge(&spinsh, pa, bp);
16191         ssbond(spinsh, apseg);
16192         spinsh = pbsegshs[i];
16193         findedge(&spinsh, bp, pb);
16194         ssbond(spinsh, pbseg);
16195       }
16196       // Bond all subfaces share at a->p together.
16197       for (i = 0; i < n; i++) {
16198         spinsh = apsegshs[i];
16199         if (i < (n - 1)) {
16200           casingout = apsegshs[i + 1];
16201         } else {
16202           casingout = apsegshs[0];
16203         }
16204         sbond1(spinsh, casingout);
16205       }
16206       // Bond all subfaces share at p->b together.
16207       for (i = 0; i < n; i++) {
16208         spinsh = pbsegshs[i];
16209         if (i < (n - 1)) {
16210           casingout = pbsegshs[i + 1];
16211         } else {
16212           casingout = pbsegshs[0];
16213         }
16214         sbond1(spinsh, casingout);
16215       }
16216       delete [] apsegshs;
16217       delete [] pbsegshs;
16218 
16219       // Check for newly encroached subsegments if the flag is set.
16220       if (chkencseg) {
16221         // Check if a->p and p->b are encroached by other vertices.
16222         checkseg4encroach(&apseg, NULL, NULL, true);
16223         checkseg4encroach(&pbseg, NULL, NULL, true);
16224         // Check if the adjacent segments are encroached by p.
16225         tallencsegs(bp, n, ceillists);
16226       }
16227     } // if (splitseg != (face *) NULL) 
16228 
16229     // Delete subfaces of old CBC_i(p)s.
16230     for (k = 0; k < n; k++) {
16231       for (i = 0; i < sublists[k]->len(); i++) {
16232         oldsh = * (face *)(* (sublists[k]))[i];
16233         shellfacedealloc(subfaces, oldsh.sh);
16234       }
16235       // Clear the list so that the subs will not get unmarked later in
16236       //   routine releasebowatcavity() which only frees the memory.
16237       sublists[k]->clear();
16238       // Only do once if p is on a facet.
16239       if (splitseg == (face *) NULL) break; 
16240     }
16241 
16242     // Check for newly encroached subfaces if the flag is set.
16243     if (chkencsub) {
16244       // Check if new subfaces of C_i(p) are encroached by other vertices.
16245       for (k = 0; k < n; k++) {
16246         subceillist = subceillists[k];
16247         for (i = 0; i < subceillist->len(); i++) {
16248           newsh = * (face *)(* subceillist)[i];
16249           checksub4encroach(&newsh, NULL, true);
16250         }
16251         // Only do once if p is on a facet.
16252         if (splitseg == (face *) NULL) break; 
16253       }
16254       // Check if the adjacent subfaces are encroached by p.
16255       tallencsubs(bp, n, ceillists);
16256     }
16257   } // if (subceillists != (list **) NULL)
16258 
16259   // Delete tets of old BC_i(p)s.
16260   for (k = 0; k < n; k++) {
16261     for (i = 0; i < tetlists[k]->len(); i++) {
16262       oldtet = * (triface *)(* (tetlists[k]))[i];
16263       tetrahedrondealloc(oldtet.tet);
16264     }
16265     // Clear the list so that the tets will not get unmarked later in
16266     //   routine releasebowatcavity() which only frees the memory.
16267     tetlists[k]->clear();
16268   }
16269 
16270   // check for bad quality tets if the flags is set.
16271   if (chkbadtet) {
16272     for (k = 0; k < n; k++) {
16273       ceillist = ceillists[k];
16274       for (i = 0; i < ceillist->len(); i++) {
16275         newtet = * (triface *)(* ceillist)[i];
16276         checktet4badqual(&newtet, true);
16277       }
16278     }
16279   }
16280 
16281   if (flipque != (queue *) NULL) {
16282     // Newly created internal faces of BC(p) (excluding faces on C(p)s) are
16283     //   in 'flipque'.  Some of these faces may be locally non-Delaunay due,
16284     //   to the existence of non-constrained tets. check and fix them.
16285     repairflipcount += flip(flipque, NULL);
16286   }
16287 }
16288 
16289 //
16290 // End of mesh transformation routines
16291 //
16292 
16293 //
16294 // Begin Delaunay tetrahedralization routines
16295 //
16296 
16298 //                                                                           //
16299 // formstarpolyhedron()    Get the star ployhedron of a point 'pt'.          //
16300 //                                                                           //
16301 // The polyhedron P is formed by faces of tets having 'pt' as a vertex.  If  //
16302 // 'complete' is TRUE, P is the complete star of 'pt'. Otherwise, P is boun- //
16303 // ded by subfaces, i.e. P is only part of the star of 'pt'.                 //
16304 //                                                                           //
16305 // 'tetlist' T returns the tets, it has one of such tets on input. Moreover, //
16306 // if t is in T, then oppo(t) = p.  Topologically, T is the star of p;  and  //
16307 // the faces of T is the link of p. 'verlist' V returns the vertices of T.   //
16308 //                                                                           //
16310 
16311 void tetgenmesh::formstarpolyhedron(point pt, list* tetlist, list* verlist,
16312   bool complete)
16313 {
16314   triface starttet, neightet;
16315   face checksh;
16316   point ver[3];
16317   int idx, i, j;
16318 
16319   // Get a tet t containing p.
16320   starttet = * (triface *)(* tetlist)[0];
16321   // Let oppo(t) = p.
16322   for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
16323     if (oppo(starttet) == pt) break;
16324   }
16325   assert(starttet.loc < 4);
16326   // Add t into T.
16327   * (triface *)(* tetlist)[0] = starttet;
16328   infect(starttet);
16329   if (verlist != (list *) NULL) {
16330     // Add three verts of t into V.
16331     ver[0] = org(starttet);
16332     ver[1] = dest(starttet);
16333     ver[2] = apex(starttet);
16334     for (i = 0; i < 3; i++) {
16335       // Mark the vert by inversing the index of the vert.
16336       idx = pointmark(ver[i]);
16337       setpointmark(ver[i], -idx - 1); // -1 to distinguish the zero.
16338       verlist->append(&(ver[i]));
16339     }
16340   }
16341 
16342   // Find other tets by a broadth-first search.
16343   for (i = 0; i < tetlist->len(); i++) {
16344     starttet = * (triface *)(* tetlist)[i];
16345     starttet.ver = 0;
16346     for (j = 0; j < 3; j++) {
16347       fnext(starttet, neightet);
16348       tspivot(neightet, checksh);
16349       // Should we cross a subface.
16350       if ((checksh.sh == dummysh) || complete) {
16351         // Get the neighbor n.
16352         symself(neightet);
16353         if ((neightet.tet != dummytet) && !infected(neightet)) {
16354           // Let oppo(n) = p.
16355           for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
16356             if (oppo(neightet) == pt) break;
16357           }
16358           assert(neightet.loc < 4);
16359           // Add n into T.
16360           infect(neightet);
16361           tetlist->append(&neightet);
16362           if (verlist != (list *) NULL) {
16363             // Add the apex vertex in n into V.
16364             ver[0] = org(starttet);
16365             ver[1] = dest(starttet);
16366             findedge(&neightet, ver[0], ver[1]);
16367             ver[2] = apex(neightet);
16368             idx = pointmark(ver[2]);
16369             if (idx >= 0) {
16370               setpointmark(ver[2], -idx - 1);
16371               verlist->append(&(ver[2]));
16372             }
16373           }
16374         }
16375       }
16376       enextself(starttet);
16377     }
16378   }
16379 
16380   // Uninfect tets.
16381   for (i = 0; i < tetlist->len(); i++) {
16382     starttet = * (triface *)(* tetlist)[i];
16383     uninfect(starttet);
16384   }
16385   if (verlist != (list *) NULL) {
16386     // Uninfect vertices.
16387     for (i = 0; i < verlist->len(); i++) {
16388       ver[0] = * (point *)(* verlist)[i];
16389       idx = pointmark(ver[0]);
16390       setpointmark(ver[0], -(idx + 1));
16391     }
16392   }
16393 }
16394 
16396 //                                                                           //
16397 // unifypoint()    Unify two distinct points if they're very close.          //
16398 //                                                                           //
16399 // This function is used for dealing with inputs from CAD tools.  Two points //
16400 // p and q are unified if: dist(p, q) / longest < eps.  Where dist() is the  //
16401 // Euclidean distance between p and q, longest is the maximum edge size of   //
16402 // the input point set, eps is the tolerrence specified by user, default is  //
16403 // 1e-6, it can be adjusted by '-T' switch.                                  //
16404 //                                                                           //
16406 
16407 bool tetgenmesh::unifypoint(point testpt, triface *starttet, enum locateresult
16408   loc, REAL eps)
16409 {
16410   triface symtet, spintet;
16411   point checkpt, tapex;
16412   REAL tol;
16413   bool merged;
16414   int hitbdry;
16415   int i;
16416 
16417   merged = false;
16418   tol = longest * eps;
16419   if ((loc == OUTSIDE) || (loc == INTETRAHEDRON) || (loc == ONFACE)) {
16420     // Check p is close to the four corners of the tet.
16421     for (i = 0; i < 4; i++) {
16422       checkpt = (point) starttet->tet[4 + i];
16423       if (distance(testpt, checkpt) < tol) {
16424         merged = true; // Found a merge point p'.
16425         break;
16426       }
16427     }
16428     if (!merged && (loc == ONFACE)) {
16429       // Check the opposite point of the neighbor tet if it exists.
16430       sym(*starttet, symtet);
16431       if (symtet.tet != dummytet) {
16432         checkpt = oppo(symtet);
16433         if (distance(testpt, checkpt) < tol) {
16434           merged = true; // Found a merge point p'.
16435         }
16436       }
16437     }
16438   } else if (loc == ONEDGE) {
16439     // Check two endpoints of the edge.
16440     checkpt = org(*starttet);
16441     if (distance(testpt, checkpt) < tol) {
16442       merged = true; // Found a merge point p'.
16443     }
16444     if (!merged) {
16445       checkpt = dest(*starttet);
16446       if (distance(testpt, checkpt) < tol) {
16447         merged = true; // Found a merge point p'.
16448       }
16449     }
16450     if (!merged) {
16451       // Check apexes of the faces having the edge.
16452       spintet = *starttet;
16453       tapex = apex(*starttet);
16454       hitbdry = 0;
16455       do {
16456         checkpt = apex(spintet);
16457         if (distance(testpt, checkpt) < tol) {
16458           merged = true; // Found a merge point p'.
16459           break;
16460         }
16461         if (!fnextself(spintet)) {
16462           hitbdry++;
16463           if (hitbdry < 2) {
16464             esym(*starttet, spintet);
16465             if (!fnextself(spintet)) {
16466               hitbdry++;
16467             }
16468           }
16469         }
16470       } while ((apex(spintet) != tapex) && (hitbdry < 2));
16471     }
16472   }
16473   if (merged) {
16474     if (b->object != tetgenbehavior::STL) {
16475       if (!b->quiet) {
16476         printf("Warning:  Point %d is unified to point %d.\n",
16477                pointmark(testpt), pointmark(checkpt));
16478       }
16479       // Count the number of duplicated points.
16480       dupverts++;
16481     }
16482     // Remember it is a duplicated point.
16483     setpointtype(testpt, DUPLICATEDVERTEX);
16484     // Set a pointer to the point it duplicates.
16485     setpoint2ppt(testpt, checkpt);
16486   }
16487   return merged;
16488 }
16489 
16491 //                                                                           //
16492 // incrflipdelaunay()   Construct a delaunay tetrahedrization from a set of  //
16493 //                      3D points by the incremental flip algorithm.         //
16494 //                                                                           //
16495 // The incremental flip algorithm (by Edelsbrunner and Shah) can be describ- //
16496 // ed as follows:                                                            //
16497 //                                                                           //
16498 //   S be a set of points in 3D, Let 4 <= i <= n and assume that the         //
16499 //   Delaunay tetrahedralization of the first i-1 points in S is already     //
16500 //   constructed; call it D(i-1). Add the i-th point p_i (belong to S) to    //
16501 //   D(i-1), and restore Delaunayhood by flipping; this result in D(i).      //
16502 //   Repeat this procedure until i = n.                                      //
16503 //                                                                           //
16504 // This strategy always leads to the Delaunay triangulation of a point set.  //
16505 // The return value is the number of convex hull faces of D.                 //
16506 //                                                                           //
16508 
16509 void tetgenmesh::incrflipdelaunay(triface* oldtet, point* insertarray, 
16510   long arraysize, bool jump, bool merge, REAL eps, queue* flipque)
16511 {
16512   triface newtet, searchtet;
16513   point swappt, lastpt;
16514   enum locateresult loc;
16515   REAL det, n[3];
16516   REAL attrib, volume;
16517   int i, j;
16518 #ifdef SELF_CHECK
16519   clock_t loc_start, loc_end;
16520 #endif
16521   
16522   det = 0.0;
16523   if (b->verbose > 0) {
16524     printf("  Creating initial tetrahedralization.\n");
16525   }
16526 
16527   // The initial tetrahedralization T only has one tet formed by 4 affinely
16528   //   linear independent vertices of the point set V = 'insertarray'. The
16529   //   first point a = insertarray[0].
16530  
16531   // Get the second point b, that is not identical or very close to a.
16532   for (i = 1; i < arraysize; i++) {
16533     det = distance(insertarray[0], insertarray[i]);
16534     if (det > (longest * eps)) break;
16535   }
16536   if (i == arraysize) {
16537     printf("\nAll points seem to be identical.\n");
16538     return;
16539   } else {
16540     // Swap to move b from index i to index 1.
16541     swappt = insertarray[i];
16542     insertarray[i] = insertarray[1];
16543     insertarray[1] = swappt;  
16544   }
16545   // Get the third point c, that is not collinear with a and b.
16546   for (i++; i < arraysize; i++) {
16547     if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps)) 
16548       break;
16549   }
16550   if (i == arraysize) {
16551     printf("\nAll points seem to be collinear.\n");
16552     return;
16553   } else {
16554     // Swap to move c from index i to index 2.
16555     swappt = insertarray[i];
16556     insertarray[i] = insertarray[2];
16557     insertarray[2] = swappt;
16558   }
16559   // Get the fourth point d, that is not coplanar with a, b, and c.
16560   for (i++; i < arraysize; i++) {
16561     det = orient3d(insertarray[0], insertarray[1], insertarray[2],
16562                    insertarray[i]);
16563     if (det == 0.0) continue;
16564     if (!iscoplanar(insertarray[0], insertarray[1], insertarray[2],
16565                     insertarray[i], det, eps)) break;
16566   }
16567   if (i == arraysize) {
16568     // It's a 2D problem.
16569     in->mesh_dim = 2;
16570     // All points are coplanar.
16571     if (b->plc) {
16572       // Create an abovepoint. Maybe a surface triangulation can be formed.
16573       facenormal(insertarray[0], insertarray[1], insertarray[2], n, &det);
16574       if (det != 0.0) for (j = 0; j < 3; j++) n[j] /= det;
16575       // Take the average edge length of the bounding box.
16576       det = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
16577       // Temporarily create a point. It will be removed by jettison();
16578       makepoint(&lastpt);
16579       for (j = 0; j < 3; j++) lastpt[j] = insertarray[0][j] + det * n[j];
16580       abovepoint = lastpt;
16581       det = orient3d(insertarray[0], insertarray[1], insertarray[2], lastpt);
16582       // The index of the next inserting point is 3.
16583       i = 3;
16584     } else {
16585       printf("\nAll points seem to be coplanar.\n");
16586       return;
16587     }
16588   } else {
16589     // Swap to move d from index i to index 3.
16590     swappt = insertarray[i];
16591     insertarray[i] = insertarray[3];
16592     insertarray[3] = swappt;
16593     lastpt = insertarray[3];
16594     // The index of the next inserting point is 4.
16595     i = 4;
16596   }
16597   
16598   // Create the initial tet.
16599   maketetrahedron(&newtet);
16600   if (det > 0.0) {
16601     // For keeping the positive orientation.
16602     swappt = insertarray[0];
16603     insertarray[0] = insertarray[1];
16604     insertarray[1] = swappt;
16605   }
16606   if (b->verbose > 2) {
16607     printf("  Create the first tet (%d, %d, %d, %d).\n",
16608            pointmark(insertarray[0]), pointmark(insertarray[1]),
16609            pointmark(insertarray[2]), pointmark(lastpt));
16610   }
16611   setorg(newtet, insertarray[0]);
16612   setdest(newtet, insertarray[1]);
16613   setapex(newtet, insertarray[2]);
16614   setoppo(newtet, lastpt);
16615   if (oldtet != (triface *) NULL) {
16616     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
16617       attrib = elemattribute(oldtet->tet, j);
16618       setelemattribute(newtet.tet, j, attrib);
16619     }
16620     if (b->varvolume) {
16621       volume = volumebound(oldtet->tet);
16622       setvolumebound(newtet.tet, volume);
16623     }
16624   }
16625   // Set vertex type be FREEVOLVERTEX if it has no type yet.
16626   if (pointtype(insertarray[0]) == UNUSEDVERTEX) {
16627     setpointtype(insertarray[0], FREEVOLVERTEX);
16628   }
16629   if (pointtype(insertarray[1]) == UNUSEDVERTEX) {
16630     setpointtype(insertarray[1], FREEVOLVERTEX);
16631   }
16632   if (pointtype(insertarray[2]) == UNUSEDVERTEX) {
16633     setpointtype(insertarray[2], FREEVOLVERTEX);
16634   }
16635   if (pointtype(lastpt) == UNUSEDVERTEX) {
16636     setpointtype(lastpt, FREEVOLVERTEX);
16637   }
16638   // Bond to 'dummytet' for point location.
16639   dummytet[0] = encode(newtet);
16640   if (b->verbose > 3) {
16641     printf("    Creating tetra ");
16642     printtet(&newtet);
16643   }
16644   // At init, all faces of this tet are hull faces.
16645   hullsize = 4;
16646 
16647   if (b->verbose > 0) {
16648     printf("  Incrementally inserting points.\n");
16649   }
16650 
16651   flip23s = flip32s = flip22s = flip44s = 0;
16652   searchtet.tet = (tetrahedron *) NULL;
16653 
16654   // Insert the rest of points, one by one.
16655   for (; i < arraysize; i++) {
16656     // Locate p_i in T.
16657 #ifdef SELF_CHECK
16658     loc_start = clock();
16659 #endif
16660     if (jump) {
16661       loc = locate(insertarray[i], &searchtet);
16662     } else {
16663       loc = preciselocate(insertarray[i], &searchtet, tetrahedrons->items);
16664     }
16665 #ifdef SELF_CHECK
16666     loc_end = clock();
16667     tloctime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16668 #endif
16669     // Keep current search state for next searching.
16670     recenttet = searchtet;
16671     if (loc == ONVERTEX) {
16672       if (b->object != tetgenbehavior::STL) {
16673         if (!b->quiet) {
16674           printf("Warning:  Point %d is identical with point %d.\n",
16675                  pointmark(insertarray[i]), pointmark(org(searchtet)));
16676         }
16677       }
16678       // Count the number of duplicated points.
16679       dupverts++;
16680       // Remember it is a duplicated point.
16681       setpointtype(insertarray[i], DUPLICATEDVERTEX);
16682       if (b->plc || b->refine) {
16683         // Set a pointer to the point it duplicates.
16684         setpoint2ppt(insertarray[i], org(searchtet));
16685       }
16686       continue; // p_i is not inserted.
16687     }
16688     if (merge) {
16689       // Unify p_i if it is too close to a point of T.
16690       if (unifypoint(insertarray[i], &searchtet, loc, eps)) {
16691         continue; // p_i is not inserted.
16692       }
16693     }
16694     // Insert p_i in T.
16695     if (loc != OUTSIDE) {
16696       if (b->verbose > 1) {
16697         printf("  Insert point %d in tetrahedralization.\n",
16698                pointmark(insertarray[i]));
16699       }
16700       if (loc == INTETRAHEDRON) {
16701         splittetrahedron(insertarray[i], &searchtet, flipque);
16702       } else if (loc == ONFACE) {
16703         splittetface(insertarray[i], &searchtet, flipque);
16704       } else if (loc == ONEDGE) {
16705         splittetedge(insertarray[i], &searchtet, flipque);
16706       }
16707     } else {
16708       if (b->verbose > 1) {
16709         printf("  Insert point %d on convex hull.\n",
16710                pointmark(insertarray[i]));
16711       }
16712       inserthullsite(insertarray[i], &searchtet, flipque);
16713     }
16714     if (pointtype(insertarray[i]) == UNUSEDVERTEX) {
16715       // p_i becomes a (volume) vertex of T.
16716       setpointtype(insertarray[i], FREEVOLVERTEX);
16717     }
16718 #ifdef SELF_CHECK
16719     loc_start = clock();
16720 #endif
16721     if (!b->noflip) {
16722       // Recover Delaunayness of T by flipping.
16723       flip(flipque, NULL); 
16724     } else {
16725       lawson(NULL, flipque);
16726       // T remains regular.
16727       // flipque->clear();
16728     }
16729 #ifdef SELF_CHECK
16730     loc_end = clock();
16731     tfliptime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16732 #endif
16733   }
16734 
16735   if (b->verbose > 0) {
16736     printf("  %ld Flips (T23 %ld, T32 %ld, T22 %ld, T44 %ld)\n",
16737       flip23s+flip32s+flip22s+flip44s, flip23s, flip32s, flip22s, flip44s);
16738   }
16739 }
16740 
16742 //                                                                           //
16743 // delaunizevertices()    Form a Delaunay tetrahedralization.                //
16744 //                                                                           //
16745 // Given a point set V (saved in 'points').  The Delaunay tetrahedralization //
16746 // D of V is created by incrementally inserting vertices. Returns the number //
16747 // of triangular faces bounding the convex hull of D.                        //
16748 //                                                                           //
16750 
16751 long tetgenmesh::delaunizevertices()
16752 {
16753   queue *flipque;
16754   point *insertarray;
16755   long arraysize;
16756   int i, j;
16757 
16758   if (!b->quiet) {
16759     if (!b->noflip) {
16760       printf("Constructing Delaunay tetrahedralization.\n");
16761     } else {
16762       printf("Constructing regular tetrahedralization.\n");
16763     }
16764   }
16765 
16766   flipque = new queue(sizeof(badface));
16767   // Prepare the array of points for inserting.
16768   arraysize = points->items;
16769   insertarray = new point[arraysize];  
16770   points->traversalinit();
16771 
16772   // Randomize the point order.
16773   // randomseed = b->srandseed;
16774   for (i = 0; i < arraysize; i++) {
16775     j = (int) randomnation(i + 1); // 0 <= j <= i;
16776     insertarray[i] = insertarray[j];
16777     insertarray[j] = pointtraverse();
16778   }
16779 
16780   // Use lawson flip.
16781   b->noflip = 1;
16782 
16783   // Form the DT by incremental flip Delaunay algorithm.
16784   incrflipdelaunay(NULL, insertarray, arraysize, true, b->plc, b->epsilon,
16785                    flipque);
16786 
16787   b->noflip = 0;
16788 
16789   delete [] insertarray;
16790   delete flipque;
16791   return hullsize;
16792 }
16793 
16794 //
16795 // End Delaunay tetrahedralization routines
16796 //
16797 
16798 //
16799 // Begin of surface triangulation routines
16800 //
16801 
16803 //                                                                           //
16804 // formstarpolygon()    Form the star polygon of a point in facet.           //
16805 //                                                                           //
16806 // The polygon P is formed by all coplanar subfaces having 'pt' as a vertex. //
16807 // P is bounded by segments, e.g, if no segments, P is the full star of pt.  //
16808 //                                                                           //
16809 // 'trilist' T returns the subfaces, it has one of such subfaces on input.   //
16810 // In addition, if f is in T, then sapex(f) = p. 'vertlist' V are verts of P.//
16811 // Topologically, T is the star of p; V and the edges of T are the link of p.//
16812 //                                                                           //
16814 
16815 void tetgenmesh::formstarpolygon(point pt, list* trilist, list* vertlist)
16816 {
16817   face steinsh, lnextsh, rnextsh;
16818   face checkseg;
16819   point pa, pb, pc, pd;
16820   int i;
16821 
16822   // Get a subface f containing p.
16823   steinsh = * (face *)(* trilist)[0];
16824   steinsh.shver = 0; // CCW
16825   // Let sapex(f) be p.
16826   for (i = 0; i < 3; i++) {
16827     if (sapex(steinsh) == pt) break;
16828     senextself(steinsh);
16829   }
16830   assert(i < 3);
16831   // Add the edge f into list.
16832   * (face *)(* trilist)[0] = steinsh;
16833   pa = sorg(steinsh);
16834   pb = sdest(steinsh);
16835   if (vertlist != (list *) NULL) {
16836     // Add two verts a, b into V,
16837     vertlist->append(&pa);
16838     vertlist->append(&pb);
16839   }
16840 
16841   // Rotate edge pa to the left (CW) until meet pb or a segment.
16842   lnextsh = steinsh;
16843   pc = pa;
16844   do {
16845     senext2self(lnextsh);
16846     assert(sorg(lnextsh) == pt);
16847     sspivot(lnextsh, checkseg);
16848     if (checkseg.sh != dummysh) break; // Do not cross a segment.
16849     // Get neighbor subface n (must exist).
16850     spivotself(lnextsh);
16851     if (lnextsh.sh == dummysh) break; // It's a hull edge.
16852     // Go to the edge ca opposite to p.
16853     if (sdest(lnextsh) != pt) sesymself(lnextsh);
16854     assert(sdest(lnextsh) == pt);
16855     senext2self(lnextsh);
16856     // Add n (at edge ca) to T.
16857     trilist->append(&lnextsh);
16858     // Add edge ca to E.
16859     pc = sorg(lnextsh);
16860     if (pc == pb) break; // Rotate back.
16861     if (vertlist != (list *) NULL) {
16862       // Add vert c into V.
16863       vertlist->append(&pc);
16864     }
16865   } while (true);
16866 
16867   if (pc != pb) {
16868     // Rotate edge bp to the right (CCW) until meet a segment.
16869     rnextsh = steinsh;
16870     do {
16871       senextself(rnextsh);
16872       assert(sdest(rnextsh) == pt);
16873       sspivot(rnextsh, checkseg);
16874       if (checkseg.sh != dummysh) break; // Do not cross a segment.
16875       // Get neighbor subface n (must exist).
16876       spivotself(rnextsh);
16877       if (rnextsh.sh == dummysh) break; // It's a hull edge.
16878       // Go to the edge bd opposite to p.
16879       if (sorg(rnextsh) != pt) sesymself(rnextsh);
16880       assert(sorg(rnextsh) == pt);
16881       senextself(rnextsh);
16882       // Add n (at edge bd) to T.
16883       trilist->append(&rnextsh);
16884       // Add edge bd to E.
16885       pd = sdest(rnextsh);
16886       if (pd == pa) break; // Rotate back.
16887       if (vertlist != (list *) NULL) {
16888         // Add vert d into V.
16889         vertlist->append(&pd);
16890       }
16891     } while (true);
16892   }
16893 }
16894 
16896 //                                                                           //
16897 // About the 'abovepoint'                                                    //
16898 //                                                                           //
16899 // The 'abovepoint' of a facet is a point which is exactly non-coplanar with //
16900 // the plane containing that facet.  With such an point, the 3D predicates:  //
16901 // orient3d(), and insphere() can be used to substitute the corresponding 2D //
16902 // siblings, e.g. orient2d(), and incircle().  Its location is not critical, //
16903 // but floating-point accuracy is improved if it is nicely placed over the   //
16904 // facet, not too close or too far away.                                     //
16905 //                                                                           //
16906 // We take the convention that the abovepoint of a facet always lies above   //
16907 // the facet. By this convention, given three points a, b, and c in a facet, //
16908 // we say c has the counterclockwise order with ab is corresponding to say   //
16909 // that c is below the plane abp, where p is the lift point.                 //
16910 //                                                                           //
16912 
16914 //                                                                           //
16915 // getfacetabovepoint()    Get a point above a plane pass through a facet.   //
16916 //                                                                           //
16917 // The calculcated point is saved in 'facetabovepointarray'. The 'abovepoint'//
16918 // is set on return.                                                         //
16919 //                                                                           //
16921 
16922 void tetgenmesh::getfacetabovepoint(face* facetsh)
16923 {
16924   list *verlist, *trilist, *tetlist;
16925   triface adjtet;
16926   face symsh;
16927   point p1, p2, p3, pa;
16928   enum locateresult loc;
16929   REAL smallcos, cosa;
16930   REAL largevol, volume;
16931   REAL v1[3], v2[3], len;
16932   int smallidx, largeidx;
16933   int shmark;
16934   int i, j;
16935 
16936   abovecount++;
16937   // Initialize working lists.
16938   verlist = new list(sizeof(point *), NULL);
16939   trilist = new list(sizeof(face), NULL);
16940   tetlist = new list(sizeof(triface), NULL);
16941 
16942   // Get three pivotal points p1, p2, and p3 in the facet as a base triangle
16943   //   which is non-trivil and has good base angle (close to 90 degree).
16944 
16945   // p1 is chosen as the one which has the smallest index in pa, pb, pc.
16946   p1 = sorg(*facetsh);
16947   pa = sdest(*facetsh);
16948   if (pointmark(pa) < pointmark(p1)) p1 = pa;
16949   pa = sapex(*facetsh);
16950   if (pointmark(pa) < pointmark(p1)) p1 = pa;
16951   // Form the star polygon of p1.
16952   trilist->append(facetsh);
16953   formstarpolygon(p1, trilist, verlist);
16954 
16955   // Get the second pivotal point p2.
16956   p2 = * (point *)(* verlist)[0];
16957   // Get vector v1 = p1->p2.
16958   for (i = 0; i < 3; i++) v1[i] = p2[i] - p1[i];
16959   len = sqrt(dot(v1, v1));
16960   assert(len > 0.0);  // p2 != p1.
16961   for (i = 0; i < 3; i++) v1[i] /= len;
16962 
16963   // Get the third pivotal point p3. p3 is chosen as the one in 'verlist'
16964   //   which forms an angle with v1 closer to 90 degree than others do.
16965   smallcos = 1.0; // The cosine value of 0 degree.
16966   smallidx = 1;   // Default value.
16967   for (i = 1; i < verlist->len(); i++) {
16968     p3 = * (point *)(* verlist)[i];
16969     for (j = 0; j < 3; j++) v2[j] = p3[j] - p1[j];
16970     len = sqrt(dot(v2, v2));
16971     if (len > 0.0) { // v2 is not too small.
16972       cosa = fabs(dot(v1, v2)) / len;
16973       if (cosa < smallcos) {
16974         smallidx = i;
16975         smallcos = cosa;
16976       }
16977     }
16978   }
16979   assert(smallcos < 1.0); // p1->p3 != p1->p2.
16980   p3 = * (point *)(* verlist)[smallidx];
16981   verlist->clear();
16982 
16983   if (tetrahedrons->items > 0l) {
16984     // Get a tet having p1 as a vertex.
16985     stpivot(*facetsh, adjtet);
16986     if (adjtet.tet == dummytet) {
16987       sesym(*facetsh, symsh);
16988       stpivot(symsh, adjtet);
16989     }
16990     if (adjtet.tet == dummytet) {
16991       decode(point2tet(p1), adjtet);
16992       if (isdead(&adjtet)) {
16993         adjtet.tet = dummytet;
16994       } else {
16995         if (!findorg(&adjtet, p1)) {
16996           adjtet.tet = dummytet;
16997         }
16998       }
16999     }
17000     if (adjtet.tet == dummytet) {
17001       loc = locate(p1, &adjtet);
17002       if (loc == ONVERTEX) {
17003         setpoint2tet(p1, encode(adjtet));
17004       } else {
17005         adjtet.tet = dummytet;
17006       }
17007     }
17008     if (adjtet.tet != dummytet) {
17009       // Get the star polyhedron of p1.
17010       tetlist->append(&adjtet);
17011       formstarpolyhedron(p1, tetlist, verlist, false);
17012     }
17013   }
17014 
17015   // Get the abovepoint in 'verlist'. It is the one form the largest valid
17016   //   volumw with the base triangle over other points in 'verlist.
17017   largevol = 0.0;
17018   largeidx = 0;
17019   for (i = 0; i < verlist->len(); i++) {
17020     pa = * (point *)(* verlist)[i];
17021     volume = orient3d(p1, p2, p3, pa);
17022     if (!iscoplanar(p1, p2, p3, pa, volume, b->epsilon * 1e+2)) {
17023       if (fabs(volume) > largevol) {
17024         largevol = fabs(volume);
17025         largeidx = i;
17026       }
17027     }
17028   }
17029 
17030   // Do we have the abovepoint?
17031   if (largevol > 0.0) {
17032     abovepoint = * (point *)(* verlist)[largeidx];
17033     if (b->verbose > 1) {
17034       printf("    Chosen abovepoint %d for facet %d.\n", pointmark(abovepoint),
17035              shellmark(*facetsh));
17036     }
17037   } else {
17038     // Calculate an abovepoint for this facet.
17039     facenormal(p1, p2, p3, v1, &len);
17040     if (len != 0.0) for (i = 0; i < 3; i++) v1[i] /= len;
17041     // Take the average edge length of the bounding box.
17042     len = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
17043     // Temporarily create a point. It will be removed by jettison();
17044     makepoint(&abovepoint);
17045     setpointtype(abovepoint, UNUSEDVERTEX);
17046     unuverts++;
17047     for (i = 0; i < 3; i++) abovepoint[i] = p1[i] + len * v1[i];
17048     if (b->verbose > 1) {
17049       printf("    Calculated abovepoint %d for facet %d.\n",
17050              pointmark(abovepoint), shellmark(*facetsh));
17051     }
17052   }
17053   // Save the abovepoint in 'facetabovepointarray'.
17054   shmark = shellmark(*facetsh);
17055   facetabovepointarray[shmark] = abovepoint;
17056   
17057   delete trilist;
17058   delete tetlist;
17059   delete verlist;
17060 }
17061 
17063 //                                                                           //
17064 // collectcavsubs()    Collect non-locally Delaunay subfaces wrt a point.    //
17065 //                                                                           //
17066 // 'cavsublist' returns the list of subfaces. On input, it conatins at least //
17067 // one subface.                                                              //
17068 //                                                                           //
17070 
17071 void tetgenmesh::collectcavsubs(point newpoint, list* cavsublist)
17072 {
17073   face startsub, neighsub;
17074   face checkseg;
17075   point pa, pb, pc;
17076   REAL sign, ori;
17077   int i, j;
17078 
17079   // First infect subfaces in 'cavsublist'.
17080   for (i = 0; i < cavsublist->len(); i++) {
17081     startsub = * (face *)(* cavsublist)[i];
17082     sinfect(startsub);
17083   }
17084   // Find the other subfaces by a broadth-first searching.
17085   for (i = 0; i < cavsublist->len(); i++) {
17086     startsub = * (face *)(* cavsublist)[i];
17087     for (j = 0; j < 3; j++) {
17088       sspivot(startsub, checkseg);
17089       // Is there a segment?
17090       if (checkseg.sh == dummysh) {
17091         // No segment. Get the neighbor.
17092         spivot(startsub, neighsub);
17093         if (!sinfected(neighsub)) {
17094           pa = sorg(neighsub);
17095           pb = sdest(neighsub);
17096           pc = sapex(neighsub);
17097           sign = insphere(pa, pb, pc, abovepoint, newpoint);
17098           ori = orient3d(pa, pb, pc, abovepoint);
17099           if (sign != 0.0) {
17100             // Correct the sign.
17101             sign = ori > 0.0 ? sign : -sign;
17102           }
17103           if (sign > 0.0) {
17104             // neighsub is encroached by newpoint.
17105             sinfect(neighsub);
17106             cavsublist->append(&neighsub);
17107           }
17108         }
17109       }
17110       senextself(startsub);
17111     }
17112   }
17113   // Having found all subfaces, uninfect them before return.
17114   for (i = 0; i < cavsublist->len(); i++) {
17115     startsub = * (face *)(* cavsublist)[i];
17116     suninfect(startsub);
17117   }
17118 }
17119 
17121 //                                                                           //
17122 // collectvisiblesubs()    Collect convex hull edges which are visible from  //
17123 //                         the inserting point. Construct new subfaces from  //
17124 //                         these edges and the point.                        //
17125 //                                                                           //
17126 // Let T be the current Delaunay triangulation (of vertices of a facet F).   //
17127 // 'shmark', the index of F in 'in->facetlist' (starts from 1);  'inspoint'  //
17128 // lies outside of T; 'horiz' is a hull edge of T which is visible by it.    //
17129 //                                                                           //
17131 
17132 void tetgenmesh::collectvisiblesubs(int shmark, point inspoint, face* horiz,
17133   queue* flipqueue)
17134 {
17135   face newsh, hullsh;
17136   face rightsh, leftsh, spinedge;
17137   point horg, hdest;
17138   bool aboveflag;
17139   REAL ori, sign;
17140 
17141   // Get the sign of abovepoint (so we can assume it is above the plane).  
17142   adjustedgering(*horiz, CCW);
17143   horg = sorg(*horiz);
17144   hdest = sdest(*horiz);
17145   ori = orient3d(horg, hdest, sapex(*horiz), abovepoint);
17146   sign = ori > 0.0 ? -1 : 1;
17147 
17148   // Create a new subface above 'horiz'.
17149   makeshellface(subfaces, &newsh);
17150   setsorg(newsh, hdest);
17151   setsdest(newsh, horg);
17152   setsapex(newsh, inspoint);
17153   setshellmark(newsh, shmark);
17154   if (b->quality && varconstraint) {
17155     setareabound(newsh, areabound(*horiz));
17156   }
17157   if (checkpbcs) {
17158     setshellpbcgroup(newsh, shellpbcgroup(*horiz));
17159   }
17160   // Make the connection.
17161   sbond(newsh, *horiz);
17162   // 'horiz' becomes interior edge.
17163   enqueueflipedge(*horiz, flipqueue);
17164   
17165   // Finish the hull edges at the right side of the newsh.
17166   hullsh = *horiz;
17167   while (1) {
17168     senext(newsh, rightsh);
17169     // Get the right hull edge of 'horiz' by spinning inside edges around
17170     //   'horg' until reaching the 'dummysh'.
17171     spinedge = hullsh;
17172     do {
17173       hullsh = spinedge;
17174       senext2self(hullsh);
17175       spivot(hullsh, spinedge);
17176       if (spinedge.sh == dummysh) break;
17177       if (sorg(spinedge) != horg) sesymself(spinedge);
17178       assert(sorg(spinedge) == horg);
17179     } while (true);
17180     horg = sorg(hullsh);
17181     // Test whether 'inspoint' is visible by 'hullsh'.
17182     ori = orient3d(horg, sdest(hullsh), abovepoint, inspoint);
17183     ori *= sign;
17184     aboveflag = ori < 0.0;
17185     if (aboveflag) {
17186       // It's visible.
17187       makeshellface(subfaces, &newsh);
17188       setsorg(newsh, sdest(hullsh));
17189       setsdest(newsh, horg);
17190       setsapex(newsh, inspoint);
17191       setshellmark(newsh, shmark);
17192       if (b->quality && varconstraint) {
17193         setareabound(newsh, areabound(hullsh));
17194       }
17195       if (checkpbcs) {
17196         setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17197       }
17198       // Make the connection.
17199       sbond(newsh, hullsh);
17200       senext2(newsh, leftsh);
17201       sbond(leftsh, rightsh);
17202       // 'hullsh' becomes interior edge.
17203       enqueueflipedge(hullsh, flipqueue); 
17204     } else {
17205       // 'rightsh' is a new hull edge.
17206       dummysh[0] = sencode(rightsh);
17207       break;
17208     }
17209   }
17210 
17211   // Finish the hull edges at the left side of the newsh.
17212   hullsh = *horiz;
17213   spivot(*horiz, newsh);
17214   while (1) {
17215     senext2(newsh, leftsh);
17216     // Get the left hull edge of 'horiz' by spinning edges around 'hdest'.
17217     spinedge = hullsh;
17218     do {
17219       hullsh = spinedge;
17220       senextself(hullsh);
17221       spivot(hullsh, spinedge);
17222       if (spinedge.sh == dummysh) break;
17223       if (sdest(spinedge) != hdest) sesymself(spinedge);
17224       assert(sdest(spinedge) == hdest);
17225     } while (true);
17226     // Update 'hdest'.
17227     hdest = sdest(hullsh);
17228     // Test whether 'inspoint' is visible from 'hullsh'.
17229     ori = orient3d(sorg(hullsh), hdest, abovepoint, inspoint);
17230     ori *= sign;
17231     aboveflag = ori < 0.0;
17232     if (aboveflag) {
17233       // It's a visible hull edge.
17234       makeshellface(subfaces, &newsh);
17235       setsorg(newsh, hdest);
17236       setsdest(newsh, sorg(hullsh));
17237       setsapex(newsh, inspoint);
17238       setshellmark(newsh, shmark);
17239       if (b->quality && varconstraint) {
17240         setareabound(newsh, areabound(hullsh));
17241       }
17242       if (checkpbcs) {
17243         setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17244       }
17245       // Make the connection.
17246       sbond(newsh, hullsh);
17247       senext(newsh, rightsh);
17248       sbond(rightsh, leftsh);
17249       // 'horiz' becomes interior edge.
17250       enqueueflipedge(hullsh, flipqueue); 
17251     } else {
17252       // 'leftsh' is a new hull edge.
17253       dummysh[0] = sencode(leftsh);
17254       break;
17255     }
17256   }
17257 }
17258 
17260 //                                                                           //
17261 // incrflipdelaunaysub()    Create a DT from a 3D coplanar point set using   //
17262 //                          the incremental flip algorithm.                  //
17263 //                                                                           //
17264 // Let T be the current Delaunay triangulation (of vertices of a facet F).   //
17265 // 'shmark', the index of F in 'in->facetlist' (starts from 1).              //
17266 //                                                                           //
17268 
17269 void tetgenmesh::incrflipdelaunaysub(int shmark, REAL eps, list* ptlist,
17270   int holes, REAL* holelist, queue* flipque)
17271 {
17272   face newsh, startsh;
17273   point *insertarray;
17274   point swappt;
17275   pbcdata *pd;
17276   enum locateresult loc;
17277   REAL det, area;
17278   bool aboveflag;
17279   int arraysize;
17280   int epscount;
17281   int fmarker;
17282   int idx, i, j, k;  
17283 
17284   // Get the point array (saved in 'ptlist').
17285   insertarray = (point *) ptlist->base;
17286   arraysize = ptlist->len();
17287   if (arraysize < 3) return;
17288 
17289   // Do calculation of 'abovepoint' if number of points > 3.
17290   aboveflag = (arraysize > 3);
17291 
17292   // The initial triangulation T only has one triangle formed by 3 not
17293   //   cillinear points of the set V = 'insertarray'. The first point:
17294   //   a = insertarray[0].
17295 
17296   epscount = 0;
17297   while (true) {
17298   for (i = 1; i < arraysize; i++) {
17299     det = distance(insertarray[0], insertarray[i]);
17300     if (det > (longest * eps)) break;
17301   }
17302   if (i < arraysize) {
17303     // Swap to move b from index i to index 1.
17304     swappt = insertarray[i];
17305     insertarray[i] = insertarray[1];
17306     insertarray[1] = swappt;  
17307   }
17308   // Get the third point c, that is not collinear with a and b.
17309   for (i++; i < arraysize; i++) {
17310     if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
17311       break;
17312   }
17313   if (i < arraysize) {
17314     // Swap to move c from index i to index 2.
17315     swappt = insertarray[i];
17316     insertarray[i] = insertarray[2];
17317     insertarray[2] = swappt;
17318     i = 3; // The next inserting point.
17319   } else {
17320     // The set of vertices is not good (or nearly degenerate).  However,
17321     //   a trivial triangulation can be formed (using 3 vertices). It may
17322     //   be corrected (or deleted) by mergefacet().
17323     if ((eps == 0.0) || (epscount > 16)) {
17324       printf("Error:  Invalid PLC.\n");
17325       printf("  Facet (%d, %d, %d", pointmark(insertarray[0]),
17326              pointmark(insertarray[1]), pointmark(insertarray[2]));
17327       if (ptlist->len() > 3) {
17328         printf(", ...");
17329       }
17330       printf(") (%d) is not a valid polygon.\n", shmark);
17331       terminatetetgen(1);
17332     }
17333     // Decrease the eps, and continue to try.
17334     eps *= 1e-2;
17335     epscount++;
17336     continue;
17337   }
17338   break;
17339   } // while (true);
17340 
17341   // Create the initial triangle.
17342   makeshellface(subfaces, &newsh);
17343   setsorg(newsh, insertarray[0]);
17344   setsdest(newsh, insertarray[1]);
17345   setsapex(newsh, insertarray[2]);
17346   // Remeber the facet it belongs to.
17347   setshellmark(newsh, shmark);
17348   // Set vertex type be FREESUBVERTEX if it has no type yet.
17349   if (pointtype(insertarray[0]) == FREEVOLVERTEX) {
17350     setpointtype(insertarray[0], FREESUBVERTEX);
17351   }
17352   if (pointtype(insertarray[1]) == FREEVOLVERTEX) {
17353     setpointtype(insertarray[1], FREESUBVERTEX);
17354   }
17355   if (pointtype(insertarray[2]) == FREEVOLVERTEX) {
17356     setpointtype(insertarray[2], FREESUBVERTEX);
17357   }
17358   // Let 'dummysh' point to it (for point location).
17359   dummysh[0] = sencode(newsh);
17360 
17361   // Are there area constraints?
17362   if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
17363     idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker.
17364     for (k = 0; k < in->numberoffacetconstraints; k++) {
17365       fmarker = (int) in->facetconstraintlist[k * 2];
17366       if (fmarker == idx) {
17367         area = in->facetconstraintlist[k * 2 + 1];
17368         setareabound(newsh, area);
17369         break;
17370       }
17371     }
17372   }
17373 
17374   // Are there pbc conditions?
17375   if (checkpbcs) {
17376     idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker.
17377     for (k = 0; k < in->numberofpbcgroups; k++) {
17378       pd = &subpbcgrouptable[k];
17379       for (j = 0; j < 2; j++) {
17380         if (pd->fmark[j] == idx) {
17381           setshellpbcgroup(newsh, k);
17382           pd->ss[j] = newsh;
17383         }
17384       }
17385     }
17386   }
17387 
17388   if (aboveflag) {
17389     // Compute the 'abovepoint' for orient3d().
17390     abovepoint = facetabovepointarray[shmark];
17391     if (abovepoint == (point) NULL) {
17392       getfacetabovepoint(&newsh);
17393     }
17394   }
17395 
17396   if (holes > 0) {
17397     // Project hole points onto the plane containing the facet.
17398     REAL prj[3];
17399     for (k = 0; k < holes; k++) {
17400       projpt2face(&(holelist[k * 3]), insertarray[0], insertarray[1],
17401                   insertarray[2], prj);
17402       for (j = 0; j < 3; j++) holelist[k * 3 + j] = prj[j];
17403     }
17404   }
17405 
17406   // Incrementally insert the rest of points into T.
17407   for (; i < arraysize; i++) {
17408     // Insert p_i.
17409     startsh.sh = dummysh;
17410     loc = locatesub(insertarray[i], &startsh, 0, 0.0);
17411     if (loc == ONFACE) {
17412       splitsubface(insertarray[i], &startsh, flipque);
17413     } else if (loc == ONEDGE) {
17414       splitsubedge(insertarray[i], &startsh, flipque);
17415     } else if (loc == OUTSIDE) {
17416       collectvisiblesubs(shmark, insertarray[i], &startsh, flipque);
17417     } else if (loc == ONVERTEX) {
17418       // !should not happen!
17419     }
17420     // Set p_i's type FREESUBVERTEX if it has no type yet.
17421     if (pointtype(insertarray[i]) == FREEVOLVERTEX) {
17422       setpointtype(insertarray[i], FREESUBVERTEX);
17423     }
17424     flipsub(flipque);
17425   }
17426 }
17427 
17429 //                                                                           //
17430 // finddirectionsub()    Find the first subface in a facet on the path from  //
17431 //                       one point to another.                               //
17432 //                                                                           //
17433 // Finds the subface in the facet that intersects a line segment drawn from  //
17434 // the origin of `searchsh' to the point `tend', and returns the result in   //
17435 // `searchsh'.  The origin of `searchsh' does not change,  even though the   //
17436 // subface returned may differ from the one passed in.                       //
17437 //                                                                           //
17438 // The return value notes whether the destination or apex of the found face  //
17439 // is collinear with the two points in question.                             //
17440 //                                                                           //
17442 
17443 enum tetgenmesh::finddirectionresult tetgenmesh::finddirectionsub(
17444   face* searchsh, point tend)
17445 {
17446   face checksh;
17447   point startpoint, leftpoint, rightpoint;
17448   REAL leftccw, rightccw;
17449   REAL ori, sign;
17450   int leftflag, rightflag;
17451 
17452   startpoint = sorg(*searchsh);
17453   // Find the sign to simulate that abovepoint is 'above' the facet.
17454   adjustedgering(*searchsh, CCW);
17455   // Make sure 'startpoint' is the origin.
17456   if (sorg(*searchsh) != startpoint) senextself(*searchsh);
17457   rightpoint = sdest(*searchsh);
17458   leftpoint = sapex(*searchsh);
17459   ori = orient3d(startpoint, rightpoint, leftpoint, abovepoint);
17460   sign = ori > 0.0 ? -1 : 1;
17461 
17462   // Is `tend' to the left?
17463   ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17464   leftccw = ori * sign;
17465   leftflag = leftccw > 0.0;
17466   // Is `tend' to the right?
17467   ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17468   rightccw = ori * sign;
17469   rightflag = rightccw > 0.0;
17470   if (leftflag && rightflag) {
17471     // `searchsh' faces directly away from `tend'.  We could go left or
17472     //   right.  Ask whether it's a triangle or a boundary on the left.
17473     senext2(*searchsh, checksh);
17474     spivotself(checksh);
17475     if (checksh.sh == dummysh) {
17476       leftflag = 0;
17477     } else {
17478       rightflag = 0;
17479     }
17480   }
17481   while (leftflag) {
17482     // Turn left until satisfied.
17483     senext2self(*searchsh);
17484     spivotself(*searchsh);
17485     if (searchsh->sh == dummysh) {
17486       printf("Internal error in finddirectionsub():  Unable to find a\n");
17487       printf("  subface leading from %d to %d.\n", pointmark(startpoint),
17488              pointmark(tend));
17489       internalerror();
17490     }
17491     if (sorg(*searchsh) != startpoint) sesymself(*searchsh);
17492     assert(sorg(*searchsh) == startpoint);
17493     leftpoint = sapex(*searchsh);
17494     rightccw = leftccw;
17495     ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17496     leftccw = ori * sign;
17497     leftflag = leftccw > 0.0;
17498   }
17499   while (rightflag) {
17500     // Turn right until satisfied.
17501     spivotself(*searchsh);
17502     if (searchsh->sh == dummysh) {
17503       printf("Internal error in finddirectionsub():  Unable to find a\n");
17504       printf("  subface leading from %d to %d.\n", pointmark(startpoint),
17505              pointmark(tend));
17506       internalerror();
17507     }
17508     if (sdest(*searchsh) != startpoint) sesymself(*searchsh);
17509     assert(sdest(*searchsh) == startpoint);
17510     senextself(*searchsh);
17511     rightpoint = sdest(*searchsh);
17512     leftccw = rightccw;
17513     ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17514     rightccw = ori * sign;
17515     rightflag = rightccw > 0.0;
17516   }
17517   if (leftccw == 0.0) {
17518     return LEFTCOLLINEAR;
17519   } else if (rightccw == 0.0) {
17520     return RIGHTCOLLINEAR;
17521   } else {
17522     return ACROSSEDGE;
17523   }
17524 }
17525 
17527 //                                                                           //
17528 // insertsubseg()    Create a subsegment and insert it between two subfaces. //
17529 //                                                                           //
17530 // The new subsegment ab is inserted at the edge of subface 'tri'.  If ab is //
17531 // not a hull edge, it is inserted between two subfaces.  If 'tri' is a hull //
17532 // face, the initial face ring of ab will be set only one face which is self-//
17533 // bonded.  The final face ring will be constructed in 'unifysegments()'.    //
17534 //                                                                           //
17536 
17537 void tetgenmesh::insertsubseg(face* tri)
17538 {
17539   face oppotri;
17540   face newsubseg;
17541   point pa, pb;
17542   REAL len;
17543   int e1, e2;
17544   int i;
17545 
17546   // Check if there's already a subsegment here.
17547   sspivot(*tri, newsubseg);
17548   if (newsubseg.sh == dummysh) {
17549     // Make new subsegment and initialize its vertices.
17550     makeshellface(subsegs, &newsubseg);
17551     pa = sorg(*tri);
17552     pb = sdest(*tri);
17553     setsorg(newsubseg, pa);
17554     setsdest(newsubseg, pb);
17555     // Are there length constraints?
17556     if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
17557       for (i = 0; i < in->numberofsegmentconstraints; i++) {
17558         e1 = (int) in->segmentconstraintlist[i * 3];
17559         e2 = (int) in->segmentconstraintlist[i * 3 + 1];
17560         if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
17561             ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
17562           len = in->segmentconstraintlist[i * 3 + 2];
17563           setareabound(newsubseg, len);
17564           break;
17565         }
17566       }
17567     }
17568     // Bond new subsegment to the two subfaces it is sandwiched between.
17569     ssbond(*tri, newsubseg);
17570     spivot(*tri, oppotri);
17571     // 'oppotri' might be "out space".
17572     if (oppotri.sh != dummysh) {
17573       ssbond(oppotri, newsubseg);
17574     } /* else {
17575       // Outside! Bond '*tri' to itself.
17576       sbond(*tri, *tri);
17577     } */
17578   }
17579 }
17580 
17582 //                                                                           //
17583 // scoutsegmentsub()    Scout the first triangle on the path from one point  //
17584 //                      to another, and check for completion (reaching the   //
17585 //                      second point), a collinear point,or the intersection //
17586 //                      of two segments.                                     //
17587 //                                                                           //
17588 // Returns true if the entire segment is successfully inserted, and false if //
17589 // the job must be finished by constrainededge().                            //
17590 //                                                                           //
17592 
17593 bool tetgenmesh::scoutsegmentsub(face* searchsh, point tend)
17594 {
17595   face newsubseg;
17596   face crosssub, crosssubseg;
17597   point leftpoint, rightpoint;
17598   enum finddirectionresult collinear;
17599 
17600   collinear = finddirectionsub(searchsh, tend);
17601   rightpoint = sdest(*searchsh);
17602   leftpoint = sapex(*searchsh);
17603   if (rightpoint == tend || leftpoint == tend) {
17604     // The segment is already an edge.
17605     if (leftpoint == tend) {
17606       senext2self(*searchsh);
17607     }
17608     // Insert a subsegment.
17609     insertsubseg(searchsh);
17610     return true;
17611   } else if (collinear == LEFTCOLLINEAR) {
17612     // We've collided with a vertex between the segment's endpoints.
17613     // Make the collinear vertex be the triangle's origin.
17614     senextself(*searchsh); // lprevself(*searchtri);
17615     // Insert a subsegment.
17616     insertsubseg(searchsh);
17617     // Insert the remainder of the segment.
17618     return scoutsegmentsub(searchsh, tend);
17619   } else if (collinear == RIGHTCOLLINEAR) {
17620     // We've collided with a vertex between the segment's endpoints.
17621     // Insert a subsegment.
17622     insertsubseg(searchsh);
17623     // Make the collinear vertex be the triangle's origin.
17624     senextself(*searchsh); // lnextself(*searchtri);
17625     // Insert the remainder of the segment.
17626     return scoutsegmentsub(searchsh, tend);
17627   } else {
17628     senext(*searchsh, crosssub); // lnext(*searchtri, crosstri);
17629     // Check for a crossing segment.
17630     sspivot(crosssub, crosssubseg);
17631 #ifdef SELF_CHECK
17632     assert(crosssubseg.sh == dummysh);
17633 #endif
17634     return false;
17635   }
17636 }
17637 
17639 //                                                                           //
17640 // flipedgerecursive()    Flip an edge.                                      //
17641 //                                                                           //
17642 // This is a support routine for inserting segments into a CDT.              //
17643 //                                                                           //
17644 // Let 'flipedge' be ab, and two triangles abc, abd share at it.  ab may not //
17645 // flipable if the four vertices a, b, c, and d are non-convex. If it is the //
17646 // case, recursively flip ad or bd. Return when ab is flipped.               //
17647 //                                                                           //
17649 
17650 void tetgenmesh::flipedgerecursive(face* flipedge, queue* flipqueue)
17651 {
17652   face fixupsh;
17653   point pa, pb, pc, pd;
17654   REAL oria, orib;
17655   bool doflip;
17656 
17657   pa = sorg(*flipedge);
17658   pb = sdest(*flipedge);
17659   pc = sapex(*flipedge);
17660   do {
17661     spivot(*flipedge, fixupsh);    
17662     pd = sapex(fixupsh);
17663     oria = orient3d(pc, pd, abovepoint, pa);
17664     orib = orient3d(pc, pd, abovepoint, pb);
17665     doflip = (oria * orib < 0.0);
17666     if (doflip) {
17667       // Flip the edge (a, b) away.      
17668       flip22sub(flipedge, flipqueue);
17669       // Fix flipedge on edge e (c, d).
17670       findedge(flipedge, pc, pd);
17671     } else {
17672       // ab is unflipable. Get the next edge (bd, or da) to flip.
17673       if (sorg(fixupsh) != pb) sesymself(fixupsh);
17674       assert(sdest(fixupsh) == pa);
17675       if (fabs(oria) > fabs(orib)) {
17676         // acd has larger area. Choose da.
17677         senextself(fixupsh);
17678       } else {
17679         // bcd has larger area. Choose bd.
17680         senext2self(fixupsh);
17681       }
17682       // Flip the edge.
17683       flipedgerecursive(&fixupsh, flipqueue);
17684     }
17685   } while (!doflip);
17686 }
17687 
17689 //                                                                           //
17690 // constrainededge()    Force a segment into a CDT.                          //
17691 //                                                                           //
17692 // The segment s is recovered by flipping away the edges it intersects, and  //
17693 // triangulating the polygons that form on each side of it.                  //
17694 //                                                                           //
17695 // Generates a single subsegment connecting `tstart' to `tend'. The triangle //
17696 // `startsh' has `tstart' as its origin.                                     //
17697 //                                                                           //
17699 
17700 void tetgenmesh::constrainededge(face* startsh, point tend, queue* flipqueue)
17701 {
17702   point tstart, tright, tleft;
17703   REAL rori, lori;
17704   bool collision;
17705 
17706   tstart = sorg(*startsh);
17707   do {
17708     // Loop edges oppo to tstart until find one crosses the segment.
17709     do {
17710       tright = sdest(*startsh);
17711       tleft = sapex(*startsh);
17712       // Is edge (tright, tleft) corss the segment.
17713       rori = orient3d(tstart, tright, abovepoint, tend);
17714       collision = (rori == 0.0);
17715       if (collision) break; // tright is on the segment.
17716       lori = orient3d(tstart, tleft, abovepoint, tend);
17717       collision = (lori == 0.0);
17718       if (collision) { //  tleft is on the segment.
17719         senext2self(*startsh);
17720         break;
17721       }
17722       if (rori * lori < 0.0) break; // Find the crossing edge.
17723       // Both points are at one side of the segment. 
17724       finddirectionsub(startsh, tend);
17725     } while (true);
17726     if (collision) break;
17727     // Get the neighbor face at edge e (tright, tleft).
17728     senextself(*startsh);
17729     // Flip the crossing edge.
17730     flipedgerecursive(startsh, flipqueue);
17731     // After flip, sorg(*startsh) == tstart.
17732     assert(sorg(*startsh) == tstart);
17733   } while (sdest(*startsh) != tend);
17734 
17735   // Insert a subsegment to make the segment permanent.
17736   insertsubseg(startsh);
17737   // If there was a collision with an interceding vertex, install another
17738   //   segment connecting that vertex with endpoint2.
17739   if (collision) {
17740     // Insert the remainder of the segment.
17741     if (!scoutsegmentsub(startsh, tend)) {
17742       constrainededge(startsh, tend, flipqueue);
17743     }
17744   }
17745 }
17746 
17748 //                                                                           //
17749 // recoversegment()    Recover a segment in the surface triangulation.       //
17750 //                                                                           //
17752 
17753 void tetgenmesh::recoversegment(point tstart, point tend, queue* flipqueue)
17754 {
17755   face searchsh;
17756 
17757   if (b->verbose > 2) {
17758     printf("    Insert seg (%d, %d).\n", pointmark(tstart), pointmark(tend));
17759   }
17760 
17761   // Find a triangle whose origin is the segment's first endpoint.
17762   searchsh.sh = dummysh;
17763   // Search for the segment's first endpoint by point location.
17764   if (locatesub(tstart, &searchsh, 0, 0.0) != ONVERTEX) {
17765     // Possibly caused by a degenerate subface. Do a brute-force search.
17766     list *newshlist;
17767     int i, j;
17768     newshlist = new list(sizeof(face), NULL, 256);
17769     // Get new subfaces, do not remove protected segments.
17770     retrievenewsubs(newshlist, false);
17771     // Search for a sub contain tstart.
17772     for (i = 0; i < newshlist->len(); i++) {
17773       searchsh = * (face *)(* newshlist)[i];
17774       for (j = 0; j < 3; j++) {
17775         if (sorg(searchsh) == tstart) break;
17776         senextself(searchsh);
17777       }
17778       if (j < 3) break;
17779     }
17780     delete newshlist;
17781     if (sorg(searchsh) != tstart) {
17782       printf("Internal error in recoversegment():  Vertex location failed.\n");
17783       internalerror();
17784     }
17785   }
17786   // Scout the segment and insert it if it is found.
17787   if (scoutsegmentsub(&searchsh, tend)) {
17788     // The segment was easily inserted.
17789     return;
17790   }  
17791   // Insert the segment into the triangulation by flips.
17792   constrainededge(&searchsh, tend, flipqueue);
17793   // Some edges may need flipping.
17794   flipsub(flipqueue);
17795 }
17796 
17798 //                                                                           //
17799 // infecthullsub()    Virally infect all of the triangles of the convex hull //
17800 //                    that are not protected by subsegments.                 //
17801 //                                                                           //
17803 
17804 void tetgenmesh::infecthullsub(memorypool* viri)
17805 {
17806   face hulltri, nexttri, starttri;
17807   face hullsubseg;
17808   shellface **deadshellface;
17809 
17810   // Find a triangle handle on the hull.
17811   hulltri.sh = dummysh;
17812   hulltri.shver = 0;
17813   spivotself(hulltri);
17814   adjustedgering(hulltri, CCW);
17815   // Remember where we started so we know when to stop.
17816   starttri = hulltri;
17817   // Go once counterclockwise around the convex hull.
17818   do {
17819     // Ignore triangles that are already infected.
17820     if (!sinfected(hulltri)) {
17821       // Is the triangle protected by a subsegment?
17822       sspivot(hulltri, hullsubseg);
17823       if (hullsubseg.sh == dummysh) {
17824         // The triangle is not protected; infect it.
17825         if (!sinfected(hulltri)) {
17826           sinfect(hulltri);
17827           deadshellface = (shellface **) viri->alloc();
17828           *deadshellface = hulltri.sh;
17829         }
17830       } 
17831     }
17832     // To find the next hull edge, go clockwise around the next vertex.
17833     senextself(hulltri); // lnextself(hulltri);
17834     spivot(hulltri, nexttri); // oprev(hulltri, nexttri);
17835     if (nexttri.sh == hulltri.sh) {
17836       nexttri.sh = dummysh;  // 'hulltri' is self-bonded.
17837     } else {
17838       adjustedgering(nexttri, CCW);
17839       senextself(nexttri);
17840     }
17841     while (nexttri.sh != dummysh) {
17842       hulltri = nexttri;
17843       spivot(hulltri, nexttri); // oprev(hulltri, nexttri);
17844       if (nexttri.sh == hulltri.sh) {
17845         nexttri.sh = dummysh;  // 'hulltri' is self-bonded.
17846       } else {
17847         adjustedgering(nexttri, CCW);
17848         senextself(nexttri);
17849       }
17850     }
17851   } while (hulltri != starttri);
17852 }
17853 
17855 //                                                                           //
17856 // plaguesub()    Spread the virus from all infected triangles to any        //
17857 //                neighbors not protected by subsegments.  Delete all        //
17858 //                infected triangles.                                        //
17859 //                                                                           //
17860 // This is the procedure that actually creates holes and concavities.        //
17861 //                                                                           //
17863 
17864 void tetgenmesh::plaguesub(memorypool* viri)
17865 {
17866   face testtri, neighbor, ghostsh;
17867   face neighborsubseg;
17868   shellface **virusloop;
17869   shellface **deadshellface;
17870   int i;
17871 
17872   // Loop through all the infected triangles, spreading the virus to
17873   //   their neighbors, then to their neighbors' neighbors.
17874   viri->traversalinit();
17875   virusloop = (shellface **) viri->traverse();
17876   while (virusloop != (shellface **) NULL) {
17877     testtri.sh = *virusloop;
17878     // Check each of the triangle's three neighbors.
17879     for (i = 0; i < 3; i++) {
17880       // Find the neighbor.
17881       spivot(testtri, neighbor);
17882       // Check for a subsegment between the triangle and its neighbor.
17883       sspivot(testtri, neighborsubseg);
17884       // Check if the neighbor is nonexistent or already infected.
17885       if ((neighbor.sh == dummysh) || sinfected(neighbor)) {
17886         if (neighborsubseg.sh != dummysh) {
17887           // There is a subsegment separating the triangle from its
17888           //   neighbor, but both triangles are dying, so the subsegment
17889           //   dies too.
17890           shellfacedealloc(subsegs, neighborsubseg.sh);
17891           if (neighbor.sh != dummysh) {
17892             // Make sure the subsegment doesn't get deallocated again
17893             //   later when the infected neighbor is visited.
17894             ssdissolve(neighbor);
17895           }
17896         }
17897       } else {                   // The neighbor exists and is not infected.
17898         if (neighborsubseg.sh == dummysh) {
17899           // There is no subsegment protecting the neighbor, so the
17900           //   neighbor becomes infected.
17901           sinfect(neighbor);
17902           // Ensure that the neighbor's neighbors will be infected.
17903           deadshellface = (shellface **) viri->alloc();
17904           *deadshellface = neighbor.sh;
17905         } else {               // The neighbor is protected by a subsegment.
17906           // Remove this triangle from the subsegment.
17907           ssbond(neighbor, neighborsubseg);
17908         }
17909       }
17910       senextself(testtri);
17911     }
17912     virusloop = (shellface **) viri->traverse();
17913   }
17914 
17915   ghostsh.sh = dummysh; // A handle of outer space.
17916   viri->traversalinit();
17917   virusloop = (shellface **) viri->traverse();
17918   while (virusloop != (shellface **) NULL) {
17919     testtri.sh = *virusloop;
17920     // Record changes in the number of boundary edges, and disconnect
17921     //   dead triangles from their neighbors. 
17922     for (i = 0; i < 3; i++) {
17923       spivot(testtri, neighbor);
17924       if (neighbor.sh != dummysh) {
17925         // Disconnect the triangle from its neighbor.
17926         // sdissolve(neighbor);
17927         sbond(neighbor, ghostsh); 
17928       }
17929       senextself(testtri);
17930     }
17931     // Return the dead triangle to the pool of triangles.
17932     shellfacedealloc(subfaces, testtri.sh);
17933     virusloop = (shellface **) viri->traverse();
17934   }
17935   // Empty the virus pool.
17936   viri->restart();
17937 }
17938 
17940 //                                                                           //
17941 // carveholessub()    Find the holes and infect them.  Find the area         //
17942 //                    constraints and infect them.  Infect the convex hull.  //
17943 //                    Spread the infection and kill triangles.  Spread the   //
17944 //                    area constraints.                                      //
17945 //                                                                           //
17946 // This routine mainly calls other routines to carry out all these functions.//
17947 //                                                                           //
17949 
17950 void tetgenmesh::carveholessub(int holes, REAL* holelist, memorypool *viri)
17951 {
17952   face searchtri, triangleloop;
17953   shellface **holetri;
17954   enum locateresult intersect;
17955   int i;
17956 
17957   // Mark as infected any unprotected triangles on the boundary.
17958   //   This is one way by which concavities are created.
17959   infecthullsub(viri);
17960 
17961   if (holes > 0) {
17962     // Infect each triangle in which a hole lies.
17963     for (i = 0; i < 3 * holes; i += 3) {
17964       // Ignore holes that aren't within the bounds of the mesh.
17965       if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
17966           && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)
17967           && (holelist[i + 2] >= zmin) && (holelist[i + 2] <= zmax)) {
17968         // Start searching from some triangle on the outer boundary.
17969         searchtri.sh = dummysh;
17970         // Find a triangle that contains the hole.
17971         intersect = locatesub(&holelist[i], &searchtri, 0, 0.0);
17972         if ((intersect != OUTSIDE) && (!sinfected(searchtri))) {
17973           // Infect the triangle.  This is done by marking the triangle
17974           //   as infected and including the triangle in the virus pool.
17975           sinfect(searchtri);
17976           holetri = (shellface **) viri->alloc();
17977           *holetri = searchtri.sh;
17978         }
17979       }
17980     }
17981   }
17982 
17983   if (viri->items > 0) {
17984     // Carve the holes and concavities.
17985     plaguesub(viri);
17986   }
17987   // The virus pool should be empty now.
17988 }
17989 
17991 //                                                                           //
17992 // triangulate()    Triangulate a PSLG into a CDT.                           //
17993 //                                                                           //
17994 // A Planar Straight Line Graph (PSLG) P is actually a 2D polygonal region,  //
17995 // possibly contains holes, segments and vertices in its interior. P is tri- //
17996 // angulated into a set of _subfaces_ forming a CDT of P.                    //
17997 //                                                                           //
17998 // The vertices and segments of P are found in 'ptlist' and 'conlist', resp- //
17999 // ectively. 'holelist' contains a list of hole points. 'shmark' will be set //
18000 // to all subfaces of P.                                                     //
18001 //                                                                           //
18002 // The CDT is created directly in the pools 'subfaces' and 'subsegs'. It can //
18003 // be retrived by a broadth-first searching starting from 'dummysh[0]'(debug //
18004 // function 'outsurfmesh()' does it).                                        //
18005 //                                                                           //
18007 
18008 void tetgenmesh::triangulate(int shmark, REAL eps, list* ptlist, list* conlist,
18009   int holes, REAL* holelist, memorypool* viri, queue* flipqueue)
18010 {
18011   face newsh;
18012   point *cons;
18013   int i;
18014 
18015   if (b->verbose > 1) {
18016     printf("    %d vertices, %d segments", ptlist->len(), conlist->len());
18017     if (holes > 0) {
18018       printf(", %d holes", holes);
18019     }
18020     printf(", shmark: %d.\n", shmark);
18021   }
18022 
18023   // Create the DT of V by the 2D incremental flip algorithm.
18024   incrflipdelaunaysub(shmark, eps, ptlist, holes, holelist, flipqueue);
18025   // Recover boundary edges.
18026   if (ptlist->len() > 3) {
18027     // Insert segments into the DT.
18028     for (i = 0; i < conlist->len(); i++) {
18029       cons = (point *)(* conlist)[i];
18030       recoversegment(cons[0], cons[1], flipqueue);        
18031     }
18032     // Carve holes and concavities.
18033     carveholessub(holes, holelist, viri);
18034   } else if (ptlist->len() == 3) {
18035     // Insert 3 segments directly.
18036     newsh.sh = dummysh;
18037     newsh.shver = 0;
18038     spivotself(newsh);
18039     for (i = 0; i < 3; i++) {
18040       insertsubseg(&newsh);
18041       senextself(newsh);
18042     }
18043   } else if (ptlist->len() == 2) {
18044     // This facet is actually a segment. It is not support by the mesh data
18045     //   strcuture. Hence the segment will not be maintained in the mesh.
18046     //   However, during segment recovery, the segment can be processed.
18047     cons = (point *)(* conlist)[0];
18048     makeshellface(subsegs, &newsh);
18049     setsorg(newsh, cons[0]);
18050     setsdest(newsh, cons[1]);
18051   }
18052 }
18053 
18055 //                                                                           //
18056 // retrievenewsubs()    Retrieve newly created subfaces.                     //
18057 //                                                                           //
18058 // The new subfaces created by triangulate() can be found by a broadth-first //
18059 // searching starting from 'dummysh[0]'.                                     //
18060 //                                                                           //
18061 // 'newshlist' (empty on input) returns the retrieved subfaces. Each edge on //
18062 // the hull is bound to 'dummysh' and protected by a segment. If 'removeseg' //
18063 // is TRUE, the segment is removed.                                          //
18064 //                                                                           //
18066 
18067 void tetgenmesh::retrievenewsubs(list* newshlist, bool removeseg)
18068 {
18069   face startsh, neighsh;
18070   face deadseg;
18071   int i, j;
18072 
18073   // The first new subface is found at dummysh[0].
18074   startsh.sh = dummysh;
18075   startsh.shver = 0;
18076   spivotself(startsh);
18077   assert(startsh.sh != dummysh);
18078   sinfect(startsh);
18079   newshlist->append(&startsh);
18080 
18081   // Find the rest of new subfaces by a broadth-first searching.
18082   for (i = 0; i < newshlist->len(); i++) {
18083     // Get a new subface s.
18084     startsh = * (face *)(* newshlist)[i];
18085     for (j = 0; j < 3; j++) {
18086       spivot(startsh, neighsh);
18087       if (neighsh.sh != dummysh) {
18088         if (!sinfected(neighsh)) {
18089           // Discovered a new subface.
18090           sinfect(neighsh);
18091           newshlist->append(&neighsh);
18092         }
18093       } else {
18094         // Found a boundary edge. 
18095         if (removeseg) {
18096           // This side of s may be protected by a segment.
18097           sspivot(startsh, deadseg);
18098           if (deadseg.sh != dummysh) {
18099             // Detach it from s.
18100             ssdissolve(startsh);
18101             // Delete the segment.
18102             shellfacedealloc(subsegs, deadseg.sh);
18103           }
18104         }
18105       }
18106       senextself(startsh);
18107     }
18108   }
18109   for (i = 0; i < newshlist->len(); i++) {
18110     startsh = * (face *)(* newshlist)[i];
18111     suninfect(startsh);
18112   }
18113 }
18114 
18116 //                                                                           //
18117 // unifysegments()    Unify identical segments and build facet connections.  //
18118 //                                                                           //
18119 // After creating the surface mesh. Each facet has its own segments.  There  //
18120 // are duplicated segments between adjacent facets.  This routine has three  //
18121 // purposes:                                                                 //
18122 //   (1) identify the set of segments which have the same endpoints and      //
18123 //       unify them into one segment, remove redundant ones;                 //
18124 //   (2) create the face rings of the unified segments, hence setup the      //
18125 //       connections between facets; and                                     //
18126 //   (3) set a unique marker (1-based) for each segment.                     //
18127 // On finish, each segment is unique and the face ring around it (right-hand //
18128 // rule) is constructed. The connections between facets-facets are setup.    //
18129 //                                                                           //
18131 
18132 void tetgenmesh::unifysegments()
18133 {
18134   list *sfacelist;
18135   shellface **facesperverlist;
18136   face subsegloop, testseg;
18137   face sface, sface1, sface2;
18138   point torg, tdest;
18139   REAL da1, da2;
18140   int *idx2facelist;
18141   int segmarker;
18142   int idx, k, m;
18143 
18144   if (b->verbose > 0) {
18145     printf("  Unifying segments.\n");
18146   }
18147 
18148   // Compute a mapping from indices of vertices to subfaces.
18149   makesubfacemap(idx2facelist, facesperverlist);
18150   // Initialize 'sfacelist' for constructing the face link of each segment.
18151   sfacelist = new list(sizeof(face), NULL); 
18152   
18153   segmarker = 1;
18154   subsegs->traversalinit();
18155   subsegloop.sh = shellfacetraverse(subsegs);
18156   while (subsegloop.sh != (shellface *) NULL) {
18157     subsegloop.shver = 0; // For sure.
18158     torg = sorg(subsegloop);
18159     tdest = sdest(subsegloop);
18160     idx = pointmark(torg) - in->firstnumber;
18161     // Loop through the set of subfaces containing 'torg'.  Get all the
18162     //   subfaces containing the edge (torg, tdest). Save and order them
18163     //   in 'sfacelist', the ordering is defined by the right-hand rule
18164     //   with thumb points from torg to tdest.
18165     for (k = idx2facelist[idx]; k < idx2facelist[idx + 1]; k++) {
18166       sface.sh = facesperverlist[k];
18167       sface.shver = 0;
18168       // sface may be died due to the removing of duplicated subfaces.
18169       if (!isdead(&sface) && isfacehasedge(&sface, torg, tdest)) {
18170         // 'sface' contains this segment.
18171         findedge(&sface, torg, tdest);
18172         // Save it in 'sfacelist'.
18173         if (sfacelist->len() < 2) {
18174           sfacelist->append(&sface);
18175         } else {
18176           for (m = 0; m < sfacelist->len() - 1; m++) {
18177             sface1 = * (face *)(* sfacelist)[m];
18178             sface2 = * (face *)(* sfacelist)[m + 1];
18179             da1 = facedihedral(torg, tdest, sapex(sface1), sapex(sface));
18180             da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
18181             if (da1 < da2) {
18182               break;  // Insert it after m.
18183             }
18184           }
18185           sfacelist->insert(m + 1, &sface);
18186         }
18187       }
18188     }
18189     if (b->verbose > 1) {
18190       printf("    Identifying %d segments of (%d  %d).\n", sfacelist->len(),
18191              pointmark(torg), pointmark(tdest));
18192     }
18193     // Set the connection between this segment and faces containing it,
18194     //   at the same time, remove redundant segments.
18195     for (k = 0; k < sfacelist->len(); k++) {
18196       sface = *(face *)(* sfacelist)[k];
18197       sspivot(sface, testseg);
18198       // If 'testseg' is not 'subsegloop', it is a redundant segment that
18199       //   needs be removed. BE CAREFUL it may already be removed. Do not
18200       //   remove it twice, i.e., do test 'isdead()' together.
18201       if ((testseg.sh != subsegloop.sh) && !isdead(&testseg)) {
18202         shellfacedealloc(subsegs, testseg.sh);
18203       }
18204       // 'ssbond' bonds the subface and the segment together, and dissloves
18205       //   the old bond as well.
18206       ssbond(sface, subsegloop);
18207     }
18208     // Set connection between these faces.
18209     sface = *(face *)(* sfacelist)[0];
18210     for (k = 1; k <= sfacelist->len(); k++) {
18211       if (k < sfacelist->len()) {
18212         sface1 = *(face *)(* sfacelist)[k];
18213       } else {
18214         sface1 = *(face *)(* sfacelist)[0];    // Form a face loop.
18215       }
18216       /*
18217       // Check if these two subfaces are the same. It is possible when user
18218       //   defines one facet (or polygon) two or more times. If they are,
18219       //   they should not be bonded together, instead of that, one of them
18220       //   should be delete from the surface mesh.
18221       if ((sfacelist->len() > 1) && sapex(sface) == sapex(sface1)) {
18222         // They are duplicated faces.
18223         if (b->verbose > 0) {
18224           printf("  A duplicated subface (%d, %d, %d) is removed.\n",
18225                  pointmark(torg), pointmark(tdest), pointmark(sapex(sface)));
18226         }
18227         if (k == sfacelist->len()) {
18228           // 'sface' is the last face, however, it is same as the first one.
18229           //   In order to form the ring, we have to let the second last
18230           //   face bond to the first one 'sface1'.
18231           shellfacedealloc(subfaces, sface.sh);
18232           assert(sfacelist->len() >= 2);
18233           assert(k == sfacelist->len());
18234           sface = *(face *)(* sfacelist)[k - 2];
18235         } else {
18236           // 'sface1' is in the middle and may be the last one. 
18237           shellfacedealloc(subfaces, sface1.sh);
18238           // Skip this face and go to the next one.
18239           continue;
18240         }
18241       }
18242       */ 
18243       if (b->verbose > 2) {
18244         printf("    Bond subfaces (%d, %d, %d) and (%d, %d, %d).\n",
18245                pointmark(torg), pointmark(tdest), pointmark(sapex(sface)),
18246                pointmark(torg), pointmark(tdest), pointmark(sapex(sface1)));
18247       }
18248       sbond1(sface, sface1);
18249       sface = sface1;
18250     }
18251     // Set the unique segment marker into the unified segment.
18252     setshellmark(subsegloop, segmarker);
18253     // Increase the marker.
18254     segmarker++;
18255     // Clear the working list.
18256     sfacelist->clear(); 
18257     subsegloop.sh = shellfacetraverse(subsegs);
18258   }
18259 
18260   delete [] idx2facelist;
18261   delete [] facesperverlist;
18262   delete sfacelist;
18263 }
18264 
18266 //                                                                           //
18267 // mergefacets()    Merge adjacent facets to be one facet if they are        //
18268 //                  coplanar and have the same boundary marker.              //
18269 //                                                                           //
18270 // Segments between two merged facets will be removed from the mesh.  If all //
18271 // segments around a vertex have been removed, change its vertex type to be  //
18272 // FREESUBVERTEX. Edge flips will be performed to ensure the Delaunayness of //
18273 // the triangulation of merged facets.                                       //
18274 //                                                                           //
18276 
18277 void tetgenmesh::mergefacets(queue* flipqueue)
18278 {
18279   face parentsh, neighsh, neineighsh;
18280   face segloop;
18281   point eorg, edest;
18282   REAL ori;
18283   bool mergeflag, pbcflag;
18284   int* segspernodelist;
18285   int fidx1, fidx2;
18286   int i, j;
18287 
18288   if (b->verbose > 0) {
18289     printf("  Merging coplanar facets.\n");
18290   }
18291   // Create and initialize 'segspernodelist'.
18292   segspernodelist = new int[points->items + 1];
18293   for (i = 0; i < points->items + 1; i++) segspernodelist[i] = 0;
18294 
18295   // Loop the segments, counter the number of segments sharing each vertex.
18296   subsegs->traversalinit();
18297   segloop.sh = shellfacetraverse(subsegs);
18298   while (segloop.sh != (shellface *) NULL) {
18299     // Increment the number of sharing segments for each endpoint.
18300     for (i = 0; i < 2; i++) {
18301       j = pointmark((point) segloop.sh[3 + i]);
18302       segspernodelist[j]++;
18303     }
18304     segloop.sh = shellfacetraverse(subsegs);
18305   }
18306 
18307   // Loop the segments, find out dead segments.
18308   subsegs->traversalinit();
18309   segloop.sh = shellfacetraverse(subsegs);
18310   while (segloop.sh != (shellface *) NULL) {
18311     eorg = sorg(segloop);
18312     edest = sdest(segloop);
18313     spivot(segloop, parentsh);
18314     spivot(parentsh, neighsh);
18315     spivot(neighsh, neineighsh);
18316     if (parentsh.sh != neighsh.sh && parentsh.sh == neineighsh.sh) {
18317       // Exactly two subfaces at this segment.
18318       fidx1 = shellmark(parentsh) - 1;
18319       fidx2 = shellmark(neighsh) - 1;
18320       pbcflag = false;
18321       if (checkpbcs) {
18322         pbcflag = (shellpbcgroup(parentsh) >= 0)
18323           || (shellpbcgroup(neighsh) >= 0);
18324       }
18325       // Possibly merge them if they are not in the same facet.
18326       if ((fidx1 != fidx2) && !pbcflag) {
18327         // Test if they are coplanar.
18328         ori = orient3d(eorg, edest, sapex(parentsh), sapex(neighsh));
18329         if (ori != 0.0) {
18330           if (iscoplanar(eorg, edest, sapex(parentsh), sapex(neighsh), ori,
18331                          b->epsilon)) {
18332             ori = 0.0; // They are assumed as coplanar.
18333           }
18334         }
18335         if (ori == 0.0) {
18336           mergeflag = (in->facetmarkerlist == (int *) NULL || 
18337           in->facetmarkerlist[fidx1] == in->facetmarkerlist[fidx2]);
18338           if (mergeflag) {
18339             // This segment becomes dead.
18340             if (b->verbose > 1) {
18341               printf("  Removing segment (%d, %d).\n", pointmark(eorg),
18342                      pointmark(edest));
18343             }
18344             ssdissolve(parentsh);
18345             ssdissolve(neighsh);
18346             shellfacedealloc(subsegs, segloop.sh);
18347             j = pointmark(eorg);
18348             segspernodelist[j]--;
18349             if (segspernodelist[j] == 0) {
18350               setpointtype(eorg, FREESUBVERTEX);
18351             }
18352             j = pointmark(edest);
18353             segspernodelist[j]--;
18354             if (segspernodelist[j] == 0) {
18355               setpointtype(edest, FREESUBVERTEX);
18356             }
18357             // Add 'parentsh' to queue checking for flip.
18358             enqueueflipedge(parentsh, flipqueue);
18359           }
18360         }
18361       }
18362     }
18363     segloop.sh = shellfacetraverse(subsegs);
18364   }
18365 
18366   if (!flipqueue->empty()) {
18367     // Restore the Delaunay property in the facet triangulation.
18368     flipsub(flipqueue);
18369   }
18370 
18371   delete [] segspernodelist;
18372 }
18373 
18375 //                                                                           //
18376 // meshsurface()    Create the surface mesh of a PLC.                        //
18377 //                                                                           //
18378 // Let X be the PLC, the surface mesh S of X consists of triangulated facets.//
18379 // S is created mainly in the following steps:                               //
18380 //                                                                           //
18381 // (1) Form the CDT of each facet of X separately (by routine triangulate()).//
18382 // After it is done, the subfaces of each facet are connected to each other, //
18383 // however there is no connection between facets yet.  Notice each facet has //
18384 // its own segments, some of them are duplicated.                            //
18385 //                                                                           //
18386 // (2) Remove the redundant segments created in step (1) (by routine unify-  //
18387 // segment()). The subface ring of each segment is created,  the connection  //
18388 // between facets are established as well.                                   //
18389 //                                                                           //
18390 // The return value indicates the number of segments of X.                   //
18391 //                                                                           //
18393 
18394 long tetgenmesh::meshsurface()
18395 {
18396   list *ptlist, *conlist;
18397   queue *flipqueue;
18398   tetgenio::facet *f;
18399   tetgenio::polygon *p;
18400   memorypool *viri;
18401   point *idx2verlist;
18402   point tstart, tend, *cons;
18403   int *worklist;
18404   int end1, end2;
18405   int shmark, i, j;
18406 
18407   if (!b->quiet) {
18408     printf("Creating surface mesh.\n");
18409   }
18410 
18411   // Compute a mapping from indices to points.
18412   makeindex2pointmap(idx2verlist);
18413   // Compute a mapping from points to tets for computing abovepoints.
18414   makepoint2tetmap();
18415   // Initialize 'facetabovepointarray'.
18416   facetabovepointarray = new point[in->numberoffacets + 1];
18417   for (i = 0; i < in->numberoffacets + 1; i++) {
18418     facetabovepointarray[i] = (point) NULL;
18419   }
18420   if (checkpbcs) {
18421     // Initialize the global array 'subpbcgrouptable'.
18422     createsubpbcgrouptable();
18423   }
18424 
18425   // Initialize working lists.
18426   viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
18427   flipqueue = new queue(sizeof(badface));
18428   ptlist = new list(sizeof(point *), NULL, 256);
18429   conlist = new list(sizeof(point *) * 2, NULL, 256);
18430   worklist = new int[points->items + 1];
18431   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
18432   
18433   // Loop the facet list, triangulate each facet. On finish, all subfaces
18434   //   are in 'subfaces', all segments are in 'subsegs'. Notice: there're
18435   //   redundant segments.  Remember: All facet indices count from 1.
18436   for (shmark = 1; shmark <= in->numberoffacets; shmark++) {    
18437     // Get a facet F.
18438     f = &in->facetlist[shmark - 1];
18439 
18440     // Process the duplicated points first, they are marked with type
18441     //   DUPLICATEDVERTEX by incrflipdelaunay().  Let p and q are dup.
18442     //   and the index of p is larger than q's, p is substituted by q.
18443     //   In a STL mesh, duplicated points are implicitly included.
18444     if ((b->object == tetgenbehavior::STL) || dupverts) {
18445       // Loop all polygons of this facet.
18446       for (i = 0; i < f->numberofpolygons; i++) {
18447         p = &(f->polygonlist[i]);
18448         // Loop other vertices of this polygon.
18449         for (j = 0; j < p->numberofvertices; j++) {
18450           end1 = p->vertexlist[j];
18451           tstart = idx2verlist[end1 - in->firstnumber];
18452           if (pointtype(tstart) == DUPLICATEDVERTEX) {
18453             // Reset the index of vertex-j.
18454             tend = point2ppt(tstart);
18455             end2 = pointmark(tend);
18456             p->vertexlist[j] = end2;
18457           }
18458         }
18459       }
18460     }
18461 
18462     // Loop polygons of F, get the set V of vertices and S of segments.
18463     for (i = 0; i < f->numberofpolygons; i++) {
18464       // Get a polygon.
18465       p = &(f->polygonlist[i]);
18466       // Get the first vertex.
18467       end1 = p->vertexlist[0];
18468       if ((end1 < in->firstnumber) || 
18469           (end1 >= in->firstnumber + in->numberofpoints)) {
18470         if (!b->quiet) {
18471           printf("Warning:  Invalid the 1st vertex %d of polygon", end1);
18472           printf(" %d in facet %d.\n", i + 1, shmark);
18473         }
18474         continue; // Skip this polygon.
18475       }
18476       tstart = idx2verlist[end1 - in->firstnumber];
18477       // Add tstart to V if it haven't been added yet.
18478       if (worklist[end1] == 0) {
18479         ptlist->append(&tstart);
18480         worklist[end1] = 1;
18481       }
18482       // Loop other vertices of this polygon.
18483       for (j = 1; j <= p->numberofvertices; j++) {
18484         // get a vertex.
18485         if (j < p->numberofvertices) {
18486           end2 = p->vertexlist[j];
18487         } else {
18488           end2 = p->vertexlist[0];  // Form a loop from last to first.
18489         }
18490         if ((end2 < in->firstnumber) ||
18491             (end2 >= in->firstnumber + in->numberofpoints)) {
18492           if (!b->quiet) {
18493             printf("Warning:  Invalid vertex %d in polygon %d", end2, i + 1);
18494             printf(" in facet %d.\n", shmark);
18495           }
18496         } else {
18497           if (end1 != end2) {
18498             // 'end1' and 'end2' form a segment.
18499             tend = idx2verlist[end2 - in->firstnumber];
18500             // Add tstart to V if it haven't been added yet.
18501             if (worklist[end2] == 0) {
18502               ptlist->append(&tend);
18503               worklist[end2] = 1;
18504             }
18505             // Save the segment in S (conlist).
18506             cons = (point *) conlist->append(NULL);
18507             cons[0] = tstart;
18508             cons[1] = tend;
18509             // Set the start for next continuous segment.
18510             end1 = end2;
18511             tstart = tend;
18512           } else {
18513             // Two identical vertices represent an isolated vertex of F.
18514             if (p->numberofvertices > 2) {
18515               // This may be an error in the input, anyway, we can continue
18516               //   by simply skipping this segment.
18517               if (!b->quiet) {
18518                 printf("Warning:  Polygon %d has two identical verts", i + 1);
18519                 printf(" in facet %d.\n", shmark);
18520               }
18521             } 
18522             // Ignore this vertex.
18523           } 
18524         }
18525         // Is the polygon degenerate (a segment or a vertex)?
18526         if (p->numberofvertices == 2) break;
18527       } 
18528     }
18529     // Unmark vertices.
18530     for (i = 0; i < ptlist->len(); i++) {
18531       tstart = * (point *)(* ptlist)[i];
18532       end1 = pointmark(tstart);
18533       assert(worklist[end1] == 1);
18534       worklist[end1] = 0;
18535     }
18536 
18537     // Create a CDT of F.
18538     triangulate(shmark, b->epsilon * 1e+2, ptlist, conlist, f->numberofholes,
18539                 f->holelist, viri, flipqueue);
18540     // Clear working lists.
18541     ptlist->clear();
18542     conlist->clear();
18543     viri->restart();
18544   }
18545 
18546   // Unify segments in 'subsegs', remove redundant segments.  Face links
18547   //   of segments are also built.
18548   unifysegments();
18549   // Remember the number of input segments (for output).
18550   insegments = subsegs->items;
18551 
18552   if (checkpbcs) {
18553     // Create the global array 'segpbcgrouptable'.
18554     createsegpbcgrouptable();
18555   }
18556 
18557   if (b->object == tetgenbehavior::STL) {
18558     // Remove redundant vertices (for .stl input mesh).
18559     jettisonnodes();
18560   }
18561 
18562   if (!b->nomerge && !b->nobisect && !checkpbcs) {
18563     // No '-M' switch - merge adjacent facets if they are coplanar.
18564     mergefacets(flipqueue);
18565   }
18566 
18567   delete [] idx2verlist;
18568   delete [] worklist;
18569   delete ptlist;
18570   delete conlist;
18571   delete flipqueue;
18572   delete viri;
18573 
18574   return subsegs->items;
18575 }
18576 
18577 //
18578 // End of surface triangulation routines
18579 //
18580 
18582 //                                                                           //
18583 // interecursive()    Recursively do intersection test on a set of triangles.//
18584 //                                                                           //
18585 // Recursively split the set 'subfacearray' of subfaces into two sets using  //
18586 // a cut plane parallel to x-, or, y-, or z-axies.  The split criteria are   //
18587 // follows. Assume the cut plane is H, and H+ denotes the left halfspace of  //
18588 // H, and H- denotes the right halfspace of H; and s be a subface:           //
18589 //                                                                           //
18590 //    (1) If all points of s lie at H+, put it into left array;              //
18591 //    (2) If all points of s lie at H-, put it into right array;             //
18592 //    (3) If some points of s lie at H+ and some of lie at H-, or some       //
18593 //        points lie on H, put it into both arraies.                         //
18594 //                                                                           //
18595 // Partitions by x-axis if axis == '0'; by y-axis if axis == '1'; by z-axis  //
18596 // if axis == '2'. If current cut plane is parallel to the x-axis, the next  //
18597 // one will be parallel to y-axis, and the next one after the next is z-axis,//
18598 // and then alternately return back to x-axis.                               //
18599 //                                                                           //
18600 // Stop splitting when the number of triangles of the input array is not     //
18601 // decreased anymore. Do tests on the current set.                           //
18602 //                                                                           //
18604 
18605 void tetgenmesh::
18606 interecursive(shellface** subfacearray, int arraysize, int axis, REAL bxmin,
18607               REAL bxmax, REAL bymin, REAL bymax, REAL bzmin, REAL bzmax,
18608               int* internum)
18609 {
18610   shellface **leftarray, **rightarray;
18611   face sface1, sface2;
18612   point p1, p2, p3;
18613   point p4, p5, p6;
18614   enum interresult intersect;
18615   REAL split;
18616   bool toleft, toright;
18617   int leftsize, rightsize;
18618   int i, j;
18619 
18620   if (b->verbose > 1) {
18621     printf("  Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
18622            arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
18623            axis == 0 ? "x" : (axis == 1 ? "y" : "z"));
18624   }
18625     
18626   leftarray = new shellface*[arraysize];
18627   if (leftarray == NULL) {
18628     printf("Error in interecursive():  Insufficient memory.\n");
18629     terminatetetgen(1);
18630   }
18631   rightarray = new shellface*[arraysize];
18632   if (rightarray == NULL) {
18633     printf("Error in interecursive():  Insufficient memory.\n");
18634     terminatetetgen(1);
18635   }
18636   leftsize = rightsize = 0;
18637 
18638   if (axis == 0) {
18639     // Split along x-axis.
18640     split = 0.5 * (bxmin + bxmax);
18641   } else if (axis == 1) {
18642     // Split along y-axis.
18643     split = 0.5 * (bymin + bymax);
18644   } else {
18645     // Split along z-axis.
18646     split = 0.5 * (bzmin + bzmax);
18647   }
18648 
18649   for (i = 0; i < arraysize; i++) {
18650     sface1.sh = subfacearray[i];
18651     p1 = (point) sface1.sh[3];
18652     p2 = (point) sface1.sh[4];
18653     p3 = (point) sface1.sh[5];
18654     toleft = toright = false;
18655     if (p1[axis] < split) {
18656       toleft = true;
18657       if (p2[axis] >= split || p3[axis] >= split) {
18658         toright = true;
18659       } 
18660     } else if (p1[axis] > split) {
18661       toright = true;
18662       if (p2[axis] <= split || p3[axis] <= split) {
18663         toleft = true;
18664       } 
18665     } else {
18666       // p1[axis] == split;
18667       toleft = true;
18668       toright = true;
18669     }
18670     // At least one is true;
18671 #ifdef SELF_CHECK
18672     assert(!(toleft == false && toright == false));
18673 #endif
18674     if (toleft) {
18675       leftarray[leftsize] = sface1.sh;
18676       leftsize++;
18677     }
18678     if (toright) {
18679       rightarray[rightsize] = sface1.sh;
18680       rightsize++;
18681     }
18682   }
18683 
18684   if (leftsize < arraysize && rightsize < arraysize) {
18685     // Continue to partition the input set. Now 'subfacearray' has been
18686     //   split into two sets, it's memory can be freed. 'leftarray' and
18687     //   'rightarray' will be freed in the next recursive (after they're
18688     //   partitioned again or performing tests).
18689     delete [] subfacearray;
18690     // Continue to split these two sets.
18691     if (axis == 0) {
18692       interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax,
18693                     bzmin, bzmax, internum);
18694       interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax,
18695                     bzmin, bzmax, internum);
18696     } else if (axis == 1) {
18697       interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split,
18698                     bzmin, bzmax, internum);
18699       interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax,
18700                     bzmin, bzmax, internum);
18701     } else {
18702       interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax,
18703                     bzmin, split, internum);
18704       interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax,
18705                     split, bzmax, internum);
18706     }
18707   } else {
18708     if (b->verbose > 1) {
18709       printf("  Checking intersecting faces.\n");
18710     }
18711     // Perform a brute-force compare on the set.
18712     for (i = 0; i < arraysize; i++) {
18713       sface1.sh = subfacearray[i];
18714       p1 = (point) sface1.sh[3];
18715       p2 = (point) sface1.sh[4];
18716       p3 = (point) sface1.sh[5];
18717       for (j = i + 1; j < arraysize; j++) {
18718         sface2.sh = subfacearray[j];
18719         p4 = (point) sface2.sh[3];
18720         p5 = (point) sface2.sh[4];
18721         p6 = (point) sface2.sh[5];
18722         intersect = tri_tri_inter(p1, p2, p3, p4, p5, p6);
18723         if (intersect == INTERSECT || intersect == SHAREFACE) {
18724           if (!b->quiet) {
18725             if (intersect == INTERSECT) {
18726               printf("  Facet #%d intersects facet #%d at triangles:\n",
18727                      shellmark(sface1), shellmark(sface2));
18728               printf("    (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
18729                      pointmark(p1), pointmark(p2), pointmark(p3),
18730                      pointmark(p4), pointmark(p5), pointmark(p6));
18731             } else {
18732               printf("  Facet #%d duplicates facet #%d at triangle:\n",
18733                      shellmark(sface1), shellmark(sface2));
18734               printf("    (%4d, %4d, %4d)\n", pointmark(p1), pointmark(p2),
18735                      pointmark(p3));
18736             }
18737           }
18738           // Increase the number of intersecting pairs.
18739           (*internum)++; 
18740           // Infect these two faces (although they may already be infected).
18741           sinfect(sface1);
18742           sinfect(sface2);
18743         }
18744       }
18745     }
18746     // Don't forget to free all three arrays. No further partition.
18747     delete [] leftarray;
18748     delete [] rightarray;  
18749     delete [] subfacearray;
18750   }
18751 }
18752 
18754 //                                                                           //
18755 // detectinterfaces()    Detect intersecting triangles.                      //
18756 //                                                                           //
18757 // Given a set of triangles,  find the pairs of intersecting triangles from  //
18758 // them.  Here the set of triangles is in 'subfaces' which is a surface mesh //
18759 // of a PLC (.poly or .smesh).                                               //
18760 //                                                                           //
18761 // To detect whether two triangles are intersecting is done by the routine   //
18762 // 'tri_tri_inter()'.  The algorithm for the test is very simple and stable. //
18763 // It is based on geometric orientation test which uses exact arithmetics.   //
18764 //                                                                           //
18765 // Use divide-and-conquer algorithm for reducing the number of intersection  //
18766 // tests.  Start from the bounding box of the input point set, recursively   //
18767 // partition the box into smaller boxes, until the number of triangles in a  //
18768 // box is not decreased anymore. Then perform triangle-triangle tests on the //
18769 // remaining set of triangles.  The memory allocated in the input set is     //
18770 // freed immediately after it has been partitioned into two arrays.  So it   //
18771 // can be re-used for the consequent partitions.                             //
18772 //                                                                           //
18773 // On return, the pool 'subfaces' will be cleared, and only the intersecting //
18774 // triangles remain for output (to a .face file).                            //
18775 //                                                                           //
18777 
18778 void tetgenmesh::detectinterfaces()
18779 {
18780   shellface **subfacearray;
18781   face shloop;
18782   int internum;
18783   int i;
18784 
18785   if (!b->quiet) {
18786     printf("Detecting intersecting facets.\n");
18787   }
18788 
18789   // Construct a map from indices to subfaces;
18790   subfacearray = new shellface*[subfaces->items];
18791   subfaces->traversalinit();
18792   shloop.sh = shellfacetraverse(subfaces);
18793   i = 0;
18794   while (shloop.sh != (shellface *) NULL) {
18795     subfacearray[i] = shloop.sh;
18796     shloop.sh = shellfacetraverse(subfaces);
18797     i++;
18798   }
18799 
18800   internum = 0;
18801   // Recursively split the set of triangles into two sets using a cut plane
18802   //   parallel to x-, or, y-, or z-axies.  Stop splitting when the number
18803   //   of subfaces is not decreasing anymore. Do tests on the current set.
18804   interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax,
18805                 zmin, zmax, &internum);
18806 
18807   if (!b->quiet) {
18808     if (internum > 0) {
18809       printf("\n!! Found %d pairs of faces are intersecting.\n\n", internum);
18810     } else {
18811       printf("\nNo faces are intersecting.\n\n");
18812     }
18813   }
18814 
18815   if (internum > 0) {
18816     // Traverse all subfaces, deallocate those have not been infected (they
18817     //   are not intersecting faces). Uninfect those have been infected.
18818     //   After this loop, only intersecting faces remain.
18819     subfaces->traversalinit();
18820     shloop.sh = shellfacetraverse(subfaces);
18821     while (shloop.sh != (shellface *) NULL) {
18822       if (sinfected(shloop)) {
18823         suninfect(shloop);
18824       } else {
18825         shellfacedealloc(subfaces, shloop.sh);
18826       }
18827       shloop.sh = shellfacetraverse(subfaces);
18828     }
18829   } else {
18830     // Deallocate all subfaces.
18831     subfaces->restart();
18832   }
18833 }
18834 
18835 //
18836 // Begin of periodic boundary condition routines
18837 //
18838 
18840 //                                                                           //
18841 // createsubpbcgrouptable()    Create the 'subpbcgrouptable'.                //
18842 //                                                                           //
18843 // Allocate the memory for 'subpbcgrouptable'.  Each entry i (a pbcdata) of  //
18844 // the table represents a pbcgroup.  Most of the fields of a group-i are set //
18845 // in this routine. 'fmark[0]', 'fmark[1]', and 'transmat[0]' are directly   //
18846 // copied from the corresponding data of 'in->numberofpbcgroups'. 'transmat  //
18847 // [1]' is calculated as the inverse matrix of 'transmat[0]'.  'ss[0]' and   //
18848 // 'ss[1]' are initilized be 'dummysh'. They are set in 'trangulatefacet()'  //
18849 // (when -p is in use) or 'reconstructmesh()' (when -r is in use).           //
18850 //                                                                           //
18852 
18853 void tetgenmesh::createsubpbcgrouptable()
18854 {
18855   tetgenio::pbcgroup *pg;
18856   pbcdata *pd;
18857   REAL A[4][4], rhs[4], D;
18858   int indx[4];
18859   int i, j, k;
18860 
18861   subpbcgrouptable = new pbcdata[in->numberofpbcgroups];
18862   for (i = 0; i < in->numberofpbcgroups; i++) {
18863     pg = &(in->pbcgrouplist[i]);
18864     pd = &(subpbcgrouptable[i]);
18865     // Copy data from pg to pd.
18866     pd->fmark[0] = pg->fmark1;
18867     pd->fmark[1] = pg->fmark2;
18868     // Initialize array 'pd->ss'.
18869     pd->ss[0].sh = dummysh;
18870     pd->ss[1].sh = dummysh;
18871     // Copy the transform matrix from pg to pd->transmat[0].
18872     for (j = 0; j < 4; j++) {
18873       for (k = 0; k < 4; k++) {
18874         pd->transmat[0][j][k] = pg->transmat[j][k];
18875         // Prepare for inverting the matrix.
18876         A[j][k] = pg->transmat[j][k];
18877       }
18878     }
18879     // Calculate the inverse matrix (pd->transmat[1]) of pd->transmat[0].
18880     lu_decmp(A, 4, indx, &D, 0);
18881     for (j = 0; j < 4; j++) {
18882       for (k = 0; k < 4; k++) rhs[k] = 0.0;
18883       rhs[j] = 1.0;
18884       lu_solve(A, 4, indx, rhs, 0);
18885       for (k = 0; k < 4; k++) pd->transmat[1][k][j] = rhs[k];
18886     }
18887   }
18888 }
18889 
18891 //                                                                           //
18892 // getsubpbcgroup()    Get the pbcgroup of a subface.                        //
18893 //                                                                           //
18894 // 'pbcsub' has pbc defined. Its pbcgroup is returned in 'pd'. In addition,  //
18895 // 'f1' (0 or 1) indicates the position of 'pbcsub' in 'pd'; 'f2' (= 1 - f1) //
18896 // is the position where the symmetric subface of 'pbcsub' is found.         //
18897 //                                                                           //
18899 
18900 void tetgenmesh::getsubpbcgroup(face* pbcsub, pbcdata** pd, int *f1, int *f2)
18901 {
18902   int groupid, fmark, idx;
18903 
18904   groupid = shellpbcgroup(*pbcsub);
18905   *pd = &subpbcgrouptable[groupid];
18906   
18907   // Get the facet index (1 - based).
18908   idx = shellmark(*pbcsub);
18909   // Get the facet marker from array (0 - based).
18910   fmark = in->facetmarkerlist[idx - 1];
18911   if ((*pd)->fmark[0] == fmark) {
18912     *f1 = 0;
18913   } else {
18914 #ifdef SELF_CHECK
18915     assert((*pd)->fmark[1] == fmark);
18916 #endif
18917     *f1 = 1;
18918   }
18919   *f2 = 1 - (*f1);
18920 }
18921 
18923 //                                                                           //
18924 // getsubpbcsympoint()    Compute the symmetric point for a subface point.   //
18925 //                                                                           //
18926 // 'newpoint' lies on 'splitsub'. This routine calculates a 'sympoint' which //
18927 // locates on 'symsplitsub' and symmtric to 'newpoint'.  Return the location //
18928 // of sympoint wrt. symsplitsub.                                             //
18929 //                                                                           //
18931 
18932 enum tetgenmesh::locateresult tetgenmesh:: getsubpbcsympoint(point newpoint,
18933   face* splitsub, point sympoint, face* symsplitsub)
18934 {
18935   pbcdata *pd;
18936   face subloop;
18937   point pa, pb, pc;
18938   enum locateresult symloc;
18939   REAL ori;
18940   int f1, f2, i;
18941 
18942   // Get the pbcgroup of 'splitsub'.
18943   getsubpbcgroup(splitsub, &pd, &f1, &f2);
18944       
18945   // Transform newpoint from f1 -> f2.
18946   for (i = 0; i < 3; i++) {
18947     sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
18948                 + pd->transmat[f1][i][1] * newpoint[1]
18949                 + pd->transmat[f1][i][2] * newpoint[2]
18950                 + pd->transmat[f1][i][3] * 1.0;
18951   }
18952   // Locate sympoint in f2.
18953   symloc = OUTSIDE;
18954   *symsplitsub = pd->ss[f2];
18955   // Is the stored subface valid? Hole removal may delete the subface.  
18956   if ((symsplitsub->sh != dummysh) && !isdead(symsplitsub)) {
18957     // 'symsplitsub' should lie on the symmetric facet. Check it.
18958     i = shellmark(*symsplitsub);
18959     if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18960       // 'symsplitsub' has the symmetric boundary marker.
18961       pa = sorg(*symsplitsub);
18962       pb = sdest(*symsplitsub);
18963       pc = sapex(*symsplitsub);
18964       // Test if they are (nearly) coplanar. Some facets may have the
18965       //   same boundary marker but not coplanar with this point.
18966       ori = orient3d(pa, pb, pc, sympoint);
18967       if (iscoplanar(pa, pb, pc, sympoint, ori, b->epsilon * 1e+2)) {
18968         // Locate sympoint in facet. Don't stop at subsegment.
18969         abovepoint = facetabovepointarray[shellmark(*symsplitsub)];
18970         if (abovepoint == (point) NULL) {
18971           getfacetabovepoint(symsplitsub);
18972         }
18973         symloc = locatesub(sympoint, symsplitsub, 0, b->epsilon * 1e+2);
18974       }
18975     }
18976   }
18977   if (symloc == OUTSIDE) {
18978     // Do a brute-force searching for the symmetric subface.
18979     REAL epspp = b->epsilon * 1e+2;
18980     int lcount = 0;
18981     do {
18982       // Locate sympoint in the pool of subfaces (with fmark pd->fmark[f2]).
18983       subfaces->traversalinit();
18984       subloop.sh = shellfacetraverse(subfaces);
18985       while (subloop.sh != (shellface *) NULL) {
18986         i = shellmark(subloop);
18987         if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18988           // Found a facet have the symmetric boundary marker.
18989           pa = sorg(subloop);
18990           pb = sdest(subloop);
18991           pc = sapex(subloop);
18992           // Test if they are (nearly) coplanar. Some facets may have the
18993           //   same boundary marker but not coplanar with this point.
18994           ori = orient3d(pa, pb, pc, sympoint);
18995           if (iscoplanar(pa, pb, pc, sympoint, ori, epspp)) {
18996             // Test if sympoint is (nearly) inside this facet. 
18997             // Get the abovepoint of the facet.
18998             abovepoint = facetabovepointarray[shellmark(subloop)];
18999             // Do we need to calculate the abovepoint?
19000             if (abovepoint == (point) NULL) {
19001               getfacetabovepoint(&subloop);
19002             }
19003             // subloop is on the facet, search sympoint.
19004             symloc = locatesub(sympoint, &subloop, 0, epspp);
19005             if (symloc != OUTSIDE) break;
19006           }
19007         }
19008         subloop.sh = shellfacetraverse(subfaces);
19009       }
19010       lcount++;
19011       epspp *= 10.0;
19012     } while ((symloc == OUTSIDE) && (lcount < 3));
19013 #ifdef SELF_CHECK
19014     // sympoint should be inside the facet.
19015     assert(symloc != OUTSIDE);
19016 #endif
19017     // Set the returning subface.
19018     *symsplitsub = subloop;
19019     // Update the stored subface for next searching.
19020     pd->ss[f2] = *symsplitsub;
19021   }
19022 
19023   return adjustlocatesub(sympoint, symsplitsub, symloc, b->epsilon);
19024 }
19025 
19027 //                                                                           //
19028 // createsegpbcgrouptable()    Create the 'segpbcgrouptable'.                //
19029 //                                                                           //
19030 // Each segment may belong to more than one pbcgroups.  For example, segment //
19031 // ab may need to be symmteric to both segments cd, and ef, then  ab and cd, //
19032 // cd and ef, ef and ab form three pbcgroups.                                //
19033 //                                                                           //
19034 // 'segpbcgrouptable' is  implemented as a list of pbcdatas. Each item i is  //
19035 // a pbcgroup.                                                               //
19036 //                                                                           //
19038 
19039 void tetgenmesh::createsegpbcgrouptable()
19040 {
19041   shellface** segsperverlist;
19042   pbcdata *pd, *ppd, pd1, pd2;
19043   face segloop, symseg;
19044   face startsh, spinsh, symsh;
19045   point pa, pb, syma, symb;
19046   enum locateresult symloc;
19047   REAL testpt[3], sympt[3];
19048   bool inflag;
19049   int *idx2seglist;
19050   int segid1, segid2;
19051   int f1, f2;
19052   int i, j, k, l;
19053 
19054   // Allocate memory for 'subpbcgrouptable'.
19055   segpbcgrouptable = new list(sizeof(pbcdata), NULL, 256);
19056 
19057   if (b->refine) {
19058     // Create a point-to-seg map for quickly finding PBC seg pairs.
19059     makesegmentmap(idx2seglist, segsperverlist);
19060   }
19061 
19062   // Loop through the segment list.
19063   subsegs->traversalinit();
19064   segloop.sh = shellfacetraverse(subsegs);
19065   while (segloop.sh != (shellface *) NULL) {
19066     // Loop the subface ring of segloop ab.
19067     pa = sorg(segloop);
19068     pb = sdest(segloop);
19069     segid1 = shellmark(segloop);
19070     spivot(segloop, startsh);
19071     spinsh = startsh;
19072     do {
19073       // Adjust spinsh be edge ab.
19074       if (sorg(spinsh) != pa) {
19075         sesymself(spinsh);
19076       }
19077       // Does spinsh belong to a pbcgroup?
19078       if (shellpbcgroup(spinsh) != -1) {
19079         // Yes! There exists a segment cd. ab and cd form a pbcgroup.
19080         if (b->refine) {
19081           getsubpbcgroup(&spinsh, &pd, &f1, &f2);
19082           // Transform pa from f1 -> f2.
19083           for (i = 0; i < 3; i++) {
19084             sympt[i] = pd->transmat[f1][i][0] * pa[0]
19085                      + pd->transmat[f1][i][1] * pa[1]
19086                      + pd->transmat[f1][i][2] * pa[2]
19087                      + pd->transmat[f1][i][3] * 1.0;
19088           }
19089           syma = point2pbcpt(pa);
19090           // Is 'sympt == syma'?
19091           if (distance(sympt, syma) > (longest * b->epsilon)) {
19092             // No. Search the symmetric vertex of pa.
19093             symloc = getsubpbcsympoint(pa, &spinsh, sympt, &symsh);
19094             syma = sorg(symsh);
19095             if (symloc != ONVERTEX) {
19096               // Do a brute force search. Not done yet.
19097               assert(0);
19098             }
19099           }
19100           // Transform pb from f1 -> f2.
19101           for (i = 0; i < 3; i++) {
19102             sympt[i] = pd->transmat[f1][i][0] * pb[0]
19103                      + pd->transmat[f1][i][1] * pb[1]
19104                      + pd->transmat[f1][i][2] * pb[2]
19105                      + pd->transmat[f1][i][3] * 1.0;
19106           }
19107           // Search sym subface from the point-to-subface map.
19108           symseg.shver = 0;
19109           j = pointmark(syma) - in->firstnumber;
19110           for (i = idx2seglist[j]; i < idx2seglist[j + 1]; i++) {
19111             symseg.sh = segsperverlist[i];
19112             if (sorg(symseg) == syma) symb = sdest(symseg);
19113             else symb = sorg(symseg);
19114             if (distance(sympt, symb) <= (longest * b->epsilon)) break;
19115           }
19116           assert(i < idx2seglist[j + 1]);
19117         } else {
19118           //   'testpt' is the midpoint of ab used to find cd.
19119           for (i = 0; i < 3; i++) testpt[i] = 0.5 * (pa[i] + pb[i]);
19120           symloc = getsubpbcsympoint(testpt, &spinsh, sympt, &symsh);
19121 #ifdef SELF_CHECK
19122           assert(symloc == ONEDGE);
19123 #endif
19124           sspivot(symsh, symseg);
19125         }
19126 #ifdef SELF_CHECK
19127         assert(symseg.sh != dummysh);
19128 #endif
19129         // Check whether this group has already been created in list.
19130         segid2 = shellmark(symseg);
19131         inflag = false;
19132         for (i = 0; i < segpbcgrouptable->len() && !inflag; i++) {
19133           pd = (pbcdata *)(* segpbcgrouptable)[i];
19134           if (pd->segid[0] == segid1) {
19135             if (pd->segid[1] == segid2) inflag = true;
19136           } else if (pd->segid[0] == segid2) {
19137             if (pd->segid[1] == segid1) inflag = true;
19138           }
19139         }
19140         if (!inflag) {
19141           // Create a segment pbcgroup in list for ab and cd.
19142           pd = (pbcdata *) segpbcgrouptable->append(NULL);
19143           // Save the markers of ab and cd.
19144           pd->segid[0] = segid1;
19145           pd->segid[1] = segid2;
19146           // Save the handles of ab and cd.
19147           pd->ss[0] = segloop;
19148           pd->ss[1] = symseg;
19149           // Find the map from ab to cd.
19150           getsubpbcgroup(&spinsh, &ppd, &f1, &f2);
19151           pd->fmark[0] = ppd->fmark[f1];
19152           pd->fmark[1] = ppd->fmark[f2];
19153           // Set the map from ab to cd.
19154           for (i = 0; i < 4; i++) {
19155             for (j = 0; j < 4; j++) {
19156               pd->transmat[0][i][j] = ppd->transmat[f1][i][j];
19157             }
19158           }
19159           // Set the map from cd to ab.
19160           for (i = 0; i < 4; i++) {
19161             for (j = 0; j < 4; j++) {
19162               pd->transmat[1][i][j] = ppd->transmat[f2][i][j];
19163             }
19164           }
19165         }
19166       }
19167       // Go to the next subface in the ring of ab.
19168       spivotself(spinsh);
19169     } while (spinsh.sh != startsh.sh);
19170     segloop.sh = shellfacetraverse(subsegs);
19171   }
19172   
19173   if (b->refine) {
19174     delete [] segsperverlist;
19175     delete [] idx2seglist;
19176   }
19177 
19178   // Create the indirect segment pbcgroups.
19179   // Bug-fixed (08 Sept. 2006). The total size of 'segpbcgrouptable' may get
19180   //   increased. Do not use pointers for 'pd1' and 'pd2'. The addresses may
19181   //   be invaild after realloc().
19182   for (i = 0; i < segpbcgrouptable->len(); i++) {
19183     pd1 = * (pbcdata *)(* segpbcgrouptable)[i];
19184     for (f1 = 0; f1 < 2; f1++) {
19185       // Search for a group (except i) contains pd1.segid[f1].
19186       for (j = 0; j < segpbcgrouptable->len(); j++) {
19187         if (j == i) continue;
19188         pd2 = * (pbcdata *)(* segpbcgrouptable)[j];
19189         f2 = -1;
19190         if (pd1.segid[f1] == pd2.segid[0]) {
19191           f2 = 0;
19192         } else if (pd1.segid[f1] == pd2.segid[1]) {
19193           f2 = 1;
19194         }
19195         if (f2 != -1) {
19196 #ifdef SELF_CHECK
19197           assert(pd1.segid[f1] == pd2.segid[f2]);
19198 #endif
19199           segid1 = pd1.segid[1 - f1];
19200           segid2 = pd2.segid[1 - f2];
19201           // Search for the existence of segment pbcgroup (segid1, segid2).
19202           inflag = false;
19203           for (k = 0; k < segpbcgrouptable->len() && !inflag; k++) {
19204             pd = (pbcdata *)(* segpbcgrouptable)[k];
19205             if (pd->segid[0] == segid1) {
19206               if (pd->segid[1] == segid2) inflag = true;
19207             } else if (pd->segid[0] == segid2) {
19208               if (pd->segid[1] == segid1) inflag = true;
19209             }
19210           }
19211           if (!inflag) {
19212             pd = (pbcdata *) segpbcgrouptable->append(NULL);
19213             pd->segid[0] = pd1.segid[1 - f1];
19214             pd->segid[1] = pd2.segid[1 - f2];
19215             pd->ss[0] = pd1.ss[1 - f1];
19216             pd->ss[1] = pd2.ss[1 - f2];
19217             // Invalid the fmark[0] == fmark[1].
19218             pd->fmark[0] = pd->fmark[1] = 0;
19219             // Translate matrix pd->transmat[0] = m2 * m1, where m1 =
19220             //   pd1.transmat[1 - f1], m2 = pd2.transmat[f2].
19221             for (k = 0; k < 4; k++) {
19222               for (l = 0; l < 4; l++) { 
19223                 pd->transmat[0][k][l] = pd2.transmat[f2][k][l];
19224               }
19225             }
19226             m4xm4(pd->transmat[0], pd1.transmat[1 - f1]);
19227             // Translate matrix pd->transmat[1] = m4 * m3, where m3 =
19228             //   pd2.transmat[1 - f2], m4 = pd1.transmat[f1].
19229             for (k = 0; k < 4; k++) {
19230               for (l = 0; l < 4; l++) { 
19231                 pd->transmat[1][k][l] = pd1.transmat[f1][k][l];
19232               }
19233             }
19234             m4xm4(pd->transmat[1], pd2.transmat[1 - f2]);
19235           }
19236         }
19237       }
19238     }
19239   }
19240 
19241   // Form a map from segment index to pbcgroup list of this segment.
19242   idx2segpglist = new int[subsegs->items + 1];
19243   for (i = 0; i < subsegs->items + 1; i++) idx2segpglist[i] = 0;
19244   // Loop through 'segpbcgrouptable', counter the number of pbcgroups of
19245   //   each segment.
19246   for (i = 0; i < segpbcgrouptable->len(); i++) {
19247     pd = (pbcdata *)(* segpbcgrouptable)[i];
19248     for (j = 0; j < 2; j++) {
19249       k = pd->segid[j] - 1;
19250       idx2segpglist[k]++;
19251     }
19252   }
19253   // Calculate the total length of array 'segpglist'.
19254   j = idx2segpglist[0];
19255   idx2segpglist[0] = 0;  // Array starts from 0 element.
19256   for (i = 0; i < subsegs->items; i++) {
19257     k = idx2segpglist[i + 1];
19258     idx2segpglist[i + 1] = idx2segpglist[i] + j;
19259     j = k;
19260   }
19261   // The total length is in the last unit of idx2segpglist.
19262   segpglist = new int[idx2segpglist[i]];
19263   // Loop the set of pbcgroups again, set the data into segpglist.
19264   for (i = 0; i < segpbcgrouptable->len(); i++) {
19265     pd = (pbcdata *)(* segpbcgrouptable)[i];
19266     for (j = 0; j < 2; j++) {
19267       k = pd->segid[j] - 1;
19268       segpglist[idx2segpglist[k]] = i;
19269       idx2segpglist[k]++;
19270     }
19271   }
19272   // Contents in 'idx2segpglist' are shifted, now shift them back.
19273   for (i = subsegs->items - 1; i >= 0; i--) {
19274     idx2segpglist[i + 1] = idx2segpglist[i];
19275   }
19276   idx2segpglist[0] = 0;
19277 }
19278 
19280 //                                                                           //
19281 // getsegpbcsympoint()    Compute the symmetric point for a segment point.   //
19282 //                                                                           //
19283 // 'newpoint' lies on 'splitseg'. This routine calculates a 'sympoint' which //
19284 // locates on 'symsplitseg' and symmtric to 'newpoint'.  Return the location //
19285 // of sympoint wrt. symsplitseg.                                             //
19286 //                                                                           //
19288 
19289 enum tetgenmesh::locateresult tetgenmesh::
19290 getsegpbcsympoint(point newpoint, face* splitseg, point sympoint,
19291                   face* symsplitseg, int groupid)
19292 {
19293   pbcdata *pd;
19294   enum locateresult symloc;
19295   int segid, f1, f2, i;
19296 
19297   pd = (pbcdata *)(* segpbcgrouptable)[groupid];
19298   segid = shellmark(*splitseg);
19299   if (pd->segid[0] == segid) {
19300     f1 = 0;
19301   } else {
19302 #ifdef SELF_CHECK
19303     assert(pd->segid[1] == segid);
19304 #endif
19305     f1 = 1;
19306   }
19307   f2 = 1 - f1;
19308 
19309   // Transform newpoint from f1 -> f2.
19310   for (i = 0; i < 3; i++) {
19311     sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
19312                 + pd->transmat[f1][i][1] * newpoint[1]
19313                 + pd->transmat[f1][i][2] * newpoint[2]
19314                 + pd->transmat[f1][i][3] * 1.0;
19315   }
19316   // Locate sympoint in f2.
19317   *symsplitseg = pd->ss[f2];
19318 #ifdef SELF_CHECK
19319   assert(symsplitseg->sh != dummysh);
19320 #endif
19321   // Locate sympoint in facet. Stop at subsegment.
19322   symloc = locateseg(sympoint, symsplitseg);
19323   symloc = adjustlocateseg(sympoint, symsplitseg, symloc, b->epsilon * 1e+2);
19324   return symloc;
19325 }
19326 
19327 //
19328 // End of periodic boundary condition routines
19329 //
19330 
19331 //
19332 // Begin of vertex perturbation routines
19333 //
19334 
19336 //                                                                           //
19337 // randgenerator()    Generate a random REAL number between (0, |range|).    //
19338 //                                                                           //
19340 
19341 REAL tetgenmesh::randgenerator(REAL range)
19342 {
19343   REAL worknumber, result;
19344   int expo;
19345 
19346   if (range == 0.0) return 0.0;
19347 
19348   expo = 0;
19349   worknumber = fabs(range);
19350   // Normalize worknumber (i.e., 1.xxxExx)
19351   if (worknumber > 10.0) {
19352     while (worknumber > 10.0) {
19353       worknumber /= 10.0;
19354       expo++;
19355     }
19356   } else if (worknumber < 1.0) {
19357     while (worknumber < 1.0) {
19358       worknumber *= 10.0;
19359       expo--;
19360     }
19361   }
19362 #ifdef SELF_CHECK
19363   assert(worknumber >= 1.0 && worknumber <= 10.0);
19364 #endif
19365 
19366   // Enlarge worknumber 1000 times.
19367   worknumber *= 1e+3;
19368   expo -= 3;
19369   // Generate a randome number between (0, worknumber).
19370   result = (double) randomnation((int) worknumber);
19371   
19372   // Scale result back into the original size.
19373   if (expo > 0) {
19374     while (expo != 0) {
19375       result *= 10.0;
19376       expo--;
19377     }
19378   } else if (expo < 0) {
19379     while (expo != 0) {
19380       result /= 10.0;
19381       expo++;
19382     }
19383   }
19384 #ifdef SELF_CHECK
19385   assert((result >= 0.0) && (result <= fabs(range)));
19386 #endif
19387 
19388   return result;
19389 }
19390 
19392 //                                                                           //
19393 // checksub4cocir()    Test a subface to find co-circular pair of subfaces.  //
19394 //                                                                           //
19395 // 'eps' is a relative tolerance for testing approximately cospherical case. //
19396 // Set it to zero if only exact test is desired.                             //
19397 //                                                                           //
19398 // An edge(not a segment) of 'testsub' is locally degenerate if the opposite //
19399 // vertex of the adjacent subface is cocircular with the vertices of testsub.//
19400 // If 'once' is TRUE, operate on the edge only if the pointer 'testsub->sh'  //
19401 // is smaller than its neighbor (for each edge is considered only once).     //
19402 //                                                                           //
19403 // Return TRUE if find an edge of testsub is locally degenerate.             //
19404 //                                                                           //
19406 
19407 bool tetgenmesh::checksub4cocir(face* testsub, REAL eps, bool once,
19408   bool enqflag)
19409 {
19410   badface *cocirsub;
19411   face subloop, neighsub;
19412   face checkseg;
19413   point pa, pb, pc, pd;
19414   REAL sign;
19415   int i;
19416   
19417   subloop = *testsub;
19418   subloop.shver = 0; // Keep the CCW orientation.
19419   // Get the abovepoint of the facet.
19420   abovepoint = facetabovepointarray[shellmark(subloop)];
19421   // Do we need to calculate the abovepoint?
19422   if (abovepoint == (point) NULL) {
19423     getfacetabovepoint(&subloop);
19424   }
19425   // Check the three edges of subloop.
19426   for (i = 0; i < 3; i++) {
19427     sspivot(subloop, checkseg);
19428     if (checkseg.sh == dummysh) {
19429       // It is not a segment, get the adjacent subface.
19430       spivot(subloop, neighsub);
19431       // assert(neighsub.sh != dummysh);
19432       if (!once || (once && (neighsub.sh > subloop.sh))) {
19433         pa = sorg(subloop);
19434         pb = sdest(subloop);
19435         pc = sapex(subloop);
19436         pd = sapex(neighsub);
19437         sign = insphere(pa, pb, pc, abovepoint, pd);
19438         if ((sign != 0.0) && (eps > 0.0)) {
19439           if (iscospheric(pa, pb, pc, abovepoint, pd, sign, eps)) sign = 0.0;
19440         }
19441         if (sign == 0.0) {
19442           // It's locally degenerate!
19443           if (enqflag && badsubfaces != (memorypool *) NULL) {
19444             // Save it.
19445             cocirsub = (badface *) badsubfaces->alloc();
19446             cocirsub->ss = subloop;
19447             cocirsub->forg = pa;
19448             cocirsub->fdest = pb;
19449             cocirsub->fapex = pc;
19450             cocirsub->foppo = pd;
19451             setshell2badface(cocirsub->ss, cocirsub);
19452           }
19453           if (b->verbose > 1) {
19454             printf("    Found set (%d, %d, %d, %d).\n", pointmark(pa),
19455                    pointmark(pb), pointmark(pc), pointmark(pd));
19456           }
19457           return true;
19458         }
19459       }
19460     }
19461     senextself(subloop);
19462   }
19463 
19464   return false;
19465 }
19466 
19468 //                                                                           //
19469 // tallcocirsubs()    Find all co-circular subfaces and save them in list.   //
19470 //                                                                           //
19472 
19473 void tetgenmesh::tallcocirsubs(REAL eps, bool enqflag)
19474 {
19475   face subloop;
19476 
19477   // Loop over all subfaces.
19478   subfaces->traversalinit();
19479   subloop.sh = shellfacetraverse(subfaces);
19480   while (subloop.sh != (shellface *) NULL) {
19481     checksub4cocir(&subloop, eps, true, enqflag);
19482     subloop.sh = shellfacetraverse(subfaces);
19483   }
19484 }
19485 
19487 //                                                                           //
19488 // tallencsegsfsubs()    Check for encroached segs from a list of subfaces.  //
19489 //                                                                           //
19491 
19492 bool tetgenmesh::tallencsegsfsubs(point testpt, list* cavsublist)
19493 {
19494   face startsub, checkseg;
19495   long oldencnum;
19496   int i, j;
19497 
19498   // Remember the current number of encroached segments.
19499   oldencnum = badsubsegs->items;
19500 
19501   // Check segments in the list of subfaces.
19502   for (i = 0; i < cavsublist->len(); i++) {
19503     startsub = * (face *)(* cavsublist)[i];
19504     // Test all three edges of startsub.
19505     for (j = 0; j < 3; j++) {
19506       sspivot(startsub, checkseg);
19507       if (checkseg.sh != dummysh) {
19508         if (!shell2badface(checkseg)) {
19509           checkseg4encroach(&checkseg, testpt, NULL, true);
19510         }
19511       }
19512       senextself(startsub);
19513     }
19514   }
19515 
19516   return (badsubsegs->items > oldencnum);
19517 }
19518 
19520 //                                                                           //
19521 // collectflipedges()    Collect edges of split subfaces for flip checking.  //
19522 //                                                                           //
19523 // 'inspoint' is a newly inserted segment point (inserted by insertsite()).  //
19524 // 'splitseg' is one of the two split subsegments. Some subfaces may be non- //
19525 // Delaunay since they're still not bonded to CDT. This routine collect all  //
19526 // such possible subfaces in 'flipqueue'.                                    //
19527 //                                                                           //
19529 
19530 void tetgenmesh::
19531 collectflipedges(point inspoint, face* splitseg, queue* flipqueue)
19532 {
19533   face startsh, spinsh, checksh;
19534   face nextseg;
19535   point pa, pb;
19536 
19537   // Let the dest of splitseg be inspoint.
19538   splitseg->shver = 0;
19539   if (sdest(*splitseg) != inspoint) {
19540     sesymself(*splitseg);
19541   }
19542 #ifdef SELF_CHECK
19543   assert(sdest(*splitseg) == inspoint);
19544 #endif
19545   pa = sorg(*splitseg);
19546   spivot(*splitseg, startsh);
19547   spinsh = startsh;
19548   do {
19549     findedge(&spinsh, pa, inspoint);
19550     senext2(spinsh, checksh);
19551     enqueueflipedge(checksh, flipqueue);
19552     spivotself(spinsh);
19553   } while (spinsh.sh != startsh.sh);
19554 
19555   // Get the next subsegment.
19556   senext(*splitseg, nextseg);
19557   spivotself(nextseg);
19558 #ifdef SELF_CHECK
19559   assert(nextseg.sh != (shellface *) NULL);
19560 #endif
19561   
19562   // Let the org of nextseg be inspoint.
19563   nextseg.shver = 0;
19564   if (sorg(nextseg) != inspoint) {
19565     sesymself(nextseg);
19566   }
19567 #ifdef SELF_CHECK
19568   assert(sorg(nextseg) == inspoint);
19569 #endif
19570   pb = sdest(nextseg);
19571   spivot(nextseg, startsh);
19572   spinsh = startsh;
19573   do {
19574     findedge(&spinsh, inspoint, pb);
19575     senext(spinsh, checksh);
19576     enqueueflipedge(checksh, flipqueue);
19577     spivotself(spinsh);
19578   } while (spinsh.sh != startsh.sh);
19579 }
19580 
19582 //                                                                           //
19583 // perturbrepairencsegs()    Repair all encroached segments.                 //
19584 //                                                                           //
19585 // All encroached segments are stored in 'badsubsegs'.  Each segment will be //
19586 // split by adding a perturbed point near its circumcenter.                  //
19587 //                                                                           //
19589 
19590 void tetgenmesh::perturbrepairencsegs(queue* flipqueue)
19591 {
19592   badface *encloop;
19593   tetrahedron encodedtet;
19594   triface splittet;
19595   face splitsub, symsplitsub;
19596   face splitseg, symsplitseg;
19597   point newpoint, sympoint;
19598   point pa, pb, pc;
19599   enum insertsiteresult success;
19600   enum locateresult loc, symloc;
19601   REAL cent[3], d1, ps, rs;
19602   int i, j;
19603 
19604   // Note that steinerleft == -1 if an unlimited number of Steiner points 
19605   //   is allowed.  Loop until 'badsubsegs' is empty.
19606   badsubsegs->traversalinit();
19607   encloop = badfacetraverse(badsubsegs);
19608   while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19609     splitseg = encloop->ss;
19610 #ifdef SELF_CHECK
19611     assert(shell2badface(splitseg) == encloop);
19612 #endif
19613     setshell2badface(splitseg, NULL);
19614     pa = sorg(splitseg);
19615     pb = sdest(splitseg);
19616     if ((pa == encloop->forg) && (pb == encloop->fdest)) {
19617       if (b->verbose > 1) {
19618         printf("  Get seg (%d, %d).\n", pointmark(pa), pointmark(pb));
19619       }
19620       // Create the newpoint.
19621       makepoint(&newpoint);
19622       // Get the circumcenter and radius of ab.
19623       for (i = 0; i < 3; i++) cent[i] = 0.5 * (pa[i] + pb[i]);
19624       d1 = 0.5 * distance(pa, pb);
19625       // Add a random perturbation to newpoint along the vector ab.
19626       ps = randgenerator(d1 * 1.0e-3);
19627       rs = ps / d1;
19628       // Set newpoint (be at the perturbed circumcenter of ab).
19629       for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19630       setpointtype(newpoint, FREESEGVERTEX);
19631       // Set splitseg into the newpoint.
19632       setpoint2sh(newpoint, sencode(splitseg));        
19633 
19634       // Is there periodic boundary condition?
19635       if (checkpbcs) {
19636         // Insert points on other segments of incident pbcgroups.
19637         i = shellmark(splitseg) - 1;
19638         for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
19639           makepoint(&sympoint);
19640           symloc = getsegpbcsympoint(newpoint, &splitseg, sympoint,
19641                                      &symsplitseg, segpglist[j]);
19642 #ifdef SELF_CHECK
19643           assert(symloc != OUTSIDE);
19644 #endif
19645           // Note: the symsplitseg and splitseg may be identical, in case
19646           //   when the the splitseg is the axis of the rotational sym.
19647           if ((symloc == ONEDGE) && (symsplitseg.sh != splitseg.sh)) {
19648             setpointtype(sympoint, FREESEGVERTEX);
19649             setpoint2sh(sympoint, sencode(symsplitseg));
19650             // Insert sympoint into DT.
19651             pc = sorg(symsplitseg);
19652             splittet.tet = dummytet;
19653             // Find a good start point to search.
19654             encodedtet = point2tet(pc);
19655             if (encodedtet != (tetrahedron) NULL) {
19656               decode(encodedtet, splittet);
19657               if (isdead(&splittet)) {
19658                 splittet.tet = dummytet; 
19659               }
19660             }
19661             // Locate sympoint in DT.  Do exact location.
19662             success = insertsite(sympoint, &splittet, false, flipqueue);
19663 #ifdef SELF_CHECK
19664             assert(success != DUPLICATEPOINT);
19665 #endif
19666             if (success == OUTSIDEPOINT) {
19667               inserthullsite(sympoint, &splittet, flipqueue);
19668             }
19669             if (steinerleft > 0) steinerleft--;
19670             // Let sympoint remember splittet.
19671             setpoint2tet(sympoint, encode(splittet));
19672             // Do flip in DT.
19673             flip(flipqueue, NULL);
19674             // Insert sympoint into F.
19675             symloc = locateseg(sympoint, &symsplitseg);
19676             if (symloc == ONEDGE) {
19677               symsplitseg.shver = 0;
19678               spivot(symsplitseg, symsplitsub);
19679               // sympoint should on the edge of symsplitsub.
19680               splitsubedge(sympoint, &symsplitsub, flipqueue);
19681             } else {
19682               // insertsite() has done the whole job.
19683 #ifdef SELF_CHECK
19684               assert(symloc == ONVERTEX);
19685               assert(checksubfaces);
19686 #endif
19687               // Some edges may need to be flipped.
19688               collectflipedges(sympoint, &symsplitseg, flipqueue);
19689             }
19690             // Do flip in facet.
19691             flipsub(flipqueue);
19692           } else { // if (symloc == ONVERTEX) {
19693             // The symmtric point already exists. It is possible when two
19694             //   pbc group are idebtical. Omit sympoint.
19695             pointdealloc(sympoint);
19696           }
19697         }
19698       }
19699 
19700       // Insert newpoint into DT.
19701       splittet.tet = dummytet;
19702       // Find a good start point to search.
19703       encodedtet = point2tet(pa);
19704       if (encodedtet != (tetrahedron) NULL) {
19705         decode(encodedtet, splittet);
19706         if (isdead(&splittet)) {
19707           splittet.tet = dummytet; 
19708         }
19709       }
19710       if (splittet.tet == dummytet) { // Try pb.
19711         encodedtet = point2tet(pb);
19712         if (encodedtet != (tetrahedron) NULL) {
19713           decode(encodedtet, splittet);
19714           if (isdead(&splittet)) {
19715             splittet.tet = dummytet;
19716           }
19717         }
19718       }
19719       // Locate the newpoint in DT.  Do exact location.
19720       success = insertsite(newpoint, &splittet, false, flipqueue);
19721 #ifdef SELF_CHECK
19722       assert(success != DUPLICATEPOINT);
19723 #endif
19724       if (success == OUTSIDEPOINT) {
19725         // A convex hull edge is mssing, and the inserting point lies
19726         //   (slightly) outside the convex hull due to the significant
19727         //   digits lost in the calculation. Enlarge the convex hull.
19728         inserthullsite(newpoint, &splittet, flipqueue);
19729       }
19730       if (steinerleft > 0) steinerleft--;
19731       // Let newpoint remember splittet.
19732       setpoint2tet(newpoint, encode(splittet));
19733       // Do flip in DT.
19734       flip(flipqueue, NULL);
19735       // Insert newpoint into F.
19736       loc = locateseg(newpoint, &splitseg);
19737       if (loc == ONEDGE) {
19738         splitseg.shver = 0;
19739         spivot(splitseg, splitsub);
19740         // newpoint should on the edge of splitsub.
19741         splitsubedge(newpoint, &splitsub, flipqueue);
19742       } else {
19743         // insertsite() has done the whole job.
19744 #ifdef SELF_CHECK
19745         assert(loc == ONVERTEX);
19746         assert(checksubfaces);
19747 #endif
19748         // Some edges may need to be flipped.
19749         collectflipedges(newpoint, &splitseg, flipqueue);
19750       }
19751       // Do flip in facet.
19752       flipsub(flipqueue);
19753     }
19754     // Remove this entry from list.
19755     badfacedealloc(badsubsegs, encloop);  
19756     // Get the next encroached segments.
19757     encloop = badfacetraverse(badsubsegs);
19758   }
19759 }
19760 
19762 //                                                                           //
19763 // perturbrepairencsubs()    Repair all encroached subfaces.                 //
19764 //                                                                           //
19765 // All encroached subfaces are stored in 'badsubfaces'. Each subface will be //
19766 // split by adding a perturbed point near its circumcenter. However, if the  //
19767 // point encroaches some segments, it will not be inserted.  Instead, the    //
19768 // encroached segments are split.                                            //
19769 //                                                                           //
19771 
19772 void tetgenmesh::perturbrepairencsubs(list* cavsublist, queue* flipqueue)
19773 {
19774   badface *encloop, *encsubseg;
19775   tetrahedron encodedtet;
19776   triface splittet;
19777   face splitsub, symsplitsub;
19778   face checkseg, symsplitseg;
19779   point newpoint, sympoint;
19780   point pa, pb, pc, pd;
19781   enum insertsiteresult success;
19782   enum locateresult loc, symloc;
19783   REAL cent[3], d1, ps, rs;
19784   bool reject;
19785   int i;
19786 
19787   // Note that steinerleft == -1 if an unlimited number of Steiner points
19788   //   is allowed.  Loop until the list 'badsubfaces' is empty.
19789   while ((badsubfaces->items > 0) && (steinerleft != 0)) {
19790     badsubfaces->traversalinit();
19791     encloop = badfacetraverse(badsubfaces);
19792     while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19793       splitsub = encloop->ss;
19794 #ifdef SELF_CHECK
19795       assert(shell2badface(splitsub) == encloop);
19796 #endif
19797       setshell2badface(splitsub, NULL);
19798       pa = sorg(splitsub);
19799       pb = sdest(splitsub);
19800       pc = sapex(splitsub);
19801       // The subface may be not the same one when it was determined to be
19802       //   encroached.  If its adjacent encroached subface was split, the
19803       //   consequent flips may change it into another subface.
19804       if ((pa == encloop->forg) && (pb == encloop->fdest) &&
19805           (pc == encloop->fapex)) {
19806         if (b->verbose > 1) {
19807           printf("  Get subface (%d, %d, %d).\n", pointmark(pa),
19808                  pointmark(pb), pointmark(pc));
19809         }
19810         // Create the newpoint.
19811         makepoint(&newpoint);
19812         // Get the circumcenter of abc.
19813         circumsphere(pa, pb, pc, NULL, cent, &d1);
19814 #ifdef SELF_CHECK
19815         assert(d1 > 0.0);
19816 #endif
19817         // Add a random perturbation to newpoint along the vector a->cent.
19818         //   This way, the perturbed point still lies in the plane of abc.
19819         ps = randgenerator(d1 * 1.0e-3);
19820         rs = ps / d1;
19821         // Set newpoint (be at the perturbed circumcenter of abc).
19822         for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19823         // Get the abovepoint of the facet.
19824         abovepoint = facetabovepointarray[shellmark(splitsub)];
19825         // Do we need to calculate the abovepoint?
19826         if (abovepoint == (point) NULL) {
19827           getfacetabovepoint(&splitsub);
19828         }
19829         loc = locatesub(newpoint, &splitsub, 1, 0.0);
19830 #ifdef SELF_CHECK
19831         assert(loc != ONVERTEX);
19832 #endif
19833         if (loc != OUTSIDE) {
19834           // Add 'splitsub' into 'cavsublist'.
19835           cavsublist->append(&splitsub);
19836           // Collect all subfaces that encroached by newpoint.
19837           collectcavsubs(newpoint, cavsublist);
19838           // Find if there are encroached segments.
19839           reject = tallencsegsfsubs(newpoint, cavsublist);
19840           // Clear cavsublist for the next use.
19841           cavsublist->clear();
19842         } else {
19843           // newpoint lies outside. splitsub contains the boundary segment.
19844           sspivot(splitsub, checkseg);
19845 #ifdef SELF_CHECK
19846           assert(checkseg.sh != dummysh);
19847 #endif
19848           // Add this segment into list for splitting.
19849           if (b->verbose > 2) {
19850             printf("    Queuing boundary segment (%d, %d).\n",
19851                    pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
19852           }
19853           encsubseg = (badface *) badsubsegs->alloc();
19854           encsubseg->ss = checkseg;
19855           encsubseg->forg = sorg(checkseg);
19856           encsubseg->fdest = sdest(checkseg);
19857           encsubseg->foppo = (point) NULL;
19858           setshell2badface(encsubseg->ss, encsubseg);
19859           // Reject newpoint.
19860           reject = true;
19861         }
19862 
19863         if (!reject) {
19864           // newpoint is going to be inserted.
19865           
19866           // Is there periodic boundary condition?
19867           if (checkpbcs) {
19868             if (shellpbcgroup(splitsub) >= 0) {
19869               // Insert a point on another facet of the pbcgroup.
19870               makepoint(&sympoint);
19871               // Note: 'abovepoint' will be changed.
19872               symloc = getsubpbcsympoint(newpoint, &splitsub, sympoint,
19873                                          &symsplitsub);
19874 #ifdef SELF_CHECK
19875               assert(symloc != ONVERTEX);
19876 #endif
19877               setpoint2pbcpt(newpoint, sympoint);
19878               setpoint2pbcpt(sympoint, newpoint);
19879               setpointtype(sympoint, FREESUBVERTEX);
19880               // setpoint2sh(sympoint, sencode(symsplitsub));
19881               // Insert sympoint into DT.
19882               pd = sorg(symsplitsub);
19883               splittet.tet = dummytet;
19884               // Find a good start point to search.
19885               encodedtet = point2tet(pd);
19886               if (encodedtet != (tetrahedron) NULL) {
19887                 decode(encodedtet, splittet);
19888                 if (isdead(&splittet)) {
19889                   splittet.tet = dummytet; 
19890                 }
19891               }
19892               // Locate sympoint in DT.  Do exact location.
19893               success = insertsite(sympoint, &splittet, false, flipqueue);
19894 #ifdef SELF_CHECK
19895               assert(success != DUPLICATEPOINT);
19896 #endif
19897               if (success == OUTSIDEPOINT) {
19898                 inserthullsite(sympoint, &splittet, flipqueue);
19899               }
19900               if (steinerleft > 0) steinerleft--;
19901               // Let sympoint remember splittet.
19902               setpoint2tet(sympoint, encode(splittet));
19903               // Do flip in DT.
19904               flip(flipqueue, NULL);
19905               // Insert sympoint into F.
19906               // getabovepoint(&symsplitsub);
19907               // symloc = locatesub(sympoint, &symsplitsub, 1, 0.0);
19908               if (symloc == ONFACE) {
19909                 splitsubface(sympoint, &symsplitsub, flipqueue);
19910               } else if (symloc == ONEDGE) {
19911                 splitsubedge(sympoint, &symsplitsub, flipqueue);
19912               } else {
19913                 // 'insertsite()' has done the whole job.
19914 #ifdef SELF_CHECK
19915                 assert(symloc == ONVERTEX);
19916                 assert(checksubfaces);
19917 #endif
19918                 // Split subfaces have been flipped.
19919                 flipqueue->clear();
19920               }
19921               // Do flip in facet.
19922               flipsub(flipqueue);
19923             }
19924           }
19925 
19926           // Insert newpoint into DT.
19927           splittet.tet = dummytet;
19928           // Find a good start point to search.
19929           encodedtet = point2tet(pa);
19930           if (encodedtet != (tetrahedron) NULL) {
19931             decode(encodedtet, splittet);
19932             if (isdead(&splittet)) {
19933               splittet.tet = dummytet; 
19934             }
19935           }
19936           if (splittet.tet == dummytet) { // Try pb.
19937             encodedtet = point2tet(pb);
19938             if (encodedtet != (tetrahedron) NULL) {
19939               decode(encodedtet, splittet);
19940               if (isdead(&splittet)) {
19941                 splittet.tet = dummytet;
19942               }
19943             }
19944           }
19945           // Locate the newpoint in DT.  Do exact location.
19946           success = insertsite(newpoint, &splittet, false, flipqueue);
19947 #ifdef SELF_CHECK
19948           assert(success != DUPLICATEPOINT);
19949 #endif
19950           if (success == OUTSIDEPOINT) {
19951             inserthullsite(newpoint, &splittet, flipqueue);
19952           }
19953           if (steinerleft > 0) steinerleft--;
19954           // Let newpoint remember splittet.
19955           setpoint2tet(newpoint, encode(splittet));
19956           // Do flip in DT.
19957           flip(flipqueue, NULL);
19958           // Insert newpoint into F.
19959           // if (checkpbcs) {
19960             // 'abovepoint' has been changed.
19961             // getabovepoint(&splitsub);
19962             // loc = locatesub(newpoint, &splitsub, 1, 0.0);
19963           // }
19964           if (loc == ONFACE) {
19965             // Insert the newpoint in facet.
19966             splitsubface(newpoint, &splitsub, flipqueue);
19967           } else if (loc == ONEDGE) {
19968             // Insert the newpoint in facet.
19969             splitsubedge(newpoint, &splitsub, flipqueue);
19970           } else {
19971             // 'insertsite()' has done the whole job.
19972 #ifdef SELF_CHECK
19973             assert(loc == ONVERTEX);
19974             assert(checksubfaces);
19975 #endif
19976             // Split subfaces have been flipped.
19977             flipqueue->clear();
19978           }
19979           // Set the type of the newpoint.
19980           setpointtype(newpoint, FREESUBVERTEX);
19981           // Set splitsub into the newpoint.
19982           // setpoint2sh(newpoint, sencode(splitsub));
19983           // Do flip in the facet.
19984           flipsub(flipqueue);
19985 
19986           // Remove this entry from list.
19987           badfacedealloc(badsubfaces, encloop);
19988         } else {
19989           // newpoint is rejected. Remove it from points.
19990           pointdealloc(newpoint);
19991           // Repair all encroached segments.
19992           perturbrepairencsegs(flipqueue);
19993           // Do not remove 'encloop'. Later it will be tested again.
19994           setshell2badface(encloop->ss, encloop);
19995         }
19996       } else {
19997         // This subface has been changed. Remove this entry from list.
19998         badfacedealloc(badsubfaces, encloop);
19999         // It may be co-circular with its neighbors.
20000         // checksub4cocir(&splitsub, eps, false, true); 
20001       }
20002       // Get the next encroached subfaces.
20003       encloop = badfacetraverse(badsubfaces);
20004     }
20005   }
20006 }
20007 
20009 //                                                                           //
20010 // incrperturbvertices()    Remove the local degeneracies in DT.             //
20011 //                                                                           //
20012 // A local degeneracy of a DT D is a set of 5 or more vertices which share a //
20013 // common sphere S and no other vertex of D in S.  D is not unique if it has //
20014 // local degeneracies. This routine removes the local degeneracies from D by //
20015 // inserting break points (as described in reference [2]).                   //
20016 //                                                                           //
20017 // 'eps' is a user-provided error tolerance. It is used to detect whether or //
20018 // not five points are approximate cospherical (evaluated in iscospheric()). //
20019 // Set it to 0.0 to disable it, i.e., only test pure degenerate point set.   //
20020 //                                                                           //
20022 
20023 void tetgenmesh::incrperturbvertices(REAL eps)
20024 {
20025   queue *flipqueue;
20026   list *cavsublist;
20027   long vertcount;
20028 
20029   if (!b->quiet) {
20030     printf("Perturbing vertices.\n");
20031   }
20032 
20033   vertcount = points->items;
20034   // Create a map from points to tets for fastening search.
20035   // makepoint2tetmap();  // This has been done in meshsurface().
20036 
20037   // Initialize working queues, lists.
20038   flipqueue = new queue(sizeof(badface));
20039   cavsublist = new list(sizeof(face), NULL, 256);
20040   // Initialize the pool of encroached subfaces and subsegments.
20041   badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20042   badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20043   // Find all pairs of co-circular subfaces.
20044   tallcocirsubs(eps, true);
20045   if (b->verbose && badsubfaces->items > 0) {
20046     printf("  Removing degenerate subfaces.\n");
20047   }
20048   perturbrepairencsubs(cavsublist, flipqueue);
20049 
20050   if (b->verbose > 0) {
20051     printf("  %ld break points.\n", points->items - vertcount);
20052   }
20053   
20054   delete cavsublist;
20055   delete flipqueue;
20056   delete badsubfaces;
20057   delete badsubsegs; 
20058   badsubsegs = (memorypool *) NULL;
20059   badsubfaces = (memorypool *) NULL;
20060 }
20061 
20062 //
20063 // End of vertex perturbation routines
20064 //
20065 
20066 //
20067 // Begin of segment recovery routines
20068 //
20069 
20071 //                                                                           //
20072 // markacutevertices()    Mark acute vertices.                               //
20073 //                                                                           //
20074 // A vertex v is called acute if there are two segments sharing at v forming //
20075 // an acute angle (i.e. smaller than 90 degree).                             //
20076 //                                                                           //
20077 // This routine finds all acute vertices in the PLC and marks them as point- //
20078 // type ACUTEVERTEX. The other vertices of segments which are non-acute will //
20079 // be marked as NACUTEVERTEX.  Vertices which are not endpoints of segments  //
20080 // (such as DUPLICATEDVERTEX, UNUSEDVERTEX, etc) are not infected.           //
20081 //                                                                           //
20082 // NOTE: This routine should be called before Steiner points are introduced. //
20083 // That is, no point has type like FREESEGVERTEX, etc.                       //
20084 //                                                                           //
20086 
20087 void tetgenmesh::markacutevertices(REAL acuteangle)
20088 {
20089   shellface **segsperverlist;
20090   face segloop, nextseg;
20091   point pointloop, edest, eapex;
20092   REAL cosbound, anglearc;
20093   REAL v1[3], v2[3], L, D;
20094   bool isacute;
20095   int *idx2seglist;
20096   int acutecount;
20097   int idx, i, j, k;
20098 
20099   if (b->verbose > 0) {
20100     printf("  Marking acute vertices.\n");
20101   }
20102 
20103   anglearc = acuteangle * PI / 180.0;
20104   cosbound = cos(anglearc);
20105   acutecount = 0;
20106   // Constructing a map from vertex to segments.
20107   makesegmentmap(idx2seglist, segsperverlist);
20108 
20109   // Loop over the set of vertices.
20110   points->traversalinit();
20111   pointloop = pointtraverse();
20112   while (pointloop != (point) NULL) {
20113     idx = pointmark(pointloop) - in->firstnumber;
20114     // Only do test if p is an endpoint of some segments.
20115     if (idx2seglist[idx + 1] > idx2seglist[idx]) {
20116       // Init p to be non-acute.
20117       setpointtype(pointloop, NACUTEVERTEX);
20118       isacute = false;
20119       // Loop through all segments sharing at p.
20120       for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isacute; i++) {
20121         segloop.sh = segsperverlist[i];
20122         // segloop.shver = 0;
20123         if (sorg(segloop) != pointloop) sesymself(segloop);
20124         edest = sdest(segloop);
20125         for (j = i + 1; j < idx2seglist[idx + 1] && !isacute; j++) {
20126           nextseg.sh = segsperverlist[j];
20127           // nextseg.shver = 0;
20128           if (sorg(nextseg) != pointloop) sesymself(nextseg);
20129           eapex = sdest(nextseg);
20130           // Check the angle formed by segs (p, edest) and (p, eapex).
20131           for (k = 0; k < 3; k++) {
20132             v1[k] = edest[k] - pointloop[k];
20133             v2[k] = eapex[k] - pointloop[k];
20134           }
20135           L = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
20136           for (k = 0; k < 3; k++) v1[k] /= L;
20137           L = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
20138           for (k = 0; k < 3; k++) v2[k] /= L;
20139           D = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
20140           // Is D acute?
20141           isacute = (D >= cosbound);
20142         }
20143       }
20144       if (isacute) {
20145         // Mark p to be acute.
20146         setpointtype(pointloop, ACUTEVERTEX);
20147         acutecount++;
20148       }
20149     }
20150     pointloop = pointtraverse();
20151   }
20152 
20153   delete [] idx2seglist;
20154   delete [] segsperverlist;
20155 
20156   if ((b->verbose > 0) && (acutecount > 0)) {
20157     printf("  %d acute vertices.\n", acutecount);
20158   }
20159 }
20160 
20162 //                                                                           //
20163 // finddirection()    Find the first tetrahedron on the path from one point  //
20164 //                    to another.                                            //
20165 //                                                                           //
20166 // Find the tetrahedron that intersects a line segment L (from the origin of //
20167 // 'searchtet' to the point 'tend'), and returns the result in 'searchtet'.  //
20168 // The origin of 'searchtet' does not change, even though the tetrahedron    //
20169 // returned may differ from the one passed in.  This routine is used to find //
20170 // the direction to move in to get from one point to another.                //
20171 //                                                                           //
20172 // The return value notes the location of the line segment L with respect to //
20173 // 'searchtet':                                                              //
20174 //   - Returns RIGHTCOLLINEAR indicates L is collinear with the line segment //
20175 //     from the origin to the destination of 'searchtet'.                    //
20176 //   - Returns LEFTCOLLINEAR indicates L is collinear with the line segment  //
20177 //     from the origin to the apex of 'searchtet'.                           //
20178 //   - Returns TOPCOLLINEAR indicates L is collinear with the line segment   //
20179 //     from the origin to the opposite of 'searchtet'.                       //
20180 //   - Returns ACROSSEDGE indicates L intersects with the line segment from  //
20181 //     the destination to the apex of 'searchtet'.                           //
20182 //   - Returns ACROSSFACE indicates L intersects with the face opposite to   //
20183 //     the origin of 'searchtet'.                                            //
20184 //   - Returns BELOWHULL indicates L crosses outside the mesh domain. This   //
20185 //     can only happen when the domain is non-convex.                        //
20186 //                                                                           //
20187 // NOTE: This routine only works correctly when the mesh is exactly Delaunay.//
20188 //                                                                           //
20189 // If 'maxtetnumber' > 0, stop the searching process if the number of passed //
20190 // tets is larger than it. Return BELOWHULL.                                 //
20191 //                                                                           //
20193 
20194 enum tetgenmesh::finddirectionresult tetgenmesh::
20195 finddirection(triface *searchtet, point tend, long maxtetnumber)
20196 {
20197   triface neightet;
20198   point tstart, tdest, tapex, toppo;
20199   REAL ori1, ori2, ori3;
20200   long tetnumber;
20201 
20202   tstart = org(*searchtet);
20203 #ifdef SELF_CHECK
20204   assert(tstart != tend);
20205 #endif
20206   adjustedgering(*searchtet, CCW);
20207   if (tstart != org(*searchtet)) {
20208     enextself(*searchtet); // For keeping the same origin.
20209   }
20210   tdest = dest(*searchtet);
20211   if (tdest == tend) {
20212     return RIGHTCOLLINEAR;
20213   }
20214   tapex = apex(*searchtet); 
20215   if (tapex == tend) {
20216     return LEFTCOLLINEAR;
20217   } 
20218 
20219   ori1 = orient3d(tstart, tdest, tapex, tend);
20220   if (ori1 > 0.0) {
20221     // 'tend' is below the face, get the neighbor of this side.
20222     sym(*searchtet, neightet);
20223     if (neightet.tet != dummytet) {
20224       findorg(&neightet, tstart); 
20225       adjustedgering(neightet, CCW);
20226       if (org(neightet) != tstart) {
20227         enextself(neightet); // keep the same origin.
20228       }
20229       // Set the changed configuratiuon.
20230       *searchtet = neightet; 
20231       ori1 = -1.0; 
20232       tdest = dest(*searchtet);
20233       tapex = apex(*searchtet);
20234     } else {
20235       // A hull face. Only possible for a nonconvex mesh.
20236 #ifdef SELF_CHECK
20237       assert(nonconvex);
20238 #endif
20239       return BELOWHULL; 
20240     }
20241   }
20242 
20243   // Repeatedly change the 'searchtet', remain 'tstart' be its origin, until
20244   //   find a tetrahedron contains 'tend' or is crossed by the line segment
20245   //   from 'tstart' to 'tend'.
20246   tetnumber = 0l;
20247   while ((maxtetnumber > 0) && (tetnumber <= maxtetnumber)) {
20248     tetnumber++;
20249     toppo = oppo(*searchtet);
20250     if (toppo == tend) {
20251       return TOPCOLLINEAR;
20252     }
20253     ori2 = orient3d(tstart, toppo, tdest, tend);
20254     if (ori2 > 0.0) {
20255       // 'tend' is below the face, get the neighbor at this side.
20256       fnext(*searchtet, neightet);
20257       symself(neightet);
20258       if (neightet.tet != dummytet) {
20259         findorg(&neightet, tstart); 
20260         adjustedgering(neightet, CCW);
20261         if (org(neightet) != tstart) {
20262           enextself(neightet); // keep the same origin.
20263         }
20264         // Set the changed configuration.
20265         *searchtet = neightet; 
20266         ori1 = -1.0; 
20267         tdest = dest(*searchtet);
20268         tapex = apex(*searchtet);
20269         // Continue the search from the changed 'searchtet'.
20270         continue;
20271       } else {
20272         // A hull face. Only possible for a nonconvex mesh.
20273 #ifdef SELF_CHECK
20274         assert(nonconvex);
20275 #endif
20276         return BELOWHULL; 
20277       }
20278     }
20279     ori3 = orient3d(tapex, toppo, tstart, tend);
20280     if (ori3 > 0.0) {
20281       // 'tend' is below the face, get the neighbor at this side.
20282       enext2fnext(*searchtet, neightet);
20283       symself(neightet);
20284       if (neightet.tet != dummytet) {
20285         findorg(&neightet, tstart); 
20286         adjustedgering(neightet, CCW);
20287         if (org(neightet) != tstart) {
20288           enextself(neightet); // keep the same origin.
20289         }
20290         // Set the changed configuration.
20291         *searchtet = neightet; 
20292         ori1 = -1.0; 
20293         tdest = dest(*searchtet);
20294         tapex = apex(*searchtet);
20295         // Continue the search from the changed 'searchtet'.
20296         continue;
20297       } else {
20298         // A hull face. Only possible for a nonconvex mesh.
20299 #ifdef SELF_CHECK
20300         assert(nonconvex);
20301 #endif
20302         return BELOWHULL; 
20303       }
20304     }
20305     // Now 'ori1', 'ori2' and 'ori3' are possible be 0.0 or all < 0.0;
20306     if (ori1 < 0.0) {
20307       // Possible cases are: ACROSSFACE, ACROSSEDGE, TOPCOLLINEAR.
20308       if (ori2 < 0.0) {
20309         if (ori3 < 0.0) {
20310           return ACROSSFACE;
20311         } else { // ori3 == 0.0;
20312           // Cross edge (apex, oppo)
20313           enext2fnextself(*searchtet);
20314           esymself(*searchtet); // org(*searchtet) == tstart;
20315           return ACROSSEDGE;
20316         }
20317       } else { // ori2 == 0.0; 
20318         if (ori3 < 0.0) {
20319           // Cross edge (dest, oppo)
20320           fnextself(*searchtet);
20321           esymself(*searchtet);
20322           enextself(*searchtet); // org(*searchtet) == tstart;
20323           return ACROSSEDGE;
20324         } else { // ori3 == 0.0;
20325           // Collinear with edge (org, oppo)
20326           return TOPCOLLINEAR;
20327         }
20328       }
20329     } else { // ori1 == 0.0;
20330       // Possible cases are: RIGHTCOLLINEAR, LEFTCOLLINEAR, ACROSSEDGE.
20331       if (ori2 < 0.0) {
20332         if (ori3 < 0.0) {
20333           // Cross edge (tdest, tapex)
20334           return ACROSSEDGE;
20335         } else { // ori3 == 0.0
20336           // Collinear with edge (torg, tapex)
20337           return LEFTCOLLINEAR;
20338         }
20339       } else { // ori2 == 0.0;
20340 #ifdef SELF_CHECK
20341         assert(ori3 != 0.0);
20342 #endif
20343         // Collinear with edge (torg, tdest)
20344         return RIGHTCOLLINEAR;
20345       }
20346     }
20347   }
20348   // Loop breakout. It may happen when the mesh is non-Delaunay.
20349   return BELOWHULL;
20350 }
20351 
20353 //                                                                           //
20354 // getsearchtet()    Find a tetrahedron whose origin is either 'p1' or 'p2'. //
20355 //                                                                           //
20356 // On return, the origin of 'searchtet' is either 'p1' or 'p2',  and 'tend'  //
20357 // returns the other point.  'searchtet' serves as the starting tetrahedron  //
20358 // for searching of the line segment from 'p1' to 'p2' or vice versa.        //
20359 //                                                                           //
20361 
20362 void tetgenmesh::getsearchtet(point p1, point p2, triface* searchtet,
20363   point* tend)
20364 {
20365   tetrahedron encodedtet1, encodedtet2;
20366 
20367   // Is there a valid handle provided by the user?
20368   if ((searchtet->tet != (tetrahedron *) NULL) && !isdead(searchtet)) {
20369     // Find which endpoint the handle holds.
20370     if (findorg(searchtet, p1)) {
20371       *tend = p2;
20372       return;
20373     } else {
20374       if (findorg(searchtet, p2)) {
20375         *tend = p1;
20376         return;
20377       }
20378     }
20379   }
20380   // If not, search the tet handle stored in 'p1' or 'p2'.
20381   *tend = (point) NULL;
20382   encodedtet1 = point2tet(p1);
20383   encodedtet2 = point2tet(p2);
20384   if (encodedtet1 != (tetrahedron) NULL) {
20385     decode(encodedtet1, *searchtet);
20386     // Be careful, here 'searchtet' may be dead.
20387     if (findorg(searchtet, p1)) {
20388       *tend = p2;
20389     }
20390   } else if (encodedtet2 != (tetrahedron) NULL) {
20391     decode(encodedtet2, *searchtet);
20392     // Be careful, here 'searchtet' may be dead.
20393     if (findorg(searchtet, p2)) {
20394       *tend = p1;
20395     }
20396   }
20397   // If still not, perform a full point location.  The starting tet is
20398   //   chosen as follows: Use the handle stored in 'p1' or 'p2' if it is
20399   //   alive; otherwise, start from a tet on the convex hull.
20400   if (*tend == (point) NULL) {
20401     if (encodedtet1 != (tetrahedron) NULL) {
20402       decode(encodedtet1, *searchtet);
20403       // Be careful, here 'searchtet' may be dead.
20404     }
20405     if (isdead(searchtet)) {
20406       if (encodedtet2 != (tetrahedron) NULL) {
20407         decode(encodedtet2, *searchtet);
20408         // Be careful, here 'searchtet' may be dead.
20409       }
20410       if (isdead(searchtet)) {
20411         searchtet->tet = dummytet;
20412         searchtet->loc = 0;
20413         symself(*searchtet);
20414       }
20415 #ifdef SELF_CHECK
20416       assert(!isdead(searchtet));
20417 #endif
20418     }
20419     if (locate(p1, searchtet) != ONVERTEX) {
20420       printf("Internal error in getsearchtet():  Failed to locate point\n");
20421       internalerror();
20422     }
20423     // Remember this handle in 'p1' to enhance the search speed.
20424     setpoint2tet(p1, encode(*searchtet));
20425     *tend = p2;
20426   }
20427 }
20428 
20430 //                                                                           //
20431 // isedgeencroached()    Check whether or not a subsegment is encroached.    //
20432 //                                                                           //
20433 // A segment with endpoints 'p1' and 'p2' is encroached by the point 'testpt'//
20434 // if it lies in the diametral sphere of this segment.  The degenerate case  //
20435 // that 'testpt' lies on the sphere is treated as encroached if 'degflag' is //
20436 // set to be TRUE.                                                           //
20437 //                                                                           //
20439 
20440 bool tetgenmesh::isedgeencroached(point p1, point p2, point testpt,
20441   bool degflag)
20442 {
20443   REAL dotproduct;
20444 
20445   // Check if the segment is facing an angle larger than 90 degree?
20446   dotproduct = (p1[0] - testpt[0]) * (p2[0] - testpt[0])
20447              + (p1[1] - testpt[1]) * (p2[1] - testpt[1])
20448              + (p1[2] - testpt[2]) * (p2[2] - testpt[2]);
20449   if (dotproduct < 0) {
20450     return true;
20451   } else if (dotproduct == 0 && degflag) {
20452     return true;
20453   } else {
20454     return false;
20455   }
20456 }
20457 
20459 //                                                                           //
20460 // scoutrefpoint()    Search the reference point of a missing segment.       //
20461 //                                                                           //
20462 // A segment S is missing in current Delaunay tetrahedralization DT and will //
20463 // be split by inserting a point V in it.  The two end points of S are the   //
20464 // origin of 'searchtet' and 'tend'. And we know that S is crossing the face //
20465 // of 'searchtet' opposite to its origin (may be intersecting with the edge  //
20466 // from the destination to the apex of the 'searchtet').  The search of P is //
20467 // completed by walking through all faces of DT across by S.                 //
20468 //                                                                           //
20469 // Warning:  This routine is correct when the tetrahedralization is Delaunay //
20470 // and convex. Otherwise, the search loop may not terminate.                 //
20471 //                                                                           //
20473 
20474 tetgenmesh::point tetgenmesh::scoutrefpoint(triface* searchtet, point tend)
20475 {
20476   triface checkface;
20477   point tstart, testpt, refpoint;
20478   REAL cent[3], radius, largest;
20479   REAL ahead;
20480   bool ncollinear;
20481   int sides;
20482 
20483   if (b->verbose > 2) {
20484     printf("  Scout the reference point of segment (%d, %d).\n",
20485            pointmark(org(*searchtet)), pointmark(tend));
20486   }
20487 
20488   tstart = org(*searchtet);
20489   refpoint = (point) NULL;
20490   largest = 0; // avoid compile warning.
20491   
20492   // Check the three vertices of the crossing face.
20493   testpt = apex(*searchtet);
20494   if (isedgeencroached(tstart, tend, testpt, true)) {
20495     ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20496 #ifdef SELF_CHECK
20497     assert(ncollinear);
20498 #endif
20499     refpoint = testpt;
20500     largest = radius;
20501   }
20502   testpt = dest(*searchtet);
20503   if (isedgeencroached(tstart, tend, testpt, true)) {
20504     ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20505 #ifdef SELF_CHECK
20506     assert(ncollinear);
20507 #endif
20508     if (refpoint == (point) NULL) {
20509       refpoint = testpt;
20510       largest = radius;
20511     } else {
20512       if (radius > largest) {
20513         refpoint = testpt;
20514         largest = radius;
20515       }
20516     }
20517   }
20518   testpt = oppo(*searchtet);
20519   if (isedgeencroached(tstart, tend, testpt, true)) {
20520     ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20521 #ifdef SELF_CHECK
20522     assert(ncollinear);
20523 #endif
20524     if (refpoint == (point) NULL) {
20525       refpoint = testpt;
20526       largest = radius;
20527     } else {
20528       if (radius > largest) {
20529         refpoint = testpt;
20530         largest = radius;
20531       }
20532     }
20533   }
20534   // Check the opposite vertex of the neighboring tet in case the segment
20535   //   crosses the edge (leftpoint, rightpoint) of the crossing face.
20536   sym(*searchtet, checkface);
20537   if (checkface.tet != dummytet) {
20538     testpt = oppo(checkface);
20539     if (isedgeencroached(tstart, tend, testpt, true)) {
20540       ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20541 #ifdef SELF_CHECK
20542       assert(ncollinear);
20543 #endif
20544       if (refpoint == (point) NULL) {
20545         refpoint = testpt;
20546         largest = radius;
20547       } else {
20548         if (radius > largest) {
20549           refpoint = testpt;
20550           largest = radius;
20551         }
20552       }
20553     }
20554   }
20555 
20556   // Walk through all crossing faces.
20557   enextfnext(*searchtet, checkface);
20558   sym(checkface, *searchtet);
20559   while (true) {
20560     // Check if we are reaching the boundary of the triangulation.
20561 #ifdef SELF_CHECK
20562     assert(searchtet->tet != dummytet);
20563 #endif
20564     // Search for an adjoining tetrahedron we can walk through.
20565     searchtet->ver = 0;
20566     // 'testpt' is the shared vertex for the following orientation tests.
20567     testpt = oppo(*searchtet);
20568     if (testpt == tend) {
20569       // The searching is finished.
20570       break; 
20571     } else {
20572       // 'testpt' may encroach the segment.
20573       if ((testpt != tstart) && (testpt != refpoint)) {
20574         if (isedgeencroached(tstart, tend, testpt, true)) {
20575           ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20576           if (!ncollinear) {
20577             // 'testpt' is collinear with the segment. It may happen when a
20578             //   set of collinear and continuous segments is defined by two
20579             //   extreme endpoints.  In this case, we should choose 'testpt'
20580             //   as the splitting point immediately.  No new point should be
20581             //   created.
20582             refpoint = testpt;
20583             break;
20584           }
20585           if (refpoint == (point) NULL) {
20586             refpoint = testpt;
20587             largest = radius;
20588           } else {
20589             if (radius > largest) {
20590               refpoint = testpt;
20591               largest = radius;
20592             }
20593           }
20594         }
20595       }
20596     }
20597     // Check three side-faces of 'searchtet' to find the one through
20598     //   which we can walk next.
20599     for (sides = 0; sides < 3; sides++) {
20600       fnext(*searchtet, checkface);
20601       ahead = orient3d(org(checkface), dest(checkface), testpt, tend);
20602       if (ahead < 0.0) {
20603         // We can walk through this face and continue the searching. 
20604         sym(checkface, *searchtet);
20605         break;
20606       }
20607       enextself(*searchtet);
20608     }
20609 #ifdef SELF_CHECK
20610     assert (sides < 3);
20611 #endif
20612   }
20613 
20614 #ifdef SELF_CHECK
20615   assert(refpoint != (point) NULL);
20616 #endif
20617   return refpoint;
20618 }
20619 
20621 //                                                                           //
20622 // getsegmentorigin()    Return the origin of the (unsplit) segment.         //
20623 //                                                                           //
20624 // After a segment (or a subsegment) is split. Two resulting subsegments are //
20625 // connecting each other through the pointers saved in their data fields.    //
20626 // With these pointers, the whole (unsplit) segment can be found. 'splitseg' //
20627 // may be a split subsegment.  Returns the origin of the unsplit segment.    //
20628 //                                                                           //
20630 
20631 tetgenmesh::point tetgenmesh::getsegmentorigin(face* splitseg)
20632 {
20633   face workseg;
20634   point farorg;
20635 
20636   farorg = sorg(*splitseg);
20637   if ((pointtype(farorg) != ACUTEVERTEX) &&
20638       (pointtype(farorg) != NACUTEVERTEX)) {
20639     workseg = *splitseg;
20640     do {
20641       senext2self(workseg);
20642       spivotself(workseg);
20643       if (workseg.sh != dummysh) {
20644         workseg.shver = 0;  // It's a subsegment.
20645         if (sdest(workseg) != farorg) {
20646           sesymself(workseg);
20647 #ifdef SELF_CHECK
20648           assert(sdest(workseg) == farorg);
20649 #endif
20650         }
20651         farorg = sorg(workseg);
20652         if ((pointtype(farorg) == ACUTEVERTEX) ||
20653             (pointtype(farorg) == NACUTEVERTEX)) break;
20654       }
20655     } while (workseg.sh != dummysh);
20656   }
20657 #ifdef SELF_CHECK
20658   assert((pointtype(farorg) == ACUTEVERTEX) ||
20659          (pointtype(farorg) == NACUTEVERTEX));
20660 #endif
20661   return farorg;
20662 }
20663 
20665 //                                                                           //
20666 // getsplitpoint()    Get a point for splitting a segment.                   //
20667 //                                                                           //
20668 // 'splitseg' is the segment will be split. 'refpoint' is a reference point  //
20669 // for splitting this segment. Moreover, it should not collinear with the    //
20670 // splitting segment. (The collinear case will be detected by iscollinear()  //
20671 // before entering this routine.)  The calculation of the splitting point is //
20672 // governed by three rules introduced in my paper.                           //
20673 //                                                                           //
20674 // After the position is calculated, a new point is created at this location.//
20675 // The new point has one of the two pointtypes: FREESEGVERTEX indicating it  //
20676 // is an inserting vertex on segment, and NACUTEVERTEX indicating it is an   //
20677 // endpoint of a segment which original has type-3 now becomes type-2.       //
20678 //                                                                           //
20680 
20681 tetgenmesh::point tetgenmesh::getsplitpoint(face* splitseg, point refpoint)
20682 {
20683   point splitpoint;
20684   point farorg, fardest;
20685   point ei, ej, ek, c;
20686   REAL v[3], r, split;
20687   REAL d1, d2, ps, rs;
20688   bool acuteorg, acutedest;
20689   int stype, rule;
20690   int i;   
20691 
20692   // First determine the type of the segment (type-1, type-2, or type-3).
20693   farorg = getsegmentorigin(splitseg);
20694   acuteorg = (pointtype(farorg) == ACUTEVERTEX);
20695   sesymself(*splitseg);
20696   fardest = getsegmentorigin(splitseg);
20697   acutedest = (pointtype(fardest) == ACUTEVERTEX);
20698   sesymself(*splitseg);
20699 
20700   ek = (point) NULL; // avoid a compilation warning.
20701 
20702   if (acuteorg) {
20703     if (acutedest) {
20704       stype = 3;
20705     } else {
20706       stype = 2;
20707       ek = farorg;
20708     }
20709   } else {
20710     if (acutedest) {
20711       stype = 2;
20712       // Adjust splitseg, so that its origin is acute.
20713       sesymself(*splitseg);
20714       ek = fardest;
20715     } else {
20716       stype = 1;
20717     }
20718   }
20719   ei = sorg(*splitseg);
20720   ej = sdest(*splitseg);
20721 
20722   if (b->verbose > 1) {
20723     printf("  Splitting segment (%d, %d) type-%d with refpoint %d.\n",
20724            pointmark(ei), pointmark(ej), stype, pointmark(refpoint));
20725   }
20726 
20727   if (stype == 1 || stype == 3) {
20728     // Use rule-1.
20729     REAL eij, eip, ejp;
20730     eij = distance(ei, ej);
20731     eip = distance(ei, refpoint);
20732     ejp = distance(ej, refpoint);
20733     if ((eip < ejp) && (eip < 0.5 * eij)) {
20734       c = ei;
20735       r = eip;
20736     } else if ((eip > ejp) && (ejp < 0.5 * eij)) {
20737       c = ej;
20738       ej = ei;
20739       r = ejp;
20740     } else {
20741       c = ei;
20742       r = 0.5 * eij;
20743     }
20744     split = r / eij;
20745     for (i = 0; i < 3; i++) {
20746       v[i] = c[i] + split * (ej[i] - c[i]);
20747     }
20748     rule = 1;
20749   } else {
20750     // Use rule-2 or rule-3.
20751     REAL eki, ekj, ekp, evj, evp, eiv;
20752     c = ek;
20753     eki = distance(ek, ei);  // eki may equal zero.
20754     ekj = distance(ek, ej);
20755     ekp = distance(ek, refpoint);
20756     // Calculate v (the going to split position between ei, ej).
20757     r = ekp;
20758     // Check the validity of the position.
20759     if (!(eki < r && r < ekj)) {
20760       printf("Error:  Invalid PLC.\n");
20761       printf("  Hint:  Use -d switch to check it.\n");
20762       terminatetetgen(1);
20763     }
20764     split = r / ekj;
20765     for (i = 0; i < 3; i++) {
20766       v[i] = c[i] + split * (ej[i] - c[i]);
20767     }
20768     rule = 2;
20769     evj = ekj - r; // distance(v, ej);
20770     evp = distance(v, refpoint);
20771     if (evj < evp) {
20772       // v is rejected, use rule-3.
20773       eiv = distance(ei, v);
20774       if (evp <= 0.5 * eiv) {
20775         r = eki + eiv - evp;
20776       } else {
20777         r = eki + 0.5 * eiv;
20778       }
20779 #ifdef SELF_CHECK
20780       assert(eki < r && r < ekj);
20781 #endif
20782       split = r / ekj;
20783       for (i = 0; i < 3; i++) {
20784         v[i] = c[i] + split * (ej[i] - c[i]);
20785       }
20786       if (b->verbose > 1) {
20787         printf("    Using rule-3.\n");
20788       }
20789       rule = 3;
20790     }
20791   }
20792 
20793   // Accumulate the corresponding counters.
20794   if (rule == 1) r1count++;
20795   else if (rule == 2) r2count++;
20796   else if (rule == 3) r3count++;
20797 
20798   if (b->verbose > 1) {
20799     if (stype == 2) {
20800       printf("    Split = %.12g.\n", distance(ei, v) / distance(ei, ej));
20801     } else {
20802       printf("    Split = %.12g.\n", distance(c, v) / distance(c, ej));
20803     }
20804   }
20805 
20806   // Create the newpoint.
20807   makepoint(&splitpoint);
20808   // Add a random perturbation on splitpoint.
20809   d1 = distance(c, v);
20810   d2 = distance(refpoint, v);
20811   if (stype == 1 || stype == 3) {
20812     ps = randgenerator(d1 * 1.0e-3);
20813   } else {
20814     // For type-2 segment, add a smaller perturbation.
20815     // ps = randgenerator(d1 * 1.0e-5);
20816     // REAL d2 = distance(refpoint, v);
20817     ps = randgenerator(d2 * 1.0e-5);
20818   }
20819   rs = ps / d1;
20820   // Perturb splitpoint away from c.
20821   for (i = 0; i < 3; i++) {
20822     splitpoint[i] = c[i] + (1.0 + rs) * (v[i] - c[i]);
20823   }
20824   // for (i = 0; i < in->numberofpointattributes; i++) {
20825   //   splitpoint[i + 3] = c[i + 3] + (split + rs) * (ej[i + 3] - c[i + 3]);
20826   // }
20827   if (stype == 3) {
20828     // Change a type-3 segment into two type-2 segments. 
20829     setpointtype(splitpoint, NACUTEVERTEX);
20830   } else {
20831     // Set it's type be FREESEGVERTEX.
20832     setpointtype(splitpoint, FREESEGVERTEX);
20833   }
20834   setpoint2sh(splitpoint, sencode(*splitseg));
20835 
20836   return splitpoint;
20837 }
20838 
20840 //                                                                           //
20841 // insertsegment()    Insert segment into DT. Queue it if it does not exist. //
20842 //                                                                           //
20844 
20845 bool tetgenmesh::insertsegment(face *insseg, list *misseglist)
20846 {
20847   badface *misseg;
20848   triface searchtet, spintet;
20849   point tend, checkpoint;
20850   point p1, p2;
20851   enum finddirectionresult collinear;
20852   int hitbdry;
20853 
20854   // Search segment ab in DT.
20855   p1 = (point) insseg->sh[3]; 
20856   p2 = (point) insseg->sh[4];
20857   getsearchtet(p1, p2, &searchtet, &tend);
20858   collinear = finddirection(&searchtet, tend, tetrahedrons->items);
20859   if (collinear == LEFTCOLLINEAR) {
20860     checkpoint = apex(searchtet);
20861     enext2self(searchtet);
20862     esymself(searchtet);
20863   } else if (collinear == RIGHTCOLLINEAR) {
20864     checkpoint = dest(searchtet);
20865   } else if (collinear == TOPCOLLINEAR) {
20866     checkpoint = oppo(searchtet);
20867     fnextself(searchtet);
20868     enext2self(searchtet);
20869     esymself(searchtet);
20870   } else {
20871     // assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
20872     checkpoint = (point) NULL;
20873   }
20874   if (checkpoint == tend) {
20875     // Segment exist. Bond it to all tets containing it.
20876     hitbdry = 0;
20877     adjustedgering(searchtet, CCW);
20878     fnextself(searchtet);
20879     spintet = searchtet;
20880     do {
20881       tssbond1(spintet, *insseg);
20882       if (!fnextself(spintet)) {
20883         hitbdry++;
20884         if (hitbdry < 2) {
20885           esym(searchtet, spintet);
20886           if (!fnextself(spintet)) {
20887             hitbdry++;
20888           }
20889         }
20890       }
20891     } while ((apex(spintet) != apex(searchtet)) && (hitbdry < 2));
20892     return true;
20893   } else {
20894     // Segment is missing.
20895     if (misseglist != (list *) NULL) {
20896       if (b->verbose > 2) {
20897         printf("    Queuing missing segment (%d, %d).\n", pointmark(p1),
20898                pointmark(p2));
20899       }
20900       misseg = (badface *) misseglist->append(NULL);
20901       misseg->ss = *insseg;
20902       misseg->forg = p1;
20903       misseg->fdest = p2;
20904       misseg->foppo = (point) NULL; // Not used.
20905       // setshell2badface(misseg->ss, misseg);
20906     }
20907     return false;
20908   }
20909 }
20910 
20912 //                                                                           //
20913 // tallmissegs()    Find and queue all missing segments in DT.               //
20914 //                                                                           //
20916 
20917 void tetgenmesh::tallmissegs(list *misseglist)
20918 {
20919   face segloop;
20920 
20921   if (b->verbose) {
20922     printf("  Queuing missing segments.\n");
20923   }
20924 
20925   subsegs->traversalinit();
20926   segloop.sh = shellfacetraverse(subsegs);
20927   while (segloop.sh != (shellface *) NULL) {
20928     insertsegment(&segloop, misseglist);  
20929     segloop.sh = shellfacetraverse(subsegs);
20930   }
20931 }
20932 
20934 //                                                                           //
20935 // delaunizesegments()    Split segments repeatedly until they appear in a   //
20936 //                        Delaunay tetrahedralization.                       //
20937 //                                                                           //
20938 // Given a PLC X, which has a set V of vertices and a set of segments. Start //
20939 // from a Delaunay tetrahedralization D of V, this routine recovers segments //
20940 // of X in D by incrementally inserting points on missing segments, updating //
20941 // D with the newly inserted points into D', which remains to be a Delaunay  //
20942 // tetrahedralization and respects the segments of X. Hence, each segment of //
20943 // X appears as a union of edges in D'.                                      //
20944 //                                                                           //
20945 // This routine dynamically maintains two meshes, one is DT, another is the  //
20946 // surface mesh F of X.  DT and F have exactly the same vertices.  They are  //
20947 // updated simultaneously with the newly inserted points.                    //
20948 //                                                                           //
20949 // Missing segments are found by looping the set S of segments, checking the //
20950 // existence of each segment in DT.  Once a segment is found missing in DT,  //
20951 // it is split into two subsegments by inserting a point into both DT and F, //
20952 // and S is updated accordingly.  However, the inserted point may cause some //
20953 // other existing segments be non-Delaunay,  hence are missing from the DT.  //
20954 // In order to force all segments to appear in DT, we have to loop S again   //
20955 // after some segments are split. (A little ugly method)  Use a handle to    //
20956 // remember the last segment be split in one loop, hence all segments after  //
20957 // it are existing and need not be checked.                                  //
20958 //                                                                           //
20959 // In priciple, a segment on the convex hull should exist in DT. However, if //
20960 // there are four coplanar points on the convex hull, and the DT only can    //
20961 // contain one diagonal edge which is unfortunately not the segment, then it //
20962 // is missing. During the recovery of the segment, it is possible that the   //
20963 // calculated inserting point for recovering this convex hull segment is not //
20964 // exact enough and lies (slightly) outside the DT. In order to insert the   //
20965 // point, we enlarge the convex hull of the DT, so it can contain the point  //
20966 // and remains convex.  'inserthullsite()' is called for this case.          //
20967 //                                                                           //
20969 
20970 void tetgenmesh::delaunizesegments()
20971 {
20972   list *misseglist;
20973   queue *flipqueue;
20974   badface *misloop;
20975   tetrahedron encodedtet;
20976   triface searchtet, splittet;
20977   face splitsh, symsplitsub;
20978   face segloop, symsplitseg;
20979   point refpoint, splitpoint, sympoint;
20980   point tend, checkpoint;
20981   point p1, p2, pa;
20982   enum finddirectionresult collinear;
20983   enum insertsiteresult success;
20984   enum locateresult symloc;
20985   bool coll;
20986   long vertcount;
20987   int i, j;
20988 
20989   if (!b->quiet) {
20990     printf("Delaunizing segments.\n");
20991   }
20992 
20993   // Construct a map from points to tets for speeding point location.
20994   makepoint2tetmap();
20995   // Initialize a flipqueue.
20996   flipqueue = new queue(sizeof(badface));
20997   // Initialize the pool of missing segments.
20998   misseglist = new list(sizeof(badface), NULL, SUBPERBLOCK);
20999   // Looking for missing segments.
21000   tallmissegs(misseglist);
21001   // The DT contains segments now.
21002   checksubsegs = 1;
21003   // Remember the current number of points.
21004   vertcount = points->items;
21005   // Initialize the counters.
21006   r1count = r2count = r3count = 0l;
21007 
21008   // Loop until 'misseglist' is empty.
21009   while (misseglist->items > 0) {
21010     // Randomly pick a missing segment to recover.
21011     i = randomnation(misseglist->items);
21012     misloop = (badface *)(* misseglist)[i];
21013     segloop = misloop->ss;
21014     // Fill the "hole" in the list by filling the last one.
21015     *misloop = *(badface *)(* misseglist)[misseglist->items - 1];
21016     misseglist->items--;
21017     // Now recover the segment.
21018       p1 = (point) segloop.sh[3];
21019       p2 = (point) segloop.sh[4];
21020       if (b->verbose > 1) {
21021         printf("  Recover segment (%d, %d).\n", pointmark(p1), pointmark(p2));
21022       }
21023       getsearchtet(p1, p2, &searchtet, &tend);
21024       collinear = finddirection(&searchtet, tend, tetrahedrons->items);
21025       if (collinear == LEFTCOLLINEAR) {
21026         checkpoint = apex(searchtet);
21027       } else if (collinear == RIGHTCOLLINEAR) {
21028         checkpoint = dest(searchtet);
21029       } else if (collinear == TOPCOLLINEAR) {
21030         checkpoint = oppo(searchtet);
21031       } else {
21032 #ifdef SELF_CHECK
21033         assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
21034 #endif
21035         checkpoint = (point) NULL;
21036       }
21037       if (checkpoint != tend) {
21038         // ab is missing.
21039         splitpoint = (point) NULL;
21040         if (checkpoint != (point) NULL) {
21041           // An existing point c is found on the segment. It can happen when
21042           //   ab is defined by a long segment with c inside it. Use c to
21043           //   split ab. No new point is created.
21044           splitpoint = checkpoint;
21045           if (pointtype(checkpoint) == FREEVOLVERTEX) {
21046             // c is not a segment vertex yet. It becomes NACUTEVERTEX.
21047             setpointtype(splitpoint, NACUTEVERTEX);  
21048           } else if (pointtype(checkpoint) == ACUTEVERTEX) {
21049             // c is an acute vertex. The definition of PLC is wrong.
21050           } else if (pointtype(checkpoint) == NACUTEVERTEX) {
21051             // c is an nonacute vertex. The definition of PLC is wrong.
21052           } else {
21053             // assert(0);
21054           }
21055         } else {
21056           // Find a reference point p of ab.
21057           refpoint = scoutrefpoint(&searchtet, tend);
21058           if (pointtype(refpoint) == FREEVOLVERTEX) {
21059             // p is an input point, check if it is nearly collinear with ab.
21060             coll = iscollinear(p1, p2, refpoint, b->epsilon);
21061             if (coll) {
21062               // a, b, and p are collinear. We insert p into ab. p becomes
21063               //   a segment vertex with type NACUTEVERTEX.
21064               splitpoint = refpoint;
21065               setpointtype(splitpoint, NACUTEVERTEX);
21066             }
21067           }
21068           if (splitpoint == (point) NULL) {
21069             // Calculate a split point v using rule 1, or 2, or 3.
21070             splitpoint = getsplitpoint(&segloop, refpoint);
21071             
21072             // Is there periodic boundary conditions?
21073             if (checkpbcs) {
21074               // Yes! Insert points on other segments of incident pbcgroups.
21075               i = shellmark(segloop) - 1;
21076               for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
21077                 makepoint(&sympoint);
21078                 symloc = getsegpbcsympoint(splitpoint, &segloop, sympoint,
21079                                            &symsplitseg, segpglist[j]);
21080 #ifdef SELF_CHECK
21081                 assert(symloc != OUTSIDE);
21082 #endif
21083                 if ((symloc == ONEDGE) && (symsplitseg.sh != segloop.sh)) {
21084 #ifdef SELF_CHECK
21085                   assert(symsplitseg.sh != dummysh);
21086 #endif
21087                   setpointtype(sympoint, FREESEGVERTEX);
21088                   setpoint2sh(sympoint, sencode(symsplitseg));
21089                   // Insert sympoint into DT.
21090                   pa = sorg(symsplitseg);
21091                   splittet.tet = dummytet;
21092                   // Find a good start point to search.
21093                   encodedtet = point2tet(pa);
21094                   if (encodedtet != (tetrahedron) NULL) {
21095                     decode(encodedtet, splittet);
21096                     if (isdead(&splittet)) {
21097                       splittet.tet = dummytet; 
21098                     }
21099                   }
21100                   // Locate sympoint in DT.  Do exact location.
21101                   success = insertsite(sympoint, &splittet, false, flipqueue);
21102 #ifdef SELF_CHECK
21103                   assert(success != DUPLICATEPOINT);
21104 #endif
21105                   if (success == OUTSIDEPOINT) {
21106                     inserthullsite(sympoint, &splittet, flipqueue);
21107                   }
21108                   if (steinerleft > 0) steinerleft--;
21109                   // Let sympoint remember splittet.
21110                   setpoint2tet(sympoint, encode(splittet));
21111                   // Do flip in DT.
21112                   lawson(misseglist, flipqueue);
21113                   // Insert sympoint into F.
21114                   symsplitseg.shver = 0;
21115                   spivot(symsplitseg, symsplitsub);
21116                   // sympoint should on the edge of symsplitsub.
21117                   splitsubedge(sympoint, &symsplitsub, flipqueue);
21118                   // Do flip in facet.
21119                   flipsub(flipqueue);
21120                   // Insert the two subsegments.
21121                   symsplitseg.shver = 0;
21122                   insertsegment(&symsplitseg, misseglist);
21123                   senextself(symsplitseg);
21124                   spivotself(symsplitseg);
21125                   symsplitseg.shver = 0;
21126                   insertsegment(&symsplitseg, misseglist);
21127                 } else { // if (symloc == ONVERTEX) {
21128                   // The sympoint already exists. It is possible when two
21129                   //   pbc groups are exactly the same. Omit this point.
21130                   pointdealloc(sympoint);
21131                 }
21132               }
21133             }
21134 
21135             // Insert 'splitpoint' into DT.
21136             if (isdead(&searchtet)) searchtet.tet = dummytet;
21137             success = insertsite(splitpoint, &searchtet, false, flipqueue);
21138             if (success == OUTSIDEPOINT) {
21139               // A convex hull edge is missing, and the inserting point lies
21140               //   (slightly) outside the convex hull due to the significant
21141               //   digits lost in the calculation. Enlarge the convex hull.
21142               inserthullsite(splitpoint, &searchtet, flipqueue);
21143             }
21144             if (steinerleft > 0) steinerleft--;
21145             // Remember a handle in 'splitpoint' to enhance the speed of
21146             //   consequent point location.
21147             setpoint2tet(splitpoint, encode(searchtet));
21148             // Maintain Delaunayness in DT.
21149             lawson(misseglist, flipqueue);
21150           }
21151         }
21152         // Insert 'splitpoint' into F.
21153         spivot(segloop, splitsh);
21154         splitsubedge(splitpoint, &splitsh, flipqueue);
21155         flipsub(flipqueue);
21156         // Insert the two subsegments.
21157         segloop.shver = 0;
21158         insertsegment(&segloop, misseglist);
21159         senextself(segloop);
21160         spivotself(segloop);
21161         segloop.shver = 0;
21162         insertsegment(&segloop, misseglist);
21163       }
21164   }
21165 
21166   // Detach all segments from tets.
21167   tetrahedrons->traversalinit();
21168   searchtet.tet = tetrahedrontraverse();
21169   while (searchtet.tet != (tetrahedron *) NULL) {
21170     for (i = 0; i < 6; i++) {
21171       searchtet.tet[8 + i] = (tetrahedron) dummysh;
21172     }
21173     searchtet.tet = tetrahedrontraverse();
21174   }
21175   // No segments now.
21176   checksubsegs = 0;
21177 
21178   if (b->verbose > 0) {
21179     printf("  %ld protect points.\n", points->items - vertcount);
21180     printf("  R1: %ld,  R2: %ld,  R3: %ld.\n", r1count, r2count, r3count);
21181   }
21182 
21183   delete flipqueue;
21184   delete misseglist;
21185 }
21186 
21187 //
21188 // End of segments recovery routines
21189 //
21190 
21191 //
21192 // Begin of facet recovery routines
21193 //
21194 
21196 //                                                                           //
21197 // insertsubface()    Fix a subface in place.                                //
21198 //                                                                           //
21199 // Search a subface s in current tetrahedralization T.  If s is found a face //
21200 // face of T, it is inserted into T.  Return FALSE if s is not found in T.   //
21201 //                                                                           //
21203 
21204 bool tetgenmesh::insertsubface(face* insertsh, triface* searchtet)
21205 {
21206   triface spintet, symtet;
21207   face testsh, testseg;
21208   face spinsh, casin, casout;
21209   point tapex, checkpoint;
21210   enum finddirectionresult collinear;
21211   int hitbdry;
21212 
21213   // Search an edge of s.
21214   getsearchtet(sorg(*insertsh), sdest(*insertsh), searchtet, &checkpoint);
21215   collinear = finddirection(searchtet, checkpoint, tetrahedrons->items);
21216   if (collinear == LEFTCOLLINEAR) {
21217     enext2self(*searchtet);
21218     esymself(*searchtet);
21219   } else if (collinear == TOPCOLLINEAR) {
21220     fnextself(*searchtet);
21221     enext2self(*searchtet);
21222     esymself(*searchtet);
21223   }
21224   if (dest(*searchtet) != checkpoint) {
21225     // The edge doesn't exist => s is missing.
21226     return false;
21227   }
21228 
21229   // Search s by spinning faces around the edge.
21230   tapex = sapex(*insertsh);
21231   spintet = *searchtet;
21232   hitbdry = 0;
21233   do {
21234     if (apex(spintet) == tapex) {
21235       // Found s in T. Check if s has already been inserted.
21236       tspivot(spintet, testsh);
21237       if (testsh.sh == dummysh) {
21238         adjustedgering(spintet, CCW);
21239         findedge(insertsh, org(spintet), dest(spintet));
21240         tsbond(spintet, *insertsh);
21241         sym(spintet, symtet); // 'symtet' maybe outside, use it anyway.
21242         sesymself(*insertsh);
21243         tsbond(symtet, *insertsh);
21244       } else {
21245         // Found a duplicated subface (due to the redundant input).
21246         if (!b->quiet) {
21247           printf("Warning:  Two subfaces are found duplicated at ");
21248           printf("(%d, %d, %d)\n", pointmark(sorg(testsh)),
21249                  pointmark(sdest(testsh)), pointmark(sapex(testsh)));
21250           printf("  Subface of facet #%d is deleted.\n", shellmark(*insertsh));
21251           // printf("  Hint: -d switch can find all duplicated facets.\n");
21252         }
21253         shellfacedealloc(subfaces, insertsh->sh);
21254       }
21255       return true;
21256     }
21257     if (!fnextself(spintet)) {
21258       hitbdry ++;
21259       if (hitbdry < 2) {
21260         esym(*searchtet, spintet);
21261         if (!fnextself(spintet)) {
21262           hitbdry ++;
21263         }
21264       }
21265     }
21266   } while (hitbdry < 2 && apex(spintet) != apex(*searchtet));
21267 
21268   // s is missing.
21269   return false;
21270 }
21271 
21273 //                                                                           //
21274 // tritritest()    Test if two triangles are intersecting in their interior. //
21275 //                                                                           //
21276 // One triangle t1 is the face of 'checktet', the other t2 is given by three //
21277 // corners 'p1', 'p2' and 'p3'. This routine calls tri_tri_inter() to detect //
21278 // whether t1 and t2 exactly intersect in their interior. Cases like share a //
21279 // vertex, share an edge, or coincidence are considered not intersect.       //
21280 //                                                                           //
21282 
21283 bool tetgenmesh::tritritest(triface* checktet, point p1, point p2, point p3)
21284 {
21285   point forg, fdest, fapex;
21286   enum interresult intersect;
21287 
21288   forg = org(*checktet);
21289   fdest = dest(*checktet);
21290   fapex = apex(*checktet);
21291 
21292 #ifdef SELF_CHECK
21293   REAL ax, ay, az, bx, by, bz;
21294   REAL n[3];
21295   // face (torg, tdest, tapex) should not be degenerate. However p1, p2,
21296   //   and p3 may be collinear. Check it.
21297   ax = forg[0] - fdest[0];
21298   ay = forg[1] - fdest[1];
21299   az = forg[2] - fdest[2];
21300   bx = forg[0] - fapex[0];
21301   by = forg[1] - fapex[1];
21302   bz = forg[2] - fapex[2];
21303   n[0] = ay * bz - by * az;
21304   n[1] = az * bx - bz * ax;
21305   n[2] = ax * by - bx * ay;
21306   assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21307   // The components of n should not smaller than the machine epsilon.
21308 
21309   ax = p1[0] - p2[0];
21310   ay = p1[1] - p2[1];
21311   az = p1[2] - p2[2];
21312   bx = p1[0] - p3[0];
21313   by = p1[1] - p3[1];
21314   bz = p1[2] - p3[2];
21315   n[0] = ay * bz - by * az;
21316   n[1] = az * bx - bz * ax;
21317   n[2] = ax * by - bx * ay;
21318   assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21319   // The components of n should not smaller than the machine epsilon.
21320 #endif
21321 
21322   intersect = tri_tri_inter(forg, fdest, fapex, p1, p2, p3);
21323   return intersect == INTERSECT;
21324 }
21325 
21327 //                                                                           //
21328 // initializecavity()    Initialize the cavity.                              //
21329 //                                                                           //
21330 // A cavity C is bounded by a list of faces, called fronts.  Each front f is //
21331 // hold by a tet t adjacent to C, t is not in C (uninfected). If f is a hull //
21332 // face, t does't exist, a fake tet t' is created to hold f. t' has the same //
21333 // vertices as f but no opposite.  t' will be removed automatically after C  //
21334 // is filled with new tets (by carvecavity()).                               //
21335 //                                                                           //
21336 // The faces of C are given in two lists. 'floorlist' is a set of subfaces,  //
21337 // each subface has been oriented to face to the inside of C.  'ceillist' is //
21338 // a set of tetrahedral faces. 'frontlist' returns the initialized fronts.   //
21339 //                                                                           //
21341 
21342 void tetgenmesh::initializecavity(list* floorlist, list* ceillist,
21343   list* frontlist)
21344 {
21345   triface neightet, casingtet;
21346   triface faketet;
21347   face worksh;
21348   int i;
21349 
21350   // Initialize subfaces of C.
21351   for (i = 0; i < floorlist->len(); i++) {
21352     // Get a subface s.
21353     worksh = * (face *)(* floorlist)[i];
21354 #ifdef SELF_CHECK
21355     // Current side of s should be empty.
21356     stpivot(worksh, neightet);
21357     assert(neightet.tet == dummytet);
21358 #endif
21359     // Get the adjacent tet t.
21360     sesymself(worksh);
21361     stpivot(worksh, casingtet);
21362     // Does t exist?
21363     if (casingtet.tet == dummytet) {
21364       // Create a fake tet t' to hold f temporarily.
21365       maketetrahedron(&faketet);
21366       setorg(faketet, sorg(worksh));
21367       setdest(faketet, sdest(worksh));
21368       setapex(faketet, sapex(worksh));
21369       setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21370       tsbond(faketet, worksh);
21371       frontlist->append(&faketet);
21372     } else {
21373       frontlist->append(&casingtet);
21374     }
21375   }
21376   // Initialize tet faces of C.
21377   for (i = 0; i < ceillist->len(); i++) {
21378     // Get a tet face c.
21379     neightet = * (triface *) (* ceillist)[i];
21380 #ifdef SELF_CHECK
21381     // The tet of c must be inside C (going to be deleted).
21382     assert(infected(neightet));
21383 #endif
21384     // Get the adjacent tet t.
21385     sym(neightet, casingtet);
21386     // Does t exist?
21387     if (casingtet.tet == dummytet) {
21388       // No. Create a fake tet t' to hold f temporarily.
21389       maketetrahedron(&faketet);
21390       // Be sure that the vertices of t' are CCW oriented.
21391       adjustedgering(neightet, CW); // CW edge ring.
21392       setorg(faketet, org(neightet));
21393       setdest(faketet, dest(neightet));
21394       setapex(faketet, apex(neightet));
21395       setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21396       // Bond t' to a subface if it exists.
21397       tspivot(neightet, worksh);
21398       if (worksh.sh != dummysh) {
21399         sesymself(worksh);
21400         tsbond(faketet, worksh);
21401       } 
21402       // Bond c <--> t'. So we're able to find t' and remove it.
21403       bond(faketet, neightet);
21404       // c may become uninfected due to the bond().
21405       infect(neightet);
21406       frontlist->append(&faketet);
21407     } else {
21408       frontlist->append(&casingtet);
21409     }
21410   }
21411 }
21412 
21414 //                                                                           //
21415 // retrievenewtets()    Retrieve the newly created tets.                     //
21416 //                                                                           //
21417 // On input, 'newtetlist' contains at least one alive new tet. From this tet,//
21418 // other new tets can be found by a broadth-first searching.                 //
21419 //                                                                           //
21421 
21422 void tetgenmesh::retrievenewtets(list* newtetlist)
21423 {
21424   triface searchtet, casingtet;
21425   int i;
21426 
21427   // There may be dead tets due to flip32(). Delete them first.
21428   for (i = 0; i < newtetlist->len(); i++) {
21429     searchtet = * (triface *)(* newtetlist)[i];
21430     if (isdead(&searchtet)) {
21431       newtetlist->del(i, 0); i--;
21432       continue;
21433     }
21434     infect(searchtet);
21435   }
21436   // Find all new tets.
21437   for (i = 0; i < newtetlist->len(); i++) {
21438     searchtet = * (triface *)(* newtetlist)[i];
21439     for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
21440       sym(searchtet, casingtet);
21441       if ((casingtet.tet != dummytet) && !infected(casingtet)) {
21442         infect(casingtet);
21443         newtetlist->append(&casingtet);
21444       }
21445     }
21446   }
21447   // Uninfect new tets.
21448   for (i = 0; i < newtetlist->len(); i++) {
21449     searchtet = * (triface *)(* newtetlist)[i];
21450     uninfect(searchtet);
21451   }
21452 }
21453 
21455 //                                                                           //
21456 // delaunizecavvertices()    Form a DT of the vertices of a cavity.          //
21457 //                                                                           //
21458 // 'floorptlist' and 'ceilptlist' are the vertices of the cavity.            //
21459 //                                                                           //
21460 // The tets of the DT are created directly in the pool 'tetrahedrons', i.e., //
21461 // no auxiliary data structure and memory are required.  The trick is at the //
21462 // time they're created, there are no connections between them to the other  //
21463 // tets in the pool. You can imagine they form an ioslated island.           //
21464 //                                                                           //
21466 
21467 void tetgenmesh::delaunizecavvertices(triface* oldtet, list* floorptlist,
21468   list* ceilptlist, list* newtetlist, queue* flipque)
21469 {
21470   point *insertarray;
21471   triface bakhulltet, newtet;
21472   long bakhullsize;
21473   long arraysize;
21474   int bakchksub;
21475   int i, j;
21476 
21477   // Prepare the array of points for inserting.
21478   arraysize = floorptlist->len();
21479   if (ceilptlist != (list *) NULL) {
21480     arraysize += ceilptlist->len();
21481   }
21482   insertarray = new point[arraysize];
21483   for (i = 0; i < floorptlist->len(); i++) {
21484     insertarray[i] = * (point *)(* floorptlist)[i];
21485   }
21486   if (ceilptlist != (list *) NULL) {
21487     for (j = 0; j < ceilptlist->len(); j++) {
21488       insertarray[i + j] = * (point *)(* ceilptlist)[j];
21489     }
21490   }
21491 
21492   // The incrflipdelaunay() is re-used. Backup global variables.
21493   decode(dummytet[0], bakhulltet);
21494   bakhullsize = hullsize;
21495   bakchksub = checksubfaces;
21496   checksubfaces = 0;
21497   b->verbose--;
21498 
21499   // Form the DT by incremental flip Delaunay algorithm. Do not jump for
21500   //   point location, do not merge points.
21501   incrflipdelaunay(oldtet, insertarray, arraysize, false, false, 0.0, flipque);
21502   
21503   // Get a tet in D.
21504   decode(dummytet[0], newtet);
21505   newtetlist->append(&newtet);
21506   // Get all tets of D.
21507   retrievenewtets(newtetlist);
21508 
21509   // Restore global variables.
21510   dummytet[0] = encode(bakhulltet);
21511   hullsize = bakhullsize;
21512   checksubfaces = bakchksub;
21513   b->verbose++;
21514   
21515   delete [] insertarray;
21516 }
21517 
21519 //                                                                           //
21520 // insertauxsubface()    Fix an auxilary subface in place.                   //
21521 //                                                                           //
21522 // An auxilary subface s is fixed in D as it is a real subface, but s has no //
21523 // vertices and neighbors. It has two uses: (1) it protects an identfied     //
21524 // front f in D; (2) it serves the link to bond a tet in C and f later. The  //
21525 // first neighbor of s (s->sh[0]) stores a pointer to f.                     //
21526 //                                                                           //
21527 // 'front' is a front f of C. idfront' t is a tet in D where f is identified //
21528 // be a face of it. s will be fixed between t and its neighbor.              //
21529 //                                                                           //
21531 
21532 void tetgenmesh::insertauxsubface(triface* front, triface* idfront)
21533 {
21534   triface neightet;
21535   face auxsh;
21536 
21537   // Create the aux subface s.
21538   makeshellface(subfaces, &auxsh);
21539   // Bond s <--> t.
21540   tsbond(*idfront, auxsh);
21541   // Does t's neighbor n exist?
21542   sym(*idfront, neightet);
21543   if (neightet.tet != dummytet) {
21544     // Bond s <--> n.
21545     sesymself(auxsh);
21546     tsbond(neightet, auxsh);
21547   }
21548   // Let s remember f.
21549   auxsh.sh[0] = (shellface) encode(*front);
21550 }
21551 
21553 //                                                                           //
21554 // scoutfront()    Scout a face in D.                                        //
21555 //                                                                           //
21556 // Search a 'front' f in D. If f is found, return TRUE and the face of D is  //
21557 // returned in 'idfront'. Otherwise, return FALSE.                           //
21558 //                                                                           //
21560 
21561 bool tetgenmesh::scoutfront(triface* front, triface* idfront, list* newtetlist)
21562 {
21563   triface spintet;
21564   point pa, pb, pc;
21565   enum locateresult loc;
21566   enum finddirectionresult col;
21567   int hitbdry;
21568   int i;
21569 
21570   // Let the front we're searching is abc.
21571   pa = org(*front);
21572   pb = dest(*front);
21573   // Get a tet in D for searching.
21574   *idfront = recenttet;
21575   // Make sure the tet is valid (it may be killed by flips).
21576   if (isdead(idfront)) {
21577     // The tet is dead. Search a live tet in D. !!!
21578     for (i = 0; i < newtetlist->len(); i++) {
21579       recenttet = * (triface *)(* newtetlist)[i];
21580       if (!isdead(&recenttet)) break;
21581     }
21582     assert(i < newtetlist->len());
21583   }
21584 
21585   // Search a tet having vertex a.
21586   loc = preciselocate(pa, idfront, (long) newtetlist->len());
21587   assert(loc == ONVERTEX);
21588   recenttet = *idfront;
21589   // Search a tet having edge ab.
21590   col = finddirection(idfront, pb, (long) newtetlist->len());
21591   if (col == RIGHTCOLLINEAR) {
21592     // b is just the destination.
21593   } else if (col == LEFTCOLLINEAR) {
21594     enext2self(*idfront);
21595     esymself(*idfront);
21596   } else if (col == TOPCOLLINEAR) {
21597     fnextself(*idfront);
21598     enext2self(*idfront);
21599     esymself(*idfront);
21600   }
21601 
21602   if (dest(*idfront) == pb) {
21603     // Search a tet having face abc
21604     pc = apex(*front);
21605     spintet = *idfront;
21606     hitbdry = 0;
21607     do {
21608       if (apex(spintet) == pc) {
21609         // Found abc. Insert an auxilary subface s at idfront.
21610         // insertauxsubface(front, &spintet);
21611         *idfront = spintet;
21612         return true;
21613       }
21614       if (!fnextself(spintet)) {
21615         hitbdry ++;
21616         if (hitbdry < 2) {
21617           esym(*idfront, spintet);
21618           if (!fnextself(spintet)) {
21619             hitbdry ++;
21620           }
21621         }
21622       }
21623       if (apex(spintet) == apex(*idfront)) break;
21624     } while (hitbdry < 2);  
21625   }
21626 
21627   // f is missing in D.
21628   if (b->verbose > 2) {
21629     printf("    Front (%d, %d, %d) is missing.\n", pointmark(pa),
21630            pointmark(pb), pointmark(apex(*front)));
21631   }
21632   return false;
21633 }
21634 
21636 //                                                                           //
21637 // gluefronts()    Glue two fronts together.                                 //
21638 //                                                                           //
21639 // This is a support routine for identifyfront().  Two fronts f and f1 are   //
21640 // found indentical. This is caused by the non-coplanarity of vertices of a  //
21641 // facet. Hence f and f1 are a subface and a tet. They are not fronts of the //
21642 // cavity anymore. This routine glues f and f1 together.                     //
21643 //                                                                           //
21645 
21646 void tetgenmesh::gluefronts(triface* front, triface* front1)
21647 {
21648   face consh;
21649 
21650   // Glue f and f1 together. There're four cases:
21651   //   (1) both f and f1 are not fake;
21652   //   (2) f is not fake, f1 is fake;
21653   //   (3) f is fake and f1 is not fake;
21654   //   (4) both f and f1 are fake.
21655   // Case (4) should be not possible. 
21656 
21657   // Is there a concrete subface c at f.
21658   tspivot(*front, consh);
21659   if (consh.sh != dummysh) {
21660     sesymself(consh);
21661     tsbond(*front1, consh); // Bond: f1 <--> c.
21662     sesymself(consh);
21663   }
21664   // Does f hold by a fake tet.
21665   if (oppo(*front) == (point) NULL) {
21666     // f is fake. Case (3) or (4).
21667     assert(oppo(*front1) != (point) NULL); // Eliminate (4).
21668     // Case (3).
21669     if (consh.sh != dummysh) {
21670       stdissolve(consh);  // Dissolve: c -x-> f.
21671     }
21672     // Dealloc f.
21673     tetrahedrondealloc(front->tet);
21674     // f1 becomes a hull. let 'dummytet' bond to it.
21675     dummytet[0] = encode(*front1);
21676   } else {
21677     // Case (1) or (2).
21678     bond(*front, *front1); // Bond f1 <--> f. 
21679   }
21680   // Is f a fake tet?
21681   if (!isdead(front)) {
21682     // No. Check for case (2).
21683     tspivot(*front1, consh);
21684     // Is f1 fake?
21685     if (oppo(*front1) == (point) NULL) {
21686       // Case (2) or (4)
21687       assert(oppo(*front) != (point) NULL); // Eliminate (4).
21688       // Case (2).
21689       if (consh.sh != dummysh) {
21690         stdissolve(consh);  // Dissolve: c -x-> f1.
21691         sesymself(consh); // Bond: f <--> c.
21692         tsbond(*front, consh);
21693       }
21694       // Dissolve: f -x->f1.
21695       dissolve(*front);
21696       // Dealloc f1.
21697       tetrahedrondealloc(front1->tet);
21698       // f becomes a hull. let 'dummytet' bond to it.
21699       dummytet[0] = encode(*front);
21700     } else {
21701       // Case (1).
21702       if (consh.sh != dummysh) {
21703         sesymself(consh);
21704         tsbond(*front, consh); // Bond: f <--> c.
21705       } 
21706     }
21707   }
21708 }
21709 
21711 //                                                                           //
21712 // identifyfronts()    Identify cavity faces in D.                           //
21713 //                                                                           //
21714 // 'frontlist' are fronts of C need indentfying.  This routine searches each //
21715 // front f in D. Once f is found, an auxilary subface s is inserted in D at  //
21716 // the face. If f is not found in D, remove it from frontlist and save it in //
21717 // 'misfrontlist'.                                                           //
21718 //                                                                           //
21720 
21721 bool tetgenmesh::identifyfronts(list* frontlist, list* misfrontlist,
21722   list* newtetlist)
21723 {
21724   triface front, front1, tfront;
21725   triface idfront, neightet;
21726   face auxsh;
21727   int len, i, j;
21728 
21729   misfrontlist->clear();
21730   // Set a new tet in D for searching.
21731   recenttet = * (triface *)(* newtetlist)[0];
21732 
21733   // Identify all fronts in D.
21734   for (i = 0; i < frontlist->len(); i++) {
21735     // Get a front f.
21736     front = * (triface *)( *frontlist)[i];
21737     if (scoutfront(&front, &idfront, newtetlist)) {
21738       // Found f. Insert an aux subface s.
21739       assert((idfront.tet != dummytet) && !isdead(&idfront));
21740       // Does s already exist?
21741       tspivot(idfront, auxsh);
21742       if (auxsh.sh != dummysh) {
21743         // There're two identical fronts, f (front) and f1 (s.sh[0])!
21744         decode((tetrahedron) auxsh.sh[0], front1);
21745         assert((front1.tet != dummytet) && !infected(front1));
21746         // Detach s in D.
21747         tsdissolve(idfront);
21748         sym(idfront, neightet);
21749         if (neightet.tet != dummytet) {
21750           tsdissolve(neightet);
21751         }
21752         // s has fulfilled its duty. Can be deleted.
21753         shellfacedealloc(subfaces, auxsh.sh);
21754         // Remove f from frontlist.
21755         frontlist->del(i, 1); i--;
21756         // Remove f1 from frontlist.
21757         len = frontlist->len();
21758         for (j = 0; j < frontlist->len(); j++) {
21759           tfront = * (triface *)(* frontlist)[j];
21760           if ((tfront.tet == front1.tet) && (tfront.loc == front1.loc)) {
21761             // Found f1 in list.  Check f1 != f.
21762             assert((tfront.tet != front.tet) || (tfront.loc != front.loc));
21763             frontlist->del(j, 1); i--;
21764             break;
21765           }
21766         }
21767         assert((frontlist->len() + 1) == len);
21768         // Glue f and f1 together.
21769         gluefronts(&front, &front1);        
21770       } else {
21771         // Insert an aux subface to protect f in D.
21772         insertauxsubface(&front, &idfront);
21773       }
21774     } else {
21775       // f is missing.
21776       frontlist->del(i, 1); i--;
21777       // Are there two identical fronts, f (front) and f1 (front1)?
21778       for (j = 0; j < misfrontlist->len(); j++) {
21779         front1 = * (triface *)(* misfrontlist)[j];
21780         if (isfacehaspoint(&front1, org(front)) &&
21781             isfacehaspoint(&front1, dest(front)) &&
21782             isfacehaspoint(&front1, apex(front))) break;
21783       }
21784       if (j < misfrontlist->len()) {
21785         // Found an identical front f1. Remove f1 from the list.
21786         misfrontlist->del(j, 1);
21787         // Glue f and f1 together.
21788         gluefronts(&front, &front1); 
21789       } else {
21790         // Add f into misfrontlist.
21791         misfrontlist->append(&front);
21792       }
21793     }
21794   }
21795   return misfrontlist->len() == 0;
21796 }
21797 
21799 //                                                                           //
21800 // detachauxsubfaces()    Detach auxilary subfaces in D.                     //
21801 //                                                                           //
21802 // This is a reverse routine of identifyfronts(). Some fronts are missing in //
21803 // D. C can not be easily tetrahedralized. It needs remediation (expansion,  //
21804 // or constrained flips, or adding a Steiner point).  This routine detaches  //
21805 // the auxilary subfaces have been inserted in D and delete them.            //
21806 //                                                                           //
21808 
21809 void tetgenmesh::detachauxsubfaces(list* newtetlist)
21810 {
21811   triface newtet, neightet;
21812   face auxsh;
21813   int i;
21814 
21815   for (i = 0; i < newtetlist->len(); i++) {
21816     // Get a new tet t.
21817     newtet = * (triface *)(* newtetlist)[i];
21818     // t may e dead due to flips.
21819     if (isdead(&newtet)) continue;
21820     assert(!infected(newtet));
21821     // Check the four faces of t.
21822     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
21823       tspivot(newtet, auxsh);
21824       if (auxsh.sh != dummysh) {
21825         // An auxilary subface s.
21826         assert(sorg(auxsh) == (point) NULL);
21827         tsdissolve(newtet);  // t -x-> s.
21828         sym(newtet, neightet);
21829         if (neightet.tet != dummytet) {
21830           assert(!isdead(&neightet));
21831           tsdissolve(neightet); // n -x-> s.
21832         }
21833         // Delete s.
21834         shellfacedealloc(subfaces, auxsh.sh);
21835       }
21836     }
21837   }
21838 }
21839 
21841 //                                                                           //
21842 // expandcavity()    Expand the cavity by adding new fronts.                 //
21843 //                                                                           //
21844 // This is the support routine for delaunizecavity().  Some fronts of C are  //
21845 // missing in D since they're not strongly Delaunay. Such fronts are removed //
21846 // and the faces of the tets abutting to them are added. C is then expanded. //
21847 // Some removed faces may be subfaces, they're queued to recover later. D is //
21848 // expanded simultaneously with the new vertices of the new fronts.          //
21849 //                                                                           //
21851 
21852 void tetgenmesh::expandcavity(list* frontlist, list* misfrontlist,
21853   list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
21854 {
21855   triface misfront, newfront, casingtet, crosstet;
21856   triface searchtet, faketet, bakhulltet;
21857   face checksh;
21858   point pd;
21859   enum insertsiteresult success;
21860   long bakhullsize;
21861   int bakchksub;
21862   int i, j, k;
21863 
21864   if (b->verbose > 1) {
21865     printf("    Expand cavity (%d missing fronts).\n", misfrontlist->len());
21866   }
21867   // Increase the number of expanded times.
21868   expcavcount++;
21869   // The incrflipdelaunay() is re-used. Backup global variables.
21870   decode(dummytet[0], bakhulltet);
21871   bakhullsize = hullsize;
21872   bakchksub = checksubfaces;
21873   checksubfaces = 0;
21874   b->verbose--;
21875 
21876   // Choose a tet in D for searching.
21877   recenttet = * (triface *)(* newtetlist)[0];
21878   assert((recenttet.tet != dummytet) && !isdead(&recenttet));
21879 
21880   // Loop through 'misfrontlist'.
21881   for (i = 0; i < misfrontlist->len(); i++) {
21882     // Get a missing front f.
21883     misfront = * (triface *)(* misfrontlist)[i];
21884     // C will be expanded at f.
21885     if (b->verbose > 1) {
21886       printf("    Get misfront (%d, %d, %d).\n", pointmark(org(misfront)),
21887              pointmark(dest(misfront)), pointmark(apex(misfront)));
21888     }
21889     // Is f has a subface s?
21890     tspivot(misfront, checksh);
21891     if (checksh.sh != dummysh) {
21892       // A subface s is found. Check whether f is expandable at s.
21893       sym(misfront, crosstet);
21894       if (!infected(crosstet)) {
21895         // f is not expandable. In principle is should not happen. However,
21896         //   it can happen when PBC is in use.
21897         assert(checkpbcs);
21898         // Skip expanding f. It will be processed later.
21899         continue;
21900       }
21901       // Temporarily remove s. Queue and recover it later.
21902       if (b->verbose > 1) {
21903         printf("    Queuing subface (%d, %d, %d).\n",
21904                pointmark(sorg(checksh)), pointmark(sdest(checksh)),
21905                pointmark(sapex(checksh)));
21906       }
21907       // Detach s from tets at its both sides.
21908       tsdissolve(misfront);
21909       tsdissolve(crosstet);
21910       // Detach tets at from s.
21911       stdissolve(checksh);
21912       sesymself(checksh);
21913       stdissolve(checksh);
21914       // Mark and queue it.
21915       sinfect(checksh);
21916       missingshqueue->push(&checksh);
21917     }
21918     // f may already be processed (become a cross tet of C).
21919     if (infected(misfront)) continue;
21920     // Get the point p = oppo(t), t is the tet holds f.
21921     pd = oppo(misfront);
21922 #ifdef SELF_CHECK
21923     // t must not be fake.
21924     assert(pd != (point) NULL);
21925 #endif
21926     // Insert p in D. p may not be inserted if it is one of the two cases:
21927     //   (1) p is already a vertex of D;
21928     //   (2) p lies outside the CH of D;
21929     searchtet = recenttet;
21930     // Make sure the tet is valid (it may be killed by flips).
21931     if (isdead(&searchtet)) {
21932       // The tet is dead. Get a live tet in D. !!!
21933       for (j = 0; j < newtetlist->len(); j++) {
21934         recenttet = * (triface *)(* newtetlist)[j];
21935         if (!isdead(&recenttet)) break;
21936       }
21937       assert(j < newtetlist->len());
21938       searchtet = recenttet;
21939     }
21940     success = insertsite(pd, &searchtet, false, flipque);
21941     if (success == OUTSIDEPOINT) {
21942       // case (2). Insert p onto CH of D.
21943       inserthullsite(pd, &searchtet, flipque);
21944     }
21945     if (success != DUPLICATEPOINT) {
21946       // p is inserted. Recover Delaunness of D by flips.
21947       flip(flipque, NULL);
21948     }
21949     // Expand C by adding new fronts. The three faces of t which have p as a
21950     //   vertex become new fronts. However, if a new front is coincident with
21951     //   an old front of C, it is not added and the old front is removed. 
21952     adjustedgering(misfront, CCW);
21953     for (j = 0; j < 3; j++) {
21954       // Notice: Below I mis-used the names. 'newfront' is not exactly a new
21955       //   front, instead the 'casingtet' should be called new front. 
21956       // Get a new front f_n.
21957       fnext(misfront, newfront);
21958       // Get the neighbor tet n at f_n.
21959       sym(newfront, casingtet);
21960       // Is n a cross tet?
21961       if (!infected(casingtet)) {
21962         // f_n becomes a new front of C.
21963         // Does n exist?
21964         if (casingtet.tet == dummytet) {
21965           // Create a fake tet n' to hold f_n temporarily.
21966           maketetrahedron(&faketet);
21967           // Be sure that the vertices of fake tet are CCW oriented.
21968           adjustedgering(newfront, CW); // CW edge ring.
21969           setorg(faketet, org(newfront));
21970           setdest(faketet, dest(newfront));
21971           setapex(faketet, apex(newfront));
21972           setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21973           // Bond n' to a subface if it exists.
21974           tspivot(newfront, checksh);
21975           if (checksh.sh != dummysh) {
21976             sesymself(checksh);
21977             tsbond(faketet, checksh);
21978           } 
21979           // Bond f_n <--> n'. So we're able to find n' and remove it.
21980           bond(faketet, newfront);
21981           frontlist->append(&faketet);
21982         } else {
21983           // Add n to frontlist.
21984           frontlist->append(&casingtet);
21985         }
21986       } else {
21987         // f_n is coincident with an existing front f' of C. f' is no longer
21988         //   a front, remove it from frontlist.  Use the inverse order to
21989         //   search f' (most likely, a newly added front may be f').
21990         for (k = frontlist->len() - 1; k >= 0; k--) {
21991           searchtet = * (triface *)(* frontlist)[k];
21992           if ((newfront.tet == searchtet.tet) &&
21993               (newfront.loc == searchtet.loc)) {
21994             frontlist->del(k, 0);
21995             break;
21996           }
21997         }
21998         // Is f_n a subface?
21999         tspivot(newfront, checksh);
22000         if (checksh.sh != dummysh) {
22001           // Temporarily remove checksh. Make it missing. recover it later.
22002           if (b->verbose > 2) {
22003             printf("    Queuing subface (%d, %d, %d).\n",
22004                    pointmark(sorg(checksh)), pointmark(sdest(checksh)),
22005                    pointmark(sapex(checksh)));
22006           }
22007           tsdissolve(newfront);
22008           tsdissolve(casingtet);
22009           // Detach tets at the both sides of checksh.
22010           stdissolve(checksh);
22011           sesymself(checksh);
22012           stdissolve(checksh);
22013           sinfect(checksh);
22014           missingshqueue->push(&checksh);
22015         }
22016       }
22017       enextself(misfront);
22018     }
22019     // C has been expanded at f. t becomes a cross tet.
22020     if (!infected(misfront)) {
22021       // t will be deleted, queue it.
22022       infect(misfront);
22023       crosstetlist->append(&misfront);
22024     }
22025   }
22026 
22027   // Loop through misfrontlist, remove infected misfronts.
22028   for (i = 0; i < misfrontlist->len(); i++) {
22029     misfront = * (triface *)(* misfrontlist)[i];
22030     if (infected(misfront)) {
22031       // Remove f, keep original list order.
22032       misfrontlist->del(i, 1);
22033       i--;
22034     }
22035   }
22036 
22037   // Are we done?
22038   if (misfrontlist->len() > 0) {
22039     // No. There are unexpandable fronts.
22040     // expandcavity_sos(misfrontlist);
22041     assert(0); // Not done yet.
22042   }
22043 
22044   // D has been updated (by added new tets or dead tets) (due to flips).
22045   retrievenewtets(newtetlist);
22046 
22047   // Restore global variables.
22048   dummytet[0] = encode(bakhulltet);
22049   hullsize = bakhullsize;
22050   checksubfaces = bakchksub;
22051   b->verbose++;
22052 }
22053 
22055 //                                                                           //
22056 // carvecavity()    Remove redundant (outside) tetrahedra from D.            //
22057 //                                                                           //
22058 // The fronts of C have been identified in D. Hence C can be tetrahedralized //
22059 // by removing the tets outside C. The CDT is then updated by filling C with //
22060 // the remaining tets (inside C) of D.                                       //
22061 //                                                                           //
22062 // Each front is protected by an auxilary subface s in D. s has a pointer to //
22063 // f (s.sh[0]). f can be used to classified the in- and out- tets of C (the  //
22064 // CW orientation of f faces to the inside of C). The classified out-tets of //
22065 // C are marked (infected) for removing.                                     //
22066 //                                                                           //
22067 // Notice that the out-tets may not only the tets on the CH of C,  but also  //
22068 // tets completely inside D, eg., there is a "hole" in D.  Such tets must be //
22069 // marked during classification. The hole tets are poped up and removed too. //
22070 //                                                                           //
22072 
22073 void tetgenmesh::carvecavity(list* newtetlist, list* outtetlist,
22074   queue* flipque)
22075 {
22076   triface newtet, neightet, front, outtet;
22077   face auxsh, consh;
22078   point pointptr;
22079   REAL ori;
22080   int i;
22081 
22082   // Clear work list.
22083   outtetlist->clear();
22084 
22085   // Classify in- and out- tets in D. Mark and queue classified out-tets.
22086   for (i = 0; i < newtetlist->len(); i++) {
22087     // Get a new tet t.
22088     newtet = * (triface *)(* newtetlist)[i];
22089     assert(!isdead(&newtet));
22090     // Look for aux subfaces attached at t.
22091     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22092       tspivot(newtet, auxsh);
22093       if (auxsh.sh != dummysh) {
22094         // Has this side a neighbor n? 
22095         sym(newtet, neightet);
22096         if (neightet.tet != dummytet) {
22097           // Classify t and n (one is "in" and another is "out").
22098           // Get the front f.
22099           decode((tetrahedron) auxsh.sh[0], front);
22100           // Let f face to the inside of C.
22101           adjustedgering(front, CW);
22102           ori = orient3d(org(front), dest(front), apex(front), oppo(newtet));
22103           assert(ori != 0.0);
22104           if (ori < 0.0) {
22105             // t is in-tet. n is out-tet.
22106             outtet = neightet;
22107           } else {
22108             // n is in-tet. t is out-tet.
22109             outtet = newtet;
22110           }
22111           // Add the out-tet into list.
22112           if (!infected(outtet)) {
22113             infect(outtet);
22114             outtetlist->append(&outtet);
22115           }
22116         }
22117       }
22118     }
22119   }
22120 
22121   // Find and mark all out-tets.
22122   for (i = 0; i < outtetlist->len(); i++) {
22123     outtet = * (triface *)(* outtetlist)[i];
22124     for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22125       sym(outtet, neightet);
22126       // Does the neighbor exist and unmarked?
22127       if ((neightet.tet != dummytet) && !infected(neightet)) {
22128         // Is it protected by an aux subface?
22129         tspivot(outtet, auxsh);
22130         if (auxsh.sh == dummysh) {
22131           // It's an out-tet.
22132           infect(neightet);
22133           outtetlist->append(&neightet);
22134         }
22135       }
22136     }
22137   }
22138 
22139   // Remove the out- (and hole) tets.
22140   for (i = 0; i < outtetlist->len(); i++) {
22141     // Get an out-tet t.
22142     outtet = * (triface *)(* outtetlist)[i];
22143     // Detach t from the in-tets.
22144     for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22145       // Is there an aux subface s?
22146       tspivot(outtet, auxsh);
22147       if (auxsh.sh != dummysh) {
22148         // Get the neighbor n.
22149         sym(outtet, neightet);
22150         assert(!infected(neightet)); // t must be in-tet.
22151         // Detach n -x-> t.
22152         dissolve(neightet);
22153       }
22154     }
22155     // Dealloc the tet.
22156     tetrahedrondealloc(outtet.tet);
22157   }
22158 
22159   // Connect the in-tets of C to fronts. Remove aux subfaces and fake tets.
22160   for (i = 0; i < newtetlist->len(); i++) {
22161     // Get a new tet t.
22162     newtet = * (triface *)(* newtetlist)[i];
22163     // t may be an out-tet and has got deleted.
22164     if (isdead(&newtet)) continue;
22165     // t is an in-tet. Look for aux subfaces attached at t.
22166     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22167       // Is there an aux subface s?
22168       tspivot(newtet, auxsh);
22169       if (auxsh.sh != dummysh) {
22170         // Get the front f.
22171         decode((tetrahedron) auxsh.sh[0], front);
22172         assert((front.tet != dummytet) && !infected(front));
22173         // s has fulfilled its duty. Can be deleted.
22174         tsdissolve(newtet); // dissolve: t -x-> s.
22175         // Delete s.
22176         shellfacedealloc(subfaces, auxsh.sh);
22177         // Connect the newtet t and front f.
22178         // Is there a concrete subface c at f.
22179         tspivot(front, consh);
22180         if (consh.sh != dummysh) {
22181           sesymself(consh);
22182           // Bond: t <--> c.
22183           tsbond(newtet, consh);
22184         }
22185         // Does f hold by a fake tet.
22186         if (oppo(front) == (point) NULL) {
22187           // f is fake.
22188           if (consh.sh != dummysh) {
22189             sesymself(consh);
22190             // Dissolve: c -x-> f.
22191             stdissolve(consh);
22192           }
22193           // Dealloc f.
22194           tetrahedrondealloc(front.tet);
22195           // f becomes a hull. let 'dummytet' bond to it.
22196           dummytet[0] = encode(newtet);
22197         } else {
22198           // Bond t <--> f.
22199           bond(newtet, front);
22200         }
22201         // t may be non-locally Delaunay and flipable.
22202         if (flipque != (queue *) NULL) {
22203           enqueueflipface(newtet, flipque);
22204         }
22205       }
22206     }
22207     // Let the corners of t2 point to it for fast searching.
22208     pointptr = org(newtet);
22209     setpoint2tet(pointptr, encode(newtet));
22210     pointptr = dest(newtet);
22211     setpoint2tet(pointptr, encode(newtet));
22212     pointptr = apex(newtet);
22213     setpoint2tet(pointptr, encode(newtet));
22214     pointptr = oppo(newtet);
22215     setpoint2tet(pointptr, encode(newtet));
22216   }
22217   // The cavity has been re-tetrahedralized.
22218 }
22219 
22221 //                                                                           //
22222 // delaunizecavity()    Tetrahedralize a cavity by Delaunay tetrahedra.      //
22223 //                                                                           //
22224 // The cavity C is bounded by a set of triangles in 'floorlist' (a list of   //
22225 // coplanar subfaces) and 'ceillist' (a list of tetrahedral faces lie above  //
22226 // the subfaces). 'floorptlist' and 'ceilptlist' are the vertices of C.      //
22227 //                                                                           //
22229 
22230 void tetgenmesh::delaunizecavity(list* floorlist, list* ceillist,
22231   list* ceilptlist, list* floorptlist, list* frontlist, list* misfrontlist,
22232   list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
22233 {
22234   int vertnum;
22235 
22236   vertnum = floorptlist->len();
22237   vertnum += (ceilptlist != (list *) NULL ? ceilptlist->len() : 0);
22238   if (b->verbose > 1) {
22239     printf("    Delaunizing cavity (%d floors, %d ceilings, %d vertices).\n",
22240            floorlist->len(), ceillist->len(), vertnum);
22241   }
22242   // Save the size of the largest cavity.
22243   if ((floorlist->len() + ceillist->len()) > maxcavfaces) {
22244     maxcavfaces = floorlist->len() + ceillist->len();
22245   }
22246   if (vertnum > maxcavverts) {
22247     maxcavverts = vertnum;
22248   }
22249 
22250   // Clear these lists.
22251   frontlist->clear();
22252   misfrontlist->clear();
22253   newtetlist->clear();
22254 
22255   // Initialize the cavity C.
22256   initializecavity(floorlist, ceillist, frontlist);
22257   // Form the D of the vertices of C.
22258   delaunizecavvertices(NULL, floorptlist, ceilptlist, newtetlist, flipque);    
22259   // Identify faces of C in D.
22260   while (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
22261     // Remove protecting subfaces, keep new tets.
22262     detachauxsubfaces(newtetlist);
22263     // Expand C and updateing D.
22264     expandcavity(frontlist, misfrontlist, newtetlist, crosstetlist,
22265                  missingshqueue, flipque);
22266   }
22267   // All fronts have identified in D. Get the shape of C by removing out
22268   //   tets of C. 'misfrontlist' is reused for removing out tets.
22269   carvecavity(newtetlist, misfrontlist, NULL);
22270 }
22271 
22273 //                                                                           //
22274 // formmissingregion()    Form the missing region.                           //
22275 //                                                                           //
22276 // 'missingsh' is a missing subface.  Start from it we can form the missing  //
22277 // region R (a set of connected missing subfaces).  Because all missing sub- //
22278 // faces have been marked (infected) before. R can be formed by checking the //
22279 // neighbors of 'missingsh', and the neighbors of the neighbors, and so on.  //
22280 // Stop checking further at either a segment or an unmarked subface.         //
22281 //                                                                           //
22282 // 'missingshlist' returns R. The edge ring of subfaces of R are oriented in //
22283 // the same direction. 'equatptlist' returns the vertices of R, each vertex  //
22284 // is marked with '1' (in 'worklist').                                       //
22285 //                                                                           //
22287 
22288 void tetgenmesh::formmissingregion(face* missingsh, list* missingshlist,
22289   list* equatptlist, int* worklist)
22290 {
22291   face neighsh, worksh, workseg;
22292   point workpt[3];
22293   int idx, i, j;
22294 
22295   // Add 'missingsh' into 'missingshlist'.
22296   missingshlist->append(missingsh);
22297   // Save and mark its three vertices.
22298   workpt[0] = sorg(*missingsh);
22299   workpt[1] = sdest(*missingsh);
22300   workpt[2] = sapex(*missingsh);
22301   for (i = 0; i < 3; i++) {
22302     idx = pointmark(workpt[i]) - in->firstnumber;
22303     worklist[idx] = 1;
22304     equatptlist->append(&workpt[i]);
22305   }
22306   // Temporarily uninfect it (avoid to save it again).
22307   suninfect(*missingsh);
22308   
22309   // Find the other missing subfaces.
22310   for (i = 0; i < missingshlist->len(); i++) {
22311     // Get a missing subface.
22312     worksh = * (face *)(* missingshlist)[i];
22313     // Check three neighbors of this face.
22314     for (j = 0; j < 3; j++) {
22315       sspivot(worksh, workseg);
22316       if (workseg.sh == dummysh) {
22317         spivot(worksh, neighsh);
22318         if (sinfected(neighsh)) {
22319           // Find a missing subface, adjust the face orientation.
22320           if (sorg(neighsh) != sdest(worksh)) {
22321             sesymself(neighsh);
22322           }
22323           if (b->verbose > 2) {
22324             printf("    Add missing subface (%d, %d, %d).\n", 
22325                    pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
22326                    pointmark(sapex(neighsh)));
22327           }
22328           missingshlist->append(&neighsh);
22329           // Save and mark its apex.
22330           workpt[0] = sapex(neighsh);
22331           idx = pointmark(workpt[0]) - in->firstnumber;
22332           // Has workpt[0] been added?
22333           if (worklist[idx] == 0) {
22334             worklist[idx] = 1;
22335             equatptlist->append(&workpt[0]);
22336           }
22337           // Temporarily uninfect it (avoid to save it again).
22338           suninfect(neighsh);
22339         } 
22340       } 
22341       senextself(worksh);
22342     }
22343   }
22344 
22345   // R has been formed. Infect missing subfaces again.
22346   for (i = 0; i < missingshlist->len(); i++) {
22347     worksh = * (face *)(* missingshlist)[i];
22348     sinfect(worksh);
22349   } 
22350 }
22351 
22353 //                                                                           //
22354 // rearrangesubfaces()    Rearrange the set of subfaces of a missing region  //
22355 //                        so that they conform to the faces of DT.           //
22356 //                                                                           //
22357 // The missing region formed by subfaces of 'missingshlist' contains a set   //
22358 // of degenerate vertices, hence the set of subfaces don't match the set of  //
22359 // faces in DT.  Instead of forcing them to present in DT, we re-arrange the //
22360 // connection of them so that the new subfaces conform to the faces of DT.   //
22361 // 'boundedgelist' is a set of boundary edges of the region, these edges(may //
22362 // be subsegments) must exist in DT.                                         //
22363 //                                                                           //
22364 // On completion, we have created and inserted a set of new subfaces which   //
22365 // conform to faces of DT. The set of old subfaces in 'missingshlist' are    //
22366 // deleted. The region vertices in 'equatptlist' are unmarked.               //
22367 //                                                                           //
22369 
22370 void tetgenmesh::rearrangesubfaces(list* missingshlist, list* boundedgelist,
22371   list* equatptlist, int* worklist)
22372 {
22373   link *boundedgelink;
22374   link *newshlink;
22375   triface starttet, spintet, neightet, worktet;
22376   face shloop, newsh, neighsh, spinsh, worksh;
22377   face workseg, casingin, casingout;
22378   point torg, tdest, workpt;
22379   point spt1, spt2, spt3;
22380   enum finddirectionresult collinear;
22381   enum shestype shtype;
22382   REAL area;
22383   bool matchflag, finishflag;
22384   int shmark, pbcgp, idx, hitbdry;
22385   int i, j;
22386 
22387   // Initialize the boundary edge link.
22388   boundedgelink = new link(sizeof(face), NULL, 256);
22389   // Initialize the new subface link.
22390   newshlink = new link(sizeof(face), NULL, 256);
22391   // Remember the type (skinny or not) of replaced subfaces.  They should
22392   //   all have the same type since there is no segment inside the region.
22393   worksh = * (face *)(* missingshlist)[0];
22394   shtype = shelltype(worksh);
22395   // The following loop is only for checking purpose.
22396   for (i = 1; i < missingshlist->len(); i++) {
22397     worksh = * (face *)(* missingshlist)[i];
22398     assert(shelltype(worksh) == shtype);
22399   }
22400   // To avoid compilation warnings.
22401   shmark = pbcgp = 0;
22402   area = 0.0; 
22403 
22404   // Create an initial boundary link.
22405   for (i = 0; i < boundedgelist->len(); i++) {
22406     shloop = * (face *)(* boundedgelist)[i];
22407     if (i == 0) {
22408       // 'shmark' will be set to all new created subfaces.
22409       shmark = shellmark(shloop);
22410       if (b->quality && varconstraint) {
22411         // area will be copied to all new created subfaces.
22412         area = areabound(shloop);
22413       }
22414       if (checkpbcs) {
22415         // pbcgp will be copied to all new created subfaces.
22416         pbcgp = shellpbcgroup(shloop);
22417       }
22418       // Get the abovepoint of this facet.
22419       abovepoint = facetabovepointarray[shellmark(shloop)];
22420       if (abovepoint == (point) NULL) {
22421         getfacetabovepoint(&shloop);
22422       }
22423     }
22424     sspivot(shloop, workseg);
22425     if (workseg.sh == dummysh) {
22426       // This edge is an interior edge.
22427       spivot(shloop, neighsh);
22428       boundedgelink->add(&neighsh);
22429     } else {
22430       // This side has a segment, the edge exists. 
22431       boundedgelink->add(&shloop);
22432     }
22433   }
22434 
22435   // Each edge ab of boundedgelink will be finished by finding a vertex c
22436   //   which is a vertex of the missing region, such that:
22437   //   (1) abc is inside the missing region, i.e., abc intersects at least
22438   //       one of missing subfaces (saved in missingshlist);
22439   //   (2) abc is not intersect with any previously created new subfaces
22440   //       in the missing region (saved in newshlink).
22441   //   After abc is created, it will be inserted into both the surface mesh
22442   //   and the DT. The boundedgelink will be updated, ab is removed, bc and
22443   //   ca will be added if they are open.
22444 
22445   while (boundedgelink->len() > 0) {
22446     // Remove an edge (ab) from the link.
22447     shloop = * (face *) boundedgelink->del(1);
22448     // 'workseg' indicates it is a segment or not.
22449     sspivot(shloop, workseg);
22450     torg = sorg(shloop);  // torg = a;
22451     tdest = sdest(shloop);  // tdest = b; 
22452     // Find a tetrahedron containing ab.
22453     getsearchtet(torg, tdest, &starttet, &workpt);
22454     collinear = finddirection(&starttet, workpt, tetrahedrons->items);
22455     if (collinear == LEFTCOLLINEAR) {
22456       enext2self(starttet);
22457       esymself(starttet);
22458     } else if (collinear == TOPCOLLINEAR) {
22459       fnextself(starttet);
22460       enext2self(starttet);
22461       esymself(starttet);
22462     }
22463     assert(dest(starttet) == workpt);
22464     // Checking faces around ab until a valid face is found.
22465     matchflag = false;
22466     spintet = starttet;
22467     hitbdry = 0;
22468     do {
22469       workpt = apex(spintet);
22470       idx = pointmark(workpt) - in->firstnumber;
22471       if (worklist[idx] == 1) {
22472         // (trog, tdest, workpt) is on the facet. Check if it satisfies (1).
22473         finishflag = false;
22474         for (i = 0; i < missingshlist->len(); i++) {
22475           worksh = * (face *)(* missingshlist)[i];
22476           spt1 = sorg(worksh);
22477           spt2 = sdest(worksh);
22478           spt3 = sapex(worksh);
22479           // Does bc intersect the face?
22480           if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22481               == INTERSECT) {
22482             finishflag = true; break;
22483           }
22484           // Does ca intersect the face?
22485           if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22486               == INTERSECT) {
22487             finishflag = true; break;
22488           }
22489           // Does c inside the face?
22490           if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22491               == INTERSECT) {
22492             finishflag = true; break;
22493           }
22494         }
22495         if (finishflag) {
22496           // Satisfying (1). Check if it satisfies (2).
22497           matchflag = true;
22498           for (i = 0; i < newshlink->len() && matchflag; i++) {
22499             worksh = * (face *) newshlink->getnitem(i + 1);
22500             spt1 = sorg(worksh);
22501             spt2 = sdest(worksh);
22502             spt3 = sapex(worksh);
22503             // Does bc intersect the face?
22504             if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22505                 == INTERSECT) {
22506               matchflag = false; break;
22507             }
22508             // Does ca intersect the face?
22509             if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22510                 == INTERSECT) {
22511               matchflag = false; break;
22512             }
22513             // Does c inside the face?
22514             if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22515                 == INTERSECT) {
22516               matchflag = false; break;
22517             }
22518           }
22519         }
22520         if (matchflag == true) {
22521           // Satisfying both (1) and (2). Find abc.
22522           break;
22523         }
22524       }
22525       if (!fnextself(spintet)) {
22526         hitbdry ++;
22527         if (hitbdry < 2) {
22528           esym(starttet, spintet);
22529           if (!fnextself(spintet)) {
22530             hitbdry ++;
22531           }
22532         }
22533       }
22534     } while (hitbdry < 2 && apex(spintet) != apex(starttet));
22535     assert(matchflag == true);
22536     tspivot(spintet, neighsh);
22537     if (neighsh.sh != dummysh) {
22538       printf("Error:  Invalid PLC.\n");
22539       printf("  Facet #%d and facet #%d overlap each other.\n",
22540              shellmark(neighsh), shellmark(shloop));
22541       printf("  It might be caused by a facet is defined more than once.\n");
22542       printf("  Hint:  Use -d switch to find all overlapping facets.\n");
22543       exit(1);
22544     }
22545     // The side of 'spintet' is at which a new subface will be attached.
22546     adjustedgering(spintet, CCW);
22547     // Create the new subface.
22548     makeshellface(subfaces, &newsh);
22549     setsorg(newsh, org(spintet));
22550     setsdest(newsh, dest(spintet));
22551     setsapex(newsh, apex(spintet));
22552     if (b->quality && varconstraint) {
22553       setareabound(newsh, area);
22554     }
22555     if (checkpbcs) {
22556       setshellpbcgroup(newsh, pbcgp);
22557     }
22558     setshellmark(newsh, shmark);
22559     setshelltype(newsh, shtype);  // It may be a skinny subface.
22560     // Add newsh into newshlink for intersecting checking.
22561     newshlink->add(&newsh);
22562     // Insert it into the current mesh.
22563     tsbond(spintet, newsh);
22564     sym(spintet, neightet);
22565     if (neightet.tet != dummytet) {
22566       sesym(newsh, neighsh);
22567       tsbond(neightet, neighsh);
22568     }
22569     // Insert it into the surface mesh.
22570     sspivot(shloop, workseg);
22571     if (workseg.sh == dummysh) {
22572       sbond(shloop, newsh);
22573     } else {
22574       // There is a subsegment, 'shloop' is the subface which is going to
22575       //   die. Insert the 'newsh' at the place of 'shloop' into its face
22576       //   link, so as to dettach 'shloop'.   The original connection is:
22577       //   -> casingin -> shloop -> casingout ->, it will be changed with:
22578       //   -> casingin ->  newsh -> casingout ->.  Pay attention to the
22579       //   case when this subsegment is dangling in the mesh, i.e., 'shloop'
22580       //   is bonded to itself.
22581       spivot(shloop, casingout);
22582       if (shloop.sh != casingout.sh) {
22583         // 'shloop' is not bonded to itself.
22584         spinsh = casingout;
22585         do {
22586           casingin = spinsh;
22587           spivotself(spinsh);
22588         } while (sapex(spinsh) != sapex(shloop));
22589         assert(casingin.sh != shloop.sh); 
22590         // Bond casingin -> newsh -> casingout.
22591         sbond1(casingin, newsh);
22592         sbond1(newsh, casingout);
22593       } else {
22594         // Bond newsh -> newsh.
22595         sbond(newsh, newsh);
22596       }
22597       // Bond the segment.
22598       ssbond(newsh, workseg);
22599     }
22600     // Check other two sides of this new subface.  If a side is not bonded
22601     //   to any edge in the link, it will be added to the link.
22602     for (i = 0; i < 2; i++) {
22603       if (i == 0) {
22604         senext(newsh, worksh);
22605       } else {
22606         senext2(newsh, worksh);
22607       }
22608       torg = sorg(worksh);
22609       tdest = sdest(worksh);
22610       finishflag = false;
22611       for (j = 0; j < boundedgelink->len() && !finishflag; j++) {
22612         neighsh = * (face *) boundedgelink->getnitem(j + 1);
22613         if ((sorg(neighsh) == torg && sdest(neighsh) == tdest) ||
22614             (sorg(neighsh) == tdest && sdest(neighsh) == torg)) {
22615           // Find a boundary edge.  Bond them and exit the loop.
22616           sspivot(neighsh, workseg);
22617           if (workseg.sh == dummysh) {
22618             sbond(neighsh, worksh);
22619           } else {
22620             // There is a subsegment, 'neighsh' is the subface which is
22621             //   going to die. Do the same as above for 'worksh'.
22622             spivot(neighsh, casingout);
22623             if (neighsh.sh != casingout.sh) {
22624               // 'neighsh' is not bonded to itself.
22625               spinsh = casingout;
22626               do {
22627                 casingin = spinsh;
22628                 spivotself(spinsh);
22629               } while (sapex(spinsh) != sapex(neighsh));
22630               assert(casingin.sh != neighsh.sh); 
22631               // Bond casingin -> worksh -> casingout.
22632               sbond1(casingin, worksh);
22633               sbond1(worksh, casingout);
22634             } else {
22635               // Bond worksh -> worksh.
22636               sbond(worksh, worksh);
22637             }
22638             // Bond the segment.
22639             ssbond(worksh, workseg);
22640           }
22641           // Remove this boundary edge from the link.
22642           boundedgelink->del(j + 1);
22643           finishflag = true;
22644         }
22645       }
22646       if (!finishflag) {
22647         // It's a new boundary edge, add it to link.
22648         boundedgelink->add(&worksh);
22649       }
22650     }
22651   }
22652 
22653   // Deallocate the set of old missing subfaces.
22654   for (i = 0; i < missingshlist->len(); i++) {
22655     worksh = * (face *)(* missingshlist)[i];
22656     shellfacedealloc(subfaces, worksh.sh);
22657   }
22658   // Unmark region vertices in 'worklist'.
22659   for (i = 0; i < equatptlist->len(); i++) {
22660     workpt = * (point *)(* equatptlist)[i];
22661     idx = pointmark(workpt) - in->firstnumber;
22662     worklist[idx] = 0;
22663   }
22664 
22665   delete boundedgelink;
22666   delete newshlink;
22667 }
22668 
22670 //                                                                           //
22671 // scoutcrossingedge()    Search an edge crossing the missing region.        //
22672 //                                                                           //
22673 // 'missingshlist' forms the missing region R. This routine searches for an  //
22674 // edge crossing R.  It first forms a 'boundedgelist' consisting of the      //
22675 // boundary edges of R. Such edges are existing in CDT.  A crossing edge is  //
22676 // found by rotating faces around one of the boundary edges. It is possible  //
22677 // there is no edge crosses R (e.g. R has a degenerate point set).           //
22678 //                                                                           //
22679 // If find a croosing edge, return TRUE, 'crossedgelist' contains this edge. //
22680 // Otherwise, return FALSE.                                                  //
22681 //                                                                           //
22683 
22684 bool tetgenmesh::scoutcrossingedge(list* missingshlist, list* boundedgelist,
22685   list* crossedgelist, int* worklist)
22686 {
22687   triface starttet, spintet, worktet;
22688   face startsh, neighsh, worksh, workseg;
22689   point torg, tdest, tapex;
22690   point workpt[3], pa, pb, pc;
22691   enum finddirectionresult collinear;
22692   REAL ori1, ori2;
22693   bool crossflag;
22694   int hitbdry;
22695   int i, j, k;
22696 
22697   // Form the 'boundedgelist'. Loop through 'missingshlist', check each
22698   //   edge of these subfaces. If an edge is a segment or the neighbor
22699   //   subface is uninfected, add it to 'boundedgelist'.
22700   for (i = 0; i < missingshlist->len(); i++) {
22701     worksh = * (face *)(* missingshlist)[i];
22702     for (j = 0; j < 3; j++) {
22703       sspivot(worksh, workseg);
22704       if (workseg.sh == dummysh) {
22705         spivot(worksh, neighsh);
22706         if (!sinfected(neighsh)) {
22707           boundedgelist->append(&worksh);
22708         }
22709       } else {
22710         boundedgelist->append(&worksh);
22711       }
22712       senextself(worksh);
22713     }
22714   }
22715 
22716   crossflag = false;
22717   // Find a crossing edge. It is possible there is no such edge. We need to
22718   //   loop through all edges of 'boundedgelist' for sure we don't miss any.
22719   for (i = 0; i < boundedgelist->len() && !crossflag; i++) {
22720     startsh = * (face *)(* boundedgelist)[i];
22721     // 'startsh' (abc) holds an existing edge of the DT, find it.
22722     torg = sorg(startsh);
22723     tdest = sdest(startsh);
22724     tapex = sapex(startsh);
22725     getsearchtet(torg, tdest, &starttet, &workpt[0]);
22726     collinear = finddirection(&starttet, workpt[0], tetrahedrons->items);
22727     if (collinear == LEFTCOLLINEAR) {
22728       enext2self(starttet);
22729       esymself(starttet);
22730     } else if (collinear == TOPCOLLINEAR) {
22731       fnextself(starttet);
22732       enext2self(starttet);
22733       esymself(starttet);
22734     }
22735 #ifdef SELF_CHECK
22736     assert(dest(starttet) == workpt[0]);
22737 #endif
22738     // Now starttet holds edge ab. Find is edge de crossing R.
22739     spintet = starttet;
22740     hitbdry = 0;
22741     do {
22742       if (fnextself(spintet)) {
22743         // splittet = abde. Check if de crosses abc.
22744         workpt[1] = apex(spintet);  // workpt[1] = d.
22745         workpt[2] = oppo(spintet);  // workpt[2] = e.
22746         j = pointmark(workpt[1]) - in->firstnumber;
22747         k = pointmark(workpt[2]) - in->firstnumber;
22748         if (worklist[j] == 1) {
22749           ori1 = 0.0; // d is a vertex of the missing region.
22750         } else {
22751           // Get the orientation of d wrt. abc.
22752           ori1 = orient3d(torg, tdest, tapex, workpt[1]);
22753         }
22754         if (worklist[k] == 1) {
22755           ori2 = 0.0; // e is a vertex of the missing region.
22756         } else {
22757           // Get the orientation of e wrt. abc.
22758           ori2 = orient3d(torg, tdest, tapex, workpt[2]);
22759         }
22760         // Only do check if d and e locate on different sides of abc.
22761         if (ori1 * ori2 < 0.0) {
22762           // Check if de crosses any subface of R.
22763           for (j = 0; j < missingshlist->len(); j++) {
22764             worksh = * (face *)(* missingshlist)[j];
22765             pa = sorg(worksh);
22766             pb = sdest(worksh);
22767             pc = sapex(worksh);
22768             crossflag = (tri_tri_inter(pa, pb, pc, workpt[0], workpt[1],
22769                                        workpt[2]) == INTERSECT);
22770             if (crossflag) {
22771               // Find a crossing edge. We're done.
22772               worktet = spintet;
22773               adjustedgering(worktet, CCW);
22774               enextfnextself(worktet);
22775               enextself(worktet);
22776               // Add this edge (worktet) into 'crossedgelist'.
22777               crossedgelist->append(&worktet);
22778               break;
22779             }
22780           }
22781           if (crossflag) break;
22782         }
22783         if (apex(spintet) == apex(starttet)) break;
22784       } else {
22785         hitbdry++;
22786         // It is only possible to hit boundary once.
22787         if (hitbdry < 2) {
22788           esym(starttet, spintet);
22789         }
22790       }
22791     } while (hitbdry < 2);
22792   }
22793 
22794   return crossflag;
22795 }
22796 
22798 //                                                                           //
22799 // formcavity()    Form the cavity for recovering the missing region.        //
22800 //                                                                           //
22801 // The cavity C is bounded by faces of current CDT.  All tetrahedra inside C //
22802 // will be removed, intead a set of constrained Delaunay tetrahedra will be  //
22803 // filled in and the missing region are recovered.                           //
22804 //                                                                           //
22805 // 'missingshlist' contains a set of subfaces forming the missing region R.  //
22806 // C is formed by first finding all the tetrahedra in CDT that intersect the //
22807 // relative interior of R; then deleting them from the CDT, this will form C //
22808 // inside the CDT. At the beginning, 'crossedgelist' contains an edge which  //
22809 // is crossing R. All tets containing this edge must cross R. Start from it, //
22810 // other crossing edges can be found incrementally.  The discovered crossing //
22811 // tets are saved in 'crosstetlist'.                                         //
22812 //                                                                           //
22813 // Notice that not all tets in 'crosstetlist' are crossing R. The discovered //
22814 // tets are connected each other. However, there may be other tets crossing  //
22815 // R but disjoint with the found tets. Due to this fact we need to check the //
22816 // 'missingshlist' once more. Only recover those subfaces which are crossed  //
22817 // by the set of discovered tets, i.e., R may be shrinked to conform the set //
22818 // of discovered tets. The extra subfaces of R will be recovered later.      //
22819 //                                                                           //
22820 // Notice that some previous recovered subfaces may completely included in C.//
22821 // This can happen when R is very big and these subfaces lie above R and so  //
22822 // close to it. Such subfaces have to be queued (and sinfected()) to recover //
22823 // them later. Otherwise, we lost the connection to these subfaces forever.  //
22824 //                                                                           //
22826 
22827 void tetgenmesh::formcavity(list* missingshlist, list* crossedgelist,
22828   list* equatptlist, list* crossshlist, list* crosstetlist,
22829   list* belowfacelist, list* abovefacelist, list* horizptlist,
22830   list* belowptlist, list* aboveptlist, queue* missingshqueue, int* worklist)
22831 {
22832   triface starttet, spintet, neightet, worktet;
22833   face startsh, neighsh, worksh, workseg;
22834   point torg, tdest, tapex, workpt[3];
22835   REAL checksign, orgori, destori;
22836   bool crossflag, inlistflag;
22837   bool belowflag, aboveflag;
22838   int idx, share;
22839   int i, j, k;
22840 
22841   // Get a face at horizon.
22842   startsh = * (face *)(* missingshlist)[0];
22843   torg = sorg(startsh);
22844   tdest = sdest(startsh);
22845   tapex = sapex(startsh);
22846 
22847   // Collect the set of crossing tetrahedra by rotating crossing edges.
22848   for (i = 0; i < crossedgelist->len(); i++) {
22849     // Get a tet abcd, ab is a crossing edge.
22850     starttet = * (triface *)(* crossedgelist)[i];
22851     adjustedgering(starttet, CCW);
22852     if (b->verbose > 2) {
22853       printf("    Collect tets containing edge (%d, %d).\n",
22854              pointmark(org(starttet)), pointmark(dest(starttet)));
22855     }
22856     orgori = orient3d(torg, tdest, tapex, org(starttet));
22857     destori = orient3d(torg, tdest, tapex, dest(starttet));
22858 #ifdef SELF_CHECK
22859     assert(orgori * destori < 0.0); 
22860 #endif
22861     spintet = starttet;
22862     do {
22863       // The face rotation should not meet boundary.
22864       fnextself(spintet); 
22865       // Check the validity of the PLC.
22866       tspivot(spintet, worksh);
22867       if (worksh.sh != dummysh) {
22868         printf("Error:  Invalid PLC.\n");
22869         printf("  Two subfaces (%d, %d, %d) and (%d, %d, %d)\n",
22870                pointmark(torg), pointmark(tdest), pointmark(tapex),
22871                pointmark(sorg(worksh)), pointmark(sdest(worksh)),
22872                pointmark(sapex(worksh)));
22873         printf("  are found intersecting each other.\n");
22874         printf("  Hint:  Use -d switch to find all intersecting facets.\n");
22875         terminatetetgen(1);
22876       }
22877       if (!infected(spintet)) {
22878         if (b->verbose > 2) {
22879           printf("      Add crossing tet (%d, %d, %d, %d).\n",
22880                  pointmark(org(spintet)), pointmark(dest(spintet)),
22881                  pointmark(apex(spintet)), pointmark(oppo(spintet)));
22882         }
22883         infect(spintet);
22884         crosstetlist->append(&spintet);
22885       }
22886       // Check whether other two edges of 'spintet' is a crossing edge.
22887       //   It can be quickly checked from the apex of 'spintet', if it is
22888       //   not on the facet, then there exists a crossing edge.
22889       workpt[0] = apex(spintet);
22890       idx = pointmark(workpt[0]) - in->firstnumber;
22891       if (worklist[idx] != 1) {
22892         // Either edge (dest, apex) or edge (apex, org) crosses.
22893         checksign = orient3d(torg, tdest, tapex, workpt[0]);
22894 #ifdef SELF_CHECK
22895         assert(checksign != 0.0);
22896 #endif
22897         if (checksign * orgori < 0.0) {
22898           enext2(spintet, worktet); // edge (apex, org).
22899           workpt[1] = org(spintet);
22900         } else {
22901 #ifdef SELF_CHECK
22902           assert(checksign * destori < 0.0);
22903 #endif
22904           enext(spintet, worktet);  // edge (dest, apex).
22905           workpt[1] = dest(spintet);
22906         }
22907         // 'worktet' represents the crossing edge. Add it into list only
22908         //   it doesn't exist in 'crossedgelist'.
22909         inlistflag = false;
22910         for (j = 0; j < crossedgelist->len() && !inlistflag; j++) {
22911           neightet = * (triface *)(* crossedgelist)[j];
22912           if (org(neightet) == workpt[0]) {
22913             if (dest(neightet) == workpt[1]) inlistflag = true;
22914           } else if (org(neightet) == workpt[1]) {
22915             if (dest(neightet) == workpt[0]) inlistflag = true;
22916           }
22917         }
22918         if (!inlistflag) {
22919           crossedgelist->append(&worktet);
22920         }
22921       }
22922     } while (apex(spintet) != apex(starttet));
22923   }
22924 
22925   // Identifying the boundary faces and vertices of C. Sort them into
22926   //   'abovefacelist', 'aboveptlist, 'belowfacelist', and 'belowptlist',
22927   //    respectively. "above" and "below" are wrt.(torg, tdest, tapex). 
22928   for (i = 0; i < crosstetlist->len(); i++) {
22929     // Get a tet abcd, ab is the crossing edge.
22930     starttet = * (triface *)(* crosstetlist)[i];
22931 #ifdef SELF_CHECK
22932     assert(infected(starttet));
22933 #endif
22934     adjustedgering(starttet, CCW);
22935     // abc and abd are sharing the crossing edge, the two neighbors must
22936     //   be crossing tetrahedra too. They can't be boundaries of C.
22937     for (j = 0; j < 2; j++) {
22938       if (j == 0) {
22939         enextfnext(starttet, worktet); // Check bcd.
22940       } else {
22941         enext2fnext(starttet, worktet); // Check acd. 
22942       } 
22943       sym(worktet, neightet);
22944       // If the neighbor doesn't exist or exists but doesn't be infected,
22945       //   it's a boundary face of C, save it.
22946       if ((neightet.tet == dummytet) || !infected(neightet)) {
22947         workpt[0] = org(worktet);
22948         workpt[1] = dest(worktet);
22949         workpt[2] = apex(worktet);
22950         belowflag = aboveflag = false;
22951         share = 0;
22952         for (k = 0; k < 3; k++) {
22953           idx = pointmark(workpt[k]) - in->firstnumber;
22954           if (worklist[idx] == 0) {
22955             // It's not a vertices of facet, find which side it lies.
22956             checksign = orient3d(torg, tdest, tapex, workpt[k]);
22957 #ifdef SELF_CHECK
22958             assert(checksign != 0.0);
22959 #endif
22960             if (checksign > 0.0) {
22961               // It lies "below" the facet wrt. 'startsh'.
22962               worklist[idx] = 2;
22963               belowptlist->append(&workpt[k]);
22964             } else if (checksign < 0.0) {
22965               // It lies "above" the facet wrt. 'startsh'.
22966               worklist[idx] = 3;
22967               aboveptlist->append(&workpt[k]);
22968             }
22969           }
22970           if (worklist[idx] == 2) {
22971             // This face lies "below" the facet wrt. 'startsh'.
22972             belowflag = true;
22973           } else if (worklist[idx] == 3) {
22974             // This face lies "above" the facet wrt. 'startsh'.
22975             aboveflag = true;
22976           } else {
22977 #ifdef SELF_CHECK
22978             // In degenerate case, this face may just be the equator.
22979             assert(worklist[idx] == 1);
22980 #endif
22981             share++;
22982           }
22983         }
22984 #ifdef SELF_CHECK
22985         // The degenerate case has been ruled out.
22986         assert(share < 3);
22987         // Only one flag is possible for a cavity face.
22988         assert(belowflag ^ aboveflag); 
22989 #endif
22990         if (belowflag) {
22991           belowfacelist->append(&worktet);
22992         } else if (aboveflag) {
22993           abovefacelist->append(&worktet);
22994         }
22995       }
22996     }
22997   }
22998 
22999   // Shrink R if not all its subfaces are crossing by the discovered tets.
23000   //   'crossshlist' and 'horizptlist' represent the set of subfaces and
23001   //   vertices of the shrinked missing region, respectively.
23002   for (i = 0; i < missingshlist->len(); i++) {
23003     worksh = * (face *)(* missingshlist)[i];
23004 #ifdef SELF_CHECK
23005     assert(sinfected(worksh));
23006 #endif
23007     workpt[0] = sorg(worksh);
23008     workpt[1] = sdest(worksh);
23009     workpt[2] = sapex(worksh);
23010     crossflag = false;
23011     for (j = 0; j < crosstetlist->len() && !crossflag; j++) {
23012       // Get a tet abcd, ab is a crossing edge.
23013       starttet = * (triface *)(* crosstetlist)[j];
23014       adjustedgering(starttet, CCW);
23015       // Only need to check two sides of worktet.
23016       for (k = 0; k < 2 && !crossflag; k++) {
23017         if (k == 0) {
23018           worktet = starttet; // Check abc.
23019         } else {
23020           fnext(starttet, worktet); // Check abd.
23021         }
23022         crossflag = tritritest(&worktet, workpt[0], workpt[1], workpt[2]);
23023       }
23024     }
23025     if (crossflag) {
23026       // 'worksh' is crossed by 'worktet', uninfect it.
23027       suninfect(worksh);
23028       crossshlist->append(&worksh);
23029       // Add its corners into 'horizptlist'.
23030       for (k = 0; k < 3; k++) {
23031         idx = pointmark(workpt[k]) - in->firstnumber;
23032         if (worklist[idx] != 4) {
23033           worklist[idx] = 4;
23034           horizptlist->append(&workpt[k]);
23035         }
23036       }
23037     } 
23038   }
23039 
23040   // Check 'crossingtetlist'. Queue subfaces inside them.
23041   for (i = 0; i < crosstetlist->len(); i++) {
23042     starttet = * (triface *)(* crosstetlist)[i];
23043     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
23044       sym(starttet, neightet);
23045       // If the neighbor exist and is infected, check it.
23046       if ((neightet.tet != dummytet) && infected(neightet)) {
23047         tspivot(starttet, worksh);
23048         if (worksh.sh != dummysh) {
23049           // Temporarily remove worksh. Make it missing. recover it later.
23050           if (b->verbose > 2) {
23051             printf("    Queuing subface (%d, %d, %d).\n",
23052                    pointmark(sorg(worksh)), pointmark(sdest(worksh)),
23053                    pointmark(sapex(worksh)));
23054           }
23055           tsdissolve(neightet);
23056           tsdissolve(starttet);
23057           // Detach tets at the both sides of this subface.
23058           stdissolve(worksh);
23059           sesymself(worksh);
23060           stdissolve(worksh);
23061           sinfect(worksh);
23062           missingshqueue->push(&worksh);
23063         }
23064       }
23065     }
23066   }
23067 
23068   // Clear flags set in 'worklist'.
23069   for (i = 0; i < equatptlist->len(); i++) {
23070     workpt[0] = * (point *)(* equatptlist)[i];
23071     idx = pointmark(workpt[0]) - in->firstnumber;
23072 #ifdef SELF_CHECK
23073     assert((worklist[idx] == 1) || (worklist[idx] == 4));
23074 #endif
23075     worklist[idx] = 0;
23076   }
23077   for (i = 0; i < belowptlist->len(); i++) {
23078     workpt[0] = * (point *)(* belowptlist)[i];
23079     idx = pointmark(workpt[0]) - in->firstnumber;
23080 #ifdef SELF_CHECK
23081     assert(worklist[idx] == 2);
23082 #endif
23083     worklist[idx] = 0;
23084   }
23085   for (i = 0; i < aboveptlist->len(); i++) {
23086     workpt[0] = * (point *)(* aboveptlist)[i];
23087     idx = pointmark(workpt[0]) - in->firstnumber;
23088 #ifdef SELF_CHECK
23089     assert(worklist[idx] == 3);
23090 #endif
23091     worklist[idx] = 0;
23092   }
23093 }
23094 
23096 //                                                                           //
23097 // insertallsubfaces()    Insert all subfaces, queue missing subfaces.       //
23098 //                                                                           //
23099 // Loop through all subfaces, insert each into the DT. If one already exists,//
23100 // bond it to the tetrahedra having it. Otherwise, it is missing, infect it  //
23101 // and save it in 'missingshqueue'.                                          //
23102 //                                                                           //
23104 
23105 void tetgenmesh::insertallsubfaces(queue* missingshqueue)
23106 {
23107   triface searchtet;
23108   face subloop;
23109 
23110   searchtet.tet = (tetrahedron *) NULL;
23111   subfaces->traversalinit();
23112   subloop.sh = shellfacetraverse(subfaces);
23113   while (subloop.sh != (shellface *) NULL) {
23114     if (!insertsubface(&subloop, &searchtet)) {
23115       if (b->verbose > 1) {
23116         printf("    Queuing subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23117                pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23118       }
23119       sinfect(subloop);
23120       missingshqueue->push(&subloop);
23121     }
23122     subloop.sh = shellfacetraverse(subfaces);
23123   }
23124 }
23125 
23127 //                                                                           //
23128 // constrainedfacets()    Recover subfaces in a Delaunay tetrahedralization. //
23129 //                                                                           //
23130 // This routine creates a CDT by incrementally updating a DT D into a CDT T. //
23131 // The process of recovering facets can be imagined by "merging" the surface //
23132 // mesh F into D. At the beginning, F and D are completely seperated.  Some  //
23133 // faces of them are matching some are not because they are crossed by some  //
23134 // tetrahedra of D. The non-matching subfaces will be forced to appear in T  //
23135 // by locally retetrahedralizing the regions where F and D are intersecting. //
23136 //                                                                           //
23137 // When a subface s of F is found missing in D, probably some other subfaces //
23138 // near to s are missing too.  The set of adjoining coplanar missing faces   //
23139 // forms a missing region R (R may not simply connected).                    //
23140 //                                                                           //
23141 // There are two possibilities can result a mssing region R: (1) Some edges  //
23142 // of D cross R; (2) No edge of D crosses R, but some faces of D spans R, ie,//
23143 // D is locally degenerate at R. In case (1), D is modified so that it resp- //
23144 // ects R (done by a cavity retetrahedralization algorithm).  In case (2), F //
23145 // is modified so that the set of subfaces of R matches faces in D (done by  //
23146 // a face rearrangment algorithm).                                           //
23147 //                                                                           //
23149 
23150 void tetgenmesh::constrainedfacets()
23151 {
23152   queue *missingshqueue, *flipque;
23153   list *missingshlist, *equatptlist;
23154   list *boundedgelist, *crossedgelist, *crosstetlist;
23155   list *crossshlist, *belowfacelist, *abovefacelist;
23156   list *horizptlist, *belowptlist, *aboveptlist;
23157   list *frontlist, *misfrontlist, *newtetlist;
23158   triface searchtet, worktet;
23159   face subloop, worksh;
23160   int *worklist;
23161   int i;
23162 
23163   if (!b->quiet) {
23164     printf("Constraining facets.\n");
23165   }
23166 
23167   // Initialize queues.
23168   missingshqueue = new queue(sizeof(face));
23169   flipque = new queue(sizeof(badface));
23170   // Initialize the working lists.
23171   missingshlist = new list(sizeof(face), NULL);
23172   boundedgelist = new list(sizeof(face), NULL);
23173   crossedgelist = new list(sizeof(triface), NULL);
23174   equatptlist = new list((char*) "point *");
23175   crossshlist = new list(sizeof(face), NULL);
23176   crosstetlist = new list(sizeof(triface), NULL);
23177   belowfacelist = new list(sizeof(triface), NULL);
23178   abovefacelist = new list(sizeof(triface), NULL);
23179   horizptlist = new list((char*)"point *");
23180   belowptlist = new list((char*)"point *");
23181   aboveptlist = new list((char*)"point *");
23182   frontlist = new list(sizeof(triface), NULL);
23183   misfrontlist = new list(sizeof(triface), NULL);
23184   newtetlist = new list(sizeof(triface), NULL);
23185   // Initialize the array for marking vertices.
23186   worklist = new int[points->items + 1];
23187   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
23188 
23189   // Compute a mapping from points to tetrahedra for fast searching.
23190   makepoint2tetmap();
23191   
23192   // Match subfaces in D, queue all missing subfaces.
23193   insertallsubfaces(missingshqueue);
23194 
23195   // Recover all missing subfaces.
23196   while (!missingshqueue->empty()) {
23197     // Get a queued face s.
23198     subloop = * (face *) missingshqueue->pop();
23199     // s may have been deleted in a face rearrangment operation.
23200     if (isdead(&subloop)) continue;
23201     // s may have been recovered in a previous missing region.
23202     if (!sinfected(subloop)) continue;
23203     // s may match a face in D now due to previous transformations.
23204     if (insertsubface(&subloop, &searchtet)) {
23205       suninfect(subloop);
23206       continue;
23207     }
23208     if (b->verbose > 1) {
23209       printf("    Recover subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23210              pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23211     }
23212     // Form the missing region R containing s.
23213     formmissingregion(&subloop, missingshlist, equatptlist, worklist);
23214     // Is R crossing by any tetrahedron?
23215     if (scoutcrossingedge(missingshlist, boundedgelist, crossedgelist,
23216                           worklist)) {
23217       // Form the cavity C containing R.
23218       formcavity(missingshlist, crossedgelist, equatptlist, crossshlist,
23219                  crosstetlist, belowfacelist, abovefacelist, horizptlist,
23220                  belowptlist, aboveptlist, missingshqueue, worklist);
23221       // Recover the above part of C.
23222       delaunizecavity(crossshlist, abovefacelist, aboveptlist, horizptlist,
23223                       frontlist, misfrontlist, newtetlist, crosstetlist,
23224                       missingshqueue, flipque);
23225       // Inverse the direction of subfaces in R.
23226       for (i = 0; i < crossshlist->len(); i++) {
23227         worksh = * (face *)(* crossshlist)[i];
23228         sesymself(worksh);
23229         * (face *)(* crossshlist)[i] = worksh;
23230       }
23231       // Recover the below part of C.
23232       delaunizecavity(crossshlist, belowfacelist, belowptlist, horizptlist,
23233                       frontlist, misfrontlist, newtetlist, crosstetlist,
23234                       missingshqueue, flipque);
23235       // Delete tetrahedra in C.
23236       for (i = 0; i < crosstetlist->len(); i++) {
23237         worktet = * (triface *)(* crosstetlist)[i];
23238         tetrahedrondealloc(worktet.tet);
23239       }
23240       // There may have some un-recovered subfaces of R. Put them back into
23241       //   queue. Otherwise, they will be missing on the boundary.
23242       for (i = 0; i < missingshlist->len(); i++) {
23243         worksh = * (face *)(* missingshlist)[i];
23244         if (sinfected(worksh)) {
23245           // An unrecovered subface, put it back into queue.
23246           missingshqueue->push(&worksh);
23247         }
23248       }
23249       crossshlist->clear();
23250       belowfacelist->clear();
23251       abovefacelist->clear();
23252       horizptlist->clear();
23253       belowptlist->clear();
23254       aboveptlist->clear();
23255       crosstetlist->clear();
23256     } else {
23257       // No. Rearrange subfaces of F conforming to that of D in R. It can
23258       //   happen when the facet has non-coplanar vertices.
23259       rearrangesubfaces(missingshlist, boundedgelist, equatptlist, worklist);
23260     }
23261     // Clear all working lists.
23262     missingshlist->clear();
23263     boundedgelist->clear();
23264     crossedgelist->clear();
23265     equatptlist->clear();
23266   }
23267 
23268   // Subfaces have been merged into D.
23269   checksubfaces = 1;
23270 
23271   if (b->verbose > 0) {
23272     printf("  The biggest cavity: %d faces, %d vertices\n", maxcavfaces,
23273            maxcavverts);
23274     printf("  Enlarged %d times\n", expcavcount);
23275   }
23276 
23277   delete missingshqueue;
23278   delete flipque;
23279   delete missingshlist;
23280   delete boundedgelist;
23281   delete crossedgelist;
23282   delete equatptlist;
23283   delete crossshlist;
23284   delete crosstetlist;
23285   delete belowfacelist;
23286   delete abovefacelist;
23287   delete horizptlist;
23288   delete belowptlist;
23289   delete aboveptlist;
23290   delete frontlist;
23291   delete misfrontlist;
23292   delete newtetlist;
23293   delete [] worklist;
23294 }
23295 
23296 //
23297 // End of facet recovery routines
23298 //
23299 
23300 //
23301 // Begin of carving out holes and concavities routines
23302 //
23303 
23305 //                                                                           //
23306 // infecthull()    Virally infect all of the tetrahedra of the convex hull   //
23307 //                 that are not protected by subfaces.  Where there are      //
23308 //                 subfaces, set boundary markers as appropriate.            //
23309 //                                                                           //
23310 // Memorypool 'viri' is used to return all the infected tetrahedra.          //
23311 //                                                                           //
23313 
23314 void tetgenmesh::infecthull(memorypool *viri)
23315 {
23316   triface tetloop, tsymtet;
23317   tetrahedron **deadtet;
23318   face hullface;
23319   // point horg, hdest, hapex;
23320 
23321   if (b->verbose > 0) {
23322     printf("  Marking concavities for elimination.\n");
23323   }
23324   tetrahedrons->traversalinit();
23325   tetloop.tet = tetrahedrontraverse();
23326   while (tetloop.tet != (tetrahedron *) NULL) {
23327     // Is this tetrahedron on the hull?
23328     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
23329       sym(tetloop, tsymtet);
23330       if (tsymtet.tet == dummytet) {
23331         // Is the tetrahedron protected by a subface?
23332         tspivot(tetloop, hullface);
23333         if (hullface.sh == dummysh) {
23334           // The tetrahedron is not protected; infect it.
23335           if (!infected(tetloop)) {
23336             infect(tetloop);
23337             deadtet = (tetrahedron **) viri->alloc();
23338             *deadtet = tetloop.tet;
23339             break;  // Go and get next tet.
23340           }
23341         } else {
23342           // The tetrahedron is protected; set boundary markers if appropriate.
23343           if (shellmark(hullface) == 0) {
23344             setshellmark(hullface, 1);
23345             /*
23346             horg = sorg(hullface);
23347             hdest = sdest(hullface);
23348             hapex = sapex(hullface);
23349             if (pointmark(horg) == 0) {
23350               setpointmark(horg, 1);
23351             }
23352             if (pointmark(hdest) == 0) {
23353               setpointmark(hdest, 1);
23354             }
23355             if (pointmark(hapex) == 0) {
23356               setpointmark(hapex, 1);
23357             }
23358             */
23359           }
23360         }
23361       }
23362     }
23363     tetloop.tet = tetrahedrontraverse();
23364   }
23365 }
23366 
23368 //                                                                           //
23369 // plague()    Spread the virus from all infected tets to any neighbors not  //
23370 //             protected by subfaces.                                        //
23371 //                                                                           //
23372 // This routine identifies all the tetrahedra that will die, and marks them  //
23373 // as infected.  They are marked to ensure that each tetrahedron is added to //
23374 // the virus pool only once, so the procedure will terminate. 'viri' returns //
23375 // all infected tetrahedra which are outside the domian.                     //
23376 //                                                                           //
23378 
23379 void tetgenmesh::plague(memorypool *viri)
23380 {
23381   tetrahedron **virusloop;
23382   tetrahedron **deadtet;
23383   triface testtet, neighbor;
23384   face neighsh, testseg;
23385   face spinsh, casingin, casingout;
23386   int firstdadsub;
23387   int i;
23388 
23389   if (b->verbose > 0) {
23390     printf("  Marking neighbors of marked tetrahedra.\n");
23391   }
23392   firstdadsub = 0;
23393   // Loop through all the infected tetrahedra, spreading the virus to
23394   //   their neighbors, then to their neighbors' neighbors.
23395   viri->traversalinit();
23396   virusloop = (tetrahedron **) viri->traverse();
23397   while (virusloop != (tetrahedron **) NULL) {
23398     testtet.tet = *virusloop;
23399     // Temporarily uninfect this tetrahedron, not necessary.
23400     uninfect(testtet);
23401     // Check each of the tetrahedron's four neighbors.
23402     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23403       // Find the neighbor.
23404       sym(testtet, neighbor);
23405       // Check for a shell between the tetrahedron and its neighbor.
23406       tspivot(testtet, neighsh);
23407       // Check if the neighbor is nonexistent or already infected.
23408       if ((neighbor.tet == dummytet) || infected(neighbor)) {
23409         if (neighsh.sh != dummysh) {
23410           // There is a subface separating the tetrahedron from its neighbor,
23411           //   but both tetrahedra are dying, so the subface dies too.
23412           // Before deallocte this subface, dissolve the connections between
23413           //   other subfaces, subsegments and tetrahedra.
23414           neighsh.shver = 0;
23415           if (!firstdadsub) {
23416             firstdadsub = 1; // Report the problem once.
23417             if (!b->quiet) {
23418               printf("Warning:  Detecting an open face (%d, %d, %d).\n",
23419                      pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
23420                      pointmark(sapex(neighsh)));
23421             }
23422           }
23423           // For keep the same enext() direction.
23424           findedge(&testtet, sorg(neighsh), sdest(neighsh));
23425           for (i = 0; i < 3; i++) {
23426             sspivot(neighsh, testseg);
23427             if (testseg.sh != dummysh) {
23428               // A subsegment is found at this side, dissolve this subface
23429               //   from the face link of this subsegment.
23430               testseg.shver = 0;
23431               spinsh = neighsh;
23432               if (sorg(spinsh) != sorg(testseg)) {
23433                 sesymself(spinsh);
23434               }
23435               spivot(spinsh, casingout);
23436               if (casingout.sh == spinsh.sh) {
23437                 // This is a trivial face link, only 'neighsh' itself,
23438                 //   the subsegment at this side is also died.
23439                 shellfacedealloc(subsegs, testseg.sh);
23440               } else {
23441                 spinsh = casingout;
23442                 do {
23443                   casingin = spinsh;
23444                   spivotself(spinsh);
23445                 } while (spinsh.sh != neighsh.sh);
23446                 // Set the link casingin->casingout.
23447                 sbond1(casingin, casingout);
23448                 // Bond the subsegment anyway.
23449                 ssbond(casingin, testseg);
23450               }
23451             }
23452             senextself(neighsh);
23453             enextself(testtet);
23454           }
23455           if (neighbor.tet != dummytet) {
23456             // Make sure the subface doesn't get deallocated again later
23457             //   when the infected neighbor is visited.
23458             tsdissolve(neighbor);
23459           }
23460           // This subface has been separated.
23461           if (in->mesh_dim > 2) {
23462             shellfacedealloc(subfaces, neighsh.sh);
23463           } else {
23464             // Dimension is 2. keep it for output.
23465             // Dissolve tets at both sides of this subface.
23466             stdissolve(neighsh);
23467             sesymself(neighsh);
23468             stdissolve(neighsh);
23469           }
23470         }
23471       } else {                   // The neighbor exists and is not infected.
23472         if (neighsh.sh == dummysh) {
23473           // There is no subface protecting the neighbor, infect it.
23474           infect(neighbor);
23475           // Ensure that the neighbor's neighbors will be infected.
23476           deadtet = (tetrahedron **) viri->alloc();
23477           *deadtet = neighbor.tet;
23478         } else {               // The neighbor is protected by a subface.
23479           // Remove this tetrahedron from the subface.
23480           stdissolve(neighsh);
23481           // The subface becomes a boundary.  Set markers accordingly.
23482           if (shellmark(neighsh) == 0) {
23483             setshellmark(neighsh, 1);
23484           }
23485           // This side becomes hull. Update the handle in dummytet.
23486           dummytet[0] = encode(neighbor);
23487         }
23488       }
23489     }
23490     // Remark the tetrahedron as infected, so it doesn't get added to the
23491     //   virus pool again.
23492     infect(testtet);
23493     virusloop = (tetrahedron **) viri->traverse();
23494   }
23495 }
23496 
23498 //                                                                           //
23499 // regionplague()    Spread regional attributes and/or volume constraints    //
23500 //                   (from a .poly file) throughout the mesh.                //
23501 //                                                                           //
23502 // This procedure operates in two phases.  The first phase spreads an attri- //
23503 // bute and/or a volume constraint through a (facet-bounded) region.  The    //
23504 // second phase uninfects all infected tetrahedra, returning them to normal. //
23505 //                                                                           //
23507 
23508 void tetgenmesh::
23509 regionplague(memorypool *regionviri, REAL attribute, REAL volume)
23510 {
23511   tetrahedron **virusloop;
23512   tetrahedron **regiontet;
23513   triface testtet, neighbor;
23514   face neighsh;
23515 
23516   if (b->verbose > 1) {
23517     printf("  Marking neighbors of marked tetrahedra.\n");
23518   }
23519   // Loop through all the infected tetrahedra, spreading the attribute
23520   //   and/or volume constraint to their neighbors, then to their neighbors'
23521   //   neighbors.
23522   regionviri->traversalinit();
23523   virusloop = (tetrahedron **) regionviri->traverse();
23524   while (virusloop != (tetrahedron **) NULL) {
23525     testtet.tet = *virusloop;
23526     // Temporarily uninfect this tetrahedron, not necessary.
23527     uninfect(testtet);
23528     if (b->regionattrib) {
23529       // Set an attribute.
23530       setelemattribute(testtet.tet, in->numberoftetrahedronattributes,
23531                        attribute);
23532     }
23533     if (b->varvolume) {
23534       // Set a volume constraint.
23535       setvolumebound(testtet.tet, volume);
23536     }
23537     // Check each of the tetrahedron's four neighbors.
23538     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23539       // Find the neighbor.
23540       sym(testtet, neighbor);
23541       // Check for a subface between the tetrahedron and its neighbor.
23542       tspivot(testtet, neighsh);
23543       // Make sure the neighbor exists, is not already infected, and
23544       //   isn't protected by a subface, or is protected by a nonsolid
23545       //   subface.
23546       if ((neighbor.tet != dummytet) && !infected(neighbor)
23547           && (neighsh.sh == dummysh)) {
23548         // Infect the neighbor.
23549         infect(neighbor);
23550         // Ensure that the neighbor's neighbors will be infected.
23551         regiontet = (tetrahedron **) regionviri->alloc();
23552         *regiontet = neighbor.tet;
23553       }
23554     }
23555     // Remark the tetrahedron as infected, so it doesn't get added to the
23556     //   virus pool again.
23557     infect(testtet);
23558     virusloop = (tetrahedron **) regionviri->traverse();
23559   }
23560 
23561   // Uninfect all tetrahedra.
23562   if (b->verbose > 1) {
23563     printf("  Unmarking marked tetrahedra.\n");
23564   }
23565   regionviri->traversalinit();
23566   virusloop = (tetrahedron **) regionviri->traverse();
23567   while (virusloop != (tetrahedron **) NULL) {
23568     testtet.tet = *virusloop;
23569     uninfect(testtet);
23570     virusloop = (tetrahedron **) regionviri->traverse();
23571   }
23572   // Empty the virus pool.
23573   regionviri->restart();
23574 }
23575 
23577 //                                                                           //
23578 // removeholetets()    Remove tetrahedra which are outside the domain.       //
23579 //                                                                           //
23581 
23582 void tetgenmesh::removeholetets(memorypool* viri)
23583 {
23584   tetrahedron **virusloop;
23585   triface testtet, neighbor;
23586   point checkpt;
23587   int *tetspernodelist;
23588   int i, j;
23589 
23590   if (b->verbose > 0) {
23591     printf("  Deleting marked tetrahedra.\n");
23592   }
23593 
23594   // Create and initialize 'tetspernodelist'.
23595   tetspernodelist = new int[points->items + 1];
23596   for (i = 0; i < points->items + 1; i++) tetspernodelist[i] = 0;
23597   
23598   // Loop the tetrahedra list, counter the number of tets sharing each node.
23599   tetrahedrons->traversalinit();
23600   testtet.tet = tetrahedrontraverse();
23601   while (testtet.tet != (tetrahedron *) NULL) {
23602     // Increment the number of sharing tets for each endpoint.
23603     for (i = 0; i < 4; i++) {
23604       j = pointmark((point) testtet.tet[4 + i]);
23605       tetspernodelist[j]++;
23606     }
23607     testtet.tet = tetrahedrontraverse();
23608   }
23609 
23610   viri->traversalinit();
23611   virusloop = (tetrahedron **) viri->traverse();
23612   while (virusloop != (tetrahedron **) NULL) {
23613     testtet.tet = *virusloop;
23614     // Record changes in the number of boundary faces, and disconnect
23615     //   dead tetrahedra from their neighbors.
23616     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23617       sym(testtet, neighbor);
23618       if (neighbor.tet == dummytet) {
23619         // There is no neighboring tetrahedron on this face, so this face
23620         //   is a boundary face.  This tetrahedron is being deleted, so this
23621         //   boundary face is deleted.
23622         hullsize--;
23623       } else {
23624         // Disconnect the tetrahedron from its neighbor.
23625         dissolve(neighbor);
23626         // There is a neighboring tetrahedron on this face, so this face
23627         //   becomes a boundary face when this tetrahedron is deleted.
23628         hullsize++;
23629       }
23630     }
23631     // Check the four corners of this tet if they're isolated.
23632     for (i = 0; i < 4; i++) {
23633       checkpt = (point) testtet.tet[4 + i];
23634       j = pointmark(checkpt);
23635       tetspernodelist[j]--;
23636       if (tetspernodelist[j] == 0) {
23637         // If it is added volume vertex or '-j' is not used, delete it.
23638         if ((pointtype(checkpt) == FREEVOLVERTEX) || !b->nojettison) { 
23639           setpointtype(checkpt, UNUSEDVERTEX);
23640           unuverts++;
23641         }
23642       }
23643     }
23644     // Return the dead tetrahedron to the pool of tetrahedra.
23645     tetrahedrondealloc(testtet.tet);
23646     virusloop = (tetrahedron **) viri->traverse();
23647   }
23648   
23649   delete [] tetspernodelist;
23650 }
23651 
23653 //                                                                           //
23654 // assignregionattribs()    Assign each tetrahedron a region number.         //
23655 //                                                                           //
23656 // This routine is called when '-AA' switch is specified.  Every tetrahedron //
23657 // of a (bounded) region will get a integer number to that region.  Default, //
23658 // regions are numbered as 1, 2, 3, etc. However, if a number has already    //
23659 // been used (set by user in the region section in .poly or .smesh), it is   //
23660 // skipped and the next available number will be used.                       //
23661 //                                                                           //
23663 
23664 void tetgenmesh::assignregionattribs()
23665 {
23666   list *regionnumlist;
23667   list *regiontetlist;
23668   triface tetloop, regiontet, neightet;
23669   face checksh;
23670   bool flag;
23671   int regionnum, num;
23672   int attridx, count;
23673   int i;
23674 
23675   if (b->verbose > 0) {
23676     printf("  Assign region numbers.\n");
23677   }
23678 
23679   regionnumlist = new list(sizeof(int), NULL, 256);
23680   regiontetlist = new list(sizeof(triface), NULL, 1024);
23681   attridx = in->numberoftetrahedronattributes;  
23682 
23683   // Loop through all tets. Infect tets which already have a region number,
23684   //   and save the used numbers in 'regionnumlist'.
23685   tetrahedrons->traversalinit();
23686   tetloop.tet = tetrahedrontraverse();
23687   while (tetloop.tet != (tetrahedron *) NULL) {
23688     if (!infected(tetloop)) {
23689       regionnum = (int) elemattribute(tetloop.tet, attridx);
23690       if (regionnum != 0.0) {
23691         // Found a numbered region tet.
23692         infect(tetloop);
23693         regiontetlist->append(&tetloop);
23694         // Found and infect all tets in this region.
23695         for (i = 0; i < regiontetlist->len(); i++) {
23696           regiontet = * (triface *)(* regiontetlist)[i];
23697           for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23698             // Is there a boundary face?
23699             tspivot(regiontet, checksh);
23700             if (checksh.sh == dummysh) {
23701               sym(regiontet, neightet);
23702               if ((neightet.tet != dummytet) && !infected(neightet)) {
23703 #ifdef SELF_CHECK
23704                 // neightet should have the same region number. Check it.
23705                 num = (int) elemattribute(neightet.tet, attridx);
23706                 assert(num == regionnum);
23707 #endif
23708                 infect(neightet);
23709                 regiontetlist->append(&neightet);
23710               }
23711             }
23712           }
23713         }
23714         // Add regionnum to list if it is not exist.
23715         flag = false;
23716         for (i = 0; i < regionnumlist->len() && !flag; i++) {
23717           num = * (int *)(* regionnumlist)[i];
23718           flag = (num == regionnum);
23719         }
23720         if (!flag) regionnumlist->append(&regionnum);
23721         // Clear list for the next region.
23722         regiontetlist->clear();
23723       }
23724     }
23725     tetloop.tet = tetrahedrontraverse();
23726   }
23727   
23728   if (b->verbose > 0) {
23729     printf("  %d user-specified regions.\n", regionnumlist->len());
23730   }
23731 
23732   // Now loop the tets again. Assign region numbers to uninfected tets.
23733   tetrahedrons->traversalinit();
23734   tetloop.tet = tetrahedrontraverse();
23735   regionnum = 1;  // Start region number.
23736   count = 0;
23737   while (tetloop.tet != (tetrahedron *) NULL) {
23738     if (!infected(tetloop)) {
23739       // An unassigned region tet.
23740       count++;
23741       do {
23742         flag = false;
23743         // Check if the region number has been used.
23744         for (i = 0; i < regionnumlist->len() && !flag; i++) {
23745           num = * (int *)(* regionnumlist)[i];
23746           flag = (num == regionnum);
23747         }
23748         if (flag) regionnum++;
23749       } while (flag);      
23750       setelemattribute(tetloop.tet, attridx, (REAL) regionnum);
23751       infect(tetloop);
23752       regiontetlist->append(&tetloop);
23753       // Found and infect all tets in this region.
23754       for (i = 0; i < regiontetlist->len(); i++) {
23755         regiontet = * (triface *)(* regiontetlist)[i];
23756         for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23757           // Is there a boundary face?
23758           tspivot(regiontet, checksh);
23759           if (checksh.sh == dummysh) {
23760             sym(regiontet, neightet);
23761             if ((neightet.tet != dummytet) && !infected(neightet)) {
23762 #ifdef SELF_CHECK
23763               // neightet should have not been assigned yet. Check it.
23764               num = (int) elemattribute(neightet.tet, attridx);
23765               assert(num == 0);
23766 #endif
23767               setelemattribute(neightet.tet, attridx, (REAL) regionnum);
23768               infect(neightet);
23769               regiontetlist->append(&neightet);
23770             }
23771           }
23772         }
23773       }
23774       regiontetlist->clear();
23775       regionnum++; // The next region number.
23776     }
23777     tetloop.tet = tetrahedrontraverse();
23778   }
23779 
23780   // Uninfect all tets.
23781   tetrahedrons->traversalinit();
23782   tetloop.tet = tetrahedrontraverse();
23783   while (tetloop.tet != (tetrahedron *) NULL) {
23784 #ifdef SELF_CHECK
23785     assert(infected(tetloop));
23786 #endif
23787     uninfect(tetloop);
23788     tetloop.tet = tetrahedrontraverse();
23789   }
23790   
23791   if (b->verbose > 0) {
23792     printf("  %d regions are numbered.\n", count);
23793   }
23794 
23795   delete regionnumlist;
23796   delete regiontetlist;
23797 }
23798 
23800 //                                                                           //
23801 // carveholes()    Find the holes and infect them.  Find the volume          //
23802 //                 constraints and infect them.  Infect the convex hull.     //
23803 //                 Spread the infection and kill tetrahedra.  Spread the     //
23804 //                 volume constraints.                                       //
23805 //                                                                           //
23806 // This routine mainly calls other routines to carry out all these functions.//
23807 //                                                                           //
23809 
23810 void tetgenmesh::carveholes()
23811 {
23812   memorypool *holeviri, *regionviri;
23813   tetrahedron *tptr, **holetet, **regiontet;
23814   triface searchtet, *holetets, *regiontets;
23815   enum locateresult intersect;
23816   int i;
23817 
23818   if (!b->quiet) {
23819     printf("Removing unwanted tetrahedra.\n");
23820     if (b->verbose && (in->numberofholes > 0)) {
23821       printf("  Marking holes for elimination.\n");
23822     }
23823   }
23824 
23825   // Initialize a pool of viri to be used for holes, concavities.
23826   holeviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23827   // Mark as infected any unprotected tetrahedra on the boundary.
23828   infecthull(holeviri);
23829 
23830   if (in->numberofholes > 0) {
23831     // Allocate storage for the tetrahedra in which hole points fall.
23832     holetets = (triface *) new triface[in->numberofholes];
23833     // Infect each tetrahedron in which a hole lies.
23834     for (i = 0; i < 3 * in->numberofholes; i += 3) {
23835       // Ignore holes that aren't within the bounds of the mesh.
23836       if ((in->holelist[i] >= xmin) && (in->holelist[i] <= xmax)
23837           && (in->holelist[i + 1] >= ymin)
23838           && (in->holelist[i + 1] <= ymax)
23839           && (in->holelist[i + 2] >= zmin)
23840           && (in->holelist[i + 2] <= zmax)) {
23841         searchtet.tet = dummytet;
23842         // Find a tetrahedron that contains the hole.
23843         intersect = locate(&in->holelist[i], &searchtet);
23844         if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23845           // Record the tetrahedron for processing carve hole.
23846           holetets[i / 3] = searchtet;
23847         }
23848       }
23849     }
23850     // Infect the hole tetrahedron.  This is done by marking the tet as
23851     //   infected and including the tetrahedron in the virus pool.
23852     for (i = 0; i < in->numberofholes; i++) {
23853       infect(holetets[i]);
23854       holetet = (tetrahedron **) holeviri->alloc();
23855       *holetet = holetets[i].tet;
23856     }
23857     // Free up memory.
23858     delete [] holetets;
23859   }
23860 
23861   // Mark as infected all tets of the holes and concavities.
23862   plague(holeviri);
23863   // The virus pool contains all outside tets now.
23864 
23865   // Is -A switch in use.
23866   if (b->regionattrib) {
23867     // Assign every tetrahedron a regional attribute of zero.
23868     tetrahedrons->traversalinit();
23869     tptr = tetrahedrontraverse();
23870     while (tptr != (tetrahedron *) NULL) {
23871       setelemattribute(tptr, in->numberoftetrahedronattributes, 0.0);
23872       tptr = tetrahedrontraverse();
23873     }
23874   }
23875 
23876   if (in->numberofregions > 0) {
23877     if (!b->quiet) {
23878       if (b->regionattrib) {
23879         if (b->varvolume) {
23880           printf("Spreading regional attributes and volume constraints.\n");
23881         } else {
23882           printf("Spreading regional attributes.\n");
23883         }
23884       } else {
23885         printf("Spreading regional volume constraints.\n");
23886       }
23887     }
23888     // Allocate storage for the tetrahedra in which region points fall.
23889     regiontets = (triface *) new triface[in->numberofregions];
23890     // Find the starting tetrahedron for each region.
23891     for (i = 0; i < in->numberofregions; i++) {
23892       regiontets[i].tet = dummytet;
23893       // Ignore region points that aren't within the bounds of the mesh.
23894       if ((in->regionlist[5 * i] >= xmin)
23895            && (in->regionlist[5 * i] <= xmax)
23896            && (in->regionlist[5 * i + 1] >= ymin)
23897            && (in->regionlist[5 * i + 1] <= ymax)
23898            && (in->regionlist[5 * i + 2] >= zmin)
23899            && (in->regionlist[5 * i + 2] <= zmax)) {
23900         searchtet.tet = dummytet;
23901         // Find a tetrahedron that contains the region point.
23902         intersect = locate(&in->regionlist[5 * i], &searchtet);
23903         if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23904           // Record the tetrahedron for processing after the
23905           //   holes have been carved.
23906           regiontets[i] = searchtet;
23907         }
23908       }
23909     }
23910     // Initialize a pool to be used for regional attrs, and/or regional
23911     //   volume constraints.
23912     regionviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23913     // Find and set all regions.
23914     for (i = 0; i < in->numberofregions; i++) {
23915       if (regiontets[i].tet != dummytet) {
23916         // Make sure the tetrahedron under consideration still exists.
23917         //   It may have been eaten by the virus.
23918         if (!isdead(&(regiontets[i]))) {
23919           // Put one tetrahedron in the virus pool.
23920           infect(regiontets[i]);
23921           regiontet = (tetrahedron **) regionviri->alloc();
23922           *regiontet = regiontets[i].tet;
23923           // Apply one region's attribute and/or volume constraint.
23924           regionplague(regionviri, in->regionlist[5 * i + 3],
23925                        in->regionlist[5 * i + 4]);
23926           // The virus pool should be empty now.
23927         }
23928       }
23929     }
23930     // Free up memory.
23931     delete [] regiontets;
23932     delete regionviri;
23933   }
23934 
23935   // Now acutually remove the outside and hole tets.
23936   removeholetets(holeviri);
23937   // The mesh is nonconvex now.
23938   nonconvex = 1;
23939 
23940   if (b->regionattrib) {
23941     if (b->regionattrib > 1) {
23942       // -AA switch. Assign each tet a region number (> 0).
23943       assignregionattribs();
23944     }
23945     // Note the fact that each tetrahedron has an additional attribute.
23946     in->numberoftetrahedronattributes++;
23947   }
23948 
23949   // Free up memory.
23950   delete holeviri;
23951 }
23952 
23953 //
23954 // End of carving out holes and concavities routines
23955 //
23956 
23957 //
23958 // Begin of boundary Steiner points removing routines
23959 //
23960 
23962 //                                                                           //
23963 // replacepolygonsubs()    Substitute the subfaces of a polygon.             //
23964 //                                                                           //
23965 // 'oldshlist' (T_old) contains the old subfaces of P.  It will be replaced  //
23966 // by 'newshlist' (T_new) of new subfaces. Each boundary edge of P is bonded //
23967 // to 'dummysh' in T_new.                                                    //
23968 //                                                                           //
23969 // Notice that Not every boundary edge of T_new is able to bond to a subface,//
23970 // e.g., when it is a segment recovered by removing a Steiner point in it.   //
23971 //                                                                           //
23973 
23974 void tetgenmesh::replacepolygonsubs(list* oldshlist, list* newshlist)
23975 {
23976   face newsh, oldsh, spinsh;
23977   face casingout, casingin;
23978   face checkseg;
23979   point pa, pb;
23980   int i, j, k, l;
23981 
23982   for (i = 0; i < newshlist->len(); i++) {
23983     // Get a new subface s.
23984     newsh = * (face *)(* newshlist)[i];
23985     // Check the three edges of s.
23986     for (k = 0; k < 3; k++) {
23987       spivot(newsh, casingout);
23988       // Is it a boundary edge?
23989       if (casingout.sh == dummysh) {
23990         // Find the old subface s_o having the same edge as s.
23991         pa = sorg(newsh);
23992         pb = sdest(newsh); 
23993         for (j = 0; j < oldshlist->len(); j++) {
23994           oldsh = * (face *)(* oldshlist)[j];
23995       for (l = 0; l < 3; l++) {
23996             if (((sorg(oldsh) == pa) && (sdest(oldsh) == pb)) ||
23997                 ((sorg(oldsh) == pb) && (sdest(oldsh) == pa))) break;
23998             senextself(oldsh);
23999           }
24000           if (l < 3) break;
24001         }
24002         // Is there a matched edge?
24003         if (j < oldshlist->len()) {
24004           // Get the neighbor subface s_out.
24005           spivot(oldsh, casingout);
24006           sspivot(oldsh, checkseg);
24007           if (checkseg.sh != dummysh) {
24008             // A segment. Insert s into the face ring, ie, s_in -> s -> s_out.
24009             if (oldsh.sh != casingout.sh) {
24010               // s is not bonded to itself.
24011               spinsh = casingout;
24012               do {
24013                 casingin = spinsh;
24014                 spivotself(spinsh);
24015               } while (sapex(spinsh) != sapex(oldsh));
24016               assert(casingin.sh != oldsh.sh); 
24017               // Bond s_in -> s -> s_out (and dissolve s_in -> s_old -> s_out).
24018               sbond1(casingin, newsh);
24019               sbond1(newsh, casingout);
24020             } else {
24021               // Bond newsh -> newsh.
24022               sbond(newsh, newsh);
24023             }
24024             // Bond the segment.
24025             ssbond(newsh, checkseg);
24026           } else {
24027             // Bond s <-> s_out (and dissolve s_out -> s_old).
24028             sbond(newsh, casingout);
24029           }
24030           // Unbound oldsh to indicate it's neighbor has been replaced.
24031           //   It will be used to indentfy the edge in the inverse.
24032           sdissolve(oldsh);
24033           ssdissolve(oldsh);
24034         }
24035       }
24036       // Go to the next edge of s.
24037       senextself(newsh);
24038     }
24039   }
24040 }
24041 
24043 //                                                                           //
24044 // orientnewsubs()    Orient new subfaces facing to the inside of cavity.    //
24045 //                                                                           //
24046 // 'newshlist' contains new subfaces of the cavity C (created by re-triangu- //
24047 // lation the polygon P). They're not necessary facing to the inside of C.   //
24048 // 'orientsh', faces to the inside of C, is used to adjust new subfaces. The //
24049 // normal of the new subfaces is returned in 'norm'.                         //
24050 //                                                                           //
24052 
24053 void tetgenmesh::orientnewsubs(list* newshlist, face* orientsh, REAL* norm)
24054 {
24055   face *newsh;
24056   point pa, pb, pc;
24057   REAL ref[3], ori, len;
24058   int i;
24059 
24060   // Calculate the normal of 'orientsh'.
24061   pa = sorg(*orientsh);
24062   pb = sdest(*orientsh);
24063   pc = sapex(*orientsh);
24064   facenormal(pa, pb, pc, norm, &len);
24065   for (i = 0; i < 3; i++) ref[i] = pa[i] + norm[i];
24066   for (i = 0; i < 3; i++) norm[i] /= len;
24067   
24068   // Orient new subfaces. Let the normal above each one.
24069   for (i = 0; i < newshlist->len(); i++) {
24070     newsh = (face *)(* newshlist)[i];
24071     pa = sorg(*newsh);
24072     pb = sdest(*newsh);
24073     pc = sapex(*newsh);
24074     ori = orient3d(pa, pb, pc, ref);
24075     assert(ori != 0.0);
24076     if (ori > 0.0) {
24077       sesymself(*newsh);
24078     }
24079   }
24080 }
24081 
24083 //                                                                           //
24084 // constrainedflip()    Flip a non-constrained face.                         //
24085 //                                                                           //
24086 // 'flipface' f (abc) is a face we want to flip. In addition, if 'front' is  //
24087 // given (not a NULL), f is a crossface. f may not be flippable if it is one //
24088 // of the following cases:                                                   //
24089 //   (1) f has an aux subface attached;                                      //
24090 //   (2) f is on the convex hull;                                            //
24091 //   (3) f is not locally Delaunay (f must be recovered by a previous flip,  //
24092 //       we should keep it, otherwise, we may fall into a flip loop);        //
24093 //   (4) f is T32 at ab, but abd or abe has an aux subface attached;         //
24094 //   (5) f is T22 or T44 at ab, but abd, or abe, or abf has an aux subface   //
24095 //       attached;                                                           //
24096 //   (6) f is unflipable at ab, and abd, abe, ... are all unflippable due to //
24097 //       the cases (1) - (5).                                                //
24098 // If f is a crssface ('front' != NULL) and it is unflipable due to case (3),//
24099 // (4), (5) and (6). Try to flip the next crossing face of front first.      //
24100 //                                                                           //
24102 
24103 bool tetgenmesh::constrainedflip(triface* flipface, triface* front,
24104   queue* flipque)
24105 {
24106   triface symface, spintet;
24107   face checksh;
24108   point pa, pb, pc, pd, pe;
24109   enum fliptype fc;
24110   REAL sign;
24111   bool doflip;
24112   int ia, ib, ic, id, ie;
24113   int i;
24114 
24115   // (1) Is f protected by an (auxilary) subface?
24116   tspivot(*flipface, checksh);
24117   if (checksh.sh != dummysh) return false;
24118   // (2) Is f on the convex hull?
24119   sym(*flipface, symface);
24120   if (symface.tet == dummytet) return false;
24121   // (3) Is f not locally Delaunay?
24122   adjustedgering(*flipface, CCW);
24123   pa = dest(*flipface);
24124   pb = org(*flipface);
24125   pc = apex(*flipface);
24126   pd = oppo(*flipface);
24127   pe = oppo(symface);
24128   // if (symbolic) {
24129     ia = pointmark(pa);
24130     ib = pointmark(pb);
24131     ic = pointmark(pc);
24132     id = pointmark(pd);
24133     ie = pointmark(pe);
24134     sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24135     assert(sign != 0.0);
24136   // } else {
24137   //   sign = insphere(pa, pb, pc, pd, pe);
24138   // }
24139   if (sign <= 0.0) {
24140     // Get the fliptype of f.
24141     checksubfaces = 0; // switch off subface test.
24142     fc = categorizeface(*flipface);
24143     checksubfaces = 1; // switch on subface test.
24144     if (fc == T23) {
24145       doflip = true;
24146       // Avoid one tet created by the 2-3 flip is nearly degenerate.
24147       /* pc = oppo(*flipface);
24148       pd = oppo(symface);
24149       adjustedgering(*flipface, CCW);
24150       for (i = 0; i < 3; i++) {
24151         pa = org(*flipface);
24152         pb = dest(*flipface);
24153         ori = orient3d(pa, pb, pc, pd);
24154         if (iscoplanar(pa, pb, pc, pd, ori, b->epsilon)) {
24155           doflip = false; break;
24156         }
24157         enextself(*flipface);
24158       } */
24159       if (doflip) {
24160         flip23(flipface, flipque);
24161         return true;
24162       }
24163     } else if (fc == T32) {
24164       // (4) Is abd, or abe protected?
24165       doflip = true;
24166       spintet = *flipface;
24167       for (i = 0; i < 2; i++) {
24168         fnextself(spintet);
24169         tspivot(spintet, checksh);
24170         if (checksh.sh != dummysh) {
24171           doflip = false; break; // f is protected. Unflipable.
24172         }
24173       }
24174       if (doflip) {
24175         flip32(flipface, flipque);
24176         return true;
24177       }
24178     } else if (fc == T22 || fc == T44) {
24179       // (5) Is abd, abe, or abf protected?
24180       doflip = true;
24181       if (fc == T22) {
24182         for (i = 0; i < 2; i++) {
24183           spintet = *flipface;
24184           if (i == 1) {
24185             esymself(spintet);
24186           }
24187           fnextself(spintet);
24188           tspivot(spintet, checksh);
24189           if (checksh.sh != dummysh) {
24190             doflip = false; break; // f is protected. Unflipable.
24191           }
24192         }
24193       } else if (fc == T44) {
24194         spintet = *flipface;
24195         for (i = 0; i < 3; i++) {
24196           fnextself(spintet);
24197           tspivot(spintet, checksh);
24198           if (checksh.sh != dummysh) {
24199             doflip = false; break; // f is protected. Unflipable.
24200           }
24201         }
24202       }
24203       if (doflip) {
24204         flip22(flipface, flipque);
24205         return true;
24206       }
24207     } else if (fc == N32) {
24208       // Is f a crossface?
24209       if (front != (triface *) NULL) {
24210         // (6) Is any obstacle face (abd, or abe, ...) flipable?
24211         spintet = *flipface;
24212         while (fnextself(spintet)) {
24213           if (apex(spintet) == apex(*flipface)) break;
24214           // Check if spintet is flipable, no recursive.
24215           if (constrainedflip(&spintet, NULL, flipque)) {
24216             // One obstacle face has been flipped.
24217             return true;
24218           }
24219           // Unflipable. Go to the next obstacle face.
24220           findedge(&spintet, org(*flipface), dest(*flipface));
24221         }
24222       }
24223     }
24224   }
24225 
24226   // f is unflipable. Is f a crossface?
24227   if (front != (triface *) NULL) {
24228     // Look if there is another crossface.
24229     pa = org(*front);
24230     pb = dest(*front);
24231     pc = apex(*front);
24232     // sym(*flipface, symface);
24233     // Have we reach the end of abc (We've started from edge ab).
24234     if (oppo(symface) != pc) {
24235       adjustedgering(symface, CCW);
24236       for (i = 0; i < 3; i++) {
24237         fnext(symface, spintet);
24238         // Is c ahead of this face?
24239         sign = orient3d(org(spintet), dest(spintet), apex(spintet), pc);
24240         if (sign < 0.0) {
24241           if (tritritest(&spintet, pa, pb, pc)) {
24242             if (b->verbose > 2) {
24243               printf("    Next crossface (%d, %d, %d).\n",
24244                      pointmark(org(spintet)), pointmark(dest(spintet)),
24245                      pointmark(apex(spintet)));
24246             }
24247             return constrainedflip(&spintet, front, flipque);
24248             // return constrainedflip(&spintet, NULL, flipque);
24249           }
24250         }
24251         enextself(symface);
24252       }
24253     }
24254   }
24255   return false;
24256 }
24257 
24259 //                                                                           //
24260 // recoverfront()    Recover a missing front by flips.                       //
24261 //                                                                           //
24262 // 'front' f is missing in D - it was crossed by faces of D. The cross faces //
24263 // may be flippable, so f can be recovered by flipping them away.            //
24264 //                                                                           //
24266 
24267 bool tetgenmesh::recoverfront(triface* front, list* newtetlist, queue* flipque)
24268 {
24269   triface idfront, starttet, spintet;
24270   point pa, pb, pc, pd, ref;
24271   enum locateresult loc;
24272   enum finddirectionresult col;
24273   REAL ori, ori1, ori2, sign;
24274   int hitbdry;
24275   int i, j;
24276 
24277   // Find an existing edge of f in D to start with.
24278   for (i = 0; i < 3; i++) {
24279     pa = org(*front);
24280     pb = dest(*front);
24281     // Get a tet for searching.
24282     idfront = recenttet;
24283     // Make sure the tet is valid (flip32() may kill a tet).
24284     if (isdead(&idfront)) {
24285       // The tet is dead. Get a live tet in D. !!!
24286       for (j = 0; j < newtetlist->len(); j++) {
24287         recenttet = * (triface *)(* newtetlist)[j];
24288         if (!isdead(&recenttet)) break;
24289       }
24290       assert(j < newtetlist->len());
24291     }
24292     loc = preciselocate(pa, &idfront, (long) newtetlist->len());
24293     if (loc != ONVERTEX) {
24294       // Do a brute-force search in D.
24295       for (j = 0; j < newtetlist->len(); j++) {
24296         idfront = * (triface *)(* newtetlist)[j];
24297         if (isdead(&idfront)) continue;
24298         if (findorg(&idfront, pa)) break;
24299       }
24300       assert(j < newtetlist->len()); // a must belong to one tet.
24301     }
24302     recenttet = idfront;
24303     // Search for a tet having edge ab.
24304     col = finddirection(&idfront, pb, (long) newtetlist->len());
24305     if (col == BELOWHULL) {
24306       // Do a brute-force search in D.
24307       for (j = 0; j < newtetlist->len(); j++) {
24308         idfront = * (triface *)(* newtetlist)[j];
24309         if (isdead(&idfront)) continue;
24310         if (findorg(&idfront, pa)) {
24311           assert(org(idfront) == pa);
24312           if (dest(idfront) == pb) {
24313             col = RIGHTCOLLINEAR; break;
24314           } else if (apex(idfront) == pb) {
24315             col = LEFTCOLLINEAR; break;
24316           } else if (oppo(idfront) == pb) {
24317             col = TOPCOLLINEAR; break;
24318           }
24319         }
24320       }
24321     }
24322     if (col == RIGHTCOLLINEAR) {
24323       // b is just the destination.
24324     } else if (col == LEFTCOLLINEAR) {
24325       enext2self(idfront);
24326       esymself(idfront);
24327     } else if (col == TOPCOLLINEAR) {
24328       fnextself(idfront);
24329       enext2self(idfront);
24330       esymself(idfront);
24331     }
24332     if (dest(idfront) == pb) break; // Found.
24333     // Missing. Go to the next edge of f.
24334     enextself(*front);
24335   }
24336   if (i == 3) {
24337     // All three edges of f are missing - unrecoverable.
24338     return false;
24339   }
24340 
24341   // Search for a tet having f (abc).
24342   pc = apex(*front);
24343   spintet = idfront;
24344   hitbdry = 0;
24345   do {
24346     if (apex(spintet) == pc) {
24347       // Found abc. Insert an auxilary subface s at idfront.
24348       insertauxsubface(front, &spintet);
24349       return true;
24350     }
24351     if (!fnextself(spintet)) {
24352       hitbdry ++;
24353       if (hitbdry < 2) {
24354         esym(idfront, spintet);
24355         if (!fnextself(spintet)) {
24356           hitbdry ++;
24357         }
24358       }
24359     }
24360     if (apex(spintet) == apex(idfront)) break;
24361   } while (hitbdry < 2);
24362 
24363   // Search for a crossing face to flip.
24364   pd = apex(idfront);
24365   assert(pd != pc);
24366   // Decide the orientation of d with abc.
24367   ori = orient3d(pa, pb, pc, pd);
24368   if (ori < 0.0) {
24369     // d is above abc. Rotate downwards.
24370     esym(idfront, starttet);
24371     sign = -1.0;
24372   } else if (ori > 0.0) {
24373     // d is below abc. Rotate upwards.
24374     starttet = idfront;
24375     sign = 1.0;
24376   } else {
24377     assert(ori == 0.0);
24378     // d is coplanar with abc. Do abc and abd intersect?
24379     ref = oppo(idfront);
24380     ori1 = orient3d(pa, pb, ref, pc);
24381     ori2 = orient3d(pa, pb, ref, pd);
24382     assert(ori1 * ori2 != 0.0);
24383     if (ori1 * ori2 > 0) {
24384       // abc and abd intersect.  There're two possible intersections: 
24385       //   ad and bc, or ac and bd.  Find it out.
24386       ori1 = orient3d(pb, pc, ref, pd);
24387       ori2 = orient3d(pb, pc, ref, pa);
24388       assert(ori1 * ori2 != 0.0);
24389       if (ori1 * ori2 > 0) {
24390         // ac intersects bd.
24391         enextself(idfront); // go to edge bd.
24392       } else {
24393         // ad intersects bc.
24394         enext2self(idfront); // go to edge ad.
24395       }
24396       adjustedgering(idfront, CCW);
24397       fnextself(idfront); // face ade or bce need a 4-to-4 flip.
24398       if (b->verbose > 2) {
24399         printf("    Get crossface (%d, %d, %d).\n", pointmark(org(idfront)),
24400                pointmark(dest(idfront)), pointmark(apex(idfront)));
24401       }
24402       if (constrainedflip(&idfront, front, flipque)) {
24403         // A crossface has been flipped. Continue to recover f.
24404         return recoverfront(front, newtetlist, flipque);
24405       }
24406       // Unable to recover f.
24407       return false; // sign = 0.0;
24408     } else {
24409       // Not intersect. We can go either direction.
24410       starttet = idfront;
24411       if (fnextself(starttet)) {
24412         // Choose to rotate upwards.
24413         sign = 1.0;
24414       } else {
24415         // Hit convex hull. Choose to rotate downwrads.
24416         esym(idfront, starttet);
24417         sign = -1.0;
24418       }
24419     }
24420   }
24421 
24422   assert(sign != 0.0);
24423   if (sign == -1) {
24424     // The edge ab has be changed. Reverse it.
24425     pa = org(starttet);
24426     pb = dest(starttet);
24427     // The sign has been reversed as well.
24428     sign = -sign;
24429   }
24430   // Rotate face abd around edge ab. Moreover, we've chosen the rotate
24431   //   direction such that no convex hull face will be reach.
24432   spintet = starttet;
24433   while (fnextself(spintet)) {
24434     pd = apex(spintet);
24435     assert(pd != pc);
24436     // Check if the orientation of d (with abc) has changed.
24437     ori = orient3d(pa, pb, pc, pd);
24438     if (ori == 0.0) {
24439       // abc and abd must coplanar intersect (4-to-4 flip is needed).
24440       ref = oppo(spintet);
24441       ori1 = orient3d(pb, pc, ref, pd);
24442       ori2 = orient3d(pb, pc, ref, pa);
24443       assert(ori1 * ori2 != 0.0);
24444       if (ori1 * ori2 > 0) {
24445         // ac intersects bd.
24446         enextself(spintet); // go to edge bd.
24447       } else {
24448         // ad intersects bc.
24449         enext2self(spintet); // go to edge ad.
24450       }
24451       adjustedgering(spintet, CCW);
24452       fnextself(spintet); // face ade or bce need a 4-to-4 flip.
24453       if (b->verbose > 2) {
24454         printf("    Get crossface (%d, %d, %d).\n", pointmark(org(spintet)),
24455                pointmark(dest(spintet)), pointmark(apex(spintet)));
24456       }
24457       if (constrainedflip(&spintet, front, flipque)) {
24458         // A crossface has been flipped. Continue to recover f.
24459         return recoverfront(front, newtetlist, flipque);
24460       }
24461       // Unable to recover f.
24462       return false; // sign = 0.0;
24463     } else if (ori * sign < 0.0) {
24464       // Sign has changed. The face dea or deb must cross abc.
24465       adjustedgering(spintet, CCW);
24466       enextself(spintet);
24467       for (i = 0; i < 2; i++) {
24468         // Get the face dea or deb.
24469         fnext(spintet, starttet);
24470         if (tritritest(&starttet, pa, pb, pc)) {
24471           if (b->verbose > 2) {
24472             printf("    Get crossface (%d, %d, %d).\n",
24473                    pointmark(org(starttet)), pointmark(dest(starttet)),
24474                    pointmark(apex(starttet)));
24475           }
24476           if (constrainedflip(&starttet, front, flipque)) {
24477             // A crossface has been flipped. Continue to recover f.
24478             return recoverfront(front, newtetlist, flipque);
24479           }
24480         }
24481         enextself(spintet);
24482       }
24483       // Unable to recover f.
24484       return false;
24485     }
24486   }
24487   // Impossible to be here.
24488   assert(0);
24489   return false;
24490 }
24491 
24493 //                                                                           //
24494 // repairflips()    Flip non-Delaunay and non-constrained faces.             //
24495 //                                                                           //
24497 
24498 void tetgenmesh::repairflips(queue* flipque)
24499 {
24500   badface *qface;
24501   triface flipface, symface, spintet;
24502   face checksh;
24503   point pa, pb, pc, pd, pe;
24504   enum fliptype fc;
24505   REAL sign;
24506   long flipcount;
24507   bool doflip;
24508   int ia, ib, ic, id, ie;
24509   int i;
24510 
24511   if (b->verbose > 1) {
24512     printf("    Repair flip %ld faces.\n", flipque->len());
24513   }
24514   flipcount = flip23s + flip32s + flip22s + flip44s;
24515   // Loop until the queue is empty.
24516   while (!flipque->empty()) {
24517     qface = (badface *) flipque->pop();
24518     flipface = qface->tt;
24519     // Check the validity of this face.
24520     if (isdead(&flipface) || flipface.tet == dummytet || 
24521         (org(flipface) != qface->forg) || 
24522         (dest(flipface) != qface->fdest) ||
24523         (apex(flipface) != qface->fapex) ||
24524         (oppo(flipface) == (point) NULL)) continue;
24525     // (1) Is f protected by an (auxilary) subface?
24526     tspivot(flipface, checksh);
24527     if (checksh.sh != dummysh) continue;
24528     // (2) Is f on the convex hull?
24529     sym(flipface, symface);
24530     if (symface.tet == dummytet) continue;
24531     // For positive orientation that insphere() test requires.
24532     adjustedgering(flipface, CW);
24533     pa = org(flipface);
24534     pb = dest(flipface);
24535     pc = apex(flipface);
24536     pd = oppo(flipface);
24537     pe = oppo(symface);
24538     // if (symbolic) {
24539       ia = pointmark(pa);
24540       ib = pointmark(pb);
24541       ic = pointmark(pc);
24542       id = pointmark(pd);
24543       ie = pointmark(pe);
24544       sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24545       assert(sign != 0.0);
24546     // } else {
24547     //   sign = insphere(pa, pb, pc, pd, pe);
24548     // }
24549     if (sign > 0.0) {
24550       // f is non-lcally Delaunay. Get the fliptype of f.
24551       checksubfaces = 0; // switch off subface test.
24552       fc = categorizeface(flipface);
24553       checksubfaces = 1; // switch on subface test.
24554       if (fc == T23) {
24555         doflip = true;
24556         // Avoid to create a nearly degenerate tet.
24557         /* pc = oppo(flipface);
24558         pd = oppo(symface);
24559         adjustedgering(flipface, CCW);
24560         for (i = 0; i < 3; i++) {
24561           pa = org(flipface);
24562           pb = dest(flipface);
24563           ori = orient3d(pa, pb, pc, pd);
24564           if (iscoplanar(pa, pb, pc, pd, ori, b->epsilon)) {
24565             doflip = false; break;
24566           }
24567           enextself(flipface);
24568         } */
24569         if (doflip) {
24570           flip23(&flipface, flipque);
24571         }
24572       } else if (fc == T32) {
24573         // (4) Is abd, or abe protected?
24574         doflip = true;
24575         spintet = flipface;
24576         for (i = 0; i < 2; i++) {
24577           fnextself(spintet);
24578           tspivot(spintet, checksh);
24579           if (checksh.sh != dummysh) {
24580             doflip = false; break; // f is protected. Unflipable.
24581           }
24582         }
24583         if (doflip) {
24584           flip32(&flipface, flipque);
24585         }
24586       } else if (fc == T22 || fc == T44) {
24587         // (5) Is abd, abe, or abf protected?
24588         doflip = true;
24589         if (fc == T22) {
24590           for (i = 0; i < 2; i++) {
24591             spintet = flipface;
24592             if (i == 1) {
24593               esymself(spintet);
24594             }
24595             fnextself(spintet);
24596             tspivot(spintet, checksh);
24597             if (checksh.sh != dummysh) {
24598               doflip = false; break; // f is protected. Unflipable.
24599             }
24600           }
24601         } else if (fc == T44) {
24602           spintet = flipface;
24603           for (i = 0; i < 3; i++) {
24604             fnextself(spintet);
24605             tspivot(spintet, checksh);
24606             if (checksh.sh != dummysh) {
24607               doflip = false; break; // f is protected. Unflipable.
24608             }
24609           }
24610         }
24611         if (doflip) {
24612           flip22(&flipface, flipque);
24613         }
24614       }
24615     }
24616   }
24617   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
24618   if (b->verbose > 1) {
24619     printf("    %ld flips.\n", flipcount);
24620   }
24621 }
24622 
24624 //                                                                           //
24625 // constrainedcavity()    Tetrahedralize a cavity by constrained tetrahedra. //
24626 //                                                                           //
24627 // The cavity C is bounded by faces F in 'floorlist' and 'ceillist'. 'ptlist'//
24628 // V is the set of vertices of C.                                            //
24629 //                                                                           //
24631 
24632 bool tetgenmesh::constrainedcavity(triface* oldtet, list* floorlist,
24633   list* ceillist, list* ptlist, list* frontlist, list* misfrontlist,
24634   list* newtetlist, queue* flipque)
24635 {
24636   triface misfront, newtet;
24637   long facenum;
24638   int i;
24639 
24640   if (b->verbose > 1) {
24641     printf("    Constrained cavity (%d floors, %d ceilings, %d vertices).\n",
24642            floorlist->len(), ceillist->len(), ptlist->len());
24643   }
24644 
24645   // symbolic = 1;
24646   
24647   // Initialize the cavity C.
24648   initializecavity(floorlist, ceillist, frontlist);
24649   // Form the D of the vertices of C.
24650   delaunizecavvertices(oldtet, ptlist, NULL, newtetlist, flipque);
24651   
24652   // Identify faces of C in D.
24653   if (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
24654     // Some faces are missing.
24655     recenttet = * (triface *)(* newtetlist)[0];
24656     assert((recenttet.tet != dummytet) && !isdead(&recenttet));
24657     // Try to recover missing faces by flips.
24658     do {
24659       facenum = misfrontlist->len();
24660       for (i = 0; i < misfrontlist->len(); i++) {
24661         // Get a missing front f.
24662         misfront = * (triface *)(* misfrontlist)[i];
24663         // Let f face toward the inside of C.
24664         adjustedgering(misfront, CW);
24665         if (b->verbose > 1) {
24666           printf("    Recover face (%d, %d, %d).\n", pointmark(org(misfront)),
24667                  pointmark(dest(misfront)), pointmark(apex(misfront)));
24668         }
24669         if (recoverfront(&misfront, newtetlist, flipque)) {
24670           // f has been recovered.
24671           frontlist->append(&misfront);
24672           misfrontlist->del(i, 0); i--;
24673         }
24674         // Flip non-locally non-constrained Delaunay faces.
24675         repairflips(flipque);
24676       }
24677       // Have all faces been recovered?
24678       if (misfrontlist->len() == 0) break;
24679       // No! There are still un-recovered faces. Continue the loop if any
24680       //   face has been recovered.
24681     } while (misfrontlist->len() < facenum);
24682     // Retrieve new tets and purge dead tets in D.
24683     retrievenewtets(newtetlist);
24684   }
24685   
24686   // symbolic = 0;
24687 
24688   if (misfrontlist->len() == 0) {
24689     // All fronts have identified in D. Get the shape of C by removing out
24690     //   tets of C. 'misfrontlist' is reused for removing out tets.
24691     //   Don't do flip since the new tets may get deleted later.
24692     carvecavity(newtetlist, misfrontlist, NULL);
24693     // Recover locally Delaunay faces.
24694     // flip(flipque, NULL);
24695     return true;
24696   } else {
24697     // Fail to tetrahedralize C.
24698     // Remove aux subfaces.
24699     detachauxsubfaces(newtetlist);
24700     // Remove new tets.
24701     for (i = 0; i < newtetlist->len(); i++) {
24702       newtet = * (triface *)(* newtetlist)[i];
24703       assert(!isdead(&newtet));
24704       tetrahedrondealloc(newtet.tet);
24705     }
24706     newtetlist->clear();
24707     // Restore faces of C in frontlist.
24708     for (i = 0; i < misfrontlist->len(); i++) {
24709       misfront = * (triface *)(* misfrontlist)[i];
24710       frontlist->append(&misfront);
24711     }
24712     return false;
24713   }
24714 }
24715 
24717 //                                                                           //
24718 // expandsteinercavity()    Expand the cavity of a Steiner point.            //
24719 //                                                                           //
24720 // Expand the cavity C if there fronts (except fronts having subfaces) which //
24721 // are either (nearly) coplanar or invisible by the Steiner point.           //
24722 //                                                                           //
24724 
24725 void tetgenmesh::expandsteinercavity(point steinpt, REAL eps, list* frontlist,
24726   list* oldtetlist)
24727 {
24728   triface front, symfront, newfront, oldfront;
24729   face frontsh;
24730   point pa, pb, pc;
24731   REAL ori;
24732   bool expflag, newflag;
24733   int i, j;
24734 
24735   do {
24736     expflag = false;
24737     for (i = 0; i < frontlist->len(); i++) {
24738       // Get a front f.
24739       front =  * (triface *)(* frontlist)[i];
24740       // f can be expanded if it is not a subface.
24741       tspivot(front, frontsh);
24742       if (frontsh.sh == dummysh) {
24743         // Let f face to the inside of C.
24744         adjustedgering(front, CW);
24745         pa = org(front);
24746         pb = dest(front);
24747         pc = apex(front);
24748         ori = orient3d(pa, pb, pc, steinpt);
24749         if (ori != 0.0) {
24750           if (iscoplanar(pa, pb, pc, steinpt, ori, eps)) {
24751             ori = 0.0; // f is nearly coplanar with p.
24752           }
24753         }
24754         if (ori >= 0.0) {
24755           // f is either invisible or coplanar with p.
24756           if (b->verbose > 2) {
24757             printf("    Remove front (%d, %d, %d).\n", pointmark(pa),
24758                    pointmark(pb), pointmark(pc));
24759           }
24760           frontlist->del(i, 1);
24761           expflag = true;
24762           break;
24763         }
24764       }
24765     }
24766     if (expflag) {
24767       assert(!infected(front) && (oppo(front) != NULL));
24768       // Expand C at f by including new fronts.
24769       adjustedgering(front, CCW);
24770       for (i = 0; i < 3; i++) {
24771         newflag = true;
24772         // Get a new boundary n of the cavity.
24773         fnext(front, symfront);
24774         tspivot(symfront, frontsh);
24775         sym(symfront, newfront);
24776         if (frontsh.sh == dummysh) {
24777           assert(newfront.tet != dummytet);
24778           // Is n a front of the unexp. cavity?
24779           if (infected(newfront)) {
24780             for (j = 0; j < frontlist->len(); j++) {
24781               oldfront = * (triface *)(* frontlist)[j];
24782               if ((oldfront.tet == symfront.tet) &&
24783                   (oldfront.loc == symfront.loc)) {
24784                 // n is not a front anymore.
24785                 if (b->verbose > 2) {
24786                   printf("    Remove front (%d, %d, %d).\n",
24787                          pointmark(org(oldfront)), pointmark(dest(oldfront)),
24788                          pointmark(apex(oldfront)));
24789                 }
24790                 frontlist->del(j, 1);
24791                 newflag = false;
24792                 break;
24793               }
24794             }
24795           }
24796         } else {
24797           // n is a subface.
24798           if (newfront.tet == dummytet) {
24799             sesymself(frontsh);
24800             // Create a fake tet to hold n.
24801             maketetrahedron(&newfront);
24802             setorg(newfront, sorg(frontsh));
24803             setdest(newfront, sdest(frontsh));
24804             setapex(newfront, sapex(frontsh));
24805             setoppo(newfront, (point) NULL);
24806             tsbond(newfront, frontsh);
24807           } else {
24808             // n should not be a front of cavity yet.
24809             assert(!infected(newfront));
24810           }
24811         }
24812         if (newflag) {
24813           if (b->verbose > 2) {
24814             printf("    Add front (%d, %d, %d).\n", pointmark(org(newfront)),
24815                    pointmark(dest(newfront)), pointmark(apex(newfront)));
24816           }
24817           frontlist->append(&newfront);
24818         }
24819         enextself(front);
24820       }
24821       // Add f into oldtetlist (to be deleted).
24822       infect(front);
24823       oldtetlist->append(&front);
24824       expcavcount++;
24825     }
24826   } while (expflag);
24827 }
24828 
24830 //                                                                           //
24831 // findrelocatepoint()    Find new location for relocating a point.          //
24832 //                                                                           //
24833 // 'frontlist' contains the boundary faces of the cavity C.  Some fronts are //
24834 // visible by 'stpt' p, some are coplanar with p.                            //
24835 //                                                                           //
24837 
24838 bool tetgenmesh::findrelocatepoint(point sp, point np, REAL* n,
24839   list* frontlist, list* oldtetlist)
24840 {
24841   triface front;
24842   point pa, pb, pc;
24843   REAL tp[3], tvol, mvol;
24844   REAL ori, eps;
24845   bool visible;
24846   int i, j, k;
24847 
24848   if (b->verbose > 1) {
24849     printf("    Find new location for point %d.\n", pointmark(sp));
24850   }
24851 
24852   // Avoid compilation warnings.
24853   tvol = mvol = 0.0;
24854   visible = false;
24855 
24856   eps = b->epsilon;
24857   // Initialize np far enough from p (outside C).
24858   for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24859   // Let tp = np;
24860   for (i = 0; i < 3; i++) tp[i] = np[i];
24861   // Interation to adjust np until it is visible by all fronts.
24862   j = 0;
24863   do {
24864     for (i = 0; i < frontlist->len(); i++) {
24865       // Get a front face f.
24866       front = * (triface *)(* frontlist)[i];
24867       // Let f face to the interior of C.
24868       adjustedgering(front, CW);
24869       pa = org(front);
24870       pb = dest(front);
24871       pc = apex(front);
24872       ori = orient3d(pa, pb, pc, np);
24873       visible = (ori < 0.0);
24874       if (!visible) {
24875         // A front is invisible by np. Move it towards p along the normal.
24876         for (i = 0; i < 3; i++) np[i] = sp[i] + 0.5 * (sp[i] - np[i]);
24877         // Failed if tp = np.
24878         if ((tp[0] == np[0]) && (tp[1] == np[1]) && (tp[2] == np[2])) {
24879           // Try to expand the cavity.
24880           expandsteinercavity(sp, eps, frontlist, oldtetlist);
24881           eps *= 10.0;
24882           if (eps > b->epsilon * 1000.0) {
24883           // printf("Internal error: Fail to relocate pt %d.\n",pointmark(sp));
24884             // internalerror();
24885             return false;
24886           }
24887           // Restart the point relocation.
24888           for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24889         }
24890         if (j % 2) {
24891           // Set tp = np (at every 2 steps) to catch the stop state.
24892           for (i = 0; i < 3; i++) tp[i] = np[i];
24893         }
24894         break;
24895       } else {
24896         // Save the smallest volume.
24897         if (i == 0) {
24898           mvol = fabs(ori);
24899         } else {
24900           mvol = fabs(ori) < mvol ? fabs(ori) : mvol;
24901         }
24902       }
24903     }
24904     j++;
24905   } while (!visible);
24906   
24907   if (b->verbose > 1) {
24908     printf("    %d iterations. minvol = %.12g.\n", j, mvol);
24909   }
24910 
24911   // Continue to adjust np until the minimal volume of tets formed by
24912   //   fronts and np doesn't increase (all fronts are visible by np).
24913   k = 0;
24914   do {
24915     j = 0;
24916     do {
24917       if (k == 0) {
24918         // Initial tp := np + 0.9 * (p - np). Move toward p.
24919         for (i = 0; i < 3; i++) tp[i] = sp[i] + 0.9 * (np[i] - sp[i]);
24920       } else {
24921         // Initial tp := np + 1.1 * (p - np). Move away from p.
24922         for (i = 0; i < 3; i++) tp[i] = sp[i] + 1.1 * (np[i] - sp[i]);
24923       }
24924       // Get the minial volume formed by tp with one of the fronts.
24925       for (i = 0; i < frontlist->len(); i++) {
24926         // Get a front face f.
24927         front = * (triface *)(* frontlist)[i];
24928         // Let f face to the interior of C.
24929         adjustedgering(front, CW);
24930         pa = org(front);
24931         pb = dest(front);
24932         pc = apex(front);
24933         ori = orient3d(pa, pb, pc, tp);
24934         visible = (ori < 0.0);
24935         if (visible) {
24936           // Save the smallest volume.
24937           if (i == 0) {
24938             tvol = fabs(ori);
24939           } else {
24940             tvol = fabs(ori) < tvol ? fabs(ori) : tvol;
24941           }
24942         } else {
24943           // A front is invisible by tp. Stop.
24944           tvol = 0.0;
24945           break;
24946         }
24947       }
24948       if (tvol > mvol) {
24949         // Get a larger minimal volume.
24950         for (i = 0; i < 3; i++) np[i] = tp[i];
24951         mvol = tvol;
24952       } else {
24953         // Minimal volume decreases. Stop.
24954         break;
24955       }
24956       // Continue to adjust np.
24957       j++;
24958     } while (true);
24959     // Has np been adjusted?
24960     if (j > 0) break;
24961     // Try to move np to anoter direction.
24962     k++;
24963   } while (k < 2);
24964 
24965   if (b->verbose > 1) {
24966     printf("    %d adjust iterations. minvol = %.12g.\n", j, mvol);
24967   }
24968   return true;
24969 }
24970 
24972 //                                                                           //
24973 // relocatepoint()    Relocate a point into the cavity.                      //
24974 //                                                                           //
24975 // 'frontlist' contains the boundary faces of the cavity C. All fronts must  //
24976 // be visible by 'steinpt'.  Some fronts may hold by 'fake' tets (they are   //
24977 // hull faces).  Fake tets will be removed when they're finished.            //
24978 //                                                                           //
24980 
24981 void tetgenmesh::relocatepoint(point steinpt, triface* oldtet, list* frontlist,
24982   list* newtetlist, queue* flipque)
24983 {
24984   triface front, newtet, newface, neightet;
24985   face checksh;
24986   point pa, pb;
24987   REAL attrib, volume;
24988   bool bdflag;
24989   int i, j, k, l;
24990 
24991   if (b->verbose > 1) {
24992     printf("    Insert Steiner point (%.12g, %.12g, %.12g) %d.\n",
24993            steinpt[0], steinpt[1], steinpt[2], pointmark(steinpt));
24994   }
24995   // Clear the list first.
24996   newtetlist->clear();
24997 
24998   // Create the tets formed by fronts and 'steinpt'.
24999   for (i = 0; i < frontlist->len(); i++) {
25000     // Get a front f.
25001     front = * (triface *)(* frontlist)[i];
25002     // Let f face inside C. (f is a face of tet adjacent to C).
25003     adjustedgering(front, CW);
25004     if (b->verbose > 2) {
25005       printf("    Get front (%d, %d, %d).\n", pointmark(org(front)),
25006              pointmark(dest(front)), pointmark(apex(front)));
25007     }
25008     maketetrahedron(&newtet);
25009     newtetlist->append(&newtet);
25010     setorg(newtet, org(front));
25011     setdest(newtet, dest(front));
25012     setapex(newtet, apex(front));
25013     setoppo(newtet, steinpt);
25014     if (oldtet != (triface *) NULL) {
25015       for (j = 0; j < in->numberoftetrahedronattributes; j++) {
25016         attrib = elemattribute(oldtet->tet, j);
25017         setelemattribute(newtet.tet, j, attrib);
25018       }
25019       if (b->varvolume) {
25020         volume = volumebound(oldtet->tet);
25021         setvolumebound(newtet.tet, volume);
25022       }
25023     }
25024     // 'front' may be a 'fake' tet.
25025     tspivot(front, checksh);
25026     if (oppo(front) == (point) NULL) {
25027       if (checksh.sh != dummysh) {
25028         stdissolve(checksh);
25029       }
25030       // Dealloc the 'fake' tet.
25031       tetrahedrondealloc(front.tet);
25032       // This side (newtet) is a boundary face, let 'dummytet' bond to it.
25033       //   Otherwise, 'dummytet' may point to a dead tetrahedron after the
25034       //   old cavity tets are removed.
25035       dummytet[0] = encode(newtet);
25036     } else {
25037       // Bond two tetrahedra, also dissolve the old bond at 'front'.
25038       bond(newtet, front);
25039     }
25040     if (checksh.sh != dummysh) {
25041       sesymself(checksh);
25042       tsbond(newtet, checksh);
25043     }
25044     if (flipque != (queue *) NULL) {
25045       // f may be non-locally Delaunay and flipable.
25046       enqueueflipface(newtet, flipque);
25047     }
25048     // The three neighbors are open. Will be finished later.
25049   }
25050 
25051   // Connect new tets in C. All connecting faces must contain 'steinpt'.
25052   for (i = 0; i < newtetlist->len(); i++) {
25053     newtet = * (triface *)(* newtetlist)[i];
25054     newtet.ver = 0;
25055     for (j = 0; j < 3; j++) {
25056       fnext(newtet, newface);
25057       sym(newface, neightet);
25058       if (neightet.tet == dummytet) {
25059         // Find a neightet to connect it.
25060         bdflag = false;
25061         pa = org(newface);
25062         pb = dest(newface);
25063         assert(apex(newface) == steinpt);
25064         for (k = i + 1; k < newtetlist->len() && !bdflag; k++) {
25065           neightet = * (triface *)(* newtetlist)[k];
25066           neightet.ver = 0;
25067           for (l = 0; l < 3; l++) {
25068             if ((org(neightet) == pa && dest(neightet) == pb) ||
25069                 (org(neightet) == pb && dest(neightet) == pa)) {
25070               // Find the neighbor.
25071               fnextself(neightet);
25072               assert(apex(neightet) == steinpt);
25073               // Now neightet is a face same as newface, bond them.
25074               bond(newface, neightet);
25075               bdflag = true;
25076               break;
25077             }
25078             enextself(neightet);
25079           }
25080         }
25081         assert(bdflag);
25082       }
25083       enextself(newtet);
25084     }
25085     // Let the corners of newtet point to it for fast searching.
25086     pa = org(newtet);
25087     setpoint2tet(pa, encode(newtet));
25088     pa = dest(newtet);
25089     setpoint2tet(pa, encode(newtet));
25090     pa = apex(newtet);
25091     setpoint2tet(pa, encode(newtet));
25092     pa = oppo(newtet);
25093     setpoint2tet(pa, encode(newtet));
25094   }
25095 
25096   if (flipque != (queue *) NULL) { 
25097     // Recover locally Delaunay faces.
25098     flip(flipque, NULL);
25099   }
25100 }
25101 
25103 //                                                                           //
25104 // findcollapseedge()    Find collapseable edge to suppress an endpoint.     //
25105 //                                                                           //
25107 
25108 bool tetgenmesh::findcollapseedge(point suppt, point *conpt, list* oldtetlist,
25109   list* ptlist)
25110 {
25111   triface front;
25112   point pt, pa, pb, pc;
25113   REAL *lenarray, ltmp, ori;
25114   bool visflag;
25115   int *idxarray, itmp;
25116   int n, i, j;
25117 
25118   if (b->verbose > 2) {
25119     printf("    Search an edge (in %d edges) for collapse %d.\n",
25120            ptlist->len(), pointmark(suppt));
25121   }
25122 
25123   // Candidate edges are p to the points of B(p) (in 'ptlist').
25124   n = ptlist->len();
25125   lenarray = new REAL[n];
25126   idxarray = new int[n];
25127   // Sort the points of B(p) by distance to p.
25128   for (i = 0; i < n; i++) {
25129     pt = * (point *)(* ptlist)[i];
25130     lenarray[i] = distance(suppt, pt);
25131     idxarray[i] = i;
25132   }
25133   // Bubble sort.
25134   for (i = 0; i < n - 1; i++) {
25135     for (j = 0; j < n - 1 - i; j++) {
25136       if (lenarray[j + 1] < lenarray[j]) {  // compare the two neighbors
25137         ltmp = lenarray[j];           // swap a[j] and a[j + 1]
25138         lenarray[j] = lenarray[j + 1];
25139         lenarray[j + 1] = ltmp;
25140         itmp = idxarray[j];           // swap a[j] and a[j + 1]
25141         idxarray[j] = idxarray[j + 1];
25142         idxarray[j + 1] = itmp;
25143       }
25144     }
25145   }
25146   // For each point q of B(p), test if the edge (p, q) can be collapseed.
25147   for (i = 0; i < n; i++) {
25148     pt = * (point *)(* ptlist)[idxarray[i]];
25149     // Is q visible by faces of B(p) not with q as a vertex.
25150     lenarray[i] = 0.0; // zero volume.
25151     visflag = true;
25152     for (j = 0; j < oldtetlist->len() && visflag; j++) {
25153       front = * (triface *)(* oldtetlist)[j];
25154       // Let f face to inside of B(p).
25155       adjustedgering(front, CCW);
25156       pa = org(front);
25157       pb = dest(front);
25158       pc = apex(front);
25159       // Is f contains q?
25160       if ((pa != pt) && (pb != pt) && (pc != pt)) {
25161         ori = orient3d(pa, pb, pc, pt);
25162         if (ori != 0.0) {
25163           if (iscoplanar(pa, pb, pc, pt, ori, b->epsilon * 1e+2)) ori = 0.0;
25164         }
25165         visflag = ori < 0.0;
25166         if (visflag) {
25167           // Visible, set the smallest volume.
25168           if (j == 0) {
25169             lenarray[i] = fabs(ori);
25170           } else {
25171             lenarray[i] = fabs(ori) < lenarray[i] ? fabs(ori) : lenarray[i];
25172           }
25173         } else {
25174           // Invisible. Do not collapse (p, q).
25175           lenarray[i] = 0.0;
25176         }
25177       }
25178     }
25179     if ((b->verbose > 2) && visflag) {
25180       printf("    Got candidate %d vol(%g).\n", pointmark(pt), lenarray[i]);
25181     }
25182   }
25183 
25184   // Select the largest non-zero volume (result in ltmp).
25185   ltmp = lenarray[0];
25186   itmp = idxarray[0];
25187   for (i = 1; i < n; i++) {
25188     if (lenarray[i] != 0.0) {
25189       if (lenarray[i] > ltmp) {
25190         ltmp = lenarray[i];
25191         itmp = idxarray[i]; // The index to find the point.
25192       }
25193     }
25194   }
25195 
25196   delete [] lenarray;
25197   delete [] idxarray;
25198 
25199   if (ltmp == 0.0) {
25200     // No edge can be collapseed.
25201     *conpt = (point) NULL;
25202     return false;
25203   } else {
25204     pt = * (point *)(* ptlist)[itmp];
25205     *conpt = pt;
25206     return true;
25207   }
25208 }
25209 
25211 //                                                                           //
25212 // collapseedge()    Remove a point by edge collapse.                        //
25213 //                                                                           //
25215 
25216 void tetgenmesh::collapseedge(point suppt, point conpt, list* oldtetlist,
25217   list* deadtetlist)
25218 {
25219   triface oldtet, deadtet;
25220   triface adjtet1, adjtet2;
25221   face adjsh;
25222   point pa, pb, pc;
25223   int i, j;
25224 
25225   if (b->verbose > 2) {
25226     printf("    Collapse edge (%d,%d).\n", pointmark(suppt), pointmark(conpt));
25227   }
25228 
25229   // Loop in B(p), replace p with np, queue dead tets, uninfect old tets.
25230   for (i = 0; i < oldtetlist->len(); i++) {
25231     oldtet = * (triface *)(* oldtetlist)[i]; // assert(infected(oldtet));
25232     uninfect(oldtet);
25233     pa = org(oldtet);
25234     pb = dest(oldtet);
25235     pc = apex(oldtet);
25236     assert(oppo(oldtet) == suppt);
25237     setoppo(oldtet, conpt);
25238     if ((pa == conpt) || (pb == conpt) || (pc == conpt)) {
25239       deadtetlist->append(&oldtet); // a collpased tet.
25240     }
25241   }
25242   // Loop in deadtetlist, glue adjacent tets of dead tets.
25243   for (i = 0; i < deadtetlist->len(); i++) {
25244     deadtet = * (triface *)(* deadtetlist)[i];
25245     // Get the adjacent tet n1 (outside B(p)).
25246     sym(deadtet, adjtet1);
25247     tspivot(deadtet, adjsh);
25248     // Find the edge in deadtet opposite to conpt.
25249     adjustedgering(deadtet, CCW);
25250     for (j = 0; j < 3; j++) {
25251       if (apex(deadtet) == conpt) break;
25252       enextself(deadtet);
25253     }
25254     assert(j < 3);
25255     // Get another adjacent tet n2.
25256     fnext(deadtet, adjtet2);
25257     symself(adjtet2);
25258     assert(adjtet2.tet != dummytet); // n2 is inside B(p).
25259     if (adjtet1.tet != dummytet) {
25260       bond(adjtet1, adjtet2); // Bond n1 <--> n2.
25261     } else {
25262       dissolve(adjtet2); // Dissolve at n2.
25263       dummytet[0] = encode(adjtet2); // Let dummytet holds n2.
25264     }
25265     if (adjsh.sh != dummysh) {
25266       tsbond(adjtet2, adjsh); // Bond s <--> n2.
25267     }
25268     // Collapse deadtet.
25269     tetrahedrondealloc(deadtet.tet);
25270   }
25271   deadtetlist->clear();
25272 }
25273 
25275 //                                                                           //
25276 // deallocfaketets()    Deleted fake tets at fronts.                         //
25277 //                                                                           //
25278 // This routine is only called when the findrelocatepoint() routine fails.   //
25279 // In other cases, the fake tets are removed automatically in carvecavity()  //
25280 // or relocatepoint().                                                       //
25281 //                                                                           //
25283 
25284 void tetgenmesh::deallocfaketets(list* frontlist)
25285 {
25286   triface front, neightet;
25287   face checksh;
25288   bool infectflag;
25289   int i;
25290 
25291   for (i = 0; i < frontlist->len(); i++) {
25292     // Get a front f.
25293     front = * (triface *)(* frontlist)[i];
25294     // Let f face inside C. (f is a face of tet adjacent to C).
25295     adjustedgering(front, CW);
25296     sym(front, neightet);
25297     tspivot(front, checksh);
25298     if (oppo(front) == (point) NULL) {
25299       if (b->verbose > 2) {
25300         printf("    Get fake tet (%d, %d, %d).\n", pointmark(org(front)),
25301                pointmark(dest(front)), pointmark(apex(front)));
25302       }
25303       if (neightet.tet != dummytet) {
25304         // The neightet may be infected. After dissolve it, the infect flag
25305         //   will be lost. Save the flag and restore it later.
25306         infectflag = infected(neightet);
25307         dissolve(neightet);
25308         if (infectflag) {
25309           infect(neightet);
25310         }
25311       }
25312       if (checksh.sh != dummysh) {
25313         infectflag = sinfected(checksh);
25314         stdissolve(checksh);
25315         if (infectflag) {
25316           sinfect(checksh);
25317         }
25318       }
25319       // Dealloc the 'fake' tet.
25320       tetrahedrondealloc(front.tet);
25321       // If 'neightet' is a hull face, let 'dummytet' bond to it. It is
25322       //   a 'dummytet' when this front was created from a new subface.
25323       //   In such case, it should not be bounded.
25324       if (neightet.tet != dummytet) {
25325         dummytet[0] = encode(neightet);
25326       }
25327     }
25328   }
25329 }
25330 
25332 //                                                                           //
25333 // restorepolyhedron()    Restore the tetrahedralization in a polyhedron.    //
25334 //                                                                           //
25335 // This routine is only called when the operation of suppressing a point is  //
25336 // aborted (eg., findrelocatepoint() routine fails). The polyhedron has been //
25337 // remeshed by new tets. This routine restore the old tets in it.            //
25338 //                                                                           //
25339 // 'oldtetlist' contains the list of old tets. Each old tet t_o assumes that //
25340 // it still connects to a tet t_b of the mesh, however, t_b does not connect //
25341 // to t_o, this routine resets the connection such that t_b <--> t_o.        //
25342 //                                                                           //
25344 
25345 void tetgenmesh::restorepolyhedron(list* oldtetlist)
25346 {
25347   triface oldtet, neightet, neineitet;
25348   face checksh;
25349   int i;
25350 
25351   for (i = 0; i < oldtetlist->len(); i++) {
25352     // Get an old tet t_o.
25353     oldtet = * (triface *)(* oldtetlist)[i];
25354     // Check the four sides of t_o.
25355     for (oldtet.loc = 0; oldtet.loc < 4; oldtet.loc++) {
25356       sym(oldtet, neightet);
25357       tspivot(oldtet, checksh);
25358       if (neightet.tet != dummytet) {
25359         sym(neightet, neineitet);
25360         if (neineitet.tet != oldtet.tet) {
25361           // This face of t_o is a boundary of P.
25362           bond(neightet, oldtet);
25363           if (checksh.sh != dummysh) {
25364             tsbond(oldtet, checksh);
25365           }
25366         }
25367       } else {
25368         // t_o has a hull face. It should be the boundary of P.
25369 #ifdef SELF_CHECK
25370         assert(checksh.sh != dummysh);
25371         stpivot(checksh, neineitet);
25372         assert(neineitet.tet != oldtet.tet);
25373 #endif
25374         tsbond(oldtet, checksh);
25375         // Let dummytet[0] points to it.
25376         dummytet[0] = encode(oldtet);
25377       }
25378     }
25379   }
25380 }
25381 
25383 //                                                                           //
25384 // suppressfacetpoint()    Suppress a point inside a facet.                  //
25385 //                                                                           //
25386 // The point p inside a facet F will be suppressed from F by either being    //
25387 // deleted from the mesh or being relocated into the volume.                 //
25388 //                                                                           //
25389 // 'supsh' is a subface f of F, and p = sapex(f); the other parameters are   //
25390 // working lists which are empty at the beginning and the end.               //
25391 //                                                                           //
25392 // 'optflag' is used for mesh optimization. If it is set, after removing p,  //
25393 // test the object function on each new tet, queue bad tets.                 //
25394 //                                                                           //
25396 
25397 bool tetgenmesh::suppressfacetpoint(face* supsh, list* frontlist,
25398   list* misfrontlist, list* ptlist, list* conlist, memorypool* viri,
25399   queue* flipque, bool noreloc, bool optflag)
25400 {
25401   list *oldtetlist[2], *newtetlist[2];
25402   list *oldshlist, *newshlist;
25403   triface oldtet, newtet;
25404   face oldsh, newsh;
25405   point suppt, newpt[2];
25406   point *cons;
25407   REAL norm[3];
25408   bool success;
25409   int shmark;
25410   int i, j;
25411 
25412   suppt = sapex(*supsh);
25413   if (b->verbose > 1) {
25414     printf("    Suppress point %d in facet.\n", pointmark(suppt));
25415   }
25416 
25417   // Initialize working lists, variables.
25418   for (i = 0; i < 2; i++) {
25419     oldtetlist[i] = (list *) NULL;
25420     newtetlist[i] = (list *) NULL;
25421     newpt[i] = (point) NULL;
25422   }
25423   oldshlist = new list(sizeof(face), NULL, 256);
25424   newshlist = new list(sizeof(face), NULL, 256);
25425   success = true; // Assume p can be suppressed.
25426 
25427   // Find subs of C(p).
25428   oldshlist->append(supsh);
25429   formstarpolygon(suppt, oldshlist, ptlist);
25430   // Get the edges of C(p). They form a closed polygon.
25431   for (i = 0; i < oldshlist->len(); i++) {
25432     oldsh = * (face *)(* oldshlist)[i];    
25433     cons = (point *) conlist->append(NULL);
25434     cons[0] = sorg(oldsh);
25435     cons[1] = sdest(oldsh);
25436   }
25437   // Re-triangulate the old C(p).
25438   shmark = shellmark(*supsh);
25439   triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25440   // Get new subs of C(p), remove protected segments.
25441   retrievenewsubs(newshlist, true);
25442   // Substitute the old C(p) with the new C(p)
25443   replacepolygonsubs(oldshlist, newshlist);
25444   // Clear work lists.
25445   ptlist->clear();
25446   conlist->clear();
25447   flipque->clear();
25448   viri->restart();
25449 
25450   // B(p) (tets with p as a vertex) has been separated into two parts
25451   //   (B_0(p) and B_1(p)) by F. Process them individually.
25452   for (i = 0; i < 2 && success; i++) { 
25453     if (i == 1) sesymself(*supsh);
25454     // Get a tet containing p.
25455     stpivot(*supsh, oldtet);
25456     // Is this part empty?
25457     if (oldtet.tet == dummytet) continue;
25458     // Allocate spaces for storing (old and new) B_i(p).
25459     oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25460     newtetlist[i] = new list(sizeof(triface), NULL, 256);
25461     // Form old B_i(p) in oldtetlist[i].
25462     assert(!isdead(&oldtet));
25463     oldtetlist[i]->append(&oldtet);
25464     formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25465     // Infect the tets in old B_i(p) (they're going to be delete).
25466     for (j = 0; j < oldtetlist[i]->len(); j++) {
25467       oldtet = * (triface *)(* (oldtetlist[i]))[j];
25468       infect(oldtet);
25469     }
25470     // Preparation for re-tetrahedralzing old B_i(p).
25471     orientnewsubs(newshlist, supsh, norm);
25472     // Tetrahedralize old B_i(p).
25473     success = constrainedcavity(&oldtet, newshlist, oldtetlist[i], ptlist,
25474                 frontlist, misfrontlist, newtetlist[i], flipque);
25475     // If p is not suppressed, do relocation if 'noreloc' is not set.
25476     if (!success && !noreloc) {
25477       // Try to relocate p into the old B_i(p).
25478       makepoint(&(newpt[i]));
25479       success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25480                                   oldtetlist[i]);
25481       // Initialize newpt = suppt.
25482       // for (j = 0; j < 3; j++) newpt[i][j] = suppt[j];
25483       // success = smoothvolpoint(newpt[i], frontlist, true);
25484       if (success) {
25485         // p is relocated by newpt[i]. Now insert it. Don't do flip since
25486         //   the new tets may get deleted again.
25487         relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25488         setpointtype(newpt[i], FREEVOLVERTEX);
25489         relverts++;
25490       } else {
25491         // Fail to relocate p. Clean fake tets and quit this option.
25492         deallocfaketets(frontlist);
25493         pointdealloc(newpt[i]);
25494         newpt[i] = (point) NULL;
25495         assert(newtetlist[i]->len() == 0);
25496       }
25497     }
25498     if (!success && noreloc) {
25499       // Failed and no point relocation. Clean fake tets.
25500       deallocfaketets(frontlist);
25501     }
25502     // Clear work lists.
25503     ptlist->clear();
25504     frontlist->clear();
25505     misfrontlist->clear();
25506     flipque->clear();
25507   }
25508 
25509   if (success) {
25510     // p has been removed! (Still in the pool).
25511     setpointtype(suppt, UNUSEDVERTEX);
25512     unuverts++;
25513     // Delete old C(p).
25514     for (i = 0; i < oldshlist->len(); i++) {
25515       oldsh = * (face *)(* oldshlist)[i];
25516       if (i == 0) {
25517         // Update the 'hullsize' if C(p) is on the hull.
25518         stpivot(oldsh, oldtet);
25519         if (oldtet.tet != dummytet) {
25520           sesymself(oldsh);
25521           stpivot(oldsh, oldtet);
25522         }
25523         if (oldtet.tet == dummytet) {
25524           // A boundary face. Update the 'hullsize'.
25525           j = oldshlist->len() - newshlist->len();
25526           assert(j > 0);
25527           hullsize -= j;
25528         }
25529       }
25530       shellfacedealloc(subfaces, oldsh.sh);
25531     }
25532     // Delete old B_i(p).
25533     for (i = 0; i < 2; i++) {
25534       if (oldtetlist[i] != (list *) NULL) {
25535         // Delete tets of the old B_i(p).
25536         for (j = 0; j < oldtetlist[i]->len(); j++) {
25537           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25538           assert(!isdead(&oldtet));
25539           tetrahedrondealloc(oldtet.tet);
25540         }
25541       }
25542     }
25543     if (optflag) {
25544       // Check for new bad-quality tets.
25545       for (i = 0; i < 2; i++) {
25546         if (newtetlist[i] != (list *) NULL) {
25547           for (j = 0; j < newtetlist[i]->len(); j++) {
25548             newtet = * (triface *)(* (newtetlist[i]))[j];
25549             if (!isdead(&newtet)) checktet4opt(&newtet, true);
25550           }
25551         }
25552       }
25553     }
25554   } else {
25555     // p is not suppressed. Recover the original state.
25556     unsupverts++;
25557     // Restore the old C(p).
25558     replacepolygonsubs(newshlist, oldshlist);
25559     // Delete subs of the new C(p)
25560     for (i = 0; i < newshlist->len(); i++) {
25561       newsh = * (face *)(* newshlist)[i];
25562       shellfacedealloc(subfaces, newsh.sh);
25563     }
25564     // Restore old B_i(p).
25565     for (i = 0; i < 2; i++) {
25566       if (oldtetlist[i] != (list *) NULL) {
25567         // Uninfect tets of old B_i(p).
25568         for (j = 0; j < oldtetlist[i]->len(); j++) {
25569           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25570           assert(infected(oldtet));
25571           uninfect(oldtet);
25572         }
25573         // Has it been re-meshed?
25574         if (newtetlist[i]->len() > 0) {
25575           // Restore the old B_i(p).
25576           restorepolyhedron(oldtetlist[i]);
25577           // Delete tets of the new B_i(p);
25578           for (j = 0; j < newtetlist[i]->len(); j++) {
25579             newtet = * (triface *)(* (newtetlist[i]))[j];
25580             // Some new tets may already be deleted (by carvecavity()).
25581             if (!isdead(&newtet)) {
25582               tetrahedrondealloc(newtet.tet);
25583             }
25584           }
25585         }
25586         // Dealloc newpt[i] if it exists.
25587         if (newpt[i] != (point) NULL) {
25588           pointdealloc(newpt[i]);
25589           relverts--;
25590         }
25591       }
25592     }
25593   }
25594 
25595   // Delete work lists.
25596   delete oldshlist;
25597   delete newshlist;
25598   for (i = 0; i < 2; i++) {
25599     if (oldtetlist[i] != (list *) NULL) {
25600       delete oldtetlist[i];
25601       delete newtetlist[i];
25602     }
25603   }
25604 
25605   return success;
25606 }
25607 
25609 //                                                                           //
25610 // suppresssegpoint()    Suppress a point on a segment.                      //
25611 //                                                                           //
25612 // The point p on a segment S will be suppressed from S by either being      //
25613 // deleted from the mesh or being relocated into the volume.                 //
25614 //                                                                           //
25615 // 'supseg' is the segment S, and p = sdest(S); the other parameters are     //
25616 // working lists which are empty at the beginning and the end.               //
25617 //                                                                           //
25619 
25620 bool tetgenmesh::suppresssegpoint(face* supseg, list* spinshlist,
25621   list* newsegshlist, list* frontlist, list* misfrontlist, list* ptlist,
25622   list* conlist, memorypool* viri, queue* flipque, bool noreloc, bool optflag)
25623 {
25624   list **oldtetlist, **newtetlist;
25625   list **oldshlist, **newshlist;
25626   list *pnewshlist, *dnewshlist;
25627   triface oldtet, newtet;
25628   face oldsh, newsh;
25629   face startsh, spinsh, segsh1, segsh2;
25630   face nsupseg, newseg, prevseg, nextseg;
25631   point suppt, *newpt;
25632   point pa, pb, *cons;
25633   REAL pnorm[2][3], norm[3];
25634   bool success;
25635   int shmark;
25636   int n, i, j, k;
25637 
25638   // Get the Steiner point p.
25639   assert(supseg->shver < 2);
25640   suppt = sdest(*supseg);
25641   // Find the segment ab split by p.
25642   senext(*supseg, nsupseg);
25643   spivotself(nsupseg);
25644   assert(nsupseg.sh != dummysh);
25645   nsupseg.shver = 0;
25646   if (sorg(nsupseg) != suppt) sesymself(nsupseg);
25647   assert(sorg(nsupseg) == suppt);
25648   pa = sorg(*supseg);
25649   pb = sdest(nsupseg);
25650   if (b->verbose > 1) {
25651     printf("    Remove point %d on segment (%d, %d).\n",
25652            pointmark(suppt), pointmark(pa), pointmark(pb));
25653   }
25654 
25655   // Let startsh s containing p.
25656   spivot(*supseg, startsh);
25657   spinsh = startsh;
25658   do {
25659     // Save it in list.
25660     spinshlist->append(&spinsh);
25661     // Go to the next facet.
25662     spivotself(spinsh);
25663   } while (spinsh.sh != startsh.sh);
25664   if (spinshlist->len() == 1) {
25665     // This case has not handled yet.
25666     // printf("Unhandled case: segment only belongs to one facet.\n");
25667     spinshlist->clear();
25668     unsupverts++;
25669     return false;
25670   }
25671 
25672   // Suppose ab is shared by n facets (n > 1), then there are n B(p) (tets
25673   //   with p as a vertex). Some B(p) may be empty, eg, outside.
25674   n = spinshlist->len();
25675   oldtetlist = new list*[n];
25676   newtetlist = new list*[n];
25677   oldshlist = new list*[n];
25678   newshlist = new list*[n];
25679   newpt = new point[n];
25680   for (i = 0; i < n; i++) {
25681     oldtetlist[i] = (list *) NULL;
25682     newtetlist[i] = (list *) NULL;
25683     oldshlist[i] = (list *) NULL;
25684     newshlist[i] = (list *) NULL;
25685     newpt[i] = (point) NULL;
25686   }
25687 
25688   // Create a new segment ab (result in newseg).
25689   makeshellface(subsegs, &newseg);
25690   setsorg(newseg, pa);
25691   setsdest(newseg, pb);
25692   // ab gets the same mark and segment type as ap.
25693   setshellmark(newseg, shellmark(*supseg));
25694   setshelltype(newseg, shelltype(*supseg));
25695   if (b->quality && varconstraint) {
25696     // Copy the areabound into the new subsegment.
25697     setareabound(newseg, areabound(*supseg));
25698   }
25699   // Save the old connection at a.
25700   senext2(*supseg, prevseg);
25701   spivotself(prevseg);
25702   if (prevseg.sh != dummysh) {
25703     prevseg.shver = 0;
25704     if (sdest(prevseg) != pa) sesymself(prevseg);
25705     assert(sdest(prevseg) == pa);
25706     senextself(prevseg);
25707     senext2self(newseg);
25708     sbond(newseg, prevseg);
25709     newseg.shver = 0;
25710   }
25711   // Save the old connection at b.
25712   senext(nsupseg, nextseg);
25713   spivotself(nextseg);
25714   if (nextseg.sh != dummysh) {
25715     nextseg.shver = 0;
25716     if (sorg(nextseg) != pb) sesymself(nextseg);
25717     assert(sorg(nextseg) == pb);
25718     senext2self(nextseg);
25719     senextself(newseg);
25720     sbond(newseg, nextseg);
25721     newseg.shver = 0;
25722   }
25723 
25724   // Re-triangulate C(p) (subs with p as a vertex) to remove p.
25725   for (i = 0; i < spinshlist->len(); i++) {
25726     spinsh = * (face *)(* spinshlist)[i];
25727     // Allocate spaces for C_i(p).
25728     oldshlist[i] = new list(sizeof(face), NULL, 256);
25729     newshlist[i] = new list(sizeof(face), NULL, 256);
25730     // Get the subs of C_i(p).
25731     oldshlist[i]->append(&spinsh);
25732     formstarpolygon(suppt, oldshlist[i], ptlist);
25733     // Find the edges of C_i(p). It DOES NOT form a closed polygon.
25734     for (j = 0; j < oldshlist[i]->len(); j++) {
25735       oldsh = * (face *)(* (oldshlist[i]))[j];    
25736       cons = (point *) conlist->append(NULL);
25737       cons[0] = sorg(oldsh);
25738       cons[1] = sdest(oldsh);
25739     }
25740     // The C_i(p) isn't closed without ab. Add it to it.
25741     cons = (point *) conlist->append(NULL);
25742     cons[0] = pa;
25743     cons[1] = pb;
25744     // Re-triangulate C_i(p).
25745     shmark = shellmark(spinsh);
25746     triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25747     // Get new subs of C_i(p), remove protected segments.
25748     retrievenewsubs(newshlist[i], true);
25749     // Substitute old C_i(p) with the new C_i(p). !IT IS NOT COMPLETE!
25750     replacepolygonsubs(oldshlist[i], newshlist[i]);
25751     // Find the new subface s having edge ab.
25752     for (j = 0; j < newshlist[i]->len(); j++) {
25753       segsh1 = * (face *)(* (newshlist[i]))[j];
25754       for (k = 0; k < 3; k++) {
25755         if (((sorg(segsh1) == pa) && (sdest(segsh1) == pb)) ||
25756             ((sorg(segsh1) == pb) && (sdest(segsh1) == pa))) break;
25757         senextself(segsh1);
25758       }
25759       if (k < 3) break; // Found.
25760     }
25761     assert(j < newshlist[i]->len()); // ab must exist.
25762     // Bond s and ab together. The C_i(p) is completedly substituted.
25763     ssbond(segsh1, newseg);
25764     // Save s for forming the face ring of ab.
25765     newsegshlist->append(&segsh1);
25766     // Clear work lists.
25767     ptlist->clear();
25768     conlist->clear();
25769     flipque->clear();
25770     viri->restart();
25771   }
25772   // Form the face ring of ab.
25773   for (i = 0; i < newsegshlist->len(); i++) {
25774     segsh1 = * (face *)(* newsegshlist)[i];
25775     if ((i + 1) == newsegshlist->len()) {
25776       segsh2 = * (face *)(* newsegshlist)[0];
25777     } else {
25778       segsh2 = * (face *)(* newsegshlist)[i + 1];
25779     }
25780     sbond1(segsh1, segsh2);
25781   }
25782 
25783   // A work list for keeping subfaces from two facets.
25784   dnewshlist = new list(sizeof(face), NULL, 256);
25785   success = true; // Assume p is suppressable.
25786 
25787   // Suppress p in all B(p). B_i(p) is looped wrt the right-hand rule of ab.
25788   for (i = 0; i < spinshlist->len() && success; i++) {
25789     // Get an old  subface s (ap) of a facet.
25790     spinsh = * (face *)(* spinshlist)[i];
25791     // Let the edge direction of s be a->b. Hence all subfaces follow
25792     //   the right-hand rule of ab.
25793     if (sorg(spinsh) != pa) sesymself(spinsh);
25794     // Get a tet t of B_i(p).
25795     stpivot(spinsh, oldtet);
25796     // Is B_i(p) empty?
25797     if (oldtet.tet == dummytet) continue;
25798     // Allocate spaces for B_i(p).
25799     oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25800     newtetlist[i] = new list(sizeof(triface), NULL, 256);
25801     // Find all tets of old B_i(p).
25802     oldtetlist[i]->append(&oldtet);
25803     formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25804     // Infect tets of old B_i(p) (they're going to be deleted).
25805     for (j = 0; j < oldtetlist[i]->len(); j++) {
25806       oldtet = * (triface *)(* (oldtetlist[i]))[j];
25807       infect(oldtet);
25808     }
25809     // Collect new subfaces (of two facets) bounded B_i(p).
25810     for (k = 0; k < 2; k++) {
25811       if ((i + k) < spinshlist->len()) {
25812         pnewshlist = newshlist[i + k];
25813         segsh1 = * (face *)(* spinshlist)[i + k];
25814       } else {
25815         pnewshlist = newshlist[0];
25816         segsh1 = * (face *)(* spinshlist)[0];
25817       }
25818       // Adjust the orientation of segsh1 to face to the inside of C.
25819       if (k == 0) {
25820         if (sorg(segsh1) != pa) sesymself(segsh1);
25821         assert(sorg(segsh1) == pa);
25822       } else {
25823         if (sdest(segsh1) != pa) sesymself(segsh1);
25824         assert(sdest(segsh1) == pa);
25825       }
25826       // Preparation for re-tetrahedralzing old B_i(p).
25827       orientnewsubs(pnewshlist, &segsh1, pnorm[k]);
25828       for (j = 0; j < pnewshlist->len(); j++) {
25829         dnewshlist->append((face *)(* pnewshlist)[j]);
25830       }
25831     }
25832     // Tetrahedralize B_i(p).
25833     success = constrainedcavity(&oldtet, dnewshlist, oldtetlist[i], ptlist,
25834                 frontlist, misfrontlist, newtetlist[i], flipque);
25835     if (!success && !noreloc) {
25836       // C must be finished by re-locating the steiner point.
25837       makepoint(&(newpt[i]));
25838       for (j = 0; j < 3; j++) norm[j] = 0.5 * (pnorm[0][j] + pnorm[1][j]);
25839       success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25840                                   oldtetlist[i]);
25841       // for (j = 0; j < 3; j++) newpt[i][j] = suppt[j];
25842       // success = smoothvolpoint(newpt[i], frontlist, true);
25843       if (success) {
25844         // p is relocated by newpt[i]. Now insert it. Don't do flip since
25845         //   the new tets may get deleted again.
25846         relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25847         setpointtype(newpt[i], FREEVOLVERTEX);
25848         relverts++;
25849       } else {
25850         // Fail to relocate p. Clean fake tets and quit this option.
25851         deallocfaketets(frontlist);
25852         pointdealloc(newpt[i]);
25853         newpt[i] = (point) NULL;
25854         assert(newtetlist[i]->len() == 0);
25855       }
25856     }
25857     if (!success && noreloc) {
25858       // Failed and no point relocation. Clean fake tets.
25859       deallocfaketets(frontlist);
25860     }
25861     // Clear work lists.
25862     dnewshlist->clear();
25863     ptlist->clear();
25864     frontlist->clear();
25865     misfrontlist->clear();
25866     flipque->clear();
25867   }
25868 
25869   if (success) {
25870     // p has been suppressed. (Still in the pool).
25871     setpointtype(suppt, UNUSEDVERTEX);
25872     unuverts++;
25873     // Update the segmnet pointers saved in a and b.
25874     setpoint2sh(pa, sencode(newseg));
25875     setpoint2sh(pb, sencode(newseg));
25876     // Delete old segments ap, pb.
25877     shellfacedealloc(subsegs, supseg->sh);
25878     shellfacedealloc(subsegs, nsupseg.sh);
25879     // Delete subs of old C_i(p).
25880     for (i = 0; i < spinshlist->len(); i++) {
25881       for (j = 0; j < oldshlist[i]->len(); j++) {
25882         oldsh = * (face *)(* (oldshlist[i]))[j];
25883         if (j == 0) {
25884           // Update 'hullsize' if C_i(p) is on the hull.
25885           stpivot(oldsh, oldtet);
25886           if (oldtet.tet != dummytet) {
25887             sesymself(oldsh);
25888             stpivot(oldsh, oldtet);
25889           }
25890           if (oldtet.tet == dummytet) {
25891             // Update 'hullsize'.
25892             k = oldshlist[i]->len() - newshlist[i]->len();
25893             assert(k > 0);
25894             hullsize -= k;
25895           }
25896         }
25897         shellfacedealloc(subfaces, oldsh.sh);
25898       }
25899     }
25900     // Delete tets old B_i(p).
25901     for (i = 0; i < spinshlist->len(); i++) {
25902       // Delete them if it is not empty.
25903       if (oldtetlist[i] != (list *) NULL) {
25904         for (j = 0; j < oldtetlist[i]->len(); j++) {
25905           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25906           assert(!isdead(&oldtet));
25907           tetrahedrondealloc(oldtet.tet);
25908         }
25909       }
25910     }
25911     if (optflag) {
25912       for (i = 0; i < spinshlist->len(); i++) {
25913         // Check for new bad-quality tets.
25914         if (newtetlist[i] != (list *) NULL) {
25915           for (j = 0; j < newtetlist[i]->len(); j++) {
25916             newtet = * (triface *)(* (newtetlist[i]))[j];
25917             if (!isdead(&newtet)) checktet4opt(&newtet, true);
25918           }
25919         }
25920       }
25921     }
25922   } else {
25923     // p is not suppressed. Recover the original state.
25924     unsupverts++;
25925     // Restore old connection at a.
25926     senext2(*supseg, prevseg);
25927     spivotself(prevseg);
25928     if (prevseg.sh != dummysh) {
25929       prevseg.shver = 0;
25930       if (sdest(prevseg) != pa) sesymself(prevseg);
25931       assert(sdest(prevseg) == pa);
25932       senextself(prevseg);
25933       senext2self(*supseg);
25934       sbond(*supseg, prevseg);
25935       senextself(*supseg); // Restore original state.
25936       assert(supseg->shver < 2);
25937     }
25938     // Restore old connection at b.
25939     senext(nsupseg, nextseg);
25940     spivotself(nextseg);
25941     if (nextseg.sh != dummysh) {
25942       nextseg.shver = 0;
25943       if (sorg(nextseg) != pb) sesymself(nextseg);
25944       assert(sorg(nextseg) == pb);
25945       senext2self(nextseg);
25946       senextself(nsupseg);
25947       sbond(nsupseg, nextseg);
25948       // nsupseg.shver = 0;
25949       senext2self(nsupseg); // Restore original state
25950       assert(nsupseg.shver < 2);
25951     }
25952     // Delete the new segment ab.
25953     shellfacedealloc(subsegs, newseg.sh);
25954     // Restore old C_i(p).
25955     for (i = 0; i < spinshlist->len(); i++) {
25956       replacepolygonsubs(newshlist[i], oldshlist[i]);
25957       // Delete subs of the new C_i(p)
25958       for (j = 0; j < newshlist[i]->len(); j++) {
25959         newsh = * (face *)(* (newshlist[i]))[j];
25960         shellfacedealloc(subfaces, newsh.sh);
25961       }
25962     }
25963     // Restore old B_i(p).
25964     for (i = 0; i < spinshlist->len(); i++) {
25965       if (oldtetlist[i] != (list *) NULL) {
25966         // Uninfect tets of old B_i(p).
25967         for (j = 0; j < oldtetlist[i]->len(); j++) {
25968           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25969           assert(infected(oldtet));
25970           uninfect(oldtet);
25971         }
25972         // Has it been re-meshed?
25973         if (newtetlist[i]->len() > 0) {
25974           // Restore the old B_i(p).
25975           restorepolyhedron(oldtetlist[i]);
25976           // Delete tets of the new B_i(p);
25977           for (j = 0; j < newtetlist[i]->len(); j++) {
25978             newtet = * (triface *)(* (newtetlist[i]))[j];
25979             // Some new tets may already be deleted (by carvecavity()).
25980             if (!isdead(&newtet)) {
25981               tetrahedrondealloc(newtet.tet);
25982             }
25983           }
25984         }
25985         // Dealloc newpt[i] if it exists.
25986         if (newpt[i] != (point) NULL) {
25987           pointdealloc(newpt[i]);
25988           relverts--;
25989         }
25990       }
25991     }
25992   }
25993 
25994   // Delete work lists.
25995   delete dnewshlist;
25996   for (i = 0; i < spinshlist->len(); i++) {
25997     delete oldshlist[i];
25998     delete newshlist[i];
25999   } 
26000   delete [] oldshlist;
26001   delete [] newshlist;
26002   for (i = 0; i < spinshlist->len(); i++) {
26003     if (oldtetlist[i] != (list *) NULL) {
26004       delete oldtetlist[i];
26005       delete newtetlist[i];
26006     }
26007   }
26008   delete [] oldtetlist;
26009   delete [] newtetlist;
26010   // Clear work lists.
26011   newsegshlist->clear();
26012   spinshlist->clear();
26013 
26014   return success;
26015 }
26016 
26018 //                                                                           //
26019 // suppressvolpoint()    Suppress a point inside mesh.                       //
26020 //                                                                           //
26021 // The point p = org(suptet) is inside the mesh and will be suppressed from  //
26022 // the mesh. Note that p may not be suppressed.                              //
26023 //                                                                           //
26024 // 'optflag' is used for mesh optimization. If it is set, after removing p,  //
26025 // test the object function on each new tet, queue bad tets.                 //
26026 //                                                                           //
26028 
26029 bool tetgenmesh::suppressvolpoint(triface* suptet, list* frontlist,
26030   list* misfrontlist, list* ptlist, queue* flipque, bool optflag)
26031 {
26032   list *myfrontlist, *mymisfrontlist, *myptlist;
26033   list *oldtetlist, *newtetlist;
26034   list *newshlist; // a dummy list.
26035   queue *myflipque;
26036   triface oldtet, newtet;
26037   point suppt, conpt;
26038   bool success;
26039   int j;
26040 
26041   // Allocate spaces for storing (old and new) B(p).
26042   oldtetlist = new list(sizeof(triface), NULL, 256);
26043   newtetlist = new list(sizeof(triface), NULL, 256);
26044   newshlist = new list(sizeof(face), NULL, 256);
26045   // Allocate work lists if user doesn't supply them.
26046   myfrontlist = mymisfrontlist = myptlist = (list *) NULL;
26047   myflipque = (queue *) NULL;
26048   if (frontlist == (list *) NULL) {
26049     myfrontlist = new list(sizeof(triface), NULL, 256);
26050     frontlist = myfrontlist;
26051     mymisfrontlist = new list(sizeof(triface), NULL, 256);
26052     misfrontlist = mymisfrontlist;
26053     myptlist = new list(sizeof(point *), NULL, 256);
26054     ptlist = myptlist;
26055     myflipque = new queue(sizeof(badface));
26056     flipque = myflipque;
26057   }
26058 
26059   suppt = org(*suptet);
26060   oldtet = *suptet;
26061   success = true; // Assume p can be suppressed.
26062 
26063   if (b->verbose > 1) {
26064     printf("    Remove point %d in mesh.\n", pointmark(suppt));
26065   }
26066 
26067   // Form old B(p) in oldtetlist.
26068   oldtetlist->append(&oldtet);
26069   formstarpolyhedron(suppt, oldtetlist, ptlist, false);
26070   // Infect the tets in old B(p) (they're going to be delete).
26071   for (j = 0; j < oldtetlist->len(); j++) {
26072     oldtet = * (triface *)(* oldtetlist)[j];
26073     infect(oldtet);
26074   }
26075   // Tetrahedralize old B(p).
26076   success = constrainedcavity(&oldtet, newshlist, oldtetlist, ptlist,
26077               frontlist, misfrontlist, newtetlist, flipque);
26078   if (!success) {
26079     // Unable to suppress p.
26080     deallocfaketets(frontlist);
26081     // Try to collapse an edge at p. 
26082     conpt = (point) NULL;
26083     assert(newtetlist->len() == 0);
26084     if (findcollapseedge(suppt, &conpt, oldtetlist, ptlist)) {
26085       // Collapse the edge suppt->conpt. Re-use newtetlist.
26086       collapseedge(suppt, conpt, oldtetlist, newtetlist);
26087       // The oldtetlist contains newtetlist.
26088       if (optflag) {
26089         assert(newtetlist->len() == 0);
26090         for (j = 0; j < oldtetlist->len(); j++) {
26091           newtet = * (triface *)(* oldtetlist)[j];
26092           newtetlist->append(&newtet);
26093         }
26094       }
26095       oldtetlist->clear(); // Do not delete them.
26096       collapverts++;
26097       success = true;
26098     }
26099   }
26100   if (success) {
26101     // p has been removed! (Still in the pool).
26102     setpointtype(suppt, UNUSEDVERTEX);
26103     unuverts++;
26104     suprelverts++;
26105     // Delete old B(p).
26106     for (j = 0; j < oldtetlist->len(); j++) {
26107       oldtet = * (triface *)(* oldtetlist)[j];
26108       assert(!isdead(&oldtet));
26109       tetrahedrondealloc(oldtet.tet);
26110     }
26111     if (optflag) {
26112       // Check for new bad tets.
26113       for (j = 0; j < newtetlist->len(); j++) {
26114         newtet = * (triface *)(* newtetlist)[j];
26115         if (!isdead(&newtet)) checktet4opt(&newtet, true);
26116       }
26117     }
26118   } else {
26119     // p is not suppressed. Recover the original state.
26120     // Uninfect tets of old B(p).
26121     for (j = 0; j < oldtetlist->len(); j++) {
26122       oldtet = * (triface *)(* oldtetlist)[j];
26123       assert(infected(oldtet));
26124       uninfect(oldtet);
26125     }
26126   }
26127 
26128   // Clear work lists.
26129   ptlist->clear();
26130   frontlist->clear();
26131   misfrontlist->clear();
26132   flipque->clear();
26133   // Deallocate work lists.
26134   if (myfrontlist != (list *) NULL) {
26135     delete myfrontlist;
26136     delete mymisfrontlist;
26137     delete myptlist;
26138     delete myflipque;
26139   }
26140   delete oldtetlist;
26141   delete newtetlist;
26142   delete newshlist;
26143 
26144   return success;
26145 }
26146 
26148 //                                                                           //
26149 // smoothpoint()    Smooth a volume/segment point.                           //
26150 //                                                                           //
26151 // 'smthpt' (p) is inside the polyhedron (C) bounded by faces in 'starlist'. //
26152 // This routine moves p inside C until an object function is maximized.      //
26153 //                                                                           //
26154 // Default, the CCW edge ring of the faces on C points to p. If 'invtori' is //
26155 // TRUE, the orientation is inversed.                                        //
26156 //                                                                           //
26157 // If 'key' != NULL, it contains an object value to be improved. Current it  //
26158 // means the cosine of the largest dihedral angle. In such case, the point   //
26159 // is smoothed only if the final configuration improves the object value, it //
26160 // is returned by the 'key'.                                                 //
26161 //                                                                           //
26163 
26164 bool tetgenmesh::smoothpoint(point smthpt, point e1, point e2, list *starlist,
26165   bool invtori, REAL *key)
26166 {
26167   triface starttet;
26168   point pa, pb, pc;
26169   REAL fcent[3], startpt[3], nextpt[3], bestpt[3];
26170   REAL iniTmax, oldTmax, newTmax;
26171   REAL ori, aspT, aspTmax, imprate;
26172   REAL cosd, maxcosd;
26173   bool segflag, randflag; //, subflag; 
26174   int numdirs;
26175   int iter, i, j;
26176   
26177   // Is p a segment vertex?
26178   segflag = (e1 != (point) NULL);
26179   // Decide the number of moving directions.
26180   numdirs = segflag ? 2 : starlist->len();
26181   randflag = numdirs > 10;
26182   if (randflag) {
26183     numdirs = 10; // Maximum 10 directions.
26184   }
26185 
26186   aspTmax = 0.0; 
26187   // Calculate the initial object value (the largest aspect ratio).
26188   for (i = 0; i < starlist->len(); i++) {
26189     starttet = * (triface *)(* starlist)[i];
26190     adjustedgering(starttet, !invtori ? CCW : CW);
26191     pa = org(starttet);
26192     pb = dest(starttet);
26193     pc = apex(starttet);
26194     aspT = tetaspectratio(pa, pb, pc, smthpt);
26195     if (i == 0) {
26196       aspTmax = aspT;
26197     } else {
26198       aspTmax = aspT > aspTmax ? aspT : aspTmax;
26199     }
26200   }
26201   iniTmax = aspTmax;
26202 
26203   if (b->verbose > 1) {
26204     printf("    Smooth %s point %d (%g, %g, %g).\n", segflag ? "seg" : "vol",
26205            pointmark(smthpt), smthpt[0], smthpt[1], smthpt[2]);
26206     printf("    Initial max L/h = %g.\n", iniTmax);
26207   }
26208   for (i = 0; i < 3; i++) {
26209     bestpt[i] = startpt[i] = smthpt[i];
26210   }
26211 
26212   // Do iteration until the new aspTmax does not decrease.
26213   newTmax = iniTmax;
26214   iter = 0;
26215   while (true) {
26216     // Find the best next location.
26217     oldTmax = newTmax;
26218     for (i = 0; i < numdirs; i++) {
26219       // Calculate the moved point (saved in 'nextpt').
26220       if (!segflag) {
26221         if (randflag) {
26222           // Randomly pick a direction.
26223           j = (int) randomnation(starlist->len());
26224         } else {
26225           j = i;
26226         }
26227         starttet = * (triface *)(* starlist)[j];
26228         adjustedgering(starttet, !invtori ? CCW : CW);
26229         pa = org(starttet);
26230         pb = dest(starttet);
26231         pc = apex(starttet);
26232         for (j = 0; j < 3; j++) {
26233           fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0;
26234         }
26235       } else {
26236         for (j = 0; j < 3; j++) {
26237           fcent[j] = (i == 0 ? e1[j] : e2[j]);
26238         }
26239       }
26240       for (j = 0; j < 3; j++) {
26241         nextpt[j] = startpt[j] + 0.01 * (fcent[j] - startpt[j]); 
26242       }
26243       // Get the largest object value for the new location.
26244       for (j = 0; j < starlist->len(); j++) {
26245         starttet = * (triface *)(* starlist)[j];
26246         adjustedgering(starttet, !invtori ? CCW : CW);
26247         pa = org(starttet);
26248         pb = dest(starttet);
26249         pc = apex(starttet);
26250         ori = orient3d(pa, pb, pc, nextpt);
26251         if (ori < 0.0) {
26252           aspT = tetaspectratio(pa, pb, pc, nextpt);
26253           if (j == 0) {
26254             aspTmax = aspT;
26255           } else {
26256             aspTmax = aspT > aspTmax ? aspT : aspTmax;
26257           }
26258         } else {
26259           // An invalid new tet. Discard this point.
26260           aspTmax = newTmax;
26261         } // if (ori < 0.0)
26262         // Stop looping when the object value is bigger than before.
26263         if (aspTmax >= newTmax) break;
26264       } // for (j = 0; j < starlist->len(); j++)
26265       if (aspTmax < newTmax) {
26266         // Save the improved object value and the location.
26267         newTmax = aspTmax;
26268         for (j = 0; j < 3; j++) bestpt[j] = nextpt[j];
26269       }
26270     } // for (i = 0; i < starlist->len(); i++)
26271     // Does the object value improved much?
26272     imprate = fabs(oldTmax - newTmax) / oldTmax;
26273     if (imprate < 1e-3) break;
26274     // Yes, move p to the new location and continue.
26275     for (j = 0; j < 3; j++) startpt[j] = bestpt[j];
26276     iter++;
26277   } // while (true)
26278 
26279   if (iter > 0) {
26280     // The point is moved.
26281     if (key) {
26282       // Check if the quality is improved by the smoothed point.
26283       maxcosd = 0.0; // = cos(90).
26284       for (j = 0; j < starlist->len(); j++) {
26285         starttet = * (triface *)(* starlist)[j];
26286         adjustedgering(starttet, !invtori ? CCW : CW);
26287         pa = org(starttet);
26288         pb = dest(starttet);
26289         pc = apex(starttet);
26290         tetalldihedral(pa, pb, pc, startpt, NULL, &cosd, NULL);
26291         if (cosd < *key) {
26292           // This quality will not be improved. Stop.
26293           iter = 0; break;
26294         } else {
26295           // Remeber the worst quality value (of the new configuration).
26296           maxcosd = maxcosd < cosd ? maxcosd : cosd;
26297         }
26298       }
26299       if (iter > 0) *key = maxcosd;
26300     }
26301   }
26302 
26303   if (iter > 0) {
26304     segflag ? smoothsegverts++ : smoothvolverts++;
26305     for (i = 0; i < 3; i++) smthpt[i] = startpt[i];
26306     if (b->verbose > 1) {
26307       printf("    Move to new location (%g, %g, %g).\n", smthpt[0], smthpt[1],
26308              smthpt[2]);
26309       printf("    Final max L/h = %g. (%d iterations)\n", newTmax, iter);
26310       if (key) {
26311         printf("    Max. dihed = %g (degree).\n", acos(*key) / PI * 180.0);
26312       }
26313     }
26314     return true;
26315   } else {
26316     if (b->verbose > 1) {
26317       printf("    Not smoothed.\n");
26318     }
26319     return false;
26320   }
26321 }
26322 
26324 //                                                                           //
26325 // removesteiners()    Delete or relocate Steiner points on facets.          //
26326 //                                                                           //
26328 
26329 void tetgenmesh::removesteiners(bool coarseflag)
26330 {
26331   list *frontlist, *misfrontlist;
26332   list *spinshlist, *newsegshlist;
26333   list *ptlist, *conlist;
26334   memorypool *viri;
26335   queue *flipque;
26336   triface checktet;
26337   face shloop;
26338   face segloop, nextseg;
26339   point pa, neipt;
26340   REAL len;
26341   bool remflag;
26342   int *worklist;
26343   int oldnum, rmstein;
26344   int i, j;
26345 
26346   if (!b->quiet) {
26347     if (!coarseflag) {
26348       printf("Removing Steiner points.\n");
26349     } else {
26350       printf("Coarsening mesh.\n");
26351     }
26352   }
26353 
26354   // Initialize work lists.
26355   frontlist = new list(sizeof(triface), NULL);
26356   misfrontlist = new list(sizeof(triface), NULL);
26357   spinshlist = new list(sizeof(face), NULL);
26358   newsegshlist = new list(sizeof(face), NULL);
26359   ptlist = new list(sizeof(point *), NULL);
26360   conlist = new list(sizeof(point *) * 2, NULL);
26361   flipque = new queue(sizeof(badface));
26362   viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
26363   oldnum = unuverts;
26364   relverts = suprelverts = collapverts = unsupverts;
26365   smoothvolverts = 0;
26366   expcavcount = 0;
26367 
26368   // Suppress Steiner points inside facets.
26369   do {
26370     rmstein = unuverts;
26371     subfaces->traversalinit();
26372     shloop.sh = shellfacetraverse(subfaces);
26373     while (shloop.sh != (shellface *) NULL) {
26374       remflag = false;
26375       // Is s contains a Steiner point?
26376       shloop.shver = 0;
26377       for (i = 0; i < 3; i++) {
26378         pa = sapex(shloop);
26379         if (pointtype(pa) == FREESUBVERTEX) {
26380           if (!coarseflag) {
26381             // Remove it if it is not an input point.
26382             j = pointmark(pa) - in->firstnumber;
26383             if (j >= in->numberofpoints) {
26384               if (b->nobisect == 1) {
26385                 // '-Y'. Remove p if s is a hull face.
26386                 stpivot(shloop, checktet);
26387                 if (checktet.tet != dummytet) {
26388                   sesymself(shloop);
26389                   stpivot(shloop, checktet);
26390                 }
26391                 remflag = (checktet.tet == dummytet);
26392               } else {
26393                 // '-YY'. Remove p whatever s is a hull face or not.
26394                 remflag = true;
26395               }
26396             }
26397           } else {
26398             // Check if this vertex can be coarsed.
26399             if (b->nobisect == 0) {
26400               // Is a background mesh available?
26401               if (b->metric) {
26402                 // assert(pa[pointmtrindex] > 0.0);
26403                 // Form the star of pa.
26404                 spinshlist->append(&shloop);
26405                 formstarpolygon(pa, spinshlist, ptlist);
26406                 len = 0.0;
26407                 for (j = 0; j < ptlist->len(); j++) {
26408                   neipt = * (point *)(* ptlist)[j];
26409                   len += distance(pa, neipt);
26410                 }
26411                 len /= ptlist->len();
26412                 // Carse it if the average edge length is small.
26413                 remflag = len < pa[pointmtrindex];
26414                 spinshlist->clear();
26415                 ptlist->clear();
26416               } else {
26417                 // Coarse it if (1) it is an input point and its pointmarker
26418                 //   is zero, or (2) it is a Steiner point.
26419                 remflag = true;
26420                 j = pointmark(pa) - in->firstnumber;
26421                 if (j < in->numberofpoints) {
26422                   remflag = (in->pointmarkerlist[j] == 0);
26423                 }
26424               } // if (b->metric)
26425             } // if (b->nobisect == 0)
26426           } // if (!coarseflag)
26427           if (remflag) break;
26428         } // if (pointtype(pa) == FREESUBVERTEX)
26429         senextself(shloop);
26430       } // for (i = 0; i < 3; i++)
26431       if (remflag) {
26432         suppressfacetpoint(&shloop, frontlist, misfrontlist, ptlist, conlist,
26433                            viri, flipque, coarseflag, false);
26434       }
26435       shloop.sh = shellfacetraverse(subfaces);
26436     }
26437     // Continue if any Steiner point has been removed.
26438   } while (unuverts > rmstein);
26439 
26440   if (coarseflag) {
26441     shellface **segsperverlist;
26442     int *idx2seglist;
26443     face seg1, seg2;
26444     point e1, e2;
26445     // Connecting collinear segments. Hence the segment vertices may be
26446     //   removed. In fact, this should be done by reconstructmesh().
26447     makesegmentmap(idx2seglist, segsperverlist);
26448     subsegs->traversalinit();
26449     segloop.sh = shellfacetraverse(subsegs);
26450     while (segloop.sh != (shellface *) NULL) {
26451       for (i = 0; i < 2; i++) {
26452         segloop.shver = i;
26453         senext(segloop, nextseg);
26454         spivotself(nextseg);
26455         if ((nextseg.sh == dummysh) || (nextseg.sh > segloop.sh)) {
26456           // No neighbor segment connection or haven't been processed yet.
26457           pa = sdest(segloop);
26458           j = pointmark(pa) - in->firstnumber;
26459           if (idx2seglist[j + 1] - idx2seglist[j] == 2) {
26460             // pa is shared by only two segments. Get the other one.
26461             nextseg.sh = segsperverlist[idx2seglist[j]];
26462             if (nextseg.sh == segloop.sh) {
26463               nextseg.sh = segsperverlist[idx2seglist[j] + 1];
26464             }
26465             nextseg.shver = 0;
26466             if (sorg(nextseg) != pa) sesymself(nextseg);
26467             // Check if the two segments are collinear.
26468             e1 = sorg(segloop);
26469             e2 = sdest(nextseg);
26470             if (iscollinear(e1, pa, e2, b->epsilon)) {
26471               // Connect the two segments together.
26472               if (b->verbose > 1) {
26473                 printf("  Glue two insegs (%d, %d) at %d.\n", pointmark(e1),
26474                        pointmark(e2), pointmark(pa));
26475               }
26476               senext(segloop, seg1);
26477               senext2(nextseg, seg2);
26478               sbond(seg1, seg2);
26479             }
26480           }
26481         } // if (nextseg.sh == dummysh)
26482       } // for (i = 0;
26483       segloop.sh = shellfacetraverse(subsegs);
26484     }
26485     delete [] segsperverlist;
26486     delete [] idx2seglist;
26487   }
26488 
26489   // Suppress Steiner points on segments.
26490   do {
26491     rmstein = unuverts;
26492     subsegs->traversalinit();
26493     segloop.sh = shellfacetraverse(subsegs);
26494     while (segloop.sh != (shellface *) NULL) {
26495       remflag = false;
26496       // for (i = 0; i < 2; i++) {
26497         // Don't check the poinytype of pa, it may be a Steiner point but
26498         //   has type NACUTEVERTEX due to splitting a type-3 segment.
26499         segloop.shver = 0; // segloop.shver = i;
26500         senext(segloop, nextseg);
26501         spivotself(nextseg);
26502         if (nextseg.sh != dummysh) {
26503           pa = sdest(segloop); // p is going to be checked for removal.
26504           nextseg.shver = 0;
26505           if (sorg(nextseg) != pa) sesymself(nextseg);  
26506           assert(sorg(nextseg) == pa);
26507           if (!coarseflag) {
26508             // try to remove it if it is not an input point.
26509             j = pointmark(pa) - in->firstnumber;
26510             if (j >= in->numberofpoints) {
26511               if (b->nobisect == 1) {
26512                 // '-Y'. Remove p if it is on the hull.
26513                 sstpivot(&segloop, &checktet);
26514                 assert(checktet.tet != dummytet);
26515                 pa = apex(checktet);
26516                 do {
26517                   if (!fnextself(checktet)) {
26518                     // Meet a boundary face - p is on the hull.
26519                     remflag = true; break;
26520                   }
26521                 } while (pa != apex(checktet));
26522               } else {
26523                 // '-YY'. Remove p whatever it is on the hull or not.
26524                 remflag = true;
26525               }
26526             }
26527           } else {
26528             // Check if this vertex can be coarsed.
26529             if (b->nobisect == 0) {
26530               if (b->metric) {
26531                 // assert(pa[pointmtrindex] > 0.0);
26532                 len = 0.0;
26533                 neipt = sorg(segloop);
26534                 for (j = 0; j < 2; j++) {
26535                   len += distance(pa, neipt);
26536                   /*// Is neipt inside the sparse ball of pa?
26537                   if (len < pa[pointmtrindex]) {
26538                     // Yes, the local of pa is too dense, corse it.
26539                     remflag = true; break;
26540                   } */
26541                   neipt = sdest(nextseg);
26542                 }
26543                 len /= 2.0;
26544                 // Carse it if the average edge lengh is small.
26545                 remflag = len < pa[pointmtrindex]; 
26546               } else {
26547                 // Coarse it if (1) it is an input point and its pointmarker
26548                 //   is zero, or (2) it is a Steiner point.
26549                 remflag = true;
26550                 j = pointmark(pa) - in->firstnumber;
26551                 if (j < in->numberofpoints) {
26552                   remflag = (in->pointmarkerlist[j] == 0);
26553                 }
26554               } // if (b->metric)
26555             } // if (b->nobisect == 0)
26556           } // if (!coarseflag)
26557         } // if (nextseg.sh != dummysh)
26558         // if (remflag) break;
26559       // } // for (i = 0; i < 2; i++)
26560       if (remflag) {
26561         suppresssegpoint(&segloop, spinshlist, newsegshlist, frontlist,
26562           misfrontlist, ptlist, conlist, viri, flipque, coarseflag, false);
26563       }
26564       segloop.sh = shellfacetraverse(subsegs);
26565     }
26566     // Continue if any Steiner point has been removed.
26567   } while (unuverts > rmstein);
26568 
26569   if ((relverts > 0) || coarseflag) {
26570     worklist = new int[points->items + 1];
26571     // Suppress relocated points & coarse free mesh points.
26572     do {
26573       // Initialize the work list. Each entry of the list counts how many
26574       //   times the point has been processed.
26575       for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26576       rmstein = unuverts;
26577       tetrahedrons->traversalinit();
26578       checktet.tet = tetrahedrontraverse();
26579       while (checktet.tet != (tetrahedron *) NULL) {
26580         remflag = false;
26581         for (i = 0; i < 4; i++) {
26582           pa = (point) checktet.tet[4 + i];
26583           if (pointtype(pa) == FREEVOLVERTEX) {
26584             // NOTE. Chenge the number 3 will change the number n of removed
26585             //   Steiner points. In my test, n is larger when it is 1. 3
26586             //   reduces n in a reasonable way (see example, mech_part,
26587             //   thepart), 5 results a larger n than 3 does. While the best
26588             //   result is no limit of this number, but it makes the code
26589             //   extremely slow.
26590             if (worklist[pointmark(pa)] < 3) {
26591               worklist[pointmark(pa)]++;
26592               if (!coarseflag) {
26593                 // Remove p if it is a Steiner point.
26594                 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26595                   remflag = true;
26596                 }
26597               } else {
26598                 if (b->metric) {
26599                   // assert(pa[pointmtrindex] > 0.0);
26600                   // Form the star of pa.
26601                   frontlist->append(&checktet);
26602                   formstarpolyhedron(pa, frontlist, ptlist, true);
26603                   len = 0.0;
26604                   for (j = 0; j < ptlist->len(); j++) {
26605                     neipt = * (point *)(* ptlist)[j];
26606                     len += distance(pa, neipt);
26607                   }
26608                   len /= ptlist->len();
26609                   // Carse it if the average edge length is small.
26610                   remflag = len < pa[pointmtrindex];
26611                   frontlist->clear();
26612                   ptlist->clear();
26613                 } else {
26614                   // Coarse it if (1) it is an input point and its pointmarker
26615                   //   is zero, or (2) it is a Steiner point.
26616                   remflag = true;
26617                   j = pointmark(pa) - in->firstnumber;
26618                   if (j < in->numberofpoints) {
26619                     remflag = (in->pointmarkerlist[j] == 0);
26620                   }
26621                 } // if (b->metric)
26622               } // if (!coarseflag)
26623               if (remflag) break;
26624             } // if (worklist[pointmark(pa)] == 0)
26625           } // if (pointtype(pa) == FREEVOLVERTEX)
26626         } // for (i = 0; i < 4; i++)
26627         if (remflag) {
26628           findorg(&checktet, pa);
26629           assert(org(checktet) == pa);
26630           suppressvolpoint(&checktet, frontlist, misfrontlist, ptlist, flipque,
26631                            false);
26632         }
26633         checktet.tet = tetrahedrontraverse();
26634       }
26635       // Continue if any relocated point has been suppressed.
26636     } while (unuverts > rmstein);
26637 
26638 
26639     // Smooth the unsuppressed points if it is not coarse mesh.
26640     if (!coarseflag && (relverts > suprelverts)) {
26641       if (b->verbose) {
26642         printf("  Smoothing relocated points.\n");
26643       }
26644       for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26645       tetrahedrons->traversalinit();
26646       checktet.tet = tetrahedrontraverse();
26647       while (checktet.tet != (tetrahedron *) NULL) {
26648         for (i = 0; i < 4; i++) {
26649           pa = (point) checktet.tet[4 + i];
26650           if (pointtype(pa) == FREEVOLVERTEX) {
26651             if (worklist[pointmark(pa)] == 0) {
26652               worklist[pointmark(pa)] = 1;
26653               if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26654                 // Smooth pa.
26655                 findorg(&checktet, pa);
26656                 frontlist->append(&checktet);
26657                 formstarpolyhedron(pa, frontlist, NULL, false);
26658                 smoothpoint(pa, NULL, NULL, frontlist, false, NULL);
26659                 frontlist->clear();
26660               }
26661             } // if (worklist[pointmark(pa)] == 0)
26662           } // if (pointtype(pa) == FREEVOLVERTEX)
26663         } // for (i = 0; i < 4; i++)
26664         checktet.tet = tetrahedrontraverse();
26665       }
26666     }
26667     delete [] worklist;
26668   }
26669 
26670   if (b->verbose > 0) {
26671     if (!coarseflag) {
26672       printf("  %d points removed from boundary", unuverts - oldnum);
26673       if (expcavcount > 0) {
26674         printf(" (%d cavity corrections)", expcavcount);
26675       }
26676       printf("\n");
26677       if (relverts > 0) {
26678         printf("  %d points relocated (%d suppressed, %d collapsed).\n",
26679                relverts, suprelverts - collapverts, collapverts);
26680         if (smoothvolverts > 0) {
26681           printf("  %d points are smoothed.\n", smoothvolverts);
26682         }
26683       }
26684       if (unsupverts > 0) {
26685         printf("  !! %d points are unsuppressed.\n", unsupverts);
26686       }
26687     } else {
26688       printf("  %d points are removed.\n", unuverts - oldnum);
26689     }
26690   }
26691 
26692   // Delete work lists.
26693   delete frontlist;
26694   delete misfrontlist;
26695   delete spinshlist;
26696   delete newsegshlist;
26697   delete ptlist;
26698   delete conlist;
26699   delete flipque;
26700   delete viri;
26701 }
26702 
26703 //
26704 // End of boundary Steiner points removing routines
26705 //
26706 
26708 //                                                                           //
26709 // reconstructmesh()    Reconstruct a tetrahedral mesh from a list of        //
26710 //                      tetrahedra and possibly a list of boundary faces.    //
26711 //                                                                           //
26712 // The list of tetrahedra is stored in 'in->tetrahedronlist',  the list of   //
26713 // boundary faces is stored in 'in->trifacelist'.  The tetrahedral mesh is   //
26714 // reconstructed in memorypool 'tetrahedrons', its boundary faces (subfaces) //
26715 // are reconstructed in 'subfaces', its boundary edges (subsegments) are     //
26716 // reconstructed in 'subsegs'. If the -a switch is used, this procedure will //
26717 // also read a list of REALs from 'in->tetrahedronvolumelist' and set a      //
26718 // maximum volume constraint on each tetrahedron.                            //
26719 //                                                                           //
26720 // If the user has provided the boundary faces in 'in->trifacelist', they    //
26721 // will be inserted the mesh. Otherwise subfaces will be identified from the //
26722 // mesh.  All hull faces (including faces of the internal holes) will be     //
26723 // recognized as subfaces, internal faces between two tetrahedra which have  //
26724 // different attributes will also be recognized as subfaces.                 //
26725 //                                                                           //
26726 // Subsegments will be identified after subfaces are reconstructed. Edges at //
26727 // the intersections of non-coplanar subfaces are recognized as subsegments. //
26728 // Edges between two coplanar subfaces with different boundary markers are   //
26729 // also recognized as subsegments.                                           //
26730 //                                                                           //
26731 // The facet index of each subface will be set automatically after we have   //
26732 // recovered subfaces and subsegments.  That is, the set of subfaces, which  //
26733 // are coplanar and have the same boundary marker will be recognized as a    //
26734 // facet and has a unique index, stored as the facet marker in each subface  //
26735 // of the set, the real boundary marker of each subface will be found in     //
26736 // 'in->facetmarkerlist' by the index.  Facet index will be used in Delaunay //
26737 // refinement for detecting two incident facets.                             //
26738 //                                                                           //
26739 // Points which are not corners of tetrahedra will be inserted into the mesh.//
26740 // Return the number of faces on the hull after the reconstruction.          //
26741 //                                                                           //
26743 
26744 long tetgenmesh::reconstructmesh()
26745 {
26746   tetrahedron **tetsperverlist;
26747   shellface **facesperverlist;
26748   triface tetloop, neightet, neineightet, spintet;
26749   face subloop, neighsh, neineighsh, subseg;
26750   face sface1, sface2;
26751   point *idx2verlist;
26752   point torg, tdest, tapex, toppo;
26753   point norg, ndest, napex;
26754   list *neighshlist, *markerlist;
26755   REAL sign, attrib, volume;
26756   REAL da1, da2;
26757   bool bondflag, insertsegflag;
26758   int *idx2tetlist;
26759   int *idx2facelist;
26760   int *worklist;
26761   int facetidx, marker;
26762   int iorg, idest, iapex, ioppo;
26763   int inorg, indest, inapex;
26764   int index, i, j;
26765 
26766   if (!b->quiet) {
26767     printf("Reconstructing mesh.\n");
26768   }
26769 
26770   // Create a map from index to points.
26771   makeindex2pointmap(idx2verlist);
26772 
26773   // Create the tetrahedra.
26774   for (i = 0; i < in->numberoftetrahedra; i++) {
26775     // Create a new tetrahedron and set its four corners, make sure that
26776     //   four corners form a positive orientation.
26777     maketetrahedron(&tetloop);
26778     index = i * in->numberofcorners;
26779     // Although there may be 10 nodes, we only read the first 4.
26780     iorg = in->tetrahedronlist[index] - in->firstnumber;
26781     idest = in->tetrahedronlist[index + 1] - in->firstnumber;
26782     iapex = in->tetrahedronlist[index + 2] - in->firstnumber;
26783     ioppo = in->tetrahedronlist[index + 3] - in->firstnumber;
26784     torg = idx2verlist[iorg];
26785     tdest = idx2verlist[idest];
26786     tapex = idx2verlist[iapex];
26787     toppo = idx2verlist[ioppo];
26788     sign = orient3d(torg, tdest, tapex, toppo);
26789     if (sign > 0.0) {
26790       norg = torg; torg = tdest; tdest = norg;
26791     } else if (sign == 0.0) {
26792       if (!b->quiet) {
26793         printf("Warning:  Tet %d is degenerate.\n", i + in->firstnumber);
26794       }
26795     }
26796     setorg(tetloop, torg);
26797     setdest(tetloop, tdest);
26798     setapex(tetloop, tapex);
26799     setoppo(tetloop, toppo);
26800     // Temporarily set the vertices be type FREEVOLVERTEX, to indicate that
26801     //   they belong to the mesh.  These types may be changed later.
26802     setpointtype(torg, FREEVOLVERTEX);
26803     setpointtype(tdest, FREEVOLVERTEX);
26804     setpointtype(tapex, FREEVOLVERTEX);
26805     setpointtype(toppo, FREEVOLVERTEX);
26806     // Set element attributes if they exist.
26807     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
26808       index = i * in->numberoftetrahedronattributes;
26809       attrib = in->tetrahedronattributelist[index + j];
26810       setelemattribute(tetloop.tet, j, attrib);
26811     }
26812     // If -a switch is used (with no number follows) Set a volume
26813     //   constraint if it exists.
26814     if (b->varvolume) {
26815       if (in->tetrahedronvolumelist != (REAL *) NULL) {
26816         volume = in->tetrahedronvolumelist[i];
26817       } else {
26818         volume = -1.0;
26819       }
26820       setvolumebound(tetloop.tet, volume);
26821     }
26822   }
26823 
26824   // Set the connection between tetrahedra.
26825   hullsize = 0l;
26826   // Create a map from nodes to tetrahedra.
26827   maketetrahedronmap(idx2tetlist, tetsperverlist);
26828   // Initialize the worklist.
26829   worklist = new int[points->items];
26830   for (i = 0; i < points->items; i++) worklist[i] = 0;
26831 
26832   // Loop all tetrahedra, bond two tetrahedra if they share a common face.
26833   tetrahedrons->traversalinit();
26834   tetloop.tet = tetrahedrontraverse();
26835   while (tetloop.tet != (tetrahedron *) NULL) {
26836     // Loop the four sides of the tetrahedron.
26837     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26838       sym(tetloop, neightet);
26839       if (neightet.tet != dummytet) continue; // This side has finished.
26840       torg = org(tetloop);
26841       tdest = dest(tetloop);
26842       tapex = apex(tetloop);
26843       iorg = pointmark(torg) - in->firstnumber;
26844       idest = pointmark(tdest) - in->firstnumber;
26845       iapex = pointmark(tapex) - in->firstnumber;
26846       worklist[iorg] = 1;
26847       worklist[idest] = 1;
26848       worklist[iapex] = 1;
26849       bondflag = false;
26850       // Search its neighbor in the adjacent tets of torg.
26851       for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag; 
26852            j++) {
26853         if (tetsperverlist[j] == tetloop.tet) continue; // Skip myself.
26854         neightet.tet = tetsperverlist[j];
26855         for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26856           sym(neightet, neineightet);
26857           if (neineightet.tet == dummytet) {
26858             norg = org(neightet);
26859             ndest = dest(neightet);
26860             napex = apex(neightet);
26861             inorg = pointmark(norg) - in->firstnumber;
26862             indest = pointmark(ndest) - in->firstnumber;
26863             inapex = pointmark(napex) - in->firstnumber;
26864             if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26865               // Find! Bond them together and break the loop.
26866               bond(tetloop, neightet);
26867               bondflag = true;
26868               break;
26869             }
26870           }
26871         }
26872       }
26873       if (!bondflag) {
26874         hullsize++;  // It's a hull face.
26875         // Bond this side to outer space.
26876         dummytet[0] = encode(tetloop);
26877         if ((in->pointmarkerlist != (int *) NULL) && !b->coarse) {
26878           // Set its three corners's markers be boundary (hull) vertices.
26879           if (in->pointmarkerlist[iorg] == 0) {
26880             in->pointmarkerlist[iorg] = 1;
26881           }
26882           if (in->pointmarkerlist[idest] == 0) {
26883             in->pointmarkerlist[idest] = 1;
26884           }
26885           if (in->pointmarkerlist[iapex] == 0) {
26886             in->pointmarkerlist[iapex] = 1;
26887           }
26888         }
26889       }
26890       worklist[iorg] = 0;
26891       worklist[idest] = 0;
26892       worklist[iapex] = 0;
26893     }
26894     tetloop.tet = tetrahedrontraverse();
26895   }
26896 
26897   // Subfaces will be inserted into the mesh. It has two phases:
26898   //   (1) Insert subfaces provided by user (in->trifacelist);
26899   //   (2) Create subfaces for hull faces (if they're not subface yet) and
26900   //       interior faces which separate two different materials.
26901 
26902   // Phase (1). Is there a list of user-provided subfaces?
26903   if (in->trifacelist != (int *) NULL) {
26904     // Recover subfaces from 'in->trifacelist'.
26905     for (i = 0; i < in->numberoftrifaces; i++) {
26906       index = i * 3;
26907       iorg = in->trifacelist[index] - in->firstnumber;
26908       idest = in->trifacelist[index + 1] - in->firstnumber;
26909       iapex = in->trifacelist[index + 2] - in->firstnumber;
26910       // Look for the location of this subface.
26911       worklist[iorg] = 1;
26912       worklist[idest] = 1;
26913       worklist[iapex] = 1;
26914       bondflag = false;
26915       // Search its neighbor in the adjacent tets of torg.
26916       for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag; 
26917            j++) {
26918         neightet.tet = tetsperverlist[j];
26919         for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26920           norg = org(neightet);
26921           ndest = dest(neightet);
26922           napex = apex(neightet);
26923           inorg = pointmark(norg) - in->firstnumber;
26924           indest = pointmark(ndest) - in->firstnumber;
26925           inapex = pointmark(napex) - in->firstnumber;
26926           if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26927             bondflag = true;  // Find!
26928             break;
26929           }
26930         }
26931       }
26932       if (bondflag) {
26933         // Create a new subface and insert it into the mesh.
26934         makeshellface(subfaces, &subloop);
26935         torg = idx2verlist[iorg];
26936         tdest = idx2verlist[idest];
26937         tapex = idx2verlist[iapex];
26938         setsorg(subloop, torg);
26939         setsdest(subloop, tdest);
26940         setsapex(subloop, tapex);
26941         // Set the vertices be FREESUBVERTEX to indicate they belong to a
26942         //   facet of the domain.  They may be changed later.
26943         setpointtype(torg, FREESUBVERTEX);
26944         setpointtype(tdest, FREESUBVERTEX);
26945         setpointtype(tapex, FREESUBVERTEX);
26946         if (in->trifacemarkerlist != (int *) NULL) {
26947           setshellmark(subloop, in->trifacemarkerlist[i]);
26948         }
26949         adjustedgering(neightet, CCW);
26950         findedge(&subloop, org(neightet), dest(neightet));
26951         tsbond(neightet, subloop);
26952         sym(neightet, neineightet);
26953         if (neineightet.tet != dummytet) {
26954           sesymself(subloop);
26955           tsbond(neineightet, subloop);
26956         }
26957       } else {
26958         if (!b->quiet) {
26959           printf("Warning:  Subface %d is discarded.\n", i + in->firstnumber);
26960         }
26961       }
26962       worklist[iorg] = 0;
26963       worklist[idest] = 0;
26964       worklist[iapex] = 0;
26965     }
26966   } 
26967 
26968   // Phase (2). Indentify subfaces from the mesh.
26969   tetrahedrons->traversalinit();
26970   tetloop.tet = tetrahedrontraverse();
26971   while (tetloop.tet != (tetrahedron *) NULL) {
26972     // Loop the four sides of the tetrahedron.
26973     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26974       tspivot(tetloop, subloop);
26975       if (subloop.sh != dummysh) continue;
26976       bondflag = false;
26977       sym(tetloop, neightet);
26978       if (neightet.tet == dummytet) {
26979         // It's a hull face. Insert a subface at here.
26980         bondflag = true;
26981       } else {
26982         // It's an interior face. Insert a subface if two tetrahedra have
26983         //   different attributes (i.e., they belong to two regions).
26984         if (in->numberoftetrahedronattributes > 0) {
26985           if (elemattribute(neightet.tet,
26986               in->numberoftetrahedronattributes - 1) != 
26987               elemattribute(tetloop.tet,
26988               in->numberoftetrahedronattributes - 1)) {
26989             bondflag = true;
26990           }
26991         }
26992       }
26993       if (bondflag) {
26994         adjustedgering(tetloop, CCW);
26995         makeshellface(subfaces, &subloop);
26996         torg = org(tetloop);
26997         tdest = dest(tetloop);
26998         tapex = apex(tetloop);
26999         setsorg(subloop, torg);
27000         setsdest(subloop, tdest);
27001         setsapex(subloop, tapex);
27002         // Set the vertices be FREESUBVERTEX to indicate they belong to a
27003         //   facet of the domain.  They may be changed later.
27004         setpointtype(torg, FREESUBVERTEX);
27005         setpointtype(tdest, FREESUBVERTEX);
27006         setpointtype(tapex, FREESUBVERTEX);
27007         tsbond(tetloop, subloop);
27008         if (neightet.tet != dummytet) {
27009           sesymself(subloop);
27010           tsbond(neightet, subloop);
27011         }
27012       }
27013     }
27014     tetloop.tet = tetrahedrontraverse();
27015   }
27016 
27017   // Set the connection between subfaces. A subsegment may have more than
27018   //   two subfaces sharing it, 'neighshlist' stores all subfaces sharing
27019   //   one edge.
27020   neighshlist = new list(sizeof(face), NULL);
27021   // Create a map from nodes to subfaces.
27022   makesubfacemap(idx2facelist, facesperverlist);
27023 
27024   // Loop over the set of subfaces, setup the connection between subfaces.
27025   subfaces->traversalinit();
27026   subloop.sh = shellfacetraverse(subfaces);
27027   while (subloop.sh != (shellface *) NULL) {
27028     for (i = 0; i < 3; i++) {
27029       spivot(subloop, neighsh);
27030       if (neighsh.sh == dummysh) {
27031         // This side is 'empty', operate on it.
27032         torg = sorg(subloop);
27033         tdest = sdest(subloop);
27034         tapex = sapex(subloop);
27035         neighshlist->append(&subloop);
27036         iorg = pointmark(torg) - in->firstnumber;
27037         // Search its neighbor in the adjacent list of torg.
27038         for (j = idx2facelist[iorg]; j < idx2facelist[iorg + 1]; j++) {
27039           neighsh.sh = facesperverlist[j];
27040           if (neighsh.sh == subloop.sh) continue;
27041           neighsh.shver = 0;
27042           if (isfacehasedge(&neighsh, torg, tdest)) {
27043             findedge(&neighsh, torg, tdest);
27044             // Insert 'neighsh' into 'neighshlist'.
27045             if (neighshlist->len() < 2) {
27046               neighshlist->append(&neighsh);
27047             } else {
27048               for (index = 0; index < neighshlist->len() - 1; index++) {
27049                 sface1 = * (face *)(* neighshlist)[index];
27050                 sface2 = * (face *)(* neighshlist)[index + 1];
27051                 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(neighsh));
27052                 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
27053                 if (da1 < da2) {
27054                   break;  // Insert it after index.
27055                 }
27056               }
27057               neighshlist->insert(index + 1, &neighsh);
27058             }
27059           }
27060         }
27061         // Bond the subfaces in 'neighshlist'. 
27062         if (neighshlist->len() > 1) {
27063           neighsh = * (face *)(* neighshlist)[0];
27064           for (j = 1; j <= neighshlist->len(); j++) {
27065             if (j < neighshlist->len()) {
27066               neineighsh = * (face *)(* neighshlist)[j];
27067             } else {
27068               neineighsh = * (face *)(* neighshlist)[0];
27069             }
27070             sbond1(neighsh, neineighsh);
27071             neighsh = neineighsh;
27072           }
27073         } else {
27074           // No neighbor subface be found, bond 'subloop' to itself.
27075           sbond(subloop, subloop);
27076         }
27077         neighshlist->clear();
27078       }
27079       senextself(subloop);
27080     }
27081     subloop.sh = shellfacetraverse(subfaces);
27082   }
27083 
27084   // Segments will be introudced. Each segment has a unique marker (1-based).
27085   marker = 1;
27086   subfaces->traversalinit();
27087   subloop.sh = shellfacetraverse(subfaces);
27088   while (subloop.sh != (shellface *) NULL) {
27089     for (i = 0; i < 3; i++) {
27090       sspivot(subloop, subseg);
27091       if (subseg.sh == dummysh) {
27092         // This side has no subsegment bonded, check it.
27093         torg = sorg(subloop);
27094         tdest = sdest(subloop);
27095         tapex = sapex(subloop);
27096         spivot(subloop, neighsh);
27097         spivot(neighsh, neineighsh);
27098         insertsegflag = false;
27099         if (subloop.sh == neighsh.sh || subloop.sh != neineighsh.sh) {
27100           // This side is either self-bonded or more than two subfaces,
27101           //   insert a subsegment at this side.
27102           insertsegflag = true;
27103         } else {
27104           // Only two subfaces case.
27105 #ifdef SELF_CHECK
27106           assert(subloop.sh != neighsh.sh);
27107 #endif
27108           napex = sapex(neighsh);
27109           sign = orient3d(torg, tdest, tapex, napex);
27110           if (iscoplanar(torg, tdest, tapex, napex, sign, b->epsilon)) {
27111             // Although they are coplanar, we still need to check if they
27112             //   have the same boundary marker.
27113             insertsegflag = (shellmark(subloop) != shellmark(neighsh));
27114           } else {
27115             // Non-coplanar.
27116             insertsegflag = true;
27117           }
27118         }
27119         if (insertsegflag) {
27120           // Create a subsegment at this side.
27121           makeshellface(subsegs, &subseg);
27122           setsorg(subseg, torg);
27123           setsdest(subseg, tdest);
27124           // The two vertices have been marked as FREESUBVERTEX. Now mark
27125           //   them as NACUTEVERTEX.
27126           setpointtype(torg, NACUTEVERTEX);
27127           setpointtype(tdest, NACUTEVERTEX);
27128           setshellmark(subseg, marker);
27129           marker++;
27130           // Bond all subfaces to this subsegment.
27131           neighsh = subloop;
27132           do {
27133             ssbond(neighsh, subseg);
27134             spivotself(neighsh);
27135           } while (neighsh.sh != subloop.sh);
27136         }
27137       }
27138       senextself(subloop);
27139     }
27140     subloop.sh = shellfacetraverse(subfaces);
27141   }
27142   // Remember the number of input segments.
27143   insegments = subsegs->items;
27144   // Find the acute vertices and set them be type ACUTEVERTEX.
27145 
27146   // Indentify facets and set the facet marker (1-based) for subfaces.
27147   markerlist = new list((char*)"int");
27148   
27149   subfaces->traversalinit();
27150   subloop.sh = shellfacetraverse(subfaces);
27151   while (subloop.sh != (shellface *) NULL) {
27152     // Only operate on uninfected subface, after operating, infect it.
27153     if (!sinfected(subloop)) {
27154       // A new facet is found.
27155       marker = shellmark(subloop);
27156       markerlist->append(&marker);
27157       facetidx = markerlist->len(); // 'facetidx' starts from 1.
27158       setshellmark(subloop, facetidx);
27159       sinfect(subloop);
27160       neighshlist->append(&subloop);
27161       // Find out all subfaces of this facet (bounded by subsegments).
27162       for (i = 0; i < neighshlist->len(); i++) {
27163         neighsh = * (face *) (* neighshlist)[i];
27164         for (j = 0; j < 3; j++) {
27165           sspivot(neighsh, subseg);
27166           if (subseg.sh == dummysh) {
27167             spivot(neighsh, neineighsh);
27168             if (!sinfected(neineighsh)) {
27169               // 'neineighsh' is in the same facet as 'subloop'.
27170 #ifdef SELF_CHECK
27171               assert(shellmark(neineighsh) == marker);
27172 #endif
27173               setshellmark(neineighsh, facetidx);
27174               sinfect(neineighsh);
27175               neighshlist->append(&neineighsh);
27176             }
27177           }
27178           senextself(neighsh);
27179         }
27180       }
27181       neighshlist->clear();
27182     }
27183     subloop.sh = shellfacetraverse(subfaces);
27184   }
27185   // Uninfect all subfaces.
27186   subfaces->traversalinit();
27187   subloop.sh = shellfacetraverse(subfaces);
27188   while (subloop.sh != (shellface *) NULL) {
27189 #ifdef SELF_CHECK
27190     assert(sinfected(subloop));
27191 #endif
27192     suninfect(subloop);
27193     subloop.sh = shellfacetraverse(subfaces);
27194   }
27195   // Save the facet markers in 'in->facetmarkerlist'.
27196   in->numberoffacets = markerlist->len();
27197   in->facetmarkerlist = new int[in->numberoffacets];
27198   for (i = 0; i < in->numberoffacets; i++) {
27199     marker = * (int *) (* markerlist)[i];
27200     in->facetmarkerlist[i] = marker;
27201   }
27202   // Initialize the 'facetabovepointlist'.
27203   facetabovepointarray = new point[in->numberoffacets + 1];
27204   for (i = 0; i < in->numberoffacets + 1; i++) {
27205     facetabovepointarray[i] = (point) NULL;
27206   }
27207 
27208   // The mesh contains boundary now.
27209   checksubfaces = 1;
27210   // The mesh is nonconvex now.
27211   nonconvex = 1;
27212 
27213   // Is there periodic boundary confitions?
27214   if (checkpbcs) {
27215     tetgenio::pbcgroup *pg;
27216     pbcdata *pd;
27217     // Initialize the global array 'subpbcgrouptable'.
27218     createsubpbcgrouptable();
27219     // Loop for each pbcgroup i.
27220     for (i = 0; i < in->numberofpbcgroups; i++) {
27221       pg = &(in->pbcgrouplist[i]);
27222       pd = &(subpbcgrouptable[i]);
27223       // Find all subfaces of pd, set each subface's group id be i.
27224       for (j = 0; j < 2; j++) {
27225         subfaces->traversalinit();
27226         subloop.sh = shellfacetraverse(subfaces);
27227         while (subloop.sh != (shellface *) NULL) {
27228           facetidx = shellmark(subloop);
27229           marker = in->facetmarkerlist[facetidx - 1];
27230           if (marker == pd->fmark[j]) {
27231             setshellpbcgroup(subloop, i);
27232             pd->ss[j] = subloop;
27233           }
27234           subloop.sh = shellfacetraverse(subfaces);
27235         }
27236       }
27237       if (pg->pointpairlist != (int *) NULL) {
27238         // Set the connections between pbc point pairs.
27239         for (j = 0; j < pg->numberofpointpairs; j++) {
27240           iorg = pg->pointpairlist[j * 2] - in->firstnumber;
27241           idest = pg->pointpairlist[j * 2 + 1] - in->firstnumber;
27242           torg = idx2verlist[iorg];
27243           tdest = idx2verlist[idest];
27244           setpoint2pbcpt(torg, tdest);
27245           setpoint2pbcpt(tdest, torg);
27246         }
27247       }
27248     }
27249     // Create the global array 'segpbcgrouptable'.
27250     createsegpbcgrouptable();
27251   }
27252 
27253   delete markerlist;
27254   delete neighshlist;
27255   delete [] worklist;
27256   delete [] idx2tetlist;
27257   delete [] tetsperverlist;
27258   delete [] idx2facelist;
27259   delete [] facesperverlist;
27260   delete [] idx2verlist;
27261   
27262   return hullsize;
27263 }
27264 
27266 //                                                                           //
27267 // insertconstrainedpoints()    Insert a list of constrained points.         //
27268 //                                                                           //
27270 
27271 void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
27272 {
27273   queue *flipqueue;
27274   triface searchtet;
27275   face checksh, checkseg;
27276   point newpoint;
27277   enum locateresult loc;
27278   REAL *attr;
27279   bool insertflag;
27280   int covertices, outvertices;
27281   int index;
27282   int i, j;
27283   
27284   if (!b->quiet) {
27285     printf("Insert additional points into mesh.\n");
27286   }
27287   // Initialize 'flipqueue'.
27288   flipqueue = new queue(sizeof(badface));
27289   recenttet.tet = dummytet;
27290   covertices = outvertices = 0;
27291 
27292   index = 0;
27293   for (i = 0; i < addio->numberofpoints; i++) {
27294     // Create a newpoint.
27295     makepoint(&newpoint);
27296     newpoint[0] = addio->pointlist[index++];
27297     newpoint[1] = addio->pointlist[index++];
27298     newpoint[2] = addio->pointlist[index++];
27299     // Read the add point attributes if current points have attributes.
27300     if ((addio->numberofpointattributes > 0) &&
27301         (in->numberofpointattributes > 0)) {
27302       attr = addio->pointattributelist + addio->numberofpointattributes * i;
27303       for (j = 0; j < in->numberofpointattributes; j++) {
27304         if (j < addio->numberofpointattributes) {
27305           newpoint[3 + j] = attr[j];
27306         }
27307       }
27308     }
27309     // Find the location of the inserted point.
27310     searchtet = recenttet;
27311     loc = locate(newpoint, &searchtet);
27312     if (loc != ONVERTEX) {
27313       loc = adjustlocate(newpoint, &searchtet, loc, b->epsilon2);
27314     }
27315     if (loc == OUTSIDE) {
27316       loc = hullwalk(newpoint, &searchtet);
27317       if (loc == OUTSIDE) {
27318         // Perform a brute-force search.
27319         tetrahedrons->traversalinit();
27320         searchtet.tet = tetrahedrontraverse();
27321         while (searchtet.tet != (tetrahedron *) NULL) {
27322           loc = adjustlocate(newpoint, &searchtet, OUTSIDE, b->epsilon2);
27323           if (loc != OUTSIDE) break;
27324           searchtet.tet = tetrahedrontraverse();
27325         }
27326       }
27327     }
27328     // Insert the point if it not lies outside or on a vertex.
27329     insertflag = true;
27330     switch (loc) {
27331     case INTETRAHEDRON:
27332       setpointtype(newpoint, FREEVOLVERTEX);
27333       splittetrahedron(newpoint, &searchtet, flipqueue);
27334       break;
27335     case ONFACE:
27336       tspivot(searchtet, checksh);
27337       if (checksh.sh != dummysh) {
27338         // It is a boundary face. Don't insert it if -Y option is used.
27339         if (b->nobisect) {
27340           insertflag = false;
27341         } else {
27342           setpointtype(newpoint, FREESUBVERTEX);
27343         }
27344       } else {
27345         setpointtype(newpoint, FREEVOLVERTEX);
27346       }
27347       if (insertflag) {
27348         splittetface(newpoint, &searchtet, flipqueue);
27349       }
27350       break;
27351     case ONEDGE:
27352       tsspivot(&searchtet, &checkseg);
27353       if (checkseg.sh != dummysh) {
27354         if (b->nobisect) {
27355           insertflag = false;
27356         } else {
27357           setpointtype(newpoint, FREESEGVERTEX);
27358           setpoint2sh(newpoint, sencode(checkseg));
27359         }
27360       } else {
27361         tspivot(searchtet, checksh);
27362         if (checksh.sh != dummysh) {
27363           if (b->nobisect) {
27364             insertflag = false;
27365           } else {
27366             setpointtype(newpoint, FREESUBVERTEX);
27367           }
27368         } else {
27369           setpointtype(newpoint, FREEVOLVERTEX);
27370         }
27371       }
27372       if (insertflag) {
27373         splittetedge(newpoint, &searchtet, flipqueue);
27374       }
27375       break;
27376     case ONVERTEX:
27377       insertflag = false;
27378       covertices++;
27379       break;
27380     case OUTSIDE:
27381       insertflag = false;
27382       outvertices++;
27383       break;
27384     }
27385     // Remember the tetrahedron for next point searching.
27386     recenttet = searchtet;
27387     if (!insertflag) {
27388       pointdealloc(newpoint);
27389     } else {
27390       flip(flipqueue, NULL);
27391     }
27392   }
27393 
27394   if (b->verbose) {
27395     if (covertices > 0) {
27396       printf("  %d constrained points already exist.\n", covertices);
27397     }
27398     if (outvertices > 0) {
27399       printf("  %d constrained points lie outside the mesh.\n", outvertices);
27400     }
27401     printf("  %d constrained points have been inserted.\n", 
27402            addio->numberofpoints - covertices - outvertices);
27403   }
27404 
27405   delete flipqueue;
27406 }
27407 
27409 //                                                                           //
27410 // p1interpolatebgm()    Set pt size by p^1 interpolation in background mesh.//
27411 //                                                                           //
27412 // On input, 'bgmtet' is a suggesting tet in background mesh for searching   //
27413 // 'pt'. It returns the tet containing 'pt'.                                 //
27414 //                                                                           //
27416 
27417 bool tetgenmesh::p1interpolatebgm(point pt, triface* bgmtet, long *scount)
27418 {
27419   point bgmpt[4];
27420   enum locateresult loc;
27421   REAL vol, volpt[4], weights[4];
27422   int i;
27423 
27424   loc = bgm->preciselocate(pt, bgmtet, bgm->tetrahedrons->items);
27425   if (loc == OUTSIDE) {
27426     loc = bgm->hullwalk(pt, bgmtet);
27427     if (loc == OUTSIDE) {
27428       // Perform a brute-force search.
27429       if (b->verbose) {
27430         printf("Warning:  Global point location.\n");
27431       }
27432       if (scount) (*scount)++;
27433       bgm->tetrahedrons->traversalinit(); // in bgm
27434       bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
27435       while (bgmtet->tet != (tetrahedron *) NULL) {
27436         loc = bgm->adjustlocate(pt, bgmtet, OUTSIDE, b->epsilon);
27437         if (loc != OUTSIDE) break;
27438         bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
27439       }
27440     }
27441   }
27442   if (loc != OUTSIDE) {
27443     // Let p remember t.
27444     setpoint2bgmtet(pt, encode(*bgmtet)); // in m
27445     // get the corners of t.
27446     for (i = 0; i < 4; i++) bgmpt[i] = (point) bgmtet->tet[4 + i];
27447     // Calculate the weighted coordinates of p in t.
27448     vol = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], bgmpt[3]);
27449     volpt[0] = orient3d(pt, bgmpt[1], bgmpt[2], bgmpt[3]);
27450     volpt[1] = orient3d(bgmpt[0], pt, bgmpt[2], bgmpt[3]);
27451     volpt[2] = orient3d(bgmpt[0], bgmpt[1], pt, bgmpt[3]);
27452     volpt[3] = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], pt);
27453     for (i = 0; i < 4; i++) weights[i] = fabs(volpt[i] / vol);
27454     // Interpolate the solution for p.
27455     for (i = 0; i < bgm->in->numberofpointmtrs; i++) {
27456       pt[pointmtrindex + i] = weights[0] * bgmpt[0][bgm->pointmtrindex + i]
27457                             + weights[1] * bgmpt[1][bgm->pointmtrindex + i]
27458                             + weights[2] * bgmpt[2][bgm->pointmtrindex + i]
27459                             + weights[3] * bgmpt[3][bgm->pointmtrindex + i];
27460     }
27461   } else {
27462     setpoint2bgmtet(pt, (tetrahedron) NULL);  // in m
27463   }
27464   return loc != OUTSIDE;
27465 }
27466 
27468 //                                                                           //
27469 // interpolatesizemap()    Interpolate the point sizes in the given size map.//
27470 //                                                                           //
27471 // The size map is specified on each node of the background mesh. The points //
27472 // of current mesh get their sizes by interpolating.                         //
27473 //                                                                           //
27474 // This function operation on two meshes simultaneously, the current mesh m, //
27475 // and the background mesh bgm. After this function, each point p in m will  //
27476 // have a pointer to a tet of bgm.                                           //
27477 //                                                                           //
27479 
27480 void tetgenmesh::interpolatesizemap()
27481 {
27482   list *adjtetlist;
27483   triface tetloop, neightet, bgmtet;
27484   point searchpt;
27485   long scount;
27486   int *worklist;
27487   int sepcount;
27488   int i;
27489 
27490   if (b->verbose) {
27491     printf("  Interpolating size map.\n");
27492   }
27493 
27494   worklist = new int[points->items + 1];
27495   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
27496   sepcount = 0;
27497   scount = 0l;
27498 
27499   tetrahedrons->traversalinit();
27500   tetloop.tet = tetrahedrontraverse();
27501   while (tetloop.tet != (tetrahedron *) NULL) {
27502     if (!infected(tetloop)) {
27503       // Find a new subdomain.
27504       adjtetlist = new list(sizeof(triface), NULL, 1024);
27505       infect(tetloop);
27506       // Search the four corners in background mesh.
27507       for (i = 0; i < 4; i++) {
27508         searchpt = (point) tetloop.tet[4 + i];
27509         // Mark the point for avoiding multiple searchings.
27510         // assert(worklist[pointmark(searchpt)] == 0);
27511         worklist[pointmark(searchpt)] = 1;
27512         // Does it contain a pointer to bgm tet?
27513         bgm->decode(point2bgmtet(searchpt), bgmtet);
27514         if (bgm->isdead(&bgmtet)) {
27515           bgmtet = bgm->recenttet;
27516         }
27517         if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27518           bgm->recenttet = bgmtet;
27519         }
27520       } // for (i = 0; i < 4; i++)
27521       // Collect all tets in this region.
27522       adjtetlist->append(&tetloop);
27523       // Collect the tets in the subdomain.
27524       for (i = 0; i < adjtetlist->len(); i++) {
27525         tetloop = * (triface *)(* adjtetlist)[i];
27526         for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27527           sym(tetloop, neightet);
27528           if ((neightet.tet != dummytet) && !infected(neightet)) {
27529             // Only need to search for the opposite point.
27530             searchpt = oppo(neightet);
27531             if (worklist[pointmark(searchpt)] == 0) {
27532               worklist[pointmark(searchpt)] = 1;
27533               decode(point2bgmtet(searchpt), bgmtet);
27534               if (bgm->isdead(&bgmtet)) {
27535                 bgmtet = bgm->recenttet;
27536               }
27537               if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27538                 bgm->recenttet = bgmtet;
27539               }
27540             }
27541             infect(neightet);
27542             adjtetlist->append(&neightet);
27543           }
27544         }
27545       }
27546       // Increase the number of separated domains.
27547       sepcount++;
27548       delete adjtetlist;
27549     } // if (!infect())
27550     tetloop.tet = tetrahedrontraverse();
27551   }
27552 
27553   // Unmark all tets.
27554   tetrahedrons->traversalinit();
27555   tetloop.tet = tetrahedrontraverse();
27556   while (tetloop.tet != (tetrahedron *) NULL) {
27557     assert(infected(tetloop));
27558     uninfect(tetloop);
27559     tetloop.tet = tetrahedrontraverse();
27560   }
27561   delete [] worklist;
27562 
27563 #ifdef SELF_CHECK
27564   if (b->verbose && scount > 0l) {
27565     printf("  %ld brute-force searches.\n", scount);
27566   }
27567   if (b->verbose && sepcount > 0) {
27568     printf("  %d separate domains.\n", sepcount);
27569   }
27570 #endif
27571 }
27572 
27574 //                                                                           //
27575 // duplicatebgmesh()    Duplicate current mesh to background mesh.           //
27576 //                                                                           //
27577 // Current mesh 'this' is copied into 'this->bgm'.Both meshes share the same //
27578 // input tetgenio object, 'this->in', same tetgenbehavior object 'this->b'.  //
27579 //                                                                           //
27581 
27582 void tetgenmesh::duplicatebgmesh()
27583 {
27584   triface tetloop, btetloop;
27585   triface symtet, bsymtet;
27586   face bhullsh, bneighsh;
27587   point *idx2bplist, *tetptbaklist;
27588   point ploop, bploop;
27589   int idx, i;
27590 
27591   if (!b->quiet) {
27592     printf("Duplicating background mesh.\n");
27593   }
27594 
27595   // The background mesh itself has no background mesh.
27596   // assert(bgm->bgm == (tetgenmesh *) NULL);
27597   // The space for metric tensor should be allocated.
27598   // assert(bgm->sizeoftensor > 0);
27599 
27600   // Copy point list.
27601   idx2bplist = new point[points->items + 1];
27602   idx = in->firstnumber;
27603   points->traversalinit();
27604   ploop = pointtraverse();
27605   while (ploop != (point) NULL) {
27606     bgm->makepoint(&bploop);
27607     // Copy coordinates, attributes.
27608     for (i = 0; i < 3 + in->numberofpointattributes; i++) {
27609       bploop[i] = ploop[i];
27610     }
27611     // Transfer the metric tensor.
27612     for (i = 0; i < bgm->sizeoftensor; i++) {
27613       bploop[bgm->pointmtrindex + i] = ploop[pointmtrindex + i];
27614       // Metric tensor should have a positive value.
27615       if (bploop[bgm->pointmtrindex + i] <= 0.0) {
27616         printf("Error:  Point %d has non-positive size %g (-m option).\n",
27617                bgm->pointmark(bploop), bploop[bgm->pointmtrindex + i]);
27618         terminatetetgen(1);
27619       }
27620     }
27621     // Remember the point for searching.
27622     idx2bplist[idx++] = bploop; 
27623     ploop = pointtraverse();
27624   }
27625 
27626   // Copy tetrahedra list.
27627   tetptbaklist = new point[tetrahedrons->items + 1];
27628   idx = in->firstnumber;
27629   tetrahedrons->traversalinit();
27630   tetloop.tet = tetrahedrontraverse();
27631   while (tetloop.tet != (tetrahedron *) NULL) {
27632     bgm->maketetrahedron(&btetloop);
27633     // Set the four corners.
27634     for (i = 0; i < 4; i++) {
27635       ploop = (point) tetloop.tet[4 + i];
27636       bploop = idx2bplist[pointmark(ploop)];
27637       btetloop.tet[4 + i] = (tetrahedron) bploop;
27638     }
27639     // Remember the tet for setting neighbor connections.
27640     tetptbaklist[idx++] = (point) tetloop.tet[4];
27641     tetloop.tet[4] = (tetrahedron) btetloop.tet; 
27642     tetloop.tet = tetrahedrontraverse();
27643   }
27644 
27645   // Set the connections between background tetrahedra. Create background
27646   //   hull subfaces. Create the map of point-to-bgmtet. 
27647   idx = in->firstnumber;
27648   tetrahedrons->traversalinit();
27649   tetloop.tet = tetrahedrontraverse();
27650   while (tetloop.tet != (tetrahedron *) NULL) {
27651     // Get the corresponding background tet.
27652     btetloop.tet = (tetrahedron *) tetloop.tet[4];
27653     // Set the four neighbors.
27654     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27655       btetloop.loc = tetloop.loc;
27656       sym(tetloop, symtet);
27657       if ((symtet.tet != dummytet) && (symtet.tet > tetloop.tet)) {
27658         // Operate on the un-connected interior face.
27659         bsymtet.tet = (tetrahedron *) symtet.tet[4]; // The saved bgm tet.
27660         bsymtet.loc = symtet.loc;
27661         bgm->bond(btetloop, bsymtet);
27662       } else if (symtet.tet == dummytet) {
27663         // Create a subface in background mesh.
27664         bgm->makeshellface(bgm->subfaces, &bhullsh);
27665         bgm->adjustedgering(btetloop, CCW); // face to inside.
27666         bgm->setsorg(bhullsh, bgm->org(btetloop));
27667         bgm->setsdest(bhullsh, bgm->dest(btetloop));
27668         bgm->setsapex(bhullsh, bgm->apex(btetloop));
27669         bgm->tsbond(btetloop, bhullsh);
27670         // Remember a hull face for point location.
27671         bgm->dummytet[0] = bgm->encode(btetloop);
27672       }
27673     }
27674     // Restore the backup tet point.
27675     tetloop.tet[4] = (tetrahedron) tetptbaklist[idx++];
27676     // Make the point-to-bgmtet map for size interpolation.
27677     btetloop.loc = 0;
27678     for (i = 0; i < 4; i++) {
27679       ploop = (point) tetloop.tet[4 + i];
27680       setpoint2bgmtet(ploop, bgm->encode(btetloop));
27681     } 
27682     // Go to the next tet, btet.
27683     tetloop.tet = tetrahedrontraverse();
27684   }
27685 
27686   // Connect bgm hull subfaces. Note: all hull subfaces form a 2-manifold.
27687   bgm->subfaces->traversalinit();
27688   bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27689   while (bhullsh.sh != (shellface *) NULL) {
27690     bhullsh.shver = 0;
27691     bgm->stpivot(bhullsh, btetloop);
27692     assert(btetloop.tet != bgm->dummytet);
27693     bgm->adjustedgering(btetloop, CCW);
27694     for (i = 0; i < 3; i++) {
27695       bgm->spivot(bhullsh, bneighsh);
27696       if (bneighsh.sh == bgm->dummysh) {
27697         // This side is open, operate on it.
27698         bsymtet = btetloop;
27699         while (bgm->fnextself(bsymtet));
27700         bgm->tspivot(bsymtet, bneighsh);
27701         bgm->findedge(&bneighsh, bgm->sdest(bhullsh), bgm->sorg(bhullsh));
27702         bgm->sbond(bhullsh, bneighsh);
27703       }
27704       bgm->enextself(btetloop);
27705       bgm->senextself(bhullsh);
27706     }
27707     bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27708   }
27709 
27710   delete [] tetptbaklist;
27711   delete [] idx2bplist;
27712 }
27713 
27714 //
27715 // Begin of Delaunay refinement routines
27716 //
27717 
27719 //                                                                           //
27720 // marksharpsegments()    Mark sharp segments.                               //
27721 //                                                                           //
27722 // A segment s is called sharp if it is in one of the two cases:             //
27723 //  (1) There is a segment s' intersecting with s.  The internal angle (*)   //
27724 //      between s and s' is acute.                                           //
27725 //  (2) There are two facets f1 and f2 intersecting at s.  The internal      //
27726 //      dihedral angle (*) between f1 and f2 is acute.                       //
27727 // This routine finds the sharp segments and marked them as type SHARP.      //
27728 // The minimum angle between segments (minfaceang) and the minimum dihedral  //
27729 // angle between facets (minfacetdihed) are calulcated.                      //
27730 //                                                                           //
27731 // (*) The internal angle (or dihedral) bewteen two features means the angle //
27732 // inside the mesh domain.                                                   //
27733 //                                                                           //
27735 
27736 void tetgenmesh::marksharpsegments(REAL sharpangle)
27737 {
27738   triface adjtet;
27739   face startsh, spinsh, neighsh;
27740   face segloop, prevseg, nextseg;
27741   point eorg, edest;
27742   REAL ang, smallang;
27743   bool issharp;
27744   int sharpsegcount;
27745 
27746   if (b->verbose > 0) {
27747     printf("  Marking sharp segments.\n");
27748   }
27749 
27750   smallang = sharpangle * PI / 180.;
27751   sharpsegcount = 0;
27752   eorg = edest = (point) NULL; // To avoid compiler warnings.
27753    
27754   // A segment s may have been split into many subsegments. Operate the one
27755   //   which contains the origin of s. Then mark the rest of subsegments.
27756   subsegs->traversalinit();
27757   segloop.sh = shellfacetraverse(subsegs);
27758   while (segloop.sh != (shellface *) NULL) {
27759     segloop.shver = 0;
27760     senext2(segloop, prevseg);
27761     spivotself(prevseg);
27762     if (prevseg.sh == dummysh) {
27763       // Operate on this seg s.
27764       assert(shelltype(segloop) != SHARP); // It should be unmarked.
27765       issharp = false;
27766       spivot(segloop, startsh);
27767       if (startsh.sh != dummysh) {
27768         // First check if two facets form an acute dihedral angle at s.
27769         eorg = sorg(segloop);
27770         edest = sdest(segloop);
27771         spinsh = startsh;
27772         do {
27773           if (sorg(spinsh) != eorg) {
27774             sesymself(spinsh);
27775           }
27776           // Only do test when the spinsh is faceing inward.
27777           stpivot(spinsh, adjtet);          
27778           if (adjtet.tet != dummytet) {
27779             // Get the subface on the adjacent facet.
27780             spivot(spinsh, neighsh);
27781             // Do not calculate if it is self-bonded.
27782             if (neighsh.sh != spinsh.sh) {
27783               // Calculate the dihedral angle between the two subfaces.
27784               ang = facedihedral(eorg, edest, sapex(spinsh), sapex(neighsh));
27785               // Only do check if a sharp angle has not been found.
27786               if (!issharp) issharp = (ang < smallang);
27787               // Remember the smallest facet dihedral angle.
27788               minfacetdihed = minfacetdihed < ang ? minfacetdihed : ang;
27789             }
27790           }
27791           // Go to the next facet.
27792           spivotself(spinsh);
27793         } while (spinsh.sh != startsh.sh);
27794         // if (!issharp) {
27795           // Second check if s forms an acute angle with another seg.
27796           spinsh = startsh;
27797           do {
27798             if (sorg(spinsh) != eorg) {
27799               sesymself(spinsh);
27800             }
27801             // Calculate the angle between s and s' of this facet.
27802             neighsh = spinsh;
27803             // Rotate edges around 'eorg' until meeting another seg s'. Such  
27804             //   seg (s') must exist since the facet is segment-bounded.
27805             //   The sum of the angles of faces at 'eorg' gives the internal
27806             //   angle between the two segments.
27807             ang = 0.0;
27808             do {
27809               ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27810               senext2self(neighsh);
27811               sspivot(neighsh, nextseg);
27812               if (nextseg.sh != dummysh) break;
27813               // Go to the next coplanar subface.
27814               spivotself(neighsh);
27815               assert(neighsh.sh != dummysh);
27816               if (sorg(neighsh) != eorg) {
27817                 sesymself(neighsh);
27818               }
27819             } while (true);
27820             // Only do check if a sharp angle has not been found.
27821             if (!issharp) issharp = (ang < smallang);
27822             // Remember the smallest input face angle.
27823             minfaceang = minfaceang < ang ? minfaceang : ang;
27824             // Go to the next facet.
27825             spivotself(spinsh);
27826           } while (spinsh.sh != startsh.sh);
27827         // }
27828       }
27829       if (issharp) {
27830         setshelltype(segloop, SHARP);
27831         // Set the type for all subsegments at forwards.
27832         senext(segloop, nextseg);
27833         spivotself(nextseg);
27834         while (nextseg.sh != dummysh) {
27835           nextseg.shver = 0;
27836           setshelltype(nextseg, SHARP);
27837           senextself(nextseg);
27838           spivotself(nextseg);
27839         }
27840         sharpsegcount++;
27841       }
27842     }
27843     segloop.sh = shellfacetraverse(subsegs);
27844   }
27845 
27846   // So far we have marked all segments which have an acute dihedral angle
27847   //   or whose ORIGINs have an acute angle. In the un-marked subsegments,
27848   //   there are possible ones whose DESTINATIONs have an acute angle.
27849   subsegs->traversalinit();
27850   segloop.sh = shellfacetraverse(subsegs);
27851   while (segloop.sh != (shellface *) NULL) {
27852     // Only operate if s is non-sharp and contains the dest.
27853     segloop.shver = 0;
27854     senext(segloop, nextseg);
27855     spivotself(nextseg);
27856     // if ((nextseg.sh == dummysh) && (shelltype(segloop) != SHARP)) {
27857     if (nextseg.sh == dummysh) {
27858       // issharp = false;
27859       issharp = (shelltype(segloop) == SHARP);
27860       spivot(segloop, startsh);
27861       if (startsh.sh != dummysh) {
27862         // Check if s forms an acute angle with another seg.
27863         eorg = sdest(segloop);
27864         spinsh = startsh;
27865         do {
27866           if (sorg(spinsh) != eorg) {
27867             sesymself(spinsh);
27868           }
27869           // Calculate the angle between s and s' of this facet.
27870           neighsh = spinsh;
27871           ang = 0.0;
27872           do {
27873             ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27874             senext2self(neighsh);
27875             sspivot(neighsh, nextseg);
27876             if (nextseg.sh != dummysh) break;
27877             // Go to the next coplanar subface.
27878             spivotself(neighsh);
27879             assert(neighsh.sh != dummysh);
27880             if (sorg(neighsh) != eorg) {
27881               sesymself(neighsh);
27882             }
27883           } while (true);
27884           // Only do check if a sharp angle has not been found.
27885           if (!issharp) issharp = (ang < smallang);
27886           // Remember the smallest input face angle.
27887           minfaceang = minfaceang < ang ? minfaceang : ang;
27888           // Go to the next facet.
27889           spivotself(spinsh);
27890         } while (spinsh.sh != startsh.sh);
27891       }
27892       if (issharp) {
27893         setshelltype(segloop, SHARP);
27894         // Set the type for all subsegments at backwards.
27895         senext2(segloop, prevseg);
27896         spivotself(prevseg);
27897         while (prevseg.sh != dummysh) {
27898           prevseg.shver = 0;
27899           setshelltype(prevseg, SHARP);
27900           senext2self(prevseg);
27901           spivotself(prevseg);
27902         }
27903         sharpsegcount++;
27904       }
27905     }
27906     segloop.sh = shellfacetraverse(subsegs);
27907   } 
27908 
27909   if ((b->verbose > 0) && (sharpsegcount > 0)) {
27910     printf("  %d sharp segments.\n", sharpsegcount);
27911   }
27912 }
27913 
27915 //                                                                           //
27916 // decidefeaturepointsizes()    Decide the sizes for all feature points.     //
27917 //                                                                           //
27918 // A feature point is a point on a sharp segment. Every feature point p will //
27919 // be assigned a positive size which is the radius of the protecting ball.   //
27920 //                                                                           //
27921 // The size of a feature point may be specified by one of the following ways://
27922 //   (1) directly specifying on an input vertex (by using .mtr file);        //
27923 //   (2) imposing a fixed maximal volume constraint ('-a__' option);         //
27924 //   (3) imposing a maximal volume constraint in a region ('-a' option);     //
27925 //   (4) imposing a maximal area constraint on a facet (in .var file);       //
27926 //   (5) imposing a maximal length constraint on a segment (in .var file);   //
27927 //   (6) combining (1) - (5).                                                //
27928 //   (7) automatically deriving a size if none of (1) - (6) is available.    //
27929 // In case (7),the size of p is set to be the smallest edge length among all //
27930 // edges connecting at p.  The final size of p is the minimum of (1) - (7).  //
27931 //                                                                           //
27933 
27934 void tetgenmesh::decidefeaturepointsizes()
27935 {
27936   list *tetlist, *verlist;
27937   shellface **segsperverlist;
27938   triface starttet;
27939   face shloop;
27940   face checkseg, prevseg, nextseg, testseg;
27941   point ploop, adjpt, e1, e2;
27942   REAL lfs_0, len, vol, maxlen, varlen;
27943   bool isfeature;
27944   int *idx2seglist;
27945   int featurecount;
27946   int idx, i, j;
27947 
27948   maxlen = 0.0;
27949   
27950   if (b->verbose > 0) {
27951     printf("  Deciding feature-point sizes.\n");
27952   }
27953 
27954   // Constructing a map from vertices to segments.
27955   makesegmentmap(idx2seglist, segsperverlist);
27956   // Initialize working lists.
27957   tetlist = new list(sizeof(triface), NULL, 256);
27958   verlist = new list(sizeof(point *), NULL, 256);
27959 
27960   if (b->fixedvolume) {
27961     // A fixed volume constraint is imposed. This gives an upper bound of
27962     //   the maximal radius of the protect ball of a vertex.
27963     maxlen = pow(6.0 * b->maxvolume, 1.0/3.0);
27964   }
27965 
27966   if (!b->refine) {
27967     // Initially correct types for Steiner points.
27968     featurecount = 0;
27969     points->traversalinit();
27970     ploop = pointtraverse();
27971     while (ploop != (point) NULL) {
27972       if (pointtype(ploop) == NACUTEVERTEX) {
27973         if (point2sh(ploop) != (shellface) NULL) {
27974           setpointtype(ploop, FREESEGVERTEX);
27975           featurecount++;
27976         }
27977       }
27978       ploop = pointtraverse();
27979     }
27980 #ifdef SELF_CHECK
27981     if ((b->verbose > 0) && (featurecount > 0)) {
27982       printf("  %d Steiner points correction.\n", featurecount);
27983     }
27984 #endif
27985   }
27986 
27987   // First only assign a size of p if p is not a Steiner point. The size of
27988   //   a Steiner point will be interpolated later from the endpoints of the
27989   //   segment on which it lies. 
27990   featurecount = 0;
27991   points->traversalinit();
27992   ploop = pointtraverse();
27993   while (ploop != (point) NULL) {
27994     if (pointtype(ploop) != FREESEGVERTEX) {
27995       // Is p a feature point?
27996       isfeature = false;
27997       idx = pointmark(ploop) - in->firstnumber;
27998       for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; i++) {
27999         checkseg.sh = segsperverlist[i];
28000         isfeature = (shelltype(checkseg) == SHARP);
28001       }
28002       // Decide the size of p if it is on a sharp segment.
28003       if (isfeature) {
28004         // Find a tet containing p (checkseg is a sharp seg which contains p).
28005         sstpivot(&checkseg, &starttet);
28006         // Form star(p).
28007         tetlist->append(&starttet);
28008         formstarpolyhedron(ploop, tetlist, verlist, true);
28009         // Decide the size for p if no input size is given on input.
28010         if (ploop[pointmtrindex] == 0.0) {
28011           // Calculate lfs_0(p).
28012           lfs_0 = longest;
28013           for (i = 0; i < verlist->len(); i++) {
28014             adjpt = * (point *)(* verlist)[i];
28015             if (pointtype(adjpt) == FREESEGVERTEX) {
28016               // A Steiner point q. Find the seg it lies on.
28017               sdecode(point2sh(adjpt), checkseg);
28018               assert(checkseg.sh != dummysh);
28019               checkseg.shver = 0;
28020               // Find the origin of this seg.
28021               prevseg = checkseg;
28022               do {
28023                 senext2(prevseg, testseg);
28024                 spivotself(testseg);
28025                 if (testseg.sh == dummysh) break;
28026                 prevseg = testseg; // Go to the previous subseg.
28027                 prevseg.shver = 0;
28028               } while (true);
28029               // Find the dest of this seg.
28030               nextseg = checkseg;
28031               do {
28032                 senext(nextseg, testseg);
28033                 spivotself(testseg);
28034                 if (testseg.sh == dummysh) break;
28035                 nextseg = testseg; // Go to the next subseg.
28036                 nextseg.shver = 0;
28037               } while (true);
28038               e1 = sorg(prevseg);
28039               e2 = sdest(nextseg);
28040               // Check if p is the origin or the dest of this seg.
28041               if (ploop == e1) {
28042                 // Set q to be the dest of this seg.
28043                 adjpt = e2;
28044               } else if (ploop == e2) {
28045                 // Set q to be the org of this seg.
28046                 adjpt = e1;
28047               }
28048             }
28049             len = distance(ploop, adjpt);
28050             if (lfs_0 > len) lfs_0 = len;
28051           }
28052           ploop[pointmtrindex] = lfs_0;
28053         }
28054         if (b->fixedvolume) {
28055           // A fixed volume constraint is imposed. Adjust H(p) <= maxlen.
28056           if (ploop[pointmtrindex] > maxlen) {
28057             ploop[pointmtrindex] = maxlen;
28058           }
28059         }
28060         if (b->varvolume) {
28061           // Variant volume constraints are imposed. Adjust H(p) <= varlen.
28062           for (i = 0; i < tetlist->len(); i++) {
28063             starttet = * (triface *)(* tetlist)[i];
28064             vol = volumebound(starttet.tet);
28065             if (vol > 0.0) {
28066               varlen = pow(6 * vol, 1.0/3.0);
28067               if (ploop[pointmtrindex] > varlen) {
28068                 ploop[pointmtrindex] = varlen;
28069               }
28070             }
28071           }
28072         }
28073         // Clear working lists.
28074         tetlist->clear();
28075         verlist->clear();
28076         featurecount++;
28077       } else {
28078         // NO feature point, set the size of p be zero.
28079         ploop[pointmtrindex] = 0.0;
28080       }
28081     } // if (pointtype(ploop) != FREESEGVERTEX) {
28082     ploop = pointtraverse();
28083   }
28084 
28085   if (b->verbose > 0) {
28086     printf("  %d feature points.\n", featurecount);
28087   }
28088 
28089   if (!b->refine) {
28090     // Second only assign sizes for all Steiner points. A Steiner point p
28091     //   inserted on a sharp segment s is assigned a size by interpolating
28092     //   the sizes of the original endpoints of s.
28093     featurecount = 0;
28094     points->traversalinit();
28095     ploop = pointtraverse();
28096     while (ploop != (point) NULL) {
28097       if (pointtype(ploop) == FREESEGVERTEX) {
28098         if (ploop[pointmtrindex] == 0.0) {
28099           sdecode(point2sh(ploop), checkseg);
28100           assert(checkseg.sh != dummysh);
28101           if (shelltype(checkseg) == SHARP) {
28102             checkseg.shver = 0;
28103             // Find the origin of this seg.
28104             prevseg = checkseg;
28105             do {
28106               senext2(prevseg, testseg);
28107               spivotself(testseg);
28108               if (testseg.sh == dummysh) break;
28109               prevseg = testseg; // Go the previous subseg.
28110               prevseg.shver = 0;
28111             } while (true);
28112             // Find the dest of this seg.
28113             nextseg = checkseg;
28114             do {
28115               senext(nextseg, testseg);
28116               spivotself(testseg);
28117               if (testseg.sh == dummysh) break;
28118               nextseg = testseg; // Go the next subseg.
28119               nextseg.shver = 0;
28120             } while (true);
28121             e1 = sorg(prevseg);
28122             e2 = sdest(nextseg);
28123             len = distance(e1, e2);
28124             lfs_0 = distance(e1, ploop);
28125             // The following assert() happens when -Y option is used.
28126             if (b->nobisect == 0) {
28127               assert(lfs_0 < len); 
28128             }
28129             ploop[pointmtrindex] = e1[pointmtrindex]
28130               + (lfs_0 / len) * (e2[pointmtrindex] - e1[pointmtrindex]);
28131             featurecount++;
28132           } else {
28133             // NO feature point, set the size of p be zero.
28134             ploop[pointmtrindex] = 0.0;
28135           } // if (shelltype(checkseg) == SHARP)
28136         } // if (ploop[pointmtrindex] == 0.0)
28137       } // if (pointtype(ploop) != FREESEGVERTEX)
28138       ploop = pointtraverse();
28139     }
28140     if ((b->verbose > 0) && (featurecount > 0)) {
28141       printf("  %d Steiner feature points.\n", featurecount);
28142     }
28143   }
28144 
28145   if (varconstraint) {
28146     // A .var file exists. Adjust feature sizes.
28147     if (in->facetconstraintlist) {
28148       // Have facet area constrains.
28149       subfaces->traversalinit();
28150       shloop.sh = shellfacetraverse(subfaces);
28151       while (shloop.sh != (shellface *) NULL) {
28152         varlen = areabound(shloop);
28153         if (varlen > 0.0) {
28154           // Check if the three corners are feature points.
28155           varlen = sqrt(varlen);
28156           for (j = 0; j < 3; j++) {
28157             ploop = (point) shloop.sh[3 + j];
28158             isfeature = false;
28159             idx = pointmark(ploop) - in->firstnumber;
28160             for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; 
28161                  i++) {
28162               checkseg.sh = segsperverlist[i];
28163               isfeature = (shelltype(checkseg) == SHARP);
28164             }
28165             if (isfeature) {
28166               assert(ploop[pointmtrindex] > 0.0);
28167               if (ploop[pointmtrindex] > varlen) {
28168                 ploop[pointmtrindex] = varlen;
28169               }
28170             }
28171           } // for (j = 0; j < 3; j++)
28172         }
28173         shloop.sh = shellfacetraverse(subfaces);
28174       }
28175     }
28176     if (in->segmentconstraintlist) {
28177       // Have facet area constrains.
28178       subsegs->traversalinit();
28179       shloop.sh = shellfacetraverse(subsegs);
28180       while (shloop.sh != (shellface *) NULL) {
28181         varlen = areabound(shloop);
28182         if (varlen > 0.0) {
28183           // Check if the two endpoints are feature points.
28184           for (j = 0; j < 2; j++) {
28185             ploop = (point) shloop.sh[3 + j];
28186             isfeature = false;
28187             idx = pointmark(ploop) - in->firstnumber;
28188             for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; 
28189                  i++) {
28190               checkseg.sh = segsperverlist[i];
28191               isfeature = (shelltype(checkseg) == SHARP);
28192             }
28193             if (isfeature) {
28194               assert(ploop[pointmtrindex] > 0.0);
28195               if (ploop[pointmtrindex] > varlen) {
28196                 ploop[pointmtrindex] = varlen;
28197               }
28198             }
28199           } // for (j = 0; j < 2; j++)
28200         }
28201         shloop.sh = shellfacetraverse(subsegs);
28202       }
28203     }
28204   } // if (varconstraint)
28205 
28206   delete [] segsperverlist;
28207   delete [] idx2seglist;
28208   delete tetlist;
28209   delete verlist;
28210 }
28211 
28213 //                                                                           //
28214 // enqueueencsub()    Add an encroached subface into the queue.              //
28215 //                                                                           //
28217 
28218 void tetgenmesh::enqueueencsub(face* testsub, point encpt, int quenumber,
28219   REAL* cent)
28220 {
28221   badface *encsub;
28222   int i;
28223 
28224   encsub = (badface *) badsubfaces->alloc();
28225   encsub->ss = *testsub;
28226   encsub->forg = sorg(*testsub);
28227   encsub->fdest = sdest(*testsub);
28228   encsub->fapex = sapex(*testsub);
28229   encsub->foppo = (point) encpt;
28230   for (i = 0; i < 3; i++) encsub->cent[i] = cent[i];
28231   encsub->nextitem = (badface *) NULL;
28232   // Set the pointer of 'encsubseg' into 'testsub'.  It has two purposes:
28233   //   (1) We can regonize it is encroached; (2) It is uniquely queued.
28234   setshell2badface(encsub->ss, encsub);
28235   // Add the subface to the end of a queue (quenumber = 2, high priority).
28236   *subquetail[quenumber] = encsub;
28237   // Maintain a pointer to the NULL pointer at the end of the queue.
28238   subquetail[quenumber] = &encsub->nextitem;
28239   if (b->verbose > 2) {
28240     printf("    Queuing subface (%d, %d, %d) [%d].\n", pointmark(encsub->forg),
28241            pointmark(encsub->fdest), pointmark(encsub->fapex), quenumber);
28242   }
28243 }
28244 
28246 //                                                                           //
28247 // dequeueencsub()    Remove an enc-subface from the front of the queue.     //
28248 //                                                                           //
28250 
28251 tetgenmesh::badface* tetgenmesh::dequeueencsub(int* pquenumber)
28252 {
28253   badface *result;
28254   int quenumber;
28255 
28256   // Look for a nonempty queue.
28257   for (quenumber = 2; quenumber >= 0; quenumber--) {
28258     result = subquefront[quenumber];
28259     if (result != (badface *) NULL) {
28260       // Remove the badface from the queue.
28261       subquefront[quenumber] = result->nextitem;
28262       // Maintain a pointer to the NULL pointer at the end of the queue.
28263       if (subquefront[quenumber] == (badface *) NULL) {
28264         subquetail[quenumber] = &subquefront[quenumber];
28265       }
28266       *pquenumber = quenumber;
28267       return result;
28268     }
28269   }
28270   return (badface *) NULL;
28271 }
28272 
28274 //                                                                           //
28275 // enqueuebadtet()    Add a tetrahedron into the queue.                      //
28276 //                                                                           //
28278 
28279 void tetgenmesh::enqueuebadtet(triface* testtet, REAL ratio2, REAL* cent)
28280 {
28281   badface *newbadtet;
28282   int queuenumber;
28283   int i;
28284 
28285   // Allocate space for the bad tetrahedron.
28286   newbadtet = (badface *) badtetrahedrons->alloc();
28287   newbadtet->tt = *testtet;
28288   newbadtet->key = ratio2;
28289   if (cent != NULL) {
28290     for (i = 0; i < 3; i++) newbadtet->cent[i] = cent[i];
28291   } else {
28292     for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
28293   }
28294   newbadtet->forg = org(*testtet);
28295   newbadtet->fdest = dest(*testtet);
28296   newbadtet->fapex = apex(*testtet);
28297   newbadtet->foppo = oppo(*testtet);
28298   newbadtet->nextitem = (badface *) NULL;
28299   // Determine the appropriate queue to put the bad tetrahedron into.
28300   if (ratio2 > b->goodratio) {
28301     // queuenumber = (int) ((ratio2 - b->goodratio) / 0.5);
28302     queuenumber = (int) (64.0 - 64.0 / ratio2);
28303     // 'queuenumber' may overflow (negative) caused by a very large ratio.
28304     if ((queuenumber > 63) || (queuenumber < 0)) {
28305       queuenumber = 63;
28306     }
28307   } else {
28308     // It's not a bad ratio; put the tet in the lowest-priority queue.
28309     queuenumber = 0;
28310   }
28311 
28312   // Are we inserting into an empty queue?
28313   if (tetquefront[queuenumber] == (badface *) NULL) {
28314     // Yes. Will this become the highest-priority queue?
28315     if (queuenumber > firstnonemptyq) {
28316       // Yes, this is the highest-priority queue.
28317       nextnonemptyq[queuenumber] = firstnonemptyq;
28318       firstnonemptyq = queuenumber; 
28319     } else {
28320       // No. Find the queue with next higher priority.
28321       i = queuenumber + 1;
28322       while (tetquefront[i] == (badface *) NULL) {
28323         i++;
28324       }
28325       // Mark the newly nonempty queue as following a higher-priority queue.
28326       nextnonemptyq[queuenumber] = nextnonemptyq[i];
28327       nextnonemptyq[i] = queuenumber;
28328     }
28329     // Put the bad tetrahedron at the beginning of the (empty) queue.
28330     tetquefront[queuenumber] = newbadtet;
28331   } else {
28332     // Add the bad tetrahedron to the end of an already nonempty queue.
28333     tetquetail[queuenumber]->nextitem = newbadtet;
28334   }
28335   // Maintain a pointer to the last tetrahedron of the queue.
28336   tetquetail[queuenumber] = newbadtet;
28337 
28338   if (b->verbose > 2) {
28339     printf("    Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
28340            pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
28341            pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
28342            sqrt(ratio2), queuenumber);
28343   }
28344 }
28345 
28347 //                                                                           //
28348 // dequeuebadtet()    Remove a tetrahedron from the front of the queue.      //
28349 //                                                                           //
28351 
28352 tetgenmesh::badface* tetgenmesh::topbadtetra()
28353 {
28354   // Keep a record of which queue was accessed in case dequeuebadtetra()
28355   //   is called later.
28356   recentq = firstnonemptyq;
28357   // If no queues are nonempty, return NULL.
28358   if (firstnonemptyq < 0) {
28359     return (badface *) NULL;
28360   } else {
28361     // Return the first tetrahedron of the highest-priority queue.
28362     return tetquefront[firstnonemptyq];
28363   }
28364 }
28365 
28366 void tetgenmesh::dequeuebadtet()
28367 {
28368   badface *deadbadtet;
28369   int i;
28370 
28371   // If queues were empty last time topbadtetra() was called, do nothing.
28372   if (recentq >= 0) {
28373     // Find the tetrahedron last returned by topbadtetra().
28374     deadbadtet = tetquefront[recentq];
28375     // Remove the tetrahedron from the queue.
28376     tetquefront[recentq] = deadbadtet->nextitem;
28377     // If this queue is now empty, update the list of nonempty queues.
28378     if (deadbadtet == tetquetail[recentq]) {
28379       // Was this the highest-priority queue?
28380       if (firstnonemptyq == recentq) {
28381         // Yes; find the queue with next lower priority.
28382         firstnonemptyq = nextnonemptyq[firstnonemptyq];
28383       } else {
28384         // No; find the queue with next higher priority.
28385         i = recentq + 1;
28386         while (tetquefront[i] == (badface *) NULL) {
28387           i++;
28388         }
28389         nextnonemptyq[i] = nextnonemptyq[recentq];
28390       }
28391     }
28392     // Return the bad tetrahedron to the pool.
28393     badfacedealloc(badtetrahedrons, deadbadtet);
28394   }
28395 }
28396 
28398 //                                                                           //
28399 // checkseg4encroach()    Check a subsegment to see if it is encroached.     //
28400 //                                                                           //
28401 // A segment s is encroached if there is a vertex lies inside or on its dia- //
28402 // metral circumsphere, i.e., s faces an angle theta >= 90 degrees.          //
28403 //                                                                           //
28404 // If 'testpt' (p) != NULL, only test if 'testseg' (s) is encroached by it,  //
28405 // else, check all apexes of faces around s. Return TRUE if s is encroached. //
28406 // If and 'enqflag' is TRUE, add it into 'badsubsegs' if s is encroached.    //
28407 //                                                                           //
28408 // If 'prefpt' != NULL, it returns the reference point (defined in my paper) //
28409 // if it exists.  This point is will be used to split s.                     //
28410 //                                                                           //
28412 
28413 bool tetgenmesh::checkseg4encroach(face* testseg, point testpt, point* prefpt,
28414   bool enqflag)
28415 {
28416   badface *encsubseg;
28417   triface starttet, spintet;
28418   point eorg, edest, eapex, encpt;
28419   REAL cent[3], radius, dist, diff;
28420   REAL maxradius;
28421   bool enq;
28422   int hitbdry;
28423 
28424   enq = false;
28425   eorg = sorg(*testseg);
28426   edest = sdest(*testseg);
28427   cent[0] = 0.5 * (eorg[0] + edest[0]);
28428   cent[1] = 0.5 * (eorg[1] + edest[1]);
28429   cent[2] = 0.5 * (eorg[2] + edest[2]);
28430   radius = distance(cent, eorg);
28431 
28432   if (varconstraint && (areabound(*testseg) > 0.0)) {
28433     enq = (2.0 * radius) > areabound(*testseg);
28434   }
28435 
28436   if (!enq) {
28437     maxradius = 0.0;
28438     if (testpt == (point) NULL) {
28439       // Check if it is encroached by traversing all faces containing it.
28440       sstpivot(testseg, &starttet);
28441       eapex = apex(starttet);
28442       spintet = starttet;
28443       hitbdry = 0;
28444       do {
28445         dist = distance(cent, apex(spintet));
28446         diff = dist - radius;
28447         if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28448         if (diff <= 0.0) {
28449           // s is encroached.
28450           enq = true;
28451           if (prefpt != (point *) NULL) {
28452             // Find the reference point.
28453             encpt = apex(spintet);
28454             circumsphere(eorg, edest, encpt, NULL, NULL, &dist);
28455             if (dist > maxradius) {
28456               // Rememebr this point.
28457               *prefpt = encpt;
28458               maxradius = dist;
28459             }
28460           } else {
28461             break;
28462           }
28463         }
28464         if (!fnextself(spintet)) {
28465           hitbdry++;
28466           if (hitbdry < 2) {
28467             esym(starttet, spintet);
28468             if (!fnextself(spintet)) {
28469               hitbdry++;
28470             } 
28471           }
28472         }
28473       } while (apex(spintet) != eapex && (hitbdry < 2));
28474     } else {
28475       // Only check if 'testseg' is encroached by 'testpt'.
28476       dist = distance(cent, testpt);
28477       diff = dist - radius;
28478       if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28479       enq = (diff <= 0.0);
28480     }
28481   }
28482 
28483   if (enq && enqflag) {
28484     if (b->verbose > 2) {
28485       printf("    Queuing encroaching subsegment (%d, %d).\n",
28486              pointmark(eorg), pointmark(edest));
28487     }
28488     encsubseg = (badface *) badsubsegs->alloc();
28489     encsubseg->ss = *testseg;
28490     encsubseg->forg = eorg;
28491     encsubseg->fdest = edest;
28492     encsubseg->foppo = (point) NULL; // Not used.
28493     // Set the pointer of 'encsubseg' into 'testseg'.  It has two purposes:
28494     //   (1) We can regonize it is encroached; (2) It is uniquely queued.
28495     setshell2badface(encsubseg->ss, encsubseg);
28496   }
28497   
28498   return enq;
28499 }
28500 
28502 //                                                                           //
28503 // checksub4encroach()    Check a subface to see if it is encroached.        //
28504 //                                                                           //
28505 // A subface f is encroached if there is a vertex inside or on its diametral //
28506 // circumsphere.                                                             //
28507 //                                                                           //
28508 // If 'testpt (p) != NULL', test if 'testsub' (f) is encroached by it, else, //
28509 // test if f is encroached by one of the two opposites of the adjacent tets. //
28510 // Return TRUE if f is encroached and queue it if 'enqflag' is set.          //
28511 //                                                                           //
28513 
28514 bool tetgenmesh::checksub4encroach(face* testsub, point testpt, bool enqflag)
28515 {
28516   triface abuttet;
28517   point pa, pb, pc, encpt;
28518   REAL A[4][4], rhs[4], D;
28519   REAL cent[3], area;
28520   REAL radius, dist, diff;
28521   bool enq;
28522   int indx[4];
28523   int quenumber;
28524   
28525   enq = false;
28526   radius = 0.0;
28527   encpt = (point) NULL;
28528 
28529   pa = sorg(*testsub);
28530   pb = sdest(*testsub);
28531   pc = sapex(*testsub);
28532   
28533   // Compute the coefficient matrix A (3x3).
28534   A[0][0] = pb[0] - pa[0];
28535   A[0][1] = pb[1] - pa[1];
28536   A[0][2] = pb[2] - pa[2]; // vector V1 (pa->pb)
28537   A[1][0] = pc[0] - pa[0];
28538   A[1][1] = pc[1] - pa[1];
28539   A[1][2] = pc[2] - pa[2]; // vector V2 (pa->pc)
28540   cross(A[0], A[1], A[2]); // vector V3 (V1 X V2)
28541 
28542   if (varconstraint && (areabound(*testsub) > 0.0)) {
28543     // Check if the subface has too big area.
28544     area = 0.5 * sqrt(dot(A[2], A[2]));
28545     enq = area > areabound(*testsub);
28546     if (enq) {
28547       quenumber = 2; // A queue of subfaces having too big area.
28548     }
28549   }
28550 
28551   // Compute the right hand side vector b (3x1).
28552   rhs[0] = 0.5 * dot(A[0], A[0]);
28553   rhs[1] = 0.5 * dot(A[1], A[1]);
28554   rhs[2] = 0.0;
28555   // Solve the 3 by 3 equations use LU decomposition with partial pivoting
28556   //   and backward and forward substitute..
28557   if (lu_decmp(A, 3, indx, &D, 0)) {
28558     lu_solve(A, 3, indx, rhs, 0);
28559     cent[0] = pa[0] + rhs[0];
28560     cent[1] = pa[1] + rhs[1];
28561     cent[2] = pa[2] + rhs[2];
28562     radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
28563   }
28564   
28565   if (!enq) {
28566     // Check if the subface is encroached.
28567     if (testpt == (point) NULL) {
28568       stpivot(*testsub, abuttet);
28569       if (abuttet.tet != dummytet) {
28570         dist = distance(cent, oppo(abuttet));
28571         diff = dist - radius;
28572         if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28573         enq = (diff <= 0.0);
28574         if (enq) encpt = oppo(abuttet);
28575       }
28576       if (!enq) {
28577         sesymself(*testsub);
28578         stpivot(*testsub, abuttet);
28579         if (abuttet.tet != dummytet) {
28580           dist = distance(cent, oppo(abuttet));
28581           diff = dist - radius;
28582           if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28583           enq = (diff <= 0.0);
28584           if (enq) encpt = oppo(abuttet);
28585         }
28586       }
28587     } else {
28588       dist = distance(cent, testpt);
28589       diff = dist - radius;
28590       if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28591       enq = (diff <= 0.0);
28592     }
28593     if (enq) {
28594       quenumber = 0; // A queue of encroached subfaces.
28595     }
28596   }
28597 
28598   if (enq && enqflag) {
28599     enqueueencsub(testsub, encpt, quenumber, cent);    
28600   }
28601 
28602   return enq;
28603 }
28604 
28606 //                                                                           //
28607 // checktet4badqual()    Test a tetrahedron for quality measures.            //
28608 //                                                                           //
28609 // Tests a tetrahedron to see if it satisfies the minimum ratio condition    //
28610 // and the maximum volume condition. Tetrahedra that aren't upto spec are    //
28611 // added to the bad tetrahedron queue.                                       //
28612 //                                                                           //
28614 
28615 bool tetgenmesh::checktet4badqual(triface* testtet, bool enqflag)
28616 {
28617   point pa, pb, pc, pd, pe1, pe2;
28618   REAL vda[3], vdb[3], vdc[3];
28619   REAL vab[3], vbc[3], vca[3]; 
28620   REAL N[4][3], A[4][4], rhs[4], D;
28621   REAL elen[6], circumcent[3];
28622   REAL bicent[3], offcent[3];
28623   REAL volume, L, cosd;
28624   REAL radius2, smlen2, ratio2;
28625   REAL dist, sdist, split;
28626   bool enq;
28627   int indx[4];
28628   int sidx, i, j; 
28629 
28630   pa = (point) testtet->tet[4];
28631   pb = (point) testtet->tet[5];
28632   pc = (point) testtet->tet[6];
28633   pd = (point) testtet->tet[7];
28634 
28635   // Get the edge vectors vda: d->a, vdb: d->b, vdc: d->c.
28636   // Set the matrix A = [vda, vdb, vdc]^T.
28637   for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
28638   for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
28639   for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
28640   // Get the rest edge vectors
28641   for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
28642   for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i];
28643   for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i];
28644 
28645   // Lu-decompose the matrix A.
28646   lu_decmp(A, 3, indx, &D, 0);
28647   // Get the volume of abcd.
28648   volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
28649   if (volume < 0.0) volume = -volume;
28650   // Check the radiu-edge ratio of the tet.
28651   rhs[0] = 0.5 * dot(vda, vda);
28652   rhs[1] = 0.5 * dot(vdb, vdb);
28653   rhs[2] = 0.5 * dot(vdc, vdc);
28654   lu_solve(A, 3, indx, rhs, 0);
28655   // Get the circumcenter.
28656   for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
28657   // Get the square of the circumradius.
28658   radius2 = dot(rhs, rhs);
28659   // Find the square of the shortest edge length.
28660   elen[0] = dot(vda, vda);
28661   elen[1] = dot(vdb, vdb);
28662   elen[2] = dot(vdc, vdc);
28663   elen[3] = dot(vab, vab);
28664   elen[4] = dot(vbc, vbc);
28665   elen[5] = dot(vca, vca);
28666   smlen2 = elen[0]; sidx = 0;
28667   for (i = 1; i < 6; i++) {
28668     if (smlen2 > elen[i]) { smlen2 = elen[i]; sidx = i; }
28669   }
28670   // Calculate the square of radius-edge ratio.
28671   ratio2 = radius2 / smlen2;
28672   // Check whether the ratio is smaller than permitted.
28673   enq = ratio2 > b->goodratio;
28674   if (!enq) {
28675     // abcd has good ratio.
28676     // ratio2 = 0.0;
28677     // if (b->offcenter) {
28678       // Test if it is a sliver.
28679       // Compute the 4 face normals (N[0], ..., N[3]).
28680       for (j = 0; j < 3; j++) {
28681         for (i = 0; i < 3; i++) rhs[i] = 0.0;
28682         rhs[j] = 1.0;  // Positive means the inside direction
28683         lu_solve(A, 3, indx, rhs, 0);
28684         for (i = 0; i < 3; i++) N[j][i] = rhs[i];
28685       }
28686       // Get the fourth normal by summing up the first three.
28687       for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
28688       // Normalized the normals.
28689       for (i = 0; i < 4; i++) {
28690         L = sqrt(dot(N[i], N[i]));
28691         if (L > 0.0) {
28692           for (j = 0; j < 3; j++) N[i][j] /= L;
28693         }
28694       }
28695       // N[0] is the normal of face bcd. Test the dihedral angles at edge
28696       //   cd, bd, and bc to see if they are too small or too big.
28697       for (i = 1; i < 4 && !enq; i++) {
28698         cosd = -dot(N[0], N[i]); // Edge cd, bd, bc.
28699         enq = cosd > cosmindihed;
28700       }
28701       if (!enq) {
28702         for (i = 2; i < 4 && !enq; i++) {
28703           cosd = -dot(N[1], N[i]); // Edge ad, ac
28704           enq = cosd > cosmindihed;
28705         }
28706         if (!enq) {
28707           cosd = -dot(N[2], N[3]); // Edge ab
28708           enq = cosd > cosmindihed;
28709         }
28710       }
28711     // }
28712   } else if (b->offcenter) {
28713     // abcd has bad-quality. Use off-center instead of circumcenter.
28714     switch (sidx) {
28715     case 0: // edge da.
28716       pe1 = pd; pe2 = pa; break;
28717     case 1: // edge db.
28718       pe1 = pd; pe2 = pb; break;
28719     case 2: // edge dc.
28720       pe1 = pd; pe2 = pc; break;
28721     case 3: // edge ab.
28722       pe1 = pa; pe2 = pb; break;
28723     case 4: // edge bc.
28724       pe1 = pb; pe2 = pc; break;
28725     case 5: // edge ca.
28726       pe1 = pc; pe2 = pa; break;
28727     default: 
28728       pe1 = pe2 = (point) NULL; // Avoid a compile warning.
28729     }
28730     // The shortest edge is e1->e2.
28731     for (i = 0; i < 3; i++) bicent[i] = 0.5 * (pe1[i] + pe2[i]);
28732     dist = distance(bicent, circumcent);
28733     // sdist = sqrt(smlen2) * sin(PI / 3.0); // A icoso-triangle.
28734     // The following formulae is from 
28735     sdist = b->alpha3 * (b->minratio+sqrt(b->goodratio-0.25))* sqrt(smlen2);
28736     split = sdist / dist;
28737     if (split > 1.0) split = 1.0;
28738     // Get the off-center.
28739     for (i = 0; i < 3; i++) {
28740       offcent[i] = bicent[i] + split * (circumcent[i] - bicent[i]);
28741     }
28742   }
28743 
28744   if (!enq && (b->varvolume || b->fixedvolume)) {
28745     // Check if the tet has too big volume.
28746     enq = b->fixedvolume && (volume > b->maxvolume);
28747     if (!enq && b->varvolume) {
28748       enq = (volume > volumebound(testtet->tet)) &&
28749             (volumebound(testtet->tet) > 0.0);
28750     }
28751   }
28752 
28753   if (!enq) {
28754     // Check if the user-defined sizing function is satisfied. 
28755     if (b->metric) {
28756       // assert(b->alpha1 > 0.0);
28757       sdist = sqrt(radius2) / b->alpha1;
28758       for (i = 0; i < 4; i++) {
28759         pa = (point) testtet->tet[4 + i];
28760         // Get the indicated size of p.
28761         dist = pa[pointmtrindex]; // dist = b->alpha1 * pa[pointmtrindex];
28762         enq = ((dist < sdist) && (dist > 0.0));
28763         if (enq) break; // It is bad wrt. a node constraint.
28764         // *** Experiment ! Stop test if c is inside H(a).
28765         // if ((dist > 0.0) && (dist > sdist)) break;
28766       }
28767       // *** Experiment !
28768       // enq = (i == 4); // Does c lies outside all sparse-ball?
28769     } // if (b->metric)
28770   }
28771 
28772   if (enq && enqflag) {
28773     if (b->offcenter && (ratio2 > b->goodratio)) {
28774       for (i = 0; i < 3; i++) circumcent[i] = offcent[i];
28775     }
28776     enqueuebadtet(testtet, ratio2, circumcent);
28777   }
28778 
28779   return enq;
28780 }
28781 
28783 //                                                                           //
28784 // acceptsegpt()    Check if a segment point can be inserted or not.         //
28785 //                                                                           //
28786 // Segment(ab) is indicated to be split by a point p (\in ab). This routine  //
28787 // decides whether p can be inserted or not.                                 //
28788 //                                                                           //
28789 // p can not be inserted either the '-Y' option is used and ab is a hull     //
28790 // segment or '-YY' option is used.                                          //
28791 //                                                                           //
28792 // p can be inserted if it is in one of the following cases:                 //
28793 //   (1) if L = |a - b| is too long wrt the edge constraint; or              //
28794 //   (2) if |x - p| > \alpha_2 H(x) for x = a, b; or                         //
28795 //   (3) if 'refpt' != NULL.                                                 //
28796 //                                                                           //
28798 
28799 bool tetgenmesh::acceptsegpt(point segpt, point refpt, face* splitseg)
28800 {
28801   point p[2];
28802   REAL L, lfs;
28803   int i, j;
28804 
28805   if (b->nobisect == 1) {
28806     // '-Y'. It can not be split if it is on the hull.
28807     triface spintet;
28808     point pc;
28809     sstpivot(splitseg, &spintet);
28810     assert(spintet.tet != dummytet);
28811     pc = apex(spintet);
28812     do {
28813       if (!fnextself(spintet)) {
28814         // Meet a boundary face - s is on the hull.
28815         return false;
28816       }
28817     } while (pc != apex(spintet));
28818   } else if (b->nobisect > 1) {
28819     // '-YY'. Do not split it.
28820     return false;
28821   }
28822   
28823   p[0] = sorg(*splitseg);
28824   p[1] = sdest(*splitseg);
28825   if (varconstraint && (areabound(*splitseg) > 0)) {
28826     lfs = areabound(*splitseg);
28827     L = distance(p[0], p[1]);
28828     if (L > lfs) {
28829       return true; // case (1)
28830     }
28831   }
28832 
28833   j = 0; // Use j to count the number of inside balls.
28834   for (i = 0; i < 2; i++) {
28835     // Check if p is inside the protect ball of q.
28836     if (p[i][pointmtrindex] > 0.0) {
28837       lfs = b->alpha2 * p[i][pointmtrindex];
28838       L = distance(p[i], segpt);
28839       if (L < lfs) j++; // p is inside ball.
28840     }
28841   }
28842   if (j == 0) return true; // case (3).
28843 
28844   // If 'refpt' != NULL, force p to be inserted.
28845   if (refpt != (point) NULL) {
28846     cdtenforcesegpts++;
28847     return true;
28848   }
28849 
28850   // Do not split it.
28851   rejsegpts++;
28852   return false;
28853 }
28854 
28856 //                                                                           //
28857 // acceptfacpt()    Check if a facet point can be inserted or not.           //
28858 //                                                                           //
28859 // 'subceillist' is CBC(p). 'verlist' (V) is empty on input, it returns the  //
28860 // set of vertices of CBC(p).                                                //
28861 //                                                                           //
28862 // p can not be inserted either the '-Y' option is used and the facet is on  //
28863 // the hull or '-YY' option is used.                                         //
28864 //                                                                           //
28865 // p can be inserted if |p - v| > \alpha_2 H(v), for all v \in V.            //
28866 //                                                                           //
28868 
28869 bool tetgenmesh::acceptfacpt(point facpt, list* subceillist, list* verlist)
28870 {
28871   face *testsh;
28872   point p[2], ploop;
28873   REAL L, lfs;
28874   int idx, i, j;
28875 
28876   if (b->nobisect == 1) {
28877     // '-Y'. p can not be inserted if CBC(p) is on the hull.
28878     triface testtet;
28879     testsh = (face *)(* subceillist)[0];
28880     stpivot(*testsh, testtet);
28881     if (testtet.tet != dummytet) {
28882       sesymself(*testsh);
28883       stpivot(*testsh, testtet);
28884     }
28885     if (testtet.tet == dummytet) return false;
28886   } else if (b->nobisect > 1) {
28887     // '-YY'. Do not split s.
28888     return false;
28889   }
28890 
28891   // Collect the vertices of CBC(p), save them in V.
28892   for (i = 0; i < subceillist->len(); i++) {
28893     testsh = (face *)(* subceillist)[i];
28894     p[0] = sorg(*testsh);
28895     p[1] = sdest(*testsh);
28896     for (j = 0; j < 2; j++) {
28897       idx = pointmark(p[j]);
28898       if (idx >= 0) {
28899         setpointmark(p[j], -idx - 1);
28900         verlist->append(&(p[j]));
28901       }
28902     }
28903   }
28904 
28905   j = 0; // Use j to count the number of inside balls.
28906   for (i = 0; i < verlist->len(); i++) {
28907     ploop = * (point *)(* verlist)[i];
28908     // Uninfect q.
28909     idx = pointmark(ploop);
28910     setpointmark(ploop, -(idx + 1)); 
28911     // Check if p is inside the protect ball of q.
28912     if (ploop[pointmtrindex] > 0.0) {
28913       lfs = b->alpha2 * ploop[pointmtrindex];
28914       L = distance(ploop, facpt);
28915       if (L < lfs) j++; // p is inside ball.
28916     }
28917   }
28918   verlist->clear();
28919 
28920   if (j == 0) return true; // case (3).
28921 
28922   rejsubpts++;
28923   return false;
28924 }
28925 
28927 //                                                                           //
28928 // acceptvolpt()    Check if a volume point can be inserted or not.          //
28929 //                                                                           //
28930 // 'ceillist' is B(p).  'verlist' (V) is empty on input, it returns the set  //
28931 // of vertices of B(p).                                                      //
28932 //                                                                           //
28933 // p can be split if |p - v| > \alpha_2 H(v), for all v \in V.               //
28934 //                                                                           //
28936 
28937 bool tetgenmesh::acceptvolpt(point volpt, list* ceillist, list* verlist)
28938 {
28939   triface* testtet;
28940   point p[3], ploop;
28941   REAL L, lfs;
28942   int idx, i, j;
28943 
28944   // Collect the vertices of CBC(p), save them in V.
28945   for (i = 0; i < ceillist->len(); i++) {
28946     testtet = (triface *)(* ceillist)[i];
28947     p[0] = org(*testtet);
28948     p[1] = dest(*testtet);
28949     p[2] = apex(*testtet);
28950     for (j = 0; j < 3; j++) {
28951       idx = pointmark(p[j]);
28952       if (idx >= 0) {
28953         setpointmark(p[j], -idx - 1);
28954         verlist->append(&(p[j]));
28955       }
28956     }
28957   }
28958 
28959   j = 0; // Use j to counte the number of inside balls.
28960   for (i = 0; i < verlist->len(); i++) {
28961     ploop = * (point *)(* verlist)[i];
28962     // Uninfect q.
28963     idx = pointmark(ploop);
28964     setpointmark(ploop, -(idx + 1));
28965     // Check if p is inside the protect ball of q.
28966     if (ploop[pointmtrindex] > 0.0) {
28967       lfs = b->alpha2 * ploop[pointmtrindex];
28968       L = distance(ploop, volpt);
28969       if (L < lfs) j++; // p is inside the protect ball.
28970     }
28971   }
28972   verlist->clear();
28973   
28974   if (j == 0) return true; // case (2).
28975 
28976   rejtetpts++;
28977   return false;
28978 }
28979 
28981 //                                                                           //
28982 // getsplitpoint()    Get the inserting point in a segment.                  //
28983 //                                                                           //
28985 
28986 void tetgenmesh::getsplitpoint(point e1, point e2, point refpt, point newpt)
28987 {
28988   point ei, ej;
28989   REAL split, L, d1, d2, ps, rs;
28990   bool acutea, acuteb;
28991   int i;
28992 
28993   if (refpt != (point) NULL) {
28994     // Use the CDT rules to split the segment.
28995     acutea = (pointtype(e1) == ACUTEVERTEX);
28996     acuteb = (pointtype(e2) == ACUTEVERTEX);
28997     if (acutea ^ acuteb) {
28998       // Only one endpoint is acute. Use rule-2 or rule-3.
28999       ei = acutea ? e1 : e2;
29000       ej = acutea ? e2 : e1;
29001       L = distance(ei, ej);
29002       // Apply rule-2.
29003       d1 = distance(ei, refpt);
29004       split = d1 / L;
29005       for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29006       // Check if rule-3 is needed.
29007       d2 = distance(refpt, newpt);
29008       if (d2 > (L - d1)) {
29009         // Apply rule-3.
29010         if ((d1 - d2) > (0.5 * d1)) {
29011           split = (d1 - d2) / L;
29012         } else {
29013           split = 0.5 * d1 / L;
29014         }
29015         for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29016         if (b->verbose > 1) {
29017           printf("    Found by rule-3:");
29018         }
29019         r3count++;
29020       } else {
29021         if (b->verbose > 1) {
29022           printf("    Found by rule-2:");
29023         }
29024         r2count++;
29025       }
29026       if (b->verbose > 1) {
29027         printf(" center %d, split = %.12g.\n", pointmark(ei), split);
29028       }
29029       // Add a random perturbation on newpt.
29030       d1 = distance(ei, newpt);
29031       d2 = distance(newpt, refpt);
29032       ps = randgenerator(d2 * b->epsilon2 * 1e+2);
29033       rs = ps / d1;
29034       // Perturb newpt away from ei.
29035       for (i = 0; i < 3; i++) newpt[i] = ei[i] + (1.0+rs) * (newpt[i] - ei[i]);
29036     } else {
29037       // Both endpoints are acute or not. Split it at the middle.
29038       for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29039       // Add a random perturbation on newpt.
29040       d1 = 0.5 * distance(e1, e2);
29041       ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29042       rs = ps / d1;
29043       for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29044     }
29045   } else {
29046     // Split the segment at its midpoint.
29047     for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29048     // Add a random perturbation on newpt.
29049     d1 = 0.5 * distance(e1, e2);
29050     ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29051     rs = ps / d1;
29052     for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29053   }
29054 }
29055 
29057 //                                                                           //
29058 // shepardinterpolation()    Interpolate the local size of a newpoint.       //
29059 //                                                                           //
29060 // The classical Shepard interoplation (inversed weighted distance) is used. //
29061 // (With the choice p = 2).                                                  //
29062 //                                                                           //
29063 // 'verlist' contains a list vertices neighboring to 'newpt'.                //
29064 //                                                                           //
29066 
29067 void tetgenmesh::shepardinterpolate(point newpt, list *verlist)
29068 {
29069   point neipt;
29070   REAL *weights, sumweight;
29071   REAL vec[3];
29072   int i, j;
29073 
29074   weights = new REAL[verlist->len()];
29075   sumweight = 0.0;
29076 
29077   // Calculate the weight of each point.
29078   for (i = 0; i < verlist->len(); i++) {
29079     neipt = * (point *)(* verlist)[i];
29080     for (j = 0; j < 3; j++) vec[j] = neipt[j] - newpt[j];
29081     weights[i] = 1.0 / dot(vec, vec);
29082     sumweight += weights[i];
29083   }
29084   // Interpolate.
29085   newpt[pointmtrindex] = 0.0;
29086   for (i = 0; i < verlist->len(); i++) {
29087     neipt = * (point *)(* verlist)[i];
29088     newpt[pointmtrindex] += (weights[i] * neipt[pointmtrindex]) / sumweight;
29089   }
29090 
29091   delete [] weights;
29092 }
29093 
29095 //                                                                           //
29096 // setnewpointsize()    Set the size for a new point.                        //
29097 //                                                                           //
29098 // The size of the new point p is interpolated either from a background mesh //
29099 // (b->bgmesh) or from the two input endpoints.                              //
29100 //                                                                           //
29102 
29103 void tetgenmesh::setnewpointsize(point newpt, point e1, point e2)
29104 {
29105   if (b->metric) {
29106     // Interpolate the point size in a background mesh.
29107     triface bgmtet;
29108     // Get a tet in background mesh for locating p.
29109     decode(point2bgmtet(e1), bgmtet);
29110     p1interpolatebgm(newpt, &bgmtet, NULL);
29111   } else {
29112     if (e2 != (point) NULL) {
29113       // Interpolate the size between the two endpoints.
29114       REAL split, l, d;
29115       l = distance(e1, e2);
29116       d = distance(e1, newpt);
29117       split = d / l;
29118 #ifdef SELF_CHECK
29119       // Check if e1 and e2 are endpoints of a sharp segment.
29120       assert(e1[pointmtrindex] > 0.0);
29121       assert(e2[pointmtrindex] > 0.0);
29122 #endif
29123       newpt[pointmtrindex] = (1.0 - split) * e1[pointmtrindex] 
29124                            + split * e2[pointmtrindex];
29125     }
29126   }
29127 }
29128 
29130 //                                                                           //
29131 // splitencseg()    Split an enc-seg and recover the Delaunayness by flips.  //
29132 //                                                                           //
29134 
29135 void tetgenmesh::splitencseg(point newpt, face* splitseg, list* tetlist,
29136   list* sublist, list* verlist, queue* flipque, bool chkencsub, bool chkbadtet,
29137   bool optflag)
29138 {
29139   list *mytetlist;
29140   queue *myflipque;
29141   triface starttet;
29142   face startsh, spinsh, checksh;
29143   int i;
29144   
29145   mytetlist = NULL;
29146   myflipque = NULL;
29147   
29148   if (optflag) {
29149     mytetlist = new list(sizeof(triface), NULL, 1024);
29150     myflipque = new queue(sizeof(badface));
29151     tetlist = mytetlist;
29152     flipque = myflipque;
29153   }
29154 
29155   // Use the base orientation (important in this routine).
29156   splitseg->shver = 0;
29157   // Insert p, this should always success.
29158   sstpivot(splitseg, &starttet);
29159   splittetedge(newpt, &starttet, flipque);
29160   // Remove locally non-Delaunay faces by flipping.
29161   flip(flipque, NULL); // lawson(NULL, flipque);
29162   
29163   if (!optflag) { 
29164     // Check the two new subsegs to see if they're encroached (not by p).
29165     for (i = 0; i < 2; i++) {
29166       if (!shell2badface(*splitseg)) {
29167         checkseg4encroach(splitseg, NULL, NULL, true);
29168       }
29169       if (i == 1) break; // Two new segs have been checked.
29170       senextself(*splitseg);
29171       spivotself(*splitseg);
29172 #ifdef SELF_CHECK
29173       assert(splitseg->sh != (shellface *) NULL);
29174 #endif
29175       splitseg->shver = 0;
29176     }
29177     // Check the new subfaces to see if they're encroached (not by p).
29178     if (chkencsub) {
29179       spivot(*splitseg, startsh);
29180       spinsh = startsh;
29181       do {
29182         sublist->append(&spinsh);
29183         formstarpolygon(newpt, sublist, verlist);
29184         for (i = 0; i < sublist->len(); i++) {
29185           checksh = * (face *)(* sublist)[i];
29186           if (!shell2badface(checksh)) {
29187             checksub4encroach(&checksh, NULL, true);
29188           }
29189         }
29190         sublist->clear();
29191         if (verlist) verlist->clear();
29192         spivotself(spinsh);
29193       } while (spinsh.sh != startsh.sh);
29194     }
29195   } // if (!optflag)  
29196 
29197   // Collect the new tets connecting at p.
29198   sstpivot(splitseg, &starttet);
29199   tetlist->append(&starttet);
29200   formstarpolyhedron(newpt, tetlist, verlist, true);
29201 
29202   if (!optflag) {
29203     // Check if p encroaches adjacent segments.
29204     tallencsegs(newpt, 1, &tetlist);
29205     if (chkencsub) {
29206       // Check if p encroaches adjacent subfaces.
29207       tallencsubs(newpt, 1, &tetlist);
29208     }
29209     if (chkbadtet) {
29210       // Check if there are new bad quality tets at p.
29211       for (i = 0; i < tetlist->len(); i++) {
29212         starttet = * (triface *)(* tetlist)[i];
29213         checktet4badqual(&starttet, true);
29214       }
29215     }
29216     tetlist->clear();
29217   } else {
29218     // Check if new tets are non-optimal.
29219     for (i = 0; i < tetlist->len(); i++) {
29220       starttet = * (triface *)(* tetlist)[i];
29221       checktet4opt(&starttet, true);
29222     }
29223     delete mytetlist;
29224     delete myflipque;
29225   }
29226 }
29227 
29229 //                                                                           //
29230 // tallencsegs()    Check for encroached segments and save them in list.     //
29231 //                                                                           //
29232 // If 'testpt' (p) != NULL, only check if segments are encroached by p, else,//
29233 // check all the nearby mesh vertices.                                       //
29234 //                                                                           //
29235 // If 'ceillists' (B_i(p)) != NULL, there are 'n' B_i(p)s, only check the    //
29236 // segments which are on B_i(p)s, else, check the entire list of segments    //
29237 // (in the pool 'this->subsegs').                                            //
29238 //                                                                           //
29240 
29241 bool tetgenmesh::tallencsegs(point testpt, int n, list **ceillists)
29242 {
29243   list *ceillist;
29244   triface ceiltet;
29245   face checkseg;
29246   long oldencnum;
29247   int i, j, k;
29248   
29249   // Remember the current number of encroached segments.
29250   oldencnum = badsubsegs->items;
29251 
29252   if (ceillists != (list **) NULL) {
29253     for (k = 0; k < n; k++) {
29254       ceillist = ceillists[k];
29255       // Check the segments on B_i(p).
29256       for (i = 0; i < ceillist->len(); i++) {
29257         ceiltet = * (triface *)(* ceillist)[i];
29258         ceiltet.ver = 0;
29259         for (j = 0; j < 3; j++) {
29260           tsspivot(&ceiltet, &checkseg);
29261           if (checkseg.sh != dummysh) {
29262             // Found a segment. Test it if it isn't in enc-list.
29263             if (!shell2badface(checkseg)) {
29264               checkseg4encroach(&checkseg, testpt, NULL, true);
29265             }
29266           }
29267           enextself(ceiltet);
29268         }
29269       }
29270     }
29271   } else {
29272     // Check the entire list of segments.
29273     subsegs->traversalinit();
29274     checkseg.sh = shellfacetraverse(subsegs);
29275     while (checkseg.sh != (shellface *) NULL) {
29276       // Test it if it isn't in enc-list.
29277       if (!shell2badface(checkseg)) {
29278         checkseg4encroach(&checkseg, testpt, NULL, true);
29279       }
29280       checkseg.sh = shellfacetraverse(subsegs);
29281     }
29282   }
29283 
29284   return (badsubsegs->items > oldencnum);
29285 }
29286 
29288 //                                                                           //
29289 // tallencsubs()    Find all encroached subfaces and save them in list.      //
29290 //                                                                           //
29291 // If 'testpt' (p) != NULL, only check if subfaces are encroached by p, else,//
29292 // check the adjacent vertices of subfaces.                                  //
29293 //                                                                           //
29294 // If 'ceillists' (B_i(p)) != NULL, there are 'n' B_i(p)s, only check the    //
29295 // subfaces which are on B_i(p)s, else, check the entire list of subfaces    //
29296 // (in the pool 'this->subfaces').                                           //
29297 //                                                                           //
29299 
29300 bool tetgenmesh::tallencsubs(point testpt, int n, list** ceillists)
29301 {
29302   list *ceillist;
29303   triface ceiltet;
29304   face checksh;
29305   long oldencnum;
29306   int i, k;
29307   
29308   // Remember the current number of encroached segments.
29309   oldencnum = badsubfaces->items;
29310 
29311   if (ceillists != (list **) NULL) {
29312     for (k = 0; k < n; k++) {
29313       ceillist = ceillists[k];
29314       // Check the subfaces on B_i(p).
29315       for (i = 0; i < ceillist->len(); i++) {
29316         ceiltet = * (triface *)(* ceillist)[i];
29317         tspivot(ceiltet, checksh);
29318         if (checksh.sh != dummysh) {
29319           // Found a subface. Test it if it isn't in enc-list.
29320           if (!shell2badface(checksh)) {
29321             checksub4encroach(&checksh, testpt, true);
29322           }
29323         }
29324       }
29325     }
29326   } else {
29327     // Check the entire list of subfaces.
29328     subfaces->traversalinit();
29329     checksh.sh = shellfacetraverse(subfaces);
29330     while (checksh.sh != (shellface *) NULL) {
29331       // Test it if it isn't in enc-list.
29332       if (!shell2badface(checksh)) {
29333         checksub4encroach(&checksh, testpt, true);
29334       }
29335       checksh.sh = shellfacetraverse(subfaces);
29336     }
29337   }
29338 
29339   return (badsubfaces->items > oldencnum);
29340 }
29341 
29343 //                                                                           //
29344 // tallbadtetrahedrons()    Queue all the bad-quality tetrahedra in the mesh.//
29345 //                                                                           //
29347 
29348 void tetgenmesh::tallbadtetrahedrons()
29349 {
29350   triface tetloop;
29351 
29352   tetrahedrons->traversalinit();
29353   tetloop.tet = tetrahedrontraverse();
29354   while (tetloop.tet != (tetrahedron *) NULL) {
29355     checktet4badqual(&tetloop, true);
29356     tetloop.tet = tetrahedrontraverse();
29357   }
29358 }
29359 
29361 //                                                                           //
29362 // repairencsegs()    Repair (split) all the encroached segments.            //
29363 //                                                                           //
29364 // Each encroached segment is repaired by splitting it - inserting a vertex  //
29365 // at or near its midpoint.  Newly inserted vertices may encroach upon other //
29366 // subsegments, these are also repaired.                                     //
29367 //                                                                           //
29368 // 'chkencsub' and 'chkbadtet' are two flags that specify whether one should //
29369 // take note of new encroaced subfaces and bad quality tets that result from //
29370 // inserting vertices to repair encroached subsegments.                      //
29371 //                                                                           //
29373 
29374 void tetgenmesh::repairencsegs(bool chkencsub, bool chkbadtet)
29375 {
29376   list **tetlists, **ceillists;
29377   list **sublists, **subceillists;
29378   list *tetlist, *sublist;
29379   queue *flipque;
29380   badface *encloop;
29381   face splitseg, symsplitseg;
29382   point newpt, sympt, refpt;
29383   point e1, e2;
29384   enum locateresult symloc;
29385   int nmax, n, i, j;
29386 
29387   ceillists = NULL;
29388   flipque = NULL;
29389   subceillists = NULL;
29390   sublist = NULL;
29391   sublists = NULL;
29392   tetlist = NULL;
29393   tetlists = NULL;
29394   
29395   n = 0;
29396   nmax = 128;
29397   if (!b->fliprepair) {
29398     tetlists = new list*[nmax];
29399     ceillists = new list*[nmax];
29400     sublists = new list*[nmax];
29401     subceillists = new list*[nmax];
29402   } else {
29403     tetlist = new list(sizeof(triface), NULL, 1024);
29404     sublist = new list(sizeof(face), NULL, 256);
29405     flipque = new queue(sizeof(badface));
29406   }
29407 
29408   // Loop until the pool 'badsubsegs' is empty. Note that steinerleft == -1
29409   //   if an unlimited number of Steiner points is allowed.
29410   while ((badsubsegs->items > 0) && (steinerleft != 0)) {
29411     badsubsegs->traversalinit();
29412     encloop = badfacetraverse(badsubsegs);
29413     while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
29414       // Get an encroached subsegment s.
29415       splitseg = encloop->ss;
29416       // Clear the in-queue flag in s.
29417       setshell2badface(splitseg, NULL);
29418       if ((sorg(splitseg) == encloop->forg) && 
29419           (sdest(splitseg) == encloop->fdest)) {
29420         if (b->verbose > 1) {
29421           printf("  Get an enc-seg (%d, %d)\n", pointmark(encloop->forg),
29422                  pointmark(encloop->fdest));
29423         }
29424         refpt = (point) NULL;
29425         if (b->conformdel) {
29426           // Look for a reference point.
29427           checkseg4encroach(&splitseg, NULL, &refpt, false);
29428         }
29429         // Create the new point p (at the middle of s).
29430         makepoint(&newpt);
29431         getsplitpoint(encloop->forg, encloop->fdest, refpt, newpt);
29432         setpointtype(newpt, FREESEGVERTEX);
29433         setpoint2sh(newpt, sencode(splitseg));
29434         // Decide whether p can be inserted or not.
29435         if (acceptsegpt(newpt, refpt, &splitseg)) {
29436           // Is there periodic boundary condition?
29437           if (checkpbcs) {
29438             // Insert points on other segments of incident pbcgroups.
29439             i = shellmark(splitseg) - 1;
29440             for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
29441               makepoint(&sympt);
29442               symloc = getsegpbcsympoint(newpt, &splitseg, sympt, &symsplitseg,
29443                                          segpglist[j]);
29444               if (symloc == ONEDGE) {
29445                 if (symsplitseg.sh != splitseg.sh) {
29446                   // Insert sympt.
29447                   setpointtype(sympt, FREESEGVERTEX);
29448                   setpoint2sh(sympt, sencode(symsplitseg));
29449                   // Save the endpoints of the seg for size interpolation.
29450                   e1 = sorg(symsplitseg);
29451                   if (shelltype(symsplitseg) == SHARP) {
29452                     e2 = sdest(symsplitseg);
29453                   } else {
29454                     e2 = (point) NULL; // No need to do size interpolation.
29455                   }
29456                   if (!b->fliprepair) {
29457                     // Form BC(symp), B(symp), CBC(symp)s, C(symp)s.
29458                     formbowatcavity(sympt, &symsplitseg, NULL, &n, &nmax,
29459                       sublists, subceillists, tetlists, ceillists);
29460                     // Validate BC(symp), B(symp), CBC(symp)s, C(symp)s.
29461                     if (trimbowatcavity(sympt, &symsplitseg, n, sublists,
29462                           subceillists, tetlists, ceillists, -1.0)) {
29463                       bowatinsertsite(sympt, &symsplitseg, n, sublists,
29464                         subceillists, tetlists, ceillists, NULL, flipque,
29465                         true, chkencsub, chkbadtet);
29466                       setnewpointsize(sympt, e1, e2);
29467                       if (steinerleft > 0) steinerleft--;
29468                     } else {
29469                       // p did not insert for invalid BC(symp).
29470                       pointdealloc(sympt);
29471                     }
29472                     // Free the memory allocated in formbowatcavity().
29473                     releasebowatcavity(&symsplitseg, n, sublists, subceillists,
29474                                        tetlists, ceillists);
29475                   } else {
29476                     splitencseg(sympt, &symsplitseg, tetlist, sublist, NULL,
29477                                 flipque, chkencsub, chkbadtet, false);
29478                     setnewpointsize(sympt, e1, e2);
29479                     if (steinerleft > 0) steinerleft--;
29480                   }
29481                 } else {
29482                   // The sympt are on the same segment. It is possible when
29483                   //   splitseg is the symmetric rotating axes.
29484                   pointdealloc(sympt);
29485                 }
29486               } else if (symloc == ONVERTEX) {
29487                 // The sympt already exists. It is possible when two pbc
29488                 //   groups are exactly the same. Omit this point.
29489                 pointdealloc(sympt);
29490               } else {
29491                 // Do not isnert symp for unknown cases: ONFACE, OUTSIDE.
29492                 // assert(0);
29493                 pointdealloc(sympt);
29494               }
29495             } // for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++)
29496           } // if (checkpbcs)
29497           // Save the endpoints of the seg for size interpolation.
29498           e1 = sorg(splitseg);
29499           if (shelltype(splitseg) == SHARP) {
29500             e2 = sdest(splitseg);
29501           } else {
29502             e2 = (point) NULL; // No need to do size interoplation.
29503           }
29504           if (!b->fliprepair) {
29505             // Form BC(p), B(p), CBC(p)s, and C(p)s.
29506             formbowatcavity(newpt, &splitseg, NULL, &n, &nmax, sublists,
29507                             subceillists, tetlists, ceillists);
29508             // Validate/update BC(p), B(p), CBC(p)s, and C(p)s.
29509             if (trimbowatcavity(newpt, &splitseg, n, sublists, subceillists, 
29510                                 tetlists, ceillists, -1.0)) {
29511               bowatinsertsite(newpt, &splitseg, n, sublists, subceillists,
29512                               tetlists, ceillists, NULL, flipque, true,
29513                               chkencsub, chkbadtet);
29514               setnewpointsize(newpt, e1, e2);
29515               if (steinerleft > 0) steinerleft--;
29516             } else {
29517               // p did not insert for invalid B(p).
29518               pointdealloc(newpt);
29519             }
29520             // Free the memory allocated in formbowatcavity().
29521             releasebowatcavity(&splitseg, n, sublists, subceillists, tetlists,
29522                                ceillists);
29523           } else {
29524             splitencseg(newpt, &splitseg, tetlist, sublist, NULL, flipque,
29525                         chkencsub, chkbadtet, false);
29526             setnewpointsize(newpt, e1, e2);
29527             if (steinerleft > 0) steinerleft--;
29528           }
29529         } else {
29530           // p did not accept for insertion.
29531           pointdealloc(newpt);
29532         } // if (checkseg4splitting(newpt, &splitseg))
29533       } // if ((encloop->forg == pa) && (encloop->fdest == pb))
29534       badfacedealloc(badsubsegs, encloop); // Remove this entry from list.
29535       encloop = badfacetraverse(badsubsegs); // Get the next enc-segment.
29536     } // while ((encloop != (badface *) NULL) && (steinerleft != 0))
29537   } // while ((badsubsegs->items > 0) && (steinerleft != 0))
29538 
29539   if (!b->fliprepair) {
29540     delete [] tetlists;
29541     delete [] ceillists;
29542     delete [] sublists;
29543     delete [] subceillists;
29544   } else {
29545     delete tetlist;
29546     delete sublist;
29547     delete flipque;
29548   }
29549 }
29550 
29552 //                                                                           //
29553 // repairencsubs()    Repair (split) all the encroached subfaces.            //
29554 //                                                                           //
29555 // Each encroached subface is repaired by splitting it - inserting a vertex  //
29556 // at or near its circumcenter.  Newly inserted vertices may encroach upon   //
29557 // other subfaces, these are also repaired.                                  //
29558 //                                                                           //
29559 // 'chkbadtet' is a flag that specifies whether one should take note of new  //
29560 // bad quality tets that result from inserted vertices.                      //
29561 //                                                                           //
29563 
29564 void tetgenmesh::repairencsubs(bool chkbadtet)
29565 {
29566   list *tetlists[2], *ceillists[2];
29567   list *sublist, *subceillist;
29568   list *verlist;
29569   badface *encloop;
29570   face splitsub, symsplitsub;
29571   point newpt, sympt, e1;
29572   enum locateresult loc, symloc;
29573   bool reject;
29574   long oldptnum;
29575   int quenumber, n, i;
29576 
29577   quenumber = 0;
29578   n = 0;
29579   sublist = (list *) NULL;
29580   subceillist = (list *) NULL;
29581   verlist = new list(sizeof(point *), NULL, 256);
29582 
29583   // Loop until the pool 'badsubfaces' is empty. Note that steinerleft == -1
29584   //   if an unlimited number of Steiner points is allowed.
29585   while ((badsubfaces->items > 0) && (steinerleft != 0)) {
29586     // Get an encroached subface f.
29587     encloop = dequeueencsub(&quenumber);
29588     splitsub = encloop->ss;
29589     // Clear the in-queue flag of f.
29590     setshell2badface(splitsub, NULL);
29591     // f may not be the same one when it was determined to be encroached.
29592     if (!isdead(&splitsub)
29593         && (sorg(splitsub) == encloop->forg)
29594         && (sdest(splitsub) == encloop->fdest)
29595         && (sapex(splitsub) == encloop->fapex)) {
29596       if (b->verbose > 1) {
29597         printf("    Dequeuing ensub (%d, %d, %d) [%d].\n",
29598                pointmark(encloop->forg), pointmark(encloop->fdest),
29599                pointmark(encloop->fapex), quenumber);
29600       }
29601       // Create a new point p at the circumcenter of f.
29602       makepoint(&newpt);
29603       for (i = 0; i < 3; i++) newpt[i] = encloop->cent[i];
29604       setpointtype(newpt, FREESUBVERTEX);
29605       setpoint2sh(newpt, sencode(splitsub));
29606       // Set the abovepoint of f for point location.
29607       abovepoint = facetabovepointarray[shellmark(splitsub)];
29608       if (abovepoint == (point) NULL) {
29609         getfacetabovepoint(&splitsub);
29610       }
29611       // Locate p, start from f, stop at segment (1), use a tolerance to
29612       //   detect ONVERTEX or OUTSIDE case. Update f on return.
29613       loc = locatesub(newpt, &splitsub, 1, b->epsilon * 1e+2);
29614       if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29615         // Form BC(p), B(p), CBC(p) and C(p).
29616         formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29617                         &subceillist, tetlists, ceillists);
29618         // Check for encroached subsegments (on B(p)).
29619         reject = tallencsegs(newpt, 2, ceillists);
29620         // Execute point accept rule if p does not encroach upon any segment.
29621         if (!reject) {
29622           reject = !acceptfacpt(newpt, subceillist, verlist);
29623         }
29624         if (!reject) {
29625           // Validate/update cavity.
29626           reject = !trimbowatcavity(newpt, NULL, n, &sublist, &subceillist,
29627                                     tetlists, ceillists, -1.0);
29628         }
29629         if (!reject) {
29630           // CBC(p) should include s, so that s can be removed after CBC(p)
29631           //   is remeshed. However, if there are locally non-Delaunay faces
29632           //   and encroached subsegments, s may not be collected in CBC(p).
29633           //   p should not be inserted in such case.
29634           reject = !sinfected(encloop->ss);
29635         }
29636         if (!reject) {
29637           if (checkpbcs) {
29638             if (shellpbcgroup(splitsub) >= 0) {
29639               // Check for splitting of the symmetric subface of f.
29640               makepoint(&sympt);
29641               symloc = getsubpbcsympoint(newpt,&splitsub,sympt,&symsplitsub);
29642               if (symloc != ONVERTEX) {
29643                 // Release CBC(p) and BC(p) and free the memory..
29644                 releasebowatcavity(NULL, 2, &sublist, &subceillist, tetlists,
29645                                    ceillists);
29646                 // Form CBC(symp), C(symp), BC(sympt) and B(sympt).
29647                 formbowatcavity(sympt, NULL, &symsplitsub, &n, NULL, &sublist,
29648                                 &subceillist, tetlists, ceillists);
29649                 reject = tallencsegs(sympt, 2, ceillists);
29650                 if (!reject) {
29651                   reject = !acceptfacpt(sympt, subceillist, verlist);
29652                 }
29653                 if (!reject) {
29654                   reject = !trimbowatcavity(sympt,NULL,n,&sublist,&subceillist,
29655                                             tetlists, ceillists, -1.0);
29656                 }
29657                 if (!reject) {
29658                   // Insert sympt.
29659                   setpoint2pbcpt(newpt, sympt);
29660                   setpoint2pbcpt(sympt, newpt);
29661                   setpointtype(sympt, FREESUBVERTEX);
29662                   setpoint2sh(sympt, sencode(symsplitsub));
29663                   // Save a point for size interpolation.
29664                   e1 = sorg(symsplitsub);
29665                   bowatinsertsite(sympt, NULL, n, &sublist, &subceillist,
29666                      tetlists,ceillists,NULL,NULL,false,true,chkbadtet);
29667                   setnewpointsize(sympt, e1, NULL);
29668                   if (steinerleft > 0) steinerleft--;
29669                   // Release CBC(symp) and BC(symp) and free the memory..
29670                   releasebowatcavity(NULL, n, &sublist, &subceillist, tetlists,
29671                                      ceillists);
29672                 } else {
29673                   // symp is rejected for one of the following reasons:
29674                   //   (1) BC(symp) is not valid; or
29675                   //   (2) symp encroaches upon some subsegments (queued); or
29676                   //   (3) symp is rejected by point accepting rule.
29677                   pointdealloc(sympt);
29678                   // Cavity will be released by the following code.
29679                 }
29680               } else {
29681                 // Do not insert sympt for invalid PBC data.
29682                 pointdealloc(sympt);
29683                 // p is rejected due to symp.
29684                 reject = true;
29685               }
29686             }
29687           } // if (checkpbcs)
29688         }
29689         if (!reject) {
29690           // Insert p.
29691           if (checkpbcs) {
29692             if (shellpbcgroup(splitsub) >= 0) {
29693               // Form CBC(p), C(p), BC(p) and B(p).
29694               formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29695                               &subceillist, tetlists, ceillists);
29696               trimbowatcavity(newpt, NULL, n, &sublist, &subceillist, tetlists,
29697                               ceillists, -1.0);
29698             }
29699           }
29700           // Save a point for size interpolation.
29701           e1 = sorg(splitsub);
29702           bowatinsertsite(newpt, NULL, n, &sublist, &subceillist, tetlists,
29703                           ceillists, NULL, NULL, true, true, chkbadtet);
29704           setnewpointsize(newpt, e1, NULL);
29705           if (steinerleft > 0) steinerleft--;
29706         } else {
29707           // p is rejected for the one of the following reasons:
29708           //   (1) BC(p) is not valid.
29709           //   (2) s does not in CBC(p).
29710           //   (3) p encroaches upon some segments (queued); or
29711           //   (4) p is rejected by point accepting rule, or
29712           //   (5) due to the rejection of symp (the PBC).
29713           pointdealloc(newpt);
29714         } // if (!reject)
29715         // Release the cavity and free the memory.
29716         releasebowatcavity(NULL,n,&sublist,&subceillist,tetlists,ceillists);
29717         if (reject) {
29718           // Are there queued encroached subsegments.
29719           if (badsubsegs->items > 0) {
29720             // Repair enc-subsegments.
29721             oldptnum = points->items;
29722             repairencsegs(true, chkbadtet);
29723             if (points->items > oldptnum) {
29724               // Some enc-subsegments got split. Try to repair f later.
29725               splitsub = encloop->ss;
29726               if (!isdead(&splitsub)) {
29727                 if (!shell2badface(splitsub)) {
29728                   checksub4encroach(&splitsub, NULL, true);
29729                 }
29730               }
29731             }
29732           }
29733         }
29734       } else {
29735         // Don't insert p for one of the following reasons:
29736         //   (1) Locate on an existing vertex; or
29737         //   (2) locate outside the domain.
29738         // Case (1) should not be possible. If such vertex v exists, it is
29739         //   the circumcenter of f, ie., f is non-Delaunay. Either f was got
29740         //   split before by v, but survived after v was inserted, or the
29741         //   same for a f' which is nearly co-circular with f.  Whatsoever,
29742         //   there are encroached segs by v, but the routine tallencsegs()
29743         //   did not find them out.
29744         if (loc == ONVERTEX) {
29745           printf("Internal error in repairencsubs():\n");
29746           printf("  During repairing encroached subface (%d, %d, %d)\n",
29747                  pointmark(encloop->forg), pointmark(encloop->fdest),
29748                  pointmark(encloop->fapex));
29749           printf("  New point %d is coincident with an existing vertex %d\n",
29750                  pointmark(newpt), pointmark(sorg(splitsub)));
29751           internalerror();
29752         }
29753         // Case (2) can happen when thers is a segment s which is close to f
29754         //   and is non-conforming Delaunay. The circumcenter of f encroaches
29755         //   upon s, but the circumcenter of s is rejected for insertion.
29756         pointdealloc(newpt);
29757       } // if ((loc != ONVERTEX) && (loc != OUTSIDE))
29758     } else {
29759       if (!isdead(&splitsub)) {
29760         // The subface has been changed, re-check it.
29761         checksub4encroach(&splitsub, NULL, true);
29762       }
29763     } // if (!isdead(&splitsub) && (sorg(splitsub) == encloop->forg) &&
29764     // Remove this entry from list.
29765     badfacedealloc(badsubfaces, encloop);
29766   } // while ((badsubfaces->items > 0) && (steinerleft != 0))
29767 
29768   delete verlist;
29769 }
29770 
29772 //                                                                           //
29773 // repairbadtets()    Repair all bad-quality tetrahedra.                     //
29774 //                                                                           //
29775 // All bad-quality tets are stored in pool 'badtetrahedrons'.  Each bad tet  //
29776 // is repaired by inserting a point at or near its circumcenter. However, if //
29777 // this point encroaches any subsegment or subface, it is not inserted. Ins- //
29778 // tead the encroached segment and subface are split.  Newly inserted points //
29779 // may create other bad-quality tets, these are also repaired.               //
29780 //                                                                           //
29782 
29783 void tetgenmesh::repairbadtets()
29784 {
29785   list *tetlist, *ceillist;
29786   list *verlist;
29787   badface *badtet;
29788   triface starttet;
29789   point newpt, e1;
29790   enum locateresult loc;
29791   bool reject;
29792   long oldptnum;
29793   int i;
29794 
29795   tetlist = new list(sizeof(triface), NULL, 1024);
29796   ceillist = new list(sizeof(triface), NULL, 1024);
29797   verlist = new list(sizeof(point *), NULL, 256);
29798 
29799   // Loop until pool 'badtetrahedrons' is empty. Note that steinerleft == -1
29800   //   if an unlimited number of Steiner points is allowed.
29801   while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
29802     // Get a bad-quality tet t.
29803     badtet = topbadtetra();
29804     // Make sure that the tet is still the same one when it was tested.
29805     //   Subsequent transformations may have made it a different tet.
29806     if ((badtet != (badface *) NULL) && !isdead(&badtet->tt)
29807          && org(badtet->tt) == badtet->forg
29808          && dest(badtet->tt) == badtet->fdest
29809          && apex(badtet->tt) == badtet->fapex
29810          && oppo(badtet->tt) == badtet->foppo) {
29811       if (b->verbose > 1) {
29812         printf("    Dequeuing btet (%d, %d, %d, %d).\n",
29813                pointmark(badtet->forg), pointmark(badtet->fdest),
29814                pointmark(badtet->fapex), pointmark(badtet->foppo));
29815       }
29816       // Create the new point p (at the circumcenter of t).
29817       makepoint(&newpt);
29818       for (i = 0; i < 3; i++) newpt[i] = badtet->cent[i];
29819       setpointtype(newpt, FREEVOLVERTEX);
29820       // Locate p.
29821       starttet = badtet->tt;
29822       loc = preciselocate(newpt, &starttet, tetrahedrons->items);
29823       if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29824         // For BC(p) and B(p).
29825         infect(starttet);
29826         tetlist->append(&starttet);
29827         formbowatcavityquad(newpt, tetlist, ceillist);
29828         // Check for encroached subsegments.
29829         reject = tallencsegs(newpt, 1, &ceillist);
29830         if (!reject) {
29831           // Check for encroached subfaces.
29832           reject = tallencsubs(newpt, 1, &ceillist);
29833         }
29834         // Execute point accepting rule if p does not encroach upon any
29835         //   subsegment and subface.
29836         if (!reject) {
29837           reject = !acceptvolpt(newpt, ceillist, verlist);
29838         }
29839         if (!reject) {
29840           reject = !trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist,
29841                                     &ceillist, -1.0);
29842         }
29843         if (!reject) {
29844           // BC(p) should include t, so that t can be removed after BC(p) is
29845           //   remeshed. However, if there are locally non-Delaunay faces
29846           //   and encroached subsegments/subfaces, t may not be collected
29847           //   in BC(p). p should not be inserted in such case.
29848           reject = !infected(badtet->tt);
29849           if (reject) outbowatcircumcount++;
29850         }
29851         if (!reject) {
29852           // Save a point for size interpolation.
29853           e1 = org(starttet);
29854           // Insert p.
29855           bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist,
29856                           NULL, NULL, false, false, true);
29857           setnewpointsize(newpt, e1, NULL);
29858           if (steinerleft > 0) steinerleft--;
29859         } else {
29860           // p is rejected for one of the following reasons:
29861           //   (1) BC(p) is not valid.
29862           //   (2) t does not in BC(p).
29863           //   (3) p encroaches upon some segments;
29864           //   (4) p encroaches upon some subfaces;
29865           //   (5) p is rejected by the point accepting rule.
29866           pointdealloc(newpt);
29867           // Uninfect tets of BC(p).
29868           for (i = 0; i < tetlist->len(); i++) {
29869             starttet = * (triface *)(* tetlist)[i];
29870             uninfect(starttet);
29871           }
29872         }
29873         tetlist->clear();
29874         ceillist->clear();
29875         // Split encroached subsegments/subfaces if there are.
29876         if (reject) {
29877           oldptnum = points->items;
29878           if (badsubsegs->items > 0) {
29879             repairencsegs(true, true);
29880           }
29881           if (badsubfaces->items > 0) {
29882             repairencsubs(true);
29883           }
29884           if (points->items > oldptnum) {
29885             // Some encroaching subsegments/subfaces got split. Re-queue the
29886             //   tet if it is still alive.
29887             starttet = badtet->tt;
29888             if (!isdead(&starttet)) {
29889               checktet4badqual(&starttet, true);
29890             }
29891           }
29892         }
29893       } else {
29894         // Do not insert p. The reason may be one of:
29895         //   (1) p is coincident (ONVERTEX) with an existing vertex; or
29896         //   (2) p is outside (OUTSIDE) the mesh.
29897         // Case (1) should not be possible. If such vertex v exists, it is
29898         //   the circumcenter of t, ie., t is non-Delaunay. Either t was got
29899         //   split before by v, but survived after v was inserted, or the
29900         //   same for a t' which is nearly co-spherical with t.  Whatsoever,
29901         //   there are encroached segments or subfaces by v but the routines
29902         //   tallencsegs() or tallencsubs() did not find them out.
29903         if (loc == ONVERTEX) {
29904           printf("Internal error in repairbadtets():\n");
29905           printf("  During repairing bad tet (%d, %d, %d, %d)\n",
29906                  pointmark(badtet->forg), pointmark(badtet->fdest),
29907                  pointmark(badtet->fapex), pointmark(badtet->foppo));
29908           printf("  New point %d is coincident with an existing vertex %d\n",
29909                  pointmark(newpt), pointmark(org(starttet)));
29910           internalerror();
29911         }
29912         // Case (2) can happen when there is a segment s (or subface f) which
29913         //   is close to f and is non-conforming Delaunay.  The circumcenter
29914         //   of t encroaches upon s (or f), but the circumcenter of s (or f)
29915         //   is rejected for insertion.
29916         pointdealloc(newpt);
29917       } // if ((loc != ONVERTEX) && (loc != OUTSIDE))
29918     } // if (!isdead(&badtet->tt) && org(badtet->tt) == badtet->forg &&
29919     // Remove the tet from the queue.
29920     dequeuebadtet();
29921   } // while ((badtetrahedrons->items > 0) && (steinerleft != 0))
29922 
29923   delete tetlist;
29924   delete ceillist;
29925   delete verlist;
29926 }
29927 
29929 //                                                                           //
29930 // enforcequality()    Refine the mesh.                                      //
29931 //                                                                           //
29933 
29934 void tetgenmesh::enforcequality()
29935 {
29936   long total, vertcount;
29937   int i;
29938   
29939   if (!b->quiet) {
29940     printf("Adding Steiner points to enforce quality.\n");
29941   } 
29942 
29943   total = vertcount = 0l;
29944   if (b->conformdel) {
29945     r2count = r3count = 0l;
29946   }
29947 
29948   // If both '-D' and '-r' options are used. 
29949   if (b->conformdel && b->refine) {
29950     markacutevertices(65.0);
29951   }
29952   // If '-m' is not used.
29953   if (!b->metric) {
29954     // Find and mark all sharp segments.
29955     marksharpsegments(65.0);
29956     // Decide the sizes for feature points.
29957     decidefeaturepointsizes();
29958   }
29959 
29960   // Initialize the pool of encroached subsegments.
29961   badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29962   // Looking for encroached subsegments.
29963   tallencsegs(NULL, 0, NULL);
29964   if (b->verbose && badsubsegs->items > 0) {
29965     printf("  Splitting encroached subsegments.\n");
29966   }
29967   vertcount = points->items;
29968   // Fix encroached segments without noting any enc subfaces.
29969   repairencsegs(false, false);
29970   if (b->verbose > 0) {
29971     printf("  %ld split points.\n", points->items - vertcount);
29972   }
29973   total += points->items - vertcount;
29974 
29975   // Initialize the pool of encroached subfaces.
29976   badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29977   // Initialize the priority queues of badfaces.
29978   for (i = 0; i < 3; i++) subquefront[i] = (badface *) NULL;
29979   for (i = 0; i < 3; i++) subquetail[i] = &subquefront[i];
29980   // Looking for encroached subfaces.
29981   tallencsubs(NULL, 0, NULL);
29982   if (b->verbose && badsubfaces->items > 0) {
29983     printf("  Splitting encroached subfaces.\n");
29984   }
29985   vertcount = points->items;
29986   // Fix encroached subfaces without noting bad tetrahedra.
29987   repairencsubs(false);
29988   if (b->verbose > 0) {
29989     printf("  %ld split points.\n", points->items - vertcount);
29990   }
29991   total += points->items - vertcount;
29992   // At this point, the mesh should be conforming Delaunay if no input
29993   //   angle is smaller than 90 degree.
29994 
29995   // Next, fix bad quality tetrahedra.
29996   if ((b->minratio > 0.0) || b->varvolume || b->fixedvolume) {
29997     // Initialize the pool of bad tets
29998     badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
29999     // Initialize the priority queues of bad tets.
30000     for (i = 0; i < 64; i++) tetquefront[i] = (badface *) NULL;
30001     firstnonemptyq = -1;
30002     recentq = -1;
30003     // Looking for bad quality tets.
30004     cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30005     cosmindihed = cos(b->mindihedral * PI / 180.0);
30006     tallbadtetrahedrons();
30007     if (b->verbose && badtetrahedrons->items > 0) {
30008       printf("  Splitting bad tetrahedra.\n");
30009     }
30010     vertcount = points->items;
30011     repairbadtets();
30012     if (b->verbose > 0) {
30013       printf("  %ld refinement points.\n", points->items - vertcount);
30014     }
30015     total += points->items - vertcount;
30016     delete badtetrahedrons;
30017   }
30018 
30019   if (b->verbose > 0) {
30020     printf("  Totally added %ld points.\n", total);
30021   }
30022 
30023   delete badsubfaces;
30024   delete badsubsegs;
30025 }
30026 
30027 //
30028 // End of Delaunay refinement routines
30029 //
30030 
30031 //
30032 // Begin of mesh optimization routines
30033 //
30034 
30035 void tetgenmesh::dumpbadtets()
30036 {
30037   FILE *fout;
30038   badface *remtet;
30039 
30040   // Write out a file of remaining bad tets.
30041   printf("  Writing bad tets to file bad-dump.lua.\n");
30042   fout = fopen("bad-dump.lua", "w");
30043   fprintf(fout, "-- %ld remaining bad tets (> %g degree).\n",
30044           badtetrahedrons->items, b->maxdihedral);
30045   badtetrahedrons->traversalinit();
30046   remtet = badfacetraverse(badtetrahedrons);
30047   while (remtet != (badface *) NULL) {
30048     if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30049         dest(remtet->tt) == remtet->fdest && 
30050         apex(remtet->tt) == remtet->fapex &&
30051         oppo(remtet->tt) == remtet->foppo) {
30052       fprintf(fout, "p:draw_tet(%d, %d, %d, %d) -- %g\n",
30053               pointmark(remtet->forg), pointmark(remtet->fdest),
30054               pointmark(remtet->fapex), pointmark(remtet->foppo),
30055               acos(remtet->key) * 180.0 / PI);
30056     }
30057     remtet = badfacetraverse(badtetrahedrons);
30058   }
30059   fclose(fout);
30060 }
30061 
30063 //                                                                           //
30064 // checktet4ill()    Check a tet to see if it is illegal.                    //
30065 //                                                                           //
30066 // A tet is "illegal" if it spans on one input facet.  Save the tet in queue //
30067 // if it is illegal and the flag 'enqflag' is set.                           //
30068 //                                                                           //
30069 // Note: Such case can happen when the input facet has non-coplanar vertices //
30070 // and the Delaunay tetrahedralization of the vertices may creat such tets.  //
30071 //                                                                           //
30073 
30074 bool tetgenmesh::checktet4ill(triface* testtet, bool enqflag)
30075 {
30076   badface *newbadtet;
30077   triface checktet;
30078   face checksh1, checksh2;
30079   face checkseg;
30080   bool illflag;
30081   int i;
30082 
30083   illflag = false;
30084   for (testtet->loc = 0; testtet->loc < 4; testtet->loc++) {
30085     tspivot(*testtet, checksh1);
30086     if (checksh1.sh != dummysh) {
30087       testtet->ver = 0;
30088       findedge(&checksh1, org(*testtet), dest(*testtet));
30089       for (i = 0; i < 3; i++) {
30090         fnext(*testtet, checktet);
30091         tspivot(checktet, checksh2);
30092         if (checksh2.sh != dummysh) {
30093           // Two subfaces share this edge.
30094           sspivot(checksh1, checkseg);
30095           if (checkseg.sh == dummysh) {
30096             // The four corners of the tet are on one facet. Illegal! Try to
30097             //   flip the opposite edge of the current one.
30098             enextfnextself(*testtet);
30099             enextself(*testtet);
30100             illflag = true; 
30101             break;
30102           }
30103         }
30104         enextself(*testtet);
30105         senextself(checksh1);
30106       }
30107     }
30108     if (illflag) break;
30109   }
30110 
30111   if (illflag && enqflag) {
30112     // Allocate space for the bad tetrahedron.
30113     newbadtet = (badface *) badtetrahedrons->alloc();
30114     newbadtet->tt = *testtet;
30115     newbadtet->key = -1.0; // = 180 degree.
30116     for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
30117     newbadtet->forg = org(*testtet);
30118     newbadtet->fdest = dest(*testtet);
30119     newbadtet->fapex = apex(*testtet);
30120     newbadtet->foppo = oppo(*testtet);
30121     newbadtet->nextitem = (badface *) NULL;
30122     if (b->verbose > 2) {
30123       printf("    Queueing illtet: (%d, %d, %d, %d).\n",
30124              pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30125              pointmark(newbadtet->fapex), pointmark(newbadtet->foppo));
30126     }
30127   }
30128 
30129   return illflag;
30130 }
30131 
30133 //                                                                           //
30134 // checktet4opt()    Check a tet to see if it needs to be optimized.         //
30135 //                                                                           //
30136 // A tet t needs to be optimized if it fails to certain quality measures.    //
30137 // The only quality measure currently used is the maximal dihedral angle at  //
30138 // edges. The desired maximal dihedral angle is b->maxdihed (set by the '-s' //
30139 // option.                                                                   //
30140 //                                                                           //
30141 // A tet may have one, two, or three big dihedral angles. Examples: Let the  //
30142 // tet t = abcd, and its four corners are nearly co-planar. Then t has one   //
30143 // big dihedral angle if d is very close to the edge ab; t has three big     //
30144 // dihedral angles if d's projection on the face abc is also inside abc, i.e.//
30145 // the shape of t likes a hat; finally, t has two big dihedral angles if d's //
30146 // projection onto abc is outside abc.                                       //
30147 //                                                                           //
30149 
30150 bool tetgenmesh::checktet4opt(triface* testtet, bool enqflag)
30151 {
30152   badface *newbadtet;
30153   point pa, pb, pc, pd;
30154   REAL N[4][3], len;
30155   REAL cosd;
30156   bool enq;
30157   int i, j;
30158   
30159   cosd = 0.0;
30160   enq = false;
30161   pa = (point) testtet->tet[4];
30162   pb = (point) testtet->tet[5];
30163   pc = (point) testtet->tet[6];
30164   pd = (point) testtet->tet[7];
30165   // Compute the 4 face normals: N[0] cbd, N[1] acd, N[2] bad, N[3] abc.
30166   tetallnormal(pa, pb, pc, pd, N, NULL);
30167   // Normalize the normals.
30168   for (i = 0; i < 4; i++) {
30169     len = sqrt(dot(N[i], N[i]));
30170     if (len != 0.0) {
30171       for (j = 0; j < 3; j++) N[i][j] /= len;
30172     }
30173   }
30174   // Find all large dihedral angles.
30175   for (i = 0; i < 6; i++) {
30176     // Locate the edge i and calculate the dihedral angle at the edge.
30177     testtet->loc = 0;
30178     testtet->ver = 0;
30179     switch (i) {
30180     case 0: // edge ab
30181       cosd = -dot(N[2], N[3]);
30182       break;
30183     case 1: // edge cd 
30184       enextfnextself(*testtet);
30185       enextself(*testtet);
30186       cosd = -dot(N[0], N[1]);
30187       break;
30188     case 2: // edge bd
30189       enextfnextself(*testtet);
30190       enext2self(*testtet);
30191       cosd = -dot(N[0], N[2]);
30192       break;
30193     case 3: // edge bc
30194       enextself(*testtet);
30195       cosd = -dot(N[0], N[3]);
30196       break;
30197     case 4: // edge ad
30198       enext2fnextself(*testtet);
30199       enextself(*testtet);
30200       cosd = -dot(N[1], N[2]);
30201       break;
30202     case 5: // edge ac
30203       enext2self(*testtet);
30204       cosd = -dot(N[1], N[3]);
30205       break;
30206     }
30207     if (cosd < cosmaxdihed) {
30208       // A bigger dihedral angle.
30209       if (enqflag) {
30210         // Allocate space for the bad tetrahedron.
30211         newbadtet = (badface *) badtetrahedrons->alloc();
30212         newbadtet->tt = *testtet;
30213         newbadtet->key = cosd;
30214         for (j = 0; j < 3; j++) newbadtet->cent[j] = 0.0;
30215         newbadtet->forg = org(*testtet);
30216         newbadtet->fdest = dest(*testtet);
30217         newbadtet->fapex = apex(*testtet);
30218         newbadtet->foppo = oppo(*testtet);
30219         newbadtet->nextitem = (badface *) NULL;
30220         if (b->verbose > 2) {
30221           printf("    Queueing tet: (%d, %d, %d, %d), dihed %g (degree).\n",
30222                  pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30223                  pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
30224                  acos(cosd) * 180.0 / PI);
30225         }
30226       }
30227       enq = true;
30228     }
30229   }
30230 
30231   return enq;
30232 }
30233 
30235 //                                                                           //
30236 // removeedge()    Remove an edge                                            //
30237 //                                                                           //
30238 // 'remedge' is a tet (abcd) having the edge ab wanted to be removed.  Local //
30239 // reconnecting operations are used to remove edge ab.  The following opera- //
30240 // tion will be tryed.                                                       //
30241 //                                                                           //
30242 // If ab is on the hull, and abc and abd are both hull faces. Then ab can be //
30243 // removed by stripping abcd from the mesh. However, if ab is a segemnt, do  //
30244 // the operation only if 'b->optlevel' > 1 and 'b->nobisect == 0'.           //
30245 //                                                                           //
30246 // If ab is an internal edge, there are n tets contains it.  Then ab can be  //
30247 // removed if there exists another m tets which can replace the n tets with- //
30248 // out changing the boundary of the n tets.                                  //
30249 //                                                                           //
30250 // If 'optflag' is set.  The value 'remedge->key' means cos(theta), where    //
30251 // 'theta' is the maximal dishedral angle at ab. In this case, even if the   //
30252 // n-to-m flip exists, it will not be performed if the maximum dihedral of   //
30253 // the new tets is larger than 'theta'.                                      //
30254 //                                                                           //
30256 
30257 bool tetgenmesh::removeedge(badface* remedge, bool optflag)
30258 {
30259   triface abcd, badc;  // Tet configuration at edge ab.
30260   triface baccasing, abdcasing;
30261   triface abtetlist[11];  // Old configuration at ab, save maximum 10 tets.
30262   triface bftetlist[11];  // Old configuration at bf, save maximum 10 tets.
30263   triface newtetlist[33]; // New configuration after removing ab.
30264   face checksh;
30265   enum fliptype fty;
30266   REAL key;
30267   bool remflag, subflag;
30268   int n, n1, m, i, j;
30269 
30270   // First try to strip abcd from the mesh. This needs to check either ab
30271   //   or cd is on the hull. Try to strip it whichever is true.
30272   abcd = remedge->tt;
30273   adjustedgering(abcd, CCW);
30274   i = 0;
30275   do {
30276     sym(abcd, baccasing);
30277     // Is the tet on the hull?
30278     if (baccasing.tet == dummytet) {
30279       fnext(abcd, badc);
30280       sym(badc, abdcasing);
30281       if (abdcasing.tet == dummytet) {
30282         // Strip the tet from the mesh -> ab is removed as well.
30283         if (removetetbypeeloff(&abcd)) {
30284           if (b->verbose > 1) {
30285             printf("    Stripped tet from the mesh.\n");
30286           }
30287           optcount[0]++;
30288           return true;
30289         }
30290       }
30291     }
30292     // Check if the oppsite edge cd is on the hull.
30293     enext2fnextself(abcd);
30294     enext2self(abcd);
30295     esymself(abcd); // --> cdab
30296     i++;
30297   } while (i < 2);
30298   
30299   // Get the tets configuration at ab. Collect maximum 10 tets.
30300   subflag = false;
30301   abcd = remedge->tt;
30302   adjustedgering(abcd, CW);
30303   n = 0;
30304   abtetlist[n] = abcd;
30305   do {
30306     // Is the list full?
30307     if (n == 10) break;
30308     // Stop if a subface appears.
30309     tspivot(abtetlist[n], checksh);
30310     if (checksh.sh != dummysh) {
30311       // ab is either a segment or a facet edge. The latter case is not
30312       //   handled yet! An edge flip is needed.
30313       subflag = true; break; // return false;
30314     }
30315     // Get the next tet at ab.
30316     fnext(abtetlist[n], abtetlist[n + 1]);
30317     n++;
30318   } while (apex(abtetlist[n]) != apex(abcd));
30319 
30320   remflag = false;
30321   key = remedge->key;
30322 
30323   if (subflag && optflag) {
30324     abcd = remedge->tt;
30325     adjustedgering(abcd, CCW);
30326     // Try to flip face cda or cdb to improve quality.
30327     for (j = 0; j < 2; j++) {
30328       if (j == 0) {
30329         enext2fnext(abcd, abtetlist[0]); // Goto cda.
30330       } else {
30331         enextfnext(abcd, abtetlist[0]); // Goto cdb.
30332       }
30333       fty = categorizeface(abtetlist[0]);
30334       if (fty == T23) {
30335         // A 2-to-3 flip is possible.
30336         sym(abtetlist[0], abtetlist[1]);
30337         assert(abtetlist[1].tet != dummytet);
30338         n = 2; 
30339         m = 3;
30340         remflag = removefacebyflip23(&key, abtetlist, newtetlist, NULL);
30341       } else if (fty == T22) {
30342         // A 2-to-2 or 4-to-4 flip is possible.
30343         n = 2;
30344         newtetlist[0] = abtetlist[0];
30345         adjustedgering(newtetlist[0], CW);
30346         fnext(newtetlist[0], newtetlist[1]);
30347         assert(newtetlist[1].tet != dummytet);
30348         // May it is 4-to-4 flip.
30349         if (fnext(newtetlist[1], newtetlist[2])) {
30350           fnext(newtetlist[2], newtetlist[3]);
30351           assert(newtetlist[3].tet != dummytet);
30352           n = 4;
30353         }
30354         m = n;
30355         remflag = removeedgebyflip22(&key, n, newtetlist, NULL);
30356       }
30357       // Has quality been improved?
30358       if (remflag) {
30359         if (b->verbose > 1) {
30360           printf("  Done flip %d-to-%d. Qual: %g -> %g.\n", n, m,
30361                  acos(remedge->key) / PI * 180.0, acos(key) / PI * 180.0);
30362         }
30363         // Delete the old tets. Note, flip22() does not create new tets.
30364         if (m == 3) {
30365           for (i = 0; i < n; i++) {
30366             tetrahedrondealloc(abtetlist[i].tet);
30367           }
30368         }
30369         for (i = 0; i < m; i++) {
30370           checktet4opt(&(newtetlist[i]), true);
30371         }
30372         optcount[1]++;
30373         return true;
30374       }
30375     } // if (j = 0; j < 2; j++)
30376     // Faces are not flipable. Return.
30377     return false;
30378   }
30379 
30380   // 2 <= n <= 10.
30381   if (n == 3) {
30382     // There are three tets at ab. Try to do a flip32 at ab.
30383     remflag = removeedgebyflip32(&key, abtetlist, newtetlist, NULL);
30384   } else if ((n == 4) || (n == 5) || (n == 6)) {
30385     // Four tets case. Try to do edge transformation.
30386     remflag = removeedgebytranNM(&key,n,abtetlist,newtetlist,NULL,NULL,NULL);
30387   } else {
30388     if (b->verbose > 1) {
30389       printf("  !! Unhandled case: n = %d.\n", n);
30390     }
30391   }
30392   if (remflag) {
30393     optcount[n]++;
30394     // Delete the old tets.
30395     for (i = 0; i < n; i++) {
30396       tetrahedrondealloc(abtetlist[i].tet);
30397     }
30398     m = (n - 2) * 2; // The numebr of new tets.
30399     if (b->verbose > 1) {
30400       printf("  Done flip %d-to-%d. ", n, m);
30401       if (optflag) {
30402         printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30403                acos(key) / PI * 180.0);
30404       }
30405       printf("\n");
30406     }
30407   } 
30408 
30409   if (!remflag && (key == remedge->key) && (n < 7)) {
30410     // Try to do a combination of flips.
30411     n1 = 0;
30412     remflag = removeedgebycombNM(&key, n, abtetlist, &n1, bftetlist,
30413       newtetlist, NULL);
30414     if (remflag) {
30415       optcount[9]++;
30416       // Delete the old tets.
30417       for (i = 0; i < n; i++) {
30418         tetrahedrondealloc(abtetlist[i].tet);
30419       }
30420       for (i = 0; i < n1; i++) {
30421         if (!isdead(&(bftetlist[i]))) {
30422           tetrahedrondealloc(bftetlist[i].tet);
30423         }
30424       }
30425       m = ((n1 - 2) * 2 - 1) + (n - 3) * 2; // The number of new tets.
30426       if (b->verbose > 1) {
30427         printf("  Done flip %d-to-%d (n-1=%d, n1=%d). ", n+n1-2, m, n-1,n1);
30428         if (optflag) {
30429           printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30430                acos(key) / PI * 180.0);
30431         }
30432         printf("\n");
30433       }
30434     }
30435   }
30436 
30437   if (remflag) {
30438     // edge is removed. Test new tets for further optimization.
30439     for (i = 0; i < m; i++) {
30440       if (optflag) {
30441         checktet4opt(&(newtetlist[i]), true);
30442       } else {
30443         checktet4ill(&(newtetlist[i]), true);
30444       }
30445     }
30446   }
30447 
30448   return remflag;
30449 }
30450 
30452 //                                                                           //
30453 // smoothsliver()    Remove a sliver by smoothing a vertex of it.            //
30454 //                                                                           //
30455 // The 'slivtet' represents a sliver abcd, and ab is the current edge which  //
30456 // has a large dihedral angle (close to 180 degree).                         //
30457 //                                                                           //
30459 
30460 bool tetgenmesh::smoothsliver(badface* remedge, list *starlist)
30461 {
30462   triface checktet;
30463   point smthpt;
30464   bool smthed;
30465   int idx, i, j;
30466 
30467   // Find a Steiner volume point and smooth it.
30468   smthed = false;
30469   for (i = 0; i < 4 && !smthed; i++) {
30470     smthpt = (point) remedge->tt.tet[4 + i];
30471     // Is it a volume point?
30472     if (pointtype(smthpt) == FREEVOLVERTEX) {
30473       // Is it a Steiner point?
30474       idx = pointmark(smthpt) - in->firstnumber;
30475       if (!(idx < in->numberofpoints)) {
30476         // Smooth a Steiner volume point.
30477         starlist->append(&(remedge->tt.tet));
30478         formstarpolyhedron(smthpt, starlist, NULL, false);
30479         smthed = smoothpoint(smthpt,NULL,NULL,starlist,false,&remedge->key);
30480         // If it is smoothed. Queue new bad tets.
30481         if (smthed) {
30482           for (j = 0; j < starlist->len(); j++) {
30483             checktet = * (triface *)(* starlist)[j];
30484             checktet4opt(&checktet, true);
30485           }
30486         }
30487         starlist->clear();
30488       }
30489     }
30490   } 
30491 
30492   /* Omit to smooth segment points. This may cause infinite loop.
30493   if (smthed) {
30494     return true;
30495   }
30496   face abseg, nextseg, prevseg;
30497   point pt[2];
30498   // Check if ab is a segment.
30499   tsspivot(slivtet, &abseg);
30500   if (abseg.sh == dummysh) {
30501     // ab is not a segment. Check if a or b is a Steiner segment point.
30502     for (i = 0; i < 2 && !smthed; i++) {
30503       smthpt = (i == 0 ? org(*slivtet) : dest(*slivtet));
30504       if (pointtype(smthpt) == FREESEGVERTEX) {
30505         // Is it a Steiner point?
30506         idx = pointmark(smthpt) - in->firstnumber;
30507         if (!(idx < in->numberofpoints)) {
30508           // Smooth a Steiner segment point. Get the segment.
30509           sdecode(point2sh(smthpt), nextseg);
30510           locateseg(smthpt, &nextseg);
30511           assert(sorg(nextseg) == smthpt);
30512           pt[0] = sdest(nextseg);
30513           senext2(nextseg, prevseg);
30514           spivotself(prevseg);
30515           prevseg.shver = 0;
30516           if (sorg(prevseg) == smthpt) sesymself(prevseg);
30517           assert(sdest(prevseg) == smthpt);
30518           pt[1] = sorg(prevseg);
30519           starlist->append(slivtet);
30520           formstarpolyhedron(smthpt, starlist, NULL, true);
30521           smthed = smoothpoint(smthpt, pt[0], pt[1], starlist, false);
30522           // If it is smoothed. Check if the tet is still a sliver.
30523           if (smthed) checktet4opt(slivtet, true);
30524           starlist->clear();
30525         }
30526       }
30527     }
30528   }
30529   */
30530 
30531   return smthed;
30532 }
30533 
30535 //                                                                           //
30536 // splitsliver()    Remove a sliver by inserting a point.                    //
30537 //                                                                           //
30538 // The 'remedge->tt' represents a sliver abcd, ab is the current edge which  //
30539 // has a large dihedral angle (close to 180 degree).                         //
30540 //                                                                           //
30542 
30543 bool tetgenmesh::splitsliver(badface *remedge, list *tetlist, list *ceillist)
30544 {
30545   triface starttet;
30546   face checkseg;
30547   point newpt, pt[4];
30548   bool remflag;
30549   int i;
30550 
30551   starttet = remedge->tt;
30552 
30553   // Check if cd is a segment.
30554   adjustedgering(starttet, CCW);
30555   enextfnextself(starttet);
30556   enextself(starttet);
30557   tsspivot(&starttet, &checkseg);
30558   if (b->nobisect == 0) {
30559     if (checkseg.sh != dummysh) {
30560       // cd is a segment. The seg will be split. BUT do not flip! Due to the
30561       //   exact predicates, lot of slivers ay be rsulted and hard to remove.
30562       checkseg.shver = 0;
30563       pt[0] = sorg(checkseg);
30564       pt[1] = sdest(checkseg);
30565       makepoint(&newpt);
30566       getsplitpoint(pt[0], pt[1], NULL, newpt);
30567       setpointtype(newpt, FREESEGVERTEX);
30568       setpoint2sh(newpt, sencode(checkseg));
30569       // Insert p, this should always success.
30570       sstpivot(&checkseg, &starttet);
30571       splittetedge(newpt, &starttet, NULL);
30572       // Collect the new tets connecting at p.
30573       sstpivot(&checkseg, &starttet);
30574       ceillist->append(&starttet);
30575       formstarpolyhedron(newpt, ceillist, NULL, true);
30576       setnewpointsize(newpt, pt[0], NULL);
30577       if (steinerleft > 0) steinerleft--;
30578       // Smooth p.
30579       smoothpoint(newpt, pt[0], pt[1], ceillist, false, NULL);
30580       // Queue new slivers.
30581       for (i = 0; i < ceillist->len(); i++) {
30582         starttet = * (triface *)(* ceillist)[i];
30583         checktet4opt(&starttet, true);
30584       }
30585       ceillist->clear();
30586       return true;
30587     }
30588   }
30589 
30590   // Get the four corners.
30591   for (i = 0; i < 4; i++) {
30592     pt[i] = (point) starttet.tet[4 + i];
30593   }
30594   // Create the new point p (at the circumcenter of t).
30595   makepoint(&newpt);
30596   for (i = 0; i < 3; i++) {
30597     newpt[i] = 0.25 * (pt[0][i] + pt[1][i] + pt[2][i] + pt[3][i]);
30598   }
30599   setpointtype(newpt, FREEVOLVERTEX);
30600 
30601   // Form the Bowyer-Watson cavity of p.
30602   remflag = false;
30603   infect(starttet);
30604   tetlist->append(&starttet);
30605   formbowatcavityquad(newpt, tetlist, ceillist);
30606   if (trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, -1.0)) {
30607     // Smooth p.
30608     if (smoothpoint( newpt, NULL, NULL, ceillist, false, &remedge->key)) {
30609       // Insert p.
30610       bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, NULL,
30611                       NULL, false, false, false);
30612       setnewpointsize(newpt, pt[0], NULL);
30613       if (steinerleft > 0) steinerleft--;
30614       // Queue new slivers.
30615       for (i = 0; i < ceillist->len(); i++) {
30616         starttet = * (triface *)(* ceillist)[i];
30617         checktet4opt(&starttet, true);
30618       }
30619       remflag = true;
30620     } // if (smoothpoint) 
30621   } // if (trimbowatcavity) 
30622 
30623   if (!remflag) {
30624     // p is rejected for BC(p) is not valid.
30625     pointdealloc(newpt);
30626     // Uninfect tets of BC(p).
30627     for (i = 0; i < tetlist->len(); i++) {
30628       starttet = * (triface *)(* tetlist)[i];
30629       uninfect(starttet);
30630     }
30631   }
30632   tetlist->clear();
30633   ceillist->clear();
30634 
30635   return remflag;
30636 }
30637 
30639 //                                                                           //
30640 // tallslivers()    Queue all the slivers in the mesh.                       //
30641 //                                                                           //
30643 
30644 void tetgenmesh::tallslivers(bool optflag)
30645 {
30646   triface tetloop;
30647 
30648   tetrahedrons->traversalinit();
30649   tetloop.tet = tetrahedrontraverse();
30650   while (tetloop.tet != (tetrahedron *) NULL) {
30651     if (optflag) {
30652       checktet4opt(&tetloop, true);
30653     } else {
30654       checktet4ill(&tetloop, true);
30655     }
30656     tetloop.tet = tetrahedrontraverse();
30657   }
30658 }
30659 
30661 //                                                                           //
30662 // optimizemesh()    Improve mesh quality by mesh optimizations.             //
30663 //                                                                           //
30664 // Available mesh optimizing operations are: (1) multiple edge flips (3-to-2,//
30665 // 4-to-4, 5-to-6, etc), (2) free vertex deletion, (3) new vertex insertion. //
30666 // (1) is mandatory, while (2) and (3) are optionally.                       //
30667 //                                                                           //
30668 // The variable 'b->optlevel' (set after '-s') determines the use of these   //
30669 // operations. If it is: 0, do no optimization; 1, only do (1) operation; 2, //
30670 // do (1) and (2) operations; 3, do all operations. Deault, b->optlvel = 2.  //
30671 //                                                                           //
30673 
30674 void tetgenmesh::optimizemesh(bool optflag)
30675 {
30676   list *splittetlist, *tetlist, *ceillist;
30677   badface *remtet, *lastentry;
30678   REAL maxdihed, objdihed, curdihed;
30679   long oldnum;
30680   int iter, i;
30681 
30682   objdihed = 0.0;
30683 
30684   if (!b->quiet) {
30685     if (optflag) {
30686       printf("Optimizing mesh.\n");
30687     } else {
30688       printf("Repairing mesh.\n");
30689     }
30690   }
30691 
30692 #ifdef SELF_CHECK
30693   if (optflag && (b->verbose)) {
30694     printf("  level = %d.\n", b->optlevel);
30695   }
30696 #endif
30697 
30698   // Initialize the pool of bad tets.
30699   badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30700   if (optflag) {
30701     cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30702     cosmindihed = cos(b->mindihedral * PI / 180.0);
30703     // The radian of the maximum dihedral angle.
30704     maxdihed = b->maxdihedral / 180.0 * PI;
30705     // A sliver has an angle large than 'objdihed' will be split.
30706     objdihed = b->maxdihedral + 5.0;
30707     if (objdihed < 170.0) objdihed = 170.0;
30708     objdihed = objdihed / 180.0 * PI;
30709   }
30710   // Looking for non-optimal tets.
30711   tallslivers(optflag);
30712 
30713   optcount[0] = 0l;  // tet strip count.
30714   optcount[1] = 0l;  // face (2-3) and edge (2-2) flip count.
30715   optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l; // edge flips.
30716   optcount[9] = 0l;  // combined flip count.
30717 
30718   // Perform edge flip to improve quality.
30719   lastentry = (badface *) NULL;
30720   // Loop until pool 'badtetrahedrons' is empty.
30721   while (badtetrahedrons->items > 0) {
30722     badtetrahedrons->traversalinit();
30723     remtet = badfacetraverse(badtetrahedrons);
30724     while (remtet != (badface *) NULL) {
30725       // Make sure that the tet is still the same one when it was tested.
30726       //   Subsequent transformations may have made it a different tet.
30727       if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30728           dest(remtet->tt) == remtet->fdest && 
30729           apex(remtet->tt) == remtet->fapex &&
30730           oppo(remtet->tt) == remtet->foppo) {
30731         if (b->verbose > 1) {
30732           printf("    Repair tet (%d, %d, %d, %d) %g (degree).\n",
30733                  pointmark(remtet->forg), pointmark(remtet->fdest),
30734                  pointmark(remtet->fapex), pointmark(remtet->foppo),
30735                  acos(remtet->key) / PI * 180.0);
30736         }
30737         if (!removeedge(remtet, optflag)) {
30738           // An unremoveable tet. Check if it forms a loop.
30739           if (lastentry != (badface *) NULL) {
30740             if (remtet == lastentry) break;
30741           } else {
30742             // Remember this tet as a breakpoint.
30743             lastentry = remtet;
30744           }
30745         } else {
30746           // Clear the breakpoint.
30747           lastentry = (badface *) NULL;
30748           // Remove the entry from the queue.
30749           badfacedealloc(badtetrahedrons, remtet);
30750         }
30751       } else {
30752         // Remove the entry from the queue.
30753         badfacedealloc(badtetrahedrons, remtet);
30754       }
30755       remtet = badfacetraverse(badtetrahedrons);
30756     }
30757     // Stop if the above loop was out by force.
30758     if (remtet != (badface *) NULL) break;
30759   }
30760 
30761   if (b->verbose) {
30762     if (optcount[0] > 0l) {
30763       printf("  %ld tets are peeled off.\n", optcount[0]);
30764     }
30765     if (optcount[1] > 0l) {
30766       printf("  %ld faces are flipped.\n", optcount[1]);
30767     }
30768     if (optcount[3] + optcount[4] + optcount[5] + optcount[6] + 
30769         optcount[9] > 0l) {
30770       printf("  %ld edges are flipped.\n", optcount[3] + optcount[4] +
30771              optcount[5] + optcount[6] + optcount[9]);
30772     }
30773     // if (badtetrahedrons->items > 0l) {
30774     //   printf("  %ld edges remain.\n", badtetrahedrons->items);
30775     // }
30776   }
30777 
30778   if ((badtetrahedrons->items > 0l) && optflag  && (b->optlevel > 2)) {
30779     splittetlist = new list(sizeof(badface), NULL, 256);
30780     tetlist = new list(sizeof(triface), NULL, 256);
30781     ceillist = new list(sizeof(triface), NULL, 256);
30782     oldnum = points->items;
30783     smoothsegverts = smoothvolverts = 0;
30784     optcount[1] = 0l;
30785     optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l; // edge flips.
30786     optcount[9] = 0l;  // combined flip count.
30787     iter = 0;
30788 
30789     do {
30790       // Form a list of slivers to be split and clean the pool.
30791       badtetrahedrons->traversalinit();
30792       remtet = badfacetraverse(badtetrahedrons);
30793       while (remtet != (badface *) NULL) {
30794         splittetlist->append(remtet);
30795         // Remove the entry from the queue.
30796         badfacedealloc(badtetrahedrons, remtet);
30797         remtet = badfacetraverse(badtetrahedrons);
30798       }
30799       for (i = 0; i < splittetlist->len(); i++) {
30800         remtet = (badface *)(* splittetlist)[i];
30801         // Make sure that the tet is still the same one when it was tested.
30802         //   Subsequent transformations may have made it a different tet.
30803         if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30804             dest(remtet->tt) == remtet->fdest && 
30805             apex(remtet->tt) == remtet->fapex &&
30806             oppo(remtet->tt) == remtet->foppo) {
30807           // The sliver may get smoothed due to a neighboring tet.
30808           curdihed = facedihedral(remtet->forg, remtet->fdest, remtet->fapex,
30809                                   remtet->foppo);
30810           // The dihedral angle of a tet must less than PI, correct it.
30811           if (curdihed > PI) curdihed = 2 * PI - curdihed;
30812           // Is it a large angle?
30813           if (curdihed > objdihed) {
30814             remtet->key = cos(curdihed);
30815             if (b->verbose > 1) {
30816               printf("    Get sliver (%d, %d, %d, %d) %g (degree).\n",
30817                      pointmark(remtet->forg), pointmark(remtet->fdest),
30818                      pointmark(remtet->fapex), pointmark(remtet->foppo),
30819                      acos(remtet->key) / PI * 180.0);
30820             }
30821             if (!removeedge(remtet, optflag)) {
30822               if (!smoothsliver(remtet, tetlist)) {
30823                 splitsliver(remtet, tetlist, ceillist);
30824               }
30825             }
30826           }
30827         }
30828       }
30829       iter++;
30830     } while ((badtetrahedrons->items > 0l) && (iter < b->optpasses));
30831     
30832     if (b->verbose) {
30833       printf("  %d passes.\n", iter);
30834       if ((points->items - oldnum) > 0l) {
30835         printf("  %ld points are inserted (%d on segment).\n",
30836                points->items - oldnum, smoothsegverts);
30837       }
30838       if (optcount[1] > 0l) {
30839         printf("  %ld faces are flipped.\n", optcount[1]);
30840       }
30841       if (optcount[3] + optcount[4] + optcount[5] + optcount[6] + 
30842           optcount[9] > 0l) {
30843         printf("  %ld edges are flipped.\n", optcount[3] + optcount[4] +
30844                optcount[5] + optcount[6] + optcount[9]);
30845       }
30846       // if (badtetrahedrons->items > 0l) {
30847       //   printf("  %ld edges remain.\n", badtetrahedrons->items);
30848       // }
30849     }
30850     delete tetlist;
30851     delete ceillist;
30852     delete splittetlist;
30853   }
30854 
30855   delete badtetrahedrons;
30856   badtetrahedrons = (memorypool *) NULL;
30857 }
30858 
30859 //
30860 // End of mesh optimization routines
30861 //
30862 
30863 //
30864 // Begin of I/O rouitnes
30865 //
30866 
30868 //                                                                           //
30869 // transfernodes()    Transfer nodes from 'io->pointlist' to 'this->points'. //
30870 //                                                                           //
30871 // Initializing 'this->points'.  Transferring all points from 'in->pointlist'//
30872 // into it. All points are indexed (start from in->firstnumber).  Each point //
30873 // is initialized be UNUSEDVERTEX.  The bounding box (xmin, xmax, ymin, ymax,//
30874 // zmin, zmax) and the diameter (longest) of the point set are calculated.   //
30875 //                                                                           //
30877 
30878 void tetgenmesh::transfernodes()
30879 {
30880   point pointloop;
30881   REAL x, y, z;
30882   int coordindex;
30883   int attribindex;
30884   int mtrindex;
30885   int i, j;
30886 
30887   // Read the points.
30888   coordindex = 0;
30889   attribindex = 0;
30890   mtrindex = 0;
30891   for (i = 0; i < in->numberofpoints; i++) {
30892     makepoint(&pointloop);
30893     // Read the point coordinates.
30894     x = pointloop[0] = in->pointlist[coordindex++];
30895     y = pointloop[1] = in->pointlist[coordindex++];
30896     z = pointloop[2] = in->pointlist[coordindex++];
30897     // Read the point attributes.
30898     for (j = 0; j < in->numberofpointattributes; j++) {
30899       pointloop[3 + j] = in->pointattributelist[attribindex++];
30900     }
30901     // Read the point metric tensor.
30902     for (j = 0; j < in->numberofpointmtrs; j++) {
30903       pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
30904     }
30905     // Determine the smallest and largests x, y and z coordinates.
30906     if (i == 0) {
30907       xmin = xmax = x;
30908       ymin = ymax = y;
30909       zmin = zmax = z;
30910     } else {
30911       xmin = (x < xmin) ? x : xmin;
30912       xmax = (x > xmax) ? x : xmax;
30913       ymin = (y < ymin) ? y : ymin;
30914       ymax = (y > ymax) ? y : ymax;
30915       zmin = (z < zmin) ? z : zmin;
30916       zmax = (z > zmax) ? z : zmax;
30917     }
30918   }
30919   // 'longest' is the largest possible edge length formed by input vertices.
30920   x = xmax - xmin;
30921   y = ymax - ymin;
30922   z = zmax - zmin;
30923   longest = sqrt(x * x + y * y + z * z);
30924   if (longest == 0.0) {
30925     printf("Error:  The point set is trivial.\n");
30926     terminatetetgen(1);
30927   }
30928   // Two identical points are distinguished by 'lengthlimit'.
30929   lengthlimit = longest * b->epsilon * 1e+2;
30930 }
30931 
30933 //                                                                           //
30934 // jettisonnodes()    Jettison unused or duplicated vertices.                //
30935 //                                                                           //
30936 // Unused points are those input points which are outside the mesh domain or //
30937 // have no connection (isolated) to the mesh.  Duplicated points exist for   //
30938 // example if the input PLC is read from a .stl mesh file (marked during the //
30939 // Delaunay tetrahedralization step. This routine remove these points from   //
30940 // points list. All existing points are reindexed.                           //
30941 //                                                                           //
30943 
30944 void tetgenmesh::jettisonnodes()
30945 {
30946   point pointloop;
30947   bool jetflag;
30948   int oldidx, newidx;
30949   int remcount;
30950 
30951   if (!b->quiet) {
30952     printf("Jettisoning redundants points.\n");
30953   }
30954 
30955   points->traversalinit();
30956   pointloop = pointtraverse();
30957   oldidx = newidx = 0; // in->firstnumber;
30958   remcount = 0;
30959   while (pointloop != (point) NULL) {
30960     jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) || 
30961       (pointtype(pointloop) == UNUSEDVERTEX);
30962     if (jetflag) {
30963       // It is a duplicated point, delete it.
30964       pointdealloc(pointloop);
30965       remcount++;
30966     } else {
30967       // Re-index it.
30968       setpointmark(pointloop, newidx + in->firstnumber);
30969       if (in->pointmarkerlist != (int *) NULL) {
30970         if (oldidx < in->numberofpoints) {
30971           // Re-index the point marker as well.
30972           in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
30973         }
30974       }
30975       newidx++;
30976     }
30977     oldidx++;
30978     if (oldidx == in->numberofpoints) {
30979       // Update the numbe of input points (Because some were removed).
30980       in->numberofpoints -= remcount;
30981       // Remember this number for output original input nodes.
30982       jettisoninverts = remcount;
30983     }
30984     pointloop = pointtraverse();
30985   }
30986   if (b->verbose) {
30987     printf("  %d duplicated vertices have been removed.\n", dupverts);
30988     printf("  %d unused vertices have been removed.\n", unuverts);
30989   }
30990   dupverts = 0;
30991   unuverts = 0;
30992 
30993   // The following line ensures that dead items in the pool of nodes cannot
30994   //   be allocated for the new created nodes. This ensures that the input
30995   //   nodes will occur earlier in the output files, and have lower indices.
30996   points->deaditemstack = (void *) NULL;
30997 }
30998 
31000 //                                                                           //
31001 // highorder()   Create extra nodes for quadratic subparametric elements.    //
31002 //                                                                           //
31003 // 'highordertable' is an array (size = numberoftetrahedra * 6) for storing  //
31004 // high-order nodes of each tetrahedron.  This routine is used only when -o2 //
31005 // switch is used.                                                           //
31006 //                                                                           //
31008 
31009 void tetgenmesh::highorder()
31010 {
31011   triface tetloop, worktet;
31012   triface spintet, adjtet;
31013   point torg, tdest, tapex;
31014   point *extralist, *adjextralist;
31015   point newpoint;
31016   int hitbdry, ptmark;
31017   int i, j;
31018 
31019   if (!b->quiet) {
31020     printf("Adding vertices for second-order tetrahedra.\n");
31021   }
31022 
31023   // Initialize the 'highordertable'.
31024   highordertable = new point[tetrahedrons->items * 6];
31025   if (highordertable == (point *) NULL) {
31026     printf("Error:  Out of memory.\n");
31027     terminatetetgen(1);
31028   }
31029 
31030   // The following line ensures that dead items in the pool of nodes cannot
31031   //   be allocated for the extra nodes associated with high order elements.
31032   //   This ensures that the primary nodes (at the corners of elements) will
31033   //   occur earlier in the output files, and have lower indices, than the
31034   //   extra nodes.
31035   points->deaditemstack = (void *) NULL;
31036 
31037   // Assign an entry for each tetrahedron to find its extra nodes. At the
31038   //   mean while, initialize all extra nodes be NULL.
31039   i = 0;
31040   tetrahedrons->traversalinit();
31041   tetloop.tet = tetrahedrontraverse();
31042   while (tetloop.tet != (tetrahedron *) NULL) {
31043     tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
31044     for (j = 0; j < 6; j++) {
31045       highordertable[i + j] = (point) NULL;
31046     }
31047     i += 6;
31048     tetloop.tet = tetrahedrontraverse();
31049   }
31050 
31051   // To create a unique node on each edge. Loop over all tetrahedra, and
31052   //   look at the six edges of each tetrahedron.  If the extra node in
31053   //   the tetrahedron corresponding to this edge is NULL, create a node
31054   //   for this edge, at the same time, set the new node into the extra
31055   //   node lists of all other tetrahedra sharing this edge.  
31056   tetrahedrons->traversalinit();
31057   tetloop.tet = tetrahedrontraverse();
31058   while (tetloop.tet != (tetrahedron *) NULL) {
31059     // Get the list of extra nodes.
31060     extralist = (point *) tetloop.tet[highorderindex];
31061     worktet.tet = tetloop.tet;
31062     for (i = 0; i < 6; i++) {
31063       if (extralist[i] == (point) NULL) {
31064         // Operate on this edge.
31065         worktet.loc = edge2locver[i][0];
31066         worktet.ver = edge2locver[i][1];
31067         // Create a new node on this edge.
31068         torg = org(worktet);
31069         tdest = dest(worktet);
31070         // Create a new node in the middle of the edge.
31071         newpoint = (point) points->alloc();
31072         // Interpolate its attributes.
31073         for (j = 0; j < 3 + in->numberofpointattributes; j++) {
31074           newpoint[j] = 0.5 * (torg[j] + tdest[j]);
31075         }
31076         ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
31077         setpointmark(newpoint, ptmark);
31078         // Add this node to its extra node list.
31079         extralist[i] = newpoint;
31080         // Set 'newpoint' into extra node lists of other tetrahedra
31081         //   sharing this edge.
31082         tapex = apex(worktet);
31083         spintet = worktet;
31084         hitbdry = 0;
31085         while (hitbdry < 2) {
31086           if (fnextself(spintet)) {
31087             // Get the extra node list of 'spintet'.
31088             adjextralist = (point *) spintet.tet[highorderindex];
31089             // Find the index of its extra node list.
31090             j = locver2edge[spintet.loc][spintet.ver];
31091             // Only set 'newpoint' into 'adjextralist' if it is a NULL.
31092             //   Because two faces can belong to the same tetrahedron.
31093             if (adjextralist[j] == (point) NULL) {
31094               adjextralist[j] = newpoint;
31095             }
31096             if (apex(spintet) == tapex) {
31097               break;
31098             }
31099           } else {
31100             hitbdry++;
31101             if (hitbdry < 2) {
31102               esym(worktet, spintet);
31103         }
31104           }
31105         }
31106       }
31107     }
31108     tetloop.tet = tetrahedrontraverse();
31109   }
31110 }
31111 
31113 //                                                                           //
31114 // outnodes()    Output the points to a .node file or a tetgenio structure.  //
31115 //                                                                           //
31116 // Note: each point has already been numbered on input (the first index is   //
31117 // 'in->firstnumber').                                                       //
31118 //                                                                           //
31120 
31121 void tetgenmesh::outnodes(tetgenio* out)
31122 {
31123   FILE *outfile;
31124   char outnodefilename[FILENAMESIZE];
31125   shellface subptr;
31126   triface adjtet;
31127   face subloop;
31128   point pointloop;
31129   point *extralist, ep[3];
31130   int nextras, bmark, shmark, marker;
31131   int coordindex, attribindex;
31132   int pointnumber, firstindex;
31133   int index, i;
31134 
31135   if (out == (tetgenio *) NULL) {
31136     strcpy(outnodefilename, b->outfilename);
31137     strcat(outnodefilename, ".node");
31138   } 
31139   
31140   if (!b->quiet) {
31141     if (out == (tetgenio *) NULL) {
31142       printf("Writing %s.\n", outnodefilename);
31143     } else {
31144       printf("Writing nodes.\n");
31145     }
31146   }
31147 
31148   nextras = in->numberofpointattributes;
31149   bmark = !b->nobound && in->pointmarkerlist;
31150 
31151   // Avoid compile warnings.
31152   outfile = (FILE *) NULL;
31153   marker = coordindex = 0;
31154 
31155   if (out == (tetgenio *) NULL) {
31156     outfile = fopen(outnodefilename, "w");
31157     if (outfile == (FILE *) NULL) {
31158       printf("File I/O Error:  Cannot create file %s.\n", outnodefilename);
31159       terminatetetgen(1);
31160     }
31161     // Number of points, number of dimensions, number of point attributes,
31162     //   and number of boundary markers (zero or one).
31163     fprintf(outfile, "%ld  %d  %d  %d\n", points->items, 3, nextras, bmark);
31164   } else {
31165     // Allocate space for 'pointlist';
31166     out->pointlist = new REAL[points->items * 3];
31167     if (out->pointlist == (REAL *) NULL) {
31168       printf("Error:  Out of memory.\n");
31169       terminatetetgen(1);
31170     }
31171     // Allocate space for 'pointattributelist' if necessary;
31172     if (nextras > 0) {
31173       out->pointattributelist = new REAL[points->items * nextras];
31174       if (out->pointattributelist == (REAL *) NULL) {
31175         printf("Error:  Out of memory.\n");
31176         terminatetetgen(1);
31177       }
31178     }
31179     // Allocate space for 'pointmarkerlist' if necessary;
31180     if (bmark) {
31181       out->pointmarkerlist = new int[points->items];
31182       if (out->pointmarkerlist == (int *) NULL) {
31183         printf("Error:  Out of memory.\n");
31184         terminatetetgen(1);
31185       }
31186     }
31187     out->numberofpoints = points->items;
31188     out->numberofpointattributes = nextras;
31189     coordindex = 0;
31190     attribindex = 0;
31191   }
31192 
31193   if (bmark && (b->plc || b->refine)) {
31194     // Initialize the point2tet field of each point.
31195     points->traversalinit();
31196     pointloop = pointtraverse();
31197     while (pointloop != (point) NULL) {
31198       setpoint2tet(pointloop, (tetrahedron) NULL);
31199       pointloop = pointtraverse();
31200     }
31201     // Make a map point-to-subface. Hence a boundary point will get the
31202     //   facet marker from that facet where it lies on.
31203     subfaces->traversalinit();
31204     subloop.sh = shellfacetraverse(subfaces);
31205     while (subloop.sh != (shellface *) NULL) {
31206       subloop.shver = 0;
31207       // Check all three points of the subface.
31208       for (i = 0; i < 3; i++) {
31209         pointloop = (point) subloop.sh[3 + i];
31210         setpoint2tet(pointloop, (tetrahedron) sencode(subloop));
31211       }
31212       if (b->order == 2) {
31213         // '-o2' switch. Set markers for quadratic nodes of this subface.
31214         stpivot(subloop, adjtet);
31215         if (adjtet.tet == dummytet) {
31216           sesymself(subloop);
31217           stpivot(subloop, adjtet);
31218         }
31219         assert(adjtet.tet != dummytet);
31220         extralist = (point *) adjtet.tet[highorderindex];
31221         switch (adjtet.loc) {
31222         case 0:
31223           ep[0] = extralist[0];
31224           ep[1] = extralist[1];
31225           ep[2] = extralist[2];
31226           break;
31227         case 1:
31228           ep[0] = extralist[0];
31229           ep[1] = extralist[4];
31230           ep[2] = extralist[3];
31231           break;
31232         case 2:
31233           ep[0] = extralist[1];
31234           ep[1] = extralist[5];
31235           ep[2] = extralist[4];
31236           break;
31237         case 3:
31238           ep[0] = extralist[2];
31239           ep[1] = extralist[3];
31240           ep[2] = extralist[5];
31241           break;
31242         default: break;
31243         }
31244         for (i = 0; i < 3; i++) {
31245           setpoint2tet(ep[i], (tetrahedron) sencode(subloop));
31246         }
31247       }
31248       subloop.sh = shellfacetraverse(subfaces);
31249     }
31250   }
31251 
31252   // Determine the first index (0 or 1).
31253   firstindex = b->zeroindex ? 0 : in->firstnumber; 
31254 
31255   points->traversalinit();
31256   pointloop = pointtraverse();
31257   pointnumber = firstindex; // in->firstnumber;
31258   index = 0;
31259   while (pointloop != (point) NULL) {
31260     if (bmark) {
31261       // Default the vertex has a zero marker.
31262       marker = 0;
31263       // Is it an input vertex?
31264       if (index < in->numberofpoints) {
31265         // Input point's marker is directly copied to output.
31266         marker = in->pointmarkerlist[index];
31267       }
31268       // Is it a boundary vertex has marker zero?
31269       if ((marker == 0) && (b->plc || b->refine)) {
31270         subptr = (shellface) point2tet(pointloop);
31271         if (subptr != (shellface) NULL) {
31272           // Default a boundary vertex has marker 1.
31273           marker = 1;
31274           if (in->facetmarkerlist != (int *) NULL) {
31275             // The vertex gets the marker from the facet it lies on.
31276             sdecode(subptr, subloop);
31277             shmark = shellmark(subloop);
31278             marker = in->facetmarkerlist[shmark - 1];
31279           }
31280         }
31281       }
31282     }
31283     if (out == (tetgenio *) NULL) {
31284       // Point number, x, y and z coordinates.
31285       fprintf(outfile, "%4d    %.17g  %.17g  %.17g", pointnumber,
31286               pointloop[0], pointloop[1], pointloop[2]);
31287       for (i = 0; i < nextras; i++) {
31288         // Write an attribute.
31289         fprintf(outfile, "  %.17g", pointloop[3 + i]);
31290       }
31291       if (bmark) {
31292         // Write the boundary marker.
31293         fprintf(outfile, "    %d", marker);
31294       }
31295       fprintf(outfile, "\n");
31296     } else {
31297       // X, y, and z coordinates.
31298       out->pointlist[coordindex++] = pointloop[0];
31299       out->pointlist[coordindex++] = pointloop[1];
31300       out->pointlist[coordindex++] = pointloop[2];
31301       // Point attributes.
31302       for (i = 0; i < nextras; i++) {
31303         // Output an attribute.
31304         out->pointattributelist[attribindex++] = pointloop[3 + i];
31305       }
31306       if (bmark) {
31307         // Output the boundary marker.  
31308         out->pointmarkerlist[index] = marker;
31309       }
31310     }
31311     pointloop = pointtraverse();
31312     pointnumber++; 
31313     index++;
31314   }
31315 
31316   if (out == (tetgenio *) NULL) {
31317     fprintf(outfile, "# Generated by %s\n", b->commandline);
31318     fclose(outfile);
31319   }
31320 }
31321 
31323 //                                                                           //
31324 // outmetrics()    Output the metric to a file (*.mtr) or a tetgenio obj.    //
31325 //                                                                           //
31327 
31328 void tetgenmesh::outmetrics(tetgenio* out)
31329 {
31330   FILE *outfile;
31331   char outmtrfilename[FILENAMESIZE];
31332   list *tetlist, *ptlist;
31333   triface tetloop;
31334   point ptloop, neipt;
31335   REAL lave, len; // lmin, lmax, 
31336   int mtrindex;
31337   int i;  
31338 
31339   lave = 0.0;
31340   
31341   if (out == (tetgenio *) NULL) {
31342     strcpy(outmtrfilename, b->outfilename);
31343     strcat(outmtrfilename, ".mtr");
31344   }
31345 
31346   if (!b->quiet) {
31347     if (out == (tetgenio *) NULL) {
31348       printf("Writing %s.\n", outmtrfilename);
31349     } else {
31350       printf("Writing metrics.\n");
31351     }
31352   }
31353 
31354   // Avoid compile warnings.
31355   outfile = (FILE *) NULL;
31356   mtrindex = 0;
31357 
31358   if (out == (tetgenio *) NULL) {
31359     outfile = fopen(outmtrfilename, "w");
31360     if (outfile == (FILE *) NULL) {
31361       printf("File I/O Error:  Cannot create file %s.\n", outmtrfilename);
31362       terminatetetgen(1);
31363     }
31364     // Number of points, number of point metrices,
31365     // fprintf(outfile, "%ld  %d\n", points->items, sizeoftensor + 3);
31366     fprintf(outfile, "%ld  %d\n", points->items, 1);
31367   } else {
31368     // Allocate space for 'pointmtrlist' if necessary;
31369     // out->pointmtrlist = new REAL[points->items * (sizeoftensor + 3)];
31370     out->pointmtrlist = new REAL[points->items];
31371     if (out->pointmtrlist == (REAL *) NULL) {
31372       printf("Error:  Out of memory.\n");
31373       terminatetetgen(1);
31374     }
31375     out->numberofpointmtrs = 1; // (sizeoftensor + 3);
31376     mtrindex = 0;
31377   }
31378   
31379   // Initialize the point2tet field of each point.
31380   points->traversalinit();
31381   ptloop = pointtraverse();
31382   while (ptloop != (point) NULL) {
31383     setpoint2tet(ptloop, (tetrahedron) NULL);
31384     ptloop = pointtraverse();
31385   }
31386   // Create the point-to-tet map.
31387   tetrahedrons->traversalinit();
31388   tetloop.tet = tetrahedrontraverse();
31389   while (tetloop.tet != (tetrahedron *) NULL) {
31390     for (i = 0; i < 4; i++) {
31391       ptloop = (point) tetloop.tet[4 + i];
31392       setpoint2tet(ptloop, encode(tetloop));
31393     }
31394     tetloop.tet = tetrahedrontraverse();
31395   }
31396 
31397   tetlist = new list(sizeof(triface), NULL, 256);
31398   ptlist = new list(sizeof(point *), NULL, 256);
31399 
31400   points->traversalinit();
31401   ptloop = pointtraverse();
31402   while (ptloop != (point) NULL) {
31403     decode(point2tet(ptloop), tetloop);
31404     if (!isdead(&tetloop)) {
31405       // Form the star of p.
31406       tetlist->append(&tetloop);
31407       formstarpolyhedron(ptloop, tetlist, ptlist, true);
31408       // lmin = longest;
31409       // lmax = 0.0;
31410       lave = 0.0;
31411       for (i = 0; i < ptlist->len(); i++) {
31412         neipt = * (point *)(* ptlist)[i];
31413         len = distance(ptloop, neipt);
31414         // lmin = lmin < len ? lmin : len;
31415         // lmax = lmax > len ? lmax : len;
31416         lave += len;
31417       }
31418       lave /= ptlist->len();
31419     }
31420     if (out == (tetgenio *) NULL) {
31421       // for (i = 0; i < sizeoftensor; i++) {
31422       //   fprintf(outfile, "%-16.8e ", ptloop[pointmtrindex + i]);
31423       // }
31424       if (ptlist->len() > 0) {
31425         // fprintf(outfile, "%-16.8e %-16.8e %-16.8e", lmin, lmax, lave);
31426         fprintf(outfile, "%-16.8e ", lave);
31427       } else {
31428         fprintf(outfile, "0.0 "); // fprintf(outfile, "0.0  0.0  0.0");
31429       }
31430       fprintf(outfile, "\n");
31431     } else {
31432       // for (i = 0; i < sizeoftensor; i++) {
31433       //   out->pointmtrlist[mtrindex++] = ptloop[pointmtrindex + i];
31434       // }
31435       if (ptlist->len() > 0) {
31436         // out->pointmtrlist[mtrindex++] = lmin;
31437         // out->pointmtrlist[mtrindex++] = lmax;
31438         out->pointmtrlist[mtrindex++] = lave;
31439       } else {
31440         // out->pointmtrlist[mtrindex++] = 0.0;
31441         // out->pointmtrlist[mtrindex++] = 0.0;
31442         out->pointmtrlist[mtrindex++] = 0.0;
31443       }
31444     }
31445     tetlist->clear();
31446     ptlist->clear();
31447     ptloop = pointtraverse();
31448   }
31449 
31450   delete tetlist;
31451   delete ptlist;
31452 
31453   if (out == (tetgenio *) NULL) {
31454     fprintf(outfile, "# Generated by %s\n", b->commandline);
31455     fclose(outfile);
31456   }
31457 }
31458 
31460 //                                                                           //
31461 // outelements()    Output the tetrahedra to an .ele file or a tetgenio      //
31462 //                  structure.                                               //
31463 //                                                                           //
31465 
31466 void tetgenmesh::outelements(tetgenio* out)
31467 {
31468   FILE *outfile;
31469   char outelefilename[FILENAMESIZE];
31470   tetrahedron* tptr;
31471   int *tlist;
31472   REAL *talist;
31473   int firstindex, shift;
31474   int pointindex;
31475   int attribindex;
31476   point p1, p2, p3, p4;
31477   point *extralist;
31478   int elementnumber;
31479   int eextras;
31480   int i;
31481 
31482   if (out == (tetgenio *) NULL) {
31483     strcpy(outelefilename, b->outfilename);
31484     strcat(outelefilename, ".ele");
31485   }
31486 
31487   if (!b->quiet) {
31488     if (out == (tetgenio *) NULL) {
31489       printf("Writing %s.\n", outelefilename);
31490     } else {
31491       printf("Writing elements.\n");
31492     }
31493   }
31494 
31495   // Avoid compile warnings.
31496   outfile = (FILE *) NULL;
31497   tlist = (int *) NULL;
31498   talist = (double *) NULL;
31499   pointindex = attribindex = 0;
31500 
31501   eextras = in->numberoftetrahedronattributes;
31502   if (out == (tetgenio *) NULL) {
31503     outfile = fopen(outelefilename, "w");
31504     if (outfile == (FILE *) NULL) {
31505       printf("File I/O Error:  Cannot create file %s.\n", outelefilename);
31506       terminatetetgen(1);
31507     }
31508     // Number of tetras, points per tetra, attributes per tetra.
31509     fprintf(outfile, "%ld  %d  %d\n", tetrahedrons->items,
31510             b->order == 1 ? 4 : 10, eextras);
31511   } else {
31512     // Allocate memory for output tetrahedra.
31513     out->tetrahedronlist = new int[tetrahedrons->items * 
31514                                    (b->order == 1 ? 4 : 10)];
31515     if (out->tetrahedronlist == (int *) NULL) {
31516       printf("Error:  Out of memory.\n");
31517       terminatetetgen(1);
31518     }
31519     // Allocate memory for output tetrahedron attributes if necessary.
31520     if (eextras > 0) {
31521       out->tetrahedronattributelist = new REAL[tetrahedrons->items * eextras];
31522       if (out->tetrahedronattributelist == (REAL *) NULL) {
31523         printf("Error:  Out of memory.\n");
31524         terminatetetgen(1);
31525       }
31526     }
31527     out->numberoftetrahedra = tetrahedrons->items;
31528     out->numberofcorners = b->order == 1 ? 4 : 10;
31529     out->numberoftetrahedronattributes = eextras;
31530     tlist = out->tetrahedronlist;
31531     talist = out->tetrahedronattributelist;
31532     pointindex = 0;
31533     attribindex = 0;
31534   }
31535 
31536   // Determine the first index (0 or 1).
31537   firstindex = b->zeroindex ? 0 : in->firstnumber;
31538   shift = 0; // Default no shiftment.
31539   if ((in->firstnumber == 1) && (firstindex == 0)) {
31540     shift = 1; // Shift the output indices by 1.
31541   }
31542 
31543   tetrahedrons->traversalinit();
31544   tptr = tetrahedrontraverse();
31545   elementnumber = firstindex; // in->firstnumber;
31546   while (tptr != (tetrahedron *) NULL) {
31547     p1 = (point) tptr[4];
31548     p2 = (point) tptr[5];
31549     p3 = (point) tptr[6];
31550     p4 = (point) tptr[7];
31551     if (out == (tetgenio *) NULL) {
31552       // Tetrahedron number, indices for four points.
31553       fprintf(outfile, "%5d   %5d %5d %5d %5d", elementnumber,
31554               pointmark(p1) - shift, pointmark(p2) - shift,
31555               pointmark(p3) - shift, pointmark(p4) - shift);
31556       if (b->order == 2) {
31557         extralist = (point *) tptr[highorderindex];
31558         // Tetrahedron number, indices for four points plus six extra points.
31559         fprintf(outfile, "  %5d %5d %5d %5d %5d %5d",
31560           pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
31561           pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
31562           pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
31563       }
31564       for (i = 0; i < eextras; i++) {
31565         fprintf(outfile, "    %.17g", elemattribute(tptr, i));
31566       }
31567       fprintf(outfile, "\n");
31568     } else {
31569       tlist[pointindex++] = pointmark(p1) - shift;
31570       tlist[pointindex++] = pointmark(p2) - shift;
31571       tlist[pointindex++] = pointmark(p3) - shift;
31572       tlist[pointindex++] = pointmark(p4) - shift;
31573       if (b->order == 2) {
31574         extralist = (point *) tptr[highorderindex];
31575         tlist[pointindex++] = pointmark(extralist[0]) - shift;
31576         tlist[pointindex++] = pointmark(extralist[1]) - shift;
31577         tlist[pointindex++] = pointmark(extralist[2]) - shift;
31578         tlist[pointindex++] = pointmark(extralist[3]) - shift;
31579         tlist[pointindex++] = pointmark(extralist[4]) - shift;
31580         tlist[pointindex++] = pointmark(extralist[5]) - shift;
31581       }
31582       for (i = 0; i < eextras; i++) {
31583         talist[attribindex++] = elemattribute(tptr, i);
31584       }
31585     }
31586     if (b->neighout) {
31587       // Remember the index of this element.
31588       * (int *) (tptr + elemmarkerindex) = elementnumber;
31589     }
31590     tptr = tetrahedrontraverse();
31591     elementnumber++;
31592   }
31593   if (b->neighout) {
31594     // Set the outside element marker.
31595     * (int *) (dummytet + elemmarkerindex) = -1;
31596   }
31597 
31598   if (out == (tetgenio *) NULL) {
31599     fprintf(outfile, "# Generated by %s\n", b->commandline);
31600     fclose(outfile);
31601   }
31602 }
31603 
31605 //                                                                           //
31606 // outfaces()    Output all faces to a .face file or a tetgenio structure.   //
31607 //                                                                           //
31608 // This routines outputs all triangular faces (including outer boundary      //
31609 // faces and inner faces) of this mesh.                                      //
31610 //                                                                           //
31612 
31613 void tetgenmesh::outfaces(tetgenio* out)
31614 {
31615   FILE *outfile;
31616   char facefilename[FILENAMESIZE];
31617   int *elist;
31618   int *emlist;
31619   int neigh1, neigh2;
31620   int index;
31621   triface tface, tsymface;
31622   face checkmark;
31623   point torg, tdest, tapex;
31624   long faces;
31625   int bmark, faceid, marker;
31626   int firstindex, shift;
31627   int facenumber;
31628 
31629   neigh1 = 0;
31630   neigh2 = 0;
31631   
31632   if (out == (tetgenio *) NULL) {
31633     strcpy(facefilename, b->outfilename);
31634     strcat(facefilename, ".face");
31635   }
31636 
31637   if (!b->quiet) {
31638     if (out == (tetgenio *) NULL) {
31639       printf("Writing %s.\n", facefilename);
31640     } else {
31641       printf("Writing faces.\n");
31642     }
31643   }
31644 
31645   // Avoid compile warnings.
31646   outfile = (FILE *) NULL;
31647   elist = (int *) NULL;
31648   emlist = (int *) NULL;
31649   index =  marker = 0;
31650 
31651   faces = (4l * tetrahedrons->items + hullsize) / 2l;
31652   bmark = !b->nobound && in->facetmarkerlist;
31653 
31654   if (out == (tetgenio *) NULL) {
31655     outfile = fopen(facefilename, "w");
31656     if (outfile == (FILE *) NULL) {
31657       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31658       terminatetetgen(1);
31659     }
31660     fprintf(outfile, "%ld  %d\n", faces, bmark);
31661   } else {
31662     // Allocate memory for 'trifacelist'.
31663     out->trifacelist = new int[faces * 3];
31664     if (out->trifacelist == (int *) NULL) {
31665       printf("Error:  Out of memory.\n");
31666       terminatetetgen(1);
31667     }
31668     // Allocate memory for 'trifacemarkerlist' if necessary.
31669     if (bmark) {
31670       out->trifacemarkerlist = new int[faces];
31671       if (out->trifacemarkerlist == (int *) NULL) {
31672         printf("Error:  Out of memory.\n");
31673         terminatetetgen(1);
31674       }
31675     }
31676     if (b->neighout > 1) {
31677       // '-nn' switch.
31678       out->adjtetlist = new int[subfaces->items * 2];
31679       if (out->adjtetlist == (int *) NULL) {
31680         printf("Error:  Out of memory.\n");
31681         terminatetetgen(1);
31682       }
31683     }
31684     out->numberoftrifaces = faces;
31685     elist = out->trifacelist;
31686     emlist = out->trifacemarkerlist;
31687     index = 0;
31688   }
31689 
31690   // Determine the first index (0 or 1).
31691   firstindex = b->zeroindex ? 0 : in->firstnumber;
31692   shift = 0; // Default no shiftment.
31693   if ((in->firstnumber == 1) && (firstindex == 0)) {
31694     shift = 1; // Shift the output indices by 1.
31695   }
31696 
31697   tetrahedrons->traversalinit();
31698   tface.tet = tetrahedrontraverse();
31699   facenumber = firstindex; // in->firstnumber;
31700   // To loop over the set of faces, loop over all tetrahedra, and look at
31701   //   the four faces of each one. If there isn't another tetrahedron
31702   //   adjacent to this face, operate on the face.  If there is another
31703   //   adjacent tetrahedron, operate on the face only if the current
31704   //   tetrahedron has a smaller pointer than its neighbor.  This way, each
31705   //   face is considered only once.
31706   while (tface.tet != (tetrahedron *) NULL) {
31707     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31708       sym(tface, tsymface);
31709       if ((tsymface.tet == dummytet) || (tface.tet < tsymface.tet)) {
31710         torg = org(tface);
31711         tdest = dest(tface);
31712         tapex = apex(tface);
31713         if (bmark) {
31714           // Get the boundary marker of this face. If it is an inner face,
31715           //   it has no boundary marker, set it be zero.
31716           if (b->useshelles) {
31717             // Shell face is used.
31718             tspivot(tface, checkmark);
31719             if (checkmark.sh == dummysh) {
31720               marker = 0;  // It is an inner face.
31721             } else {
31722               faceid = shellmark(checkmark) - 1;
31723               marker = in->facetmarkerlist[faceid];
31724             }
31725           } else {
31726             // Shell face is not used, only distinguish outer and inner face.
31727             marker = tsymface.tet != dummytet ? 1 : 0;
31728           }
31729         }
31730         if (b->neighout > 1) {
31731           // '-nn' switch. Output adjacent tets indices.
31732           neigh1 = * (int *)(tface.tet + elemmarkerindex);
31733           if (tsymface.tet != dummytet) {
31734             neigh2 = * (int *)(tsymface.tet + elemmarkerindex);
31735           } else {
31736             neigh2 = -1;  
31737           }
31738         }
31739         if (out == (tetgenio *) NULL) {
31740           // Face number, indices of three vertices.
31741           fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
31742                   pointmark(torg) - shift, pointmark(tdest) - shift,
31743                   pointmark(tapex) - shift);
31744           if (bmark) {
31745             // Output a boundary marker.
31746             fprintf(outfile, "  %d", marker);
31747           }
31748           if (b->neighout > 1) {
31749             fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
31750           }
31751           fprintf(outfile, "\n");
31752         } else {
31753           // Output indices of three vertices.
31754           elist[index++] = pointmark(torg) - shift;
31755           elist[index++] = pointmark(tdest) - shift;
31756           elist[index++] = pointmark(tapex) - shift;
31757           if (bmark) {
31758             emlist[facenumber - in->firstnumber] = marker;
31759           }
31760           if (b->neighout > 1) {
31761             out->adjtetlist[(facenumber - in->firstnumber) * 2]     = neigh1;
31762             out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
31763           }
31764         }
31765         facenumber++;
31766       }
31767     }
31768     tface.tet = tetrahedrontraverse();
31769   }
31770 
31771   if (out == (tetgenio *) NULL) {
31772     fprintf(outfile, "# Generated by %s\n", b->commandline);
31773     fclose(outfile);
31774   }
31775 }
31776 
31778 //                                                                           //
31779 // outhullfaces()    Output outer boundary faces to a .face file or a        //
31780 //                   tetgenio structure.                                     //
31781 //                                                                           //
31782 // The normal of each face is arranged to point inside of the domain (use    //
31783 // right-hand rule).  This routines will outputs convex hull faces if the    //
31784 // mesh is a Delaunay tetrahedralization.                                    //
31785 //                                                                           //
31787 
31788 void tetgenmesh::outhullfaces(tetgenio* out)
31789 {
31790   FILE *outfile;
31791   char facefilename[FILENAMESIZE];
31792   int *elist;
31793   int index;
31794   triface tface, tsymface;
31795   face checkmark;
31796   point torg, tdest, tapex;
31797   int firstindex, shift;
31798   int facenumber;
31799 
31800   if (out == (tetgenio *) NULL) {
31801     strcpy(facefilename, b->outfilename);
31802     strcat(facefilename, ".face");
31803   }
31804 
31805   if (!b->quiet) {
31806     if (out == (tetgenio *) NULL) {
31807       printf("Writing %s.\n", facefilename);
31808     } else {
31809       printf("Writing faces.\n");
31810     }
31811   }
31812 
31813   // Avoid compile warnings.
31814   outfile = (FILE *) NULL;
31815   elist = (int *) NULL;
31816   index = 0;
31817 
31818   if (out == (tetgenio *) NULL) {
31819     outfile = fopen(facefilename, "w");
31820     if (outfile == (FILE *) NULL) {
31821       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31822       terminatetetgen(1);
31823     }
31824     fprintf(outfile, "%ld  0\n", hullsize);
31825   } else {
31826     // Allocate memory for 'trifacelist'.
31827     out->trifacelist = new int[hullsize * 3];
31828     if (out->trifacelist == (int *) NULL) {
31829       printf("Error:  Out of memory.\n");
31830       terminatetetgen(1);
31831     }
31832     out->numberoftrifaces = hullsize;
31833     elist = out->trifacelist;
31834     index = 0;
31835   }
31836 
31837   // Determine the first index (0 or 1).
31838   firstindex = b->zeroindex ? 0 : in->firstnumber;
31839   shift = 0; // Default no shiftment.
31840   if ((in->firstnumber == 1) && (firstindex == 0)) {
31841     shift = 1; // Shift the output indices by 1.
31842   }
31843 
31844   tetrahedrons->traversalinit();
31845   tface.tet = tetrahedrontraverse();
31846   facenumber = firstindex; // in->firstnumber;
31847   // To loop over the set of hull faces, loop over all tetrahedra, and look
31848   //   at the four faces of each one. If there isn't another tetrahedron
31849   //   adjacent to this face, operate on the face.
31850   while (tface.tet != (tetrahedron *) NULL) {
31851     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31852       sym(tface, tsymface);
31853       if (tsymface.tet == dummytet) {
31854         torg = org(tface);
31855         tdest = dest(tface);
31856         tapex = apex(tface);
31857         if (out == (tetgenio *) NULL) {
31858           // Face number, indices of three vertices.
31859           fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
31860                   pointmark(torg) - shift, pointmark(tdest) - shift,
31861                   pointmark(tapex) - shift);
31862           fprintf(outfile, "\n");
31863         } else {
31864           // Output indices of three vertices.
31865           elist[index++] = pointmark(torg) - shift;
31866           elist[index++] = pointmark(tdest) - shift;
31867           elist[index++] = pointmark(tapex) - shift;
31868         }
31869         facenumber++;
31870       }
31871     }
31872     tface.tet = tetrahedrontraverse();
31873   }
31874 
31875   if (out == (tetgenio *) NULL) {
31876     fprintf(outfile, "# Generated by %s\n", b->commandline);
31877     fclose(outfile);
31878   }
31879 }
31880 
31882 //                                                                           //
31883 // outsubfaces()    Output subfaces (i.e. boundary faces) to a .face file or //
31884 //                  a tetgenio structure.                                    //
31885 //                                                                           //
31886 // The boundary faces are exist in 'subfaces'. For listing triangle vertices //
31887 // in the same sense for all triangles in the mesh, the direction determined //
31888 // by right-hand rule is pointer to the inside of the volume.                //
31889 //                                                                           //
31891 
31892 void tetgenmesh::outsubfaces(tetgenio* out)
31893 {
31894   FILE *outfile;
31895   char facefilename[FILENAMESIZE];
31896   int *elist;
31897   int *emlist;
31898   int index, index1, index2;
31899   triface abuttingtet;
31900   face faceloop;
31901   point torg, tdest, tapex;
31902   int bmark, faceid, marker;
31903   int firstindex, shift;
31904   int neigh1, neigh2;
31905   int facenumber;
31906 
31907   if (out == (tetgenio *) NULL) {
31908     strcpy(facefilename, b->outfilename);
31909     strcat(facefilename, ".face");
31910   }
31911 
31912   if (!b->quiet) {
31913     if (out == (tetgenio *) NULL) {
31914       printf("Writing %s.\n", facefilename);
31915     } else {
31916       printf("Writing faces.\n");
31917     }
31918   }
31919 
31920   // Avoid compile warnings.
31921   outfile = (FILE *) NULL;
31922   elist = (int *) NULL;
31923   emlist = (int *) NULL;
31924   index = index1 = index2 = 0;
31925   faceid = marker = 0;
31926   neigh1 = neigh2 = 0;
31927 
31928   bmark = !b->nobound && in->facetmarkerlist;
31929 
31930   if (out == (tetgenio *) NULL) {
31931     outfile = fopen(facefilename, "w");
31932     if (outfile == (FILE *) NULL) {
31933       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31934       terminatetetgen(1);
31935     }
31936     // Number of subfaces.
31937     fprintf(outfile, "%ld  %d\n", subfaces->items, bmark);
31938   } else {
31939     // Allocate memory for 'trifacelist'.
31940     out->trifacelist = new int[subfaces->items * 3];
31941     if (out->trifacelist == (int *) NULL) {
31942       printf("Error:  Out of memory.\n");
31943       terminatetetgen(1);
31944     }
31945     if (bmark) {
31946       // Allocate memory for 'trifacemarkerlist'.
31947       out->trifacemarkerlist = new int[subfaces->items];
31948       if (out->trifacemarkerlist == (int *) NULL) {
31949         printf("Error:  Out of memory.\n");
31950         terminatetetgen(1);
31951       }
31952     }
31953     if (b->neighout > 1) {
31954       // '-nn' switch.
31955       out->adjtetlist = new int[subfaces->items * 2];
31956       if (out->adjtetlist == (int *) NULL) {
31957         printf("Error:  Out of memory.\n");
31958         terminatetetgen(1);
31959       }
31960     }
31961     out->numberoftrifaces = subfaces->items;
31962     elist = out->trifacelist;
31963     emlist = out->trifacemarkerlist;
31964   }
31965 
31966   // Determine the first index (0 or 1).
31967   firstindex = b->zeroindex ? 0 : in->firstnumber;
31968   shift = 0; // Default no shiftment.
31969   if ((in->firstnumber == 1) && (firstindex == 0)) {
31970     shift = 1; // Shift the output indices by 1.
31971   }
31972 
31973   subfaces->traversalinit();
31974   faceloop.sh = shellfacetraverse(subfaces);
31975   facenumber = firstindex; // in->firstnumber;
31976   while (faceloop.sh != (shellface *) NULL) {
31977     stpivot(faceloop, abuttingtet);
31978     if (abuttingtet.tet == dummytet) {
31979       sesymself(faceloop);
31980       stpivot(faceloop, abuttingtet);
31981     }
31982     if (abuttingtet.tet != dummytet) {
31983       // If there is a tetrahedron containing this subface, orient it so
31984       //   that the normal of this face points to inside of the volume by
31985       //   right-hand rule.
31986       adjustedgering(abuttingtet, CCW);
31987       torg = org(abuttingtet);
31988       tdest = dest(abuttingtet);
31989       tapex = apex(abuttingtet);
31990     } else {
31991       // This may happen when only a surface mesh be generated.
31992       torg = sorg(faceloop);
31993       tdest = sdest(faceloop);
31994       tapex = sapex(faceloop);
31995     }
31996     if (bmark) {
31997       faceid = shellmark(faceloop) - 1;
31998       marker = in->facetmarkerlist[faceid];
31999     }
32000     if (b->neighout > 1) {
32001       // '-nn' switch. Output adjacent tets indices.
32002       neigh1 = -1;
32003       stpivot(faceloop, abuttingtet);
32004       if (abuttingtet.tet != dummytet) {
32005         neigh1 = * (int *)(abuttingtet.tet + elemmarkerindex);
32006       }
32007       neigh2 = -1;
32008       sesymself(faceloop);
32009       stpivot(faceloop, abuttingtet);
32010       if (abuttingtet.tet != dummytet) {
32011         neigh2 = * (int *)(abuttingtet.tet + elemmarkerindex);
32012       }
32013     }
32014     if (out == (tetgenio *) NULL) {
32015       fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
32016               pointmark(torg) - shift, pointmark(tdest) - shift,
32017               pointmark(tapex) - shift);
32018       if (bmark) {
32019         fprintf(outfile, "    %d", marker);
32020       }
32021       if (b->neighout > 1) {
32022         fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
32023       }
32024       fprintf(outfile, "\n");
32025     } else {
32026       // Output three vertices of this face;
32027       elist[index++] = pointmark(torg) - shift;
32028       elist[index++] = pointmark(tdest) - shift;
32029       elist[index++] = pointmark(tapex) - shift;
32030       if (bmark) {
32031         emlist[index1++] = marker;
32032       }
32033       if (b->neighout > 1) {
32034         out->adjtetlist[index2++] = neigh1;
32035         out->adjtetlist[index2++] = neigh2;
32036       }
32037     }
32038     facenumber++;
32039     faceloop.sh = shellfacetraverse(subfaces);
32040   }
32041 
32042   if (out == (tetgenio *) NULL) {
32043     fprintf(outfile, "# Generated by %s\n", b->commandline);
32044     fclose(outfile);
32045   }
32046 }
32047 
32049 //                                                                           //
32050 // outedges()    Output all edges to a .edge file or a structure.            //
32051 //                                                                           //
32053 
32054 void tetgenmesh::outedges(tetgenio* out)
32055 {
32056   FILE *outfile;
32057   char edgefilename[FILENAMESIZE];
32058   int *elist, *emlist;
32059   int index, index1;
32060   triface tetloop, worktet, spintet;
32061   face checksh;
32062   point torg, tdest;
32063   long faces, edges;
32064   int firstindex, shift;
32065   int edgenumber, faceid, marker;
32066   int hitbdry, i;
32067 
32068   if (out == (tetgenio *) NULL) {
32069     strcpy(edgefilename, b->outfilename);
32070     strcat(edgefilename, ".edge");
32071   }
32072 
32073   if (!b->quiet) {
32074     if (out == (tetgenio *) NULL) {
32075       printf("Writing %s.\n", edgefilename);
32076     } else {
32077       printf("Writing edges.\n");
32078     }
32079   }
32080 
32081   // Avoid compile warnings.
32082   outfile = (FILE *) NULL;
32083   elist = (int *) NULL;
32084   emlist = (int *) NULL;
32085   index = index1 = 0;
32086   faceid = marker = 0;
32087 
32088   // Using the Euler formula (V-E+F-T=1) to get the total number of edges.
32089   faces = (4l * tetrahedrons->items + hullsize) / 2l;
32090   edges = points->items + faces - tetrahedrons->items - 1l;
32091 
32092   if (out == (tetgenio *) NULL) {
32093     outfile = fopen(edgefilename, "w");
32094     if (outfile == (FILE *) NULL) {
32095       printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
32096       terminatetetgen(1);
32097     }
32098     // Write the number of edges, boundary markers (0 or 1).
32099     fprintf(outfile, "%ld  %d\n", edges, !b->nobound);
32100   } else {
32101     // Allocate memory for 'edgelist'.
32102     out->edgelist = new int[edges * 2];
32103     if (out->edgelist == (int *) NULL) {
32104       printf("Error:  Out of memory.\n");
32105       terminatetetgen(1);
32106     }
32107     if (!b->nobound) {
32108       out->edgemarkerlist = new int[edges];
32109     }
32110     out->numberofedges = edges;
32111     elist = out->edgelist;
32112     emlist = out->edgemarkerlist;
32113   }
32114 
32115   // Determine the first index (0 or 1).
32116   firstindex = b->zeroindex ? 0 : in->firstnumber;
32117   shift = 0; // Default no shiftment.
32118   if ((in->firstnumber == 1) && (firstindex == 0)) {
32119     shift = 1; // Shift (reduce) the output indices by 1.
32120   }
32121 
32122   tetrahedrons->traversalinit();
32123   tetloop.tet = tetrahedrontraverse();
32124   edgenumber = firstindex; // in->firstnumber;
32125   while (tetloop.tet != (tetrahedron *) NULL) {
32126     // Count the number of Voronoi faces. Look at the six edges of each
32127     //   tetrahedron. Count the edge only if the tetrahedron's pointer is
32128     //   smaller than those of all other tetrahedra that share the edge.
32129     worktet.tet = tetloop.tet;
32130     for (i = 0; i < 6; i++) {
32131       worktet.loc = edge2locver[i][0];
32132       worktet.ver = edge2locver[i][1];
32133       adjustedgering(worktet, CW);
32134       spintet = worktet;
32135       hitbdry = 0;
32136       while (hitbdry < 2) {
32137         if (fnextself(spintet)) {
32138           if (apex(spintet) == apex(worktet)) break;
32139           if (spintet.tet < worktet.tet) break;
32140         } else {
32141           hitbdry++;
32142           if (hitbdry < 2) {
32143             esym(worktet, spintet);
32144             fnextself(spintet); // In the same tet.
32145       }
32146         }
32147       }
32148       // Count this edge if no adjacent tets are smaller than this tet.
32149       if (spintet.tet >= worktet.tet) {
32150         torg = org(worktet);
32151         tdest = dest(worktet);
32152         if (out == (tetgenio *) NULL) {
32153           fprintf(outfile, "%5d   %4d  %4d", edgenumber,
32154                   pointmark(torg) - shift, pointmark(tdest) - shift);
32155         } else {
32156           // Output three vertices of this face;
32157           elist[index++] = pointmark(torg) - shift;
32158           elist[index++] = pointmark(tdest) - shift;
32159         }
32160         if (!b->nobound) {
32161           if (hitbdry > 0) {
32162             // It is a boundary edge. Get the boundary marker of the facet
32163             //   containing this edge. Note there may have more than one
32164             //   facet, choose one arbitrarily.
32165             if ((b->plc || b->refine) && in->facetmarkerlist) {
32166               tspivot(spintet, checksh);
32167               faceid = shellmark(checksh) - 1;
32168               marker = in->facetmarkerlist[faceid];
32169             } else {
32170               marker = 1;  // Indicate it's a boundary edge.
32171             }
32172           } else {
32173             marker = 0;
32174           }
32175           if (out == (tetgenio *) NULL) {
32176             fprintf(outfile, "  %d", marker);
32177           } else {
32178             emlist[index1++] = marker;
32179           }
32180         }
32181         if (out == (tetgenio *) NULL) {
32182           fprintf(outfile, "\n");
32183         }
32184         edgenumber++;
32185       }
32186     }
32187     tetloop.tet = tetrahedrontraverse();
32188   }
32189 
32190   if (out == (tetgenio *) NULL) {
32191     fprintf(outfile, "# Generated by %s\n", b->commandline);
32192     fclose(outfile);
32193   }
32194 }
32195 
32197 //                                                                           //
32198 // outsubsegments()    Output segments to a .edge file or a structure.       //
32199 //                                                                           //
32201 
32202 void tetgenmesh::outsubsegments(tetgenio* out)
32203 {
32204   FILE *outfile;
32205   char edgefilename[FILENAMESIZE];
32206   int *elist;
32207   int index;
32208   face edgeloop;
32209   point torg, tdest;
32210   int firstindex, shift;
32211   int edgenumber;
32212 
32213   if (out == (tetgenio *) NULL) {
32214     strcpy(edgefilename, b->outfilename);
32215     strcat(edgefilename, ".edge");
32216   }
32217 
32218   if (!b->quiet) {
32219     if (out == (tetgenio *) NULL) {
32220       printf("Writing %s.\n", edgefilename);
32221     } else {
32222       printf("Writing edges.\n");
32223     }
32224   }
32225 
32226   // Avoid compile warnings.
32227   outfile = (FILE *) NULL;
32228   elist = (int *) NULL;
32229   index = 0;  
32230 
32231   if (out == (tetgenio *) NULL) {
32232     outfile = fopen(edgefilename, "w");
32233     if (outfile == (FILE *) NULL) {
32234       printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
32235       terminatetetgen(1);
32236     }
32237     // Number of subsegments.
32238     fprintf(outfile, "%ld\n", subsegs->items);
32239   } else {
32240     // Allocate memory for 'edgelist'.
32241     out->edgelist = new int[subsegs->items * 2];
32242     if (out->edgelist == (int *) NULL) {
32243       printf("Error:  Out of memory.\n");
32244       terminatetetgen(1);
32245     }
32246     out->numberofedges = subsegs->items;
32247     elist = out->edgelist;
32248   }
32249 
32250   // Determine the first index (0 or 1).
32251   firstindex = b->zeroindex ? 0 : in->firstnumber;
32252   shift = 0; // Default no shiftment.
32253   if ((in->firstnumber == 1) && (firstindex == 0)) {
32254     shift = 1; // Shift the output indices by 1.
32255   }
32256 
32257   subsegs->traversalinit();
32258   edgeloop.sh = shellfacetraverse(subsegs);
32259   edgenumber = firstindex; // in->firstnumber;
32260   while (edgeloop.sh != (shellface *) NULL) {
32261     torg = sorg(edgeloop);
32262     tdest = sdest(edgeloop);
32263     if (out == (tetgenio *) NULL) {
32264       fprintf(outfile, "%5d   %4d  %4d\n", edgenumber,
32265               pointmark(torg) - shift, pointmark(tdest) - shift);
32266     } else {
32267       // Output three vertices of this face;
32268       elist[index++] = pointmark(torg) - shift;
32269       elist[index++] = pointmark(tdest) - shift;
32270     }
32271     edgenumber++;
32272     edgeloop.sh = shellfacetraverse(subsegs);
32273   }
32274 
32275   if (out == (tetgenio *) NULL) {
32276     fprintf(outfile, "# Generated by %s\n", b->commandline);
32277     fclose(outfile);
32278   }
32279 }
32280 
32282 //                                                                           //
32283 // outneighbors()    Output tet neighbors to a .neigh file or a structure.   //
32284 //                                                                           //
32286 
32287 void tetgenmesh::outneighbors(tetgenio* out)
32288 {
32289   FILE *outfile;
32290   char neighborfilename[FILENAMESIZE];
32291   int *nlist;
32292   int index;
32293   triface tetloop, tetsym;
32294   int neighbor1, neighbor2, neighbor3, neighbor4;
32295   int firstindex;
32296   int elementnumber;
32297 
32298   if (out == (tetgenio *) NULL) {
32299     strcpy(neighborfilename, b->outfilename);
32300     strcat(neighborfilename, ".neigh");
32301   }
32302 
32303   if (!b->quiet) {
32304     if (out == (tetgenio *) NULL) {
32305       printf("Writing %s.\n", neighborfilename);
32306     } else {
32307       printf("Writing neighbors.\n");
32308     }
32309   }
32310 
32311   // Avoid compile warnings.
32312   outfile = (FILE *) NULL;
32313   nlist = (int *) NULL;
32314   index = 0;
32315 
32316   if (out == (tetgenio *) NULL) {
32317     outfile = fopen(neighborfilename, "w");
32318     if (outfile == (FILE *) NULL) {
32319       printf("File I/O Error:  Cannot create file %s.\n", neighborfilename);
32320       terminatetetgen(1);
32321     }
32322     // Number of tetrahedra, four faces per tetrahedron.
32323     fprintf(outfile, "%ld  %d\n", tetrahedrons->items, 4);
32324   } else {
32325     // Allocate memory for 'neighborlist'.
32326     out->neighborlist = new int[tetrahedrons->items * 4];
32327     if (out->neighborlist == (int *) NULL) {
32328       printf("Error:  Out of memory.\n");
32329       terminatetetgen(1);
32330     }
32331     nlist = out->neighborlist;
32332   }
32333 
32334   // Determine the first index (0 or 1).
32335   firstindex = b->zeroindex ? 0 : in->firstnumber;
32336 
32337   tetrahedrons->traversalinit();
32338   tetloop.tet = tetrahedrontraverse();
32339   elementnumber = firstindex; // in->firstnumber;
32340   while (tetloop.tet != (tetrahedron *) NULL) {
32341     tetloop.loc = 2;
32342     sym(tetloop, tetsym);
32343     neighbor1 = * (int *) (tetsym.tet + elemmarkerindex);
32344     tetloop.loc = 3;
32345     sym(tetloop, tetsym);
32346     neighbor2 = * (int *) (tetsym.tet + elemmarkerindex);
32347     tetloop.loc = 1;
32348     sym(tetloop, tetsym);
32349     neighbor3 = * (int *) (tetsym.tet + elemmarkerindex);
32350     tetloop.loc = 0;
32351     sym(tetloop, tetsym);
32352     neighbor4 = * (int *) (tetsym.tet + elemmarkerindex);
32353     if (out == (tetgenio *) NULL) {
32354       // Tetrahedra number, neighboring tetrahedron numbers.
32355       fprintf(outfile, "%4d    %4d  %4d  %4d  %4d\n", elementnumber,
32356               neighbor1, neighbor2, neighbor3, neighbor4);
32357     } else {
32358       nlist[index++] = neighbor1;
32359       nlist[index++] = neighbor2;
32360       nlist[index++] = neighbor3;
32361       nlist[index++] = neighbor4;
32362     }
32363     tetloop.tet = tetrahedrontraverse();
32364     elementnumber++;
32365   }
32366 
32367   if (out == (tetgenio *) NULL) {
32368     fprintf(outfile, "# Generated by %s\n", b->commandline);
32369     fclose(outfile);
32370   }
32371 }
32372 
32374 //                                                                           //
32375 // outvoronoi()    Output the Voronoi diagram to .v.node, .v.edge, v.face,   //
32376 //                 and .v.cell.                                              //
32377 //                                                                           //
32378 // The Voronoi diagram is the geometric dual of the Delaunay triangulation.  //
32379 // The Voronoi vertices are the circumcenters of Delaunay tetrahedra.  Each  //
32380 // Voronoi edge connects two Voronoi vertices at two sides of a common Dela- //
32381 // unay face. At a face of convex hull, it becomes a ray (goto the infinity).//
32382 // A Voronoi face is the convex hull of all Voronoi vertices around a common //
32383 // Delaunay edge. It is a closed polygon for any interal Delaunay edge. At a //
32384 // ridge, it is unbounded.  Each Voronoi cell is the convex hull of all Vor- //
32385 // onoi vertices around a common Delaunay vertex. It is a polytope for any   //
32386 // internal Delaunay vertex. It is an unbounded polyhedron for a Delaunay    //
32387 // vertex belonging to the convex hull.                                      //
32388 //                                                                           //
32390 
32391 void tetgenmesh::outvoronoi(tetgenio* out)
32392 {
32393   FILE *outfile;
32394   char outfilename[FILENAMESIZE];
32395   tetgenio::voroedge *vedge;
32396   tetgenio::vorofacet *vfacet;
32397   list *tetlist, *ptlist;
32398   triface tetloop, worktet, spintet;
32399   point pt[4], ptloop, neipt;
32400   REAL ccent[3], infvec[3], vec1[3], vec2[3], L;
32401   long faces, edges;
32402   int *tetfaceindexarray, *tetedgeindexarray;
32403   int arraysize, *vertarray;
32404   int vpointcount, vedgecount, vfacecount, tcount;
32405   int index, shift;
32406   int end1, end2;
32407   int hitbdry, i, j, k;
32408 
32409   vedge = NULL;
32410   vertarray = NULL;
32411   vfacet = NULL;
32412   k = 0;
32413   
32414   // Output Voronoi vertices to .v.node file.
32415   if (out == (tetgenio *) NULL) {
32416     strcpy(outfilename, b->outfilename);
32417     strcat(outfilename, ".v.node");
32418   }
32419 
32420   if (!b->quiet) {
32421     if (out == (tetgenio *) NULL) {
32422       printf("Writing %s.\n", outfilename);
32423     } else {
32424       printf("Writing Voronoi vertices.\n");
32425     }
32426   }
32427 
32428   // Determine the first index (0 or 1).
32429   shift = (b->zeroindex ? 0 : in->firstnumber);
32430   // The number of Delaunay faces (= the number of Voronoi edges).
32431   faces = (4l * tetrahedrons->items + hullsize) / 2l;
32432   // The number of Delaunay edges (= the number of Voronoi faces).
32433   edges = points->items + faces - tetrahedrons->items - 1;
32434   outfile = (FILE *) NULL; // Avoid compile warnings.
32435 
32436   if (out == (tetgenio *) NULL) {
32437     outfile = fopen(outfilename, "w");
32438     if (outfile == (FILE *) NULL) {
32439       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32440       terminatetetgen(1);
32441     }
32442     // Number of voronoi points, 3 dim, no attributes, no marker.
32443     fprintf(outfile, "%ld  3  0  0\n", tetrahedrons->items);
32444   } else {
32445     // Allocate space for 'vpointlist'.
32446     out->numberofvpoints = (int) tetrahedrons->items;
32447     out->vpointlist = new REAL[out->numberofvpoints * 3];
32448     if (out->vpointlist == (REAL *) NULL) {
32449       printf("Error:  Out of memory.\n");
32450       terminatetetgen(1);
32451     }
32452   }
32453 
32454   // Loop the tetrahedronlist once, do the following: 
32455   //   (1) Output Voronoi vertices (the circumcenter of the tetrahedron).
32456   //   (2) Make a map from points-to-tetrahedra (for Voronoi cells).
32457   tetrahedrons->traversalinit();
32458   tetloop.tet = tetrahedrontraverse();
32459   vpointcount = 0;
32460   index = 0;
32461   while (tetloop.tet != (tetrahedron *) NULL) {
32462     // Calculate the circumcenter.
32463     for (i = 0; i < 4; i++) {
32464       pt[i] = (point) tetloop.tet[4 + i];
32465       setpoint2tet(pt[i], encode(tetloop));
32466     }
32467     circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
32468     if (out == (tetgenio *) NULL) {
32469       fprintf(outfile, "%4d  %16.8e %16.8e %16.8e\n", vpointcount + shift,
32470               ccent[0], ccent[1], ccent[2]);
32471     } else {
32472       out->vpointlist[index++] = ccent[0];
32473       out->vpointlist[index++] = ccent[1];
32474       out->vpointlist[index++] = ccent[2];
32475     }
32476     // Remember the index of this element.
32477     * (int *) (tetloop.tet + elemmarkerindex) = vpointcount;
32478     vpointcount++;
32479     tetloop.tet = tetrahedrontraverse();
32480   }
32481   // Set the outside element marker.
32482   * (int *) (dummytet + elemmarkerindex) = -1;
32483 
32484   if (out == (tetgenio *) NULL) {
32485     fprintf(outfile, "# Generated by %s\n", b->commandline);
32486     fclose(outfile);
32487   }
32488 
32489   // Output Voronoi edges to .v.edge file.
32490   if (out == (tetgenio *) NULL) {
32491     strcpy(outfilename, b->outfilename);
32492     strcat(outfilename, ".v.edge");
32493   }
32494   
32495   if (!b->quiet) {
32496     if (out == (tetgenio *) NULL) {
32497       printf("Writing %s.\n", outfilename);
32498     } else {
32499       printf("Writing Voronoi edges.\n");
32500     }
32501   }
32502 
32503   if (out == (tetgenio *) NULL) {
32504     outfile = fopen(outfilename, "w");
32505     if (outfile == (FILE *) NULL) {
32506       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32507       terminatetetgen(1);
32508     }
32509     // Number of Voronoi edges, no marker.
32510     fprintf(outfile, "%ld  0\n", faces);
32511   } else {
32512     // Allocate space for 'vpointlist'.
32513     out->numberofedges = (int) faces;
32514     out->vedgelist = new tetgenio::voroedge[out->numberofvedges];
32515   }
32516 
32517   // Loop the tetrahedronlist once, output the Voronoi edges. The index of
32518   //   each Voronoi edge corresponding to the index of the Delaunay face.
32519   //   The four faces' indices of each tetrahedron are saved in the list
32520   //   'tetfaceindexarray', in the entry of i,  where i (0-based) is the
32521   //   index of this tetrahedron (= vpointcount). 
32522   tetfaceindexarray = new int[tetrahedrons->items * 4];  
32523   tetrahedrons->traversalinit();
32524   tetloop.tet = tetrahedrontraverse();
32525   vedgecount = 0;
32526   index = 0;
32527   while (tetloop.tet != (tetrahedron *) NULL) {
32528     // Count the number of Voronoi edges. Look at the four faces of each
32529     //   tetrahedron. Count the face if the tetrahedron's pointer is
32530     //   smaller than its neighbor's or the neighbor is outside.
32531     end1 = * (int *) (tetloop.tet + elemmarkerindex);
32532     for (i = 0; i < 4; i++) {
32533       decode(tetloop.tet[i], worktet);
32534       if ((worktet.tet == dummytet) || (tetloop.tet < worktet.tet)) {
32535         if (out == (tetgenio *) NULL) {
32536           fprintf(outfile, "%4d  %4d", vedgecount + shift, end1 + shift);
32537         } else {
32538           vedge = &(out->vedgelist[index++]);
32539           vedge->v1 = end1 + shift;
32540         }
32541         end2 = * (int *) (worktet.tet + elemmarkerindex);
32542         // Note that end2 may be -1 (worktet.tet is outside).
32543         if (end2 == -1) {
32544           // Calculate the out normal of this hull face.
32545           worktet.tet = tetloop.tet;
32546           worktet.loc = i;
32547           worktet.ver = 1; // The CW edge ring.
32548           pt[0] = org(worktet);
32549           pt[1] = dest(worktet);
32550           pt[2] = apex(worktet);
32551           for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j];
32552           for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j];
32553           cross(vec1, vec2, infvec);
32554           // Normalize it.
32555           L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1]
32556                    + infvec[2] * infvec[2]);
32557           if (L > 0) for (j = 0; j < 3; j++) infvec[j] /= L;
32558           if (out == (tetgenio *) NULL) {
32559             fprintf(outfile, " -1");
32560             fprintf(outfile, " %g %g %g\n", infvec[0], infvec[1], infvec[2]);
32561           } else {
32562             vedge->v2 = -1;
32563             vedge->vnormal[0] = infvec[0];
32564             vedge->vnormal[1] = infvec[1];
32565             vedge->vnormal[2] = infvec[2];
32566           }
32567         } else {
32568           if (out == (tetgenio *) NULL) {
32569             fprintf(outfile, " %4d\n", end2 + shift);
32570           } else {
32571             vedge->v2 = end2 + shift;
32572             vedge->vnormal[0] = 0.0;
32573             vedge->vnormal[1] = 0.0;
32574             vedge->vnormal[2] = 0.0;
32575           }
32576         }
32577         // Save the face index in this tet and its neighbor if exists.
32578         tetfaceindexarray[end1 * 4 + i] = vedgecount;
32579         if (end2 != -1) {
32580           tetfaceindexarray[end2 * 4 + worktet.loc] = vedgecount;
32581         }
32582         vedgecount++;
32583       }
32584     }
32585     tetloop.tet = tetrahedrontraverse();
32586   }
32587 
32588   if (out == (tetgenio *) NULL) {
32589     fprintf(outfile, "# Generated by %s\n", b->commandline);
32590     fclose(outfile);
32591   }
32592 
32593   // Output Voronoi faces to .v.face file.
32594   if (out == (tetgenio *) NULL) {
32595     strcpy(outfilename, b->outfilename);
32596     strcat(outfilename, ".v.face");
32597   }
32598   
32599   if (!b->quiet) {
32600     if (out == (tetgenio *) NULL) {
32601       printf("Writing %s.\n", outfilename);
32602     } else {
32603       printf("Writing Voronoi faces.\n");
32604     }
32605   }
32606 
32607   if (out == (tetgenio *) NULL) {
32608     outfile = fopen(outfilename, "w");
32609     if (outfile == (FILE *) NULL) {
32610       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32611       terminatetetgen(1);
32612     }
32613     // Number of Voronoi faces.
32614     fprintf(outfile, "%ld  0\n", edges);
32615   } else {
32616     out->numberofvfacets = edges;
32617     out->vfacetlist = new tetgenio::vorofacet[out->numberofvfacets];
32618     if (out->vfacetlist == (tetgenio::vorofacet *) NULL) {
32619       printf("Error:  Out of memory.\n");
32620       terminatetetgen(1);
32621     }
32622   }
32623 
32624   // Loop the tetrahedronlist once, Output Voronoi facets. The index of each
32625   //   Voronoi facet corresponding to the index of the Delaunay edge.  The
32626   //   six edges' indices of each tetrahedron are saved in the list 'tetedge-
32627   //   indexarray', in the entry of i,  where i (0-based) is the index of
32628   //   this tetrahedron (= vpointcount). 
32629   tetedgeindexarray = new int[tetrahedrons->items * 6];
32630   tetrahedrons->traversalinit();
32631   tetloop.tet = tetrahedrontraverse();
32632   vfacecount = 0;
32633   while (tetloop.tet != (tetrahedron *) NULL) {
32634     // Count the number of Voronoi faces. Look at the six edges of each
32635     //   tetrahedron. Count the edge only if the tetrahedron's pointer is
32636     //   smaller than those of all other tetrahedra that share the edge.
32637     worktet = tetloop;
32638     for (i = 0; i < 6; i++) {
32639       worktet.loc = edge2locver[i][0];
32640       worktet.ver = edge2locver[i][1];
32641       // Now count the number of tets surrounding this edge.
32642       tcount = 1;
32643       adjustedgering(worktet, CW);
32644       spintet = worktet;
32645       hitbdry = 0;
32646       while (hitbdry < 2) {
32647         if (fnextself(spintet)) {
32648           if (apex(spintet) == apex(worktet)) break;
32649           if (spintet.tet < worktet.tet) break;
32650           tcount++;
32651         } else {
32652           hitbdry++;
32653           if (hitbdry < 2) {
32654             esym(worktet, spintet);
32655             fnextself(spintet); // In the same tet.
32656       }
32657         }
32658       }
32659       // Count this edge if no adjacent tets are smaller than this tet.
32660       if (spintet.tet >= worktet.tet) {
32661         // Get the two endpoints of this edge.
32662         pt[0] = org(worktet);
32663         pt[1] = dest(worktet);
32664         end1 = pointmark(pt[0]) - in->firstnumber;
32665         end2 = pointmark(pt[1]) - in->firstnumber;
32666         if (out == (tetgenio *) NULL) {
32667           fprintf(outfile, "%4d  %4d %4d  %-2d ", vfacecount + shift, 
32668                   end1 + shift, end2 + shift, tcount + (hitbdry > 0));
32669         } else {
32670           vfacet = &(out->vfacetlist[vfacecount]);
32671           vfacet->c1 = end1 + shift;
32672           vfacet->c2 = end2 + shift;
32673           vfacet->elist = new int[tcount + (hitbdry > 0) + 1];
32674           vfacet->elist[0] = tcount + (hitbdry > 0);
32675           index = 1;
32676         }
32677         // If hitbdry > 0, then spintet is a hull face.
32678         if (hitbdry > 0) {
32679           // The edge list starts with a ray.
32680           vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32681           vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32682           if (out == (tetgenio *) NULL) {
32683             fprintf(outfile, " %d", vedgecount + shift);
32684           } else {
32685             vfacet->elist[index++] = vedgecount + shift;
32686           }
32687           // Save this facet number in tet.
32688           tetedgeindexarray[vpointcount * 6 + 
32689             locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32690           esymself(spintet);
32691           fnextself(spintet); // In the same tet.
32692         }
32693         // Output internal Voronoi edges.
32694         for (j = 0; j < tcount; j++) {
32695           vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32696           vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32697           if (out == (tetgenio *) NULL) {
32698             fprintf(outfile, " %d", vedgecount + shift);
32699           } else {
32700             vfacet->elist[index++] = vedgecount + shift;
32701           }
32702           // Save this facet number in tet.
32703           tetedgeindexarray[vpointcount * 6 + 
32704             locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32705           fnextself(spintet);
32706         }
32707         if (out == (tetgenio *) NULL) {
32708           fprintf(outfile, "\n");
32709         }
32710         vfacecount++;
32711       }
32712     } // if (i = 0; i < 6; i++)
32713     tetloop.tet = tetrahedrontraverse();
32714   }
32715 
32716   if (out == (tetgenio *) NULL) {
32717     fprintf(outfile, "# Generated by %s\n", b->commandline);
32718     fclose(outfile);
32719   }
32720 
32721   // Output Voronoi cells to .v.cell file.
32722   if (out == (tetgenio *) NULL) {
32723     strcpy(outfilename, b->outfilename);
32724     strcat(outfilename, ".v.cell");
32725   }
32726   
32727   if (!b->quiet) {
32728     if (out == (tetgenio *) NULL) {
32729       printf("Writing %s.\n", outfilename);
32730     } else {
32731       printf("Writing Voronoi cells.\n");
32732     }
32733   }
32734 
32735   if (out == (tetgenio *) NULL) {
32736     outfile = fopen(outfilename, "w");
32737     if (outfile == (FILE *) NULL) {
32738       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32739       terminatetetgen(1);
32740     }
32741     // Number of Voronoi cells.
32742     fprintf(outfile, "%ld\n", points->items);
32743   } else {
32744     out->numberofvcells = points->items;
32745     out->vcelllist = new int*[out->numberofvcells];
32746     if (out->vcelllist == (int **) NULL) {
32747       printf("Error:  Out of memory.\n");
32748       terminatetetgen(1);
32749     }
32750   }
32751 
32752   // Loop through point list, for each point, output a Voronoi cell.
32753   tetlist = new list(sizeof(triface), NULL, 256);
32754   ptlist = new list(sizeof(point *), NULL, 256);
32755   points->traversalinit();
32756   ptloop = pointtraverse();
32757   vpointcount = 0;
32758   while (ptloop != (point) NULL) {
32759     decode(point2tet(ptloop), tetloop);
32760     // assert(!isdead(&tetloop));
32761     if (!isdead(&tetloop)) {
32762       // Form the star of p.
32763       tetlist->append(&tetloop);
32764       formstarpolyhedron(ptloop, tetlist, ptlist, true);
32765       tcount = ptlist->len();
32766       if (out == (tetgenio *) NULL) {
32767         fprintf(outfile, "%4d  %-2d ", vpointcount + shift, tcount);
32768       } else {
32769         arraysize = tcount;
32770         vertarray = out->vcelllist[vpointcount];
32771         vertarray = new int[arraysize + 1];
32772         vertarray[0] = arraysize;
32773         index = 1;
32774       }
32775       // List Voronoi facets bounding this cell.
32776       for (i = 0; i < ptlist->len(); i++) {
32777         neipt =  * (point *)(* ptlist)[i];
32778         // Find a tet in tetlist having edge (ptloop, neipt) -- Very Slow.
32779         for (j = 0; j < tetlist->len(); j++) {
32780           tetloop = * (triface *)(* tetlist)[j];
32781           for (k = 0; k < 6; k++) {
32782             tetloop.loc = edge2locver[k][0];
32783             tetloop.ver = edge2locver[k][1];
32784             if (org(tetloop) == ptloop) {
32785               if (dest(tetloop) == neipt) break;
32786             } else if (org(tetloop) == neipt) {
32787               if (dest(tetloop) == ptloop) break;
32788             }
32789           }
32790           if (k < 6) break; // Found this edge.
32791         }
32792         assert(j < tetlist->len());
32793         // k is the right edge number.        
32794         end1 = * (int *) (tetloop.tet + elemmarkerindex);
32795         vfacecount = tetedgeindexarray[end1 * 6 + k];
32796         if (out == (tetgenio *) NULL) {
32797           fprintf(outfile, " %d", vfacecount + shift);
32798         } else {
32799           vertarray[index++] = vfacecount + shift;
32800         }
32801       } // for (i = 0; i < ptlist->len(); i++) {
32802       if (out == (tetgenio *) NULL) {
32803         fprintf(outfile, "\n");
32804       }
32805       vpointcount++;
32806     }
32807     tetlist->clear();
32808     ptlist->clear();
32809     ptloop = pointtraverse();
32810   }
32811   delete tetlist;
32812   delete ptlist;
32813   delete [] tetfaceindexarray;
32814   delete [] tetedgeindexarray;
32815 
32816   if (out == (tetgenio *) NULL) {
32817     fprintf(outfile, "# Generated by %s\n", b->commandline);
32818     fclose(outfile);
32819   }
32820 }
32821 
32823 //                                                                           //
32824 // outpbcnodes()    Output pbc node pairs to a .pbc file or a structure.     //
32825 //                                                                           //
32827 
32828 void tetgenmesh::outpbcnodes(tetgenio* out)
32829 { 
32830   FILE *outfile;
32831   char pbcfilename[FILENAMESIZE];
32832   list *ptpairlist;
32833   tetgenio::pbcgroup *pgi, *pgo;
32834   pbcdata *pd;
32835   face faceloop;
32836   face checkseg, symseg;
32837   point *ptpair, pa, pb;
32838   enum locateresult loc;
32839   REAL sympt[3], d1, d2;
32840   int *worklist;
32841   int firstindex, shift;
32842   int index, idx;
32843   int i, j, k, l;
32844 
32845   if (out == (tetgenio *) NULL) {
32846     strcpy(pbcfilename, b->outfilename);
32847     strcat(pbcfilename, ".pbc");
32848   }
32849 
32850   if (!b->quiet) {
32851     if (out == (tetgenio *) NULL) {
32852       printf("Writing %s.\n", pbcfilename);
32853     } else {
32854       printf("Writing pbc nodes.\n");
32855     }
32856   }
32857 
32858   // Avoid compilation warnings.
32859   outfile = (FILE *) NULL;
32860   pgo = (tetgenio::pbcgroup *) NULL;
32861   index = 0;
32862 
32863   if (out == (tetgenio *) NULL) {
32864     outfile = fopen(pbcfilename, "w");
32865     if (outfile == (FILE *) NULL) {
32866       printf("File I/O Error:  Cannot create file %s.\n", pbcfilename);
32867       terminatetetgen(1);
32868     }
32869     // Number of pbc groups.
32870     fprintf(outfile, "# number of PBCs.\n");
32871     fprintf(outfile, "%d\n\n", in->numberofpbcgroups);
32872   } else {
32873     out->numberofpbcgroups = in->numberofpbcgroups;
32874     // Allocate memory for 'out->pbcgrouplist'.
32875     out->pbcgrouplist = new tetgenio::pbcgroup[in->numberofpbcgroups];
32876     // (Next line was a bug, reported by Murry Nigel). 
32877     if (out->pbcgrouplist == (tetgenio::pbcgroup *) NULL) {
32878       printf("Error:  Out of memory.\n");
32879       terminatetetgen(1);
32880     }
32881   }
32882 
32883   ptpairlist = new list(2 * sizeof(point *), NULL, 256);
32884   worklist = new int[points->items + 1];
32885   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
32886 
32887   // Determine the first index (0 or 1).
32888   firstindex = b->zeroindex ? 0 : in->firstnumber;
32889   shift = 0; // Default no shiftment.
32890   if ((in->firstnumber == 1) && (firstindex == 0)) {
32891     shift = 1; // Shift the output indices by 1.
32892   }
32893 
32894   for (i = 0; i < in->numberofpbcgroups; i++) {
32895     // Group i.
32896     pgi = &(in->pbcgrouplist[i]);
32897     if (out == (tetgenio *) NULL) {
32898       fprintf(outfile, "# PBC %d\n", in->firstnumber + i);
32899       // Output facet markers.
32900       fprintf(outfile, "%d  %d\n", pgi->fmark1, pgi->fmark2);
32901       // Output transformation matrix.
32902       fprintf(outfile, "[\n");
32903       for (j = 0; j < 4; j++) {
32904         fprintf(outfile, "  %.12g %.12g %.12g %.12g\n", pgi->transmat[j][0],
32905                 pgi->transmat[j][1], pgi->transmat[j][2], pgi->transmat[j][3]);
32906       }
32907       fprintf(outfile, "]\n");
32908     } else {
32909       pgo = &(out->pbcgrouplist[i]);
32910       // Copy data from pgi to pgo.
32911       pgo->fmark1 = pgi->fmark1;
32912       pgo->fmark2 = pgi->fmark2;
32913       for (j = 0; j < 4; j++) {
32914         for (k = 0; k < 4; k++) pgo->transmat[j][k] = pgi->transmat[j][k];
32915       }
32916     }
32917 
32918     // Find the point pairs of group i.
32919     subfaces->traversalinit();
32920     faceloop.sh = shellfacetraverse(subfaces);
32921     while (faceloop.sh != (shellface *) NULL) {
32922       if (shellpbcgroup(faceloop) == i) {
32923         // It is in group i. Operate on it if it has pgi->fmark1.
32924         idx = shellmark(faceloop) - 1;
32925         if (in->facetmarkerlist[idx] == pgi->fmark1) {
32926           // Loop three edges of the subface.
32927           for (j = 0; j < 3; j++) {
32928             sspivot(faceloop, checkseg);
32929             // Loop two vertices of the edge.
32930             for (k = 0; k < 2; k++) {
32931               if (k == 0) pa = sorg(faceloop);
32932               else pa = sdest(faceloop);
32933               if (worklist[pointmark(pa)] == 0) {
32934                 pb = (point) NULL;
32935                 if (checkseg.sh != dummysh) {
32936                   // pa is on a segment. Find pb.
32937                   // Find the incident pbcgroup of checkseg.
32938                   idx = shellmark(checkseg) - 1;
32939                   for (l = idx2segpglist[idx]; l < idx2segpglist[idx + 1];
32940                        l++) {
32941                     pd = (pbcdata *)(* segpbcgrouptable)[segpglist[l]];
32942                     if (((pd->fmark[0] == pgi->fmark1) &&
32943                          (pd->fmark[1] == pgi->fmark2)) ||
32944                         ((pd->fmark[0] == pgi->fmark2) &&
32945                          (pd->fmark[1] == pgi->fmark1))) break;
32946                   }
32947 #ifdef SELF_CHECK
32948                   assert(l < idx2segpglist[idx + 1]);
32949 #endif
32950                   loc = getsegpbcsympoint(pa, &checkseg, sympt, &symseg,
32951                                           segpglist[l]);
32952                   if (loc != ONVERTEX) {
32953                     // Not found a match point! It may be caused by the
32954                     //   pair of input vertices don't have enough digits.
32955                     //   Choose a near vertex.
32956                     d1 = distance(sympt, sorg(symseg));
32957                     d2 = distance(sympt, sdest(symseg));
32958                     if (d1 > d2) sesymself(symseg);
32959                   }
32960                   pb = sorg(symseg);
32961                 } else {
32962                   // Operate on pa if it is inside the facet.
32963                   if (pointtype(pa) == FREESUBVERTEX) {
32964                     pb = point2pbcpt(pa);
32965                   }
32966                 }
32967                 if (pb != (point) NULL) {
32968                   // Add the pair (pa, pb) into list. 
32969                   ptpair = (point *) ptpairlist->append(NULL);
32970                   ptpair[0] = pa;
32971                   ptpair[1] = pb;
32972                   // Mark pa (avoid to operate on it later).
32973                   worklist[pointmark(pa)] = 1;
32974                 }
32975               }
32976             }
32977             // Get the next edge.
32978             senextself(faceloop);
32979           }
32980         }
32981       }
32982       faceloop.sh = shellfacetraverse(subfaces);
32983     }
32984 
32985     // Output the list of pbc points.
32986     if (out == (tetgenio *) NULL) {
32987       fprintf(outfile, "%d\n", ptpairlist->len());
32988     } else {
32989       pgo->numberofpointpairs = ptpairlist->len();
32990       pgo->pointpairlist = new int[pgo->numberofpointpairs * 2];
32991       index = 0;
32992     }
32993     for (j = 0; j < ptpairlist->len(); j++) {
32994       ptpair = (point *)(* ptpairlist)[j];
32995       pa = ptpair[0];
32996       pb = ptpair[1];
32997       if (out == (tetgenio *) NULL) {
32998         fprintf(outfile, "  %4d %4d\n", pointmark(pa) - shift,
32999                 pointmark(pb) - shift);
33000       } else {
33001         pgo->pointpairlist[index++] = pointmark(pa) - shift;
33002         pgo->pointpairlist[index++] = pointmark(pb) - shift;
33003       }
33004       // Unmark pa.
33005       worklist[pointmark(pa)] = 0;
33006     }
33007     if (out == (tetgenio *) NULL) {
33008       fprintf(outfile, "\n");
33009     }
33010     ptpairlist->clear();
33011   }
33012 
33013   delete [] worklist;
33014   delete ptpairlist;
33015 
33016   if (out == (tetgenio *) NULL) {
33017     fprintf(outfile, "# Generated by %s\n", b->commandline);
33018     fclose(outfile);
33019   }
33020 }
33021 
33023 //                                                                           //
33024 // outsmesh()    Write surface mesh to a .smesh file, which can be read and  //
33025 //               tetrahedralized by TetGen.                                  //
33026 //                                                                           //
33027 // You can specify a filename (without suffix) in 'smfilename'. If you don't //
33028 // supply a filename (let smfilename be NULL), the default name stored in    //
33029 // 'tetgenbehavior' will be used.                                            //
33030 //                                                                           //
33032 
33033 void tetgenmesh::outsmesh(char* smfilename)
33034 {
33035   FILE *outfile;
33036   char nodfilename[FILENAMESIZE];
33037   char smefilename[FILENAMESIZE];
33038   face faceloop;
33039   point p1, p2, p3;
33040   int firstindex, shift;
33041   int bmark;
33042   int faceid, marker;
33043   int i;
33044 
33045   if (smfilename != (char *) NULL && smfilename[0] != '\0') {
33046     strcpy(smefilename, smfilename);
33047   } else if (b->outfilename[0] != '\0') {
33048     strcpy(smefilename, b->outfilename);
33049   } else {
33050     strcpy(smefilename, "unnamed");
33051   }
33052   strcpy(nodfilename, smefilename);
33053   strcat(smefilename, ".smesh");
33054   strcat(nodfilename, ".node");
33055 
33056   if (!b->quiet) {
33057     printf("Writing %s.\n", smefilename);
33058   }
33059   outfile = fopen(smefilename, "w");
33060   if (outfile == (FILE *) NULL) {
33061     printf("File I/O Error:  Cannot create file %s.\n", smefilename);
33062     return;
33063   }
33064 
33065   // Determine the first index (0 or 1).
33066   firstindex = b->zeroindex ? 0 : in->firstnumber;
33067   shift = 0; // Default no shiftment.
33068   if ((in->firstnumber == 1) && (firstindex == 0)) {
33069     shift = 1; // Shift the output indices by 1.
33070   }
33071 
33072   fprintf(outfile, "# %s.  TetGen's input file.\n", smefilename);
33073   fprintf(outfile, "\n# part 1: node list.\n");
33074   fprintf(outfile, "0  3  0  0  # nodes are found in %s.\n", nodfilename);
33075 
33076   marker = 0; // avoid compile warning.
33077   bmark = !b->nobound && in->facetmarkerlist;  
33078 
33079   fprintf(outfile, "\n# part 2: facet list.\n");
33080   // Number of facets, boundary marker.
33081   fprintf(outfile, "%ld  %d\n", subfaces->items, bmark);
33082   
33083   subfaces->traversalinit();
33084   faceloop.sh = shellfacetraverse(subfaces);
33085   while (faceloop.sh != (shellface *) NULL) {
33086     p1 = sorg(faceloop);
33087     p2 = sdest(faceloop);
33088     p3 = sapex(faceloop);
33089     if (bmark) {
33090       faceid = shellmark(faceloop) - 1;
33091       if (faceid >= 0) { 
33092         marker = in->facetmarkerlist[faceid];
33093       } else {
33094         marker = 0; // This subface must be added manually later.
33095       }
33096     }
33097     fprintf(outfile, "3    %4d  %4d  %4d", pointmark(p1) - shift,
33098             pointmark(p2) - shift, pointmark(p3) - shift);
33099     if (bmark) {
33100       fprintf(outfile, "    %d", marker);
33101     }
33102     fprintf(outfile, "\n");
33103     faceloop.sh = shellfacetraverse(subfaces);
33104   }
33105 
33106   // Copy input holelist.
33107   fprintf(outfile, "\n# part 3: hole list.\n");
33108   fprintf(outfile, "%d\n", in->numberofholes);
33109   for (i = 0; i < in->numberofholes; i++) {
33110     fprintf(outfile, "%d  %g  %g  %g\n", i + in->firstnumber,
33111             in->holelist[i * 3], in->holelist[i * 3 + 1],
33112             in->holelist[i * 3 + 2]);
33113   }
33114 
33115   // Copy input regionlist.
33116   fprintf(outfile, "\n# part 4: region list.\n");
33117   fprintf(outfile, "%d\n", in->numberofregions);
33118   for (i = 0; i < in->numberofregions; i++) {
33119     fprintf(outfile, "%d  %g  %g  %g  %d  %g\n", i + in->firstnumber,
33120             in->regionlist[i * 5], in->regionlist[i * 5 + 1],
33121             in->regionlist[i * 5 + 2], (int) in->regionlist[i * 5 + 3],
33122             in->regionlist[i * 5 + 4]);
33123   }
33124 
33125   fprintf(outfile, "# Generated by %s\n", b->commandline);
33126   fclose(outfile);
33127 }
33128 
33130 //                                                                           //
33131 // outmesh2medit()    Write mesh to a .mesh file, which can be read and      //
33132 //                    rendered by Medit (a free mesh viewer from INRIA).     //
33133 //                                                                           //
33134 // You can specify a filename (without suffix) in 'mfilename'.  If you don't //
33135 // supply a filename (let mfilename be NULL), the default name stored in     //
33136 // 'tetgenbehavior' will be used. The output file will have the suffix .mesh.//
33137 //                                                                           //
33139 
33140 void tetgenmesh::outmesh2medit(char* mfilename)
33141 {
33142   FILE *outfile;
33143   char mefilename[FILENAMESIZE];
33144   tetrahedron* tetptr;
33145   triface tface, tsymface;
33146   face segloop, checkmark;
33147   point ptloop, p1, p2, p3, p4;
33148   long faces;
33149   int pointnumber;
33150   int i;
33151 
33152   if (mfilename != (char *) NULL && mfilename[0] != '\0') {
33153     strcpy(mefilename, mfilename);
33154   } else if (b->outfilename[0] != '\0') {
33155     strcpy(mefilename, b->outfilename);
33156   } else {
33157     strcpy(mefilename, "unnamed");
33158   }
33159   strcat(mefilename, ".mesh");
33160 
33161   if (!b->quiet) {
33162     printf("Writing %s.\n", mefilename);
33163   }
33164   outfile = fopen(mefilename, "w");
33165   if (outfile == (FILE *) NULL) {
33166     printf("File I/O Error:  Cannot create file %s.\n", mefilename);
33167     return;
33168   }
33169 
33170   fprintf(outfile, "MeshVersionFormatted 1\n");
33171   fprintf(outfile, "\n");
33172   fprintf(outfile, "Dimension\n");
33173   fprintf(outfile, "3\n");
33174   fprintf(outfile, "\n");
33175 
33176   fprintf(outfile, "\n# Set of mesh vertices\n");
33177   fprintf(outfile, "Vertices\n");
33178   fprintf(outfile, "%ld\n", points->items);
33179 
33180   points->traversalinit();
33181   ptloop = pointtraverse();
33182   pointnumber = 1;                        // Medit need start number form 1.
33183   while (ptloop != (point) NULL) {
33184     // Point coordinates.
33185     fprintf(outfile, "%.17g  %.17g  %.17g", ptloop[0], ptloop[1], ptloop[2]);
33186     if (in->numberofpointattributes > 0) {
33187       // Write an attribute, ignore others if more than one.
33188       fprintf(outfile, "  %.17g\n", ptloop[3]);
33189     } else {
33190       fprintf(outfile, "    0\n");
33191     }
33192     setpointmark(ptloop, pointnumber);
33193     ptloop = pointtraverse();
33194     pointnumber++;
33195   }
33196 
33197   // Compute the number of edges.
33198   faces = (4l * tetrahedrons->items + hullsize) / 2l;
33199 
33200   fprintf(outfile, "\n# Set of Triangles\n");
33201   fprintf(outfile, "Triangles\n");
33202   fprintf(outfile, "%ld\n", faces);
33203 
33204   tetrahedrons->traversalinit();
33205   tface.tet = tetrahedrontraverse();
33206   // To loop over the set of faces, loop over all tetrahedra, and look at
33207   //   the four faces of each tetrahedron. If there isn't another tetrahedron
33208   //   adjacent to the face, operate on the face.  If there is another adj-
33209   //   acent tetrahedron, operate on the face only if the current tetrahedron
33210   //   has a smaller pointer than its neighbor.  This way, each face is
33211   //   considered only once.
33212   while (tface.tet != (tetrahedron *) NULL) {
33213     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33214       sym(tface, tsymface);
33215       if (tface.tet < tsymface.tet || tsymface.tet == dummytet) {
33216         p1 = org (tface);
33217         p2 = dest(tface);
33218         p3 = apex(tface);
33219         fprintf(outfile, "%5d  %5d  %5d",
33220                 pointmark(p1), pointmark(p2), pointmark(p3));
33221         fprintf(outfile, "    0\n");
33222       }
33223     }
33224     tface.tet = tetrahedrontraverse();
33225   }
33226 
33227   fprintf(outfile, "\n# Set of Tetrahedra\n");
33228   fprintf(outfile, "Tetrahedra\n");
33229   fprintf(outfile, "%ld\n", tetrahedrons->items);
33230 
33231   tetrahedrons->traversalinit();
33232   tetptr = tetrahedrontraverse();
33233   while (tetptr != (tetrahedron *) NULL) {
33234     p1 = (point) tetptr[4];
33235     p2 = (point) tetptr[5];
33236     p3 = (point) tetptr[6];
33237     p4 = (point) tetptr[7];
33238     fprintf(outfile, "%5d  %5d  %5d  %5d",
33239             pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33240     if (in->numberoftetrahedronattributes > 0) {
33241       fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
33242     } else {
33243       fprintf(outfile, "  0");
33244     }
33245     fprintf(outfile, "\n");
33246     tetptr = tetrahedrontraverse();
33247   }
33248 
33249   fprintf(outfile, "\nCorners\n");
33250   fprintf(outfile, "%d\n", in->numberofpoints);
33251 
33252   for (i = 0; i < in->numberofpoints; i++) {
33253     fprintf(outfile, "%4d\n", i + 1);
33254   }
33255 
33256   if (b->useshelles) {
33257     fprintf(outfile, "\nEdges\n");
33258     fprintf(outfile, "%ld\n", subsegs->items);
33259 
33260     subsegs->traversalinit();
33261     segloop.sh = shellfacetraverse(subsegs);
33262     while (segloop.sh != (shellface *) NULL) {
33263       p1 = sorg(segloop);
33264       p2 = sdest(segloop);
33265       fprintf(outfile, "%5d  %5d", pointmark(p1), pointmark(p2));
33266       fprintf(outfile, "    0\n");
33267       segloop.sh = shellfacetraverse(subsegs);
33268     }
33269   }
33270 
33271   fprintf(outfile, "\nEnd\n");
33272   fclose(outfile);
33273 }
33274 
33276 //                                                                           //
33277 // outmesh2gid()    Write mesh to a .ele.msh file and a .face.msh file,      //
33278 //                  which can be imported and rendered by Gid.               //
33279 //                                                                           //
33280 // You can specify a filename (without suffix) in 'gfilename'.  If you don't //
33281 // supply a filename (let gfilename be NULL), the default name stored in     //
33282 // 'tetgenbehavior' will be used. The suffixes (.ele.msh and .face.msh) will //
33283 // be automatically added.                                                   //
33284 //                                                                           //
33286 
33287 void tetgenmesh::outmesh2gid(char* gfilename)
33288 {
33289   FILE *outfile;
33290   char gidfilename[FILENAMESIZE];
33291   tetrahedron* tetptr;
33292   triface tface, tsymface;
33293   face sface;
33294   point ptloop, p1, p2, p3, p4;
33295   int pointnumber;
33296   int elementnumber;
33297 
33298   if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33299     strcpy(gidfilename, gfilename);
33300   } else if (b->outfilename[0] != '\0') {
33301     strcpy(gidfilename, b->outfilename);
33302   } else {
33303     strcpy(gidfilename, "unnamed");
33304   }
33305   strcat(gidfilename, ".ele.msh");
33306 
33307   if (!b->quiet) {
33308     printf("Writing %s.\n", gidfilename);
33309   }
33310   outfile = fopen(gidfilename, "w");
33311   if (outfile == (FILE *) NULL) {
33312     printf("File I/O Error:  Cannot create file %s.\n", gidfilename);
33313     return;
33314   }
33315 
33316   fprintf(outfile, "mesh dimension = 3 elemtype tetrahedron nnode = 4\n");
33317   fprintf(outfile, "coordinates\n");
33318 
33319   points->traversalinit();
33320   ptloop = pointtraverse();
33321   pointnumber = 1;                        // Gid need start number form 1.
33322   while (ptloop != (point) NULL) {
33323     // Point coordinates.
33324     fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
33325             ptloop[0], ptloop[1], ptloop[2]);
33326     if (in->numberofpointattributes > 0) {
33327       // Write an attribute, ignore others if more than one.
33328       fprintf(outfile, "  %.17g", ptloop[3]);
33329     }
33330     fprintf(outfile, "\n");
33331     setpointmark(ptloop, pointnumber);
33332     ptloop = pointtraverse();
33333     pointnumber++;
33334   }
33335 
33336   fprintf(outfile, "end coordinates\n");
33337   fprintf(outfile, "elements\n");
33338 
33339   tetrahedrons->traversalinit();
33340   tetptr = tetrahedrontraverse();
33341   elementnumber = 1;
33342   while (tetptr != (tetrahedron *) NULL) {
33343     p1 = (point) tetptr[4];
33344     p2 = (point) tetptr[5];
33345     p3 = (point) tetptr[6];
33346     p4 = (point) tetptr[7];
33347     fprintf(outfile, "%5d  %5d %5d %5d %5d", elementnumber,
33348             pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33349     if (in->numberoftetrahedronattributes > 0) {
33350       fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
33351     } 
33352     fprintf(outfile, "\n");
33353     tetptr = tetrahedrontraverse();
33354     elementnumber++;
33355   }
33356 
33357   fprintf(outfile, "end elements\n");
33358   fclose(outfile);
33359 
33360   if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33361     strcpy(gidfilename, gfilename);
33362   } else if (b->outfilename[0] != '\0') {
33363     strcpy(gidfilename, b->outfilename);
33364   } else {
33365     strcpy(gidfilename, "unnamed");
33366   }
33367   strcat(gidfilename, ".face.msh");
33368 
33369   if (!b->quiet) {
33370     printf("Writing %s.\n", gidfilename);
33371   }
33372   outfile = fopen(gidfilename, "w");
33373   if (outfile == (FILE *) NULL) {
33374     printf("File I/O Error:  Cannot create file %s.\n", gidfilename);
33375     return;
33376   }
33377 
33378   fprintf(outfile, "mesh dimension = 3 elemtype triangle nnode = 3\n");
33379   fprintf(outfile, "coordinates\n");
33380 
33381   points->traversalinit();
33382   ptloop = pointtraverse();
33383   pointnumber = 1;                        // Gid need start number form 1.
33384   while (ptloop != (point) NULL) {
33385     // Point coordinates.
33386     fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
33387             ptloop[0], ptloop[1], ptloop[2]);
33388     if (in->numberofpointattributes > 0) {
33389       // Write an attribute, ignore others if more than one.
33390       fprintf(outfile, "  %.17g", ptloop[3]);
33391     }
33392     fprintf(outfile, "\n");
33393     setpointmark(ptloop, pointnumber);
33394     ptloop = pointtraverse();
33395     pointnumber++;
33396   }
33397 
33398   fprintf(outfile, "end coordinates\n");
33399   fprintf(outfile, "elements\n");
33400 
33401   tetrahedrons->traversalinit();
33402   tface.tet = tetrahedrontraverse();
33403   elementnumber = 1;
33404   while (tface.tet != (tetrahedron *) NULL) {
33405     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33406       sym(tface, tsymface);
33407       if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33408         p1 = org(tface);
33409         p2 = dest(tface);
33410         p3 = apex(tface);
33411         if (tsymface.tet == dummytet) {
33412           // It's a hull face, output it.
33413           fprintf(outfile, "%5d   %d  %d  %d\n", elementnumber,
33414                   pointmark(p1), pointmark(p2), pointmark(p3));
33415           elementnumber++;
33416         } else if (b->useshelles) {
33417           // Only output it if it's a subface.
33418           tspivot(tface, sface);
33419           if (sface.sh != dummysh) {
33420             fprintf(outfile, "%5d   %d  %d  %d\n", elementnumber,
33421                     pointmark(p1), pointmark(p2), pointmark(p3));
33422             elementnumber++;
33423           }
33424         }
33425       }
33426     }
33427     tface.tet = tetrahedrontraverse();
33428   }
33429 
33430   fprintf(outfile, "end elements\n");
33431   fclose(outfile);
33432 }
33433 
33435 //                                                                           //
33436 // outmesh2off()    Write the mesh to an .off file.                          //
33437 //                                                                           //
33438 // .off, the Object File Format, is one of the popular file formats from the //
33439 // Geometry Center's Geomview package (http://www.geomview.org).             //
33440 //                                                                           //
33442 
33443 void tetgenmesh::outmesh2off(char* ofilename)
33444 {
33445   FILE *outfile;
33446   char offfilename[FILENAMESIZE];
33447   triface tface, tsymface;
33448   point ptloop, p1, p2, p3;
33449   long faces;
33450   int shift;
33451 
33452   if (ofilename != (char *) NULL && ofilename[0] != '\0') {
33453     strcpy(offfilename, ofilename);
33454   } else if (b->outfilename[0] != '\0') {
33455     strcpy(offfilename, b->outfilename);
33456   } else {
33457     strcpy(offfilename, "unnamed");
33458   }
33459   strcat(offfilename, ".off");
33460 
33461   if (!b->quiet) {
33462     printf("Writing %s.\n", offfilename);
33463   }
33464   outfile = fopen(offfilename, "w");
33465   if (outfile == (FILE *) NULL) {
33466     printf("File I/O Error:  Cannot create file %s.\n", offfilename);
33467     return;
33468   }
33469 
33470   // Calculate the number of triangular faces in the tetrahedral mesh.
33471   faces = (4l * tetrahedrons->items + hullsize) / 2l;
33472 
33473   // Number of points, faces, and edges(not used, here show hullsize).
33474   fprintf(outfile, "OFF\n%ld  %ld  %ld\n", points->items, faces, hullsize);
33475 
33476   // Write the points.
33477   points->traversalinit();
33478   ptloop = pointtraverse();
33479   while (ptloop != (point) NULL) {
33480     fprintf(outfile, " %.17g  %.17g  %.17g\n",ptloop[0], ptloop[1], ptloop[2]);
33481     ptloop = pointtraverse();
33482   }
33483 
33484   // OFF always use zero as the first index.
33485   shift = in->firstnumber == 1 ? 1 : 0;
33486 
33487   tetrahedrons->traversalinit();
33488   tface.tet = tetrahedrontraverse();
33489   // To loop over the set of faces, loop over all tetrahedra, and look at
33490   //   the four faces of each tetrahedron. If there isn't another tetrahedron
33491   //   adjacent to the face, operate on the face.  If there is another adj-
33492   //   acent tetrahedron, operate on the face only if the current tetrahedron
33493   //   has a smaller pointer than its neighbor.  This way, each face is
33494   //   considered only once.
33495   while (tface.tet != (tetrahedron *) NULL) {
33496     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33497       sym(tface, tsymface);
33498       if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33499         p1 = org(tface);
33500         p2 = dest(tface);
33501         p3 = apex(tface);
33502         // Face number, indices of three vertexs.
33503         fprintf(outfile, "3   %4d  %4d  %4d\n", pointmark(p1) - shift,
33504                 pointmark(p2) - shift, pointmark(p3) - shift);
33505       }
33506     }
33507     tface.tet = tetrahedrontraverse();
33508   }
33509 
33510   fprintf(outfile, "# Generated by %s\n", b->commandline);
33511   fclose(outfile);
33512 }
33513 
33514 //
33515 // End of I/O rouitnes
33516 //
33517 
33518 //
33519 // Begin of user interaction routines
33520 //
33521 
33523 //                                                                           //
33524 // internalerror()    Ask the user to send me the defective product.  Exit.  //
33525 //                                                                           //
33527 
33528 void tetgenmesh::internalerror()
33529 {
33530   printf("  Please report this bug to sihang@mail.berlios.de. Include the\n");
33531   printf("    message above, your input data set, and the exact command\n");
33532   printf("    line you used to run this program, thank you.\n");
33533   terminatetetgen(2);
33534 }
33535 
33537 //                                                                           //
33538 // checkmesh()    Test the mesh for topological consistency.                 //
33539 //                                                                           //
33541 
33542 void tetgenmesh::checkmesh()
33543 {
33544   triface tetraloop;
33545   triface oppotet, oppooppotet;
33546   point tetorg, tetdest, tetapex, tetoppo;
33547   REAL oritest;
33548   int horrors;
33549 
33550   if (!b->quiet) {
33551     printf("  Checking consistency of mesh...\n");
33552   }
33553 
33554   horrors = 0;
33555   // Run through the list of tetrahedra, checking each one.
33556   tetrahedrons->traversalinit();
33557   tetraloop.tet = tetrahedrontraverse();
33558   while (tetraloop.tet != (tetrahedron *) NULL) {
33559     // Check all four faces of the tetrahedron.
33560     for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33561       tetorg = org(tetraloop);
33562       tetdest = dest(tetraloop);
33563       tetapex = apex(tetraloop);
33564       tetoppo = oppo(tetraloop);
33565       if (tetraloop.loc == 0) {             // Only test for inversion once.
33566         oritest = orient3d(tetorg, tetdest, tetapex, tetoppo);
33567         if (oritest >= 0.0) {
33568           printf("  !! !! %s ", oritest > 0.0 ? "Inverted" : "Degenerated");
33569           printtet(&tetraloop);
33570           printf("  orient3d = %.17g.\n", oritest);
33571           horrors++;
33572         }
33573       }
33574       // Find the neighboring tetrahedron on this face.
33575       sym(tetraloop, oppotet);
33576       if (oppotet.tet != dummytet) {
33577         // Check that the tetrahedron's neighbor knows it's a neighbor.
33578         sym(oppotet, oppooppotet);
33579         if ((tetraloop.tet != oppooppotet.tet)
33580             || (tetraloop.loc != oppooppotet.loc)) {
33581           printf("  !! !! Asymmetric tetra-tetra bond:\n");
33582           if (tetraloop.tet == oppooppotet.tet) {
33583             printf("   (Right tetrahedron, wrong orientation)\n");
33584           }
33585           printf("    First ");
33586           printtet(&tetraloop);
33587           printf("    Second (nonreciprocating) ");
33588           printtet(&oppotet);
33589           horrors++;
33590         }
33591       }
33592     }
33593     tetraloop.tet = tetrahedrontraverse();
33594   }
33595   if (horrors == 0) {
33596     if (!b->quiet) {
33597       printf("  In my studied opinion, the mesh appears to be consistent.\n");
33598     }
33599   } else if (horrors == 1) {
33600     printf("  !! !! !! !! Precisely one festering wound discovered.\n");
33601   } else {
33602     printf("  !! !! !! !! %d abominations witnessed.\n", horrors);
33603   }
33604 }
33605 
33607 //                                                                           //
33608 // checkshells()       Test the boundary mesh for topological consistency.   //
33609 //                                                                           //
33611 
33612 void tetgenmesh::checkshells()
33613 {
33614   triface oppotet, oppooppotet, testtet; 
33615   face shloop, segloop, spin;
33616   face testsh, testseg, testshsh;
33617   point shorg, shdest, segorg, segdest;
33618   REAL checksign;
33619   bool same;
33620   int horrors;
33621   int i;
33622 
33623   if (!b->quiet) {
33624     printf("  Checking consistency of the mesh boundary...\n");
33625   }
33626   horrors = 0;
33627 
33628   // Run through the list of subfaces, checking each one.
33629   subfaces->traversalinit();
33630   shloop.sh = shellfacetraverse(subfaces);
33631   while (shloop.sh != (shellface *) NULL) {
33632     // Check two connected tetrahedra if they exist.
33633     shloop.shver = 0;
33634     stpivot(shloop, oppotet);
33635     if (oppotet.tet != dummytet) {
33636       tspivot(oppotet, testsh);
33637       if (testsh.sh != shloop.sh) {
33638         printf("  !! !! Wrong tetra-subface connection.\n");
33639         printf("    Tetra: ");
33640         printtet(&oppotet);
33641         printf("    Subface: ");
33642         printsh(&shloop);
33643         horrors++;
33644       }
33645       if (oppo(oppotet) != (point) NULL) {
33646         adjustedgering(oppotet, CCW);
33647         checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33648                              oppo(oppotet));
33649         if (checksign >= 0.0) {
33650           printf("  !! !! Wrong subface orientation.\n");
33651           printf("    Subface: ");
33652           printsh(&shloop);
33653           horrors++;
33654         }
33655       }
33656     }
33657     sesymself(shloop);
33658     stpivot(shloop, oppooppotet);
33659     if (oppooppotet.tet != dummytet) {
33660       tspivot(oppooppotet, testsh);
33661       if (testsh.sh != shloop.sh) {
33662         printf("  !! !! Wrong tetra-subface connection.\n");
33663         printf("    Tetra: ");
33664         printtet(&oppooppotet);
33665         printf("    Subface: ");
33666         printsh(&shloop);
33667         horrors++;
33668       }
33669       if (oppotet.tet != dummytet) {
33670         sym(oppotet, testtet);
33671         if (testtet.tet != oppooppotet.tet) {
33672           printf("  !! !! Wrong tetra-subface-tetra connection.\n");
33673           printf("    Tetra 1: ");
33674           printtet(&oppotet);
33675           printf("    Subface: ");
33676           printsh(&shloop);
33677           printf("    Tetra 2: ");
33678           printtet(&oppooppotet);
33679           horrors++;
33680         }
33681       }
33682       if (oppo(oppooppotet) != (point) NULL) {
33683         adjustedgering(oppooppotet, CCW);
33684         checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33685                              oppo(oppooppotet));
33686         if (checksign >= 0.0) {
33687           printf("  !! !! Wrong subface orientation.\n");
33688           printf("    Subface: ");
33689           printsh(&shloop);
33690           horrors++;
33691         }
33692       }
33693     }
33694     // Check connection between subfaces.
33695     shloop.shver = 0;
33696     for (i = 0; i < 3; i++) {
33697       shorg = sorg(shloop);
33698       shdest = sdest(shloop);
33699       sspivot(shloop, testseg);
33700       if (testseg.sh != dummysh) {
33701         segorg = sorg(testseg);
33702         segdest = sdest(testseg);
33703         same = ((shorg == segorg) && (shdest == segdest)) 
33704         || ((shorg == segdest) && (shdest == segorg));
33705         if (!same) {
33706           printf("  !! !! Wrong subface-subsegment connection.\n");
33707           printf("    Subface: ");
33708           printsh(&shloop);
33709           printf("    Subsegment: ");
33710           printsh(&testseg);
33711           horrors++;
33712         } 
33713       } 
33714       spivot(shloop, testsh);
33715       if (testsh.sh != dummysh) {
33716         segorg = sorg(testsh);
33717         segdest = sdest(testsh);
33718         same = ((shorg == segorg) && (shdest == segdest)) 
33719         || ((shorg == segdest) && (shdest == segorg));
33720         if (!same) {
33721           printf("  !! !! Wrong subface-subface connection.\n");
33722           printf("    Subface 1: ");
33723           printsh(&shloop);
33724           printf("    Subface 2: ");
33725           printsh(&testsh);
33726           horrors++;
33727         }
33728         spivot(testsh, testshsh);
33729         shorg = sorg(testshsh);
33730         shdest = sdest(testshsh);
33731         same = ((shorg == segorg) && (shdest == segdest)) 
33732         || ((shorg == segdest) && (shdest == segorg));
33733         if (!same) {
33734           printf("  !! !! Wrong subface-subface connection.\n");
33735           printf("    Subface 1: ");
33736           printsh(&testsh);
33737           printf("    Subface 2: ");
33738           printsh(&testshsh);
33739           horrors++;
33740         }
33741         if (testseg.sh == dummysh) {
33742           if (testshsh.sh != shloop.sh) {
33743             printf("  !! !! Wrong subface-subface connection.\n");
33744             printf("    Subface 1: ");
33745             printsh(&shloop);
33746             printf("    Subface 2: ");
33747             printsh(&testsh);
33748             horrors++;
33749           }
33750         } 
33751       }
33752       senextself(shloop);
33753     }
33754     shloop.sh = shellfacetraverse(subfaces);
33755   }
33756 
33757   // Run through the list of subsegs, checking each one.
33758   subsegs->traversalinit();
33759   segloop.sh = shellfacetraverse(subsegs);
33760   while (segloop.sh != (shellface *) NULL) {
33761     segorg = sorg(segloop);
33762     segdest = sdest(segloop);
33763     spivot(segloop, testsh);
33764     if (testsh.sh == dummysh) {
33765       printf("  !! !! Wrong subsegment-subface connection.\n");
33766       printf("    Subsegment: ");
33767       printsh(&segloop);
33768       horrors++;
33769       segloop.sh = shellfacetraverse(subsegs);
33770       continue;
33771     }
33772     shorg = sorg(testsh);
33773     shdest = sdest(testsh);
33774     same = ((shorg == segorg) && (shdest == segdest)) 
33775         || ((shorg == segdest) && (shdest == segorg));
33776     if (!same) {
33777       printf("  !! !! Wrong subsegment-subface connection.\n");
33778       printf("    Subsegment : ");
33779       printsh(&segloop);
33780       printf("    Subface : ");
33781       printsh(&testsh);
33782       horrors++;
33783       segloop.sh = shellfacetraverse(subsegs);
33784       continue;
33785     }
33786     // Check the connection of face loop around this subsegment.
33787     spin = testsh;
33788     i = 0;
33789     do {
33790       spivotself(spin);
33791       shorg = sorg(spin);
33792       shdest = sdest(spin);
33793       same = ((shorg == segorg) && (shdest == segdest)) 
33794           || ((shorg == segdest) && (shdest == segorg));
33795       if (!same) {
33796         printf("  !! !! Wrong subsegment-subface connection.\n");
33797         printf("    Subsegment : ");
33798         printsh(&segloop);
33799         printf("    Subface : ");
33800         printsh(&testsh);
33801         horrors++;
33802         break;
33803       }
33804       i++;
33805     } while (spin.sh != testsh.sh && i < 1000);
33806     if (i >= 1000) {
33807       printf("  !! !! Wrong subsegment-subface connection.\n");
33808       printf("    Subsegment : ");
33809       printsh(&segloop);
33810       horrors++;
33811     }
33812     segloop.sh = shellfacetraverse(subsegs);
33813   }
33814   if (horrors == 0) {
33815     if (!b->quiet) {
33816       printf("  Mesh boundaries connected correctly.\n");
33817     }
33818   } else {
33819     printf("  !! !! !! !! %d boundary connection viewed with horror.\n",
33820            horrors);
33821     return;
33822   }
33823 }
33824 
33826 //                                                                           //
33827 // checkdelaunay()    Ensure that the mesh is constrained Delaunay.          //
33828 //                                                                           //
33829 // If 'flipqueue' is not NULL, non-locally Delaunay faces are saved in it.   //
33830 //                                                                           //
33832 
33833 void tetgenmesh::checkdelaunay(REAL eps, queue* flipqueue)
33834 {
33835   triface tetraloop;
33836   triface oppotet;
33837   face opposhelle;
33838   point tetorg, tetdest, tetapex, tetoppo;
33839   point oppooppo;
33840   enum fliptype fc;
33841   REAL sign;
33842   int shouldbedelaunay;
33843   int horrors;
33844 
33845   if (!b->quiet) {
33846     printf("  Checking Delaunay property of the mesh...\n");
33847   }
33848   horrors = 0;
33849   // Run through the list of triangles, checking each one.
33850   tetrahedrons->traversalinit();
33851   tetraloop.tet = tetrahedrontraverse();
33852   while (tetraloop.tet != (tetrahedron *) NULL) {
33853     // Check all four faces of the tetrahedron.
33854     for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33855       tetorg = org(tetraloop);
33856       tetdest = dest(tetraloop);
33857       tetapex = apex(tetraloop);
33858       tetoppo = oppo(tetraloop);
33859       sym(tetraloop, oppotet);
33860       oppooppo = oppo(oppotet);
33861       // Only do testif there is an adjoining tetrahedron whose pointer is
33862       //   larger (to ensure that each pair isn't tested twice).
33863       shouldbedelaunay = (oppotet.tet != dummytet)
33864                           && (tetoppo != (point) NULL)
33865                           && (oppooppo != (point) NULL)
33866                           && (tetraloop.tet < oppotet.tet);
33867       if (checksubfaces && shouldbedelaunay) {
33868         // If a shell face separates the tetrahedra, then the face is
33869         //   constrained, so no local Delaunay test should be done.
33870         tspivot(tetraloop, opposhelle);
33871         if (opposhelle.sh != dummysh){
33872           shouldbedelaunay = 0;
33873         }
33874       }
33875       if (shouldbedelaunay) {
33876         sign = insphere(tetdest, tetorg, tetapex, tetoppo, oppooppo);
33877         if ((sign > 0.0) && (eps > 0.0)) {
33878           if (iscospheric(tetdest, tetorg, tetapex, tetoppo, oppooppo, sign,
33879                           eps)) sign = 0.0;
33880         }
33881         if (sign > 0.0) {
33882           if (flipqueue) {
33883             enqueueflipface(tetraloop, flipqueue);
33884           } else {
33885             printf("  !! Non-locally Delaunay face (%d, %d, %d) ",
33886                    pointmark(tetorg), pointmark(tetdest), pointmark(tetapex));
33887             fc = categorizeface(tetraloop);
33888             switch (fc) {
33889             case T23: printf("\"T23\""); break;
33890             case T32: printf("\"T32\""); break;
33891             case T22: printf("\"T22\""); break;
33892             case T44: printf("\"T44\""); break;
33893             case N32: printf("\"N32\""); break;
33894             case N40: printf("\"N40\""); break;
33895             case FORBIDDENFACE:printf("\"FORBIDDENFACE\""); break;
33896             case FORBIDDENEDGE:printf("\"FORBIDDENEDGE\""); break;
33897             }
33898             printf("\n");
33899           }
33900           horrors++;
33901         }
33902       }
33903     }
33904     tetraloop.tet = tetrahedrontraverse();
33905   }
33906   if (flipqueue == (queue *) NULL) {
33907     if (horrors == 0) {
33908       if (!b->quiet) {
33909         printf("  The mesh is %s.\n",
33910                checksubfaces ? "constrained Delaunay" : "Delaunay");
33911       }
33912     } else {
33913       printf("  !! !! !! !! %d obscenities viewed with horror.\n", horrors);
33914     }
33915   }
33916 }
33917 
33919 //                                                                           //
33920 // checkconforming()    Ensure that the mesh is conforming Delaunay.         //
33921 //                                                                           //
33923 
33924 void tetgenmesh::checkconforming()
33925 {
33926   face segloop, shloop;
33927   int encsubsegs, encsubfaces;
33928 
33929   if (!b->quiet) {
33930     printf("  Checking conforming Delaunay property of mesh...\n");
33931   }
33932   encsubsegs = encsubfaces = 0;
33933   // Run through the list of subsegments, check each one.
33934   subsegs->traversalinit();
33935   segloop.sh = shellfacetraverse(subsegs);
33936   while (segloop.sh != (shellface *) NULL) {
33937     if (checkseg4encroach(&segloop, NULL, NULL, false)) {
33938       printf("  !! !! Non-conforming subsegment: (%d, %d)\n",
33939              pointmark(sorg(segloop)), pointmark(sdest(segloop)));
33940       encsubsegs++;
33941     }
33942     segloop.sh = shellfacetraverse(subsegs);
33943   }
33944   // Run through the list of subfaces, check each one.
33945   subfaces->traversalinit();
33946   shloop.sh = shellfacetraverse(subfaces);
33947   while (shloop.sh != (shellface *) NULL) {
33948     if (checksub4encroach(&shloop, NULL, false)) {
33949       printf("  !! !! Non-conforming subface: (%d, %d, %d)\n",
33950              pointmark(sorg(shloop)), pointmark(sdest(shloop)),
33951              pointmark(sapex(shloop)));
33952       encsubfaces++;
33953     }
33954     shloop.sh = shellfacetraverse(subfaces);
33955   }
33956   if (encsubsegs == 0 && encsubfaces == 0) {
33957     if (!b->quiet) {
33958       printf("  The mesh is conforming Delaunay.\n");
33959     }
33960   } else {
33961     if (encsubsegs > 0) {
33962       printf("  !! !! %d subsegments are non-conforming.\n", encsubsegs);
33963     }
33964     if (encsubfaces > 0) {
33965       printf("  !! !! %d subfaces are non-conforming.\n", encsubfaces);
33966     }
33967   }
33968 }
33969 
33971 //                                                                           //
33972 // algorithmicstatistics()    Print statistics about the mesh algorithms.    //
33973 //                                                                           //
33975 
33976 #ifdef SELF_CHECK
33977 
33978 void tetgenmesh::algorithmicstatistics()
33979 {
33980   /*
33981   printf("Algorithmic statistics:\n\n");
33982   printf("  Point location millisecond:  %g\n", (REAL) tloctime * 1e+3);
33983   printf("  Flip millisecond:  %g\n", (REAL) tfliptime * 1e+3);
33984   if (b->plc || b->refine) {
33985     printf("  Number of facet above points calculations: %ld\n", abovecount);
33986   }
33987   if (b->plc) {
33988     printf("  Segment split rules: R1 %ld, R2 %ld, R3 %ld\n", r1count, r2count,
33989            r3count);
33990   }
33991   if (b->quality) {
33992     printf("  Bowyer-Watson insertions: seg %ld, sub %ld, vol %ld.\n",
33993            bowatsegcount, bowatsubcount, bowatvolcount);
33994     printf("  Bowyer-Watson corrections: seg %ld, sub %ld, vol %ld\n",
33995            updsegcount, updsubcount, updvolcount);
33996     printf("  Bowyer-Watson failures: seg %ld, sub %ld, vol %ld\n",
33997            failsegcount, failsubcount, failvolcount);
33998     printf("  Number of repair flips: %ld.\n", repairflipcount);
33999     printf("  Number of circumcenters outside Bowat-cav.: %ld.\n",
34000            outbowatcircumcount);
34001     if (b->conformdel) {
34002       printf("  Segment split rules: R2 %ld, R3 %ld\n", r2count, r3count);
34003       printf("  Number of CDT enforcement points: %ld.\n", cdtenforcesegpts);
34004     }
34005     printf("  Number of Rejections: seg %ld, sub %ld, tet %ld.\n", rejsegpts,
34006            rejsubpts, rejtetpts);
34007     if (b->optlevel) {
34008       printf(
34009       "  Optimization flips: f32 %ld, f44 %ld, f56 %ld, f68 %ld, fnm %ld.\n",
34010              optcount[3], optcount[4], optcount[5], optcount[6], optcount[9]);
34011       printf("  Optimization segment deletions: %ld.\n", optcount[1]);
34012     }
34013   }
34014   printf("\n");
34015   */
34016 }
34017 
34018 #endif // #ifdef SELF_CHECK
34019 
34021 //                                                                           //
34022 // qualitystatistics()    Print statistics about the quality of the mesh.    //
34023 //                                                                           //
34025 
34026 void tetgenmesh::qualitystatistics()
34027 {
34028   triface tetloop, neightet;
34029   point p[4];
34030   char sbuf[128];
34031   REAL radiusratiotable[12];
34032   REAL aspectratiotable[12];
34033   REAL A[4][4], rhs[4], D;
34034   REAL V[6][3], N[4][3], H[4]; // edge-vectors, face-normals, face-heights.
34035   REAL edgelength[6], alldihed[6], faceangle[3];
34036   REAL shortest, longest;
34037   REAL smallestvolume, biggestvolume;
34038   REAL smallestdiangle, biggestdiangle;
34039   REAL smallestfaangle, biggestfaangle;
34040   REAL tetvol, minaltitude;
34041   REAL cirradius, minheightinv; // insradius;
34042   REAL shortlen, longlen;
34043   REAL tetaspect, tetradius;
34044   REAL smalldiangle, bigdiangle;
34045   REAL smallfaangle, bigfaangle;
34046   int radiustable[12];
34047   int aspecttable[16];
34048   int dihedangletable[18];
34049   int faceangletable[18];
34050   int indx[4];
34051   int radiusindex;
34052   int aspectindex;
34053   int tendegree;
34054   int i, j;
34055 
34056   smallfaangle = 0.0;
34057   bigfaangle = 0.0;
34058 
34059   printf("Mesh quality statistics:\n\n");
34060 
34061   // Avoid compile warnings.
34062   shortlen = longlen = 0.0;
34063   smalldiangle = bigdiangle = 0.0;
34064 
34065   radiusratiotable[0]  =    0.707;    radiusratiotable[1]  =     1.0;
34066   radiusratiotable[2]  =      1.1;    radiusratiotable[3]  =     1.2;
34067   radiusratiotable[4]  =      1.4;    radiusratiotable[5]  =     1.6;
34068   radiusratiotable[6]  =      1.8;    radiusratiotable[7]  =     2.0;
34069   radiusratiotable[8]  =      2.5;    radiusratiotable[9]  =     3.0;
34070   radiusratiotable[10] =     10.0;    radiusratiotable[11] =     0.0;
34071 
34072   aspectratiotable[0]  =      1.5;    aspectratiotable[1]  =     2.0;
34073   aspectratiotable[2]  =      2.5;    aspectratiotable[3]  =     3.0;
34074   aspectratiotable[4]  =      4.0;    aspectratiotable[5]  =     6.0;
34075   aspectratiotable[6]  =     10.0;    aspectratiotable[7]  =    15.0;
34076   aspectratiotable[8]  =     25.0;    aspectratiotable[9]  =    50.0;
34077   aspectratiotable[10] =    100.0;    aspectratiotable[11] =     0.0;
34078   
34079   for (i = 0; i < 12; i++) radiustable[i] = 0;
34080   for (i = 0; i < 12; i++) aspecttable[i] = 0;
34081   for (i = 0; i < 18; i++) dihedangletable[i] = 0;
34082   for (i = 0; i < 18; i++) faceangletable[i] = 0;
34083 
34084   minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
34085   minaltitude = minaltitude * minaltitude;
34086   shortest = minaltitude;
34087   longest = 0.0;
34088   smallestvolume = minaltitude;
34089   biggestvolume = 0.0;
34090   smallestdiangle = smallestfaangle = 180.0;
34091   biggestdiangle = biggestfaangle = 0.0;
34092 
34093   // Loop all elements, calculate quality parameters for each element.
34094   tetrahedrons->traversalinit();
34095   tetloop.tet = tetrahedrontraverse();
34096   while (tetloop.tet != (tetrahedron *) NULL) {
34097     
34098     // Get four vertices: p0, p1, p2, p3.
34099     for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i];
34100     // Set the edge vectors: V[0], ..., V[5]
34101     for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i]; // V[0]: p3->p0.
34102     for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i]; // V[1]: p3->p1.
34103     for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i]; // V[2]: p3->p2.
34104     for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i]; // V[3]: p0->p1.
34105     for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i]; // V[4]: p1->p2.
34106     for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i]; // V[5]: p2->p0.
34107     // Set the matrix A = [V[0], V[1], V[2]]^T.
34108     for (j = 0; j < 3; j++) {
34109       for (i = 0; i < 3; i++) A[j][i] = V[j][i];
34110     }
34111     // Decompose A just once.
34112     lu_decmp(A, 3, indx, &D, 0);   
34113     // Get the tet volume.
34114     tetvol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
34115     // Get the three faces normals.
34116     for (j = 0; j < 3; j++) {
34117       for (i = 0; i < 3; i++) rhs[i] = 0.0;
34118       rhs[j] = 1.0;  // Positive means the inside direction
34119       lu_solve(A, 3, indx, rhs, 0);
34120       for (i = 0; i < 3; i++) N[j][i] = rhs[i];
34121     }
34122     // Get the fourth face normal by summing up the first three.
34123     for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
34124     // Get the radius of the circumsphere.
34125     for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]);
34126     lu_solve(A, 3, indx, rhs, 0);
34127     cirradius = sqrt(dot(rhs, rhs));
34128     // Normalize the face normals.
34129     for (i = 0; i < 4; i++) {
34130       // H[i] is the inverse of height of its corresponding face.
34131       H[i] = sqrt(dot(N[i], N[i]));
34132       for (j = 0; j < 3; j++) N[i][j] /= H[i];
34133     }
34134     // Get the radius of the inscribed sphere.
34135     // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]);
34136     // Get the biggest H[i] (corresponding to the smallest height).
34137     minheightinv = H[0];
34138     for (i = 1; i < 3; i++) {
34139       if (H[i] > minheightinv) minheightinv = H[i];
34140     }
34141     // Get the squares of the edge lengthes.
34142     for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
34143     // Get the dihedrals (in degree) at each edges.
34144     j = 0;
34145     for (i = 1; i < 4; i++) {
34146       alldihed[j] = -dot(N[0], N[i]); // Edge cd, bd, bc.
34147       if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34148       else if (alldihed[j] > 1.0) alldihed[j] = 1;
34149       alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34150       j++;
34151     }
34152     for (i = 2; i < 4; i++) {
34153       alldihed[j] = -dot(N[1], N[i]); // Edge ad, ac.
34154       if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34155       else if (alldihed[j] > 1.0) alldihed[j] = 1;
34156       alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34157       j++;
34158     }
34159     alldihed[j] = -dot(N[2], N[3]); // Edge ab.
34160     if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34161     else if (alldihed[j] > 1.0) alldihed[j] = 1;
34162     alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34163     
34164     // Calculate the longest and shortest edge length.
34165     for (i = 0; i < 6; i++) {
34166       if (i == 0) {
34167         shortlen = longlen = edgelength[i];
34168       } else {
34169         shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen;
34170         longlen  = edgelength[i] > longlen  ? edgelength[i] : longlen;
34171       }
34172       if (edgelength[i] > longest) {
34173         longest = edgelength[i];
34174       } 
34175       if (edgelength[i] < shortest) {
34176         shortest = edgelength[i];
34177       }
34178     }
34179     
34180     // Calculate the largest and smallest volume.
34181     if (tetvol < smallestvolume) {
34182       smallestvolume = tetvol;
34183     } 
34184     if (tetvol > biggestvolume) {
34185       biggestvolume = tetvol;
34186     }
34187     
34188     // Calculate the largest and smallest dihedral angles.
34189     for (i = 0; i < 6; i++) {
34190       if (i == 0) {
34191         smalldiangle = bigdiangle = alldihed[i];
34192       } else {
34193         smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle;
34194         bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle;
34195       }
34196       if (alldihed[i] < smallestdiangle) {
34197         smallestdiangle = alldihed[i];
34198       } 
34199       if (alldihed[i] > biggestdiangle) {
34200         biggestdiangle = alldihed[i];
34201       }
34202     }
34203     // Accumulate the corresponding number in the dihedral angle histogram.
34204     if (smalldiangle < 5.0) {
34205       tendegree = 0;
34206     } else if (smalldiangle >= 5.0 && smalldiangle < 10.0) {
34207       tendegree = 1;
34208     } else if (smalldiangle >= 80.0 && smalldiangle < 110.0) {
34209       tendegree = 9; // Angles between 80 to 110 degree are in one entry.
34210     } else {
34211       tendegree = (int) (smalldiangle / 10.);
34212       if (smalldiangle < 80.0) {
34213         tendegree++;  // In the left column.
34214       } else {
34215         tendegree--;  // In the right column.
34216       }
34217     }
34218     dihedangletable[tendegree]++;
34219     if (bigdiangle >= 80.0 && bigdiangle < 110.0) {
34220       tendegree = 9; // Angles between 80 to 110 degree are in one entry.
34221     } else if (bigdiangle >= 170.0 && bigdiangle < 175.0) {
34222       tendegree = 16;
34223     } else if (bigdiangle >= 175.0) {
34224       tendegree = 17;
34225     } else {
34226       tendegree = (int) (bigdiangle / 10.);
34227       if (bigdiangle < 80.0) {
34228         tendegree++;  // In the left column.
34229       } else {
34230         tendegree--;  // In the right column.
34231       }
34232     }
34233     dihedangletable[tendegree]++;
34234 
34235     // Calulate the largest and smallest face angles.
34236     tetloop.ver = 0;
34237     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
34238       sym(tetloop, neightet);
34239       // Only do the calulation once for a face.
34240       if ((neightet.tet == dummytet) || (tetloop.tet < neightet.tet)) {
34241         p[0] = org(tetloop);
34242         p[1] = dest(tetloop);
34243         p[2] = apex(tetloop);
34244         faceangle[0] = interiorangle(p[0], p[1], p[2], NULL);
34245         faceangle[1] = interiorangle(p[1], p[2], p[0], NULL);
34246         faceangle[2] = PI - (faceangle[0] + faceangle[1]);
34247         // Translate angles into degrees.
34248         for (i = 0; i < 3; i++) {
34249           faceangle[i] = (faceangle[i] * 180.0) / PI;
34250         }
34251         // Calculate the largest and smallest face angles.
34252         for (i = 0; i < 3; i++) {
34253           if (i == 0) {
34254             smallfaangle = bigfaangle = faceangle[i];
34255           } else {
34256             smallfaangle = faceangle[i] < smallfaangle ? 
34257               faceangle[i] : smallfaangle;
34258             bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle;
34259           }
34260           if (faceangle[i] < smallestfaangle) {
34261             smallestfaangle = faceangle[i];
34262           } 
34263           if (faceangle[i] > biggestfaangle) {
34264             biggestfaangle = faceangle[i];
34265           }
34266         }
34267         tendegree = (int) (smallfaangle / 10.);
34268         faceangletable[tendegree]++;
34269         tendegree = (int) (bigfaangle / 10.);
34270         faceangletable[tendegree]++;
34271       }
34272     }
34273 
34274     // Calculate aspect ratio and radius-edge ratio for this element.
34275     tetradius = cirradius / sqrt(shortlen);
34276     // tetaspect = sqrt(longlen) / (2.0 * insradius);
34277     tetaspect = sqrt(longlen) * minheightinv;
34278     aspectindex = 0;
34279     while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) {
34280       aspectindex++;
34281     }
34282     aspecttable[aspectindex]++;
34283     radiusindex = 0;
34284     while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) {
34285       radiusindex++;
34286     }
34287     radiustable[radiusindex]++;
34288 
34289     tetloop.tet = tetrahedrontraverse();
34290   }
34291 
34292   shortest = sqrt(shortest);
34293   longest = sqrt(longest);
34294   minaltitude = sqrt(minaltitude);
34295 
34296   printf("  Smallest volume: %16.5g   |  Largest volume: %16.5g\n",
34297          smallestvolume, biggestvolume);
34298   printf("  Shortest edge:   %16.5g   |  Longest edge:   %16.5g\n",
34299          shortest, longest);
34300   sprintf(sbuf, "%.17g", biggestfaangle);
34301   if (strlen(sbuf) > 8) {
34302     sbuf[8] = '\0';
34303   }
34304   printf("  Smallest facangle: %14.5g   |  Largest facangle:       %s\n",
34305          smallestfaangle, sbuf);
34306   sprintf(sbuf, "%.17g", biggestdiangle);
34307   if (strlen(sbuf) > 8) {
34308     sbuf[8] = '\0';
34309   }
34310   printf("  Smallest dihedral: %14.5g   |  Largest dihedral:       %s\n\n",
34311          smallestdiangle, sbuf);
34312 
34313   /*
34314   printf("  Radius-edge ratio histogram:\n");
34315   printf("         < %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34316          radiusratiotable[0], radiustable[0], radiusratiotable[5],
34317          radiusratiotable[6], radiustable[6]);
34318   for (i = 1; i < 5; i++) {
34319     printf("  %6.6g - %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34320            radiusratiotable[i - 1], radiusratiotable[i], radiustable[i],
34321            radiusratiotable[i + 5], radiusratiotable[i + 6],
34322            radiustable[i + 6]);
34323   }
34324   printf("  %6.6g - %-6.6g    :  %8d      | %6.6g -            :  %8d\n",
34325          radiusratiotable[4], radiusratiotable[5], radiustable[5],
34326          radiusratiotable[10], radiustable[11]);
34327   printf("  (A tetrahedron's radius-edge ratio is its radius of ");
34328   printf("circumsphere divided\n");
34329   printf("    by its shortest edge length)\n\n");
34330   */
34331 
34332   printf("  Aspect ratio histogram:\n");
34333   printf("         < %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34334          aspectratiotable[0], aspecttable[0], aspectratiotable[5],
34335          aspectratiotable[6], aspecttable[6]);
34336   for (i = 1; i < 5; i++) {
34337     printf("  %6.6g - %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34338            aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i],
34339            aspectratiotable[i + 5], aspectratiotable[i + 6],
34340            aspecttable[i + 6]);
34341   }
34342   printf("  %6.6g - %-6.6g    :  %8d      | %6.6g -            :  %8d\n",
34343          aspectratiotable[4], aspectratiotable[5], aspecttable[5],
34344          aspectratiotable[10], aspecttable[11]);
34345   printf("  (A tetrahedron's aspect ratio is its longest edge length");
34346   printf(" divided by its\n");
34347   printf("    smallest side height)\n\n");
34348 
34349   printf("  Face angle histogram:\n");
34350   for (i = 0; i < 9; i++) {
34351     printf("    %3d - %3d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34352            i * 10, i * 10 + 10, faceangletable[i],
34353            i * 10 + 90, i * 10 + 100, faceangletable[i + 9]);
34354   }
34355   if (minfaceang != PI) {
34356     printf("  Minimum input face angle is %g (degree).\n",
34357            minfaceang / PI * 180.0);
34358   }
34359   printf("\n");
34360 
34361   printf("  Dihedral angle histogram:\n");
34362   // Print the three two rows:
34363   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34364          0, 5, dihedangletable[0], 80, 110, dihedangletable[9]);
34365   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34366          5, 10, dihedangletable[1], 110, 120, dihedangletable[10]);
34367   // Print the third to seventh rows.
34368   for (i = 2; i < 7; i++) {
34369     printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34370            (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i],
34371            (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]);
34372   }
34373   // Print the last two rows.
34374   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34375          60, 70, dihedangletable[7], 170, 175, dihedangletable[16]);
34376   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34377          70, 80, dihedangletable[8], 175, 180, dihedangletable[17]);
34378   if (minfacetdihed != PI) {
34379     printf("  Minimum input facet dihedral angle is %g (degree).\n",
34380            minfacetdihed / PI * 180.0);
34381   }
34382   printf("\n");
34383 }
34384 
34386 //                                                                           //
34387 // statistics()    Print all sorts of cool facts.                            //
34388 //                                                                           //
34390 
34391 void tetgenmesh::statistics()
34392 {
34393   printf("\nStatistics:\n\n");
34394   printf("  Input points: %d\n", in->numberofpoints + jettisoninverts);
34395   if (b->refine) {
34396     printf("  Input tetrahedra: %d\n", in->numberoftetrahedra);
34397   }
34398   if (b->plc) {
34399     printf("  Input facets: %d\n", in->numberoffacets);
34400     printf("  Input segments: %ld\n", insegments);
34401     printf("  Input holes: %d\n", in->numberofholes);
34402     printf("  Input regions: %d\n", in->numberofregions);
34403   }
34404 
34405   printf("\n  Mesh points: %ld\n", points->items);
34406   printf("  Mesh tetrahedra: %ld\n", tetrahedrons->items);
34407   if (b->plc || b->refine) {
34408     printf("  Mesh triangles: %ld\n", (4l*tetrahedrons->items+hullsize)/2l);
34409   }
34410   if (b->plc || b->refine) {
34411     printf("  Mesh subfaces: %ld\n", subfaces->items);
34412     printf("  Mesh subsegments: %ld\n\n", subsegs->items);
34413   } else {
34414     printf("  Convex hull triangles: %ld\n\n", hullsize);
34415   }
34416   if (b->verbose > 0) {
34417     qualitystatistics();
34418     unsigned long totalmeshbytes;
34419     printf("Memory allocation statistics:\n\n");
34420     printf("  Maximum number of vertices: %ld\n", points->maxitems);
34421     totalmeshbytes = points->maxitems * points->itembytes;
34422     printf("  Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems);
34423     totalmeshbytes += tetrahedrons->maxitems * tetrahedrons->itembytes;
34424     if (subfaces != (memorypool *) NULL) {
34425       printf("  Maximum number of subfaces: %ld\n", subfaces->maxitems);
34426       totalmeshbytes += subfaces->maxitems * subfaces->itembytes;
34427     }
34428     if (subsegs != (memorypool *) NULL) {
34429       printf("  Maximum number of segments: %ld\n", subsegs->maxitems);
34430       totalmeshbytes += subsegs->maxitems * subsegs->itembytes;
34431     }
34432     printf("  Approximate heap memory used by the mesh (K bytes): %g\n\n",
34433            (double) totalmeshbytes / 1024.0);
34434 #ifdef SELF_CHECK
34435     algorithmicstatistics();
34436 #endif
34437   }
34438 }
34439 
34440 //
34441 // End of user interaction routines
34442 //
34443 
34444 //
34445 // Begin of constructor and destructor of tetgenmesh
34446 //
34447 
34449 //                                                                           //
34450 // ~tetgenmesh()    Deallocte memory occupied by a tetgenmesh object.        //
34451 //                                                                           //
34453 
34454 tetgenmesh::~tetgenmesh()
34455 {
34456   bgm = (tetgenmesh *) NULL;
34457   in = (tetgenio *) NULL;
34458   b = (tetgenbehavior *) NULL;
34459 
34460   if (tetrahedrons != (memorypool *) NULL) {
34461     delete tetrahedrons;
34462   }
34463   if (subfaces != (memorypool *) NULL) {
34464     delete subfaces;
34465   }
34466   if (subsegs != (memorypool *) NULL) {
34467     delete subsegs;
34468   }
34469   if (points != (memorypool *) NULL) {
34470     delete points;
34471   }
34472   if (dummytetbase != (tetrahedron *) NULL) {
34473     delete [] dummytetbase;
34474   }
34475   if (dummyshbase != (shellface *) NULL) {
34476     delete [] dummyshbase;
34477   }
34478   if (facetabovepointarray != (point *) NULL) {
34479     delete [] facetabovepointarray;
34480   }
34481   if (highordertable != (point *) NULL) {
34482     delete [] highordertable;
34483   }
34484   if (subpbcgrouptable != (pbcdata *) NULL) {
34485     delete [] subpbcgrouptable;
34486   }
34487   if (segpbcgrouptable != (list *) NULL) {
34488     delete segpbcgrouptable;
34489     delete [] idx2segpglist;
34490     delete [] segpglist;
34491   }
34492 }
34493 
34495 //                                                                           //
34496 // tetgenmesh()    Initialize a tetgenmesh object.                           //
34497 //                                                                           //
34499 
34500 tetgenmesh::tetgenmesh()
34501 {
34502   bgm = (tetgenmesh *) NULL;
34503   in = (tetgenio *) NULL;
34504   b = (tetgenbehavior *) NULL;
34505 
34506   tetrahedrons = (memorypool *) NULL;
34507   subfaces = (memorypool *) NULL;
34508   subsegs = (memorypool *) NULL;
34509   points = (memorypool *) NULL;
34510   badsubsegs = (memorypool *) NULL;
34511   badsubfaces = (memorypool *) NULL;
34512   badtetrahedrons = (memorypool *) NULL;
34513   flipstackers = (memorypool *) NULL;
34514 
34515   dummytet = (tetrahedron *) NULL;
34516   dummytetbase = (tetrahedron *) NULL;
34517   dummysh = (shellface *) NULL;
34518   dummyshbase = (shellface *) NULL;
34519 
34520   facetabovepointarray = (point *) NULL;
34521   abovepoint = (point) NULL;
34522   highordertable = (point *) NULL;
34523   subpbcgrouptable = (pbcdata *) NULL;
34524   segpbcgrouptable = (list *) NULL;
34525   idx2segpglist = (int *) NULL;
34526   segpglist = (int *) NULL;
34527 
34528   xmax = xmin = ymax = ymin = zmax = zmin = 0.0; 
34529   longest = 0.0;
34530   hullsize = 0l;
34531   insegments = 0l;
34532   pointmtrindex = 0;
34533   pointmarkindex = 0;
34534   point2simindex = 0;
34535   point2pbcptindex = 0;
34536   highorderindex = 0;
34537   elemattribindex = 0;
34538   volumeboundindex = 0;
34539   shmarkindex = 0;
34540   areaboundindex = 0;
34541   checksubfaces = 0;
34542   checksubsegs = 0;
34543   checkpbcs = 0;
34544   varconstraint = 0;
34545   nonconvex = 0;
34546   dupverts = 0;
34547   unuverts = 0;
34548   relverts = 0;
34549   suprelverts = 0;
34550   collapverts = 0;
34551   unsupverts = 0;
34552   jettisoninverts = 0;
34553   symbolic = 1;
34554   samples = 0l;
34555   randomseed = 1l;
34556   macheps = 0.0;
34557   minfaceang = minfacetdihed = PI;
34558   maxcavfaces = maxcavverts = 0;
34559   expcavcount = 0;
34560   abovecount = 0l;
34561   bowatvolcount = bowatsubcount = bowatsegcount = 0l;
34562   updvolcount = updsubcount = updsegcount = 0l;
34563   repairflipcount = 0l;
34564   outbowatcircumcount = 0l;
34565   failvolcount = failsubcount = failsegcount = 0l;
34566   r1count = r2count = r3count = 0l;
34567   cdtenforcesegpts = 0l;
34568   rejsegpts = rejsubpts = rejtetpts = 0l;
34569   flip23s = flip32s = flip22s = flip44s = 0l;
34570   tloctime = tfliptime = 0.0;
34571 }
34572 
34573 //
34574 // End of constructor and destructor of tetgenmesh
34575 //
34576 
34577 //
34578 // End of class 'tetgenmesh' implementation.
34579 //
34580 
34582 //                                                                           //
34583 // tetrahedralize()    The interface for users using TetGen library to       //
34584 //                     generate tetrahedral meshes with all features.        //
34585 //                                                                           //
34586 // The sequence is roughly as follows.  Many of these steps can be skipped,  //
34587 // depending on the command line switches.                                   //
34588 //                                                                           //
34589 // - Initialize constants and parse the command line.                        //
34590 // - Read the vertices from a file and either                                //
34591 //   - tetrahedralize them (no -r), or                                       //
34592 //   - read an old mesh from files and reconstruct it (-r).                  //
34593 // - Insert the PLC segments and facets (-p).                                //
34594 // - Read the holes (-p), regional attributes (-pA), and regional volume     //
34595 //   constraints (-pa).  Carve the holes and concavities, and spread the     //
34596 //   regional attributes and volume constraints.                             //
34597 // - Enforce the constraints on minimum quality bound (-q) and maximum       //
34598 //   volume (-a). Also enforce the conforming Delaunay property (-q and -a). //
34599 // - Promote the mesh's linear tetrahedra to higher order elements (-o).     //
34600 // - Write the output files and print the statistics.                        //
34601 // - Check the consistency and Delaunay property of the mesh (-C).           //
34602 //                                                                           //
34604 
34605 void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
34606   tetgenio *addin, tetgenio *bgmin)
34607 {
34608   tetgenmesh m;
34609   // Variables for timing the performance of TetGen (defined in time.h).
34610   clock_t tv[14];
34611 
34612   tv[0] = clock();
34613  
34614   m.b = b;
34615   m.in = in;
34616   m.macheps = exactinit();
34617   m.steinerleft = b->steiner;
34618   if (b->metric) {
34619     m.bgm = new tetgenmesh();
34620     m.bgm->b = b;
34621     m.bgm->in = bgmin;
34622     m.bgm->macheps = exactinit();
34623   }
34624   m.initializepools();
34625   m.transfernodes();
34626 
34627   tv[1] = clock();
34628 
34629   if (b->refine) {
34630     m.reconstructmesh();
34631   } else {
34632     m.delaunizevertices();
34633   }
34634 
34635   tv[2] = clock();
34636 
34637   if (!b->quiet) {
34638     if (b->refine) {
34639       printf("Mesh reconstruction seconds:");
34640     } else {
34641       printf("Delaunay seconds:");
34642     }
34643     printf("  %g\n", (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
34644   }
34645 
34646   if (b->metric) {
34647     if (bgmin != (tetgenio *) NULL) {
34648       m.bgm->initializepools();
34649       m.bgm->transfernodes();
34650       m.bgm->reconstructmesh();
34651     } else {
34652       m.bgm->in = in;
34653       m.bgm->initializepools();
34654       m.duplicatebgmesh();
34655     }
34656   }
34657 
34658   tv[3] = clock();
34659 
34660   if (!b->quiet) {
34661     if (b->metric) {
34662       printf("Background mesh reconstruct seconds:  %g\n",
34663              (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
34664     }
34665   }
34666 
34667   if (b->useshelles && !b->refine) {
34668     m.meshsurface();
34669     if (b->diagnose != 1) {
34670       m.markacutevertices(89.0);
34671       m.incrperturbvertices(b->epsilon);
34672       m.delaunizesegments();
34673       if (m.checkpbcs) {
34674         long oldnum;
34675         do {
34676           oldnum = m.points->items;
34677           m.incrperturbvertices(b->epsilon);
34678           if (m.points->items > oldnum) {
34679             oldnum = m.points->items;
34680             m.delaunizesegments();
34681           }
34682         } while (oldnum < m.points->items);
34683       }
34684       m.constrainedfacets();
34685     } else {
34686       m.detectinterfaces();
34687     }
34688   }
34689 
34690   tv[4] = clock();
34691 
34692   if (!b->quiet) {
34693     if (b->useshelles && !b->refine) {
34694       if (b->diagnose != 1) {
34695         printf("Segment and facet ");
34696       } else {
34697         printf("Intersection "); 
34698       }
34699       printf("seconds:  %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
34700     }
34701   }
34702 
34703   if (b->plc && !(b->diagnose == 1)) {
34704     m.carveholes();
34705   }
34706 
34707   tv[5] = clock();
34708 
34709   if (!b->quiet) {
34710     if (b->plc && !(b->diagnose == 1)) {
34711       printf("Hole seconds:  %g\n", (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
34712     }
34713   }
34714 
34715   if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34716     m.optimizemesh(false); 
34717   }
34718 
34719   tv[6] = clock();
34720 
34721   if (!b->quiet) {
34722     if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34723       printf("Repair seconds:  %g\n", (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
34724     }
34725   }
34726 
34727   if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34728     m.removesteiners(false);
34729   }
34730 
34731   tv[7] = clock();
34732 
34733   if (!b->quiet) {
34734     if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34735       printf("Steiner removal seconds:  %g\n",
34736              (tv[7] - tv[6]) / (REAL) CLOCKS_PER_SEC);
34737     }
34738   }
34739 
34740   if (b->insertaddpoints && (addin != (tetgenio *) NULL)) {
34741     if (addin->numberofpoints > 0) {
34742       m.insertconstrainedpoints(addin); 
34743     }
34744   }
34745 
34746   tv[8] = clock();
34747 
34748   if (!b->quiet) {
34749     if ((b->plc || b->refine) && (b->insertaddpoints)) {
34750       printf("Constrained points seconds:  %g\n", 
34751              (tv[8] - tv[7]) / (REAL) CLOCKS_PER_SEC);
34752     }
34753   }
34754 
34755   if (b->metric) {
34756     m.interpolatesizemap();
34757   }
34758 
34759   tv[9] = clock();
34760 
34761   if (!b->quiet) {
34762     if (b->metric) {
34763       printf("Size interpolating seconds:  %g\n",
34764              (tv[9] - tv[8]) / (REAL) CLOCKS_PER_SEC);
34765     }
34766   }
34767 
34768   if (b->coarse) {
34769     m.removesteiners(true);
34770   }
34771 
34772   tv[10] = clock();
34773 
34774   if (!b->quiet) {
34775     if (b->coarse) {
34776       printf("Mesh coarsening seconds:  %g\n",
34777              (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
34778     }
34779   }
34780 
34781   if (b->quality) {
34782     m.enforcequality();
34783   }
34784 
34785   tv[11] = clock();
34786 
34787   if (!b->quiet) {
34788     if (b->quality) {
34789       printf("Quality seconds:  %g\n",
34790              (tv[11] - tv[10]) / (REAL) CLOCKS_PER_SEC);
34791     }
34792   }
34793 
34794   if (b->quality && (b->optlevel > 0)) {
34795     m.optimizemesh(true);
34796   }
34797 
34798   tv[12] = clock();
34799 
34800   if (!b->quiet) {
34801     if (b->quality && (b->optlevel > 0)) {
34802       printf("Optimize seconds:  %g\n",
34803              (tv[12] - tv[11]) / (REAL) CLOCKS_PER_SEC);
34804     }
34805   }
34806 
34807   if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0)
34808       || (b->refine && (in->numberofcorners == 10)))) {
34809     m.jettisonnodes();
34810   }
34811 
34812   if (b->order > 1) {
34813     m.highorder();
34814   }
34815 
34816   if (!b->quiet) {
34817     printf("\n");
34818   }
34819 
34820   if (out != (tetgenio *) NULL) {
34821     out->firstnumber = in->firstnumber;
34822     out->mesh_dim = in->mesh_dim;
34823   }
34824 
34825   if (b->nonodewritten || b->noiterationnum) {
34826     if (!b->quiet) {
34827       printf("NOT writing a .node file.\n");
34828     }
34829   } else {
34830     if (b->diagnose == 1) {
34831       if (m.subfaces->items > 0l) {
34832         m.outnodes(out);  // Only output when self-intersecting faces exist.
34833       }
34834     } else {
34835       m.outnodes(out);
34836       if (b->quality || b->metric) {
34837         // m.outmetrics(out);
34838       }
34839     }
34840   }
34841 
34842   if (b->noelewritten) {
34843     if (!b->quiet) {
34844       printf("NOT writing an .ele file.\n");
34845     }
34846   } else {
34847     if (!(b->diagnose == 1)) {
34848       if (m.tetrahedrons->items > 0l) {
34849         m.outelements(out);
34850       }
34851     }
34852   }
34853 
34854   if (b->nofacewritten) {
34855     if (!b->quiet) {
34856       printf("NOT writing an .face file.\n");
34857     }
34858   } else {
34859     if (b->facesout) {
34860       if (m.tetrahedrons->items > 0l) {
34861         m.outfaces(out);  // Output all faces.
34862       }
34863     } else {
34864       if (b->diagnose == 1) {
34865         if (m.subfaces->items > 0l) {
34866           m.outsubfaces(out); // Only output self-intersecting faces.
34867         }
34868       } else if (b->plc || b->refine) {
34869         if (m.subfaces->items > 0l) {
34870           m.outsubfaces(out); // Output boundary faces.
34871         }
34872       } else {
34873         if (m.tetrahedrons->items > 0l) {
34874           m.outhullfaces(out); // Output convex hull faces.
34875         }
34876       }
34877     }
34878   }
34879 
34880   if (m.checkpbcs) {
34881     m.outpbcnodes(out);
34882   }
34883 
34884   if (b->edgesout) {
34885     if (b->edgesout > 1) {
34886       m.outedges(out); // -ee, output all mesh edges. 
34887     } else {
34888       m.outsubsegments(out); // -e, only output subsegments.
34889     }
34890   }
34891 
34892   if (!out && b->plc && 
34893       ((b->object == tetgenbehavior::OFF) ||
34894        (b->object == tetgenbehavior::PLY) ||
34895        (b->object == tetgenbehavior::STL))) {
34896     m.outsmesh(b->outfilename);
34897   }
34898 
34899   if (!out && b->meditview) {
34900     m.outmesh2medit(b->outfilename); 
34901   }
34902 
34903   if (!out && b->gidview) {
34904     m.outmesh2gid(b->outfilename); 
34905   }
34906 
34907   if (!out && b->geomview) {
34908     m.outmesh2off(b->outfilename); 
34909   }
34910 
34911   if (b->neighout) {
34912     m.outneighbors(out);
34913   }
34914 
34915   if (b->voroout) {
34916     m.outvoronoi(out);
34917   }
34918 
34919   tv[13] = clock();
34920 
34921   if (!b->quiet) {
34922     printf("\nOutput seconds:  %g\n",
34923            (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
34924     printf("Total running seconds:  %g\n",
34925            (tv[13] - tv[0]) / (REAL) CLOCKS_PER_SEC);
34926   }
34927 
34928   if (b->docheck) {
34929     m.checkmesh();
34930     if (m.checksubfaces) {
34931       m.checkshells();
34932     }
34933     if (b->docheck > 1) {
34934       m.checkdelaunay(0.0, NULL);
34935       if (b->docheck > 2) {
34936         if (b->quality || b->refine) {
34937           m.checkconforming();
34938         }
34939       }
34940     }
34941   }
34942 
34943   if (!b->quiet) {
34944     m.statistics();
34945   }
34946 
34947   if (b->metric) {
34948     delete m.bgm;
34949   }
34950 }
34951 
34952 #ifndef TETLIBRARY
34953 
34955 //                                                                           //
34956 // main()    The entrance for running TetGen from command line.              //
34957 //                                                                           //
34959 
34960 int main(int argc, char *argv[])
34961 
34962 #else // with TETLIBRARY
34963 
34965 //                                                                           //
34966 // tetrahedralize()    The entrance for calling TetGen from another program. //
34967 //                                                                           //
34969 
34970 void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
34971   tetgenio *addin, tetgenio *bgmin)
34972 
34973 #endif // not TETLIBRARY
34974 
34975 {
34976   tetgenbehavior b;
34977 
34978 #ifndef TETLIBRARY
34979 
34980   tetgenio in, addin, bgmin;
34981   
34982   if (!b.parse_commandline(argc, argv)) {
34983     terminatetetgen(1);
34984   }
34985   if (b.refine) {
34986     if (!in.load_tetmesh(b.infilename)) {
34987       terminatetetgen(1);
34988     }
34989   } else {
34990     if (!in.load_plc(b.infilename, (int) b.object)) {
34991       terminatetetgen(1);
34992     }
34993   }
34994   if (b.insertaddpoints) {
34995     if (!addin.load_node(b.addinfilename)) {
34996       addin.numberofpoints = 0l;
34997     }
34998   }
34999   if (b.metric) {
35000     if (!bgmin.load_tetmesh(b.bgmeshfilename)) {
35001       bgmin.numberoftetrahedra = 0l;
35002     }
35003   }
35004 
35005   if (bgmin.numberoftetrahedra > 0l) {
35006     tetrahedralize(&b, &in, NULL, &addin, &bgmin);
35007   } else {
35008     tetrahedralize(&b, &in, NULL, &addin, NULL);
35009   }
35010 
35011   return 0;
35012 
35013 #else // with TETLIBRARY
35014 
35015   if (!b.parse_commandline(switches)) {
35016     terminatetetgen(1);
35017   }
35018   tetrahedralize(&b, in, out, addin, bgmin);
35019 
35020 #endif // not TETLIBRARY
35021 }
35022 
35023 } //Added namespace to avoid clash with triangle
35024 
35025 #ifndef TETLIBRARY
35026 // Shim for entry point to main inside the namespace.  This is just in case we want to compile up a binary from this
35027 // source code.
35028 int main(int argc, char *argv[])
35029 {
35030     tetgen::main(argc, argv);
35031 }
35032 #endif // not TETLIBRARY

Generated on Tue May 31 14:31:47 2011 for Chaste by  doxygen 1.5.5