Chaste Release::3.1
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;
10597 #ifdef SELF_CHECK
10598   point pe, pf;
10599 #endif
10600   int mirrorflag, i;
10601 
10602   adjustedgering(*flipface, CCW); // 'flipface' is bae.
10603   fnext(*flipface, abce);
10604   esymself(abce);
10605   adjustedgering(*flipface, CW); // 'flipface' is abe.
10606   fnext(*flipface, bade);
10607 #ifdef SELF_CHECK
10608   assert(bade.tet != dummytet);
10609 #endif
10610   esymself(bade);
10611   pa = org(abce);
10612   pb = dest(abce);
10613   pc = apex(abce);
10614   pd = apex(bade);
10615 #ifdef SELF_CHECK
10616   pe = oppo(bade);
10617   assert(oppo(abce) == pe);
10618 #endif
10619   sym(abce, bacf);
10620   mirrorflag = bacf.tet != dummytet;
10621   if (mirrorflag) {
10622     // findedge(&bacf, pb, pa);
10623     bacf.ver = 0;
10624     for (i = 0; (i < 3) && (org(bacf) != pb); i++) {
10625       enextself(bacf);
10626     }
10627     sym(bade, abdf);
10628 #ifdef SELF_CHECK
10629     assert(abdf.tet != dummytet);
10630 #endif
10631     // findedge(&abdf, pa, pb);
10632     abdf.ver = 0;
10633     for (i = 0; (i < 3) && (org(abdf) != pa); i++) {
10634       enextself(abdf);
10635     }
10636 
10637 #ifdef SELF_CHECK
10638     pf = oppo(bacf);
10639     assert(oppo(abdf) == pf);
10640 #endif
10641   }
10642 
10643   if (b->verbose > 2) {
10644     printf("    Do %s on edge (%d, %d).\n", mirrorflag ? "T44" : "T22",
10645            pointmark(pa), pointmark(pb));
10646   }
10647   mirrorflag ? flip44s++ : flip22s++;
10648 
10649   // Save the old configuration at the convex hull.
10650   enextfnext(abce, oldbce);
10651   enext2fnext(abce, oldcae);
10652   enextfnext(bade, oldade);
10653   enext2fnext(bade, olddbe);
10654   sym(oldbce, bcecasing);
10655   sym(oldcae, caecasing);
10656   sym(oldade, adecasing);
10657   sym(olddbe, dbecasing);
10658   if (checksubfaces) {
10659     tspivot(oldbce, bcesh);
10660     tspivot(oldcae, caesh);
10661     tspivot(oldade, adesh);
10662     tspivot(olddbe, dbesh);
10663     tspivot(abce, abc);
10664     tspivot(bade, bad);
10665   } else if (checksubsegs) {
10666     // Coplanar segs: a->d->b->c.
10667     enext(bade, worktet);
10668     tsspivot1(worktet, adseg);
10669     enext2(bade, worktet);
10670     tsspivot1(worktet, dbseg);
10671     enext(abce, worktet);
10672     tsspivot1(worktet, bcseg);
10673     enext2(abce, worktet);
10674     tsspivot1(worktet, caseg);
10675     // Above segs: a->e, d->e, b->e, c->e.
10676     fnext(bade, worktet);
10677     enextself(worktet);
10678     tsspivot1(worktet, aeseg);
10679     enextfnext(bade, worktet);
10680     enextself(worktet);
10681     tsspivot1(worktet, deseg);
10682     enext2fnext(bade, worktet);
10683     enextself(worktet);
10684     tsspivot1(worktet, beseg);
10685     enextfnext(abce, worktet);
10686     enextself(worktet);
10687     tsspivot1(worktet, ceseg);
10688   }
10689   if (mirrorflag) {
10690     enextfnext(bacf, oldacf);
10691     enext2fnext(bacf, oldcbf);
10692     enextfnext(abdf, oldbdf);
10693     enext2fnext(abdf, olddaf);
10694     sym(oldacf, acfcasing);
10695     sym(oldcbf, cbfcasing);
10696     sym(oldbdf, bdfcasing);
10697     sym(olddaf, dafcasing);
10698     if (checksubfaces) {
10699       tspivot(oldacf, acfsh);
10700       tspivot(oldcbf, cbfsh);
10701       tspivot(oldbdf, bdfsh);
10702       tspivot(olddaf, dafsh);
10703     } else if (checksubsegs) {
10704       // Below segs: a->f, d->f, b->f, c->f.
10705       fnext(abdf, worktet);
10706       enext2self(worktet);
10707       tsspivot1(worktet, afseg);
10708       enext2fnext(abdf, worktet);
10709       enext2self(worktet);
10710       tsspivot1(worktet, dfseg);
10711       enextfnext(abdf, worktet);
10712       enext2self(worktet);
10713       tsspivot1(worktet, bfseg);
10714       enextfnext(bacf, worktet);
10715       enextself(worktet);
10716       tsspivot1(worktet, cfseg);
10717     }
10718   }
10719 
10720   // Rotate abce, bade one-quarter turn counterclockwise.
10721   bond(oldbce, caecasing);
10722   bond(oldcae, adecasing);
10723   bond(oldade, dbecasing);
10724   bond(olddbe, bcecasing);
10725   if (checksubfaces) {
10726     // Check for subfaces and rebond them to the rotated tets.
10727     if (caesh.sh == dummysh) {
10728       tsdissolve(oldbce);
10729     } else {
10730       tsbond(oldbce, caesh);
10731     }
10732     if (adesh.sh == dummysh) {
10733       tsdissolve(oldcae);
10734     } else {
10735       tsbond(oldcae, adesh);
10736     }
10737     if (dbesh.sh == dummysh) {
10738       tsdissolve(oldade);
10739     } else {
10740       tsbond(oldade, dbesh);
10741     }
10742     if (bcesh.sh == dummysh) {
10743       tsdissolve(olddbe);
10744     } else {
10745       tsbond(olddbe, bcesh);
10746     }
10747   } else if (checksubsegs) {
10748     // 5 edges in abce are changed.
10749     enext(abce, worktet);  // fit b->c into c->a.
10750     if (caseg.sh == dummysh) {
10751       tssdissolve1(worktet);
10752     } else {
10753       tssbond1(worktet, caseg);
10754     }
10755     enext2(abce, worktet); // fit c->a into a->d.
10756     if (adseg.sh == dummysh) {
10757       tssdissolve1(worktet);
10758     } else {
10759       tssbond1(worktet, adseg);
10760     }
10761     fnext(abce, worktet); // fit b->e into c->e.
10762     enextself(worktet);
10763     if (ceseg.sh == dummysh) {
10764       tssdissolve1(worktet);
10765     } else {
10766       tssbond1(worktet, ceseg);
10767     }
10768     enextfnext(abce, worktet); // fit c->e into a->e.
10769     enextself(worktet);
10770     if (aeseg.sh == dummysh) {
10771       tssdissolve1(worktet);
10772     } else {
10773       tssbond1(worktet, aeseg);
10774     }
10775     enext2fnext(abce, worktet); // fit a->e into d->e.
10776     enextself(worktet);
10777     if (deseg.sh == dummysh) {
10778       tssdissolve1(worktet);
10779     } else {
10780       tssbond1(worktet, deseg);
10781     }
10782     // 5 edges in bade are changed.
10783     enext(bade, worktet); // fit a->d into d->b.
10784     if (dbseg.sh == dummysh) {
10785       tssdissolve1(worktet);
10786     } else {
10787       tssbond1(worktet, dbseg);
10788     }
10789     enext2(bade, worktet); // fit d->b into b->c.
10790     if (bcseg.sh == dummysh) {
10791       tssdissolve1(worktet);
10792     } else {
10793       tssbond1(worktet, bcseg);
10794     }
10795     fnext(bade, worktet); // fit a->e into d->e.
10796     enextself(worktet);
10797     if (deseg.sh == dummysh) {
10798       tssdissolve1(worktet);
10799     } else {
10800       tssbond1(worktet, deseg);
10801     }
10802     enextfnext(bade, worktet); // fit d->e into b->e.
10803     enextself(worktet);
10804     if (beseg.sh == dummysh) {
10805       tssdissolve1(worktet);
10806     } else {
10807       tssbond1(worktet, beseg);
10808     }
10809     enext2fnext(bade, worktet); // fit b->e into c->e.
10810     enextself(worktet);
10811     if (ceseg.sh == dummysh) {
10812       tssdissolve1(worktet);
10813     } else {
10814       tssbond1(worktet, ceseg);
10815     }
10816   }
10817   if (mirrorflag) {
10818     // Rotate bacf, abdf one-quarter turn counterclockwise.
10819     bond(oldcbf, acfcasing);
10820     bond(oldacf, dafcasing);
10821     bond(olddaf, bdfcasing);
10822     bond(oldbdf, cbfcasing);
10823     if (checksubfaces) {
10824       // Check for subfaces and rebond them to the rotated tets.
10825       if (acfsh.sh == dummysh) {
10826         tsdissolve(oldcbf);
10827       } else {
10828         tsbond(oldcbf, acfsh);
10829       }
10830       if (dafsh.sh == dummysh) {
10831         tsdissolve(oldacf);
10832       } else {
10833         tsbond(oldacf, dafsh);
10834       }
10835       if (bdfsh.sh == dummysh) {
10836         tsdissolve(olddaf);
10837       } else {
10838         tsbond(olddaf, bdfsh);
10839       }
10840       if (cbfsh.sh == dummysh) {
10841         tsdissolve(oldbdf);
10842       } else {
10843         tsbond(oldbdf, cbfsh);
10844       }
10845     } else if (checksubsegs) {
10846       // 5 edges in bacf are changed.
10847       enext2(bacf, worktet); // fit b->c into c->a.
10848       if (caseg.sh == dummysh) {
10849         tssdissolve1(worktet);
10850       } else {
10851         tssbond1(worktet, caseg);
10852       }
10853       enext(bacf, worktet); // fit c->a into a->d.
10854       if (adseg.sh == dummysh) {
10855         tssdissolve1(worktet);
10856       } else {
10857         tssbond1(worktet, adseg);
10858       }
10859       fnext(bacf, worktet); // fit b->f into c->f.
10860       enext2self(worktet);
10861       if (cfseg.sh == dummysh) {
10862         tssdissolve1(worktet);
10863       } else {
10864         tssbond1(worktet, cfseg);
10865       }
10866       enext2fnext(bacf, worktet); // fit c->f into a->f.
10867       enext2self(worktet);
10868       if (afseg.sh == dummysh) {
10869         tssdissolve1(worktet);
10870       } else {
10871         tssbond1(worktet, afseg);
10872       }
10873       enextfnext(bacf, worktet); // fit a->f into d->f.
10874       enext2self(worktet);
10875       if (dfseg.sh == dummysh) {
10876         tssdissolve1(worktet);
10877       } else {
10878         tssbond1(worktet, dfseg);
10879       }
10880       // 5 edges in abdf are changed.
10881       enext2(abdf, worktet); // fit a->d into d->b.
10882       if (dbseg.sh == dummysh) {
10883         tssdissolve1(worktet);
10884       } else {
10885         tssbond1(worktet, dbseg);
10886       }
10887       enext(abdf, worktet); // fit d->b into b->c.
10888       if (bcseg.sh == dummysh) {
10889         tssdissolve1(worktet);
10890       } else {
10891         tssbond1(worktet, bcseg);
10892       }
10893       fnext(abdf, worktet); // fit a->f into d->f.
10894       enext2self(worktet);
10895       if (dfseg.sh == dummysh) {
10896         tssdissolve1(worktet);
10897       } else {
10898         tssbond1(worktet, dfseg);
10899       }
10900       enext2fnext(abdf, worktet); // fit d->f into b->f.
10901       enext2self(worktet);
10902       if (bfseg.sh == dummysh) {
10903         tssdissolve1(worktet);
10904       } else {
10905         tssbond1(worktet, bfseg);
10906       }
10907       enextfnext(abdf, worktet); // fit b->f into c->f.
10908       enext2self(worktet);
10909       if (cfseg.sh == dummysh) {
10910         tssdissolve1(worktet);
10911       } else {
10912         tssbond1(worktet, cfseg);
10913       }
10914     }
10915   }
10916 
10917   // New vertex assignments for the rotated tetrahedra.
10918   setorg(abce, pd); // Update abce to dcae
10919   setdest(abce, pc);
10920   setapex(abce, pa);
10921   setorg(bade, pc); // Update bade to cdbe
10922   setdest(bade, pd);
10923   setapex(bade, pb);
10924   if (mirrorflag) {
10925     setorg(bacf, pc); // Update bacf to cdaf
10926     setdest(bacf, pd);
10927     setapex(bacf, pa);
10928     setorg(abdf, pd); // Update abdf to dcbf
10929     setdest(abdf, pc);
10930     setapex(abdf, pb);
10931   }
10932 
10933   // Are there subfaces need to be flipped?
10934   if (checksubfaces && abc.sh != dummysh) {
10935 #ifdef SELF_CHECK
10936     assert(bad.sh != dummysh);
10937 #endif
10938     // Adjust the edge be ab, so the rotation of subfaces is according with
10939     //   the rotation of tetrahedra.
10940     findedge(&abc, pa, pb);
10941     // Flip an edge of two subfaces, ignore non-Delaunay edges.
10942     flip22sub(&abc, NULL);
10943   }
10944 
10945   if (b->verbose > 3) {
10946     printf("    Updating abce ");
10947     printtet(&abce);
10948     printf("    Updating bade ");
10949     printtet(&bade);
10950     if (mirrorflag) {
10951       printf("    Updating bacf ");
10952       printtet(&bacf);
10953       printf("    Updating abdf ");
10954       printtet(&abdf);
10955     }
10956   }
10957 
10958   if (flipqueue != (queue *) NULL) {
10959     enextfnext(abce, bcecasing);
10960     enqueueflipface(bcecasing, flipqueue);
10961     enext2fnext(abce, caecasing);
10962     enqueueflipface(caecasing, flipqueue);
10963     enextfnext(bade, adecasing);
10964     enqueueflipface(adecasing, flipqueue);
10965     enext2fnext(bade, dbecasing);
10966     enqueueflipface(dbecasing, flipqueue);
10967     if (mirrorflag) {
10968       enextfnext(bacf, acfcasing);
10969       enqueueflipface(acfcasing, flipqueue);
10970       enext2fnext(bacf, cbfcasing);
10971       enqueueflipface(cbfcasing, flipqueue);
10972       enextfnext(abdf, bdfcasing);
10973       enqueueflipface(bdfcasing, flipqueue);
10974       enext2fnext(abdf, dafcasing);
10975       enqueueflipface(dafcasing, flipqueue);
10976     }
10977     // The two new faces dcae (abce), cdbe (bade) may still not be locally
10978     //   Delaunay, and may need be flipped (flip23).  On the other hand, in
10979     //   conforming Delaunay algorithm, two new subfaces dca (abc), and cdb
10980     //   (bad) may be non-conforming Delaunay, they need be queued if they
10981     //   are locally Delaunay but non-conforming Delaunay.
10982     enqueueflipface(abce, flipqueue);
10983     enqueueflipface(bade, flipqueue);
10984   }
10985 
10986   // Save a live handle in 'recenttet'.
10987   recenttet = abce;
10988 }
10989 
10991 //                                                                           //
10992 // flip22sub()    Perform a 2-to-2 flip on a subface edge.                   //
10993 //                                                                           //
10994 // The flip edge is given by subface 'flipedge'.  Let it is abc, where ab is //
10995 // the flipping edge.  The other subface is bad,  where a, b, c, d form a    //
10996 // convex quadrilateral.  ab is not a subsegment.                            //
10997 //                                                                           //
10998 // A 2-to-2 subface flip is to change two subfaces abc and bad to another    //
10999 // two subfaces dca and cdb.  Hence, edge ab has been removed and dc becomes //
11000 // an edge. If a point e is above abc, this flip is equal to rotate abc and  //
11001 // bad counterclockwise using right-hand rule with thumb points to e. It is  //
11002 // important to know that the edge rings of the flipped subfaces dca and cdb //
11003 // are keeping the same orientation as their original subfaces. So they have //
11004 // the same orientation with respect to the lift point of this facet.        //
11005 //                                                                           //
11006 // During rotating, the face rings of the four edges bc, ca, ad, and de need //
11007 // be re-connected. If the edge is not a subsegment, then its face ring has  //
11008 // only two faces, a sbond() will bond them together. If it is a subsegment, //
11009 // one should use sbond1() twice to bond two different handles to the rotat- //
11010 // ing subface, one is predecssor (-casin), another is successor (-casout).  //
11011 //                                                                           //
11012 // If 'flipqueue' is not NULL, it returns four edges bc, ca, ad, de, which   //
11013 // may be non-Delaunay.                                                      //
11014 //                                                                           //
11016 
11017 void tetgenmesh::flip22sub(face* flipedge, queue* flipqueue)
11018 {
11019   face abc, bad;
11020   face oldbc, oldca, oldad, olddb;
11021   face bccasin, bccasout, cacasin, cacasout;
11022   face adcasin, adcasout, dbcasin, dbcasout;
11023   face bc, ca, ad, db;
11024   face spinsh;
11025   point pa, pb, pc, pd;
11026 
11027   abc = *flipedge;
11028   spivot(abc, bad);
11029   if (sorg(bad) != sdest(abc)) {
11030     sesymself(bad);
11031   }
11032   pa = sorg(abc);
11033   pb = sdest(abc);
11034   pc = sapex(abc);
11035   pd = sapex(bad);
11036 
11037   if (b->verbose > 2) {
11038     printf("    Flip sub edge (%d, %d).\n", pointmark(pa), pointmark(pb));
11039   }
11040 
11041   // Save the old configuration outside the quadrilateral.
11042   senext(abc, oldbc);
11043   senext2(abc, oldca);
11044   senext(bad, oldad);
11045   senext2(bad, olddb);
11046   // Get the outside connection. Becareful if there is a subsegment on the
11047   //   quadrilateral, two casings (casin and casout) are needed to save for
11048   //   keeping the face link.
11049   spivot(oldbc, bccasout);
11050   sspivot(oldbc, bc);
11051   if (bc.sh != dummysh) {
11052     // 'bc' is a subsegment.
11053     if (bccasout.sh != dummysh) {
11054       if (oldbc.sh != bccasout.sh) {
11055         // 'oldbc' is not self-bonded.
11056         spinsh = bccasout;
11057         do {
11058           bccasin = spinsh;
11059           spivotself(spinsh);
11060         } while (spinsh.sh != oldbc.sh);
11061       } else {
11062         bccasout.sh = dummysh;
11063       }
11064     }
11065     ssdissolve(oldbc);
11066   }
11067   spivot(oldca, cacasout);
11068   sspivot(oldca, ca);
11069   if (ca.sh != dummysh) {
11070     // 'ca' is a subsegment.
11071     if (cacasout.sh != dummysh) {
11072       if (oldca.sh != cacasout.sh) {
11073         // 'oldca' is not self-bonded.
11074         spinsh = cacasout;
11075         do {
11076           cacasin = spinsh;
11077           spivotself(spinsh);
11078         } while (spinsh.sh != oldca.sh);
11079       } else {
11080         cacasout.sh = dummysh;
11081       }
11082     }
11083     ssdissolve(oldca);
11084   }
11085   spivot(oldad, adcasout);
11086   sspivot(oldad, ad);
11087   if (ad.sh != dummysh) {
11088     // 'ad' is a subsegment.
11089     if (adcasout.sh != dummysh) {
11090       if (oldad.sh != adcasout.sh) {
11091         // 'adcasout' is not self-bonded.
11092         spinsh = adcasout;
11093         do {
11094           adcasin = spinsh;
11095           spivotself(spinsh);
11096         } while (spinsh.sh != oldad.sh);
11097       } else {
11098         adcasout.sh = dummysh;
11099       }
11100     }
11101     ssdissolve(oldad);
11102   }
11103   spivot(olddb, dbcasout);
11104   sspivot(olddb, db);
11105   if (db.sh != dummysh) {
11106     // 'db' is a subsegment.
11107     if (dbcasout.sh != dummysh) {
11108       if (olddb.sh != dbcasout.sh) {
11109         // 'dbcasout' is not self-bonded.
11110         spinsh = dbcasout;
11111         do {
11112           dbcasin = spinsh;
11113           spivotself(spinsh);
11114         } while (spinsh.sh != olddb.sh);
11115       } else {
11116         dbcasout.sh = dummysh;
11117       }
11118     }
11119     ssdissolve(olddb);
11120   }
11121 
11122   // Rotate abc and bad one-quarter turn counterclockwise.
11123   if (ca.sh != dummysh) {
11124     if (cacasout.sh != dummysh) {
11125       sbond1(cacasin, oldbc);
11126       sbond1(oldbc, cacasout);
11127     } else {
11128       // Bond 'oldbc' to itself.
11129       sbond(oldbc, oldbc);
11130       // Make sure that dummysh always correctly bonded.
11131       dummysh[0] = sencode(oldbc);
11132     }
11133     ssbond(oldbc, ca);
11134   } else {
11135     sbond(oldbc, cacasout);
11136   }
11137   if (ad.sh != dummysh) {
11138     if (adcasout.sh != dummysh) {
11139       sbond1(adcasin, oldca);
11140       sbond1(oldca, adcasout);
11141     } else {
11142       // Bond 'oldca' to itself.
11143       sbond(oldca, oldca);
11144       // Make sure that dummysh always correctly bonded.
11145       dummysh[0] = sencode(oldca);
11146     }
11147     ssbond(oldca, ad);
11148   } else {
11149     sbond(oldca, adcasout);
11150   }
11151   if (db.sh != dummysh) {
11152     if (dbcasout.sh != dummysh) {
11153       sbond1(dbcasin, oldad);
11154       sbond1(oldad, dbcasout);
11155     } else {
11156       // Bond 'oldad' to itself.
11157       sbond(oldad, oldad);
11158       // Make sure that dummysh always correctly bonded.
11159       dummysh[0] = sencode(oldad);
11160     }
11161     ssbond(oldad, db);
11162   } else {
11163     sbond(oldad, dbcasout);
11164   }
11165   if (bc.sh != dummysh) {
11166     if (bccasout.sh != dummysh) {
11167       sbond1(bccasin, olddb);
11168       sbond1(olddb, bccasout);
11169     } else {
11170       // Bond 'olddb' to itself.
11171       sbond(olddb, olddb);
11172       // Make sure that dummysh always correctly bonded.
11173       dummysh[0] = sencode(olddb);
11174     }
11175     ssbond(olddb, bc);
11176   } else {
11177     sbond(olddb, bccasout);
11178   }
11179 
11180   // New vertex assignments for the rotated subfaces.
11181   setsorg(abc, pd);  // Update abc to dca.
11182   setsdest(abc, pc);
11183   setsapex(abc, pa);
11184   setsorg(bad, pc);  // Update bad to cdb.
11185   setsdest(bad, pd);
11186   setsapex(bad, pb);
11187 
11188   if (flipqueue != (queue *) NULL) {
11189     enqueueflipedge(bccasout, flipqueue);
11190     enqueueflipedge(cacasout, flipqueue);
11191     enqueueflipedge(adcasout, flipqueue);
11192     enqueueflipedge(dbcasout, flipqueue);
11193   }
11194 }
11195 
11197 //                                                                           //
11198 // flip()    Flips non-locally Delaunay faces in flipqueue until it is empty.//
11199 //                                                                           //
11200 // Assumpation:  Current tetrahedralization is non-Delaunay after inserting  //
11201 // a point or performing a flip operation, all possibly non-Delaunay faces   //
11202 // are in 'flipqueue'.                                                       //
11203 //                                                                           //
11204 // If 'plastflip' is not NULL,  it is used to return a stack of recently     //
11205 // flipped faces.  This stack will be used to reverse the flips done in this //
11206 // routine later for removing a newly inserted point because it encroaches   //
11207 // any subfaces or subsegments.                                              //
11208 //                                                                           //
11209 // The return value is the total number of flips done during this invocation.//
11210 //                                                                           //
11212 
11213 long tetgenmesh::flip(queue* flipqueue, badface **plastflip)
11214 {
11215   badface *qface, *newflip;
11216   triface flipface, symface;
11217   point pa, pb, pc, pd, pe;
11218   enum fliptype fc;
11219   REAL sign, bakepsilon;
11220   long flipcount; //, maxfaces; - commented out to get gcc4.6 working
11221   int epscount, fcount;
11222   int ia, ib, ic, id, ie;
11223 
11224   if (b->verbose > 1) {
11225     printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
11226   }
11227 
11228   flipcount = flip23s + flip32s + flip22s + flip44s;
11229   if (checksubfaces) {
11230     //maxfaces = (4l * tetrahedrons->items + hullsize) / 2l; // commented out to get gcc 4.6 working
11231     fcount = 0;
11232   }
11233 
11234   if (plastflip != (badface **) NULL) {
11235     // Initialize the stack of the flip sequence.
11236     flipstackers->restart();
11237     *plastflip = (badface *) NULL;
11238   }
11239 
11240   // Loop until the queue is empty.
11241   while (!flipqueue->empty()) {
11242     qface = (badface *) flipqueue->pop();
11243     flipface = qface->tt;
11244     if (isdead(&flipface)) continue;
11245     sym(flipface, symface);
11246     // Only do check when the adjacent tet exists and it's not a "fake" tet.
11247     if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11248       // For positive orientation that insphere() test requires.
11249       adjustedgering(flipface, CW);
11250       pa = org(flipface);
11251       pb = dest(flipface);
11252       pc = apex(flipface);
11253       pd = oppo(flipface);
11254       pe = oppo(symface);
11255       if (symbolic) {
11256         ia = pointmark(pa);
11257         ib = pointmark(pb);
11258         ic = pointmark(pc);
11259         id = pointmark(pd);
11260         ie = pointmark(pe);
11261         sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
11262         assert(sign != 0.0);
11263       } else {
11264         sign = insphere(pa, pb, pc, pd, pe);
11265       }
11266     } else {
11267       sign = -1.0; // A hull face is locally Delaunay.
11268     }
11269     if (sign > 0.0) {
11270       // 'flipface' is non-locally Delaunay, try to flip it.
11271       if (checksubfaces) {
11272         fcount++;
11273         bakepsilon = b->epsilon;
11274         epscount = 0;
11275         while (epscount < 32) {
11276           fc = categorizeface(flipface);
11277           if (fc == N40) {
11278             b->epsilon *= 1e-1;
11279             epscount++;
11280             continue;
11281           }
11282           break;
11283         }
11284         b->epsilon = bakepsilon;
11285         if (epscount >= 32) {
11286           if (b->verbose > 0) {
11287             printf("Warning:  Can't flip a degenerate tetrahedron.\n");
11288           }
11289           fc = N40;
11290         }
11291       } else {
11292         fc = categorizeface(flipface);
11293 #ifdef SELF_CHECK
11294         assert(fc != N40);
11295 #endif
11296       }
11297       switch (fc) {
11298       // The following face types are flipable.
11299       case T44:
11300       case T22:
11301         flip22(&flipface, flipqueue);
11302         break;
11303       case T23:
11304         flip23(&flipface, flipqueue);
11305         break;
11306       case T32:
11307         flip32(&flipface, flipqueue);
11308         break;
11309       // The following face types are unflipable.
11310       case N32:
11311         break;
11312       case FORBIDDENFACE:
11313         break;
11314       case FORBIDDENEDGE:
11315         break;
11316       // This case is only possible when the domain is nonconvex.
11317       case N40:
11318         // assert(nonconvex);
11319         break;
11320       }
11321       if (plastflip != (badface **) NULL) {
11322         if ((fc == T44) || (fc == T22) || (fc == T23) || (fc == T32)) {
11323           // Push the flipped face into stack.
11324           newflip = (badface *) flipstackers->alloc();
11325           newflip->tt = flipface;
11326           newflip->key = (REAL) fc;
11327           newflip->forg = org(flipface);
11328           newflip->fdest = dest(flipface);
11329           newflip->fapex = apex(flipface);
11330           newflip->previtem = *plastflip;
11331           *plastflip = newflip;
11332         }
11333       }
11334     }
11335   }
11336 
11337   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11338   if (b->verbose > 1) {
11339     printf("    %ld flips.\n", flipcount);
11340   }
11341 
11342   return flipcount;
11343 }
11344 
11346 //                                                                           //
11347 // lawson()    Flip locally non-Delaunay faces by Lawson's algorithm.        //
11348 //                                                                           //
11350 
11351 long tetgenmesh::lawson(list *misseglist, queue* flipqueue)
11352 {
11353   badface *qface, *misseg;
11354   triface flipface, symface;
11355   triface starttet, spintet;
11356   face checksh, checkseg;
11357   point pa, pb, pc, pd, pe;
11358   point swappt;
11359   REAL sign, ori;
11360   long flipcount;
11361   int ia, ib, ic, id, ie;
11362   int hitbdry, i;
11363 
11364   if (b->verbose > 1) {
11365     printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
11366   }
11367   flipcount = flip23s + flip32s + flip22s + flip44s;
11368 
11369   // Go through the stack of possible flips and decide whether to do them.
11370   //   Note that during the loop new possible flips will be pushed onto
11371   //   this stack, while they popped in this loop.
11372   while (!flipqueue->empty()) {
11373     qface = (badface *) flipqueue->pop();
11374     flipface = qface->tt;
11375     // Check if tet has already been flipped out of existence.
11376     if (!isdead(&flipface)) {
11377       sym(flipface, symface);
11378       // Check if this tet is the same as the one which was stacked.
11379       if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11380         flipface.ver = 0; // Select the CCW ring.
11381         pa = org(flipface);
11382         pb = dest(flipface);
11383         pc = apex(flipface);
11384         pd = oppo(flipface);
11385         pe = oppo(symface);
11386         if (symbolic) {
11387           ia = pointmark(pa);
11388           ib = pointmark(pb);
11389           ic = pointmark(pc);
11390           id = pointmark(pd);
11391           ie = pointmark(pe);
11392           sign = insphere_sos(pb, pa, pc, pd, pe, ib, ia, ic, id, ie);
11393         } else {
11394           sign = insphere(pb, pa, pc, pd, pe);
11395         }
11396         if (sign > 0.0) {
11397           for (i = 0; i < 3; i++) {
11398             ori = orient3d(pa, pb, pd, pe);
11399             if (ori > 0.0) {
11400               // Goto and check the next edge.
11401               swappt = pa;
11402               pa = pb;
11403               pb = pc;
11404               pc = swappt;
11405               enextself(flipface);
11406             } else {
11407               break; // either (ori < 0.0) or (ori == 0.0)
11408             }
11409           } // for (i = 0; ....)
11410           if (ori > 0.0) {
11411             // All three edges are convex, a 2-3 flip is possible.
11412             if (checksubfaces) {
11413               tspivot(flipface, checksh);
11414               if (checksh.sh != dummysh) {
11415                 // A subface is not flipable.
11416                 continue;
11417               }
11418             }
11419             flip23(&flipface, flipqueue);
11420           } else if (ori < 0.0) {
11421             // The edge (a, b) is non-convex, check for a 3-2 flip.
11422             fnext(flipface, symface);
11423             symself(symface);
11424             if (oppo(symface) == pe) {
11425               // Only three tets adjoining this edge.
11426               if (checksubfaces) {
11427                 tsspivot(&flipface, &checkseg);
11428                 if (checkseg.sh != dummysh) {
11429                   // A subsegment is not flipable.
11430                   continue;
11431                 }
11432               } else if (checksubsegs) {
11433                 tsspivot1(flipface, checkseg);
11434                 if (checkseg.sh != dummysh) {
11435                   if (b->verbose > 2) {
11436                     printf("    Queuing missing segment (%d, %d).\n",
11437                       pointmark(org(flipface)), pointmark(dest(flipface)));
11438                   }
11439                   misseg = (badface *) misseglist->append(NULL);
11440                   misseg->ss = checkseg;
11441                   misseg->forg = sorg(checkseg);
11442                   misseg->fdest = sdest(checkseg);
11443                   // Detach all tets having this seg.
11444                   starttet = flipface;
11445                   adjustedgering(starttet, CCW);
11446                   fnextself(starttet);
11447                   spintet = starttet;
11448                   hitbdry = 0;
11449                   do {
11450                     tssdissolve1(spintet);
11451                     if (!fnextself(spintet)) {
11452                       hitbdry++;
11453                       if (hitbdry < 2) {
11454                         esym(starttet, spintet);
11455                         if (!fnextself(spintet)) {
11456                           hitbdry++;
11457                         }
11458                       }
11459                     }
11460                   } while ((apex(spintet) != apex(starttet)) && (hitbdry < 2));
11461                 }
11462               } // if (checksubfaces)
11463               flip32(&flipface, flipqueue);
11464             }
11465           } else {
11466             // Four points (a, b, d, e) are coplanar.
11467             fnext(flipface, symface);
11468             if (fnextself(symface)) {
11469               // Check for a 4-4 flip.
11470               fnextself(symface);
11471               if (apex(symface) == pe) {
11472                 if (checksubfaces) {
11473                   tsspivot(&flipface, &checkseg);
11474                   if (checkseg.sh != dummysh) {
11475                     // A subsegment is not flippable.
11476                     continue;
11477                   }
11478                 } else if (checksubsegs) {
11479                   tsspivot1(flipface, checkseg);
11480                   if (checkseg.sh != dummysh) {
11481                     if (b->verbose > 2) {
11482                       printf("    Queuing missing segment (%d, %d).\n",
11483                         pointmark(org(flipface)), pointmark(dest(flipface)));
11484                     }
11485                     misseg = (badface *) misseglist->append(NULL);
11486                     misseg->ss = checkseg;
11487                     misseg->forg = sorg(checkseg);
11488                     misseg->fdest = sdest(checkseg);
11489                     // Detach all tets having this seg.
11490                     starttet = flipface;
11491                     adjustedgering(starttet, CCW);
11492                     fnextself(starttet);
11493                     spintet = starttet;
11494                     hitbdry = 0;
11495                     do {
11496                       tssdissolve1(spintet);
11497                       if (!fnextself(spintet)) {
11498                         hitbdry++;
11499                         if (hitbdry < 2) {
11500                           esym(starttet, spintet);
11501                           if (!fnextself(spintet)) {
11502                             hitbdry++;
11503                           }
11504                         }
11505                       }
11506                     } while ((apex(spintet) != apex(starttet)) &&
11507                              (hitbdry < 2));
11508                   }
11509                 } // if (checksubfaces)
11510                 flip22(&flipface, flipqueue);
11511               }
11512             } else {
11513               // Check for a 2-2 flip.
11514               esym(flipface, symface);
11515               fnextself(symface);
11516               symself(symface);
11517               if (symface.tet == dummytet) {
11518                 if (checksubfaces) {
11519                   tsspivot(&flipface, &checkseg);
11520                   if (checkseg.sh != dummysh) {
11521                     // A subsegment is not flipable.
11522                     continue;
11523                   }
11524                 } else if (checksubsegs) {
11525                   tsspivot1(flipface, checkseg);
11526                   if (checkseg.sh != dummysh) {
11527                     if (b->verbose > 2) {
11528                       printf("    Queuing missing segment (%d, %d).\n",
11529                         pointmark(org(flipface)), pointmark(dest(flipface)));
11530                     }
11531                     misseg = (badface *) misseglist->append(NULL);
11532                     misseg->ss = checkseg;
11533                     misseg->forg = sorg(checkseg);
11534                     misseg->fdest = sdest(checkseg);
11535                     // Detach all tets having this seg.
11536                     starttet = flipface;
11537                     adjustedgering(starttet, CCW);
11538                     fnextself(starttet);
11539                     spintet = starttet;
11540                     hitbdry = 0;
11541                     do {
11542                       tssdissolve1(spintet);
11543                       if (!fnextself(spintet)) {
11544                         hitbdry++;
11545                         if (hitbdry < 2) {
11546                           esym(starttet, spintet);
11547                           if (!fnextself(spintet)) {
11548                             hitbdry++;
11549                           }
11550                         }
11551                       }
11552                     } while ((apex(spintet) != apex(starttet)) &&
11553                              (hitbdry < 2));
11554                   }
11555                 } // if (checksubfaces)
11556                 flip22(&flipface, flipqueue);
11557               }
11558             }
11559           } // if (ori > 0.0)
11560         } // if (sign > 0.0)
11561       }
11562     } // !isdead(&qface->tt)
11563   } // while (!flipqueue->empty())
11564 
11565   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11566   if (b->verbose > 1) {
11567     printf("    %ld flips.\n", flipcount);
11568   }
11569   return flipcount;
11570 }
11571 
11573 //                                                                           //
11574 // undoflip()    Undo the most recent flip sequence induced by flip().       //
11575 //                                                                           //
11576 // 'lastflip' is the stack of recently flipped faces. Walks through the list //
11577 // of flips, in the reverse of the order in which they were done, and undoes //
11578 // them.                                                                     //
11579 //                                                                           //
11581 
11582 void tetgenmesh::undoflip(badface *lastflip)
11583 {
11584   enum fliptype fc;
11585 
11586   while (lastflip != (badface *) NULL) {
11587     // Get the right flipped face.
11588     findface(&lastflip->tt, lastflip->forg, lastflip->fdest, lastflip->fapex);
11589     fc = (enum fliptype) (int) lastflip->key;
11590     switch (fc) {
11591     case T23:
11592       // The reverse operation of T23 is T32.
11593       flip32(&lastflip->tt, NULL);
11594       break;
11595     case T32:
11596       // The reverse operation of T32 is T23.
11597       flip23(&lastflip->tt, NULL);
11598       break;
11599     case T22:
11600     case T44:
11601       // The reverse operation of T22 or T44 is again T22 or T44.
11602       flip22(&lastflip->tt, NULL);
11603       break;
11604     default: // To omit compile warnings.
11605       break;
11606     }
11607     // Go on and process the next transformation.
11608     lastflip = lastflip->previtem;
11609   }
11610 }
11611 
11613 //                                                                           //
11614 // flipsub()    Flip non-Delaunay edges in a queue of (coplanar) subfaces.   //
11615 //                                                                           //
11616 // Assumpation:  Current triangulation T contains non-Delaunay edges (after  //
11617 // inserting a point or performing a flip). Non-Delaunay edges are queued in //
11618 // 'facequeue'. Returns the total number of flips done during this call.     //
11619 //                                                                           //
11621 
11622 long tetgenmesh::flipsub(queue* flipqueue)
11623 {
11624   badface *qedge;
11625   face flipedge, symedge;
11626   face checkseg;
11627   point pa, pb, pc, pd;
11628   REAL vab[3], vac[3], vad[3];
11629   REAL dot1, dot2, lac, lad;
11630   REAL sign, ori;
11631   int edgeflips;
11632   int i;
11633 
11634   if (b->verbose > 1) {
11635     printf("  Start do edge queue: %ld edges.\n", flipqueue->len());
11636   }
11637 
11638   edgeflips = 0;
11639 
11640   while (!flipqueue->empty()) {
11641     qedge = (badface *) flipqueue->pop();
11642     flipedge = qedge->ss;
11643     if (flipedge.sh == dummysh) continue;
11644     if ((sorg(flipedge) != qedge->forg) ||
11645         (sdest(flipedge) != qedge->fdest)) continue;
11646     sspivot(flipedge, checkseg);
11647     if (checkseg.sh != dummysh) continue;  // Can't flip a subsegment.
11648     spivot(flipedge, symedge);
11649     if (symedge.sh == dummysh) continue; // Can't flip a hull edge.
11650     pa = sorg(flipedge);
11651     pb = sdest(flipedge);
11652     pc = sapex(flipedge);
11653     pd = sapex(symedge);
11654     // Choose the triangle abc or abd as the base depending on the angle1
11655     //   (Vac, Vab) and angle2 (Vad, Vab).
11656     for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
11657     for (i = 0; i < 3; i++) vac[i] = pc[i] - pa[i];
11658     for (i = 0; i < 3; i++) vad[i] = pd[i] - pa[i];
11659     dot1 = dot(vac, vab);
11660     dot2 = dot(vad, vab);
11661     dot1 *= dot1;
11662     dot2 *= dot2;
11663     lac = dot(vac, vac);
11664     lad = dot(vad, vad);
11665     if (lad * dot1 <= lac * dot2) {
11666       // angle1 is closer to 90 than angle2, choose abc (flipedge).
11667       abovepoint = facetabovepointarray[shellmark(flipedge)];
11668       if (abovepoint == (point) NULL) {
11669         getfacetabovepoint(&flipedge);
11670       }
11671       sign = insphere(pa, pb, pc, abovepoint, pd);
11672       ori = orient3d(pa, pb, pc, abovepoint);
11673     } else {
11674       // angle2 is closer to 90 than angle1, choose abd (symedge).
11675       abovepoint = facetabovepointarray[shellmark(symedge)];
11676       if (abovepoint == (point) NULL) {
11677         getfacetabovepoint(&symedge);
11678       }
11679       sign = insphere(pa, pb, pd, abovepoint, pc);
11680       ori = orient3d(pa, pb, pd, abovepoint);
11681     }
11682     // Correct the sign.
11683     sign = ori > 0.0 ? sign : -sign;
11684     if (sign > 0.0) {
11685       // Flip the non-Delaunay edge.
11686       flip22sub(&flipedge, flipqueue);
11687       edgeflips++;
11688     }
11689   }
11690 
11691   if (b->verbose > 1) {
11692     printf("  Total %d flips.\n", edgeflips);
11693   }
11694 
11695   return edgeflips;
11696 }
11697 
11699 //                                                                           //
11700 // removetetbypeeloff()    Remove a boundary tet by peeling it off.          //
11701 //                                                                           //
11702 // 'striptet' (abcd) is on boundary and can be removed by stripping it off.  //
11703 // Let abc and bad are the external boundary faces.                          //
11704 //                                                                           //
11705 // To strip 'abcd' from the mesh is to detach its two interal faces (dca and //
11706 // cdb) from their adjoining tets together with a 2-to-2 flip to transform   //
11707 // two subfaces (abc and bad) into another two (dca and cdb).                //
11708 //                                                                           //
11709 // In mesh optimization. It is possible that ab is a segment and abcd is a   //
11710 // sliver on the hull. Strip abcd will also delete the segment ab.           //
11711 //                                                                           //
11713 
11714 bool tetgenmesh::removetetbypeeloff(triface *striptet)
11715 {
11716   triface abcd, badc;
11717   triface dcacasing, cdbcasing;
11718   face abc, bad;
11719   face abseg;
11720   REAL ang;
11721 
11722   abcd = *striptet;
11723   adjustedgering(abcd, CCW);
11724   // Get the casing tets at the internal sides.
11725   enextfnext(abcd, cdbcasing);
11726   enext2fnext(abcd, dcacasing);
11727   symself(cdbcasing);
11728   symself(dcacasing);
11729   // Do the neighboring tets exist?  During optimization. It is possible
11730   //   that the neighboring tets are already dead.
11731   if ((cdbcasing.tet == dummytet) || (dcacasing.tet == dummytet)) {
11732     // Do not strip this tet.
11733     return false;
11734   }
11735 
11736   // Are there subfaces?
11737   if (checksubfaces) {
11738     // Get the external subfaces abc, bad.
11739     fnext(abcd, badc);
11740     esymself(badc);
11741     tspivot(abcd, abc);
11742     tspivot(badc, bad);
11743     if (abc.sh != dummysh) {
11744       assert(bad.sh != dummysh);
11745       findedge(&abc, org(abcd), dest(abcd));
11746       findedge(&bad, org(badc), dest(badc));
11747       // Is ab a segment?
11748       sspivot(abc, abseg);
11749       if (abseg.sh != dummysh) {
11750         // Does a segment allow to be removed?
11751         if ((b->optlevel > 3) && (b->nobisect == 0)) {
11752           // Only remove this segment if the dihedal angle at ab is between
11753           //   [b->maxdihedral-9, 180] (deg).  This avoids mistakely fliping
11754           //   ab when it has actually no big dihedral angle while cd has.
11755           ang = facedihedral(org(abcd), dest(abcd), apex(abcd), oppo(abcd));
11756           ang = ang * 180.0 / PI;
11757           if ((ang + 9.0) > b->maxdihedral) {
11758             if (b->verbose > 1) {
11759               printf("    Remove a segment during peeling.\n");
11760             }
11761             face prevseg, nextseg;
11762             // It is only shared by abc and bad (abcd is a tet).
11763             ssdissolve(abc);
11764             ssdissolve(bad);
11765             abseg.shver = 0;
11766             senext(abseg, nextseg);
11767             spivotself(nextseg);
11768             if (nextseg.sh != dummysh) {
11769               ssdissolve(nextseg);
11770             }
11771             senext2(abseg, prevseg);
11772             spivotself(prevseg);
11773             if (prevseg.sh != dummysh) {
11774               ssdissolve(prevseg);
11775             }
11776             shellfacedealloc(subsegs, abseg.sh);
11777             optcount[1]++;
11778           } else {
11779             return false;
11780           }
11781         } else {
11782           return false;
11783         }
11784       }
11785       // Do a 2-to-2 flip on abc and bad, transform abc->dca, bad->cdb.
11786       flip22sub(&abc, NULL);
11787       // The two internal faces become boundary faces.
11788       tsbond(cdbcasing, bad);
11789       tsbond(dcacasing, abc);
11790     }
11791   }
11792 
11793   // Detach abcd from the two internal faces.
11794   dissolve(cdbcasing);
11795   dissolve(dcacasing);
11796   // Delete abcd.
11797   tetrahedrondealloc(abcd.tet);
11798   return true;
11799 }
11800 
11802 //                                                                           //
11803 // removeedgebyflip22()    Remove an edge by a 2-to-2 (or 4-to-4) flip.      //
11804 //                                                                           //
11805 // 'abtetlist' contains n tets (n is 2 or 4) sharing edge ab,  abtetlist[0]  //
11806 // and abtetlist[1] are tets abec and abde, respectively (NOTE, both are in  //
11807 // CW edge ring), where a, b, c, and d are coplanar.  If n = 4, abtetlist[2] //
11808 // and abtetlist[3] are tets abfd and abcf, respectively.  This routine uses //
11809 // flip22() to replace edge ab with cd, the surrounding tets are rotated.    //
11810 //                                                                           //
11811 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
11812 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
11813 // is the maximum dihedral angle in the old tets.                            //
11814 //                                                                           //
11816 
11817 bool tetgenmesh::removeedgebyflip22(REAL *key, int n, triface *abtetlist,
11818   queue *flipque)
11819 {
11820   point pa, pb, pc, pd, pe, pf;
11821   REAL cosmaxd, d1, d2, d3;
11822   bool doflip;
11823 
11824   cosmaxd = 0.0;
11825   pf = apex(abtetlist[2]);
11826   doflip = true;
11827   adjustedgering(abtetlist[0], CW);
11828   pa = org(abtetlist[0]);
11829   pb = dest(abtetlist[0]);
11830   pe = apex(abtetlist[0]);
11831   pc = oppo(abtetlist[0]);
11832   pd = apex(abtetlist[1]);
11833   if (n == 4) {
11834     pf = apex(abtetlist[2]);
11835   }
11836   if (key && (*key > -1.0)) {
11837     tetalldihedral(pc, pd, pe, pa, NULL, &d1, NULL);
11838     tetalldihedral(pd, pc, pe, pb, NULL, &d2, NULL);
11839     cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11840     if (n == 4) {
11841       tetalldihedral(pd, pc, pf, pa, NULL, &d1, NULL);
11842       tetalldihedral(pc, pd, pf, pb, NULL, &d2, NULL);
11843       d3 = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11844       cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
11845     }
11846     doflip = (*key < cosmaxd); // Can local quality be improved?
11847   }
11848 
11849   if (doflip) {
11850     flip22(&abtetlist[0], NULL);
11851     // Return the improved quality value.
11852     if (key) *key = cosmaxd;
11853   }
11854 
11855   return doflip;
11856 }
11857 
11859 //                                                                           //
11860 // removefacebyflip23()    Remove a face by a 2-to-3 flip.                   //
11861 //                                                                           //
11862 // 'abctetlist' contains 2 tets sharing abc, which are [0]abcd and [1]bace.  //
11863 // This routine forms three new tets that abc is not a face anymore. Save    //
11864 // them in 'newtetlist': [0]edab, [1]edbc, and [2]edca.  Note that the new   //
11865 // tets may not valid if one of them get inverted. return false if so.       //
11866 //                                                                           //
11867 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
11868 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
11869 // is the maximum dihedral angle in the old tets.                            //
11870 //                                                                           //
11871 // If the face is flipped, 'newtetlist' returns the three new tets. The two  //
11872 // tets in 'abctetlist' are NOT deleted.  The caller has the right to either //
11873 // delete them or reverse the operation.                                     //
11874 //                                                                           //
11876 
11877 bool tetgenmesh::removefacebyflip23(REAL *key, triface *abctetlist,
11878   triface *newtetlist, queue *flipque)
11879 {
11880   triface edab, edbc, edca; // new configuration.
11881   triface newfront, oldfront, adjfront;
11882   face checksh;
11883   point pa, pb, pc, pd, pe;
11884   REAL ori, cosmaxd, d1, d2, d3;
11885   REAL attrib, volume;
11886   bool doflip;
11887   int i;
11888 
11889   cosmaxd = 0.0;
11890 
11891   adjustedgering(abctetlist[0], CCW);
11892   pa = org(abctetlist[0]);
11893   pb = dest(abctetlist[0]);
11894   pc = apex(abctetlist[0]);
11895   pd = oppo(abctetlist[0]);
11896   pe = oppo(abctetlist[1]);
11897 
11898   // Check if the flip creates valid new tets.
11899   ori = orient3d(pe, pd, pa, pb);
11900   if (ori < 0.0) {
11901     ori = orient3d(pe, pd, pb, pc);
11902     if (ori < 0.0) {
11903       ori = orient3d(pe, pd, pc, pa);
11904     }
11905   }
11906   doflip = (ori < 0.0); // Can abc be flipped away?
11907   if (doflip && (key != (REAL *) NULL)) {
11908     if (*key > -1.0) {
11909       // Test if the new tets reduce the maximal dihedral angle.
11910       tetalldihedral(pe, pd, pa, pb, NULL, &d1, NULL);
11911       tetalldihedral(pe, pd, pb, pc, NULL, &d2, NULL);
11912       tetalldihedral(pe, pd, pc, pa, NULL, &d3, NULL);
11913       cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11914       cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
11915       doflip = (*key < cosmaxd); // Can local quality be improved?
11916     }
11917   }
11918 
11919   if (doflip) {
11920     // A valid (2-to-3) flip is found.
11921     flip23s++;
11922     // Create the new tets.
11923     maketetrahedron(&edab);
11924     setorg(edab, pe);
11925     setdest(edab, pd);
11926     setapex(edab, pa);
11927     setoppo(edab, pb);
11928     maketetrahedron(&edbc);
11929     setorg(edbc, pe);
11930     setdest(edbc, pd);
11931     setapex(edbc, pb);
11932     setoppo(edbc, pc);
11933     maketetrahedron(&edca);
11934     setorg(edca, pe);
11935     setdest(edca, pd);
11936     setapex(edca, pc);
11937     setoppo(edca, pa);
11938     // Transfer the element attributes.
11939     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
11940       attrib = elemattribute(abctetlist[0].tet, i);
11941       setelemattribute(edab.tet, i, attrib);
11942       setelemattribute(edbc.tet, i, attrib);
11943       setelemattribute(edca.tet, i, attrib);
11944     }
11945     // Transfer the volume constraints.
11946     if (b->varvolume && !b->refine) {
11947       volume = volumebound(abctetlist[0].tet);
11948       setvolumebound(edab.tet, volume);
11949       setvolumebound(edbc.tet, volume);
11950       setvolumebound(edca.tet, volume);
11951     }
11952     // Return two new tets.
11953     newtetlist[0] = edab;
11954     newtetlist[1] = edbc;
11955     newtetlist[2] = edca;
11956     // Glue the three new tets.
11957     for (i = 0; i < 3; i++) {
11958       fnext(newtetlist[i], newfront);
11959       bond(newfront, newtetlist[(i + 1) % 3]);
11960     }
11961     // Substitute the three new tets into the old cavity.
11962     for (i = 0; i < 3; i++) {
11963       fnext(abctetlist[0], oldfront);
11964       sym(oldfront, adjfront); // may be outside.
11965       enextfnext(newtetlist[i], newfront);
11966       bond(newfront, adjfront);
11967       if (checksubfaces) {
11968         tspivot(oldfront, checksh);
11969         if (checksh.sh != dummysh) {
11970           tsbond(newfront, checksh);
11971         }
11972       }
11973       if (flipque != (queue *) NULL) {
11974         enqueueflipface(newfront, flipque);
11975       }
11976       enextself(abctetlist[0]);
11977     }
11978     findedge(&(abctetlist[1]), pb, pa);
11979     for (i = 0; i < 3; i++) {
11980       fnext(abctetlist[1], oldfront);
11981       sym(oldfront, adjfront); // may be outside.
11982       enext2fnext(newtetlist[i], newfront);
11983       bond(newfront, adjfront);
11984       if (checksubfaces) {
11985         tspivot(oldfront, checksh);
11986         if (checksh.sh != dummysh) {
11987           tsbond(newfront, checksh);
11988         }
11989       }
11990       if (flipque != (queue *) NULL) {
11991         enqueueflipface(newfront, flipque);
11992       }
11993       enext2self(abctetlist[1]);
11994     }
11995     // Do not delete the old tets.
11996     // for (i = 0; i < 2; i++) {
11997     //   tetrahedrondealloc(abctetlist[i].tet);
11998     // }
11999     // Return the improved quality value.
12000     if (key != (REAL *) NULL) *key = cosmaxd;
12001     return true;
12002   }
12003 
12004   return false;
12005 }
12006 
12008 //                                                                           //
12009 // removeedgebyflip32()    Remove an edge by a 3-to-2 flip.                  //
12010 //                                                                           //
12011 // 'abtetlist' contains 3 tets sharing ab. Imaging that ab is perpendicular  //
12012 // to the screen, where a lies in front of and b lies behind it. The 3 tets  //
12013 // of the list are: [0]abce, [1]abdc, and [2]abed, respectively.             //
12014 //                                                                           //
12015 // This routine forms two new tets that ab is not an edge of them. Save them //
12016 // in 'newtetlist', [0]dcea, [1]cdeb. Note that the new tets may not valid   //
12017 // if one of them get inverted. return false if so.                          //
12018 //                                                                           //
12019 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
12020 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
12021 // is the maximum dihedral angle in the old tets.                            //
12022 //                                                                           //
12023 // If the edge is flipped, 'newtetlist' returns the two new tets. The three  //
12024 // tets in 'abtetlist' are NOT deleted.  The caller has the right to either  //
12025 // delete them or reverse the operation.                                     //
12026 //                                                                           //
12028 
12029 bool tetgenmesh::removeedgebyflip32(REAL *key, triface *abtetlist,
12030   triface *newtetlist, queue *flipque)
12031 {
12032   triface dcea, cdeb; // new configuration.
12033   triface newfront, oldfront, adjfront;
12034   face checksh;
12035   point pa, pb, pc, pd, pe;
12036   REAL ori, cosmaxd, d1, d2;
12037   REAL attrib, volume;
12038   bool doflip;
12039   int i;
12040 
12041   pa = org(abtetlist[0]);
12042   pb = dest(abtetlist[0]);
12043   pc = apex(abtetlist[0]);
12044   pd = apex(abtetlist[1]);
12045   pe = apex(abtetlist[2]);
12046 
12047   ori = orient3d(pd, pc, pe, pa);
12048   if (ori < 0.0) {
12049     ori = orient3d(pc, pd, pe, pb);
12050   }
12051   doflip = (ori < 0.0); // Can ab be flipped away?
12052 
12053   // Does the caller ensure a valid configuration?
12054   if (doflip && (key != (REAL *) NULL)) {
12055     if (*key > -1.0) {
12056       // Test if the new tets reduce the maximal dihedral angle.
12057       tetalldihedral(pd, pc, pe, pa, NULL, &d1, NULL);
12058       tetalldihedral(pc, pd, pe, pb, NULL, &d2, NULL);
12059       cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
12060       doflip = (*key < cosmaxd); // Can local quality be improved?
12061       // Return the key
12062       *key = cosmaxd;
12063     }
12064   }
12065 
12066   if (doflip) {
12067     // Create the new tets.
12068     maketetrahedron(&dcea);
12069     setorg(dcea, pd);
12070     setdest(dcea, pc);
12071     setapex(dcea, pe);
12072     setoppo(dcea, pa);
12073     maketetrahedron(&cdeb);
12074     setorg(cdeb, pc);
12075     setdest(cdeb, pd);
12076     setapex(cdeb, pe);
12077     setoppo(cdeb, pb);
12078     // Transfer the element attributes.
12079     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12080       attrib = elemattribute(abtetlist[0].tet, i);
12081       setelemattribute(dcea.tet, i, attrib);
12082       setelemattribute(cdeb.tet, i, attrib);
12083     }
12084     // Transfer the volume constraints.
12085     if (b->varvolume && !b->refine) {
12086       volume = volumebound(abtetlist[0].tet);
12087       setvolumebound(dcea.tet, volume);
12088       setvolumebound(cdeb.tet, volume);
12089     }
12090     // Return two new tets.
12091     newtetlist[0] = dcea;
12092     newtetlist[1] = cdeb;
12093     // Glue the two new tets.
12094     bond(dcea, cdeb);
12095     // Substitute the two new tets into the old three-tets cavity.
12096     for (i = 0; i < 3; i++) {
12097       fnext(dcea, newfront); // face dca, cea, eda.
12098       esym(abtetlist[(i + 1) % 3], oldfront);
12099       enextfnextself(oldfront);
12100       // Get the adjacent tet at the face (may be a dummytet).
12101       sym(oldfront, adjfront);
12102       bond(newfront, adjfront);
12103       if (checksubfaces) {
12104         tspivot(oldfront, checksh);
12105         if (checksh.sh != dummysh) {
12106           tsbond(newfront, checksh);
12107         }
12108       }
12109       if (flipque != (queue *) NULL) {
12110         enqueueflipface(newfront, flipque);
12111       }
12112       enext2self(dcea);
12113     }
12114     for (i = 0; i < 3; i++) {
12115       fnext(cdeb, newfront); // face cdb, deb, ecb.
12116       esym(abtetlist[(i + 1) % 3], oldfront);
12117       enext2fnextself(oldfront);
12118       // Get the adjacent tet at the face (may be a dummytet).
12119       sym(oldfront, adjfront);
12120       bond(newfront, adjfront);
12121       if (checksubfaces) {
12122         tspivot(oldfront, checksh);
12123         if (checksh.sh != dummysh) {
12124           tsbond(newfront, checksh);
12125         }
12126       }
12127       if (flipque != (queue *) NULL) {
12128         enqueueflipface(newfront, flipque);
12129       }
12130       enextself(cdeb);
12131     }
12132     // Do not delete the old tets.
12133     // for (i = 0; i < 3; i++) {
12134     //   tetrahedrondealloc(abtetlist[i].tet);
12135     // }
12136     return true;
12137   } // if (doflip)
12138 
12139   return false;
12140 }
12141 
12143 //                                                                           //
12144 // removeedgebytranNM()    Remove an edge by transforming n-to-m tets.       //
12145 //                                                                           //
12146 // This routine attempts to remove a given edge (ab) by transforming the set //
12147 // T of tets surrounding ab into another set T' of tets.  T and T' have the  //
12148 // same outer faces and ab is not an edge of T' anymore. Let |T|=n, and |T'| //
12149 // =m, it is actually a n-to-m flip for n > 3.  The relation between n and m //
12150 // depends on the method, ours is found below.                               //
12151 //                                                                           //
12152 // 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
12153 // to the screen, where a lies in front of and b lies behind it.  Let the    //
12154 // projections of the n apexes onto screen in clockwise order are: p_0, ...  //
12155 // p_n-1, respectively. The tets in the list are: [0]abp_0p_n-1,[1]abp_1p_0, //
12156 // ..., [n-1]abp_n-1p_n-2, respectively.                                     //
12157 //                                                                           //
12158 // The principle of the approach is: Recursively reduce the link of ab by    //
12159 // using flip23 until only three faces remain, hence a flip32 can be applied //
12160 // to remove ab. For a given face a.b.p_0, check a flip23 can be applied on  //
12161 // it, i.e, edge p_1.p_n-1 crosses it. NOTE*** We do the flip even p_1.p_n-1 //
12162 // intersects with a.b (they are coplanar). If so, a degenerate tet (a.b.p_1.//
12163 // p_n-1) is temporarily created, but it will be eventually removed by the   //
12164 // final flip32. This relaxation splits a flip44 into flip23 + flip32. *NOTE //
12165 // Now suppose a.b.p_0 gets flipped, p_0 is not on the link of ab anymore.   //
12166 // The link is then reduced (by 1). 2 of the 3 new tets, p_n-1.p_1.p_0.a and //
12167 // p_1.p_n-1.p_0.b, will be part of the new configuration.  The left new tet,//
12168 // a.b.p_1.p_n-1, goes into the new link of ab. A recurrence can be applied. //
12169 //                                                                           //
12170 // If 'e1' and 'e2' are not NULLs, they specify an wanted edge to appear in  //
12171 // the new tet configuration. In such case, only do flip23 if edge e1<->e2   //
12172 // can be recovered. It is used in removeedgebycombNM().                     //
12173 //                                                                           //
12174 // If ab gets removed. 'newtetlist' contains m new tets.  By using the above //
12175 // approach, the pairs (n, m) can be easily enumerated.  For example, (3, 2),//
12176 // (4, 4), (5, 6), (6, 8), (7, 10), (8, 12), (9, 14), (10, 16),  and so on.  //
12177 // It is easy to deduce, that m = (n - 2) * 2, when n >= 3.  The n tets in   //
12178 // 'abtetlist' are NOT deleted in this routine. The caller has the right to  //
12179 // either delete them or reverse this operation.                             //
12180 //                                                                           //
12182 
12183 bool tetgenmesh::removeedgebytranNM(REAL *key, int n, triface *abtetlist,
12184   triface *newtetlist, point e1, point e2, queue *flipque)
12185 {
12186   triface tmpabtetlist[9]; // Temporary max 9 tets configuration.
12187   triface newfront, oldfront, adjfront;
12188   face checksh;
12189   point pa, pb, p[10];
12190   REAL ori, cosmaxd, d1, d2;
12191   REAL tmpkey;
12192   REAL attrib, volume;
12193   bool doflip, copflag, success;
12194   int i, j, k;
12195 
12196   cosmaxd = 0.0;
12197   // Maximum 10 tets.
12198   assert(n <= 10);
12199   // Two points a and b are fixed.
12200   pa = org(abtetlist[0]);
12201   pb = dest(abtetlist[0]);
12202   // The points p_0, p_1, ..., p_n-1 are permuted in each new configuration.
12203   //   These permutations can be easily done in the following loop.
12204   // Loop through all the possible new tets configurations. Stop on finding
12205   //   a valid new tet configuration which also immproves the quality value.
12206   for (i = 0; i < n; i++) {
12207     // Get other n points for the current configuration.
12208     for (j = 0; j < n; j++) {
12209       p[j] = apex(abtetlist[(i + j) % n]);
12210     }
12211     // Is there a wanted edge?
12212     if ((e1 != (point) NULL) && (e2 != (point) NULL)) {
12213       // Yes. Skip this face if p[1]<->p[n-1] is not the edge.
12214       if (!(((p[1] == e1) && (p[n - 1] == e2)) ||
12215         ((p[1] == e2) && (p[n - 1] == e1)))) continue;
12216     }
12217     // Test if face a.b.p_0 can be flipped (by flip23), ie, to check if the
12218     //   edge p_n-1.p_1 crosses face a.b.p_0 properly.
12219     // Note. It is possible that face a.b.p_0 has type flip44, ie, a,b,p_1,
12220     //   and p_n-1 are coplanar. A trick is to split the flip44 into two
12221     //   steps: frist a flip23, then a flip32. The first step creates a
12222     //   degenerate tet (vol=0) which will be removed by the second flip.
12223     ori = orient3d(pa, pb, p[1], p[n - 1]);
12224     copflag = (ori == 0.0); // Are they coplanar?
12225     if (ori >= 0.0) {
12226       // Accept the coplanar case which supports flip44.
12227       ori = orient3d(pb, p[0], p[1], p[n - 1]);
12228       if (ori > 0.0) {
12229         ori = orient3d(p[0], pa, p[1], p[n - 1]);
12230       }
12231     }
12232     // Is face abc flipable?
12233     if (ori > 0.0) {
12234       // A valid (2-to-3) flip (or 4-to-4 flip) is found.
12235       copflag ? flip44s++ : flip23s++;
12236       doflip = true;
12237       if (key != (REAL *) NULL) {
12238         if (*key > -1.0) {
12239           // Test if the new tets reduce the maximal dihedral angle. Only 2
12240           //   tets, p_n-1.p_1.p_0.a and p_1.p_n-1.p_0.b, need to be tested
12241           //   The left one a.b.p_n-1.p_1 goes into the new link of ab.
12242           tetalldihedral(p[n - 1], p[1], p[0], pa, NULL, &d1, NULL);
12243           tetalldihedral(p[1], p[n - 1], p[0], pb, NULL, &d2, NULL);
12244           cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
12245           doflip = *key < cosmaxd; // Can the local quality be improved?
12246         }
12247       }
12248       if (doflip) {
12249         tmpkey = key != NULL ? *key : -1.0;
12250         // Create the two new tets.
12251         maketetrahedron(&(newtetlist[0]));
12252         setorg(newtetlist[0], p[n - 1]);
12253         setdest(newtetlist[0], p[1]);
12254         setapex(newtetlist[0], p[0]);
12255         setoppo(newtetlist[0], pa);
12256         maketetrahedron(&(newtetlist[1]));
12257         setorg(newtetlist[1], p[1]);
12258         setdest(newtetlist[1], p[n - 1]);
12259         setapex(newtetlist[1], p[0]);
12260         setoppo(newtetlist[1], pb);
12261         // Create the n - 1 temporary new tets (the new Star(ab)).
12262         maketetrahedron(&(tmpabtetlist[0]));
12263         setorg(tmpabtetlist[0], pa);
12264         setdest(tmpabtetlist[0], pb);
12265         setapex(tmpabtetlist[0], p[n - 1]);
12266         setoppo(tmpabtetlist[0], p[1]);
12267         for (j = 1; j < n - 1; j++) {
12268           maketetrahedron(&(tmpabtetlist[j]));
12269           setorg(tmpabtetlist[j], pa);
12270           setdest(tmpabtetlist[j], pb);
12271           setapex(tmpabtetlist[j], p[j]);
12272           setoppo(tmpabtetlist[j], p[j + 1]);
12273         }
12274         // Transfer the element attributes.
12275         for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12276           attrib = elemattribute(abtetlist[0].tet, j);
12277           setelemattribute(newtetlist[0].tet, j, attrib);
12278           setelemattribute(newtetlist[1].tet, j, attrib);
12279           for (k = 0; k < n - 1; k++) {
12280             setelemattribute(tmpabtetlist[k].tet, j, attrib);
12281           }
12282         }
12283         // Transfer the volume constraints.
12284         if (b->varvolume && !b->refine) {
12285           volume = volumebound(abtetlist[0].tet);
12286           setvolumebound(newtetlist[0].tet, volume);
12287           setvolumebound(newtetlist[1].tet, volume);
12288           for (k = 0; k < n - 1; k++) {
12289             setvolumebound(tmpabtetlist[k].tet, volume);
12290           }
12291         }
12292         // Glue the new tets at their internal faces: 2 + (n - 1).
12293         bond(newtetlist[0], newtetlist[1]); // p_n-1.p_1.p_0.
12294         fnext(newtetlist[0], newfront);
12295         enext2fnext(tmpabtetlist[0], adjfront);
12296         bond(newfront, adjfront); // p_n-1.p_1.a.
12297         fnext(newtetlist[1], newfront);
12298         enextfnext(tmpabtetlist[0], adjfront);
12299         bond(newfront, adjfront); // p_n-1.p_1.b.
12300         // Glue n - 1 internal faces around ab.
12301         for (j = 0; j < n - 1; j++) {
12302           fnext(tmpabtetlist[j], newfront);
12303           bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
12304         }
12305         // Substitute the old tets with the new tets by connecting the new
12306         //   tets to the adjacent tets in the mesh. There are n * 2 (outer)
12307         //   faces of the new tets need to be operated.
12308         // Note, after the substitution, the old tets still have pointers to
12309         //   their adjacent tets in the mesh.  These pointers can be re-used
12310         //   to inverse the substitution.
12311         for (j = 0; j < n; j++) {
12312           // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
12313           oldfront = abtetlist[(i + j) % n];
12314           esymself(oldfront);
12315           enextfnextself(oldfront);
12316           // Get an adjacent tet at face: [0]a.p_0.p_n-1 or [j]a.p_j.p_j-1.
12317           sym(oldfront, adjfront); // adjfront may be dummy.
12318           // Get the corresponding face from the new tets.
12319           if (j == 0) {
12320             enext2fnext(newtetlist[0], newfront); // a.p_0.n_n-1
12321           } else if (j == 1) {
12322             enextfnext(newtetlist[0], newfront); // a.p_1.p_0
12323           } else { // j >= 2.
12324             enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
12325           }
12326           bond(newfront, adjfront);
12327           if (checksubfaces) {
12328             tspivot(oldfront, checksh);
12329             if (checksh.sh != dummysh) {
12330               tsbond(newfront, checksh);
12331             }
12332           }
12333           if (flipque != (queue *) NULL) {
12334             // Only queue the faces of the two new tets.
12335             if (j < 2) enqueueflipface(newfront, flipque);
12336           }
12337         }
12338         for (j = 0; j < n; j++) {
12339           // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
12340           oldfront = abtetlist[(i + j) % n];
12341           esymself(oldfront);
12342           enext2fnextself(oldfront);
12343           // Get an adjacent tet at face: [0]b.p_0.p_n-1 or [j]b.p_j.p_j-1.
12344           sym(oldfront, adjfront); // adjfront may be dummy.
12345           // Get the corresponding face from the new tets.
12346           if (j == 0) {
12347             enextfnext(newtetlist[1], newfront); // b.p_0.n_n-1
12348           } else if (j == 1) {
12349             enext2fnext(newtetlist[1], newfront); // b.p_1.p_0
12350           } else { // j >= 2.
12351             enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
12352           }
12353           bond(newfront, adjfront);
12354           if (checksubfaces) {
12355             tspivot(oldfront, checksh);
12356             if (checksh.sh != dummysh) {
12357               tsbond(newfront, checksh);
12358             }
12359           }
12360           if (flipque != (queue *) NULL) {
12361             // Only queue the faces of the two new tets.
12362             if (j < 2) enqueueflipface(newfront, flipque);
12363           }
12364         }
12365         // Adjust the faces in the temporary new tets at ab for recursively
12366         //   processing on the n-1 tets.(See the description at beginning)
12367         for (j = 0; j < n - 1; j++) {
12368           fnextself(tmpabtetlist[j]);
12369         }
12370         if (n > 4) {
12371           success = removeedgebytranNM(&tmpkey, n-1, tmpabtetlist,
12372             &(newtetlist[2]), NULL, NULL, flipque);
12373         } else { // assert(n == 4);
12374           success = removeedgebyflip32(&tmpkey, tmpabtetlist,
12375             &(newtetlist[2]), flipque);
12376         }
12377         // No matter it was success or not, delete the temporary tets.
12378         for (j = 0; j < n - 1; j++) {
12379           tetrahedrondealloc(tmpabtetlist[j].tet);
12380         }
12381         if (success) {
12382           // The new configuration is good.
12383           // Do not delete the old tets.
12384           // for (j = 0; j < n; j++) {
12385           //   tetrahedrondealloc(abtetlist[j].tet);
12386           // }
12387           // Save the minimal improved quality value.
12388           if (key != (REAL *) NULL) {
12389             *key = (tmpkey < cosmaxd ? tmpkey : cosmaxd);
12390           }
12391           return true;
12392         } else {
12393           // The new configuration is bad, substitue back the old tets.
12394           for (j = 0; j < n; j++) {
12395             oldfront = abtetlist[(i + j) % n];
12396             esymself(oldfront);
12397             enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
12398             sym(oldfront, adjfront); // adjfront may be dummy.
12399             bond(oldfront, adjfront);
12400             if (checksubfaces) {
12401               tspivot(oldfront, checksh);
12402               if (checksh.sh != dummysh) {
12403                 tsbond(oldfront, checksh);
12404               }
12405             }
12406           }
12407           for (j = 0; j < n; j++) {
12408             oldfront = abtetlist[(i + j) % n];
12409             esymself(oldfront);
12410             enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12411             sym(oldfront, adjfront); // adjfront may be dummy
12412             bond(oldfront, adjfront);
12413             if (checksubfaces) {
12414               tspivot(oldfront, checksh);
12415               if (checksh.sh != dummysh) {
12416                 tsbond(oldfront, checksh);
12417               }
12418             }
12419           }
12420           // Delete the new tets.
12421           tetrahedrondealloc(newtetlist[0].tet);
12422           tetrahedrondealloc(newtetlist[1].tet);
12423           // If tmpkey has been modified, then the failure was not due to
12424           //   unflipable configuration, but the non-improvement.
12425           if (key && (tmpkey < *key)) {
12426             *key = tmpkey;
12427             return false;
12428           }
12429         } // if (success)
12430       } // if (doflip)
12431     } // if (ori > 0.0)
12432   } // for (i = 0; i < n; i++)
12433 
12434   return false;
12435 }
12436 
12438 //                                                                           //
12439 // removeedgebycombNM()    Remove an edge by combining two flipNMs.          //
12440 //                                                                           //
12441 // Given a set T of tets surrounding edge ab. The premise is that ab can not //
12442 // be removed by a flipNM. This routine attempts to remove ab by two flipNMs,//
12443 // i.e., first find and flip an edge af (or bf) by flipNM, then flip ab by   //
12444 // flipNM. If it succeeds, two sets T(ab) and T(af) of tets are replaced by  //
12445 // a new set T' and both ab and af are not edges in T' anymore.              //
12446 //                                                                           //
12447 // 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
12448 // to the screen, such that a lies in front of and b lies behind it. Let the //
12449 // projections of the n apexes on the screen in clockwise order are: p_0,...,//
12450 // p_n-1, respectively. So the list of tets are: [0]abp_0p_n-1, [1]abp_1p_0, //
12451 // ..., [n-1]abp_n-1p_n-2, respectively.                                     //
12452 //                                                                           //
12453 // The principle of the approach is: for a face a.b.p_0, check if edge b.p_0 //
12454 // is of type N32 (or N44). If it is, then try to do a flipNM on it. If the  //
12455 // flip is successful, then try to do another flipNM on a.b.  If one of the  //
12456 // two flipNMs fails, restore the old tets as they have never been flipped.  //
12457 // Then try the next face a.b.p_1.  The process can be looped for all faces  //
12458 // having ab. Stop if ab is removed or all faces have been visited. Note in  //
12459 // the above description only b.p_0 is considered, a.p_0 is done by swapping //
12460 // the position of a and b.                                                  //
12461 //                                                                           //
12462 // Similar operations have been described in [Joe,1995].  My approach checks //
12463 // more cases for finding flips than Joe's.  For instance, the cases (1)-(7) //
12464 // of Joe only consider abf for finding a flip (T23/T32).  My approach looks //
12465 // all faces at ab for finding flips. Moreover, the flipNM can flip an edge  //
12466 // whose star may have more than 3 tets while Joe's only works on 3-tet case.//
12467 //                                                                           //
12468 // If ab is removed, 'newtetlist' contains the new tets. Two sets 'abtetlist'//
12469 // (n tets) and 'bftetlist' (n1 tets) have been replaced.  The number of new //
12470 // tets can be calculated by follows: the 1st flip transforms n1 tets into   //
12471 // (n1 - 2) * 2 new tets, however,one of the new tets goes into the new link //
12472 // of ab, i.e., the reduced tet number in Star(ab) is n - 1;  the 2nd flip   //
12473 // transforms n - 1 tets into (n - 3) * 2 new tets. Hence the number of new  //
12474 // tets are: m = ((n1 - 2) * 2 - 1) + (n - 3) * 2.  The old tets are NOT del-//
12475 // eted. The caller has the right to delete them or reverse the operation.   //
12476 //                                                                           //
12478 
12479 bool tetgenmesh::removeedgebycombNM(REAL *key, int n, triface *abtetlist,
12480   int *n1, triface *bftetlist, triface *newtetlist, queue *flipque)
12481 {
12482   triface tmpabtetlist[11];
12483   triface newfront, oldfront, adjfront;
12484   face checksh;
12485   point pa, pb, p[10];
12486   REAL ori, tmpkey, tmpkey2;
12487   REAL attrib, volume;
12488   bool doflip, success;
12489   int twice, count;
12490   int i, j, k, m;
12491 
12492   // Maximal 10 tets in Star(ab).
12493   assert(n <= 10);
12494 
12495   // Do the following procedure twice, one for flipping edge b.p_0 and the
12496   //   other for p_0.a which is symmetric to the first.
12497   twice = 0;
12498   do {
12499     // Two points a and b are fixed.
12500     pa = org(abtetlist[0]);
12501     pb = dest(abtetlist[0]);
12502     // The points p_0, ..., p_n-1 are permuted in the following loop.
12503     for (i = 0; i < n; i++) {
12504       // Get the n points for the current configuration.
12505       for (j = 0; j < n; j++) {
12506         p[j] = apex(abtetlist[(i + j) % n]);
12507       }
12508       // Check if b.p_0 is of type N32 or N44.
12509       ori = orient3d(pb, p[0], p[1], p[n - 1]);
12510       if ((ori > 0) && (key != (REAL *) NULL)) {
12511         // b.p_0 is not N32. However, it is possible that the tet b.p_0.p_1.
12512         //   p_n-1 has worse quality value than the key. In such case, also
12513         //   try to flip b.p_0.
12514         tetalldihedral(pb, p[0], p[n - 1], p[1], NULL, &tmpkey, NULL);
12515         if (tmpkey < *key) ori = 0.0;
12516       }
12517       if (ori <= 0.0) {
12518         // b.p_0 is either N32 or N44. Try the 1st flipNM.
12519         bftetlist[0] = abtetlist[i];
12520         enextself(bftetlist[0]);// go to edge b.p_0.
12521         adjustedgering(bftetlist[0], CW); // edge p_0.b.
12522         assert(apex(bftetlist[0]) == pa);
12523         // Form Star(b.p_0).
12524         doflip = true;
12525         *n1 = 0;
12526         do {
12527           // Is the list full?
12528           if (*n1 == 10) break;
12529           if (checksubfaces) {
12530             // Stop if a subface appears.
12531             tspivot(bftetlist[*n1], checksh);
12532             if (checksh.sh != dummysh) {
12533               doflip = false; break;
12534             }
12535           }
12536           // Get the next tet at p_0.b.
12537           fnext(bftetlist[*n1], bftetlist[(*n1) + 1]);
12538           (*n1)++;
12539         } while (apex(bftetlist[*n1]) != pa);
12540         // 2 <= n1 <= 10.
12541         if (doflip) {
12542           success = false;
12543           tmpkey = -1.0;  // = acos(pi).
12544           if (key != (REAL *) NULL) tmpkey = *key;
12545           m = 0;
12546           if (*n1 == 3) {
12547             // Three tets case. Try flip32.
12548             success = removeedgebyflip32(&tmpkey,bftetlist,newtetlist,flipque);
12549             m = 2;
12550           } else if ((*n1 > 3) && (*n1 < 7)) {
12551             // Four or more tets case. Try flipNM.
12552             success = removeedgebytranNM(&tmpkey, *n1, bftetlist, newtetlist,
12553                                          p[1], p[n - 1], flipque);
12554             // If success, the number of new tets.
12555             m = ((*n1) - 2) * 2;
12556           } else {
12557             if (b->verbose > 1) {
12558               printf("  !! Unhandled case: n1 = %d.\n", *n1);
12559             }
12560           }
12561           if (success) {
12562             // b.p_0 is flipped. The link of ab is reduced (by 1), i.e., p_0
12563             //   is not on the link of ab. Two old tets a.b.p_0.p_n-1 and
12564             //   a.b.p_1.p_0 have been removed from the Star(ab) and one new
12565             //   tet t = a.b.p_1.p_n-1 belongs to Star(ab).
12566             // Find t in the 'newtetlist' and remove it from the list.
12567             setpointmark(pa, -pointmark(pa) - 1);
12568             setpointmark(pb, -pointmark(pb) - 1);
12569             assert(m > 0);
12570             for (j = 0; j < m; j++) {
12571               tmpabtetlist[0] = newtetlist[j];
12572               // Does it has ab?
12573               count = 0;
12574               for (k = 0; k < 4; k++) {
12575                 if (pointmark((point)(tmpabtetlist[0].tet[4+k])) < 0) count++;
12576               }
12577               if (count == 2) {
12578                 // It is. Adjust t to be the edge ab.
12579                 for (tmpabtetlist[0].loc = 0; tmpabtetlist[0].loc < 4;
12580                      tmpabtetlist[0].loc++) {
12581                   if ((oppo(tmpabtetlist[0]) != pa) &&
12582                       (oppo(tmpabtetlist[0]) != pb)) break;
12583                 }
12584                 // The face of t must contain ab.
12585                 assert(tmpabtetlist[0].loc < 4);
12586                 findedge(&(tmpabtetlist[0]), pa, pb);
12587                 break;
12588               }
12589             }
12590             assert(j < m); // The tet must exist.
12591             // Remove t from list. Fill t's position by the last tet.
12592             newtetlist[j] = newtetlist[m - 1];
12593             setpointmark(pa, -(pointmark(pa) + 1));
12594             setpointmark(pb, -(pointmark(pb) + 1));
12595             // Create the temporary Star(ab) for the next flipNM.
12596             adjustedgering(tmpabtetlist[0], CCW);
12597             if (org(tmpabtetlist[0]) != pa) {
12598               fnextself(tmpabtetlist[0]);
12599               esymself(tmpabtetlist[0]);
12600             }
12601 #ifdef SELF_CHECK
12602             // Make sure current edge is a->b.
12603             assert(org(tmpabtetlist[0]) == pa);
12604             assert(dest(tmpabtetlist[0]) == pb);
12605             assert(apex(tmpabtetlist[0]) == p[n - 1]);
12606             assert(oppo(tmpabtetlist[0]) == p[1]);
12607 #endif // SELF_CHECK
12608             // There are n - 2 left temporary tets.
12609             for (j = 1; j < n - 1; j++) {
12610               maketetrahedron(&(tmpabtetlist[j]));
12611               setorg(tmpabtetlist[j], pa);
12612               setdest(tmpabtetlist[j], pb);
12613               setapex(tmpabtetlist[j], p[j]);
12614               setoppo(tmpabtetlist[j], p[j + 1]);
12615             }
12616             // Transfer the element attributes.
12617             for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12618               attrib = elemattribute(abtetlist[0].tet, j);
12619               for (k = 0; k < n - 1; k++) {
12620                 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12621               }
12622             }
12623             // Transfer the volume constraints.
12624             if (b->varvolume && !b->refine) {
12625               volume = volumebound(abtetlist[0].tet);
12626               for (k = 0; k < n - 1; k++) {
12627                 setvolumebound(tmpabtetlist[k].tet, volume);
12628               }
12629             }
12630             // Glue n - 1 internal faces of Star(ab).
12631             for (j = 0; j < n - 1; j++) {
12632               fnext(tmpabtetlist[j], newfront);
12633               bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
12634             }
12635             // Substitute the old tets with the new tets by connecting the
12636             //   new tets to the adjacent tets in the mesh. There are (n-2)
12637             //   * 2 (outer) faces of the new tets need to be operated.
12638             // Note that the old tets still have the pointers to their
12639             //   adjacent tets in the mesh.  These pointers can be re-used
12640             //   to inverse the substitution.
12641             for (j = 2; j < n; j++) {
12642               // Get an old tet: [j]a.b.p_j.p_j-1, (j > 1).
12643               oldfront = abtetlist[(i + j) % n];
12644               esymself(oldfront);
12645               enextfnextself(oldfront);
12646               // Get an adjacent tet at face: [j]a.p_j.p_j-1.
12647               sym(oldfront, adjfront); // adjfront may be dummy.
12648               // Get the corresponding face from the new tets.
12649               // j >= 2.
12650               enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
12651               bond(newfront, adjfront);
12652               if (checksubfaces) {
12653                 tspivot(oldfront, checksh);
12654                 if (checksh.sh != dummysh) {
12655                   tsbond(newfront, checksh);
12656                 }
12657               }
12658             }
12659             for (j = 2; j < n; j++) {
12660               // Get an old tet: [j]a.b.p_j.p_j-1, (j > 2).
12661               oldfront = abtetlist[(i + j) % n];
12662               esymself(oldfront);
12663               enext2fnextself(oldfront);
12664               // Get an adjacent tet at face: [j]b.p_j.p_j-1.
12665               sym(oldfront, adjfront); // adjfront may be dummy.
12666               // Get the corresponding face from the new tets.
12667               // j >= 2.
12668               enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
12669               bond(newfront, adjfront);
12670               if (checksubfaces) {
12671                 tspivot(oldfront, checksh);
12672                 if (checksh.sh != dummysh) {
12673                   tsbond(newfront, checksh);
12674                 }
12675               }
12676             }
12677             // Adjust the faces in the temporary new tets at ab for
12678             //   recursively processing on the n-1 tets.
12679             for (j = 0; j < n - 1; j++) {
12680               fnextself(tmpabtetlist[j]);
12681             }
12682             tmpkey2 = -1;
12683             if (key) tmpkey2 = *key;
12684             if ((n - 1) == 3) {
12685               success = removeedgebyflip32(&tmpkey2, tmpabtetlist,
12686                 &(newtetlist[m - 1]), flipque);
12687             } else { // assert((n - 1) >= 4);
12688               success = removeedgebytranNM(&tmpkey2, n - 1, tmpabtetlist,
12689                 &(newtetlist[m - 1]), NULL, NULL, flipque);
12690             }
12691             // No matter it was success or not, delete the temporary tets.
12692             for (j = 0; j < n - 1; j++) {
12693               tetrahedrondealloc(tmpabtetlist[j].tet);
12694             }
12695             if (success) {
12696               // The new configuration is good.
12697               // Do not delete the old tets.
12698               // for (j = 0; j < n; j++) {
12699               //   tetrahedrondealloc(abtetlist[j].tet);
12700               // }
12701               // Return the bigger dihedral in the two sets of new tets.
12702               if (key != (REAL *) NULL) {
12703                 *key = tmpkey2 < tmpkey ? tmpkey2 : tmpkey;
12704               }
12705               return true;
12706             } else {
12707               // The new configuration is bad, substitue back the old tets.
12708               for (j = 0; j < n; j++) {
12709                 oldfront = abtetlist[(i + j) % n];
12710                 esymself(oldfront);
12711                 enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
12712                 sym(oldfront, adjfront); // adjfront may be dummy.
12713                 bond(oldfront, adjfront);
12714                 if (checksubfaces) {
12715                   tspivot(oldfront, checksh);
12716                   if (checksh.sh != dummysh) {
12717                     tsbond(oldfront, checksh);
12718                   }
12719                 }
12720               }
12721               for (j = 0; j < n; j++) {
12722                 oldfront = abtetlist[(i + j) % n];
12723                 esymself(oldfront);
12724                 enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12725                 sym(oldfront, adjfront); // adjfront may be dummy
12726                 bond(oldfront, adjfront);
12727                 if (checksubfaces) {
12728                   tspivot(oldfront, checksh);
12729                   if (checksh.sh != dummysh) {
12730                     tsbond(oldfront, checksh);
12731                   }
12732                 }
12733               }
12734               // Substitute back the old tets of the first flip.
12735               for (j = 0; j < *n1; j++) {
12736                 oldfront = bftetlist[j];
12737                 esymself(oldfront);
12738                 enextfnextself(oldfront);
12739                 sym(oldfront, adjfront); // adjfront may be dummy.
12740                 bond(oldfront, adjfront);
12741                 if (checksubfaces) {
12742                   tspivot(oldfront, checksh);
12743                   if (checksh.sh != dummysh) {
12744                     tsbond(oldfront, checksh);
12745                   }
12746                 }
12747               }
12748               for (j = 0; j < *n1; j++) {
12749                 oldfront = bftetlist[j];
12750                 esymself(oldfront);
12751                 enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12752                 sym(oldfront, adjfront); // adjfront may be dummy
12753                 bond(oldfront, adjfront);
12754                 if (checksubfaces) {
12755                   tspivot(oldfront, checksh);
12756                   if (checksh.sh != dummysh) {
12757                     tsbond(oldfront, checksh);
12758                   }
12759                 }
12760               }
12761               // Delete the new tets of the first flip. Note that one new
12762               //   tet has already been removed from the list.
12763               for (j = 0; j < m - 1; j++) {
12764                 tetrahedrondealloc(newtetlist[j].tet);
12765               }
12766             } // if (success)
12767           } // if (success)
12768         } // if (doflip)
12769       } // if (ori <= 0.0)
12770     } // for (i = 0; i < n; i++)
12771     // Inverse a and b and the tets configuration.
12772     for (i = 0; i < n; i++) newtetlist[i] = abtetlist[i];
12773     for (i = 0; i < n; i++) {
12774       oldfront = newtetlist[n - i - 1];
12775       esymself(oldfront);
12776       fnextself(oldfront);
12777       abtetlist[i] = oldfront;
12778     }
12779     twice++;
12780   } while (twice < 2);
12781 
12782   return false;
12783 }
12784 
12786 //                                                                           //
12787 // splittetrahedron()    Insert a point into a tetrahedron, split it into    //
12788 //                       four tetrahedra.                                    //
12789 //                                                                           //
12790 // The tetrahedron is given by 'splittet'.  Let it is abcd.  The inserting   //
12791 // point 'newpoint' v should lie strictly inside abcd.                       //
12792 //                                                                           //
12793 // Splitting a tetrahedron is to shrink abcd to abcv,  and create three new  //
12794 // tetrahedra badv, cbdv, and acdv.                                          //
12795 //                                                                           //
12796 // On completion, 'splittet' returns abcv.  If 'flipqueue' is not NULL, it   //
12797 // contains all possibly non-locally Delaunay faces.                         //
12798 //                                                                           //
12800 
12801 void tetgenmesh::splittetrahedron(point newpoint, triface* splittet,
12802   queue* flipqueue)
12803 {
12804   triface oldabd, oldbcd, oldcad;                      // Old configuration.
12805   triface abdcasing, bcdcasing, cadcasing;
12806   face abdsh, bcdsh, cadsh;
12807   triface abcv, badv, cbdv, acdv;                      // New configuration.
12808   triface worktet;
12809   face abseg, bcseg, caseg;
12810   face adseg, bdseg, cdseg;
12811   point pa, pb, pc, pd;
12812   REAL attrib, volume;
12813   int i;
12814 
12815   abcv = *splittet;
12816   abcv.ver = 0;
12817   // Set the changed vertices and new tetrahedron.
12818   pa = org(abcv);
12819   pb = dest(abcv);
12820   pc = apex(abcv);
12821   pd = oppo(abcv);
12822 
12823   if (b->verbose > 1) {
12824     printf("  Inserting point %d in tetrahedron (%d, %d, %d, %d).\n",
12825            pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc),
12826            pointmark(pd));
12827   }
12828 
12829   fnext(abcv, oldabd);
12830   enextfnext(abcv, oldbcd);
12831   enext2fnext(abcv, oldcad);
12832   sym(oldabd, abdcasing);
12833   sym(oldbcd, bcdcasing);
12834   sym(oldcad, cadcasing);
12835   maketetrahedron(&badv);
12836   maketetrahedron(&cbdv);
12837   maketetrahedron(&acdv);
12838 
12839   // Set 'badv' vertices.
12840   setorg (badv, pb);
12841   setdest(badv, pa);
12842   setapex(badv, pd);
12843   setoppo(badv, newpoint);
12844   // Set 'cbdv' vertices.
12845   setorg (cbdv, pc);
12846   setdest(cbdv, pb);
12847   setapex(cbdv, pd);
12848   setoppo(cbdv, newpoint);
12849   // Set 'acdv' vertices.
12850   setorg (acdv, pa);
12851   setdest(acdv, pc);
12852   setapex(acdv, pd);
12853   setoppo(acdv, newpoint);
12854   // Set 'abcv' vertices
12855   setoppo(abcv, newpoint);
12856 
12857   // Set the element attributes of the new tetrahedra.
12858   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12859     attrib = elemattribute(abcv.tet, i);
12860     setelemattribute(badv.tet, i, attrib);
12861     setelemattribute(cbdv.tet, i, attrib);
12862     setelemattribute(acdv.tet, i, attrib);
12863   }
12864   // Set the volume constraint of the new tetrahedra.
12865   if (b->varvolume) {
12866     volume = volumebound(abcv.tet);
12867     setvolumebound(badv.tet, volume);
12868     setvolumebound(cbdv.tet, volume);
12869     setvolumebound(acdv.tet, volume);
12870   }
12871 
12872   // Bond the new triangles to the surrounding tetrahedron.
12873   bond(badv, abdcasing);
12874   bond(cbdv, bcdcasing);
12875   bond(acdv, cadcasing);
12876   // There may exist subfaces need to be bonded to the new tetrahedra.
12877   if (checksubfaces) {
12878     tspivot(oldabd, abdsh);
12879     if (abdsh.sh != dummysh) {
12880       tsdissolve(oldabd);
12881       tsbond(badv, abdsh);
12882     }
12883     tspivot(oldbcd, bcdsh);
12884     if (bcdsh.sh != dummysh) {
12885       tsdissolve(oldbcd);
12886       tsbond(cbdv, bcdsh);
12887     }
12888     tspivot(oldcad, cadsh);
12889     if (cadsh.sh != dummysh) {
12890       tsdissolve(oldcad);
12891       tsbond(acdv, cadsh);
12892     }
12893   } else if (checksubsegs) {
12894     tsspivot1(abcv, abseg);
12895     if (abseg.sh != dummysh) {
12896       tssbond1(badv, abseg);
12897     }
12898     enext(abcv, worktet);
12899     tsspivot1(worktet, bcseg);
12900     if (bcseg.sh != dummysh) {
12901       tssbond1(cbdv, bcseg);
12902     }
12903     enext2(abcv, worktet);
12904     tsspivot1(worktet, caseg);
12905     if (caseg.sh != dummysh) {
12906       tssbond1(acdv, caseg);
12907     }
12908     fnext(abcv, worktet);
12909     enext2self(worktet);
12910     tsspivot1(worktet, adseg);
12911     if (adseg.sh != dummysh) {
12912       tssdissolve1(worktet);
12913       enext(badv, worktet);
12914       tssbond1(worktet, adseg);
12915       enext2(acdv, worktet);
12916       tssbond1(worktet, adseg);
12917     }
12918     enextfnext(abcv, worktet);
12919     enext2self(worktet);
12920     tsspivot1(worktet, bdseg);
12921     if (bdseg.sh != dummysh) {
12922       tssdissolve1(worktet);
12923       enext(cbdv, worktet);
12924       tssbond1(worktet, bdseg);
12925       enext2(badv, worktet);
12926       tssbond1(worktet, bdseg);
12927     }
12928     enext2fnext(abcv, worktet);
12929     enext2self(worktet);
12930     tsspivot1(worktet, cdseg);
12931     if (cdseg.sh != dummysh) {
12932       tssdissolve1(worktet);
12933       enext(acdv, worktet);
12934       tssbond1(worktet, cdseg);
12935       enext2(cbdv, worktet);
12936       tssbond1(worktet, cdseg);
12937     }
12938   }
12939   badv.loc = 3;
12940   cbdv.loc = 2;
12941   bond(badv, cbdv);
12942   cbdv.loc = 3;
12943   acdv.loc = 2;
12944   bond(cbdv, acdv);
12945   acdv.loc = 3;
12946   badv.loc = 2;
12947   bond(acdv, badv);
12948   badv.loc = 1;
12949   bond(badv, oldabd);
12950   cbdv.loc = 1;
12951   bond(cbdv, oldbcd);
12952   acdv.loc = 1;
12953   bond(acdv, oldcad);
12954 
12955   badv.loc = 0;
12956   cbdv.loc = 0;
12957   acdv.loc = 0;
12958   if (b->verbose > 3) {
12959     printf("    Updating abcv ");
12960     printtet(&abcv);
12961     printf("    Creating badv ");
12962     printtet(&badv);
12963     printf("    Creating cbdv ");
12964     printtet(&cbdv);
12965     printf("    Creating acdv ");
12966     printtet(&acdv);
12967   }
12968 
12969   if (flipqueue != (queue *) NULL) {
12970     enqueueflipface(abcv, flipqueue);
12971     enqueueflipface(badv, flipqueue);
12972     enqueueflipface(cbdv, flipqueue);
12973     enqueueflipface(acdv, flipqueue);
12974   }
12975 
12976   // Save a handle for quick point location.
12977   recenttet = abcv;
12978   // Set the return handle be abcv.
12979   *splittet = abcv;
12980 }
12981 
12983 //                                                                           //
12984 // unsplittetrahedron()    Reverse the operation of inserting a point into a //
12985 //                         tetrahedron, so as to remove the newly inserted   //
12986 //                         point from the mesh.                              //
12987 //                                                                           //
12988 // Assume the origional tetrahedron is abcd, it was split by v into four     //
12989 // tetrahedra abcv, badv, cbdv, and acdv. 'splittet' represents face abc of  //
12990 // abcv (i.e., its opposite is v).                                           //
12991 //                                                                           //
12992 // Point v is removed by expanding abcv to abcd, deleting three tetrahedra   //
12993 // badv, cbdv and acdv.  On return, point v is not deleted in this routine.  //
12994 //                                                                           //
12996 
12997 void tetgenmesh::unsplittetrahedron(triface* splittet)
12998 {
12999   triface abcv, badv, cbdv, acdv;
13000   triface oldabv, oldbcv, oldcav;
13001   triface badcasing, cbdcasing, acdcasing;
13002   face badsh, cbdsh, acdsh;
13003 
13004   abcv = *splittet;
13005   adjustedgering(abcv, CCW);  // for sure.
13006   fnext(abcv, oldabv);
13007   fnext(oldabv, badv);
13008   esymself(badv);
13009   enextfnext(abcv, oldbcv);
13010   fnext(oldbcv, cbdv);
13011   esymself(cbdv);
13012   enext2fnext(abcv, oldcav);
13013   fnext(oldcav, acdv);
13014   esymself(acdv);
13015 
13016   if (b->verbose > 1) {
13017     printf("  Removing point %d in tetrahedron (%d, %d, %d, %d).\n",
13018            pointmark(oppo(abcv)), pointmark(org(abcv)), pointmark(dest(abcv)),
13019            pointmark(apex(abcv)), pointmark(apex(badv)));
13020   }
13021 
13022   sym(badv, badcasing);
13023   tspivot(badv, badsh);
13024   sym(cbdv, cbdcasing);
13025   tspivot(cbdv, cbdsh);
13026   sym(acdv, acdcasing);
13027   tspivot(acdv, acdsh);
13028 
13029   // Expanding abcv to abcd.
13030   setoppo(abcv, apex(badv));
13031   bond(oldabv, badcasing);
13032   if (badsh.sh != dummysh) {
13033     tsbond(oldabv, badsh);
13034   }
13035   bond(oldbcv, cbdcasing);
13036   if (cbdsh.sh != dummysh) {
13037     tsbond(oldbcv, cbdsh);
13038   }
13039   bond(oldcav, acdcasing);
13040   if (acdsh.sh != dummysh) {
13041     tsbond(oldcav, acdsh);
13042   }
13043 
13044   // Delete the three split-out tetrahedra.
13045   tetrahedrondealloc(badv.tet);
13046   tetrahedrondealloc(cbdv.tet);
13047   tetrahedrondealloc(acdv.tet);
13048 }
13049 
13051 //                                                                           //
13052 // splittetface()    Insert a point on a face of a mesh.                     //
13053 //                                                                           //
13054 // 'splittet' is the splitting face.  Let it is abcd, where abc is the face  //
13055 // will be split. If abc is not a hull face, abce is the tetrahedron at the  //
13056 // opposite of d.                                                            //
13057 //                                                                           //
13058 // To split face abc by a point v is to shrink the tetrahedra abcd to abvd,  //
13059 // create two new tetrahedra bcvd, cavd.  If abc is not a hull face, shrink  //
13060 // the tetrahedra bace to bave, create two new tetrahedra cbve, acve.        //
13061 //                                                                           //
13062 // If abc is a subface, it is split into three subfaces simultaneously by    //
13063 // calling routine splitsubface(), hence, abv, bcv, cav.  The edge rings of  //
13064 // the split subfaces have the same orientation as abc's.                    //
13065 //                                                                           //
13066 // On completion, 'splittet' returns abvd.  If 'flipqueue' is not NULL, it   //
13067 // contains all possibly non-locally Delaunay faces.                         //
13068 //                                                                           //
13070 
13071 void tetgenmesh::splittetface(point newpoint, triface* splittet,
13072   queue* flipqueue)
13073 {
13074   triface abcd, bace;                                  // Old configuration.
13075   triface oldbcd, oldcad, oldace, oldcbe;
13076   triface bcdcasing, cadcasing, acecasing, cbecasing;
13077   face abcsh, bcdsh, cadsh, acesh, cbesh;
13078   triface abvd, bcvd, cavd, bave, cbve, acve;          // New configuration.
13079   triface worktet;
13080   face bcseg, caseg;
13081   face adseg, bdseg, cdseg;
13082   face aeseg, beseg, ceseg;
13083   point pa, pb, pc, pd, pe;
13084   REAL attrib, volume;
13085   bool mirrorflag;
13086   int i;
13087 
13088   abcd = *splittet;
13089   // abcd.ver = 0; // Adjust to be CCW edge ring.
13090   adjustedgering(abcd, CCW);
13091   pa = org(abcd);
13092   pb = dest(abcd);
13093   pc = apex(abcd);
13094   pd = oppo(abcd);
13095   pe = (point) NULL; // avoid a compile warning.
13096   // Is there a second tetrahderon?
13097   mirrorflag = issymexist(&abcd);
13098   if (mirrorflag) {
13099     // This is an interior face.
13100     sym(abcd, bace);
13101     findedge(&bace, dest(abcd), org(abcd));
13102     pe = oppo(bace);
13103   }
13104   if (checksubfaces) {
13105     // Is there a subface need to be split together?
13106     tspivot(abcd, abcsh);
13107     if (abcsh.sh != dummysh) {
13108       // Exists! Keep the edge ab of both handles be the same.
13109       findedge(&abcsh, org(abcd), dest(abcd));
13110     }
13111   }
13112 
13113   if (b->verbose > 1) {
13114     printf("  Inserting point %d on face (%d, %d, %d).\n", pointmark(newpoint),
13115            pointmark(pa), pointmark(pb), pointmark(pc));
13116   }
13117 
13118   // Save the old configuration at faces bcd and cad.
13119   enextfnext(abcd, oldbcd);
13120   enext2fnext(abcd, oldcad);
13121   sym(oldbcd, bcdcasing);
13122   sym(oldcad, cadcasing);
13123   // Create two new tetrahedra.
13124   maketetrahedron(&bcvd);
13125   maketetrahedron(&cavd);
13126   if (mirrorflag) {
13127     // Save the old configuration at faces bce and cae.
13128     enextfnext(bace, oldace);
13129     enext2fnext(bace, oldcbe);
13130     sym(oldace, acecasing);
13131     sym(oldcbe, cbecasing);
13132     // Create two new tetrahedra.
13133     maketetrahedron(&acve);
13134     maketetrahedron(&cbve);
13135   } else {
13136     // Splitting a boundary face increases the number of boundary faces.
13137     hullsize += 2;
13138   }
13139 
13140   // Set vertices to the changed tetrahedron and new tetrahedra.
13141   abvd = abcd;  // Update 'abcd' to 'abvd'.
13142   setapex(abvd, newpoint);
13143   setorg (bcvd, pb);  // Set 'bcvd'.
13144   setdest(bcvd, pc);
13145   setapex(bcvd, newpoint);
13146   setoppo(bcvd, pd);
13147   setorg (cavd, pc);  // Set 'cavd'.
13148   setdest(cavd, pa);
13149   setapex(cavd, newpoint);
13150   setoppo(cavd, pd);
13151   // Set the element attributes of the new tetrahedra.
13152   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13153     attrib = elemattribute(abvd.tet, i);
13154     setelemattribute(bcvd.tet, i, attrib);
13155     setelemattribute(cavd.tet, i, attrib);
13156   }
13157   if (b->varvolume) {
13158     // Set the area constraint of the new tetrahedra.
13159     volume = volumebound(abvd.tet);
13160     setvolumebound(bcvd.tet, volume);
13161     setvolumebound(cavd.tet, volume);
13162   }
13163   if (mirrorflag) {
13164     bave = bace;  // Update 'bace' to 'bave'.
13165     setapex(bave, newpoint);
13166     setorg (acve, pa);  // Set 'acve'.
13167     setdest(acve, pc);
13168     setapex(acve, newpoint);
13169     setoppo(acve, pe);
13170     setorg (cbve, pc);  // Set 'cbve'.
13171     setdest(cbve, pb);
13172     setapex(cbve, newpoint);
13173     setoppo(cbve, pe);
13174     // Set the element attributes of the new tetrahedra.
13175     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13176       attrib = elemattribute(bave.tet, i);
13177       setelemattribute(acve.tet, i, attrib);
13178       setelemattribute(cbve.tet, i, attrib);
13179     }
13180     if (b->varvolume) {
13181       // Set the area constraint of the new tetrahedra.
13182       volume = volumebound(bave.tet);
13183       setvolumebound(acve.tet, volume);
13184       setvolumebound(cbve.tet, volume);
13185     }
13186   }
13187 
13188   // Bond the new tetrahedra to the surrounding tetrahedra.
13189   bcvd.loc = 1;
13190   bond(bcvd, bcdcasing);
13191   cavd.loc = 1;
13192   bond(cavd, cadcasing);
13193   bcvd.loc = 3;
13194   bond(bcvd, oldbcd);
13195   cavd.loc = 2;
13196   bond(cavd, oldcad);
13197   bcvd.loc = 2;
13198   cavd.loc = 3;
13199   bond(bcvd, cavd);
13200   if (mirrorflag) {
13201     acve.loc = 1;
13202     bond(acve, acecasing);
13203     cbve.loc = 1;
13204     bond(cbve, cbecasing);
13205     acve.loc = 3;
13206     bond(acve, oldace);
13207     cbve.loc = 2;
13208     bond(cbve, oldcbe);
13209     acve.loc = 2;
13210     cbve.loc = 3;
13211     bond(acve, cbve);
13212     // Bond two new coplanar facets.
13213     bcvd.loc = 0;
13214     cbve.loc = 0;
13215     bond(bcvd, cbve);
13216     cavd.loc = 0;
13217     acve.loc = 0;
13218     bond(cavd, acve);
13219   }
13220 
13221   // There may exist subface needed to be bonded to the new tetrahedra.
13222   if (checksubfaces) {
13223     tspivot(oldbcd, bcdsh);
13224     if (bcdsh.sh != dummysh) {
13225       tsdissolve(oldbcd);
13226       bcvd.loc = 1;
13227       tsbond(bcvd, bcdsh);
13228     }
13229     tspivot(oldcad, cadsh);
13230     if (cadsh.sh != dummysh) {
13231       tsdissolve(oldcad);
13232       cavd.loc = 1;
13233       tsbond(cavd, cadsh);
13234     }
13235     if (mirrorflag) {
13236       tspivot(oldace, acesh);
13237       if (acesh.sh != dummysh) {
13238         tsdissolve(oldace);
13239         acve.loc = 1;
13240         tsbond(acve, acesh);
13241       }
13242       tspivot(oldcbe, cbesh);
13243       if (cbesh.sh != dummysh) {
13244         tsdissolve(oldcbe);
13245         cbve.loc = 1;
13246         tsbond(cbve, cbesh);
13247       }
13248     }
13249     // Is there a subface needs to be split together?
13250     if (abcsh.sh != dummysh) {
13251       // Split this subface 'abc' into three i.e, abv, bcv, cav.
13252       splitsubface(newpoint, &abcsh, (queue *) NULL);
13253     }
13254   } else if (checksubsegs) {
13255     // abvd.loc = abvd.ver = 0;
13256     bcvd.loc = bcvd.ver = 0;
13257     cavd.loc = cavd.ver = 0;
13258     if (mirrorflag) {
13259       // bave.loc = bave.ver = 0;
13260       cbve.loc = cbve.ver = 0;
13261       acve.loc = acve.ver = 0;
13262     }
13263     enext(abvd, worktet);
13264     tsspivot1(worktet, bcseg);
13265     if (bcseg.sh != dummysh) {
13266       tssdissolve1(worktet);
13267       tssbond1(bcvd, bcseg);
13268       if (mirrorflag) {
13269         enext2(bave, worktet);
13270         tssdissolve1(worktet);
13271         tssbond1(cbve, bcseg);
13272       }
13273     }
13274     enext2(abvd, worktet);
13275     tsspivot1(worktet, caseg);
13276     if (caseg.sh != dummysh) {
13277       tssdissolve1(worktet);
13278       tssbond1(cavd, caseg);
13279       if (mirrorflag) {
13280         enext(bave, worktet);
13281         tssdissolve1(worktet);
13282         tssbond1(acve, caseg);
13283       }
13284     }
13285     fnext(abvd, worktet);
13286     enext2self(worktet);
13287     tsspivot1(worktet, adseg);
13288     if (adseg.sh != dummysh) {
13289       fnext(cavd, worktet);
13290       enextself(worktet);
13291       tssbond1(worktet, adseg);
13292     }
13293     fnext(abvd, worktet);
13294     enextself(worktet);
13295     tsspivot1(worktet, bdseg);
13296     if (bdseg.sh != dummysh) {
13297       fnext(bcvd, worktet);
13298       enext2self(worktet);
13299       tssbond1(worktet, bdseg);
13300     }
13301     enextfnext(abvd, worktet);
13302     enextself(worktet);
13303     tsspivot1(worktet, cdseg);
13304     if (cdseg.sh != dummysh) {
13305       tssdissolve1(worktet);
13306       fnext(bcvd, worktet);
13307       enextself(worktet);
13308       tssbond1(worktet, cdseg);
13309       fnext(cavd, worktet);
13310       enext2self(worktet);
13311       tssbond1(worktet, cdseg);
13312     }
13313     if (mirrorflag) {
13314       fnext(bave, worktet);
13315       enextself(worktet);
13316       tsspivot1(worktet, aeseg);
13317       if (aeseg.sh != dummysh) {
13318         fnext(acve, worktet);
13319         enext2self(worktet);
13320         tssbond1(worktet, aeseg);
13321       }
13322       fnext(bave, worktet);
13323       enext2self(worktet);
13324       tsspivot1(worktet, beseg);
13325       if (beseg.sh != dummysh) {
13326         fnext(cbve, worktet);
13327         enextself(worktet);
13328         tssbond1(worktet, beseg);
13329       }
13330       enextfnext(bave, worktet);
13331       enextself(worktet);
13332       tsspivot1(worktet, ceseg);
13333       if (ceseg.sh != dummysh) {
13334         tssdissolve1(worktet);
13335         fnext(cbve, worktet);
13336         enext2self(worktet);
13337         tssbond1(worktet, ceseg);
13338         fnext(acve, worktet);
13339         enextself(worktet);
13340         tssbond1(worktet, ceseg);
13341       }
13342     }
13343   }
13344 
13345   // Save a handle for quick point location.
13346   recenttet = abvd;
13347   // Set the return handle be abvd.
13348   *splittet = abvd;
13349 
13350   bcvd.loc = 0;
13351   cavd.loc = 0;
13352   if (mirrorflag) {
13353     cbve.loc = 0;
13354     acve.loc = 0;
13355   }
13356   if (b->verbose > 3) {
13357     printf("    Updating abvd ");
13358     printtet(&abvd);
13359     printf("    Creating bcvd ");
13360     printtet(&bcvd);
13361     printf("    Creating cavd ");
13362     printtet(&cavd);
13363     if (mirrorflag) {
13364       printf("    Updating bave ");
13365       printtet(&bave);
13366       printf("    Creating cbve ");
13367       printtet(&cbve);
13368       printf("    Creating acve ");
13369       printtet(&acve);
13370     }
13371   }
13372 
13373   if (flipqueue != (queue *) NULL) {
13374     fnextself(abvd);
13375     enqueueflipface(abvd, flipqueue);
13376     fnextself(bcvd);
13377     enqueueflipface(bcvd, flipqueue);
13378     fnextself(cavd);
13379     enqueueflipface(cavd, flipqueue);
13380     if (mirrorflag) {
13381       fnextself(bave);
13382       enqueueflipface(bave, flipqueue);
13383       fnextself(cbve);
13384       enqueueflipface(cbve, flipqueue);
13385       fnextself(acve);
13386       enqueueflipface(acve, flipqueue);
13387     }
13388   }
13389 }
13390 
13392 //                                                                           //
13393 // unsplittetface()    Reverse the operation of inserting a point on a face, //
13394 //                     so as to remove the newly inserted point.             //
13395 //                                                                           //
13396 // Assume the original face is abc, the tetrahedron containing abc is abcd.  //
13397 // If abc is not a hull face, bace is the tetrahedron at the opposite of d.  //
13398 // After face abc was split by a point v, tetrahedron abcd had been split    //
13399 // into three tetrahedra, abvd, bcvd, cavd, and bace (if it exists) had been //
13400 // split into bave, cbve, acve. 'splittet' represents abvd (its apex is v).  //
13401 //                                                                           //
13402 // Point v is removed by expanding abvd to abcd, deleting two tetrahedra     //
13403 // bcvd, cavd. Expanding bave(if it exists) to bace, deleting two tetrahedra //
13404 // cbve, acve.  If abv is a subface, routine unsplitsubface() will be called //
13405 // to reverse the operation of splitting a subface. On completion, point v   //
13406 // is not deleted in this routine.                                           //
13407 //                                                                           //
13409 
13410 void tetgenmesh::unsplittetface(triface* splittet)
13411 {
13412   triface abvd, bcvd, cavd, bave, cbve, acve;
13413   triface oldbvd, oldvad, oldvbe, oldave;
13414   triface bcdcasing, cadcasing, cbecasing, acecasing;
13415   face bcdsh, cadsh, cbesh, acesh;
13416   face abvsh;
13417   bool mirrorflag;
13418 
13419   abvd = *splittet;
13420   adjustedgering(abvd, CCW); // for sure.
13421   enextfnext(abvd, oldbvd);
13422   fnext(oldbvd, bcvd);
13423   esymself(bcvd);
13424   enextself(bcvd);
13425   enext2fnext(abvd, oldvad);
13426   fnext(oldvad, cavd);
13427   esymself(cavd);
13428   enext2self(cavd);
13429   // Is there a second tetrahedron?
13430   sym(abvd, bave);
13431   mirrorflag = bave.tet != dummytet;
13432   if (mirrorflag) {
13433     findedge(&bave, dest(abvd), org(abvd));
13434     enextfnext(bave, oldave);
13435     fnext(oldave, acve);
13436     esymself(acve);
13437     enextself(acve);
13438     enext2fnext(bave, oldvbe);
13439     fnext(oldvbe, cbve);
13440     esymself(cbve);
13441     enext2self(cbve);
13442   } else {
13443     // Unsplit a hull face decrease the number of boundary faces.
13444     hullsize -= 2;
13445   }
13446   // Is there a subface at abv.
13447   tspivot(abvd, abvsh);
13448   if (abvsh.sh != dummysh) {
13449     // Exists! Keep the edge ab of both handles be the same.
13450     findedge(&abvsh, org(abvd), dest(abvd));
13451   }
13452 
13453   if (b->verbose > 1) {
13454     printf("  Removing point %d on face (%d, %d, %d).\n",
13455            pointmark(apex(abvd)), pointmark(org(abvd)), pointmark(dest(abvd)),
13456            pointmark(dest(bcvd)));
13457   }
13458 
13459   fnextself(bcvd); // bcvd has changed to bcdv.
13460   sym(bcvd, bcdcasing);
13461   tspivot(bcvd, bcdsh);
13462   fnextself(cavd); // cavd has changed to cadv.
13463   sym(cavd, cadcasing);
13464   tspivot(cavd, cadsh);
13465   if (mirrorflag) {
13466     fnextself(acve); // acve has changed to acev.
13467     sym(acve, acecasing);
13468     tspivot(acve, acesh);
13469     fnextself(cbve); // cbve has changed to cbev.
13470     sym(cbve, cbecasing);
13471     tspivot(cbve, cbesh);
13472   }
13473 
13474   // Expand abvd to abcd.
13475   setapex(abvd, dest(bcvd));
13476   bond(oldbvd, bcdcasing);
13477   if (bcdsh.sh != dummysh) {
13478     tsbond(oldbvd, bcdsh);
13479   }
13480   bond(oldvad, cadcasing);
13481   if (cadsh.sh != dummysh) {
13482     tsbond(oldvad, cadsh);
13483   }
13484   if (mirrorflag) {
13485     // Expanding bave to bace.
13486     setapex(bave, dest(acve));
13487     bond(oldave, acecasing);
13488     if (acesh.sh != dummysh) {
13489       tsbond(oldave, acesh);
13490     }
13491     bond(oldvbe, cbecasing);
13492     if (cbesh.sh != dummysh) {
13493       tsbond(oldvbe, cbesh);
13494     }
13495   }
13496 
13497   // Unsplit a subface if there exists.
13498   if (abvsh.sh != dummysh) {
13499     unsplitsubface(&abvsh);
13500   }
13501 
13502   // Delete the split-out tetrahedra.
13503   tetrahedrondealloc(bcvd.tet);
13504   tetrahedrondealloc(cavd.tet);
13505   if (mirrorflag) {
13506     tetrahedrondealloc(acve.tet);
13507     tetrahedrondealloc(cbve.tet);
13508   }
13509 }
13510 
13512 //                                                                           //
13513 // splitsubface()    Insert a point on a subface, split it into three.       //
13514 //                                                                           //
13515 // The subface is 'splitface'.  Let it is abc. The inserting point 'newpoint'//
13516 // v should lie inside abc.  If the neighbor tetrahedra of abc exist, i.e.,  //
13517 // abcd and bace, they should have been split by routine splittetface()      //
13518 // before calling this routine, so the connection between the new tetrahedra //
13519 // and new subfaces can be correctly set.                                    //
13520 //                                                                           //
13521 // To split subface abc by point v is to shrink abc to abv, create two new   //
13522 // subfaces bcv and cav.  Set the connection between updated and new created //
13523 // subfaces. If there is a subsegment at edge bc or ca, connection of new    //
13524 // subface (bcv or cav) to its casing subfaces is a face link, 'casingin' is //
13525 // the predecessor and 'casingout' is the successor. It is important to keep //
13526 // the orientations of the edge rings of the updated and created subfaces be //
13527 // the same as abc's. So they have the same orientation as other subfaces of //
13528 // this facet with respect to the lift point of this facet.                  //
13529 //                                                                           //
13530 // On completion, 'splitface' returns abv.  If 'flipqueue' is not NULL, it   //
13531 // returns all possibly non-Delaunay edges.                                  //
13532 //                                                                           //
13534 
13535 void tetgenmesh::splitsubface(point newpoint, face* splitface,
13536   queue* flipqueue)
13537 {
13538   triface abvd, bcvd, cavd, bave, cbve, acve;
13539   face abc, oldbc, oldca, bc, ca, spinsh;
13540   face bccasin, bccasout, cacasin, cacasout;
13541   face abv, bcv, cav;
13542   point pa, pb, pc;
13543 
13544   abc = *splitface;
13545   // The newly created subfaces will have the same edge ring as abc.
13546   adjustedgering(abc, CCW);
13547   pa = sorg(abc);
13548   pb = sdest(abc);
13549   pc = sapex(abc);
13550 
13551   if (b->verbose > 1) {
13552     printf("  Inserting point %d on subface (%d, %d, %d).\n",
13553            pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc));
13554   }
13555 
13556   // Save the old configuration at edge bc and ca.  Subsegments may appear
13557   //   at both sides, save the face links and dissolve them.
13558   senext(abc, oldbc);
13559   senext2(abc, oldca);
13560   spivot(oldbc, bccasout);
13561   sspivot(oldbc, bc);
13562   if (bc.sh != dummysh) {
13563     if (oldbc.sh != bccasout.sh) {
13564       // 'oldbc' is not self-bonded.
13565       spinsh = bccasout;
13566       do {
13567         bccasin = spinsh;
13568         spivotself(spinsh);
13569       } while (spinsh.sh != oldbc.sh);
13570     } else {
13571       bccasout.sh = dummysh;
13572     }
13573     ssdissolve(oldbc);
13574   }
13575   spivot(oldca, cacasout);
13576   sspivot(oldca, ca);
13577   if (ca.sh != dummysh) {
13578     if (oldca.sh != cacasout.sh) {
13579       // 'oldca' is not self-bonded.
13580       spinsh = cacasout;
13581       do {
13582         cacasin = spinsh;
13583         spivotself(spinsh);
13584       } while (spinsh.sh != oldca.sh);
13585     } else {
13586       cacasout.sh = dummysh;
13587     }
13588     ssdissolve(oldca);
13589   }
13590   // Create two new subfaces.
13591   makeshellface(subfaces, &bcv);
13592   makeshellface(subfaces, &cav);
13593 
13594   // Set the vertices of changed and new subfaces.
13595   abv = abc;  // Update 'abc' to 'abv'.
13596   setsapex(abv, newpoint);
13597   setsorg(bcv, pb);  // Set 'bcv'.
13598   setsdest(bcv, pc);
13599   setsapex(bcv, newpoint);
13600   setsorg(cav, pc);  // Set 'cav'.
13601   setsdest(cav, pa);
13602   setsapex(cav, newpoint);
13603   if (b->quality && varconstraint) {
13604     // Copy yhr area bound into the new subfaces.
13605     setareabound(bcv, areabound(abv));
13606     setareabound(cav, areabound(abv));
13607   }
13608   // Copy the boundary mark into the new subfaces.
13609   setshellmark(bcv, shellmark(abv));
13610   setshellmark(cav, shellmark(abv));
13611   // Copy the subface type into the new subfaces.
13612   setshelltype(bcv, shelltype(abv));
13613   setshelltype(cav, shelltype(abv));
13614   if (checkpbcs) {
13615     // Copy the pbcgroup into the new subfaces.
13616     setshellpbcgroup(bcv, shellpbcgroup(abv));
13617     setshellpbcgroup(cav, shellpbcgroup(abv));
13618   }
13619   // Bond the new subfaces to the surrounding subfaces.
13620   if (bc.sh != dummysh) {
13621     if (bccasout.sh != dummysh) {
13622       sbond1(bccasin, bcv);
13623       sbond1(bcv, bccasout);
13624     } else {
13625       // Bond 'bcv' to itsself.
13626       sbond(bcv, bcv);
13627     }
13628     ssbond(bcv, bc);
13629   } else {
13630     sbond(bcv, bccasout);
13631   }
13632   if (ca.sh != dummysh) {
13633     if (cacasout.sh != dummysh) {
13634       sbond1(cacasin, cav);
13635       sbond1(cav, cacasout);
13636     } else {
13637       // Bond 'cav' to itself.
13638       sbond(cav, cav);
13639     }
13640     ssbond(cav, ca);
13641   } else {
13642     sbond(cav, cacasout);
13643   }
13644   senext2self(bcv);
13645   sbond(bcv, oldbc);
13646   senextself(cav);
13647   sbond(cav, oldca);
13648   senext2self(bcv);
13649   senextself(cav);
13650   sbond(bcv, cav);
13651 
13652   // Bond the new subfaces to the new tetrahedra if they exist.
13653   stpivot(abv, abvd);
13654   if (abvd.tet != dummytet) {
13655     // Get two new tetrahedra and their syms.
13656     findedge(&abvd, sorg(abv), sdest(abv));
13657     enextfnext(abvd, bcvd);
13658 #ifdef SELF_CHECK
13659     assert(bcvd.tet != dummytet);
13660 #endif
13661     fnextself(bcvd);
13662     enext2fnext(abvd, cavd);
13663 #ifdef SELF_CHECK
13664     assert(cavd.tet != dummytet);
13665 #endif
13666     fnextself(cavd);
13667     // Bond two new subfaces to the two new tetrahedra.
13668     tsbond(bcvd, bcv);
13669     tsbond(cavd, cav);
13670   }
13671   // Set the connection at the other sides if the tetrahedra exist.
13672   sesymself(abv);  // bav
13673   stpivot(abv, bave);
13674   if (bave.tet != dummytet) {
13675     sesymself(bcv);  // cbv
13676     sesymself(cav);  // acv
13677     // Get two new tetrahedra and their syms.
13678     findedge(&bave, sorg(abv), sdest(abv));
13679     enextfnext(bave, acve);
13680 #ifdef SELF_CHECK
13681     assert(acve.tet != dummytet);
13682 #endif
13683     fnextself(acve);
13684     enext2fnext(bave, cbve);
13685 #ifdef SELF_CHECK
13686     assert(cbve.tet != dummytet);
13687 #endif
13688     fnextself(cbve);
13689     // Bond two new subfaces to the two new tetrahedra.
13690     tsbond(acve, cav);
13691     tsbond(cbve, bcv);
13692   }
13693 
13694   bcv.shver = 0;
13695   cav.shver = 0;
13696   if (b->verbose > 3) {
13697     printf("    Updating abv ");
13698     printsh(&abv);
13699     printf("    Creating bcv ");
13700     printsh(&bcv);
13701     printf("    Creating cav ");
13702     printsh(&cav);
13703   }
13704 
13705   if (flipqueue != (queue *) NULL) {
13706     enqueueflipedge(abv, flipqueue);
13707     enqueueflipedge(bcv, flipqueue);
13708     enqueueflipedge(cav, flipqueue);
13709   }
13710 
13711   // Set the return handle be abv.
13712   *splitface = abv;
13713 }
13714 
13716 //                                                                           //
13717 // unsplitsubface()    Reverse the operation of inserting a point on a       //
13718 //                     subface, so as to remove the newly inserted point.    //
13719 //                                                                           //
13720 // Assume the original subface is abc, it was split by a point v into three  //
13721 // subfaces abv, bcv and cav.  'splitsh' represents abv.                     //
13722 //                                                                           //
13723 // To remove point v is to expand abv to abc, delete bcv and cav. If edge bc //
13724 // or ca is a subsegment,  the connection at a subsegment is a subface link, //
13725 // '-casin' and '-casout' are used to save the predecessor and successor of  //
13726 // bcv or cav.  On completion, point v is not deleted in this routine.       //
13727 //                                                                           //
13729 
13730 void tetgenmesh::unsplitsubface(face* splitsh)
13731 {
13732   face abv, bcv, cav;
13733   face oldbv, oldva, bc, ca, spinsh;
13734   face bccasin, bccasout, cacasin, cacasout;
13735 
13736   abv = *splitsh;
13737   senext(abv, oldbv);
13738   spivot(oldbv, bcv);
13739   if (sorg(bcv) != sdest(oldbv)) {
13740     sesymself(bcv);
13741   }
13742   senextself(bcv);
13743   senext2(abv, oldva);
13744   spivot(oldva, cav);
13745   if (sorg(cav) != sdest(oldva)) {
13746     sesymself(cav);
13747   }
13748   senext2self(cav);
13749 
13750   if (b->verbose > 1) {
13751     printf("  Removing point %d on subface (%d, %d, %d).\n",
13752            pointmark(sapex(abv)), pointmark(sorg(abv)), pointmark(sdest(abv)),
13753            pointmark(sdest(bcv)));
13754   }
13755 
13756   spivot(bcv, bccasout);
13757   sspivot(bcv, bc);
13758   if (bc.sh != dummysh) {
13759     if (bcv.sh != bccasout.sh) {
13760       // 'bcv' is not self-bonded.
13761       spinsh = bccasout;
13762       do {
13763         bccasin = spinsh;
13764         spivotself(spinsh);
13765       } while (spinsh.sh != bcv.sh);
13766     } else {
13767       bccasout.sh = dummysh;
13768     }
13769   }
13770   spivot(cav, cacasout);
13771   sspivot(cav, ca);
13772   if (ca.sh != dummysh) {
13773     if (cav.sh != cacasout.sh) {
13774       // 'cav' is not self-bonded.
13775       spinsh = cacasout;
13776       do {
13777        cacasin = spinsh;
13778        spivotself(spinsh);
13779       } while (spinsh.sh != cav.sh);
13780     } else {
13781       cacasout.sh = dummysh;
13782     }
13783   }
13784 
13785   // Expand abv to abc.
13786   setsapex(abv, sdest(bcv));
13787   if (bc.sh != dummysh) {
13788     if (bccasout.sh != dummysh) {
13789       sbond1(bccasin, oldbv);
13790       sbond1(oldbv, bccasout);
13791     } else {
13792       // Bond 'oldbv' to itself.
13793       sbond(oldbv, oldbv);
13794     }
13795     ssbond(oldbv, bc);
13796   } else {
13797     sbond(oldbv, bccasout);
13798   }
13799   if (ca.sh != dummysh) {
13800     if (cacasout.sh != dummysh) {
13801       sbond1(cacasin, oldva);
13802       sbond1(oldva, cacasout);
13803     } else {
13804       // Bond 'oldva' to itself.
13805       sbond(oldva, oldva);
13806     }
13807     ssbond(oldva, ca);
13808   } else {
13809     sbond(oldva, cacasout);
13810   }
13811 
13812   // Delete two split-out subfaces.
13813   shellfacedealloc(subfaces, bcv.sh);
13814   shellfacedealloc(subfaces, cav.sh);
13815 }
13816 
13818 //                                                                           //
13819 // splittetedge()    Insert a point on an edge of the mesh.                  //
13820 //                                                                           //
13821 // The edge is given by 'splittet'. Assume its four corners are a, b, n1 and //
13822 // n2, where ab is the edge will be split. Around ab may exist any number of //
13823 // tetrahedra. For convenience, they're ordered in a sequence following the  //
13824 // right-hand rule with your thumb points from a to b. Let the vertex set of //
13825 // these tetrahedra be {a, b, n1, n2, ..., n(i)}. NOTE the tetrahedra around //
13826 // ab may not connect to each other (can only happen when ab is a subsegment,//
13827 // hence some faces abn(i) are subfaces).  If ab is a subsegment, abn1 must  //
13828 // be a subface.                                                             //
13829 //                                                                           //
13830 // To split edge ab by a point v is to split all tetrahedra containing ab by //
13831 // v.  More specifically, for each such tetrahedron, an1n2b, it is shrunk to //
13832 // an1n2v, and a new tetrahedra bn2n1v is created. If ab is a subsegment, or //
13833 // some faces of the splitting tetrahedra are subfaces, they must be split   //
13834 // either by calling routine 'splitsubedge()'.                               //
13835 //                                                                           //
13836 // On completion, 'splittet' returns avn1n2.  If 'flipqueue' is not NULL, it //
13837 // returns all faces which may become non-Delaunay after this operation.     //
13838 //                                                                           //
13840 
13841 void tetgenmesh::splittetedge(point newpoint, triface* splittet,
13842   queue* flipqueue)
13843 {
13844   triface *bots, *newtops;
13845   triface oldtop, topcasing;
13846   triface spintet, tmpbond0, tmpbond1;
13847   face abseg, splitsh, topsh, spinsh;
13848   triface worktet;
13849   face n1n2seg, n2vseg, n1vseg;
13850   point pa, pb, n1, n2;
13851   REAL attrib, volume;
13852   int wrapcount, hitbdry;
13853   int i, j;
13854 
13855   if (checksubfaces) {
13856     // Is there a subsegment need to be split together?
13857     tsspivot(splittet, &abseg);
13858     if (abseg.sh != dummysh) {
13859       abseg.shver = 0;
13860       // Orient the edge direction of 'splittet' be abseg.
13861       if (org(*splittet) != sorg(abseg)) {
13862         esymself(*splittet);
13863       }
13864     }
13865   }
13866   spintet = *splittet;
13867   pa = org(spintet);
13868   pb = dest(spintet);
13869 
13870   if (b->verbose > 1) {
13871     printf("  Inserting point %d on edge (%d, %d).\n",
13872            pointmark(newpoint), pointmark(pa), pointmark(pb));
13873   }
13874 
13875   // Collect the tetrahedra containing the splitting edge (ab).
13876   n1 = apex(spintet);
13877   hitbdry = 0;
13878   wrapcount = 1;
13879   if (checksubfaces && abseg.sh != dummysh) {
13880     // It may happen that some tetrahedra containing ab (a subsegment) are
13881     //   completely disconnected with others. If it happens, use the face
13882     //   link of ab to cross the boundary.
13883     while (true) {
13884       if (!fnextself(spintet)) {
13885         // Meet a boundary, walk through it.
13886         hitbdry ++;
13887         tspivot(spintet, spinsh);
13888 #ifdef SELF_CHECK
13889         assert(spinsh.sh != dummysh);
13890 #endif
13891         findedge(&spinsh, pa, pb);
13892         sfnextself(spinsh);
13893         stpivot(spinsh, spintet);
13894 #ifdef SELF_CHECK
13895         assert(spintet.tet != dummytet);
13896 #endif
13897         findedge(&spintet, pa, pb);
13898         // Remember this position (hull face) in 'splittet'.
13899         *splittet = spintet;
13900         // Split two hull faces increase the hull size;
13901         hullsize += 2;
13902       }
13903       if (apex(spintet) == n1) break;
13904       wrapcount ++;
13905     }
13906     if (hitbdry > 0) {
13907       wrapcount -= hitbdry;
13908     }
13909   } else {
13910     // All the tetrahedra containing ab are connected together. If there
13911     //   are subfaces, 'splitsh' keeps one of them.
13912     splitsh.sh = dummysh;
13913     while (hitbdry < 2) {
13914       if (checksubfaces && splitsh.sh == dummysh) {
13915         tspivot(spintet, splitsh);
13916       }
13917       if (fnextself(spintet)) {
13918         if (apex(spintet) == n1) break;
13919         wrapcount++;
13920       } else {
13921         hitbdry ++;
13922         if (hitbdry < 2) {
13923           esym(*splittet, spintet);
13924         }
13925       }
13926     }
13927     if (hitbdry > 0) {
13928       // ab is on the hull.
13929       wrapcount -= 1;
13930       // 'spintet' now is a hull face, inverse its edge direction.
13931       esym(spintet, *splittet);
13932       // Split two hull faces increases the number of hull faces.
13933       hullsize += 2;
13934     }
13935   }
13936 
13937   // Make arrays of updating (bot, oldtop) and new (newtop) tetrahedra.
13938   bots = new triface[wrapcount];
13939   newtops = new triface[wrapcount];
13940   // Spin around ab, gather tetrahedra and set up new tetrahedra.
13941   spintet = *splittet;
13942   for (i = 0; i < wrapcount; i++) {
13943     // Get 'bots[i] = an1n2b'.
13944     enext2fnext(spintet, bots[i]);
13945     esymself(bots[i]);
13946     // Create 'newtops[i]'.
13947     maketetrahedron(&(newtops[i]));
13948     // Go to the next.
13949     fnextself(spintet);
13950     if (checksubfaces && abseg.sh != dummysh) {
13951       if (!issymexist(&spintet)) {
13952         // We meet a hull face, walk through it.
13953         tspivot(spintet, spinsh);
13954 #ifdef SELF_CHECK
13955         assert(spinsh.sh != dummysh);
13956 #endif
13957         findedge(&spinsh, pa, pb);
13958         sfnextself(spinsh);
13959         stpivot(spinsh, spintet);
13960 #ifdef SELF_CHECK
13961         assert(spintet.tet != dummytet);
13962 #endif
13963         findedge(&spintet, pa, pb);
13964       }
13965     }
13966   }
13967 
13968   // Set the vertices of updated and new tetrahedra.
13969   for (i = 0; i < wrapcount; i++) {
13970     // Update 'bots[i] = an1n2v'.
13971     setoppo(bots[i], newpoint);
13972     // Set 'newtops[i] = bn2n1v'.
13973     n1 = dest(bots[i]);
13974     n2 = apex(bots[i]);
13975     // Set 'newtops[i]'.
13976     setorg(newtops[i], pb);
13977     setdest(newtops[i], n2);
13978     setapex(newtops[i], n1);
13979     setoppo(newtops[i], newpoint);
13980     // Set the element attributes of a new tetrahedron.
13981     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
13982       attrib = elemattribute(bots[i].tet, j);
13983       setelemattribute(newtops[i].tet, j, attrib);
13984     }
13985     if (b->varvolume) {
13986       // Set the area constraint of a new tetrahedron.
13987       volume = volumebound(bots[i].tet);
13988       setvolumebound(newtops[i].tet, volume);
13989     }
13990 #ifdef SELF_CHECK
13991     // Make sure no inversed tetrahedron has been created.
13992     // volume = orient3d(pa, n1, n2, newpoint);
13993     // if (volume >= 0.0) {
13994     //   printf("Internal error in splittetedge(): volume = %.12g.\n", volume);
13995     // }
13996     // volume = orient3d(pb, n2, n1, newpoint);
13997     // if (volume >= 0.0) {
13998     //   printf("Internal error in splittetedge(): volume = %.12g.\n", volume);
13999     // }
14000 #endif
14001   }
14002 
14003   // Bond newtops to topcasings and bots.
14004   for (i = 0; i < wrapcount; i++) {
14005     // Get 'oldtop = n1n2va' from 'bots[i]'.
14006     enextfnext(bots[i], oldtop);
14007     sym(oldtop, topcasing);
14008     bond(newtops[i], topcasing);
14009     if (checksubfaces) {
14010       tspivot(oldtop, topsh);
14011       if (topsh.sh != dummysh) {
14012         tsdissolve(oldtop);
14013         tsbond(newtops[i], topsh);
14014       }
14015     }
14016     enextfnext(newtops[i], tmpbond0);
14017     bond(oldtop, tmpbond0);
14018   }
14019   // Bond between newtops.
14020   fnext(newtops[0], tmpbond0);
14021   enext2fnext(bots[0], spintet);
14022   for (i = 1; i < wrapcount; i ++) {
14023     if (issymexist(&spintet)) {
14024       enext2fnext(newtops[i], tmpbond1);
14025       bond(tmpbond0, tmpbond1);
14026     }
14027     fnext(newtops[i], tmpbond0);
14028     enext2fnext(bots[i], spintet);
14029   }
14030   // Bond the last to the first if no boundary.
14031   if (issymexist(&spintet)) {
14032     enext2fnext(newtops[0], tmpbond1);
14033     bond(tmpbond0, tmpbond1);
14034   }
14035   if (checksubsegs) {
14036     for (i = 0; i < wrapcount; i++) {
14037       enextfnext(bots[i], worktet); // edge n1->n2.
14038       tsspivot1(worktet, n1n2seg);
14039       if (n1n2seg.sh != dummysh) {
14040         enext(newtops[i], tmpbond0);
14041         tssbond1(tmpbond0, n1n2seg);
14042       }
14043       enextself(worktet); // edge n2->v ==> n2->b
14044       tsspivot1(worktet, n2vseg);
14045       if (n2vseg.sh != dummysh) {
14046         tssdissolve1(worktet);
14047         tssbond1(newtops[i], n2vseg);
14048       }
14049       enextself(worktet); // edge v->n1 ==> b->n1
14050       tsspivot1(worktet, n1vseg);
14051       if (n1vseg.sh != dummysh) {
14052         tssdissolve1(worktet);
14053         enext2(newtops[i], tmpbond0);
14054         tssbond1(tmpbond0, n1vseg);
14055       }
14056     }
14057   }
14058 
14059   // Is there exist subfaces and subsegment need to be split?
14060   if (checksubfaces) {
14061     if (abseg.sh != dummysh) {
14062       // A subsegment needs be split.
14063       spivot(abseg, splitsh);
14064 #ifdef SELF_CHECK
14065       assert(splitsh.sh != dummysh);
14066 #endif
14067     }
14068     if (splitsh.sh != dummysh) {
14069       // Split subfaces (and subsegment).
14070       findedge(&splitsh, pa, pb);
14071       splitsubedge(newpoint, &splitsh, (queue *) NULL);
14072     }
14073   }
14074 
14075   if (b->verbose > 3) {
14076     for (i = 0; i < wrapcount; i++) {
14077       printf("    Updating bots[%i] ", i);
14078       printtet(&(bots[i]));
14079       printf("    Creating newtops[%i] ", i);
14080       printtet(&(newtops[i]));
14081     }
14082   }
14083 
14084   if (flipqueue != (queue *) NULL) {
14085     for (i = 0; i < wrapcount; i++) {
14086       enqueueflipface(bots[i], flipqueue);
14087       enqueueflipface(newtops[i], flipqueue);
14088     }
14089   }
14090 
14091   // Set the return handle be avn1n2.  It is got by transforming from
14092   //   'bots[0]' (which is an1n2v).
14093   fnext(bots[0], spintet); // spintet is an1vn2.
14094   esymself(spintet); // spintet is n1avn2.
14095   enextself(spintet); // spintet is avn1n2.
14096   *splittet = spintet;
14097 
14098   delete [] bots;
14099   delete [] newtops;
14100 }
14101 
14103 //                                                                           //
14104 // unsplittetedge()    Reverse the operation of splitting an edge, so as to  //
14105 //                     remove the newly inserted point.                      //
14106 //                                                                           //
14107 // Assume the original edge is ab, the tetrahedron containing ab is abn1n2.  //
14108 // After ab was split by a point v, every tetrahedron containing ab (e.g.,   //
14109 // abn1n2) has been split into two (e.g., an1n2v and bn2n1v). 'splittet'     //
14110 // represents avn1n2 (i.e., its destination is v).                           //
14111 //                                                                           //
14112 // To remove point v is to expand each split tetrahedron containing ab (e.g.,//
14113 // (avn1n2 to abn1n2), then delete the redundant one(e.g., vbn1n2). If there //
14114 // exists any subface around ab, routine unsplitsubedge() will be called to  //
14115 // reverse the operation of splitting a edge (or a subsegment) of subfaces.  //
14116 // On completion, point v is not deleted in this routine.                    //
14117 //                                                                           //
14119 
14120 void tetgenmesh::unsplittetedge(triface* splittet)
14121 {
14122   triface *bots, *newtops;
14123   triface oldtop, topcasing;
14124   triface spintet;
14125   face avseg, splitsh, topsh, spinsh;
14126   point pa, pv, n1;
14127   int wrapcount, hitbdry;
14128   int i;
14129 
14130   spintet = *splittet;
14131   pa = org(spintet);
14132   pv = dest(spintet);
14133   if (checksubfaces) {
14134     // Is there a subsegment need to be unsplit together?
14135     tsspivot(splittet, &avseg);
14136     if (avseg.sh != dummysh) {
14137       // The subsegment's direction should conform to 'splittet'.
14138       if (sorg(avseg) != pa) {
14139         sesymself(avseg);
14140       }
14141     }
14142   }
14143 
14144   n1 = apex(spintet);
14145   hitbdry = 0;
14146   wrapcount = 1;
14147   if (checksubfaces && avseg.sh != dummysh) {
14148     // It may happen that some tetrahedra containing ab (a subsegment) are
14149     //   completely disconnected with others. If it happens, use the face
14150     //   link of ab to cross the boundary.
14151     while (true) {
14152       if (!fnextself(spintet)) {
14153         // Meet a boundary, walk through it.
14154         hitbdry ++;
14155         tspivot(spintet, spinsh);
14156 #ifdef SELF_CHECK
14157         assert(spinsh.sh != dummysh);
14158 #endif
14159         findedge(&spinsh, pa, pv);
14160         sfnextself(spinsh);
14161         stpivot(spinsh, spintet);
14162 #ifdef SELF_CHECK
14163         assert(spintet.tet != dummytet);
14164 #endif
14165         findedge(&spintet, pa, pv);
14166         // Remember this position (hull face) in 'splittet'.
14167         *splittet = spintet;
14168         // Split two hull faces increase the hull size;
14169         hullsize += 2;
14170       }
14171       if (apex(spintet) == n1) break;
14172       wrapcount ++;
14173     }
14174     if (hitbdry > 0) {
14175       wrapcount -= hitbdry;
14176     }
14177   } else {
14178     // All the tetrahedra containing ab are connected together. If there
14179     //   are subfaces, 'splitsh' keeps one of them.
14180     splitsh.sh = dummysh;
14181     while (hitbdry < 2) {
14182       if (checksubfaces && splitsh.sh == dummysh) {
14183         tspivot(spintet, splitsh);
14184       }
14185       if (fnextself(spintet)) {
14186         if (apex(spintet) == n1) break;
14187         wrapcount++;
14188       } else {
14189         hitbdry ++;
14190         if (hitbdry < 2) {
14191           esym(*splittet, spintet);
14192         }
14193       }
14194     }
14195     if (hitbdry > 0) {
14196       // ab is on the hull.
14197       wrapcount -= 1;
14198       // 'spintet' now is a hull face, inverse its edge direction.
14199       esym(spintet, *splittet);
14200       // Split two hull faces increases the number of hull faces.
14201       hullsize += 2;
14202     }
14203   }
14204 
14205   // Make arrays of updating (bot, oldtop) and new (newtop) tetrahedra.
14206   bots = new triface[wrapcount];
14207   newtops = new triface[wrapcount];
14208   // Spin around av, gather tetrahedra and set up new tetrahedra.
14209   spintet = *splittet;
14210   for (i = 0; i < wrapcount; i++) {
14211     // Get 'bots[i] = an1n2v'.
14212     enext2fnext(spintet, bots[i]);
14213     esymself(bots[i]);
14214     // Get 'oldtop = n1n2va'.
14215     enextfnext(bots[i], oldtop);
14216     // Get 'newtops[i] = 'bn1n2v'
14217     fnext(oldtop, newtops[i]); // newtop = n1n2bv
14218     esymself(newtops[i]); // newtop = n2n1bv
14219     enext2self(newtops[i]); // newtop = bn2n1v
14220     // Go to the next.
14221     fnextself(spintet);
14222     if (checksubfaces && avseg.sh != dummysh) {
14223       if (!issymexist(&spintet)) {
14224         // We meet a hull face, walk through it.
14225         tspivot(spintet, spinsh);
14226 #ifdef SELF_CHECK
14227         assert(spinsh.sh != dummysh);
14228 #endif
14229         findedge(&spinsh, pa, pv);
14230         sfnextself(spinsh);
14231         stpivot(spinsh, spintet);
14232 #ifdef SELF_CHECK
14233         assert(spintet.tet != dummytet);
14234 #endif
14235         findedge(&spintet, pa, pv);
14236       }
14237     }
14238   }
14239 
14240   if (b->verbose > 1) {
14241     printf("  Removing point %d from edge (%d, %d).\n",
14242            pointmark(oppo(bots[0])), pointmark(org(bots[0])),
14243            pointmark(org(newtops[0])));
14244   }
14245 
14246   for (i = 0; i < wrapcount; i++) {
14247     // Expand an1n2v to an1n2b.
14248     setoppo(bots[i], org(newtops[i]));
14249     // Get 'oldtop = n1n2va' from 'bot[i]'.
14250     enextfnext(bots[i], oldtop);
14251     // Get 'topcasing' from 'newtop[i]'
14252     sym(newtops[i], topcasing);
14253     // Bond them.
14254     bond(oldtop, topcasing);
14255     if (checksubfaces) {
14256       tspivot(newtops[i], topsh);
14257       if (topsh.sh != dummysh) {
14258         tsbond(oldtop, topsh);
14259       }
14260     }
14261     // Delete the tetrahedron above an1n2v.
14262     tetrahedrondealloc(newtops[i].tet);
14263   }
14264 
14265   // If there exists any subface, unsplit them.
14266   if (checksubfaces) {
14267     if (avseg.sh != dummysh) {
14268       spivot(avseg, splitsh);
14269 #ifdef SELF_CHECK
14270       assert(splitsh.sh != dummysh);
14271 #endif
14272     }
14273     if (splitsh.sh != dummysh) {
14274       findedge(&splitsh, pa, pv);
14275       unsplitsubedge(&splitsh);
14276     }
14277   }
14278 
14279   delete [] bots;
14280   delete [] newtops;
14281 }
14282 
14284 //                                                                           //
14285 // splitsubedge()    Insert a point on an edge of the surface mesh.          //
14286 //                                                                           //
14287 // The splitting edge is given by 'splitsh'. Assume its three corners are a, //
14288 // b, c, where ab is the edge will be split. ab may be a subsegment.         //
14289 //                                                                           //
14290 // To split edge ab is to split all subfaces conatining ab. If ab is not a   //
14291 // subsegment, there are only two subfaces need be split, otherwise, there   //
14292 // may have any number of subfaces need be split. Each splitting subface abc //
14293 // is shrunk to avc, a new subface vbc is created.  It is important to keep  //
14294 // the orientations of edge rings of avc and vbc be the same as abc's. If ab //
14295 // is a subsegment, it is shrunk to av and a new subsegment vb is created.   //
14296 //                                                                           //
14297 // If there are tetrahedra adjoining to the splitting subfaces, they should  //
14298 // be split before calling this routine, so the connection between the new   //
14299 // tetrahedra and the new subfaces can be correctly set.                     //
14300 //                                                                           //
14301 // On completion, 'splitsh' returns avc.  If 'flipqueue' is not NULL, it     //
14302 // returns all edges which may be non-Delaunay.                              //
14303 //                                                                           //
14305 
14306 void tetgenmesh::splitsubedge(point newpoint, face* splitsh, queue* flipqueue)
14307 {
14308   triface abcd, bace, vbcd, bvce;
14309   face startabc, spinabc, spinsh;
14310   face oldbc, bccasin, bccasout;
14311   face ab, bc;
14312   face avc, vbc, vbc1;
14313   face av, vb;
14314   point pa, pb;
14315 
14316   startabc = *splitsh;
14317   // Is there a subsegment?
14318   sspivot(startabc, ab);
14319   if (ab.sh != dummysh) {
14320     ab.shver = 0;
14321     if (sorg(startabc) != sorg(ab)) {
14322       sesymself(startabc);
14323     }
14324   }
14325   pa = sorg(startabc);
14326   pb = sdest(startabc);
14327 
14328   if (b->verbose > 1) {
14329     printf("  Inserting point %d on subedge (%d, %d) %s.\n",
14330            pointmark(newpoint), pointmark(pa), pointmark(pb),
14331            (ab.sh != dummysh ? "(seg)" : " "));
14332   }
14333 
14334   // Spin arround ab, split every subface containing ab.
14335   spinabc = startabc;
14336   do {
14337     // Adjust spinabc be edge ab.
14338     if (sorg(spinabc) != pa) {
14339       sesymself(spinabc);
14340     }
14341     // Save old configuration at edge bc, if bc has a subsegment, save the
14342     //   face link of it and dissolve it from bc.
14343     senext(spinabc, oldbc);
14344     spivot(oldbc, bccasout);
14345     sspivot(oldbc, bc);
14346     if (bc.sh != dummysh) {
14347       if (spinabc.sh != bccasout.sh) {
14348         // 'spinabc' is not self-bonded.
14349         spinsh = bccasout;
14350         do {
14351           bccasin = spinsh;
14352           spivotself(spinsh);
14353         } while (spinsh.sh != oldbc.sh);
14354       } else {
14355         bccasout.sh = dummysh;
14356       }
14357       ssdissolve(oldbc);
14358     }
14359     // Create a new subface.
14360     makeshellface(subfaces, &vbc);
14361     // Split abc.
14362     avc = spinabc;  // Update 'abc' to 'avc'.
14363     setsdest(avc, newpoint);
14364     // Make 'vbc' be in the same edge ring as 'avc'.
14365     vbc.shver = avc.shver;
14366     setsorg(vbc, newpoint); // Set 'vbc'.
14367     setsdest(vbc, pb);
14368     setsapex(vbc, sapex(avc));
14369     if (b->quality && varconstraint) {
14370       // Copy the area bound into the new subface.
14371       setareabound(vbc, areabound(avc));
14372     }
14373     // Copy the shell marker and shell type into the new subface.
14374     setshellmark(vbc, shellmark(avc));
14375     setshelltype(vbc, shelltype(avc));
14376     if (checkpbcs) {
14377       // Copy the pbcgroup into the new subface.
14378       setshellpbcgroup(vbc, shellpbcgroup(avc));
14379     }
14380     // Set the connection between updated and new subfaces.
14381     senext2self(vbc);
14382     sbond(vbc, oldbc);
14383     // Set the connection between new subface and casings.
14384     senext2self(vbc);
14385     if (bc.sh != dummysh) {
14386       if (bccasout.sh != dummysh) {
14387         // Insert 'vbc' into face link.
14388         sbond1(bccasin, vbc);
14389         sbond1(vbc, bccasout);
14390       } else {
14391         // Bond 'vbc' to itself.
14392         sbond(vbc, vbc);
14393       }
14394       ssbond(vbc, bc);
14395     } else {
14396       sbond(vbc, bccasout);
14397     }
14398     // Go to next subface at edge ab.
14399     spivotself(spinabc);
14400     if (spinabc.sh == dummysh) {
14401       break; // 'ab' is a hull edge.
14402     }
14403   } while (spinabc.sh != startabc.sh);
14404 
14405   // Get the new subface vbc above the updated subface avc (= startabc).
14406   senext(startabc, oldbc);
14407   spivot(oldbc, vbc);
14408   if (sorg(vbc) == newpoint) {
14409     sesymself(vbc);
14410   }
14411 #ifdef SELF_CHECK
14412   assert(sorg(vbc) == sdest(oldbc) && sdest(vbc) == sorg(oldbc));
14413 #endif
14414   senextself(vbc);
14415   // Set the face link for the new created subfaces around edge vb.
14416   spinabc = startabc;
14417   do {
14418     // Go to the next subface at edge av.
14419     spivotself(spinabc);
14420     if (spinabc.sh == dummysh) {
14421       break; // 'ab' is a hull edge.
14422     }
14423     if (sorg(spinabc) != pa) {
14424       sesymself(spinabc);
14425     }
14426     // Get the new subface vbc1 above the updated subface avc (= spinabc).
14427     senext(spinabc, oldbc);
14428     spivot(oldbc, vbc1);
14429     if (sorg(vbc1) == newpoint) {
14430       sesymself(vbc1);
14431     }
14432 #ifdef SELF_CHECK
14433     assert(sorg(vbc1) == sdest(oldbc) && sdest(vbc1) == sorg(oldbc));
14434 #endif
14435     senextself(vbc1);
14436     // Set the connection: vbc->vbc1.
14437     sbond1(vbc, vbc1);
14438     // For the next connection.
14439     vbc = vbc1;
14440   } while (spinabc.sh != startabc.sh);
14441 
14442   // Split ab if it is a subsegment.
14443   if (ab.sh != dummysh) {
14444     // Update subsegment ab to av.
14445     av = ab;
14446     setsdest(av, newpoint);
14447     // Create a new subsegment vb.
14448     makeshellface(subsegs, &vb);
14449     setsorg(vb, newpoint);
14450     setsdest(vb, pb);
14451     // vb gets the same mark and segment type as av.
14452     setshellmark(vb, shellmark(av));
14453     setshelltype(vb, shelltype(av));
14454     if (b->quality && varconstraint) {
14455       // Copy the area bound into the new subsegment.
14456       setareabound(vb, areabound(av));
14457     }
14458     // Save the old connection at ab (re-use the handles oldbc, bccasout).
14459     senext(av, oldbc);
14460     spivot(oldbc, bccasout);
14461     // Bond av and vb (bonded at their "fake" edges).
14462     senext2(vb, bccasin);
14463     sbond(bccasin, oldbc);
14464     if (bccasout.sh != dummysh) {
14465       // There is a subsegment connecting with ab at b. It will connect
14466       //   to vb at b after splitting.
14467       bccasout.shver = 0;
14468       if (sorg(bccasout) != pb) sesymself(bccasout);
14469 #ifdef SELF_CHECK
14470       assert(sorg(bccasout) == pb);
14471 #endif
14472       senext2self(bccasout);
14473       senext(vb, bccasin);
14474       sbond(bccasin, bccasout);
14475     }
14476     // Bond all new subfaces (vbc) to vb.
14477     spinabc = startabc;
14478     do {
14479       // Adjust spinabc be edge av.
14480       if (sorg(spinabc) != pa) {
14481         sesymself(spinabc);
14482       }
14483       // Get new subface vbc above the updated subface avc (= spinabc).
14484       senext(spinabc, oldbc);
14485       spivot(oldbc, vbc);
14486       if (sorg(vbc) == newpoint) {
14487         sesymself(vbc);
14488       }
14489       senextself(vbc);
14490       // Bond the new subface and the new subsegment.
14491       ssbond(vbc, vb);
14492       // Go to the next.
14493       spivotself(spinabc);
14494 #ifdef SELF_CHECK
14495       assert(spinabc.sh != dummysh);
14496 #endif
14497     } while (spinabc.sh != startabc.sh);
14498   }
14499 
14500   // Bond the new subfaces to new tetrahedra if they exist.  New tetrahedra
14501   //   should have been created before calling this routine.
14502   spinabc = startabc;
14503   do {
14504     // Adjust spinabc be edge av.
14505     if (sorg(spinabc) != pa) {
14506       sesymself(spinabc);
14507     }
14508     // Get new subface vbc above the updated subface avc (= spinabc).
14509     senext(spinabc, oldbc);
14510     spivot(oldbc, vbc);
14511     if (sorg(vbc) == newpoint) {
14512       sesymself(vbc);
14513     }
14514     senextself(vbc);
14515     // Get the adjacent tetrahedra at 'spinabc'.
14516     stpivot(spinabc, abcd);
14517     if (abcd.tet != dummytet) {
14518       findedge(&abcd, sorg(spinabc), sdest(spinabc));
14519       enextfnext(abcd, vbcd);
14520       fnextself(vbcd);
14521 #ifdef SELF_CHECK
14522       assert(vbcd.tet != dummytet);
14523 #endif
14524       tsbond(vbcd, vbc);
14525       sym(vbcd, bvce);
14526       sesymself(vbc);
14527       tsbond(bvce, vbc);
14528     } else {
14529       // One side is empty, check the other side.
14530       sesymself(spinabc);
14531       stpivot(spinabc, bace);
14532       if (bace.tet != dummytet) {
14533         findedge(&bace, sorg(spinabc), sdest(spinabc));
14534         enext2fnext(bace, bvce);
14535         fnextself(bvce);
14536 #ifdef SELF_CHECK
14537         assert(bvce.tet != dummytet);
14538 #endif
14539         sesymself(vbc);
14540         tsbond(bvce, vbc);
14541       }
14542     }
14543     // Go to the next.
14544     spivotself(spinabc);
14545     if (spinabc.sh == dummysh) {
14546       break; // 'ab' is a hull edge.
14547     }
14548   } while (spinabc.sh != startabc.sh);
14549 
14550   if (b->verbose > 3) {
14551     spinabc = startabc;
14552     do {
14553       // Adjust spinabc be edge av.
14554       if (sorg(spinabc) != pa) {
14555         sesymself(spinabc);
14556       }
14557       printf("    Updating abc:\n");
14558       printsh(&spinabc);
14559       // Get new subface vbc above the updated subface avc (= spinabc).
14560       senext(spinabc, oldbc);
14561       spivot(oldbc, vbc);
14562       if (sorg(vbc) == newpoint) {
14563         sesymself(vbc);
14564       }
14565       senextself(vbc);
14566       printf("    Creating vbc:\n");
14567       printsh(&vbc);
14568       // Go to the next.
14569       spivotself(spinabc);
14570       if (spinabc.sh == dummysh) {
14571         break; // 'ab' is a hull edge.
14572       }
14573     } while (spinabc.sh != startabc.sh);
14574   }
14575 
14576   if (flipqueue != (queue *) NULL) {
14577     spinabc = startabc;
14578     do {
14579       // Adjust spinabc be edge av.
14580       if (sorg(spinabc) != pa) {
14581         sesymself(spinabc);
14582       }
14583       senext2(spinabc, oldbc); // Re-use oldbc.
14584       enqueueflipedge(oldbc, flipqueue);
14585       // Get new subface vbc above the updated subface avc (= spinabc).
14586       senext(spinabc, oldbc);
14587       spivot(oldbc, vbc);
14588       if (sorg(vbc) == newpoint) {
14589         sesymself(vbc);
14590       }
14591       senextself(vbc);
14592       senext(vbc, oldbc); // Re-use oldbc.
14593       enqueueflipedge(oldbc, flipqueue);
14594       // Go to the next.
14595       spivotself(spinabc);
14596       if (spinabc.sh == dummysh) {
14597         break; // 'ab' is a hull edge.
14598       }
14599     } while (spinabc.sh != startabc.sh);
14600   }
14601 }
14602 
14604 //                                                                           //
14605 // unsplitsubedge()    Reverse the operation of splitting an edge of subface,//
14606 //                     so as to remove a point from the edge.                //
14607 //                                                                           //
14608 // Assume the original edge is ab, the subface containing it is abc. It was  //
14609 // split by a point v into avc, and vbc.  'splitsh' represents avc, further- //
14610 // more, if av is a subsegment, av should be the zero version of the split   //
14611 // subsegment (i.e., av.shver = 0), so we are sure that the destination (v)  //
14612 // of both avc and av is the deleting point.                                 //
14613 //                                                                           //
14614 // To remove point v is to expand avc to abc, delete vbc, do the same for    //
14615 // other subfaces containing av and vb. If av and vb are subsegments, expand //
14616 // av to ab, delete vb.  On completion, point v is not deleted.              //
14617 //                                                                           //
14619 
14620 void tetgenmesh::unsplitsubedge(face* splitsh)
14621 {
14622   face startavc, spinavc, spinbcv;
14623   face oldvc, bccasin, bccasout, spinsh;
14624   face av, vb, bc;
14625   point pa, pv, pb;
14626 
14627   startavc = *splitsh;
14628   sspivot(startavc, av);
14629   if (av.sh != dummysh) {
14630     // Orient the direction of subsegment to conform the subface.
14631     if (sorg(av) != sorg(startavc)) {
14632       sesymself(av);
14633     }
14634 #ifdef SELF_CHECK
14635     assert(av.shver == 0);
14636 #endif
14637   }
14638   senext(startavc, oldvc);
14639   spivot(oldvc, vb);  // vb is subface vbc
14640   if (sorg(vb) != sdest(oldvc)) {
14641     sesymself(vb);
14642   }
14643   senextself(vb);
14644   pa = sorg(startavc);
14645   pv = sdest(startavc);
14646   pb = sdest(vb);
14647 
14648   if (b->verbose > 1) {
14649     printf("  Removing point %d from subedge (%d, %d).\n",
14650            pointmark(pv), pointmark(pa), pointmark(pb));
14651   }
14652 
14653   // Spin arround av, unsplit every subface containing av.
14654   spinavc = startavc;
14655   do {
14656     // Adjust spinavc be edge av.
14657     if (sorg(spinavc) != pa) {
14658       sesymself(spinavc);
14659     }
14660     // Save old configuration at edge bc, if bc has a subsegment, save the
14661     //   face link of it.
14662     senext(spinavc, oldvc);
14663     spivot(oldvc, spinbcv);
14664     if (sorg(spinbcv) != sdest(oldvc)) {
14665       sesymself(spinbcv);
14666     }
14667     senext2self(spinbcv);
14668     spivot(spinbcv, bccasout);
14669     sspivot(spinbcv, bc);
14670     if (bc.sh != dummysh) {
14671       if (spinbcv.sh != bccasout.sh) {
14672         // 'spinbcv' is not self-bonded.
14673         spinsh = bccasout;
14674         do {
14675           bccasin = spinsh;
14676           spivotself(spinsh);
14677         } while (spinsh.sh != spinbcv.sh);
14678       } else {
14679         bccasout.sh = dummysh;
14680       }
14681     }
14682     // Expand avc to abc.
14683     setsdest(spinavc, pb);
14684     if (bc.sh != dummysh) {
14685       if (bccasout.sh != dummysh) {
14686         sbond1(bccasin, oldvc);
14687         sbond1(oldvc, bccasout);
14688       } else {
14689         // Bond 'oldbc' to itself.
14690         sbond(oldvc, oldvc);
14691       }
14692       ssbond(oldvc, bc);
14693     } else {
14694       sbond(oldvc, bccasout);
14695     }
14696     // Delete bcv.
14697     shellfacedealloc(subfaces, spinbcv.sh);
14698     // Go to next subface at edge av.
14699     spivotself(spinavc);
14700     if (spinavc.sh == dummysh) {
14701       break; // 'av' is a hull edge.
14702     }
14703   } while (spinavc.sh != startavc.sh);
14704 
14705   // Is there a subsegment need to be unsplit?
14706   if (av.sh != dummysh) {
14707     senext(av, oldvc);  // Re-use oldvc.
14708     spivot(oldvc, vb);
14709     vb.shver = 0;
14710 #ifdef SELF_CHECK
14711     assert(sdest(av) == sorg(vb));
14712 #endif
14713     senext(vb, spinbcv); // Re-use spinbcv.
14714     spivot(spinbcv, bccasout);
14715     // Expand av to ab.
14716     setsdest(av, pb);
14717     sbond(oldvc, bccasout);
14718     // Delete vb.
14719     shellfacedealloc(subsegs, vb.sh);
14720   }
14721 }
14722 
14724 //                                                                           //
14725 // insertsite()    Insert a point into the mesh.                             //
14726 //                                                                           //
14727 // The 'newpoint' is located.  If 'searchtet->tet' is not NULL, the search   //
14728 // for the containing tetrahedron begins from 'searchtet', otherwise, a full //
14729 // point location procedure is called.  If 'newpoint' is found inside a      //
14730 // tetrahedron, the tetrahedron is split into four (by splittetrahedron());  //
14731 // if 'newpoint' lies on a face, the face is split into three, thereby       //
14732 // splitting the two adjacent tetrahedra into six (by splittetface()); if    //
14733 // 'newpoint' lies on an edge, the edge is split into two, thereby, every    //
14734 // tetrahedron containing this edge is split into two. If 'newpoint' lies on //
14735 // an existing vertex, no action is taken, and the value DUPLICATEPOINT  is  //
14736 // returned and 'searchtet' is set to a handle whose origin is the vertex.   //
14737 //                                                                           //
14738 // If 'flipqueue' is not NULL, after 'newpoint' is inserted, it returns all  //
14739 // faces which may become non-Delaunay due to the newly inserted point. Flip //
14740 // operations can be performed as necessary on them to maintain the Delaunay //
14741 // property.                                                                 //
14742 //                                                                           //
14744 
14745 enum tetgenmesh::insertsiteresult tetgenmesh::insertsite(point newpoint,
14746   triface* searchtet, bool approx, queue* flipqueue)
14747 {
14748   enum locateresult intersect, exactloc;
14749   point checkpt;
14750   REAL epspp, checklen;
14751   int count;
14752 
14753   if (b->verbose > 1) {
14754     printf("  Insert point to mesh: (%.12g, %.12g, %.12g) %d.\n",
14755            newpoint[0], newpoint[1], newpoint[2], pointmark(newpoint));
14756   }
14757 
14758   if (searchtet->tet == (tetrahedron *) NULL) {
14759     // Search for a tetrahedron containing 'newpoint'.
14760     searchtet->tet = dummytet;
14761     exactloc = locate(newpoint, searchtet);
14762   } else {
14763     // Start searching from the tetrahedron provided by the caller.
14764     exactloc = preciselocate(newpoint, searchtet, tetrahedrons->items);
14765   }
14766   intersect = exactloc;
14767   if (approx && (exactloc != ONVERTEX)) {
14768     // Adjust the exact location to an approx. location wrt. epsilon.
14769     epspp = b->epsilon;
14770     count = 0;
14771     while (count < 16) {
14772       intersect = adjustlocate(newpoint, searchtet, exactloc, epspp);
14773       if (intersect == ONVERTEX) {
14774         checkpt = org(*searchtet);
14775         checklen = distance(checkpt, newpoint);
14776         if (checklen / longest > b->epsilon) {
14777           epspp *= 1e-2;
14778           count++;
14779           continue;
14780         }
14781       }
14782       break;
14783     }
14784   }
14785   // Keep current search state for next searching.
14786   recenttet = *searchtet;
14787 
14788   // Insert the point using the right routine
14789   switch (intersect) {
14790   case ONVERTEX:
14791     // There's already a vertex there. Return in 'searchtet' a tetrahedron
14792     //   whose origin is the existing vertex.
14793     if (b->verbose > 1) {
14794       printf("  Not insert for duplicating point.\n");
14795     }
14796     return DUPLICATEPOINT;
14797 
14798   case OUTSIDE:
14799     if (b->verbose > 1) {
14800       printf("  Not insert for locating outside the mesh.\n");
14801     }
14802     return OUTSIDEPOINT;
14803 
14804   case ONEDGE:
14805     // 'newpoint' falls on an edge.
14806     splittetedge(newpoint, searchtet, flipqueue);
14807     return SUCCESSONEDGE;
14808 
14809   case ONFACE:
14810     // 'newpoint' falls on a face.
14811     splittetface(newpoint, searchtet, flipqueue);
14812     return SUCCESSONFACE;
14813 
14814   case INTETRAHEDRON:
14815     // 'newpoint' falls inside a tetrahedron.
14816     splittetrahedron(newpoint, searchtet, flipqueue);
14817     return SUCCESSINTET;
14818 
14819   default:
14820     // Impossible case.
14821     return OUTSIDEPOINT;
14822   }
14823 }
14824 
14826 //                                                                           //
14827 // undosite()    Undo the most recently point insertion.                     //
14828 //                                                                           //
14829 // 'insresult' indicates in where the newpoint has been inserted, i.e., in a //
14830 // tetrahedron, on a face, or on an edge.  A correspoding routine will be    //
14831 // called to undo the point insertion.  'splittet' is a handle represent one //
14832 // of the resulting tetrahedra, but it may be changed after transformation,  //
14833 // even may be dead.  Four points 'torg', ... 'toppo' are the corners which  //
14834 // 'splittet' should have. On finish, 'newpoint' is not removed.             //
14835 //                                                                           //
14837 
14838 void tetgenmesh::undosite(enum insertsiteresult insresult, triface* splittet,
14839   point torg, point tdest, point tapex, point toppo)
14840 {
14841   // Set the four corners of 'splittet' exactly be 'torg', ... 'toppo'.
14842   findface(splittet, torg, tdest, tapex);
14843   if (oppo(*splittet) != toppo) {
14844     symself(*splittet);
14845 #ifdef SELF_CHECK
14846     assert(oppo(*splittet) == toppo);
14847 #endif
14848     // The sym() operation may inverse the edge, correct it if so.
14849     findedge(splittet, torg, tdest);
14850   }
14851 
14852   // Unsplit the tetrahedron according to 'insresult'.
14853   switch (insresult) {
14854   case SUCCESSINTET:
14855     // 'splittet' should be the face with 'newpoint' as its opposite.
14856     unsplittetrahedron(splittet);
14857     break;
14858   case SUCCESSONFACE:
14859     // 'splittet' should be the one of three splitted face with 'newpoint'
14860     //   as its apex.
14861     unsplittetface(splittet);
14862     break;
14863   case SUCCESSONEDGE:
14864     // 'splittet' should be the tet with destination is 'newpoint'.
14865     unsplittetedge(splittet);
14866     break;
14867   default: // To omit compile warnings.
14868     break;
14869   }
14870 }
14871 
14873 //                                                                           //
14874 // closeopenface()    Close "open" faces recursively.                        //
14875 //                                                                           //
14876 // This is the support routine of inserthullsite(). A point p which lies out-//
14877 // side of CH(T). p is inserted to T by forming a tet t from p and a visible //
14878 // CH face f. The three sides of f which have p as a vertex is called "open" //
14879 // face. Each open face will be closed by either creating a tet on top of it //
14880 // or become a new CH face.                                                  //
14881 //                                                                           //
14883 
14884 void tetgenmesh::closeopenface(triface* openface, queue* flipque)
14885 {
14886   triface newtet, oldhull;
14887   triface newopenface, closeface;
14888   point inspoint, pa, pb, pc;
14889   REAL attrib, volume;
14890   int i;
14891 
14892   // Get the new point p.
14893   inspoint = apex(*openface);
14894   // Find the old CH face f_o (f and f_o share the same edge).
14895   esym(*openface, oldhull);
14896   while (fnextself(oldhull)) ;
14897   if (apex(oldhull) != inspoint) {
14898     // Is f_o visible by p?
14899     pa = org(oldhull);
14900     pb = dest(oldhull);
14901     pc = apex(oldhull);
14902     if (orient3d(pa, pb, pc, inspoint) < 0.0) {
14903       // Yes. Create a new tet t above f_o.
14904       maketetrahedron(&newtet);
14905       setorg(newtet, pa);
14906       setdest(newtet, pb);
14907       setapex(newtet, pc);
14908       setoppo(newtet, inspoint);
14909       for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14910         attrib = elemattribute(oldhull.tet, i);
14911         setelemattribute(newtet.tet, i, attrib);
14912       }
14913       if (b->varvolume) {
14914         volume = volumebound(oldhull.tet);
14915         setvolumebound(newtet.tet, volume);
14916       }
14917       // Connect t to T.
14918       bond(newtet, oldhull);
14919       // Close f.
14920       fnext(newtet, newopenface);
14921       bond(newopenface, *openface);
14922       // f_o becomes an interior face.
14923       enqueueflipface(oldhull, flipque);
14924       // Hull face number decreases.
14925       hullsize--;
14926       // Two faces of t become open face.
14927       enextself(newtet);
14928       for (i = 0; i < 2; i++) {
14929         fnext(newtet, newopenface);
14930         sym(newopenface, closeface);
14931         if (closeface.tet == dummytet) {
14932           closeopenface(&newopenface, flipque);
14933         }
14934         enextself(newtet);
14935       }
14936     } else {
14937       // Inivisible. f becomes a new CH face.
14938       hullsize++;
14939       // Let 'dummytet' holds f for the next point location.
14940       dummytet[0] = encode(*openface);
14941     }
14942   } else {
14943     // f_o is co-incident with f --> f is closed by f_o.
14944     bond(*openface, oldhull);
14945     // f is an interior face.
14946     enqueueflipface(*openface, flipque);
14947   }
14948 }
14949 
14951 //                                                                           //
14952 // inserthullsite()    Insert a point which lies outside the convex hull.    //
14953 //                                                                           //
14954 // The 'inspoint' p lies outside the tetrahedralization T.  The 'horiz' f is //
14955 // on the convex hull of T, CH(T), which is visible by p (Imagine f is para- //
14956 // llel to the horizon). To insert p into T we have to enlarge the CH(T) and //
14957 // update T so that p is on the new CH(T).                                   //
14958 //                                                                           //
14959 // To enlarge the CH(T).  We need to find the set F of faces which are on CH //
14960 // (T) and visible by p (F can be formed by a depth-first search from f).  p //
14961 // is then inserted into T by mounting new tets formed by p and these faces. //
14962 // Faces of F become interior faces and may non-locally Delaunay.  They are  //
14963 // queued in 'flipqueue' for flip tests.                                     //
14964 //                                                                           //
14966 
14967 void tetgenmesh::inserthullsite(point inspoint, triface* horiz, queue* flipque)
14968 {
14969   triface firstnewtet;
14970   triface openface, closeface;
14971   REAL attrib, volume;
14972   int i;
14973 
14974   // Let f face to p.
14975   adjustedgering(*horiz, CW);
14976   // Create the first tet t (from f and p).
14977   maketetrahedron(&firstnewtet);
14978   setorg (firstnewtet, org(*horiz));
14979   setdest(firstnewtet, dest(*horiz));
14980   setapex(firstnewtet, apex(*horiz));
14981   setoppo(firstnewtet, inspoint);
14982   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14983     attrib = elemattribute(horiz->tet, i);
14984     setelemattribute(firstnewtet.tet, i, attrib);
14985   }
14986   if (b->varvolume) {
14987     volume = volumebound(horiz->tet);
14988     setvolumebound(firstnewtet.tet, volume);
14989   }
14990   // Connect t to T.
14991   bond(firstnewtet, *horiz);
14992   // f is not on CH(T) anymore.
14993   enqueueflipface(*horiz, flipque);
14994   // Hull face number decreases.
14995   hullsize--;
14996 
14997   // Call the faces of t which have p as a vertex "open" face.
14998   for (i = 0; i < 3; i++) {
14999     // Get an open face f_i of t.
15000     fnext(firstnewtet, openface);
15001     // Close f_i if it is still open.
15002     sym(openface, closeface);
15003     if (closeface.tet == dummytet) {
15004       closeopenface(&openface, flipque);
15005     }
15006     // Go to the next open face of t.
15007     enextself(firstnewtet);
15008   }
15009 }
15010 
15012 //                                                                           //
15013 // Terminology: BC(p) and CBC(p), B(p) and C(p).                             //
15014 //                                                                           //
15015 // Given an arbitrary point p,  the Bowyer-Watson cavity BC(p) is formed by  //
15016 // tets whose circumspheres containing p.  The outer faces of BC(p) form a   //
15017 // polyhedron B(p).                                                          //
15018 //                                                                           //
15019 // If p is on a facet F, the constrained Bowyer-Watson cavity CBC(p) on F is //
15020 // formed by subfaces of F whose circumspheres containing p. The outer edges //
15021 // of CBC(p) form a polygon C(p).  B(p) is separated into two parts by C(p), //
15022 // denoted as B_1(p) and B_2(p), one of them may be empty (F is on the hull).//
15023 //                                                                           //
15024 // If p is on a segment S which is shared by n facets.  There exist n C(p)s, //
15025 // each one is a non-closed polygon (without S). B(p) is split into n parts, //
15026 // each of them is denoted as B_i(p), some B_i(p) may be empty.              //
15027 //                                                                           //
15029 
15031 //                                                                           //
15032 // formbowatcavitysub()    Form CBC(p) and C(p) on a facet F.                //
15033 //                                                                           //
15034 // Parameters: bp = p, bpseg = S, sublist = CBC(p), subceillist = C(p).      //
15035 //                                                                           //
15036 // CBC(p) contains at least one subface on input; S may be NULL which means  //
15037 // that p is inside a facet. On output, all subfaces of CBC(p) are infected, //
15038 // and the edge rings are oriented to the same halfspace.                    //
15039 //                                                                           //
15041 
15042 void tetgenmesh::formbowatcavitysub(point bp, face* bpseg, list* sublist,
15043   list* subceillist)
15044 {
15045   triface adjtet;
15046   face startsh, neighsh;
15047   face checkseg;
15048   point pa, pb, pc, pd;
15049   REAL sign;
15050   int i, j;
15051 
15052   // Form CBC(p) and C(p) by a broadth-first searching.
15053   for (i = 0; i < sublist->len(); i++) {
15054     startsh = * (face *)(* sublist)[i]; // startsh = f.
15055     // Look for three neighbors of f.
15056     for (j = 0; j < 3; j++) {
15057       sspivot(startsh, checkseg);
15058       if (checkseg.sh == dummysh) {
15059         // Get its neighbor n.
15060         spivot(startsh, neighsh);
15061         // Is n already in CBC(p)?
15062         if (!sinfected(neighsh)) {
15063           stpivot(neighsh, adjtet);
15064           if (adjtet.tet == dummytet) {
15065             sesymself(neighsh);
15066             stpivot(neighsh, adjtet);
15067           }
15068           // For positive orientation that insphere() test requires.
15069           adjustedgering(adjtet, CW);
15070           pa = org(adjtet);
15071           pb = dest(adjtet);
15072           pc = apex(adjtet);
15073           pd = oppo(adjtet);
15074           sign = insphere(pa, pb, pc, pd, bp);
15075           if (sign >= 0.0) {
15076             // Orient edge ring of n according to that of f.
15077             if (sorg(neighsh) != sdest(startsh)) sesymself(neighsh);
15078             // Collect it into CBC(p).
15079             sinfect(neighsh);
15080             sublist->append(&neighsh);
15081           } else {
15082             subceillist->append(&startsh); // Found an edge of C(p).
15083           }
15084         }
15085       } else {
15086         // Do not cross a segment.
15087         if (bpseg != (face *) NULL) {
15088           if (checkseg.sh != bpseg->sh) {
15089             subceillist->append(&startsh); // Found an edge of C(p).
15090           }
15091         } else {
15092           subceillist->append(&startsh); // Found an edge of C(p).
15093         }
15094       }
15095       senextself(startsh);
15096     }
15097   }
15098 
15099   if (b->verbose > 2) {
15100     printf("    Collect CBC(%d): %d subfaces, %d edges.\n", pointmark(bp),
15101            sublist->len(), subceillist->len());
15102   }
15103 }
15104 
15106 //                                                                           //
15107 // formbowatcavityquad()    Form BC_i(p) and B_i(p) in a quadrant.           //
15108 //                                                                           //
15109 // Parameters: bp = p, tetlist = BC_i(p), ceillist = B_i(p).                 //
15110 //                                                                           //
15111 // BC_i(p) contains at least one tet on input. On finish, all tets collected //
15112 // in BC_i(p) are infected. B_i(p) may not closed when p is on segment or in //
15113 // facet. C(p) must be formed before this routine.  Check the infect flag of //
15114 // a subface to identify the unclosed side of B_i(p).  These sides will be   //
15115 // closed by new subfaces of C(p)s.                                          //
15116 //                                                                           //
15118 
15119 void tetgenmesh::formbowatcavityquad(point bp, list* tetlist, list* ceillist)
15120 {
15121   triface starttet, neightet;
15122   face checksh;
15123   point pa, pb, pc, pd;
15124   REAL sign;
15125   int i;
15126 
15127   // Form BC_i(p) and B_i(p) by a broadth-first searching.
15128   for (i = 0; i < tetlist->len(); i++) {
15129     starttet = * (triface *)(* tetlist)[i];
15130     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15131       // Try to collect the neighbor of the face (f).
15132       tspivot(starttet, checksh);
15133       if (checksh.sh == dummysh) {
15134         // Get its neighbor n.
15135         sym(starttet, neightet);
15136         // Is n already in BC_i(p)?
15137         if (!infected(neightet)) {
15138           // For positive orientation that insphere() test requires.
15139           adjustedgering(neightet, CW);
15140           pa = org(neightet);
15141           pb = dest(neightet);
15142           pc = apex(neightet);
15143           pd = oppo(neightet);
15144           sign = insphere(pa, pb, pc, pd, bp);
15145           if (sign >= 0.0) {
15146             // Collect it into BC_i(p).
15147             infect(neightet);
15148             tetlist->append(&neightet);
15149           } else {
15150             ceillist->append(&starttet); // Found a face of B_i(p).
15151           }
15152         }
15153       } else {
15154         // Do not cross a boundary face.
15155         if (!sinfected(checksh)) {
15156           ceillist->append(&starttet); // Found a face of B_i(p).
15157         }
15158       }
15159     }
15160   }
15161 
15162   if (b->verbose > 2) {
15163     printf("    Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15164            tetlist->len(), ceillist->len());
15165   }
15166 }
15167 
15169 //                                                                           //
15170 // formbowatcavitysegquad()    Form BC_i(p) and B_i(p) in a segment quadrant.//
15171 //                                                                           //
15172 // Parameters: bp = p, tetlist = BC_i(p), ceillist = B_i(p).                 //
15173 //                                                                           //
15174 // BC_i(p) contains at least one tet on input. On finish, all tets collected //
15175 // in BC_i(p) are infected. B_i(p) is not closed. C(p) must be formed before //
15176 // this routine. Check the infect flag of a subface to identify the unclosed //
15177 // sides of B_i(p).  These sides will be closed by new subfaces of C(p)s.    //
15178 //                                                                           //
15179 // During the repair of encroaching subsegments, there may exist locally non-//
15180 // Delaunay faces. These faces are collected in BC_i(p) either.  B_i(p) has  //
15181 // to be formed later than BC_i(p).                                          //
15182 //                                                                           //
15184 
15185 void tetgenmesh::formbowatcavitysegquad(point bp, list* tetlist,list* ceillist)
15186 {
15187   triface starttet, neightet, cavtet;
15188   face checksh;
15189   point pa, pb, pc, pd, pe;
15190   REAL sign;
15191   int i;
15192 
15193   // Form BC_i(p) by a broadth-first searching.
15194   for (i = 0; i < tetlist->len(); i++) {
15195     starttet = * (triface *)(* tetlist)[i];
15196     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15197       // Try to collect the neighbor of the face f.
15198       tspivot(starttet, checksh);
15199       if (checksh.sh == dummysh) {
15200         // Get its neighbor n.
15201         sym(starttet, neightet);
15202         // Is n already in BC_i(p)?
15203         if (!infected(neightet)) {
15204           // For positive orientation that insphere() test requires.
15205           adjustedgering(neightet, CW);
15206           pa = org(neightet);
15207           pb = dest(neightet);
15208           pc = apex(neightet);
15209           pd = oppo(neightet);
15210           sign = insphere(pa, pb, pc, pd, bp);
15211           if (sign >= 0.0) {
15212             // Collect it into BC_i(p).
15213             infect(neightet);
15214             tetlist->append(&neightet);
15215           } else {
15216             // Check if the face is locally non-Delaunay.
15217             pe = oppo(starttet);
15218             sign = insphere(pa, pb, pc, pd, pe);
15219             if (sign >= 0.0) {
15220               // Collect it into BC_i(p).
15221               infect(neightet);
15222               tetlist->append(&neightet);
15223             }
15224           }
15225         }
15226       }
15227     }
15228   }
15229 
15230   // Generate B_i(p).
15231   for (i = 0; i < tetlist->len(); i++) {
15232     cavtet = * (triface *)(* tetlist)[i];
15233     for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15234       tspivot(cavtet, checksh);
15235       if (checksh.sh == dummysh) {
15236         sym(cavtet, neightet);
15237         if (!infected(neightet)) {
15238           ceillist->append(&cavtet); // Found a face of B(p).
15239         }
15240       } else {
15241         // Do not cross a boundary face.
15242         if (!sinfected(checksh)) {
15243           ceillist->append(&cavtet); // Found a face of B(p).
15244         }
15245       }
15246     }
15247   }
15248 
15249   if (b->verbose > 2) {
15250     printf("    Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15251            tetlist->len(), ceillist->len());
15252   }
15253 }
15254 
15256 //                                                                           //
15257 // formbowatcavity()    Form BC(p), B(p), CBC(p)s, and C(p)s.                //
15258 //                                                                           //
15259 // If 'bpseg'(S) != NULL, p is on segment S, else, p is on facet containing  //
15260 // 'bpsh' (F).  'n' returns the number of quadrants in BC(p). 'nmax' is the  //
15261 // maximum pre-allocated array length for the lists.                         //
15262 //                                                                           //
15264 
15265 void tetgenmesh::formbowatcavity(point bp, face* bpseg, face* bpsh, int* n,
15266   int* nmax, list** sublists, list** subceillists, list** tetlists,
15267   list** ceillists)
15268 {
15269   list *sublist;
15270   triface adjtet;
15271   face startsh, spinsh;
15272   point pa, pb;
15273   int i, j;
15274 
15275   *n = 0;
15276   if (bpseg != (face *) NULL) {
15277     // p is on segment S.
15278     bpseg->shver = 0;
15279     pa = sorg(*bpseg);
15280     pb = sdest(*bpseg);
15281     // Count the number of facets sharing at S.
15282     spivot(*bpseg, startsh);
15283     spinsh = startsh;
15284     do {
15285       (*n)++; // spinshlist->append(&spinsh);
15286       spivotself(spinsh);
15287     } while (spinsh.sh != startsh.sh);
15288     // *n is the number of quadrants around S.
15289     if (*n > *nmax) {
15290       // Reallocate arrays. Should not happen very often.
15291       delete [] tetlists;
15292       delete [] ceillists;
15293       delete [] sublists;
15294       delete [] subceillists;
15295       tetlists = new list*[*n];
15296       ceillists = new list*[*n];
15297       sublists = new list*[*n];
15298       subceillists = new list*[*n];
15299       *nmax = *n;
15300     }
15301     // Form CBC(p)s and C(p)s.
15302     spinsh = startsh;
15303     for (i = 0; i < *n; i++) {
15304       sublists[i] = new list(sizeof(face), NULL, 256);
15305       subceillists[i] = new list(sizeof(face), NULL, 256);
15306       // Set a subface f to start search.
15307       startsh = spinsh;
15308       // Let f face to the quadrant of interest (used in forming BC(p)).
15309       findedge(&startsh, pa, pb);
15310       sinfect(startsh);
15311       sublists[i]->append(&startsh);
15312       formbowatcavitysub(bp, bpseg, sublists[i], subceillists[i]);
15313       // Go to the next facet.
15314       spivotself(spinsh);
15315     }
15316   } else if (sublists != (list **) NULL) {
15317     // p is on a facet.
15318     *n = 2;
15319     // Form CBC(p) and C(p).
15320     sublists[0] = new list(sizeof(face), NULL, 256);
15321     subceillists[0] = new list(sizeof(face), NULL, 256);
15322     sinfect(*bpsh);
15323     sublists[0]->append(bpsh);
15324     formbowatcavitysub(bp, NULL, sublists[0], subceillists[0]);
15325   } else {
15326     // p is inside a tet.
15327     *n = 1;
15328   }
15329 
15330   // Form BC_i(p) and B_i(p).
15331   for (i = 0; i < *n; i++) {
15332     tetlists[i] = new list(sizeof(triface), NULL, 256);
15333     ceillists[i] = new list(sizeof(triface), NULL, 256);
15334     if (sublists != (list **) NULL) {
15335       // There are C(p)s.
15336       sublist = ((bpseg == (face *) NULL) ? sublists[0] : sublists[i]);
15337       // Add all adjacent tets of C_i(p) into BC_i(p).
15338       for (j = 0; j < sublist->len(); j++) {
15339         startsh = * (face *)(* sublist)[j];
15340         // Adjust the side facing to the right quadrant for C(p).
15341         if ((bpseg == (face *) NULL) && (i == 1)) sesymself(startsh);
15342         stpivot(startsh, adjtet);
15343         if (adjtet.tet != dummytet) {
15344           if (!infected(adjtet)) {
15345             infect(adjtet);
15346             tetlists[i]->append(&adjtet);
15347           }
15348         }
15349       }
15350       if (bpseg != (face *) NULL) {
15351         // The quadrant is bounded by another facet.
15352         sublist = ((i < *n - 1) ? sublists[i + 1] : sublists[0]);
15353         for (j = 0; j < sublist->len(); j++) {
15354           startsh = * (face *)(* sublist)[j];
15355           // Adjust the side facing to the right quadrant for C(p).
15356           sesymself(startsh);
15357           stpivot(startsh, adjtet);
15358           if (adjtet.tet != dummytet) {
15359             if (!infected(adjtet)) {
15360               infect(adjtet);
15361               tetlists[i]->append(&adjtet);
15362             }
15363           }
15364         }
15365       }
15366     }
15367     // It is possible that BC_i(p) is empty.
15368     if (tetlists[i]->len() == 0) continue;
15369     // Collect the rest of tets of BC_i(p) and form B_i(p).
15370     // if (b->conformdel) {
15371       // formbowatcavitysegquad(bp, tetlists[i], ceillists[i]);
15372     // } else {
15373       formbowatcavityquad(bp, tetlists[i], ceillists[i]);
15374     // }
15375   }
15376 }
15377 
15379 //                                                                           //
15380 // releasebowatcavity()    Undo and free the memory allocated in routine     //
15381 //                         formbowatcavity().                                //
15382 //                                                                           //
15384 
15385 void tetgenmesh::releasebowatcavity(face* bpseg, int n, list** sublists,
15386   list** subceillist, list** tetlists, list** ceillists)
15387 {
15388   triface oldtet;
15389   face oldsh;
15390   int i, j;
15391 
15392   if (sublists != (list **) NULL) {
15393     // Release CBC(p)s.
15394     for (i = 0; i < n; i++) {
15395       // Uninfect subfaces of CBC(p).
15396       for (j = 0; j < sublists[i]->len(); j++) {
15397         oldsh = * (face *)(* (sublists[i]))[j];
15398 #ifdef SELF_CHECK
15399         assert(sinfected(oldsh));
15400 #endif
15401         suninfect(oldsh);
15402       }
15403       delete sublists[i];
15404       delete subceillist[i];
15405       sublists[i] = (list *) NULL;
15406       subceillist[i] = (list *) NULL;
15407       if (bpseg == (face *) NULL) break;
15408     }
15409   }
15410   // Release BC(p).
15411   for (i = 0; i < n; i++) {
15412     // Uninfect tets of BC_i(p).
15413     for (j = 0; j < tetlists[i]->len(); j++) {
15414       oldtet = * (triface *)(* (tetlists[i]))[j];
15415 #ifdef SELF_CHECK
15416       assert(infected(oldtet));
15417 #endif
15418       uninfect(oldtet);
15419     }
15420     delete tetlists[i];
15421     delete ceillists[i];
15422     tetlists[i] = (list *) NULL;
15423     ceillists[i] = (list *) NULL;
15424   }
15425 }
15426 
15428 //                                                                           //
15429 // validatebowatcavityquad()    Valid B_i(p).                                //
15430 //                                                                           //
15431 // B_i(p) is valid if all faces of B_i(p) are visible by p, else B_i(p) is   //
15432 // invalid.  Each tet of BC_i(p) which has such a face is marked (uninfect). //
15433 // They will be removed in updatebowatcavityquad().                          //
15434 //                                                                           //
15435 // Return TRUE if B(p) is valid, else, return FALSE.                         //
15436 //                                                                           //
15438 
15439 bool tetgenmesh::validatebowatcavityquad(point bp,list* ceillist,REAL maxcosd)
15440 {
15441   triface ceiltet;
15442   point pa, pb, pc;
15443   REAL ori, cosd;
15444   int remcount, i;
15445 
15446   // Check the validate of B(p), cut tets having invisible faces.
15447   remcount = 0;
15448   for (i = 0; i < ceillist->len(); i++) {
15449     ceiltet = * (triface *)(* ceillist)[i];
15450     if (infected(ceiltet)) {
15451       adjustedgering(ceiltet, CCW);
15452       pa = org(ceiltet);
15453       pb = dest(ceiltet);
15454       pc = apex(ceiltet);
15455       ori = orient3d(pa, pb, pc, bp);
15456       if (ori >= 0.0) {
15457         // Found an invisible face.
15458         uninfect(ceiltet);
15459         remcount++;
15460         continue;
15461       }
15462       // If a non-trival 'maxcosd' is given.
15463       if (maxcosd > -1.0) {
15464         // Get the maximal dihedral angle of tet abcp.
15465         tetalldihedral(pa, pb, pc, bp, NULL, &cosd, NULL);
15466         // Do not form the tet if the maximal dihedral angle is not reduced.
15467         if (cosd < maxcosd) {
15468           uninfect(ceiltet);
15469           remcount++;
15470         }
15471       }
15472     }
15473   }
15474   return remcount == 0;
15475 }
15476 
15478 //                                                                           //
15479 // updatebowatcavityquad()    Update BC_i(p) and reform B_i(p).              //
15480 //                                                                           //
15481 // B_i(p) is invalid and some tets in BC_i(p) have been marked to be removed //
15482 // in validatebowatcavityquad().  This routine actually remove the cut tets  //
15483 // of BC_i(p) and re-form the B_i(p).                                        //
15484 //                                                                           //
15486 
15487 void tetgenmesh::updatebowatcavityquad(list* tetlist, list* ceillist)
15488 {
15489   triface cavtet, neightet;
15490   face checksh;
15491   int remcount, i;
15492 
15493   remcount = 0;
15494   for (i = 0; i < tetlist->len(); i++) {
15495     cavtet = * (triface *)(* tetlist)[i];
15496     if (!infected(cavtet)) {
15497       tetlist->del(i, 1);
15498       remcount++;
15499       i--;
15500     }
15501   }
15502 
15503   // Are there tets have been cut in BC_i(p)?
15504   if (remcount > 0) {
15505     // Re-form B_i(p).
15506     ceillist->clear();
15507     for (i = 0; i < tetlist->len(); i++) {
15508       cavtet = * (triface *)(* tetlist)[i];
15509       for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15510         tspivot(cavtet, checksh);
15511         if (checksh.sh == dummysh) {
15512           sym(cavtet, neightet);
15513           if (!infected(neightet)) {
15514             ceillist->append(&cavtet); // Found a face of B_i(p).
15515           }
15516         } else {
15517           // Do not cross a boundary face.
15518           if (!sinfected(checksh)) {
15519             ceillist->append(&cavtet); // Found a face of B_i(p).
15520           }
15521         }
15522       }
15523     }
15524     if (b->verbose > 2) {
15525       printf("    Update BC_i(p): %d tets, %d faces.\n", tetlist->len(),
15526              ceillist->len());
15527     }
15528   }
15529 }
15530 
15532 //                                                                           //
15533 // updatebowatcavitysub()    Check and update CBC(p) and C(p).               //
15534 //                                                                           //
15535 // A CBC(p) is valid if all its subfaces are inside or on the hull of BC(p). //
15536 // A subface s of CBC(p) is invalid if it is in one of the two cases:        //
15537 //   (1) s is completely outside BC(p);                                      //
15538 //   (2) s has two adjacent tets but only one of them is in BC(p);           //
15539 // s is removed from CBC(p) if it is invalid. If there is an adjacent tet of //
15540 // s which is in BC(p), it gets removed from BC(p) too. If CBC(p) is updated,//
15541 // C(p) is re-formed.                                                        //
15542 //                                                                           //
15543 // A C(p) is valid if all its edges are on the hull of BC(p).  An edge e of  //
15544 // C(p) may be inside BC(p) if e is a segment and belongs to only one facet. //
15545 // To correct C(p), a tet of BC(p) which shields e gets removed.             //
15546 //                                                                           //
15547 // If BC(p) is formed with locally non-Delaunay check (b->conformdel > 0).   //
15548 // A boundary-consistent check is needed for non-segment edges of C(p). Let  //
15549 // e be such an edge, the subface f contains e and outside C(p) may belong   //
15550 // to B(p) due to the non-coplanarity of the facet definition.  The tet of   //
15551 // BC(p) containing f gets removed to avoid creating a degenerate new tet.   //
15552 //                                                                           //
15553 // 'cutcount' accumulates the total number of cuttets(not only by this call).//
15554 //                                                                           //
15556 
15557 void tetgenmesh::updatebowatcavitysub(list* sublist, list* subceillist,
15558   int* cutcount)
15559 {
15560   triface adjtet, rotface;
15561   face checksh, neighsh;
15562   face checkseg;
15563   point pa, pb, pc;
15564   REAL ori1, ori2;
15565   int remcount;
15566   int i, j;
15567 
15568   remcount = 0;
15569   // Check the validity of CBC(p).
15570   for (i = 0; i < sublist->len(); i++) {
15571     checksh = * (face *)(* sublist)[i];
15572     // Check two adjacent tets of s.
15573     for (j = 0; j < 2; j++) {
15574       stpivot(checksh, adjtet);
15575       if (adjtet.tet != dummytet) {
15576         if (!infected(adjtet)) {
15577           // Could be either case (1) or (2).
15578           suninfect(checksh); // s survives.
15579           // If the sym. adjtet exists, it should remove from BC(p) too.
15580           sesymself(checksh);
15581           stpivot(checksh, adjtet);
15582           if (adjtet.tet != dummytet) {
15583             if (infected(adjtet)) {
15584               // Found an adj. tet in BC(p), remove it.
15585               uninfect(adjtet);
15586               (*cutcount)++;
15587             }
15588           }
15589           // Remove s from C(p).
15590           sublist->del(i, 1);
15591           i--;
15592           remcount++;
15593           break;
15594         }
15595       }
15596       sesymself(checksh);
15597     }
15598   }
15599   if (remcount > 0) {
15600     if (b->verbose > 2) {
15601       printf("    Removed %d subfaces from CBC(p).\n", remcount);
15602     }
15603     // Re-generate C(p).
15604     subceillist->clear();
15605     for (i = 0; i < sublist->len(); i++) {
15606       checksh = * (face *)(* sublist)[i];
15607       for (j = 0; j < 3; j++) {
15608         spivot(checksh, neighsh);
15609         if (!sinfected(neighsh)) {
15610           subceillist->append(&checksh);
15611         }
15612         senextself(checksh);
15613       }
15614     }
15615     if (b->verbose > 2) {
15616       printf("    Update CBC(p): %d subs, %d edges.\n", sublist->len(),
15617              subceillist->len());
15618     }
15619   }
15620 
15621   // Check the validity of C(p).
15622   for (i = 0; i < subceillist->len(); i++) {
15623     checksh = * (face *)(* subceillist)[i];
15624     sspivot(checksh, checkseg);
15625     if (checkseg.sh != dummysh) {
15626       // A segment. Check if it is inside BC(p).
15627       stpivot(checksh, adjtet);
15628       if (adjtet.tet == dummytet) {
15629         sesym(checksh, neighsh);
15630         stpivot(neighsh, adjtet);
15631       }
15632       findedge(&adjtet, sorg(checkseg), sdest(checkseg));
15633       adjustedgering(adjtet, CCW);
15634       fnext(adjtet, rotface); // It's the same tet.
15635       // Rotate rotface (f), stop on either of the following cases:
15636       //   (a) meet a subface, or
15637       //   (b) enter an uninfected tet, or
15638       //   (c) rewind back to adjtet.
15639       do {
15640         if (!infected(rotface)) break; // case (b)
15641         tspivot(rotface, neighsh);
15642         if (neighsh.sh != dummysh) break; // case (a)
15643         // Go to the next tet of the facing ring.
15644         fnextself(rotface);
15645       } while (apex(rotface) != apex(adjtet));
15646       // Is it case (c)?
15647       if (apex(rotface) == apex(adjtet)) {
15648         // The segment is enclosed by BC(p), invalid cavity.
15649         pa = org(adjtet);
15650         pb = dest(adjtet);
15651         pc = apex(adjtet);
15652         // Find the shield tet and cut it. Notice that the shield tet may
15653         //   not be unique when there are four coplanar points, ie.,
15654         //   ori1 * ori2 == 0.0. In such case, choose either of them.
15655         fnext(adjtet, rotface);
15656         do {
15657           fnextself(rotface);
15658           assert(infected(rotface));
15659           ori1 = orient3d(pa, pb, pc, apex(rotface));
15660           ori2 = orient3d(pa, pb, pc, oppo(rotface));
15661         } while (ori1 * ori2 > 0.0);
15662         // Cut this tet from BC(p).
15663         uninfect(rotface);
15664         (*cutcount)++;
15665       }
15666     } else {
15667       /*// An edge. Check if boundary-consistency should be enforced.
15668       if (b->conformdel > 0) {
15669         // Get the adj-sub n at e, it must be outside C(p).
15670         spivot(checksh, neighsh);
15671         assert(!sinfected(neighsh));
15672         // Check if n is on B(p).
15673         for (j = 0; j < 2; j++) {
15674           stpivot(neighsh, adjtet);
15675           if (adjtet.tet != dummytet) {
15676             if (infected(adjtet)) {
15677               uninfect(adjtet);
15678               (*cutcount)++;
15679             }
15680           }
15681           sesymself(neighsh);
15682         }
15683       } */
15684     }
15685   }
15686 }
15687 
15689 //                                                                           //
15690 // trimbowatcavity()    Validate B(p), CBC(p)s and C(p)s, update BC(p).      //
15691 //                                                                           //
15692 // A B(p) is valid if all its faces are visible by p. If a face f of B(p) is //
15693 // found invisible by p, the tet of BC(p) containing f gets removed and B(p) //
15694 // is refromed. The new B(p) may still contain invisible faces by p. Iterat- //
15695 // ively do the above procedure until B(p) is satisfied.                     //
15696 //                                                                           //
15697 // A CBC(p) is valid if each subface of CBC(p) is either on the hull of BC(p)//
15698 // or completely inside BC(p). If a subface s of CBC(p) is not valid, it is  //
15699 // removed from CBC(p) and C(p) is reformed. If there exists a tet t of BC(p)//
15700 // containg s, t is removed from BC(p). The process for validating BC(p) and //
15701 // B(p) is re-excuted.                                                       //
15702 //                                                                           //
15703 // A C(p) is valid if each edge of C(p) is on the hull of BC(p). If an edge  //
15704 // e of C(p) is invalid (e should be a subsegment which only belong to one   //
15705 // facet), a tet of BC(p) which contains e and has two other faces shielding //
15706 // e is removed. The process for validating BC(p) and B(p) is re-excuted.    //
15707 //                                                                           //
15708 // If either BC(p) or CBC(p) becomes empty. No valid BC(p) is found, return  //
15709 // FALSE. else, return TRUE.                                                 //
15710 //                                                                           //
15712 
15713 bool tetgenmesh::trimbowatcavity(point bp, face* bpseg, int n, list** sublists,
15714   list** subceillists, list** tetlists, list** ceillists, REAL maxcosd)
15715 {
15716   bool valflag;
15717   int oldnum, cutnum, cutcount;
15718   int i;
15719 
15720   cutnum = 0; // Count the total number of cut-off tets of BC(p).
15721   valflag = true;
15722 
15723   do {
15724     // Validate BC(p), B(p).
15725     for (i = 0; i < n && valflag; i++) {
15726       oldnum = tetlists[i]->len();
15727       // Iteratively validate BC_i(p) and B_i(p).
15728       while (!validatebowatcavityquad(bp, ceillists[i], maxcosd)) {
15729         // Update BC_i(p) and B_i(p).
15730         updatebowatcavityquad(tetlists[i], ceillists[i]);
15731         valflag = tetlists[i]->len() > 0;
15732       }
15733       cutnum += (oldnum - tetlists[i]->len());
15734     }
15735     if (valflag && (sublists != (list **) NULL)) {
15736       // Validate CBC(p), C(p).
15737       cutcount = 0;
15738       for (i = 0; i < n; i++) {
15739         updatebowatcavitysub(sublists[i], subceillists[i], &cutcount);
15740         // Only do once if p is on a facet.
15741         if (bpseg == (face *) NULL) break;
15742       }
15743       // Are there cut tets?
15744       if (cutcount > 0) {
15745         // Squeeze all cut tets in BC(p), keep valflag once it gets FLASE.
15746         for (i = 0; i < n; i++) {
15747           if (tetlists[i]->len() > 0) {
15748             updatebowatcavityquad(tetlists[i], ceillists[i]);
15749             if (valflag) {
15750               valflag = tetlists[i]->len() > 0;
15751             }
15752           }
15753         }
15754         cutnum += cutcount;
15755         // Go back to valid the updated BC(p).
15756         continue;
15757       }
15758     }
15759     break; // Leave the while-loop.
15760   } while (true);
15761 
15762   // Check if any CBC(p) becomes non-empty.
15763   if (valflag && (sublists != (list **) NULL)) {
15764     for (i = 0; i < n && valflag; i++) {
15765       valflag = (sublists[i]->len() > 0);
15766       if (bpseg == (face *) NULL) break;
15767     }
15768   }
15769 
15770   if (valflag && (cutnum > 0)) {
15771     // Accumulate counters.
15772     if (bpseg != (face *) NULL) {
15773       updsegcount++;
15774     } else if (sublists != (list **) NULL) {
15775       updsubcount++;
15776     } else {
15777       updvolcount++;
15778     }
15779   }
15780 
15781   if (!valflag) {
15782     // Accumulate counters.
15783     if (bpseg != (face *) NULL) {
15784       failsegcount++;
15785     } else if (sublists != (list **) NULL) {
15786       failsubcount++;
15787     } else {
15788       failvolcount++;
15789     }
15790   }
15791 
15792   return valflag;
15793 }
15794 
15796 //                                                                           //
15797 // bowatinsertsite()    Insert a point using the Bowyer-Watson method.       //
15798 //                                                                           //
15799 // Parameters: 'bp' = p, 'splitseg' = S, 'n' = the number of quadrants,      //
15800 // 'sublists', an array of CBC_i(p)s, 'subceillists', an array of C_i(p)s,   //
15801 // 'tetlists', an array of BC_i(p)s, 'ceillists', an array of B_i(p)s.       //
15802 //                                                                           //
15803 // If p is inside the mesh domain, then S = NULL, n = 1, CBC(p) and C(p) are //
15804 //   NULLs. 'tetlists[0]' = BC(p), 'ceillists[0]' = B(p).                    //
15805 // If p is on a facet F, then S = NULL, n = 2, and 'subceillists[0]' = C(p), //
15806 //  'subceillists[1]' is not needed (set it to NULL). B_1(p) and B_2(p) are  //
15807 //  in 'ceillists[0]' and 'ceillists[1]'.                                    //
15808 // If p is on a segment S, then F(S) is a list of subfaces around S, and n = //
15809 //   len(F(S)), there are n C_i(p)s and B_i(p)s supplied in 'subceillists[i]'//
15810 //   and 'ceillists[i]'.                                                     //
15811 //                                                                           //
15812 // If 'verlist' != NULL, it returns a list of vertices which connect to p.   //
15813 //   This vertices are used for interpolating size of p.                     //
15814 //                                                                           //
15815 // If 'flipque' != NULL, it returns a list of internal faces of new tets in  //
15816 //   BC(p), faces on C(p)s are excluded. These faces may be locally non-     //
15817 //   Delaunay and will be flipped if they are flippable. Such non-Delaunay   //
15818 //   faces may exist when p is inserted to split an encroaching segment.     //
15819 //                                                                           //
15820 // 'chkencseg', 'chkencsub', and 'chkbadtet' are flags that indicate whether //
15821 // or not there should be checks for the creation of encroached subsegments, //
15822 // subfaces, or bad quality tets. If 'chkencseg' = TRUE, the encroached sub- //
15823 // segments are added to the list of subsegments to be split.                //
15824 //                                                                           //
15825 // On return, 'ceillists' returns Star(p).                                   //
15826 //                                                                           //
15828 
15829 void tetgenmesh::bowatinsertsite(point bp,face* splitseg,int n,list** sublists,
15830   list** subceillists, list** tetlists, list** ceillists, list* verlist,
15831   queue* flipque, bool chkencseg, bool chkencsub, bool chkbadtet)
15832 {
15833   list *ceillist, *subceillist;
15834   triface oldtet, newtet, newface, rotface, neightet;
15835   face oldsh, newsh, newedge, checksh;
15836   face spinsh, casingin, casingout;
15837   face *apsegshs, *pbsegshs;
15838   face apseg, pbseg, checkseg;
15839   point pa, pb, pc;
15840   REAL attrib, volume;
15841   int idx, i, j, k;
15842 
15843   apsegshs = NULL;
15844   pbsegshs = NULL;
15845 
15846   if (b->verbose > 1) {
15847     printf("    Insert point %d (%.12g, %.12g, %.12g)", pointmark(bp), bp[0],
15848            bp[1], bp[2]);
15849   }
15850   if (splitseg != (face *) NULL) {
15851     if (b->verbose > 1) {
15852       printf(" on segment.\n");
15853     }
15854     bowatsegcount++;
15855   } else {
15856     if (subceillists != (list **) NULL) {
15857       if (b->verbose > 1) {
15858         printf(" on facet.\n");
15859       }
15860       bowatsubcount++;
15861     } else {
15862       if (b->verbose > 1) {
15863         printf(" in volume.\n");
15864       }
15865       bowatvolcount++;
15866     }
15867   }
15868 
15869   // Create new tets to fill B(p).
15870   for (k = 0; k < n; k++) {
15871     // Create new tets from each B_i(p).
15872     ceillist = ceillists[k];
15873     for (i = 0; i < ceillist->len(); i++) {
15874       oldtet = * (triface *)(* ceillist)[i];
15875       adjustedgering(oldtet, CCW);
15876       pa = org(oldtet);
15877       pb = dest(oldtet);
15878       pc = apex(oldtet);
15879       maketetrahedron(&newtet);
15880       setorg(newtet, pa);
15881       setdest(newtet, pb);
15882       setapex(newtet, pc);
15883       setoppo(newtet, bp);
15884       for (j = 0; j < in->numberoftetrahedronattributes; j++) {
15885         attrib = elemattribute(oldtet.tet, j);
15886         setelemattribute(newtet.tet, j, attrib);
15887       }
15888       if (b->varvolume) {
15889         volume = volumebound(oldtet.tet);
15890         if (volume > 0.0) {
15891           if (!b->fixedvolume && b->refine) {
15892             // '-r -a' switches and a .vol file case. Enlarge the maximum
15893             //   volume constraint for the new tets. Hence the new points
15894             //   only spread near the original constrained tet.
15895             volume *= 1.2;
15896           }
15897         }
15898         setvolumebound(newtet.tet, volume);
15899       }
15900       sym(oldtet, neightet);
15901       tspivot(oldtet, checksh);
15902       if (neightet.tet != dummytet) {
15903         bond(newtet, neightet);
15904       }
15905       if (checksh.sh != dummysh) {
15906         tsbond(newtet, checksh);
15907       }
15908       if (verlist != (list *) NULL) {
15909         // Collect vertices connecting to p.
15910         idx = pointmark(pa);
15911         if (idx >= 0) {
15912           setpointmark(pa, -idx - 1);
15913           verlist->append(&pa);
15914         }
15915         idx = pointmark(pb);
15916         if (idx >= 0) {
15917           setpointmark(pb, -idx - 1);
15918           verlist->append(&pb);
15919         }
15920         idx = pointmark(pc);
15921         if (idx >= 0) {
15922           setpointmark(pc, -idx - 1);
15923           verlist->append(&pc);
15924         }
15925       }
15926       // Replace the tet by the newtet for checking the quality.
15927       * (triface *)(* ceillist)[i] = newtet;
15928     }
15929   }
15930   if (verlist != (list *) NULL) {
15931     // Uninfect collected vertices.
15932     for (i = 0; i < verlist->len(); i++) {
15933       pa = * (point *)(* verlist)[i];
15934       idx = pointmark(pa);
15935       setpointmark(pa, -(idx + 1));
15936     }
15937   }
15938 
15939   // Connect new tets of B(p). Not all faces of new tets can be connected,
15940   //   e.g., if there are empty B_i(p)s.
15941   for (k = 0; k < n; k++) {
15942     ceillist = ceillists[k];
15943     for (i = 0; i < ceillist->len(); i++) {
15944       newtet = * (triface *)(* ceillist)[i];
15945       newtet.ver = 0;
15946       for (j = 0; j < 3; j++) {
15947         fnext(newtet, newface);
15948         sym(newface, neightet);
15949         if (neightet.tet == dummytet) {
15950           // Find the neighbor face by rotating the faces at edge ab.
15951           esym(newtet, rotface);
15952           pa = org(rotface);
15953           pb = dest(rotface);
15954           while (fnextself(rotface));
15955           // Do we meet a boundary face?
15956           tspivot(rotface, checksh);
15957           if (checksh.sh != dummysh) {
15958             // Walk through the boundary and continue to rotate faces.
15959             do {
15960               findedge(&checksh, pa, pb);
15961               sfnextself(checksh);
15962               assert((sorg(checksh) == pa) && (sdest(checksh) == pb));
15963               stpivot(checksh, rotface);
15964               if (infected(rotface)) {
15965                 // Meet an old tet of B_i(p). This side is on the hull and
15966                 //   will be connected to a new subface created in C(p).
15967                 break;
15968               }
15969               findedge(&rotface, pa, pb);
15970               while (fnextself(rotface));
15971               tspivot(rotface, checksh);
15972             } while (checksh.sh != dummysh);
15973           }
15974           // The rotface has edge ab, but it may not have newpt.
15975           if (apex(rotface) == apex(newface)) {
15976             // Bond the two tets together.
15977             bond(newface, rotface);
15978             // Queue (uniquely) this face if 'flipque' is given.
15979             if (flipque != (queue *) NULL) {
15980               enqueueflipface(newface, flipque);
15981             }
15982           }
15983         }
15984         enextself(newtet);
15985       }
15986     }
15987   }
15988 
15989   if (subceillists != (list **) NULL) {
15990     // There are C(p)s.
15991     if (splitseg != (face *) NULL) {
15992       // S (ab) is split by p.
15993       splitseg->shver = 0;
15994       pa = sorg(*splitseg);
15995       pb = sdest(*splitseg);
15996       // Allcate two arrays for saving the subface rings of the two new
15997       //   segments a->p and p->b.
15998       apsegshs = new face[n];
15999       pbsegshs = new face[n];
16000     }
16001 
16002     // For each C_k(p), do the following:
16003     //   (1) Create new subfaces to fill C_k(p), insert them into B(p);
16004     //   (2) Connect new subfaces to each other;
16005     for (k = 0; k < n; k++) {
16006       subceillist = subceillists[k];
16007 
16008       // Check if 'hullsize' should be updated.
16009       oldsh = * (face *)(* subceillist)[0];
16010       stpivot(oldsh, neightet);
16011       if (neightet.tet != dummytet) {
16012         sesymself(oldsh);
16013         stpivot(oldsh, neightet);
16014       }
16015       if (neightet.tet == dummytet) {
16016         // The hull size changes.
16017         hullsize += (subceillist->len() - sublists[k]->len());
16018       }
16019 
16020       // (1) Create new subfaces to fill C_k(p), insert them into B(p).
16021       for (i = 0; i < subceillist->len(); i++) {
16022         oldsh = * (face *)(* subceillist)[i];
16023         makeshellface(subfaces, &newsh);
16024         setsorg(newsh, sorg(oldsh));
16025         setsdest(newsh, sdest(oldsh));
16026         setsapex(newsh, bp);
16027         if (b->quality && varconstraint) {
16028           setareabound(newsh, areabound(oldsh));
16029         }
16030         setshellmark(newsh, shellmark(oldsh));
16031         setshelltype(newsh, shelltype(oldsh));
16032         if (checkpbcs) {
16033           setshellpbcgroup(newsh, shellpbcgroup(oldsh));
16034         }
16035         // Replace oldsh by newsh at the edge.
16036         spivot(oldsh, casingout);
16037         sspivot(oldsh, checkseg);
16038         if (checkseg.sh != dummysh) {
16039           // A segment. Insert s into the face ring, ie, s_in -> s -> s_out.
16040           if (oldsh.sh != casingout.sh) {
16041             // s is not bonded to itself.
16042             spinsh = casingout;
16043             do {
16044               casingin = spinsh;
16045               spivotself(spinsh);
16046             } while (sapex(spinsh) != sapex(oldsh));
16047             assert(casingin.sh != oldsh.sh);
16048             // Bond s_in -> s -> s_out (and dissolve s_in -> s_old -> s_out).
16049             sbond1(casingin, newsh);
16050             sbond1(newsh, casingout);
16051           } else {
16052             // Bond newsh -> newsh.
16053             sbond(newsh, newsh);
16054           }
16055           // Bond the segment.
16056           ssbond(newsh, checkseg);
16057         } else {
16058           // Bond s <-> s_out (and dissolve s_out -> s_old).
16059           sbond(newsh, casingout);
16060         }
16061 
16062         // Insert newsh into B(p). Use the coonections of oldsh.
16063         stpivot(oldsh, neightet);
16064         if (neightet.tet == dummytet) {
16065           sesymself(oldsh);
16066           sesymself(newsh); // Keep the same orientation as oldsh.
16067           stpivot(oldsh, neightet);
16068         }
16069         assert(infected(neightet));
16070         // Set on the rotating edge.
16071         findedge(&neightet, sorg(oldsh), sdest(oldsh));
16072         // Choose the rotating direction (to the inside of B(p)).
16073         adjustedgering(neightet, CCW);
16074         rotface = neightet;
16075         // Rotate face. Stop at a non-infected tet t (not in B(p)) or a
16076         //   hull face f (on B(p)). Get the neighbor n of t or f.  n is
16077         //   a new tet that has just been created to fill B(p).
16078         do {
16079           fnextself(rotface);
16080           sym(rotface, neightet);
16081           if (neightet.tet == dummytet) {
16082             tspivot(rotface, checksh);
16083             assert(checksh.sh != dummysh);
16084             stpivot(checksh, newtet);
16085             break;
16086           } else if (!infected(neightet)) {
16087             sym(neightet, newtet);
16088             break;
16089           }
16090         } while (true);
16091         assert(newtet.tet != rotface.tet);
16092         // Set the rotating edge of n.
16093         findedge(&newtet, sorg(oldsh), sdest(oldsh));
16094         // Choose the rotating direction (to the inside of B(p)).
16095         adjustedgering(newtet, CCW);
16096         fnext(newtet, newface);
16097         assert(apex(newface) == bp);
16098         // newsh has already been oriented toward n.
16099         tsbond(newface, newsh);
16100         sym(newface, neightet); // 'neightet' maybe outside.
16101         sesymself(newsh);
16102         tsbond(neightet, newsh); // Bond them anyway.
16103 
16104         // Replace oldsh by newsh in list.
16105         * (face *)(* subceillist)[i] = newsh;
16106       }
16107 
16108       // (2) Connect new subfaces to each other.
16109       for (i = 0; i < subceillist->len(); i++) {
16110         // Get a face cdp.
16111         newsh = * (face *)(* subceillist)[i];
16112         // Get a new tet containing cdp.
16113         stpivot(newsh, newtet);
16114         if (newtet.tet == dummytet) {
16115           sesymself(newsh);
16116           stpivot(newsh, newtet);
16117         }
16118         for (j = 0; j < 2; j++) {
16119           if (j == 0) {
16120             senext(newsh, newedge); // edge dp.
16121           } else {
16122             senext2(newsh, newedge); // edge pc.
16123             sesymself(newedge); // edge cp.
16124           }
16125           if (splitseg != (face *) NULL) {
16126             // Don not operate on newedge if it is ap or pb.
16127             if (sorg(newedge) == pa) {
16128               apsegshs[k] = newedge;
16129               continue;
16130             } else if (sorg(newedge) == pb) {
16131               pbsegshs[k] = newedge;
16132               continue;
16133             }
16134           }
16135           // There should no segment inside the cavity. Check it.
16136           sspivot(newedge, checkseg);
16137           assert(checkseg.sh == dummysh);
16138           spivot(newedge, casingout);
16139           if (casingout.sh == dummysh) {
16140             rotface = newtet;
16141             findedge(&rotface, sorg(newedge), sdest(newedge));
16142             // Rotate newtet until meeting a new subface which contains
16143             //   newedge. It must exist since newedge is not a seg.
16144             adjustedgering(rotface, CCW);
16145             do {
16146               fnextself(rotface);
16147               tspivot(rotface, checksh);
16148               if (checksh.sh != dummysh) break;
16149             } while (true);
16150             findedge(&checksh, sorg(newedge), sdest(newedge));
16151             sbond(newedge, checksh);
16152           }
16153         }
16154       }
16155       // Only do once if p is on a facet.
16156       if (splitseg == (face *) NULL) break;
16157     } // for (k = 0; k < n; k++)
16158 
16159     if (splitseg != (face *) NULL) {
16160       // Update a->b to be a->p.
16161       apseg = *splitseg;
16162       setsdest(apseg, bp);
16163       // Create a new subsegment p->b.
16164       makeshellface(subsegs, &pbseg);
16165       setsorg(pbseg, bp);
16166       setsdest(pbseg, pb);
16167       // p->b gets the same mark and segment type as a->p.
16168       setshellmark(pbseg, shellmark(apseg));
16169       setshelltype(pbseg, shelltype(apseg));
16170       if (b->quality && varconstraint) {
16171         // Copy the area bound into the new subsegment.
16172         setareabound(pbseg, areabound(apseg));
16173       }
16174       senext(apseg, checkseg);
16175       // Get the old connection at b of a->b.
16176       spivot(checkseg, casingout);
16177       // Bond a->p and p->b together.
16178       senext2(pbseg, casingin);
16179       sbond(casingin, checkseg);
16180       if (casingout.sh != dummysh) {
16181         // There is a subsegment connect at b of p->b.
16182         casingout.shver = 0;
16183 #ifdef SELF_CHECK
16184         assert(sorg(casingout) == pb);
16185 #endif
16186         senext2self(casingout);
16187         senext(pbseg, casingin);
16188         sbond(casingin, casingout);
16189       }
16190 
16191       // Bond all new subfaces to a->p and p->b.
16192       for (i = 0; i < n; i++) {
16193         spinsh = apsegshs[i];
16194         findedge(&spinsh, pa, bp);
16195         ssbond(spinsh, apseg);
16196         spinsh = pbsegshs[i];
16197         findedge(&spinsh, bp, pb);
16198         ssbond(spinsh, pbseg);
16199       }
16200       // Bond all subfaces share at a->p together.
16201       for (i = 0; i < n; i++) {
16202         spinsh = apsegshs[i];
16203         if (i < (n - 1)) {
16204           casingout = apsegshs[i + 1];
16205         } else {
16206           casingout = apsegshs[0];
16207         }
16208         sbond1(spinsh, casingout);
16209       }
16210       // Bond all subfaces share at p->b together.
16211       for (i = 0; i < n; i++) {
16212         spinsh = pbsegshs[i];
16213         if (i < (n - 1)) {
16214           casingout = pbsegshs[i + 1];
16215         } else {
16216           casingout = pbsegshs[0];
16217         }
16218         sbond1(spinsh, casingout);
16219       }
16220       delete [] apsegshs;
16221       delete [] pbsegshs;
16222 
16223       // Check for newly encroached subsegments if the flag is set.
16224       if (chkencseg) {
16225         // Check if a->p and p->b are encroached by other vertices.
16226         checkseg4encroach(&apseg, NULL, NULL, true);
16227         checkseg4encroach(&pbseg, NULL, NULL, true);
16228         // Check if the adjacent segments are encroached by p.
16229         tallencsegs(bp, n, ceillists);
16230       }
16231     } // if (splitseg != (face *) NULL)
16232 
16233     // Delete subfaces of old CBC_i(p)s.
16234     for (k = 0; k < n; k++) {
16235       for (i = 0; i < sublists[k]->len(); i++) {
16236         oldsh = * (face *)(* (sublists[k]))[i];
16237         shellfacedealloc(subfaces, oldsh.sh);
16238       }
16239       // Clear the list so that the subs will not get unmarked later in
16240       //   routine releasebowatcavity() which only frees the memory.
16241       sublists[k]->clear();
16242       // Only do once if p is on a facet.
16243       if (splitseg == (face *) NULL) break;
16244     }
16245 
16246     // Check for newly encroached subfaces if the flag is set.
16247     if (chkencsub) {
16248       // Check if new subfaces of C_i(p) are encroached by other vertices.
16249       for (k = 0; k < n; k++) {
16250         subceillist = subceillists[k];
16251         for (i = 0; i < subceillist->len(); i++) {
16252           newsh = * (face *)(* subceillist)[i];
16253           checksub4encroach(&newsh, NULL, true);
16254         }
16255         // Only do once if p is on a facet.
16256         if (splitseg == (face *) NULL) break;
16257       }
16258       // Check if the adjacent subfaces are encroached by p.
16259       tallencsubs(bp, n, ceillists);
16260     }
16261   } // if (subceillists != (list **) NULL)
16262 
16263   // Delete tets of old BC_i(p)s.
16264   for (k = 0; k < n; k++) {
16265     for (i = 0; i < tetlists[k]->len(); i++) {
16266       oldtet = * (triface *)(* (tetlists[k]))[i];
16267       tetrahedrondealloc(oldtet.tet);
16268     }
16269     // Clear the list so that the tets will not get unmarked later in
16270     //   routine releasebowatcavity() which only frees the memory.
16271     tetlists[k]->clear();
16272   }
16273 
16274   // check for bad quality tets if the flags is set.
16275   if (chkbadtet) {
16276     for (k = 0; k < n; k++) {
16277       ceillist = ceillists[k];
16278       for (i = 0; i < ceillist->len(); i++) {
16279         newtet = * (triface *)(* ceillist)[i];
16280         checktet4badqual(&newtet, true);
16281       }
16282     }
16283   }
16284 
16285   if (flipque != (queue *) NULL) {
16286     // Newly created internal faces of BC(p) (excluding faces on C(p)s) are
16287     //   in 'flipque'.  Some of these faces may be locally non-Delaunay due,
16288     //   to the existence of non-constrained tets. check and fix them.
16289     repairflipcount += flip(flipque, NULL);
16290   }
16291 }
16292 
16293 //
16294 // End of mesh transformation routines
16295 //
16296 
16297 //
16298 // Begin Delaunay tetrahedralization routines
16299 //
16300 
16302 //                                                                           //
16303 // formstarpolyhedron()    Get the star ployhedron of a point 'pt'.          //
16304 //                                                                           //
16305 // The polyhedron P is formed by faces of tets having 'pt' as a vertex.  If  //
16306 // 'complete' is TRUE, P is the complete star of 'pt'. Otherwise, P is boun- //
16307 // ded by subfaces, i.e. P is only part of the star of 'pt'.                 //
16308 //                                                                           //
16309 // 'tetlist' T returns the tets, it has one of such tets on input. Moreover, //
16310 // if t is in T, then oppo(t) = p.  Topologically, T is the star of p;  and  //
16311 // the faces of T is the link of p. 'verlist' V returns the vertices of T.   //
16312 //                                                                           //
16314 
16315 void tetgenmesh::formstarpolyhedron(point pt, list* tetlist, list* verlist,
16316   bool complete)
16317 {
16318   triface starttet, neightet;
16319   face checksh;
16320   point ver[3];
16321   int idx, i, j;
16322 
16323   // Get a tet t containing p.
16324   starttet = * (triface *)(* tetlist)[0];
16325   // Let oppo(t) = p.
16326   for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
16327     if (oppo(starttet) == pt) break;
16328   }
16329   assert(starttet.loc < 4);
16330   // Add t into T.
16331   * (triface *)(* tetlist)[0] = starttet;
16332   infect(starttet);
16333   if (verlist != (list *) NULL) {
16334     // Add three verts of t into V.
16335     ver[0] = org(starttet);
16336     ver[1] = dest(starttet);
16337     ver[2] = apex(starttet);
16338     for (i = 0; i < 3; i++) {
16339       // Mark the vert by inversing the index of the vert.
16340       idx = pointmark(ver[i]);
16341       setpointmark(ver[i], -idx - 1); // -1 to distinguish the zero.
16342       verlist->append(&(ver[i]));
16343     }
16344   }
16345 
16346   // Find other tets by a broadth-first search.
16347   for (i = 0; i < tetlist->len(); i++) {
16348     starttet = * (triface *)(* tetlist)[i];
16349     starttet.ver = 0;
16350     for (j = 0; j < 3; j++) {
16351       fnext(starttet, neightet);
16352       tspivot(neightet, checksh);
16353       // Should we cross a subface.
16354       if ((checksh.sh == dummysh) || complete) {
16355         // Get the neighbor n.
16356         symself(neightet);
16357         if ((neightet.tet != dummytet) && !infected(neightet)) {
16358           // Let oppo(n) = p.
16359           for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
16360             if (oppo(neightet) == pt) break;
16361           }
16362           assert(neightet.loc < 4);
16363           // Add n into T.
16364           infect(neightet);
16365           tetlist->append(&neightet);
16366           if (verlist != (list *) NULL) {
16367             // Add the apex vertex in n into V.
16368             ver[0] = org(starttet);
16369             ver[1] = dest(starttet);
16370             findedge(&neightet, ver[0], ver[1]);
16371             ver[2] = apex(neightet);
16372             idx = pointmark(ver[2]);
16373             if (idx >= 0) {
16374               setpointmark(ver[2], -idx - 1);
16375               verlist->append(&(ver[2]));
16376             }
16377           }
16378         }
16379       }
16380       enextself(starttet);
16381     }
16382   }
16383 
16384   // Uninfect tets.
16385   for (i = 0; i < tetlist->len(); i++) {
16386     starttet = * (triface *)(* tetlist)[i];
16387     uninfect(starttet);
16388   }
16389   if (verlist != (list *) NULL) {
16390     // Uninfect vertices.
16391     for (i = 0; i < verlist->len(); i++) {
16392       ver[0] = * (point *)(* verlist)[i];
16393       idx = pointmark(ver[0]);
16394       setpointmark(ver[0], -(idx + 1));
16395     }
16396   }
16397 }
16398 
16400 //                                                                           //
16401 // unifypoint()    Unify two distinct points if they're very close.          //
16402 //                                                                           //
16403 // This function is used for dealing with inputs from CAD tools.  Two points //
16404 // p and q are unified if: dist(p, q) / longest < eps.  Where dist() is the  //
16405 // Euclidean distance between p and q, longest is the maximum edge size of   //
16406 // the input point set, eps is the tolerrence specified by user, default is  //
16407 // 1e-6, it can be adjusted by '-T' switch.                                  //
16408 //                                                                           //
16410 
16411 bool tetgenmesh::unifypoint(point testpt, triface *starttet, enum locateresult
16412   loc, REAL eps)
16413 {
16414   triface symtet, spintet;
16415   point checkpt, tapex;
16416   REAL tol;
16417   bool merged;
16418   int hitbdry;
16419   int i;
16420 
16421   merged = false;
16422   tol = longest * eps;
16423   if ((loc == OUTSIDE) || (loc == INTETRAHEDRON) || (loc == ONFACE)) {
16424     // Check p is close to the four corners of the tet.
16425     for (i = 0; i < 4; i++) {
16426       checkpt = (point) starttet->tet[4 + i];
16427       if (distance(testpt, checkpt) < tol) {
16428         merged = true; // Found a merge point p'.
16429         break;
16430       }
16431     }
16432     if (!merged && (loc == ONFACE)) {
16433       // Check the opposite point of the neighbor tet if it exists.
16434       sym(*starttet, symtet);
16435       if (symtet.tet != dummytet) {
16436         checkpt = oppo(symtet);
16437         if (distance(testpt, checkpt) < tol) {
16438           merged = true; // Found a merge point p'.
16439         }
16440       }
16441     }
16442   } else if (loc == ONEDGE) {
16443     // Check two endpoints of the edge.
16444     checkpt = org(*starttet);
16445     if (distance(testpt, checkpt) < tol) {
16446       merged = true; // Found a merge point p'.
16447     }
16448     if (!merged) {
16449       checkpt = dest(*starttet);
16450       if (distance(testpt, checkpt) < tol) {
16451         merged = true; // Found a merge point p'.
16452       }
16453     }
16454     if (!merged) {
16455       // Check apexes of the faces having the edge.
16456       spintet = *starttet;
16457       tapex = apex(*starttet);
16458       hitbdry = 0;
16459       do {
16460         checkpt = apex(spintet);
16461         if (distance(testpt, checkpt) < tol) {
16462           merged = true; // Found a merge point p'.
16463           break;
16464         }
16465         if (!fnextself(spintet)) {
16466           hitbdry++;
16467           if (hitbdry < 2) {
16468             esym(*starttet, spintet);
16469             if (!fnextself(spintet)) {
16470               hitbdry++;
16471             }
16472           }
16473         }
16474       } while ((apex(spintet) != tapex) && (hitbdry < 2));
16475     }
16476   }
16477   if (merged) {
16478     if (b->object != tetgenbehavior::STL) {
16479       if (!b->quiet) {
16480         printf("Warning:  Point %d is unified to point %d.\n",
16481                pointmark(testpt), pointmark(checkpt));
16482       }
16483       // Count the number of duplicated points.
16484       dupverts++;
16485     }
16486     // Remember it is a duplicated point.
16487     setpointtype(testpt, DUPLICATEDVERTEX);
16488     // Set a pointer to the point it duplicates.
16489     setpoint2ppt(testpt, checkpt);
16490   }
16491   return merged;
16492 }
16493 
16495 //                                                                           //
16496 // incrflipdelaunay()   Construct a delaunay tetrahedrization from a set of  //
16497 //                      3D points by the incremental flip algorithm.         //
16498 //                                                                           //
16499 // The incremental flip algorithm (by Edelsbrunner and Shah) can be describ- //
16500 // ed as follows:                                                            //
16501 //                                                                           //
16502 //   S be a set of points in 3D, Let 4 <= i <= n and assume that the         //
16503 //   Delaunay tetrahedralization of the first i-1 points in S is already     //
16504 //   constructed; call it D(i-1). Add the i-th point p_i (belong to S) to    //
16505 //   D(i-1), and restore Delaunayhood by flipping; this result in D(i).      //
16506 //   Repeat this procedure until i = n.                                      //
16507 //                                                                           //
16508 // This strategy always leads to the Delaunay triangulation of a point set.  //
16509 // The return value is the number of convex hull faces of D.                 //
16510 //                                                                           //
16512 
16513 void tetgenmesh::incrflipdelaunay(triface* oldtet, point* insertarray,
16514   long arraysize, bool jump, bool merge, REAL eps, queue* flipque)
16515 {
16516   triface newtet, searchtet;
16517   point swappt, lastpt;
16518   enum locateresult loc;
16519   REAL det, n[3];
16520   REAL attrib, volume;
16521   int i, j;
16522 #ifdef SELF_CHECK
16523   clock_t loc_start, loc_end;
16524 #endif
16525 
16526   det = 0.0;
16527   if (b->verbose > 0) {
16528     printf("  Creating initial tetrahedralization.\n");
16529   }
16530 
16531   // The initial tetrahedralization T only has one tet formed by 4 affinely
16532   //   linear independent vertices of the point set V = 'insertarray'. The
16533   //   first point a = insertarray[0].
16534 
16535   // Get the second point b, that is not identical or very close to a.
16536   for (i = 1; i < arraysize; i++) {
16537     det = distance(insertarray[0], insertarray[i]);
16538     if (det > (longest * eps)) break;
16539   }
16540   if (i == arraysize) {
16541     printf("\nAll points seem to be identical.\n");
16542     return;
16543   } else {
16544     // Swap to move b from index i to index 1.
16545     swappt = insertarray[i];
16546     insertarray[i] = insertarray[1];
16547     insertarray[1] = swappt;
16548   }
16549   // Get the third point c, that is not collinear with a and b.
16550   for (i++; i < arraysize; i++) {
16551     if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
16552       break;
16553   }
16554   if (i == arraysize) {
16555     printf("\nAll points seem to be collinear.\n");
16556     return;
16557   } else {
16558     // Swap to move c from index i to index 2.
16559     swappt = insertarray[i];
16560     insertarray[i] = insertarray[2];
16561     insertarray[2] = swappt;
16562   }
16563   // Get the fourth point d, that is not coplanar with a, b, and c.
16564   for (i++; i < arraysize; i++) {
16565     det = orient3d(insertarray[0], insertarray[1], insertarray[2],
16566                    insertarray[i]);
16567     if (det == 0.0) continue;
16568     if (!iscoplanar(insertarray[0], insertarray[1], insertarray[2],
16569                     insertarray[i], det, eps)) break;
16570   }
16571   if (i == arraysize) {
16572     // It's a 2D problem.
16573     in->mesh_dim = 2;
16574     // All points are coplanar.
16575     if (b->plc) {
16576       // Create an abovepoint. Maybe a surface triangulation can be formed.
16577       facenormal(insertarray[0], insertarray[1], insertarray[2], n, &det);
16578       if (det != 0.0) for (j = 0; j < 3; j++) n[j] /= det;
16579       // Take the average edge length of the bounding box.
16580       det = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
16581       // Temporarily create a point. It will be removed by jettison();
16582       makepoint(&lastpt);
16583       for (j = 0; j < 3; j++) lastpt[j] = insertarray[0][j] + det * n[j];
16584       abovepoint = lastpt;
16585       det = orient3d(insertarray[0], insertarray[1], insertarray[2], lastpt);
16586       // The index of the next inserting point is 3.
16587       i = 3;
16588     } else {
16589       printf("\nAll points seem to be coplanar.\n");
16590       return;
16591     }
16592   } else {
16593     // Swap to move d from index i to index 3.
16594     swappt = insertarray[i];
16595     insertarray[i] = insertarray[3];
16596     insertarray[3] = swappt;
16597     lastpt = insertarray[3];
16598     // The index of the next inserting point is 4.
16599     i = 4;
16600   }
16601 
16602   // Create the initial tet.
16603   maketetrahedron(&newtet);
16604   if (det > 0.0) {
16605     // For keeping the positive orientation.
16606     swappt = insertarray[0];
16607     insertarray[0] = insertarray[1];
16608     insertarray[1] = swappt;
16609   }
16610   if (b->verbose > 2) {
16611     printf("  Create the first tet (%d, %d, %d, %d).\n",
16612            pointmark(insertarray[0]), pointmark(insertarray[1]),
16613            pointmark(insertarray[2]), pointmark(lastpt));
16614   }
16615   setorg(newtet, insertarray[0]);
16616   setdest(newtet, insertarray[1]);
16617   setapex(newtet, insertarray[2]);
16618   setoppo(newtet, lastpt);
16619   if (oldtet != (triface *) NULL) {
16620     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
16621       attrib = elemattribute(oldtet->tet, j);
16622       setelemattribute(newtet.tet, j, attrib);
16623     }
16624     if (b->varvolume) {
16625       volume = volumebound(oldtet->tet);
16626       setvolumebound(newtet.tet, volume);
16627     }
16628   }
16629   // Set vertex type be FREEVOLVERTEX if it has no type yet.
16630   if (pointtype(insertarray[0]) == UNUSEDVERTEX) {
16631     setpointtype(insertarray[0], FREEVOLVERTEX);
16632   }
16633   if (pointtype(insertarray[1]) == UNUSEDVERTEX) {
16634     setpointtype(insertarray[1], FREEVOLVERTEX);
16635   }
16636   if (pointtype(insertarray[2]) == UNUSEDVERTEX) {
16637     setpointtype(insertarray[2], FREEVOLVERTEX);
16638   }
16639   if (pointtype(lastpt) == UNUSEDVERTEX) {
16640     setpointtype(lastpt, FREEVOLVERTEX);
16641   }
16642   // Bond to 'dummytet' for point location.
16643   dummytet[0] = encode(newtet);
16644   if (b->verbose > 3) {
16645     printf("    Creating tetra ");
16646     printtet(&newtet);
16647   }
16648   // At init, all faces of this tet are hull faces.
16649   hullsize = 4;
16650 
16651   if (b->verbose > 0) {
16652     printf("  Incrementally inserting points.\n");
16653   }
16654 
16655   flip23s = flip32s = flip22s = flip44s = 0;
16656   searchtet.tet = (tetrahedron *) NULL;
16657 
16658   // Insert the rest of points, one by one.
16659   for (; i < arraysize; i++) {
16660     // Locate p_i in T.
16661 #ifdef SELF_CHECK
16662     loc_start = clock();
16663 #endif
16664     if (jump) {
16665       loc = locate(insertarray[i], &searchtet);
16666     } else {
16667       loc = preciselocate(insertarray[i], &searchtet, tetrahedrons->items);
16668     }
16669 #ifdef SELF_CHECK
16670     loc_end = clock();
16671     tloctime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16672 #endif
16673     // Keep current search state for next searching.
16674     recenttet = searchtet;
16675     if (loc == ONVERTEX) {
16676       if (b->object != tetgenbehavior::STL) {
16677         if (!b->quiet) {
16678           printf("Warning:  Point %d is identical with point %d.\n",
16679                  pointmark(insertarray[i]), pointmark(org(searchtet)));
16680         }
16681       }
16682       // Count the number of duplicated points.
16683       dupverts++;
16684       // Remember it is a duplicated point.
16685       setpointtype(insertarray[i], DUPLICATEDVERTEX);
16686       if (b->plc || b->refine) {
16687         // Set a pointer to the point it duplicates.
16688         setpoint2ppt(insertarray[i], org(searchtet));
16689       }
16690       continue; // p_i is not inserted.
16691     }
16692     if (merge) {
16693       // Unify p_i if it is too close to a point of T.
16694       if (unifypoint(insertarray[i], &searchtet, loc, eps)) {
16695         continue; // p_i is not inserted.
16696       }
16697     }
16698     // Insert p_i in T.
16699     if (loc != OUTSIDE) {
16700       if (b->verbose > 1) {
16701         printf("  Insert point %d in tetrahedralization.\n",
16702                pointmark(insertarray[i]));
16703       }
16704       if (loc == INTETRAHEDRON) {
16705         splittetrahedron(insertarray[i], &searchtet, flipque);
16706       } else if (loc == ONFACE) {
16707         splittetface(insertarray[i], &searchtet, flipque);
16708       } else if (loc == ONEDGE) {
16709         splittetedge(insertarray[i], &searchtet, flipque);
16710       }
16711     } else {
16712       if (b->verbose > 1) {
16713         printf("  Insert point %d on convex hull.\n",
16714                pointmark(insertarray[i]));
16715       }
16716       inserthullsite(insertarray[i], &searchtet, flipque);
16717     }
16718     if (pointtype(insertarray[i]) == UNUSEDVERTEX) {
16719       // p_i becomes a (volume) vertex of T.
16720       setpointtype(insertarray[i], FREEVOLVERTEX);
16721     }
16722 #ifdef SELF_CHECK
16723     loc_start = clock();
16724 #endif
16725     if (!b->noflip) {
16726       // Recover Delaunayness of T by flipping.
16727       flip(flipque, NULL);
16728     } else {
16729       lawson(NULL, flipque);
16730       // T remains regular.
16731       // flipque->clear();
16732     }
16733 #ifdef SELF_CHECK
16734     loc_end = clock();
16735     tfliptime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16736 #endif
16737   }
16738 
16739   if (b->verbose > 0) {
16740     printf("  %ld Flips (T23 %ld, T32 %ld, T22 %ld, T44 %ld)\n",
16741       flip23s+flip32s+flip22s+flip44s, flip23s, flip32s, flip22s, flip44s);
16742   }
16743 }
16744 
16746 //                                                                           //
16747 // delaunizevertices()    Form a Delaunay tetrahedralization.                //
16748 //                                                                           //
16749 // Given a point set V (saved in 'points').  The Delaunay tetrahedralization //
16750 // D of V is created by incrementally inserting vertices. Returns the number //
16751 // of triangular faces bounding the convex hull of D.                        //
16752 //                                                                           //
16754 
16755 long tetgenmesh::delaunizevertices()
16756 {
16757   queue *flipque;
16758   point *insertarray;
16759   long arraysize;
16760   int i, j;
16761 
16762   if (!b->quiet) {
16763     if (!b->noflip) {
16764       printf("Constructing Delaunay tetrahedralization.\n");
16765     } else {
16766       printf("Constructing regular tetrahedralization.\n");
16767     }
16768   }
16769 
16770   flipque = new queue(sizeof(badface));
16771   // Prepare the array of points for inserting.
16772   arraysize = points->items;
16773   insertarray = new point[arraysize];
16774   points->traversalinit();
16775 
16776   // Randomize the point order.
16777   // randomseed = b->srandseed;
16778   for (i = 0; i < arraysize; i++) {
16779     j = (int) randomnation(i + 1); // 0 <= j <= i;
16780     insertarray[i] = insertarray[j];
16781     insertarray[j] = pointtraverse();
16782   }
16783 
16784   // Use lawson flip.
16785   b->noflip = 1;
16786 
16787   // Form the DT by incremental flip Delaunay algorithm.
16788   incrflipdelaunay(NULL, insertarray, arraysize, true, b->plc, b->epsilon,
16789                    flipque);
16790 
16791   b->noflip = 0;
16792 
16793   delete [] insertarray;
16794   delete flipque;
16795   return hullsize;
16796 }
16797 
16798 //
16799 // End Delaunay tetrahedralization routines
16800 //
16801 
16802 //
16803 // Begin of surface triangulation routines
16804 //
16805 
16807 //                                                                           //
16808 // formstarpolygon()    Form the star polygon of a point in facet.           //
16809 //                                                                           //
16810 // The polygon P is formed by all coplanar subfaces having 'pt' as a vertex. //
16811 // P is bounded by segments, e.g, if no segments, P is the full star of pt.  //
16812 //                                                                           //
16813 // 'trilist' T returns the subfaces, it has one of such subfaces on input.   //
16814 // In addition, if f is in T, then sapex(f) = p. 'vertlist' V are verts of P.//
16815 // Topologically, T is the star of p; V and the edges of T are the link of p.//
16816 //                                                                           //
16818 
16819 void tetgenmesh::formstarpolygon(point pt, list* trilist, list* vertlist)
16820 {
16821   face steinsh, lnextsh, rnextsh;
16822   face checkseg;
16823   point pa, pb, pc, pd;
16824   int i;
16825 
16826   // Get a subface f containing p.
16827   steinsh = * (face *)(* trilist)[0];
16828   steinsh.shver = 0; // CCW
16829   // Let sapex(f) be p.
16830   for (i = 0; i < 3; i++) {
16831     if (sapex(steinsh) == pt) break;
16832     senextself(steinsh);
16833   }
16834   assert(i < 3);
16835   // Add the edge f into list.
16836   * (face *)(* trilist)[0] = steinsh;
16837   pa = sorg(steinsh);
16838   pb = sdest(steinsh);
16839   if (vertlist != (list *) NULL) {
16840     // Add two verts a, b into V,
16841     vertlist->append(&pa);
16842     vertlist->append(&pb);
16843   }
16844 
16845   // Rotate edge pa to the left (CW) until meet pb or a segment.
16846   lnextsh = steinsh;
16847   pc = pa;
16848   do {
16849     senext2self(lnextsh);
16850     assert(sorg(lnextsh) == pt);
16851     sspivot(lnextsh, checkseg);
16852     if (checkseg.sh != dummysh) break; // Do not cross a segment.
16853     // Get neighbor subface n (must exist).
16854     spivotself(lnextsh);
16855     if (lnextsh.sh == dummysh) break; // It's a hull edge.
16856     // Go to the edge ca opposite to p.
16857     if (sdest(lnextsh) != pt) sesymself(lnextsh);
16858     assert(sdest(lnextsh) == pt);
16859     senext2self(lnextsh);
16860     // Add n (at edge ca) to T.
16861     trilist->append(&lnextsh);
16862     // Add edge ca to E.
16863     pc = sorg(lnextsh);
16864     if (pc == pb) break; // Rotate back.
16865     if (vertlist != (list *) NULL) {
16866       // Add vert c into V.
16867       vertlist->append(&pc);
16868     }
16869   } while (true);
16870 
16871   if (pc != pb) {
16872     // Rotate edge bp to the right (CCW) until meet a segment.
16873     rnextsh = steinsh;
16874     do {
16875       senextself(rnextsh);
16876       assert(sdest(rnextsh) == pt);
16877       sspivot(rnextsh, checkseg);
16878       if (checkseg.sh != dummysh) break; // Do not cross a segment.
16879       // Get neighbor subface n (must exist).
16880       spivotself(rnextsh);
16881       if (rnextsh.sh == dummysh) break; // It's a hull edge.
16882       // Go to the edge bd opposite to p.
16883       if (sorg(rnextsh) != pt) sesymself(rnextsh);
16884       assert(sorg(rnextsh) == pt);
16885       senextself(rnextsh);
16886       // Add n (at edge bd) to T.
16887       trilist->append(&rnextsh);
16888       // Add edge bd to E.
16889       pd = sdest(rnextsh);
16890       if (pd == pa) break; // Rotate back.
16891       if (vertlist != (list *) NULL) {
16892         // Add vert d into V.
16893         vertlist->append(&pd);
16894       }
16895     } while (true);
16896   }
16897 }
16898 
16900 //                                                                           //
16901 // About the 'abovepoint'                                                    //
16902 //                                                                           //
16903 // The 'abovepoint' of a facet is a point which is exactly non-coplanar with //
16904 // the plane containing that facet.  With such an point, the 3D predicates:  //
16905 // orient3d(), and insphere() can be used to substitute the corresponding 2D //
16906 // siblings, e.g. orient2d(), and incircle().  Its location is not critical, //
16907 // but floating-point accuracy is improved if it is nicely placed over the   //
16908 // facet, not too close or too far away.                                     //
16909 //                                                                           //
16910 // We take the convention that the abovepoint of a facet always lies above   //
16911 // the facet. By this convention, given three points a, b, and c in a facet, //
16912 // we say c has the counterclockwise order with ab is corresponding to say   //
16913 // that c is below the plane abp, where p is the lift point.                 //
16914 //                                                                           //
16916 
16918 //                                                                           //
16919 // getfacetabovepoint()    Get a point above a plane pass through a facet.   //
16920 //                                                                           //
16921 // The calculcated point is saved in 'facetabovepointarray'. The 'abovepoint'//
16922 // is set on return.                                                         //
16923 //                                                                           //
16925 
16926 void tetgenmesh::getfacetabovepoint(face* facetsh)
16927 {
16928   list *verlist, *trilist, *tetlist;
16929   triface adjtet;
16930   face symsh;
16931   point p1, p2, p3, pa;
16932   enum locateresult loc;
16933   REAL smallcos, cosa;
16934   REAL largevol, volume;
16935   REAL v1[3], v2[3], len;
16936   int smallidx, largeidx;
16937   int shmark;
16938   int i, j;
16939 
16940   abovecount++;
16941   // Initialize working lists.
16942   verlist = new list(sizeof(point *), NULL);
16943   trilist = new list(sizeof(face), NULL);
16944   tetlist = new list(sizeof(triface), NULL);
16945 
16946   // Get three pivotal points p1, p2, and p3 in the facet as a base triangle
16947   //   which is non-trivil and has good base angle (close to 90 degree).
16948 
16949   // p1 is chosen as the one which has the smallest index in pa, pb, pc.
16950   p1 = sorg(*facetsh);
16951   pa = sdest(*facetsh);
16952   if (pointmark(pa) < pointmark(p1)) p1 = pa;
16953   pa = sapex(*facetsh);
16954   if (pointmark(pa) < pointmark(p1)) p1 = pa;
16955   // Form the star polygon of p1.
16956   trilist->append(facetsh);
16957   formstarpolygon(p1, trilist, verlist);
16958 
16959   // Get the second pivotal point p2.
16960   p2 = * (point *)(* verlist)[0];
16961   // Get vector v1 = p1->p2.
16962   for (i = 0; i < 3; i++) v1[i] = p2[i] - p1[i];
16963   len = sqrt(dot(v1, v1));
16964   assert(len > 0.0);  // p2 != p1.
16965   for (i = 0; i < 3; i++) v1[i] /= len;
16966 
16967   // Get the third pivotal point p3. p3 is chosen as the one in 'verlist'
16968   //   which forms an angle with v1 closer to 90 degree than others do.
16969   smallcos = 1.0; // The cosine value of 0 degree.
16970   smallidx = 1;   // Default value.
16971   for (i = 1; i < verlist->len(); i++) {
16972     p3 = * (point *)(* verlist)[i];
16973     for (j = 0; j < 3; j++) v2[j] = p3[j] - p1[j];
16974     len = sqrt(dot(v2, v2));
16975     if (len > 0.0) { // v2 is not too small.
16976       cosa = fabs(dot(v1, v2)) / len;
16977       if (cosa < smallcos) {
16978         smallidx = i;
16979         smallcos = cosa;
16980       }
16981     }
16982   }
16983   assert(smallcos < 1.0); // p1->p3 != p1->p2.
16984   p3 = * (point *)(* verlist)[smallidx];
16985   verlist->clear();
16986 
16987   if (tetrahedrons->items > 0l) {
16988     // Get a tet having p1 as a vertex.
16989     stpivot(*facetsh, adjtet);
16990     if (adjtet.tet == dummytet) {
16991       sesym(*facetsh, symsh);
16992       stpivot(symsh, adjtet);
16993     }
16994     if (adjtet.tet == dummytet) {
16995       decode(point2tet(p1), adjtet);
16996       if (isdead(&adjtet)) {
16997         adjtet.tet = dummytet;
16998       } else {
16999         if (!findorg(&adjtet, p1)) {
17000           adjtet.tet = dummytet;
17001         }
17002       }
17003     }
17004     if (adjtet.tet == dummytet) {
17005       loc = locate(p1, &adjtet);
17006       if (loc == ONVERTEX) {
17007         setpoint2tet(p1, encode(adjtet));
17008       } else {
17009         adjtet.tet = dummytet;
17010       }
17011     }
17012     if (adjtet.tet != dummytet) {
17013       // Get the star polyhedron of p1.
17014       tetlist->append(&adjtet);
17015       formstarpolyhedron(p1, tetlist, verlist, false);
17016     }
17017   }
17018 
17019   // Get the abovepoint in 'verlist'. It is the one form the largest valid
17020   //   volumw with the base triangle over other points in 'verlist.
17021   largevol = 0.0;
17022   largeidx = 0;
17023   for (i = 0; i < verlist->len(); i++) {
17024     pa = * (point *)(* verlist)[i];
17025     volume = orient3d(p1, p2, p3, pa);
17026     if (!iscoplanar(p1, p2, p3, pa, volume, b->epsilon * 1e+2)) {
17027       if (fabs(volume) > largevol) {
17028         largevol = fabs(volume);
17029         largeidx = i;
17030       }
17031     }
17032   }
17033 
17034   // Do we have the abovepoint?
17035   if (largevol > 0.0) {
17036     abovepoint = * (point *)(* verlist)[largeidx];
17037     if (b->verbose > 1) {
17038       printf("    Chosen abovepoint %d for facet %d.\n", pointmark(abovepoint),
17039              shellmark(*facetsh));
17040     }
17041   } else {
17042     // Calculate an abovepoint for this facet.
17043     facenormal(p1, p2, p3, v1, &len);
17044     if (len != 0.0) for (i = 0; i < 3; i++) v1[i] /= len;
17045     // Take the average edge length of the bounding box.
17046     len = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
17047     // Temporarily create a point. It will be removed by jettison();
17048     makepoint(&abovepoint);
17049     setpointtype(abovepoint, UNUSEDVERTEX);
17050     unuverts++;
17051     for (i = 0; i < 3; i++) abovepoint[i] = p1[i] + len * v1[i];
17052     if (b->verbose > 1) {
17053       printf("    Calculated abovepoint %d for facet %d.\n",
17054              pointmark(abovepoint), shellmark(*facetsh));
17055     }
17056   }
17057   // Save the abovepoint in 'facetabovepointarray'.
17058   shmark = shellmark(*facetsh);
17059   facetabovepointarray[shmark] = abovepoint;
17060 
17061   delete trilist;
17062   delete tetlist;
17063   delete verlist;
17064 }
17065 
17067 //                                                                           //
17068 // collectcavsubs()    Collect non-locally Delaunay subfaces wrt a point.    //
17069 //                                                                           //
17070 // 'cavsublist' returns the list of subfaces. On input, it conatins at least //
17071 // one subface.                                                              //
17072 //                                                                           //
17074 
17075 void tetgenmesh::collectcavsubs(point newpoint, list* cavsublist)
17076 {
17077   face startsub, neighsub;
17078   face checkseg;
17079   point pa, pb, pc;
17080   REAL sign, ori;
17081   int i, j;
17082 
17083   // First infect subfaces in 'cavsublist'.
17084   for (i = 0; i < cavsublist->len(); i++) {
17085     startsub = * (face *)(* cavsublist)[i];
17086     sinfect(startsub);
17087   }
17088   // Find the other subfaces by a broadth-first searching.
17089   for (i = 0; i < cavsublist->len(); i++) {
17090     startsub = * (face *)(* cavsublist)[i];
17091     for (j = 0; j < 3; j++) {
17092       sspivot(startsub, checkseg);
17093       // Is there a segment?
17094       if (checkseg.sh == dummysh) {
17095         // No segment. Get the neighbor.
17096         spivot(startsub, neighsub);
17097         if (!sinfected(neighsub)) {
17098           pa = sorg(neighsub);
17099           pb = sdest(neighsub);
17100           pc = sapex(neighsub);
17101           sign = insphere(pa, pb, pc, abovepoint, newpoint);
17102           ori = orient3d(pa, pb, pc, abovepoint);
17103           if (sign != 0.0) {
17104             // Correct the sign.
17105             sign = ori > 0.0 ? sign : -sign;
17106           }
17107           if (sign > 0.0) {
17108             // neighsub is encroached by newpoint.
17109             sinfect(neighsub);
17110             cavsublist->append(&neighsub);
17111           }
17112         }
17113       }
17114       senextself(startsub);
17115     }
17116   }
17117   // Having found all subfaces, uninfect them before return.
17118   for (i = 0; i < cavsublist->len(); i++) {
17119     startsub = * (face *)(* cavsublist)[i];
17120     suninfect(startsub);
17121   }
17122 }
17123 
17125 //                                                                           //
17126 // collectvisiblesubs()    Collect convex hull edges which are visible from  //
17127 //                         the inserting point. Construct new subfaces from  //
17128 //                         these edges and the point.                        //
17129 //                                                                           //
17130 // Let T be the current Delaunay triangulation (of vertices of a facet F).   //
17131 // 'shmark', the index of F in 'in->facetlist' (starts from 1);  'inspoint'  //
17132 // lies outside of T; 'horiz' is a hull edge of T which is visible by it.    //
17133 //                                                                           //
17135 
17136 void tetgenmesh::collectvisiblesubs(int shmark, point inspoint, face* horiz,
17137   queue* flipqueue)
17138 {
17139   face newsh, hullsh;
17140   face rightsh, leftsh, spinedge;
17141   point horg, hdest;
17142   bool aboveflag;
17143   REAL ori, sign;
17144 
17145   // Get the sign of abovepoint (so we can assume it is above the plane).
17146   adjustedgering(*horiz, CCW);
17147   horg = sorg(*horiz);
17148   hdest = sdest(*horiz);
17149   ori = orient3d(horg, hdest, sapex(*horiz), abovepoint);
17150   sign = ori > 0.0 ? -1 : 1;
17151 
17152   // Create a new subface above 'horiz'.
17153   makeshellface(subfaces, &newsh);
17154   setsorg(newsh, hdest);
17155   setsdest(newsh, horg);
17156   setsapex(newsh, inspoint);
17157   setshellmark(newsh, shmark);
17158   if (b->quality && varconstraint) {
17159     setareabound(newsh, areabound(*horiz));
17160   }
17161   if (checkpbcs) {
17162     setshellpbcgroup(newsh, shellpbcgroup(*horiz));
17163   }
17164   // Make the connection.
17165   sbond(newsh, *horiz);
17166   // 'horiz' becomes interior edge.
17167   enqueueflipedge(*horiz, flipqueue);
17168 
17169   // Finish the hull edges at the right side of the newsh.
17170   hullsh = *horiz;
17171   while (1) {
17172     senext(newsh, rightsh);
17173     // Get the right hull edge of 'horiz' by spinning inside edges around
17174     //   'horg' until reaching the 'dummysh'.
17175     spinedge = hullsh;
17176     do {
17177       hullsh = spinedge;
17178       senext2self(hullsh);
17179       spivot(hullsh, spinedge);
17180       if (spinedge.sh == dummysh) break;
17181       if (sorg(spinedge) != horg) sesymself(spinedge);
17182       assert(sorg(spinedge) == horg);
17183     } while (true);
17184     horg = sorg(hullsh);
17185     // Test whether 'inspoint' is visible by 'hullsh'.
17186     ori = orient3d(horg, sdest(hullsh), abovepoint, inspoint);
17187     ori *= sign;
17188     aboveflag = ori < 0.0;
17189     if (aboveflag) {
17190       // It's visible.
17191       makeshellface(subfaces, &newsh);
17192       setsorg(newsh, sdest(hullsh));
17193       setsdest(newsh, horg);
17194       setsapex(newsh, inspoint);
17195       setshellmark(newsh, shmark);
17196       if (b->quality && varconstraint) {
17197         setareabound(newsh, areabound(hullsh));
17198       }
17199       if (checkpbcs) {
17200         setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17201       }
17202       // Make the connection.
17203       sbond(newsh, hullsh);
17204       senext2(newsh, leftsh);
17205       sbond(leftsh, rightsh);
17206       // 'hullsh' becomes interior edge.
17207       enqueueflipedge(hullsh, flipqueue);
17208     } else {
17209       // 'rightsh' is a new hull edge.
17210       dummysh[0] = sencode(rightsh);
17211       break;
17212     }
17213   }
17214 
17215   // Finish the hull edges at the left side of the newsh.
17216   hullsh = *horiz;
17217   spivot(*horiz, newsh);
17218   while (1) {
17219     senext2(newsh, leftsh);
17220     // Get the left hull edge of 'horiz' by spinning edges around 'hdest'.
17221     spinedge = hullsh;
17222     do {
17223       hullsh = spinedge;
17224       senextself(hullsh);
17225       spivot(hullsh, spinedge);
17226       if (spinedge.sh == dummysh) break;
17227       if (sdest(spinedge) != hdest) sesymself(spinedge);
17228       assert(sdest(spinedge) == hdest);
17229     } while (true);
17230     // Update 'hdest'.
17231     hdest = sdest(hullsh);
17232     // Test whether 'inspoint' is visible from 'hullsh'.
17233     ori = orient3d(sorg(hullsh), hdest, abovepoint, inspoint);
17234     ori *= sign;
17235     aboveflag = ori < 0.0;
17236     if (aboveflag) {
17237       // It's a visible hull edge.
17238       makeshellface(subfaces, &newsh);
17239       setsorg(newsh, hdest);
17240       setsdest(newsh, sorg(hullsh));
17241       setsapex(newsh, inspoint);
17242       setshellmark(newsh, shmark);
17243       if (b->quality && varconstraint) {
17244         setareabound(newsh, areabound(hullsh));
17245       }
17246       if (checkpbcs) {
17247         setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17248       }
17249       // Make the connection.
17250       sbond(newsh, hullsh);
17251       senext(newsh, rightsh);
17252       sbond(rightsh, leftsh);
17253       // 'horiz' becomes interior edge.
17254       enqueueflipedge(hullsh, flipqueue);
17255     } else {
17256       // 'leftsh' is a new hull edge.
17257       dummysh[0] = sencode(leftsh);
17258       break;
17259     }
17260   }
17261 }
17262 
17264 //                                                                           //
17265 // incrflipdelaunaysub()    Create a DT from a 3D coplanar point set using   //
17266 //                          the incremental flip algorithm.                  //
17267 //                                                                           //
17268 // Let T be the current Delaunay triangulation (of vertices of a facet F).   //
17269 // 'shmark', the index of F in 'in->facetlist' (starts from 1).              //
17270 //                                                                           //
17272 
17273 void tetgenmesh::incrflipdelaunaysub(int shmark, REAL eps, list* ptlist,
17274   int holes, REAL* holelist, queue* flipque)
17275 {
17276   face newsh, startsh;
17277   point *insertarray;
17278   point swappt;
17279   pbcdata *pd;
17280   enum locateresult loc;
17281   REAL det, area;
17282   bool aboveflag;
17283   int arraysize;
17284   int epscount;
17285   int fmarker;
17286   int idx, i, j, k;
17287 
17288   // Get the point array (saved in 'ptlist').
17289   insertarray = (point *) ptlist->base;
17290   arraysize = ptlist->len();
17291   if (arraysize < 3) return;
17292 
17293   // Do calculation of 'abovepoint' if number of points > 3.
17294   aboveflag = (arraysize > 3);
17295 
17296   // The initial triangulation T only has one triangle formed by 3 not
17297   //   cillinear points of the set V = 'insertarray'. The first point:
17298   //   a = insertarray[0].
17299 
17300   epscount = 0;
17301   while (true) {
17302   for (i = 1; i < arraysize; i++) {
17303     det = distance(insertarray[0], insertarray[i]);
17304     if (det > (longest * eps)) break;
17305   }
17306   if (i < arraysize) {
17307     // Swap to move b from index i to index 1.
17308     swappt = insertarray[i];
17309     insertarray[i] = insertarray[1];
17310     insertarray[1] = swappt;
17311   }
17312   // Get the third point c, that is not collinear with a and b.
17313   for (i++; i < arraysize; i++) {
17314     if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
17315       break;
17316   }
17317   if (i < arraysize) {
17318     // Swap to move c from index i to index 2.
17319     swappt = insertarray[i];
17320     insertarray[i] = insertarray[2];
17321     insertarray[2] = swappt;
17322     i = 3; // The next inserting point.
17323   } else {
17324     // The set of vertices is not good (or nearly degenerate).  However,
17325     //   a trivial triangulation can be formed (using 3 vertices). It may
17326     //   be corrected (or deleted) by mergefacet().
17327     if ((eps == 0.0) || (epscount > 16)) {
17328       printf("Error:  Invalid PLC.\n");
17329       printf("  Facet (%d, %d, %d", pointmark(insertarray[0]),
17330              pointmark(insertarray[1]), pointmark(insertarray[2]));
17331       if (ptlist->len() > 3) {
17332         printf(", ...");
17333       }
17334       printf(") (%d) is not a valid polygon.\n", shmark);
17335       terminatetetgen(1);
17336     }
17337     // Decrease the eps, and continue to try.
17338     eps *= 1e-2;
17339     epscount++;
17340     continue;
17341   }
17342   break;
17343   } // while (true);
17344 
17345   // Create the initial triangle.
17346   makeshellface(subfaces, &newsh);
17347   setsorg(newsh, insertarray[0]);
17348   setsdest(newsh, insertarray[1]);
17349   setsapex(newsh, insertarray[2]);
17350   // Remeber the facet it belongs to.
17351   setshellmark(newsh, shmark);
17352   // Set vertex type be FREESUBVERTEX if it has no type yet.
17353   if (pointtype(insertarray[0]) == FREEVOLVERTEX) {
17354     setpointtype(insertarray[0], FREESUBVERTEX);
17355   }
17356   if (pointtype(insertarray[1]) == FREEVOLVERTEX) {
17357     setpointtype(insertarray[1], FREESUBVERTEX);
17358   }
17359   if (pointtype(insertarray[2]) == FREEVOLVERTEX) {
17360     setpointtype(insertarray[2], FREESUBVERTEX);
17361   }
17362   // Let 'dummysh' point to it (for point location).
17363   dummysh[0] = sencode(newsh);
17364 
17365   // Are there area constraints?
17366   if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
17367     idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker.
17368     for (k = 0; k < in->numberoffacetconstraints; k++) {
17369       fmarker = (int) in->facetconstraintlist[k * 2];
17370       if (fmarker == idx) {
17371         area = in->facetconstraintlist[k * 2 + 1];
17372         setareabound(newsh, area);
17373         break;
17374       }
17375     }
17376   }
17377 
17378   // Are there pbc conditions?
17379   if (checkpbcs) {
17380     idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker.
17381     for (k = 0; k < in->numberofpbcgroups; k++) {
17382       pd = &subpbcgrouptable[k];
17383       for (j = 0; j < 2; j++) {
17384         if (pd->fmark[j] == idx) {
17385           setshellpbcgroup(newsh, k);
17386           pd->ss[j] = newsh;
17387         }
17388       }
17389     }
17390   }
17391 
17392   if (aboveflag) {
17393     // Compute the 'abovepoint' for orient3d().
17394     abovepoint = facetabovepointarray[shmark];
17395     if (abovepoint == (point) NULL) {
17396       getfacetabovepoint(&newsh);
17397     }
17398   }
17399 
17400   if (holes > 0) {
17401     // Project hole points onto the plane containing the facet.
17402     REAL prj[3];
17403     for (k = 0; k < holes; k++) {
17404       projpt2face(&(holelist[k * 3]), insertarray[0], insertarray[1],
17405                   insertarray[2], prj);
17406       for (j = 0; j < 3; j++) holelist[k * 3 + j] = prj[j];
17407     }
17408   }
17409 
17410   // Incrementally insert the rest of points into T.
17411   for (; i < arraysize; i++) {
17412     // Insert p_i.
17413     startsh.sh = dummysh;
17414     loc = locatesub(insertarray[i], &startsh, 0, 0.0);
17415     if (loc == ONFACE) {
17416       splitsubface(insertarray[i], &startsh, flipque);
17417     } else if (loc == ONEDGE) {
17418       splitsubedge(insertarray[i], &startsh, flipque);
17419     } else if (loc == OUTSIDE) {
17420       collectvisiblesubs(shmark, insertarray[i], &startsh, flipque);
17421     } else if (loc == ONVERTEX) {
17422       // !should not happen!
17423     }
17424     // Set p_i's type FREESUBVERTEX if it has no type yet.
17425     if (pointtype(insertarray[i]) == FREEVOLVERTEX) {
17426       setpointtype(insertarray[i], FREESUBVERTEX);
17427     }
17428     flipsub(flipque);
17429   }
17430 }
17431 
17433 //                                                                           //
17434 // finddirectionsub()    Find the first subface in a facet on the path from  //
17435 //                       one point to another.                               //
17436 //                                                                           //
17437 // Finds the subface in the facet that intersects a line segment drawn from  //
17438 // the origin of `searchsh' to the point `tend', and returns the result in   //
17439 // `searchsh'.  The origin of `searchsh' does not change,  even though the   //
17440 // subface returned may differ from the one passed in.                       //
17441 //                                                                           //
17442 // The return value notes whether the destination or apex of the found face  //
17443 // is collinear with the two points in question.                             //
17444 //                                                                           //
17446 
17447 enum tetgenmesh::finddirectionresult tetgenmesh::finddirectionsub(
17448   face* searchsh, point tend)
17449 {
17450   face checksh;
17451   point startpoint, leftpoint, rightpoint;
17452   REAL leftccw, rightccw;
17453   REAL ori, sign;
17454   int leftflag, rightflag;
17455 
17456   startpoint = sorg(*searchsh);
17457   // Find the sign to simulate that abovepoint is 'above' the facet.
17458   adjustedgering(*searchsh, CCW);
17459   // Make sure 'startpoint' is the origin.
17460   if (sorg(*searchsh) != startpoint) senextself(*searchsh);
17461   rightpoint = sdest(*searchsh);
17462   leftpoint = sapex(*searchsh);
17463   ori = orient3d(startpoint, rightpoint, leftpoint, abovepoint);
17464   sign = ori > 0.0 ? -1 : 1;
17465 
17466   // Is `tend' to the left?
17467   ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17468   leftccw = ori * sign;
17469   leftflag = leftccw > 0.0;
17470   // Is `tend' to the right?
17471   ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17472   rightccw = ori * sign;
17473   rightflag = rightccw > 0.0;
17474   if (leftflag && rightflag) {
17475     // `searchsh' faces directly away from `tend'.  We could go left or
17476     //   right.  Ask whether it's a triangle or a boundary on the left.
17477     senext2(*searchsh, checksh);
17478     spivotself(checksh);
17479     if (checksh.sh == dummysh) {
17480       leftflag = 0;
17481     } else {
17482       rightflag = 0;
17483     }
17484   }
17485   while (leftflag) {
17486     // Turn left until satisfied.
17487     senext2self(*searchsh);
17488     spivotself(*searchsh);
17489     if (searchsh->sh == dummysh) {
17490       printf("Internal error in finddirectionsub():  Unable to find a\n");
17491       printf("  subface leading from %d to %d.\n", pointmark(startpoint),
17492              pointmark(tend));
17493       internalerror();
17494     }
17495     if (sorg(*searchsh) != startpoint) sesymself(*searchsh);
17496     assert(sorg(*searchsh) == startpoint);
17497     leftpoint = sapex(*searchsh);
17498     rightccw = leftccw;
17499     ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17500     leftccw = ori * sign;
17501     leftflag = leftccw > 0.0;
17502   }
17503   while (rightflag) {
17504     // Turn right until satisfied.
17505     spivotself(*searchsh);
17506     if (searchsh->sh == dummysh) {
17507       printf("Internal error in finddirectionsub():  Unable to find a\n");
17508       printf("  subface leading from %d to %d.\n", pointmark(startpoint),
17509              pointmark(tend));
17510       internalerror();
17511     }
17512     if (sdest(*searchsh) != startpoint) sesymself(*searchsh);
17513     assert(sdest(*searchsh) == startpoint);
17514     senextself(*searchsh);
17515     rightpoint = sdest(*searchsh);
17516     leftccw = rightccw;
17517     ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17518     rightccw = ori * sign;
17519     rightflag = rightccw > 0.0;
17520   }
17521   if (leftccw == 0.0) {
17522     return LEFTCOLLINEAR;
17523   } else if (rightccw == 0.0) {
17524     return RIGHTCOLLINEAR;
17525   } else {
17526     return ACROSSEDGE;
17527   }
17528 }
17529 
17531 //                                                                           //
17532 // insertsubseg()    Create a subsegment and insert it between two subfaces. //
17533 //                                                                           //
17534 // The new subsegment ab is inserted at the edge of subface 'tri'.  If ab is //
17535 // not a hull edge, it is inserted between two subfaces.  If 'tri' is a hull //
17536 // face, the initial face ring of ab will be set only one face which is self-//
17537 // bonded.  The final face ring will be constructed in 'unifysegments()'.    //
17538 //                                                                           //
17540 
17541 void tetgenmesh::insertsubseg(face* tri)
17542 {
17543   face oppotri;
17544   face newsubseg;
17545   point pa, pb;
17546   REAL len;
17547   int e1, e2;
17548   int i;
17549 
17550   // Check if there's already a subsegment here.
17551   sspivot(*tri, newsubseg);
17552   if (newsubseg.sh == dummysh) {
17553     // Make new subsegment and initialize its vertices.
17554     makeshellface(subsegs, &newsubseg);
17555     pa = sorg(*tri);
17556     pb = sdest(*tri);
17557     setsorg(newsubseg, pa);
17558     setsdest(newsubseg, pb);
17559     // Are there length constraints?
17560     if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
17561       for (i = 0; i < in->numberofsegmentconstraints; i++) {
17562         e1 = (int) in->segmentconstraintlist[i * 3];
17563         e2 = (int) in->segmentconstraintlist[i * 3 + 1];
17564         if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
17565             ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
17566           len = in->segmentconstraintlist[i * 3 + 2];
17567           setareabound(newsubseg, len);
17568           break;
17569         }
17570       }
17571     }
17572     // Bond new subsegment to the two subfaces it is sandwiched between.
17573     ssbond(*tri, newsubseg);
17574     spivot(*tri, oppotri);
17575     // 'oppotri' might be "out space".
17576     if (oppotri.sh != dummysh) {
17577       ssbond(oppotri, newsubseg);
17578     } /* else {
17579       // Outside! Bond '*tri' to itself.
17580       sbond(*tri, *tri);
17581     } */
17582   }
17583 }
17584 
17586 //                                                                           //
17587 // scoutsegmentsub()    Scout the first triangle on the path from one point  //
17588 //                      to another, and check for completion (reaching the   //
17589 //                      second point), a collinear point,or the intersection //
17590 //                      of two segments.                                     //
17591 //                                                                           //
17592 // Returns true if the entire segment is successfully inserted, and false if //
17593 // the job must be finished by constrainededge().                            //
17594 //                                                                           //
17596 
17597 bool tetgenmesh::scoutsegmentsub(face* searchsh, point tend)
17598 {
17599   face newsubseg;
17600   face crosssub, crosssubseg;
17601   point leftpoint, rightpoint;
17602   enum finddirectionresult collinear;
17603 
17604   collinear = finddirectionsub(searchsh, tend);
17605   rightpoint = sdest(*searchsh);
17606   leftpoint = sapex(*searchsh);
17607   if (rightpoint == tend || leftpoint == tend) {
17608     // The segment is already an edge.
17609     if (leftpoint == tend) {
17610       senext2self(*searchsh);
17611     }
17612     // Insert a subsegment.
17613     insertsubseg(searchsh);
17614     return true;
17615   } else if (collinear == LEFTCOLLINEAR) {
17616     // We've collided with a vertex between the segment's endpoints.
17617     // Make the collinear vertex be the triangle's origin.
17618     senextself(*searchsh); // lprevself(*searchtri);
17619     // Insert a subsegment.
17620     insertsubseg(searchsh);
17621     // Insert the remainder of the segment.
17622     return scoutsegmentsub(searchsh, tend);
17623   } else if (collinear == RIGHTCOLLINEAR) {
17624     // We've collided with a vertex between the segment's endpoints.
17625     // Insert a subsegment.
17626     insertsubseg(searchsh);
17627     // Make the collinear vertex be the triangle's origin.
17628     senextself(*searchsh); // lnextself(*searchtri);
17629     // Insert the remainder of the segment.
17630     return scoutsegmentsub(searchsh, tend);
17631   } else {
17632     senext(*searchsh, crosssub); // lnext(*searchtri, crosstri);
17633     // Check for a crossing segment.
17634     sspivot(crosssub, crosssubseg);
17635 #ifdef SELF_CHECK
17636     assert(crosssubseg.sh == dummysh);
17637 #endif
17638     return false;
17639   }
17640 }
17641 
17643 //                                                                           //
17644 // flipedgerecursive()    Flip an edge.                                      //
17645 //                                                                           //
17646 // This is a support routine for inserting segments into a CDT.              //
17647 //                                                                           //
17648 // Let 'flipedge' be ab, and two triangles abc, abd share at it.  ab may not //
17649 // flipable if the four vertices a, b, c, and d are non-convex. If it is the //
17650 // case, recursively flip ad or bd. Return when ab is flipped.               //
17651 //                                                                           //
17653 
17654 void tetgenmesh::flipedgerecursive(face* flipedge, queue* flipqueue)
17655 {
17656   face fixupsh;
17657   point pa, pb, pc, pd;
17658   REAL oria, orib;
17659   bool doflip;
17660 
17661   pa = sorg(*flipedge);
17662   pb = sdest(*flipedge);
17663   pc = sapex(*flipedge);
17664   do {
17665     spivot(*flipedge, fixupsh);
17666     pd = sapex(fixupsh);
17667     oria = orient3d(pc, pd, abovepoint, pa);
17668     orib = orient3d(pc, pd, abovepoint, pb);
17669     doflip = (oria * orib < 0.0);
17670     if (doflip) {
17671       // Flip the edge (a, b) away.
17672       flip22sub(flipedge, flipqueue);
17673       // Fix flipedge on edge e (c, d).
17674       findedge(flipedge, pc, pd);
17675     } else {
17676       // ab is unflipable. Get the next edge (bd, or da) to flip.
17677       if (sorg(fixupsh) != pb) sesymself(fixupsh);
17678       assert(sdest(fixupsh) == pa);
17679       if (fabs(oria) > fabs(orib)) {
17680         // acd has larger area. Choose da.
17681         senextself(fixupsh);
17682       } else {
17683         // bcd has larger area. Choose bd.
17684         senext2self(fixupsh);
17685       }
17686       // Flip the edge.
17687       flipedgerecursive(&fixupsh, flipqueue);
17688     }
17689   } while (!doflip);
17690 }
17691 
17693 //                                                                           //
17694 // constrainededge()    Force a segment into a CDT.                          //
17695 //                                                                           //
17696 // The segment s is recovered by flipping away the edges it intersects, and  //
17697 // triangulating the polygons that form on each side of it.                  //
17698 //                                                                           //
17699 // Generates a single subsegment connecting `tstart' to `tend'. The triangle //
17700 // `startsh' has `tstart' as its origin.                                     //
17701 //                                                                           //
17703 
17704 void tetgenmesh::constrainededge(face* startsh, point tend, queue* flipqueue)
17705 {
17706   point tstart, tright, tleft;
17707   REAL rori, lori;
17708   bool collision;
17709 
17710   tstart = sorg(*startsh);
17711   do {
17712     // Loop edges oppo to tstart until find one crosses the segment.
17713     do {
17714       tright = sdest(*startsh);
17715       tleft = sapex(*startsh);
17716       // Is edge (tright, tleft) corss the segment.
17717       rori = orient3d(tstart, tright, abovepoint, tend);
17718       collision = (rori == 0.0);
17719       if (collision) break; // tright is on the segment.
17720       lori = orient3d(tstart, tleft, abovepoint, tend);
17721       collision = (lori == 0.0);
17722       if (collision) { //  tleft is on the segment.
17723         senext2self(*startsh);
17724         break;
17725       }
17726       if (rori * lori < 0.0) break; // Find the crossing edge.
17727       // Both points are at one side of the segment.
17728       finddirectionsub(startsh, tend);
17729     } while (true);
17730     if (collision) break;
17731     // Get the neighbor face at edge e (tright, tleft).
17732     senextself(*startsh);
17733     // Flip the crossing edge.
17734     flipedgerecursive(startsh, flipqueue);
17735     // After flip, sorg(*startsh) == tstart.
17736     assert(sorg(*startsh) == tstart);
17737   } while (sdest(*startsh) != tend);
17738 
17739   // Insert a subsegment to make the segment permanent.
17740   insertsubseg(startsh);
17741   // If there was a collision with an interceding vertex, install another
17742   //   segment connecting that vertex with endpoint2.
17743   if (collision) {
17744     // Insert the remainder of the segment.
17745     if (!scoutsegmentsub(startsh, tend)) {
17746       constrainededge(startsh, tend, flipqueue);
17747     }
17748   }
17749 }
17750 
17752 //                                                                           //
17753 // recoversegment()    Recover a segment in the surface triangulation.       //
17754 //                                                                           //
17756 
17757 void tetgenmesh::recoversegment(point tstart, point tend, queue* flipqueue)
17758 {
17759   face searchsh;
17760 
17761   if (b->verbose > 2) {
17762     printf("    Insert seg (%d, %d).\n", pointmark(tstart), pointmark(tend));
17763   }
17764 
17765   // Find a triangle whose origin is the segment's first endpoint.
17766   searchsh.sh = dummysh;
17767   // Search for the segment's first endpoint by point location.
17768   if (locatesub(tstart, &searchsh, 0, 0.0) != ONVERTEX) {
17769     // Possibly caused by a degenerate subface. Do a brute-force search.
17770     list *newshlist;
17771     int i, j;
17772     newshlist = new list(sizeof(face), NULL, 256);
17773     // Get new subfaces, do not remove protected segments.
17774     retrievenewsubs(newshlist, false);
17775     // Search for a sub contain tstart.
17776     for (i = 0; i < newshlist->len(); i++) {
17777       searchsh = * (face *)(* newshlist)[i];
17778       for (j = 0; j < 3; j++) {
17779         if (sorg(searchsh) == tstart) break;
17780         senextself(searchsh);
17781       }
17782       if (j < 3) break;
17783     }
17784     delete newshlist;
17785     if (sorg(searchsh) != tstart) {
17786       printf("Internal error in recoversegment():  Vertex location failed.\n");
17787       internalerror();
17788     }
17789   }
17790   // Scout the segment and insert it if it is found.
17791   if (scoutsegmentsub(&searchsh, tend)) {
17792     // The segment was easily inserted.
17793     return;
17794   }
17795   // Insert the segment into the triangulation by flips.
17796   constrainededge(&searchsh, tend, flipqueue);
17797   // Some edges may need flipping.
17798   flipsub(flipqueue);
17799 }
17800 
17802 //                                                                           //
17803 // infecthullsub()    Virally infect all of the triangles of the convex hull //
17804 //                    that are not protected by subsegments.                 //
17805 //                                                                           //
17807 
17808 void tetgenmesh::infecthullsub(memorypool* viri)
17809 {
17810   face hulltri, nexttri, starttri;
17811   face hullsubseg;
17812   shellface **deadshellface;
17813 
17814   // Find a triangle handle on the hull.
17815   hulltri.sh = dummysh;
17816   hulltri.shver = 0;
17817   spivotself(hulltri);
17818   adjustedgering(hulltri, CCW);
17819   // Remember where we started so we know when to stop.
17820   starttri = hulltri;
17821   // Go once counterclockwise around the convex hull.
17822   do {
17823     // Ignore triangles that are already infected.
17824     if (!sinfected(hulltri)) {
17825       // Is the triangle protected by a subsegment?
17826       sspivot(hulltri, hullsubseg);
17827       if (hullsubseg.sh == dummysh) {
17828         // The triangle is not protected; infect it.
17829         if (!sinfected(hulltri)) {
17830           sinfect(hulltri);
17831           deadshellface = (shellface **) viri->alloc();
17832           *deadshellface = hulltri.sh;
17833         }
17834       }
17835     }
17836     // To find the next hull edge, go clockwise around the next vertex.
17837     senextself(hulltri); // lnextself(hulltri);
17838     spivot(hulltri, nexttri); // oprev(hulltri, nexttri);
17839     if (nexttri.sh == hulltri.sh) {
17840       nexttri.sh = dummysh;  // 'hulltri' is self-bonded.
17841     } else {
17842       adjustedgering(nexttri, CCW);
17843       senextself(nexttri);
17844     }
17845     while (nexttri.sh != dummysh) {
17846       hulltri = nexttri;
17847       spivot(hulltri, nexttri); // oprev(hulltri, nexttri);
17848       if (nexttri.sh == hulltri.sh) {
17849         nexttri.sh = dummysh;  // 'hulltri' is self-bonded.
17850       } else {
17851         adjustedgering(nexttri, CCW);
17852         senextself(nexttri);
17853       }
17854     }
17855   } while (hulltri != starttri);
17856 }
17857 
17859 //                                                                           //
17860 // plaguesub()    Spread the virus from all infected triangles to any        //
17861 //                neighbors not protected by subsegments.  Delete all        //
17862 //                infected triangles.                                        //
17863 //                                                                           //
17864 // This is the procedure that actually creates holes and concavities.        //
17865 //                                                                           //
17867 
17868 void tetgenmesh::plaguesub(memorypool* viri)
17869 {
17870   face testtri, neighbor, ghostsh;
17871   face neighborsubseg;
17872   shellface **virusloop;
17873   shellface **deadshellface;
17874   int i;
17875 
17876   // Loop through all the infected triangles, spreading the virus to
17877   //   their neighbors, then to their neighbors' neighbors.
17878   viri->traversalinit();
17879   virusloop = (shellface **) viri->traverse();
17880   while (virusloop != (shellface **) NULL) {
17881     testtri.sh = *virusloop;
17882     // Check each of the triangle's three neighbors.
17883     for (i = 0; i < 3; i++) {
17884       // Find the neighbor.
17885       spivot(testtri, neighbor);
17886       // Check for a subsegment between the triangle and its neighbor.
17887       sspivot(testtri, neighborsubseg);
17888       // Check if the neighbor is nonexistent or already infected.
17889       if ((neighbor.sh == dummysh) || sinfected(neighbor)) {
17890         if (neighborsubseg.sh != dummysh) {
17891           // There is a subsegment separating the triangle from its
17892           //   neighbor, but both triangles are dying, so the subsegment
17893           //   dies too.
17894           shellfacedealloc(subsegs, neighborsubseg.sh);
17895           if (neighbor.sh != dummysh) {
17896             // Make sure the subsegment doesn't get deallocated again
17897             //   later when the infected neighbor is visited.
17898             ssdissolve(neighbor);
17899           }
17900         }
17901       } else {                   // The neighbor exists and is not infected.
17902         if (neighborsubseg.sh == dummysh) {
17903           // There is no subsegment protecting the neighbor, so the
17904           //   neighbor becomes infected.
17905           sinfect(neighbor);
17906           // Ensure that the neighbor's neighbors will be infected.
17907           deadshellface = (shellface **) viri->alloc();
17908           *deadshellface = neighbor.sh;
17909         } else {               // The neighbor is protected by a subsegment.
17910           // Remove this triangle from the subsegment.
17911           ssbond(neighbor, neighborsubseg);
17912         }
17913       }
17914       senextself(testtri);
17915     }
17916     virusloop = (shellface **) viri->traverse();
17917   }
17918 
17919   ghostsh.sh = dummysh; // A handle of outer space.
17920   viri->traversalinit();
17921   virusloop = (shellface **) viri->traverse();
17922   while (virusloop != (shellface **) NULL) {
17923     testtri.sh = *virusloop;
17924     // Record changes in the number of boundary edges, and disconnect
17925     //   dead triangles from their neighbors.
17926     for (i = 0; i < 3; i++) {
17927       spivot(testtri, neighbor);
17928       if (neighbor.sh != dummysh) {
17929         // Disconnect the triangle from its neighbor.
17930         // sdissolve(neighbor);
17931         sbond(neighbor, ghostsh);
17932       }
17933       senextself(testtri);
17934     }
17935     // Return the dead triangle to the pool of triangles.
17936     shellfacedealloc(subfaces, testtri.sh);
17937     virusloop = (shellface **) viri->traverse();
17938   }
17939   // Empty the virus pool.
17940   viri->restart();
17941 }
17942 
17944 //                                                                           //
17945 // carveholessub()    Find the holes and infect them.  Find the area         //
17946 //                    constraints and infect them.  Infect the convex hull.  //
17947 //                    Spread the infection and kill triangles.  Spread the   //
17948 //                    area constraints.                                      //
17949 //                                                                           //
17950 // This routine mainly calls other routines to carry out all these functions.//
17951 //                                                                           //
17953 
17954 void tetgenmesh::carveholessub(int holes, REAL* holelist, memorypool *viri)
17955 {
17956   face searchtri, triangleloop;
17957   shellface **holetri;
17958   enum locateresult intersect;
17959   int i;
17960 
17961   // Mark as infected any unprotected triangles on the boundary.
17962   //   This is one way by which concavities are created.
17963   infecthullsub(viri);
17964 
17965   if (holes > 0) {
17966     // Infect each triangle in which a hole lies.
17967     for (i = 0; i < 3 * holes; i += 3) {
17968       // Ignore holes that aren't within the bounds of the mesh.
17969       if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
17970           && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)
17971           && (holelist[i + 2] >= zmin) && (holelist[i + 2] <= zmax)) {
17972         // Start searching from some triangle on the outer boundary.
17973         searchtri.sh = dummysh;
17974         // Find a triangle that contains the hole.
17975         intersect = locatesub(&holelist[i], &searchtri, 0, 0.0);
17976         if ((intersect != OUTSIDE) && (!sinfected(searchtri))) {
17977           // Infect the triangle.  This is done by marking the triangle
17978           //   as infected and including the triangle in the virus pool.
17979           sinfect(searchtri);
17980           holetri = (shellface **) viri->alloc();
17981           *holetri = searchtri.sh;
17982         }
17983       }
17984     }
17985   }
17986 
17987   if (viri->items > 0) {
17988     // Carve the holes and concavities.
17989     plaguesub(viri);
17990   }
17991   // The virus pool should be empty now.
17992 }
17993 
17995 //                                                                           //
17996 // triangulate()    Triangulate a PSLG into a CDT.                           //
17997 //                                                                           //
17998 // A Planar Straight Line Graph (PSLG) P is actually a 2D polygonal region,  //
17999 // possibly contains holes, segments and vertices in its interior. P is tri- //
18000 // angulated into a set of _subfaces_ forming a CDT of P.                    //
18001 //                                                                           //
18002 // The vertices and segments of P are found in 'ptlist' and 'conlist', resp- //
18003 // ectively. 'holelist' contains a list of hole points. 'shmark' will be set //
18004 // to all subfaces of P.                                                     //
18005 //                                                                           //
18006 // The CDT is created directly in the pools 'subfaces' and 'subsegs'. It can //
18007 // be retrived by a broadth-first searching starting from 'dummysh[0]'(debug //
18008 // function 'outsurfmesh()' does it).                                        //
18009 //                                                                           //
18011 
18012 void tetgenmesh::triangulate(int shmark, REAL eps, list* ptlist, list* conlist,
18013   int holes, REAL* holelist, memorypool* viri, queue* flipqueue)
18014 {
18015   face newsh;
18016   point *cons;
18017   int i;
18018 
18019   if (b->verbose > 1) {
18020     printf("    %d vertices, %d segments", ptlist->len(), conlist->len());
18021     if (holes > 0) {
18022       printf(", %d holes", holes);
18023     }
18024     printf(", shmark: %d.\n", shmark);
18025   }
18026 
18027   // Create the DT of V by the 2D incremental flip algorithm.
18028   incrflipdelaunaysub(shmark, eps, ptlist, holes, holelist, flipqueue);
18029   // Recover boundary edges.
18030   if (ptlist->len() > 3) {
18031     // Insert segments into the DT.
18032     for (i = 0; i < conlist->len(); i++) {
18033       cons = (point *)(* conlist)[i];
18034       recoversegment(cons[0], cons[1], flipqueue);
18035     }
18036     // Carve holes and concavities.
18037     carveholessub(holes, holelist, viri);
18038   } else if (ptlist->len() == 3) {
18039     // Insert 3 segments directly.
18040     newsh.sh = dummysh;
18041     newsh.shver = 0;
18042     spivotself(newsh);
18043     for (i = 0; i < 3; i++) {
18044       insertsubseg(&newsh);
18045       senextself(newsh);
18046     }
18047   } else if (ptlist->len() == 2) {
18048     // This facet is actually a segment. It is not support by the mesh data
18049     //   strcuture. Hence the segment will not be maintained in the mesh.
18050     //   However, during segment recovery, the segment can be processed.
18051     cons = (point *)(* conlist)[0];
18052     makeshellface(subsegs, &newsh);
18053     setsorg(newsh, cons[0]);
18054     setsdest(newsh, cons[1]);
18055   }
18056 }
18057 
18059 //                                                                           //
18060 // retrievenewsubs()    Retrieve newly created subfaces.                     //
18061 //                                                                           //
18062 // The new subfaces created by triangulate() can be found by a broadth-first //
18063 // searching starting from 'dummysh[0]'.                                     //
18064 //                                                                           //
18065 // 'newshlist' (empty on input) returns the retrieved subfaces. Each edge on //
18066 // the hull is bound to 'dummysh' and protected by a segment. If 'removeseg' //
18067 // is TRUE, the segment is removed.                                          //
18068 //                                                                           //
18070 
18071 void tetgenmesh::retrievenewsubs(list* newshlist, bool removeseg)
18072 {
18073   face startsh, neighsh;
18074   face deadseg;
18075   int i, j;
18076 
18077   // The first new subface is found at dummysh[0].
18078   startsh.sh = dummysh;
18079   startsh.shver = 0;
18080   spivotself(startsh);
18081   assert(startsh.sh != dummysh);
18082   sinfect(startsh);
18083   newshlist->append(&startsh);
18084 
18085   // Find the rest of new subfaces by a broadth-first searching.
18086   for (i = 0; i < newshlist->len(); i++) {
18087     // Get a new subface s.
18088     startsh = * (face *)(* newshlist)[i];
18089     for (j = 0; j < 3; j++) {
18090       spivot(startsh, neighsh);
18091       if (neighsh.sh != dummysh) {
18092         if (!sinfected(neighsh)) {
18093           // Discovered a new subface.
18094           sinfect(neighsh);
18095           newshlist->append(&neighsh);
18096         }
18097       } else {
18098         // Found a boundary edge.
18099         if (removeseg) {
18100           // This side of s may be protected by a segment.
18101           sspivot(startsh, deadseg);
18102           if (deadseg.sh != dummysh) {
18103             // Detach it from s.
18104             ssdissolve(startsh);
18105             // Delete the segment.
18106             shellfacedealloc(subsegs, deadseg.sh);
18107           }
18108         }
18109       }
18110       senextself(startsh);
18111     }
18112   }
18113   for (i = 0; i < newshlist->len(); i++) {
18114     startsh = * (face *)(* newshlist)[i];
18115     suninfect(startsh);
18116   }
18117 }
18118 
18120 //                                                                           //
18121 // unifysegments()    Unify identical segments and build facet connections.  //
18122 //                                                                           //
18123 // After creating the surface mesh. Each facet has its own segments.  There  //
18124 // are duplicated segments between adjacent facets.  This routine has three  //
18125 // purposes:                                                                 //
18126 //   (1) identify the set of segments which have the same endpoints and      //
18127 //       unify them into one segment, remove redundant ones;                 //
18128 //   (2) create the face rings of the unified segments, hence setup the      //
18129 //       connections between facets; and                                     //
18130 //   (3) set a unique marker (1-based) for each segment.                     //
18131 // On finish, each segment is unique and the face ring around it (right-hand //
18132 // rule) is constructed. The connections between facets-facets are setup.    //
18133 //                                                                           //
18135 
18136 void tetgenmesh::unifysegments()
18137 {
18138   list *sfacelist;
18139   shellface **facesperverlist;
18140   face subsegloop, testseg;
18141   face sface, sface1, sface2;
18142   point torg, tdest;
18143   REAL da1, da2;
18144   int *idx2facelist;
18145   int segmarker;
18146   int idx, k, m;
18147 
18148   if (b->verbose > 0) {
18149     printf("  Unifying segments.\n");
18150   }
18151 
18152   // Compute a mapping from indices of vertices to subfaces.
18153   makesubfacemap(idx2facelist, facesperverlist);
18154   // Initialize 'sfacelist' for constructing the face link of each segment.
18155   sfacelist = new list(sizeof(face), NULL);
18156 
18157   segmarker = 1;
18158   subsegs->traversalinit();
18159   subsegloop.sh = shellfacetraverse(subsegs);
18160   while (subsegloop.sh != (shellface *) NULL) {
18161     subsegloop.shver = 0; // For sure.
18162     torg = sorg(subsegloop);
18163     tdest = sdest(subsegloop);
18164     idx = pointmark(torg) - in->firstnumber;
18165     // Loop through the set of subfaces containing 'torg'.  Get all the
18166     //   subfaces containing the edge (torg, tdest). Save and order them
18167     //   in 'sfacelist', the ordering is defined by the right-hand rule
18168     //   with thumb points from torg to tdest.
18169     for (k = idx2facelist[idx]; k < idx2facelist[idx + 1]; k++) {
18170       sface.sh = facesperverlist[k];
18171       sface.shver = 0;
18172       // sface may be died due to the removing of duplicated subfaces.
18173       if (!isdead(&sface) && isfacehasedge(&sface, torg, tdest)) {
18174         // 'sface' contains this segment.
18175         findedge(&sface, torg, tdest);
18176         // Save it in 'sfacelist'.
18177         if (sfacelist->len() < 2) {
18178           sfacelist->append(&sface);
18179         } else {
18180           for (m = 0; m < sfacelist->len() - 1; m++) {
18181             sface1 = * (face *)(* sfacelist)[m];
18182             sface2 = * (face *)(* sfacelist)[m + 1];
18183             da1 = facedihedral(torg, tdest, sapex(sface1), sapex(sface));
18184             da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
18185             if (da1 < da2) {
18186               break;  // Insert it after m.
18187             }
18188           }
18189           sfacelist->insert(m + 1, &sface);
18190         }
18191       }
18192     }
18193     if (b->verbose > 1) {
18194       printf("    Identifying %d segments of (%d  %d).\n", sfacelist->len(),
18195              pointmark(torg), pointmark(tdest));
18196     }
18197     // Set the connection between this segment and faces containing it,
18198     //   at the same time, remove redundant segments.
18199     for (k = 0; k < sfacelist->len(); k++) {
18200       sface = *(face *)(* sfacelist)[k];
18201       sspivot(sface, testseg);
18202       // If 'testseg' is not 'subsegloop', it is a redundant segment that
18203       //   needs be removed. BE CAREFUL it may already be removed. Do not
18204       //   remove it twice, i.e., do test 'isdead()' together.
18205       if ((testseg.sh != subsegloop.sh) && !isdead(&testseg)) {
18206         shellfacedealloc(subsegs, testseg.sh);
18207       }
18208       // 'ssbond' bonds the subface and the segment together, and dissloves
18209       //   the old bond as well.
18210       ssbond(sface, subsegloop);
18211     }
18212     // Set connection between these faces.
18213     sface = *(face *)(* sfacelist)[0];
18214     for (k = 1; k <= sfacelist->len(); k++) {
18215       if (k < sfacelist->len()) {
18216         sface1 = *(face *)(* sfacelist)[k];
18217       } else {
18218         sface1 = *(face *)(* sfacelist)[0];    // Form a face loop.
18219       }
18220       /*
18221       // Check if these two subfaces are the same. It is possible when user
18222       //   defines one facet (or polygon) two or more times. If they are,
18223       //   they should not be bonded together, instead of that, one of them
18224       //   should be delete from the surface mesh.
18225       if ((sfacelist->len() > 1) && sapex(sface) == sapex(sface1)) {
18226         // They are duplicated faces.
18227         if (b->verbose > 0) {
18228           printf("  A duplicated subface (%d, %d, %d) is removed.\n",
18229                  pointmark(torg), pointmark(tdest), pointmark(sapex(sface)));
18230         }
18231         if (k == sfacelist->len()) {
18232           // 'sface' is the last face, however, it is same as the first one.
18233           //   In order to form the ring, we have to let the second last
18234           //   face bond to the first one 'sface1'.
18235           shellfacedealloc(subfaces, sface.sh);
18236           assert(sfacelist->len() >= 2);
18237           assert(k == sfacelist->len());
18238           sface = *(face *)(* sfacelist)[k - 2];
18239         } else {
18240           // 'sface1' is in the middle and may be the last one.
18241           shellfacedealloc(subfaces, sface1.sh);
18242           // Skip this face and go to the next one.
18243           continue;
18244         }
18245       }
18246       */
18247       if (b->verbose > 2) {
18248         printf("    Bond subfaces (%d, %d, %d) and (%d, %d, %d).\n",
18249                pointmark(torg), pointmark(tdest), pointmark(sapex(sface)),
18250                pointmark(torg), pointmark(tdest), pointmark(sapex(sface1)));
18251       }
18252       sbond1(sface, sface1);
18253       sface = sface1;
18254     }
18255     // Set the unique segment marker into the unified segment.
18256     setshellmark(subsegloop, segmarker);
18257     // Increase the marker.
18258     segmarker++;
18259     // Clear the working list.
18260     sfacelist->clear();
18261     subsegloop.sh = shellfacetraverse(subsegs);
18262   }
18263 
18264   delete [] idx2facelist;
18265   delete [] facesperverlist;
18266   delete sfacelist;
18267 }
18268 
18270 //                                                                           //
18271 // mergefacets()    Merge adjacent facets to be one facet if they are        //
18272 //                  coplanar and have the same boundary marker.              //
18273 //                                                                           //
18274 // Segments between two merged facets will be removed from the mesh.  If all //
18275 // segments around a vertex have been removed, change its vertex type to be  //
18276 // FREESUBVERTEX. Edge flips will be performed to ensure the Delaunayness of //
18277 // the triangulation of merged facets.                                       //
18278 //                                                                           //
18280 
18281 void tetgenmesh::mergefacets(queue* flipqueue)
18282 {
18283   face parentsh, neighsh, neineighsh;
18284   face segloop;
18285   point eorg, edest;
18286   REAL ori;
18287   bool mergeflag, pbcflag;
18288   int* segspernodelist;
18289   int fidx1, fidx2;
18290   int i, j;
18291 
18292   if (b->verbose > 0) {
18293     printf("  Merging coplanar facets.\n");
18294   }
18295   // Create and initialize 'segspernodelist'.
18296   segspernodelist = new int[points->items + 1];
18297   for (i = 0; i < points->items + 1; i++) segspernodelist[i] = 0;
18298 
18299   // Loop the segments, counter the number of segments sharing each vertex.
18300   subsegs->traversalinit();
18301   segloop.sh = shellfacetraverse(subsegs);
18302   while (segloop.sh != (shellface *) NULL) {
18303     // Increment the number of sharing segments for each endpoint.
18304     for (i = 0; i < 2; i++) {
18305       j = pointmark((point) segloop.sh[3 + i]);
18306       segspernodelist[j]++;
18307     }
18308     segloop.sh = shellfacetraverse(subsegs);
18309   }
18310 
18311   // Loop the segments, find out dead segments.
18312   subsegs->traversalinit();
18313   segloop.sh = shellfacetraverse(subsegs);
18314   while (segloop.sh != (shellface *) NULL) {
18315     eorg = sorg(segloop);
18316     edest = sdest(segloop);
18317     spivot(segloop, parentsh);
18318     spivot(parentsh, neighsh);
18319     spivot(neighsh, neineighsh);
18320     if (parentsh.sh != neighsh.sh && parentsh.sh == neineighsh.sh) {
18321       // Exactly two subfaces at this segment.
18322       fidx1 = shellmark(parentsh) - 1;
18323       fidx2 = shellmark(neighsh) - 1;
18324       pbcflag = false;
18325       if (checkpbcs) {
18326         pbcflag = (shellpbcgroup(parentsh) >= 0)
18327           || (shellpbcgroup(neighsh) >= 0);
18328       }
18329       // Possibly merge them if they are not in the same facet.
18330       if ((fidx1 != fidx2) && !pbcflag) {
18331         // Test if they are coplanar.
18332         ori = orient3d(eorg, edest, sapex(parentsh), sapex(neighsh));
18333         if (ori != 0.0) {
18334           if (iscoplanar(eorg, edest, sapex(parentsh), sapex(neighsh), ori,
18335                          b->epsilon)) {
18336             ori = 0.0; // They are assumed as coplanar.
18337           }
18338         }
18339         if (ori == 0.0) {
18340           mergeflag = (in->facetmarkerlist == (int *) NULL ||
18341           in->facetmarkerlist[fidx1] == in->facetmarkerlist[fidx2]);
18342           if (mergeflag) {
18343             // This segment becomes dead.
18344             if (b->verbose > 1) {
18345               printf("  Removing segment (%d, %d).\n", pointmark(eorg),
18346                      pointmark(edest));
18347             }
18348             ssdissolve(parentsh);
18349             ssdissolve(neighsh);
18350             shellfacedealloc(subsegs, segloop.sh);
18351             j = pointmark(eorg);
18352             segspernodelist[j]--;
18353             if (segspernodelist[j] == 0) {
18354               setpointtype(eorg, FREESUBVERTEX);
18355             }
18356             j = pointmark(edest);
18357             segspernodelist[j]--;
18358             if (segspernodelist[j] == 0) {
18359               setpointtype(edest, FREESUBVERTEX);
18360             }
18361             // Add 'parentsh' to queue checking for flip.
18362             enqueueflipedge(parentsh, flipqueue);
18363           }
18364         }
18365       }
18366     }
18367     segloop.sh = shellfacetraverse(subsegs);
18368   }
18369 
18370   if (!flipqueue->empty()) {
18371     // Restore the Delaunay property in the facet triangulation.
18372     flipsub(flipqueue);
18373   }
18374 
18375   delete [] segspernodelist;
18376 }
18377 
18379 //                                                                           //
18380 // meshsurface()    Create the surface mesh of a PLC.                        //
18381 //                                                                           //
18382 // Let X be the PLC, the surface mesh S of X consists of triangulated facets.//
18383 // S is created mainly in the following steps:                               //
18384 //                                                                           //
18385 // (1) Form the CDT of each facet of X separately (by routine triangulate()).//
18386 // After it is done, the subfaces of each facet are connected to each other, //
18387 // however there is no connection between facets yet.  Notice each facet has //
18388 // its own segments, some of them are duplicated.                            //
18389 //                                                                           //
18390 // (2) Remove the redundant segments created in step (1) (by routine unify-  //
18391 // segment()). The subface ring of each segment is created,  the connection  //
18392 // between facets are established as well.                                   //
18393 //                                                                           //
18394 // The return value indicates the number of segments of X.                   //
18395 //                                                                           //
18397 
18398 long tetgenmesh::meshsurface()
18399 {
18400   list *ptlist, *conlist;
18401   queue *flipqueue;
18402   tetgenio::facet *f;
18403   tetgenio::polygon *p;
18404   memorypool *viri;
18405   point *idx2verlist;
18406   point tstart, tend, *cons;
18407   int *worklist;
18408   int end1, end2;
18409   int shmark, i, j;
18410 
18411   if (!b->quiet) {
18412     printf("Creating surface mesh.\n");
18413   }
18414 
18415   // Compute a mapping from indices to points.
18416   makeindex2pointmap(idx2verlist);
18417   // Compute a mapping from points to tets for computing abovepoints.
18418   makepoint2tetmap();
18419   // Initialize 'facetabovepointarray'.
18420   facetabovepointarray = new point[in->numberoffacets + 1];
18421   for (i = 0; i < in->numberoffacets + 1; i++) {
18422     facetabovepointarray[i] = (point) NULL;
18423   }
18424   if (checkpbcs) {
18425     // Initialize the global array 'subpbcgrouptable'.
18426     createsubpbcgrouptable();
18427   }
18428 
18429   // Initialize working lists.
18430   viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
18431   flipqueue = new queue(sizeof(badface));
18432   ptlist = new list(sizeof(point *), NULL, 256);
18433   conlist = new list(sizeof(point *) * 2, NULL, 256);
18434   worklist = new int[points->items + 1];
18435   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
18436 
18437   // Loop the facet list, triangulate each facet. On finish, all subfaces
18438   //   are in 'subfaces', all segments are in 'subsegs'. Notice: there're
18439   //   redundant segments.  Remember: All facet indices count from 1.
18440   for (shmark = 1; shmark <= in->numberoffacets; shmark++) {
18441     // Get a facet F.
18442     f = &in->facetlist[shmark - 1];
18443 
18444     // Process the duplicated points first, they are marked with type
18445     //   DUPLICATEDVERTEX by incrflipdelaunay().  Let p and q are dup.
18446     //   and the index of p is larger than q's, p is substituted by q.
18447     //   In a STL mesh, duplicated points are implicitly included.
18448     if ((b->object == tetgenbehavior::STL) || dupverts) {
18449       // Loop all polygons of this facet.
18450       for (i = 0; i < f->numberofpolygons; i++) {
18451         p = &(f->polygonlist[i]);
18452         // Loop other vertices of this polygon.
18453         for (j = 0; j < p->numberofvertices; j++) {
18454           end1 = p->vertexlist[j];
18455           tstart = idx2verlist[end1 - in->firstnumber];
18456           if (pointtype(tstart) == DUPLICATEDVERTEX) {
18457             // Reset the index of vertex-j.
18458             tend = point2ppt(tstart);
18459             end2 = pointmark(tend);
18460             p->vertexlist[j] = end2;
18461           }
18462         }
18463       }
18464     }
18465 
18466     // Loop polygons of F, get the set V of vertices and S of segments.
18467     for (i = 0; i < f->numberofpolygons; i++) {
18468       // Get a polygon.
18469       p = &(f->polygonlist[i]);
18470       // Get the first vertex.
18471       end1 = p->vertexlist[0];
18472       if ((end1 < in->firstnumber) ||
18473           (end1 >= in->firstnumber + in->numberofpoints)) {
18474         if (!b->quiet) {
18475           printf("Warning:  Invalid the 1st vertex %d of polygon", end1);
18476           printf(" %d in facet %d.\n", i + 1, shmark);
18477         }
18478         continue; // Skip this polygon.
18479       }
18480       tstart = idx2verlist[end1 - in->firstnumber];
18481       // Add tstart to V if it haven't been added yet.
18482       if (worklist[end1] == 0) {
18483         ptlist->append(&tstart);
18484         worklist[end1] = 1;
18485       }
18486       // Loop other vertices of this polygon.
18487       for (j = 1; j <= p->numberofvertices; j++) {
18488         // get a vertex.
18489         if (j < p->numberofvertices) {
18490           end2 = p->vertexlist[j];
18491         } else {
18492           end2 = p->vertexlist[0];  // Form a loop from last to first.
18493         }
18494         if ((end2 < in->firstnumber) ||
18495             (end2 >= in->firstnumber + in->numberofpoints)) {
18496           if (!b->quiet) {
18497             printf("Warning:  Invalid vertex %d in polygon %d", end2, i + 1);
18498             printf(" in facet %d.\n", shmark);
18499           }
18500         } else {
18501           if (end1 != end2) {
18502             // 'end1' and 'end2' form a segment.
18503             tend = idx2verlist[end2 - in->firstnumber];
18504             // Add tstart to V if it haven't been added yet.
18505             if (worklist[end2] == 0) {
18506               ptlist->append(&tend);
18507               worklist[end2] = 1;
18508             }
18509             // Save the segment in S (conlist).
18510             cons = (point *) conlist->append(NULL);
18511             cons[0] = tstart;
18512             cons[1] = tend;
18513             // Set the start for next continuous segment.
18514             end1 = end2;
18515             tstart = tend;
18516           } else {
18517             // Two identical vertices represent an isolated vertex of F.
18518             if (p->numberofvertices > 2) {
18519               // This may be an error in the input, anyway, we can continue
18520               //   by simply skipping this segment.
18521               if (!b->quiet) {
18522                 printf("Warning:  Polygon %d has two identical verts", i + 1);
18523                 printf(" in facet %d.\n", shmark);
18524               }
18525             }
18526             // Ignore this vertex.
18527           }
18528         }
18529         // Is the polygon degenerate (a segment or a vertex)?
18530         if (p->numberofvertices == 2) break;
18531       }
18532     }
18533     // Unmark vertices.
18534     for (i = 0; i < ptlist->len(); i++) {
18535       tstart = * (point *)(* ptlist)[i];
18536       end1 = pointmark(tstart);
18537       assert(worklist[end1] == 1);
18538       worklist[end1] = 0;
18539     }
18540 
18541     // Create a CDT of F.
18542     triangulate(shmark, b->epsilon * 1e+2, ptlist, conlist, f->numberofholes,
18543                 f->holelist, viri, flipqueue);
18544     // Clear working lists.
18545     ptlist->clear();
18546     conlist->clear();
18547     viri->restart();
18548   }
18549 
18550   // Unify segments in 'subsegs', remove redundant segments.  Face links
18551   //   of segments are also built.
18552   unifysegments();
18553   // Remember the number of input segments (for output).
18554   insegments = subsegs->items;
18555 
18556   if (checkpbcs) {
18557     // Create the global array 'segpbcgrouptable'.
18558     createsegpbcgrouptable();
18559   }
18560 
18561   if (b->object == tetgenbehavior::STL) {
18562     // Remove redundant vertices (for .stl input mesh).
18563     jettisonnodes();
18564   }
18565 
18566   if (!b->nomerge && !b->nobisect && !checkpbcs) {
18567     // No '-M' switch - merge adjacent facets if they are coplanar.
18568     mergefacets(flipqueue);
18569   }
18570 
18571   delete [] idx2verlist;
18572   delete [] worklist;
18573   delete ptlist;
18574   delete conlist;
18575   delete flipqueue;
18576   delete viri;
18577 
18578   return subsegs->items;
18579 }
18580 
18581 //
18582 // End of surface triangulation routines
18583 //
18584 
18586 //                                                                           //
18587 // interecursive()    Recursively do intersection test on a set of triangles.//
18588 //                                                                           //
18589 // Recursively split the set 'subfacearray' of subfaces into two sets using  //
18590 // a cut plane parallel to x-, or, y-, or z-axies.  The split criteria are   //
18591 // follows. Assume the cut plane is H, and H+ denotes the left halfspace of  //
18592 // H, and H- denotes the right halfspace of H; and s be a subface:           //
18593 //                                                                           //
18594 //    (1) If all points of s lie at H+, put it into left array;              //
18595 //    (2) If all points of s lie at H-, put it into right array;             //
18596 //    (3) If some points of s lie at H+ and some of lie at H-, or some       //
18597 //        points lie on H, put it into both arraies.                         //
18598 //                                                                           //
18599 // Partitions by x-axis if axis == '0'; by y-axis if axis == '1'; by z-axis  //
18600 // if axis == '2'. If current cut plane is parallel to the x-axis, the next  //
18601 // one will be parallel to y-axis, and the next one after the next is z-axis,//
18602 // and then alternately return back to x-axis.                               //
18603 //                                                                           //
18604 // Stop splitting when the number of triangles of the input array is not     //
18605 // decreased anymore. Do tests on the current set.                           //
18606 //                                                                           //
18608 
18609 void tetgenmesh::
18610 interecursive(shellface** subfacearray, int arraysize, int axis, REAL bxmin,
18611               REAL bxmax, REAL bymin, REAL bymax, REAL bzmin, REAL bzmax,
18612               int* internum)
18613 {
18614   shellface **leftarray, **rightarray;
18615   face sface1, sface2;
18616   point p1, p2, p3;
18617   point p4, p5, p6;
18618   enum interresult intersect;
18619   REAL split;
18620   bool toleft, toright;
18621   int leftsize, rightsize;
18622   int i, j;
18623 
18624   if (b->verbose > 1) {
18625     printf("  Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
18626            arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
18627            axis == 0 ? "x" : (axis == 1 ? "y" : "z"));
18628   }
18629 
18630   leftarray = new shellface*[arraysize];
18631   if (leftarray == NULL) {
18632     printf("Error in interecursive():  Insufficient memory.\n");
18633     terminatetetgen(1);
18634   }
18635   rightarray = new shellface*[arraysize];
18636   if (rightarray == NULL) {
18637     printf("Error in interecursive():  Insufficient memory.\n");
18638     terminatetetgen(1);
18639   }
18640   leftsize = rightsize = 0;
18641 
18642   if (axis == 0) {
18643     // Split along x-axis.
18644     split = 0.5 * (bxmin + bxmax);
18645   } else if (axis == 1) {
18646     // Split along y-axis.
18647     split = 0.5 * (bymin + bymax);
18648   } else {
18649     // Split along z-axis.
18650     split = 0.5 * (bzmin + bzmax);
18651   }
18652 
18653   for (i = 0; i < arraysize; i++) {
18654     sface1.sh = subfacearray[i];
18655     p1 = (point) sface1.sh[3];
18656     p2 = (point) sface1.sh[4];
18657     p3 = (point) sface1.sh[5];
18658     toleft = toright = false;
18659     if (p1[axis] < split) {
18660       toleft = true;
18661       if (p2[axis] >= split || p3[axis] >= split) {
18662         toright = true;
18663       }
18664     } else if (p1[axis] > split) {
18665       toright = true;
18666       if (p2[axis] <= split || p3[axis] <= split) {
18667         toleft = true;
18668       }
18669     } else {
18670       // p1[axis] == split;
18671       toleft = true;
18672       toright = true;
18673     }
18674     // At least one is true;
18675 #ifdef SELF_CHECK
18676     assert(!(toleft == false && toright == false));
18677 #endif
18678     if (toleft) {
18679       leftarray[leftsize] = sface1.sh;
18680       leftsize++;
18681     }
18682     if (toright) {
18683       rightarray[rightsize] = sface1.sh;
18684       rightsize++;
18685     }
18686   }
18687 
18688   if (leftsize < arraysize && rightsize < arraysize) {
18689     // Continue to partition the input set. Now 'subfacearray' has been
18690     //   split into two sets, it's memory can be freed. 'leftarray' and
18691     //   'rightarray' will be freed in the next recursive (after they're
18692     //   partitioned again or performing tests).
18693     delete [] subfacearray;
18694     // Continue to split these two sets.
18695     if (axis == 0) {
18696       interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax,
18697                     bzmin, bzmax, internum);
18698       interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax,
18699                     bzmin, bzmax, internum);
18700     } else if (axis == 1) {
18701       interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split,
18702                     bzmin, bzmax, internum);
18703       interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax,
18704                     bzmin, bzmax, internum);
18705     } else {
18706       interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax,
18707                     bzmin, split, internum);
18708       interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax,
18709                     split, bzmax, internum);
18710     }
18711   } else {
18712     if (b->verbose > 1) {
18713       printf("  Checking intersecting faces.\n");
18714     }
18715     // Perform a brute-force compare on the set.
18716     for (i = 0; i < arraysize; i++) {
18717       sface1.sh = subfacearray[i];
18718       p1 = (point) sface1.sh[3];
18719       p2 = (point) sface1.sh[4];
18720       p3 = (point) sface1.sh[5];
18721       for (j = i + 1; j < arraysize; j++) {
18722         sface2.sh = subfacearray[j];
18723         p4 = (point) sface2.sh[3];
18724         p5 = (point) sface2.sh[4];
18725         p6 = (point) sface2.sh[5];
18726         intersect = tri_tri_inter(p1, p2, p3, p4, p5, p6);
18727         if (intersect == INTERSECT || intersect == SHAREFACE) {
18728           if (!b->quiet) {
18729             if (intersect == INTERSECT) {
18730               printf("  Facet #%d intersects facet #%d at triangles:\n",
18731                      shellmark(sface1), shellmark(sface2));
18732               printf("    (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
18733                      pointmark(p1), pointmark(p2), pointmark(p3),
18734                      pointmark(p4), pointmark(p5), pointmark(p6));
18735             } else {
18736               printf("  Facet #%d duplicates facet #%d at triangle:\n",
18737                      shellmark(sface1), shellmark(sface2));
18738               printf("    (%4d, %4d, %4d)\n", pointmark(p1), pointmark(p2),
18739                      pointmark(p3));
18740             }
18741           }
18742           // Increase the number of intersecting pairs.
18743           (*internum)++;
18744           // Infect these two faces (although they may already be infected).
18745           sinfect(sface1);
18746           sinfect(sface2);
18747         }
18748       }
18749     }
18750     // Don't forget to free all three arrays. No further partition.
18751     delete [] leftarray;
18752     delete [] rightarray;
18753     delete [] subfacearray;
18754   }
18755 }
18756 
18758 //                                                                           //
18759 // detectinterfaces()    Detect intersecting triangles.                      //
18760 //                                                                           //
18761 // Given a set of triangles,  find the pairs of intersecting triangles from  //
18762 // them.  Here the set of triangles is in 'subfaces' which is a surface mesh //
18763 // of a PLC (.poly or .smesh).                                               //
18764 //                                                                           //
18765 // To detect whether two triangles are intersecting is done by the routine   //
18766 // 'tri_tri_inter()'.  The algorithm for the test is very simple and stable. //
18767 // It is based on geometric orientation test which uses exact arithmetics.   //
18768 //                                                                           //
18769 // Use divide-and-conquer algorithm for reducing the number of intersection  //
18770 // tests.  Start from the bounding box of the input point set, recursively   //
18771 // partition the box into smaller boxes, until the number of triangles in a  //
18772 // box is not decreased anymore. Then perform triangle-triangle tests on the //
18773 // remaining set of triangles.  The memory allocated in the input set is     //
18774 // freed immediately after it has been partitioned into two arrays.  So it   //
18775 // can be re-used for the consequent partitions.                             //
18776 //                                                                           //
18777 // On return, the pool 'subfaces' will be cleared, and only the intersecting //
18778 // triangles remain for output (to a .face file).                            //
18779 //                                                                           //
18781 
18782 void tetgenmesh::detectinterfaces()
18783 {
18784   shellface **subfacearray;
18785   face shloop;
18786   int internum;
18787   int i;
18788 
18789   if (!b->quiet) {
18790     printf("Detecting intersecting facets.\n");
18791   }
18792 
18793   // Construct a map from indices to subfaces;
18794   subfacearray = new shellface*[subfaces->items];
18795   subfaces->traversalinit();
18796   shloop.sh = shellfacetraverse(subfaces);
18797   i = 0;
18798   while (shloop.sh != (shellface *) NULL) {
18799     subfacearray[i] = shloop.sh;
18800     shloop.sh = shellfacetraverse(subfaces);
18801     i++;
18802   }
18803 
18804   internum = 0;
18805   // Recursively split the set of triangles into two sets using a cut plane
18806   //   parallel to x-, or, y-, or z-axies.  Stop splitting when the number
18807   //   of subfaces is not decreasing anymore. Do tests on the current set.
18808   interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax,
18809                 zmin, zmax, &internum);
18810 
18811   if (!b->quiet) {
18812     if (internum > 0) {
18813       printf("\n!! Found %d pairs of faces are intersecting.\n\n", internum);
18814     } else {
18815       printf("\nNo faces are intersecting.\n\n");
18816     }
18817   }
18818 
18819   if (internum > 0) {
18820     // Traverse all subfaces, deallocate those have not been infected (they
18821     //   are not intersecting faces). Uninfect those have been infected.
18822     //   After this loop, only intersecting faces remain.
18823     subfaces->traversalinit();
18824     shloop.sh = shellfacetraverse(subfaces);
18825     while (shloop.sh != (shellface *) NULL) {
18826       if (sinfected(shloop)) {
18827         suninfect(shloop);
18828       } else {
18829         shellfacedealloc(subfaces, shloop.sh);
18830       }
18831       shloop.sh = shellfacetraverse(subfaces);
18832     }
18833   } else {
18834     // Deallocate all subfaces.
18835     subfaces->restart();
18836   }
18837 }
18838 
18839 //
18840 // Begin of periodic boundary condition routines
18841 //
18842 
18844 //                                                                           //
18845 // createsubpbcgrouptable()    Create the 'subpbcgrouptable'.                //
18846 //                                                                           //
18847 // Allocate the memory for 'subpbcgrouptable'.  Each entry i (a pbcdata) of  //
18848 // the table represents a pbcgroup.  Most of the fields of a group-i are set //
18849 // in this routine. 'fmark[0]', 'fmark[1]', and 'transmat[0]' are directly   //
18850 // copied from the corresponding data of 'in->numberofpbcgroups'. 'transmat  //
18851 // [1]' is calculated as the inverse matrix of 'transmat[0]'.  'ss[0]' and   //
18852 // 'ss[1]' are initilized be 'dummysh'. They are set in 'trangulatefacet()'  //
18853 // (when -p is in use) or 'reconstructmesh()' (when -r is in use).           //
18854 //                                                                           //
18856 
18857 void tetgenmesh::createsubpbcgrouptable()
18858 {
18859   tetgenio::pbcgroup *pg;
18860   pbcdata *pd;
18861   REAL A[4][4], rhs[4], D;
18862   int indx[4];
18863   int i, j, k;
18864 
18865   subpbcgrouptable = new pbcdata[in->numberofpbcgroups];
18866   for (i = 0; i < in->numberofpbcgroups; i++) {
18867     pg = &(in->pbcgrouplist[i]);
18868     pd = &(subpbcgrouptable[i]);
18869     // Copy data from pg to pd.
18870     pd->fmark[0] = pg->fmark1;
18871     pd->fmark[1] = pg->fmark2;
18872     // Initialize array 'pd->ss'.
18873     pd->ss[0].sh = dummysh;
18874     pd->ss[1].sh = dummysh;
18875     // Copy the transform matrix from pg to pd->transmat[0].
18876     for (j = 0; j < 4; j++) {
18877       for (k = 0; k < 4; k++) {
18878         pd->transmat[0][j][k] = pg->transmat[j][k];
18879         // Prepare for inverting the matrix.
18880         A[j][k] = pg->transmat[j][k];
18881       }
18882     }
18883     // Calculate the inverse matrix (pd->transmat[1]) of pd->transmat[0].
18884     lu_decmp(A, 4, indx, &D, 0);
18885     for (j = 0; j < 4; j++) {
18886       for (k = 0; k < 4; k++) rhs[k] = 0.0;
18887       rhs[j] = 1.0;
18888       lu_solve(A, 4, indx, rhs, 0);
18889       for (k = 0; k < 4; k++) pd->transmat[1][k][j] = rhs[k];
18890     }
18891   }
18892 }
18893 
18895 //                                                                           //
18896 // getsubpbcgroup()    Get the pbcgroup of a subface.                        //
18897 //                                                                           //
18898 // 'pbcsub' has pbc defined. Its pbcgroup is returned in 'pd'. In addition,  //
18899 // 'f1' (0 or 1) indicates the position of 'pbcsub' in 'pd'; 'f2' (= 1 - f1) //
18900 // is the position where the symmetric subface of 'pbcsub' is found.         //
18901 //                                                                           //
18903 
18904 void tetgenmesh::getsubpbcgroup(face* pbcsub, pbcdata** pd, int *f1, int *f2)
18905 {
18906   int groupid, fmark, idx;
18907 
18908   groupid = shellpbcgroup(*pbcsub);
18909   *pd = &subpbcgrouptable[groupid];
18910 
18911   // Get the facet index (1 - based).
18912   idx = shellmark(*pbcsub);
18913   // Get the facet marker from array (0 - based).
18914   fmark = in->facetmarkerlist[idx - 1];
18915   if ((*pd)->fmark[0] == fmark) {
18916     *f1 = 0;
18917   } else {
18918 #ifdef SELF_CHECK
18919     assert((*pd)->fmark[1] == fmark);
18920 #endif
18921     *f1 = 1;
18922   }
18923   *f2 = 1 - (*f1);
18924 }
18925 
18927 //                                                                           //
18928 // getsubpbcsympoint()    Compute the symmetric point for a subface point.   //
18929 //                                                                           //
18930 // 'newpoint' lies on 'splitsub'. This routine calculates a 'sympoint' which //
18931 // locates on 'symsplitsub' and symmtric to 'newpoint'.  Return the location //
18932 // of sympoint wrt. symsplitsub.                                             //
18933 //                                                                           //
18935 
18936 enum tetgenmesh::locateresult tetgenmesh:: getsubpbcsympoint(point newpoint,
18937   face* splitsub, point sympoint, face* symsplitsub)
18938 {
18939   pbcdata *pd;
18940   face subloop;
18941   point pa, pb, pc;
18942   enum locateresult symloc;
18943   REAL ori;
18944   int f1, f2, i;
18945 
18946   // Get the pbcgroup of 'splitsub'.
18947   getsubpbcgroup(splitsub, &pd, &f1, &f2);
18948 
18949   // Transform newpoint from f1 -> f2.
18950   for (i = 0; i < 3; i++) {
18951     sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
18952                 + pd->transmat[f1][i][1] * newpoint[1]
18953                 + pd->transmat[f1][i][2] * newpoint[2]
18954                 + pd->transmat[f1][i][3] * 1.0;
18955   }
18956   // Locate sympoint in f2.
18957   symloc = OUTSIDE;
18958   *symsplitsub = pd->ss[f2];
18959   // Is the stored subface valid? Hole removal may delete the subface.
18960   if ((symsplitsub->sh != dummysh) && !isdead(symsplitsub)) {
18961     // 'symsplitsub' should lie on the symmetric facet. Check it.
18962     i = shellmark(*symsplitsub);
18963     if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18964       // 'symsplitsub' has the symmetric boundary marker.
18965       pa = sorg(*symsplitsub);
18966       pb = sdest(*symsplitsub);
18967       pc = sapex(*symsplitsub);
18968       // Test if they are (nearly) coplanar. Some facets may have the
18969       //   same boundary marker but not coplanar with this point.
18970       ori = orient3d(pa, pb, pc, sympoint);
18971       if (iscoplanar(pa, pb, pc, sympoint, ori, b->epsilon * 1e+2)) {
18972         // Locate sympoint in facet. Don't stop at subsegment.
18973         abovepoint = facetabovepointarray[shellmark(*symsplitsub)];
18974         if (abovepoint == (point) NULL) {
18975           getfacetabovepoint(symsplitsub);
18976         }
18977         symloc = locatesub(sympoint, symsplitsub, 0, b->epsilon * 1e+2);
18978       }
18979     }
18980   }
18981   if (symloc == OUTSIDE) {
18982     // Do a brute-force searching for the symmetric subface.
18983     REAL epspp = b->epsilon * 1e+2;
18984     int lcount = 0;
18985     do {
18986       // Locate sympoint in the pool of subfaces (with fmark pd->fmark[f2]).
18987       subfaces->traversalinit();
18988       subloop.sh = shellfacetraverse(subfaces);
18989       while (subloop.sh != (shellface *) NULL) {
18990         i = shellmark(subloop);
18991         if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18992           // Found a facet have the symmetric boundary marker.
18993           pa = sorg(subloop);
18994           pb = sdest(subloop);
18995           pc = sapex(subloop);
18996           // Test if they are (nearly) coplanar. Some facets may have the
18997           //   same boundary marker but not coplanar with this point.
18998           ori = orient3d(pa, pb, pc, sympoint);
18999           if (iscoplanar(pa, pb, pc, sympoint, ori, epspp)) {
19000             // Test if sympoint is (nearly) inside this facet.
19001             // Get the abovepoint of the facet.
19002             abovepoint = facetabovepointarray[shellmark(subloop)];
19003             // Do we need to calculate the abovepoint?
19004             if (abovepoint == (point) NULL) {
19005               getfacetabovepoint(&subloop);
19006             }
19007             // subloop is on the facet, search sympoint.
19008             symloc = locatesub(sympoint, &subloop, 0, epspp);
19009             if (symloc != OUTSIDE) break;
19010           }
19011         }
19012         subloop.sh = shellfacetraverse(subfaces);
19013       }
19014       lcount++;
19015       epspp *= 10.0;
19016     } while ((symloc == OUTSIDE) && (lcount < 3));
19017 #ifdef SELF_CHECK
19018     // sympoint should be inside the facet.
19019     assert(symloc != OUTSIDE);
19020 #endif
19021     // Set the returning subface.
19022     *symsplitsub = subloop;
19023     // Update the stored subface for next searching.
19024     pd->ss[f2] = *symsplitsub;
19025   }
19026 
19027   return adjustlocatesub(sympoint, symsplitsub, symloc, b->epsilon);
19028 }
19029 
19031 //                                                                           //
19032 // createsegpbcgrouptable()    Create the 'segpbcgrouptable'.                //
19033 //                                                                           //
19034 // Each segment may belong to more than one pbcgroups.  For example, segment //
19035 // ab may need to be symmteric to both segments cd, and ef, then  ab and cd, //
19036 // cd and ef, ef and ab form three pbcgroups.                                //
19037 //                                                                           //
19038 // 'segpbcgrouptable' is  implemented as a list of pbcdatas. Each item i is  //
19039 // a pbcgroup.                                                               //
19040 //                                                                           //
19042 
19043 void tetgenmesh::createsegpbcgrouptable()
19044 {
19045   shellface** segsperverlist;
19046   pbcdata *pd, *ppd, pd1, pd2;
19047   face segloop, symseg;
19048   face startsh, spinsh, symsh;
19049   point pa, pb, syma, symb;
19050   enum locateresult symloc;
19051   REAL testpt[3], sympt[3];
19052   bool inflag;
19053   int *idx2seglist;
19054   int segid1, segid2;
19055   int f1, f2;
19056   int i, j, k, l;
19057 
19058   // Allocate memory for 'subpbcgrouptable'.
19059   segpbcgrouptable = new list(sizeof(pbcdata), NULL, 256);
19060 
19061   if (b->refine) {
19062     // Create a point-to-seg map for quickly finding PBC seg pairs.
19063     makesegmentmap(idx2seglist, segsperverlist);
19064   }
19065 
19066   // Loop through the segment list.
19067   subsegs->traversalinit();
19068   segloop.sh = shellfacetraverse(subsegs);
19069   while (segloop.sh != (shellface *) NULL) {
19070     // Loop the subface ring of segloop ab.
19071     pa = sorg(segloop);
19072     pb = sdest(segloop);
19073     segid1 = shellmark(segloop);
19074     spivot(segloop, startsh);
19075     spinsh = startsh;
19076     do {
19077       // Adjust spinsh be edge ab.
19078       if (sorg(spinsh) != pa) {
19079         sesymself(spinsh);
19080       }
19081       // Does spinsh belong to a pbcgroup?
19082       if (shellpbcgroup(spinsh) != -1) {
19083         // Yes! There exists a segment cd. ab and cd form a pbcgroup.
19084         if (b->refine) {
19085           getsubpbcgroup(&spinsh, &pd, &f1, &f2);
19086           // Transform pa from f1 -> f2.
19087           for (i = 0; i < 3; i++) {
19088             sympt[i] = pd->transmat[f1][i][0] * pa[0]
19089                      + pd->transmat[f1][i][1] * pa[1]
19090                      + pd->transmat[f1][i][2] * pa[2]
19091                      + pd->transmat[f1][i][3] * 1.0;
19092           }
19093           syma = point2pbcpt(pa);
19094           // Is 'sympt == syma'?
19095           if (distance(sympt, syma) > (longest * b->epsilon)) {
19096             // No. Search the symmetric vertex of pa.
19097             symloc = getsubpbcsympoint(pa, &spinsh, sympt, &symsh);
19098             syma = sorg(symsh);
19099             if (symloc != ONVERTEX) {
19100               // Do a brute force search. Not done yet.
19101               assert(0);
19102             }
19103           }
19104           // Transform pb from f1 -> f2.
19105           for (i = 0; i < 3; i++) {
19106             sympt[i] = pd->transmat[f1][i][0] * pb[0]
19107                      + pd->transmat[f1][i][1] * pb[1]
19108                      + pd->transmat[f1][i][2] * pb[2]
19109                      + pd->transmat[f1][i][3] * 1.0;
19110           }
19111           // Search sym subface from the point-to-subface map.
19112           symseg.shver = 0;
19113           j = pointmark(syma) - in->firstnumber;
19114           for (i = idx2seglist[j]; i < idx2seglist[j + 1]; i++) {
19115             symseg.sh = segsperverlist[i];
19116             if (sorg(symseg) == syma) symb = sdest(symseg);
19117             else symb = sorg(symseg);
19118             if (distance(sympt, symb) <= (longest * b->epsilon)) break;
19119           }
19120           assert(i < idx2seglist[j + 1]);
19121         } else {
19122           //   'testpt' is the midpoint of ab used to find cd.
19123           for (i = 0; i < 3; i++) testpt[i] = 0.5 * (pa[i] + pb[i]);
19124           symloc = getsubpbcsympoint(testpt, &spinsh, sympt, &symsh);
19125 #ifdef SELF_CHECK
19126           assert(symloc == ONEDGE);
19127 #endif
19128           sspivot(symsh, symseg);
19129         }
19130 #ifdef SELF_CHECK
19131         assert(symseg.sh != dummysh);
19132 #endif
19133         // Check whether this group has already been created in list.
19134         segid2 = shellmark(symseg);
19135         inflag = false;
19136         for (i = 0; i < segpbcgrouptable->len() && !inflag; i++) {
19137           pd = (pbcdata *)(* segpbcgrouptable)[i];
19138           if (pd->segid[0] == segid1) {
19139             if (pd->segid[1] == segid2) inflag = true;
19140           } else if (pd->segid[0] == segid2) {
19141             if (pd->segid[1] == segid1) inflag = true;
19142           }
19143         }
19144         if (!inflag) {
19145           // Create a segment pbcgroup in list for ab and cd.
19146           pd = (pbcdata *) segpbcgrouptable->append(NULL);
19147           // Save the markers of ab and cd.
19148           pd->segid[0] = segid1;
19149           pd->segid[1] = segid2;
19150           // Save the handles of ab and cd.
19151           pd->ss[0] = segloop;
19152           pd->ss[1] = symseg;
19153           // Find the map from ab to cd.
19154           getsubpbcgroup(&spinsh, &ppd, &f1, &f2);
19155           pd->fmark[0] = ppd->fmark[f1];
19156           pd->fmark[1] = ppd->fmark[f2];
19157           // Set the map from ab to cd.
19158           for (i = 0; i < 4; i++) {
19159             for (j = 0; j < 4; j++) {
19160               pd->transmat[0][i][j] = ppd->transmat[f1][i][j];
19161             }
19162           }
19163           // Set the map from cd to ab.
19164           for (i = 0; i < 4; i++) {
19165             for (j = 0; j < 4; j++) {
19166               pd->transmat[1][i][j] = ppd->transmat[f2][i][j];
19167             }
19168           }
19169         }
19170       }
19171       // Go to the next subface in the ring of ab.
19172       spivotself(spinsh);
19173     } while (spinsh.sh != startsh.sh);
19174     segloop.sh = shellfacetraverse(subsegs);
19175   }
19176 
19177   if (b->refine) {
19178     delete [] segsperverlist;
19179     delete [] idx2seglist;
19180   }
19181 
19182   // Create the indirect segment pbcgroups.
19183   // Bug-fixed (08 Sept. 2006). The total size of 'segpbcgrouptable' may get
19184   //   increased. Do not use pointers for 'pd1' and 'pd2'. The addresses may
19185   //   be invaild after realloc().
19186   for (i = 0; i < segpbcgrouptable->len(); i++) {
19187     pd1 = * (pbcdata *)(* segpbcgrouptable)[i];
19188     for (f1 = 0; f1 < 2; f1++) {
19189       // Search for a group (except i) contains pd1.segid[f1].
19190       for (j = 0; j < segpbcgrouptable->len(); j++) {
19191         if (j == i) continue;
19192         pd2 = * (pbcdata *)(* segpbcgrouptable)[j];
19193         f2 = -1;
19194         if (pd1.segid[f1] == pd2.segid[0]) {
19195           f2 = 0;
19196         } else if (pd1.segid[f1] == pd2.segid[1]) {
19197           f2 = 1;
19198         }
19199         if (f2 != -1) {
19200 #ifdef SELF_CHECK
19201           assert(pd1.segid[f1] == pd2.segid[f2]);
19202 #endif
19203           segid1 = pd1.segid[1 - f1];
19204           segid2 = pd2.segid[1 - f2];
19205           // Search for the existence of segment pbcgroup (segid1, segid2).
19206           inflag = false;
19207           for (k = 0; k < segpbcgrouptable->len() && !inflag; k++) {
19208             pd = (pbcdata *)(* segpbcgrouptable)[k];
19209             if (pd->segid[0] == segid1) {
19210               if (pd->segid[1] == segid2) inflag = true;
19211             } else if (pd->segid[0] == segid2) {
19212               if (pd->segid[1] == segid1) inflag = true;
19213             }
19214           }
19215           if (!inflag) {
19216             pd = (pbcdata *) segpbcgrouptable->append(NULL);
19217             pd->segid[0] = pd1.segid[1 - f1];
19218             pd->segid[1] = pd2.segid[1 - f2];
19219             pd->ss[0] = pd1.ss[1 - f1];
19220             pd->ss[1] = pd2.ss[1 - f2];
19221             // Invalid the fmark[0] == fmark[1].
19222             pd->fmark[0] = pd->fmark[1] = 0;
19223             // Translate matrix pd->transmat[0] = m2 * m1, where m1 =
19224             //   pd1.transmat[1 - f1], m2 = pd2.transmat[f2].
19225             for (k = 0; k < 4; k++) {
19226               for (l = 0; l < 4; l++) {
19227                 pd->transmat[0][k][l] = pd2.transmat[f2][k][l];
19228               }
19229             }
19230             m4xm4(pd->transmat[0], pd1.transmat[1 - f1]);
19231             // Translate matrix pd->transmat[1] = m4 * m3, where m3 =
19232             //   pd2.transmat[1 - f2], m4 = pd1.transmat[f1].
19233             for (k = 0; k < 4; k++) {
19234               for (l = 0; l < 4; l++) {
19235                 pd->transmat[1][k][l] = pd1.transmat[f1][k][l];
19236               }
19237             }
19238             m4xm4(pd->transmat[1], pd2.transmat[1 - f2]);
19239           }
19240         }
19241       }
19242     }
19243   }
19244 
19245   // Form a map from segment index to pbcgroup list of this segment.
19246   idx2segpglist = new int[subsegs->items + 1];
19247   for (i = 0; i < subsegs->items + 1; i++) idx2segpglist[i] = 0;
19248   // Loop through 'segpbcgrouptable', counter the number of pbcgroups of
19249   //   each segment.
19250   for (i = 0; i < segpbcgrouptable->len(); i++) {
19251     pd = (pbcdata *)(* segpbcgrouptable)[i];
19252     for (j = 0; j < 2; j++) {
19253       k = pd->segid[j] - 1;
19254       idx2segpglist[k]++;
19255     }
19256   }
19257   // Calculate the total length of array 'segpglist'.
19258   j = idx2segpglist[0];
19259   idx2segpglist[0] = 0;  // Array starts from 0 element.
19260   for (i = 0; i < subsegs->items; i++) {
19261     k = idx2segpglist[i + 1];
19262     idx2segpglist[i + 1] = idx2segpglist[i] + j;
19263     j = k;
19264   }
19265   // The total length is in the last unit of idx2segpglist.
19266   segpglist = new int[idx2segpglist[i]];
19267   // Loop the set of pbcgroups again, set the data into segpglist.
19268   for (i = 0; i < segpbcgrouptable->len(); i++) {
19269     pd = (pbcdata *)(* segpbcgrouptable)[i];
19270     for (j = 0; j < 2; j++) {
19271       k = pd->segid[j] - 1;
19272       segpglist[idx2segpglist[k]] = i;
19273       idx2segpglist[k]++;
19274     }
19275   }
19276   // Contents in 'idx2segpglist' are shifted, now shift them back.
19277   for (i = subsegs->items - 1; i >= 0; i--) {
19278     idx2segpglist[i + 1] = idx2segpglist[i];
19279   }
19280   idx2segpglist[0] = 0;
19281 }
19282 
19284 //                                                                           //
19285 // getsegpbcsympoint()    Compute the symmetric point for a segment point.   //
19286 //                                                                           //
19287 // 'newpoint' lies on 'splitseg'. This routine calculates a 'sympoint' which //
19288 // locates on 'symsplitseg' and symmtric to 'newpoint'.  Return the location //
19289 // of sympoint wrt. symsplitseg.                                             //
19290 //                                                                           //
19292 
19293 enum tetgenmesh::locateresult tetgenmesh::
19294 getsegpbcsympoint(point newpoint, face* splitseg, point sympoint,
19295                   face* symsplitseg, int groupid)
19296 {
19297   pbcdata *pd;
19298   enum locateresult symloc;
19299   int segid, f1, f2, i;
19300 
19301   pd = (pbcdata *)(* segpbcgrouptable)[groupid];
19302   segid = shellmark(*splitseg);
19303   if (pd->segid[0] == segid) {
19304     f1 = 0;
19305   } else {
19306 #ifdef SELF_CHECK
19307     assert(pd->segid[1] == segid);
19308 #endif
19309     f1 = 1;
19310   }
19311   f2 = 1 - f1;
19312 
19313   // Transform newpoint from f1 -> f2.
19314   for (i = 0; i < 3; i++) {
19315     sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
19316                 + pd->transmat[f1][i][1] * newpoint[1]
19317                 + pd->transmat[f1][i][2] * newpoint[2]
19318                 + pd->transmat[f1][i][3] * 1.0;
19319   }
19320   // Locate sympoint in f2.
19321   *symsplitseg = pd->ss[f2];
19322 #ifdef SELF_CHECK
19323   assert(symsplitseg->sh != dummysh);
19324 #endif
19325   // Locate sympoint in facet. Stop at subsegment.
19326   symloc = locateseg(sympoint, symsplitseg);
19327   symloc = adjustlocateseg(sympoint, symsplitseg, symloc, b->epsilon * 1e+2);
19328   return symloc;
19329 }
19330 
19331 //
19332 // End of periodic boundary condition routines
19333 //
19334 
19335 //
19336 // Begin of vertex perturbation routines
19337 //
19338 
19340 //                                                                           //
19341 // randgenerator()    Generate a random REAL number between (0, |range|).    //
19342 //                                                                           //
19344 
19345 REAL tetgenmesh::randgenerator(REAL range)
19346 {
19347   REAL worknumber, result;
19348   int expo;
19349 
19350   if (range == 0.0) return 0.0;
19351 
19352   expo = 0;
19353   worknumber = fabs(range);
19354   // Normalize worknumber (i.e., 1.xxxExx)
19355   if (worknumber > 10.0) {
19356     while (worknumber > 10.0) {
19357       worknumber /= 10.0;
19358       expo++;
19359     }
19360   } else if (worknumber < 1.0) {
19361     while (worknumber < 1.0) {
19362       worknumber *= 10.0;
19363       expo--;
19364     }
19365   }
19366 #ifdef SELF_CHECK
19367   assert(worknumber >= 1.0 && worknumber <= 10.0);
19368 #endif
19369 
19370   // Enlarge worknumber 1000 times.
19371   worknumber *= 1e+3;
19372   expo -= 3;
19373   // Generate a randome number between (0, worknumber).
19374   result = (double) randomnation((int) worknumber);
19375 
19376   // Scale result back into the original size.
19377   if (expo > 0) {
19378     while (expo != 0) {
19379       result *= 10.0;
19380       expo--;
19381     }
19382   } else if (expo < 0) {
19383     while (expo != 0) {
19384       result /= 10.0;
19385       expo++;
19386     }
19387   }
19388 #ifdef SELF_CHECK
19389   assert((result >= 0.0) && (result <= fabs(range)));
19390 #endif
19391 
19392   return result;
19393 }
19394 
19396 //                                                                           //
19397 // checksub4cocir()    Test a subface to find co-circular pair of subfaces.  //
19398 //                                                                           //
19399 // 'eps' is a relative tolerance for testing approximately cospherical case. //
19400 // Set it to zero if only exact test is desired.                             //
19401 //                                                                           //
19402 // An edge(not a segment) of 'testsub' is locally degenerate if the opposite //
19403 // vertex of the adjacent subface is cocircular with the vertices of testsub.//
19404 // If 'once' is TRUE, operate on the edge only if the pointer 'testsub->sh'  //
19405 // is smaller than its neighbor (for each edge is considered only once).     //
19406 //                                                                           //
19407 // Return TRUE if find an edge of testsub is locally degenerate.             //
19408 //                                                                           //
19410 
19411 bool tetgenmesh::checksub4cocir(face* testsub, REAL eps, bool once,
19412   bool enqflag)
19413 {
19414   badface *cocirsub;
19415   face subloop, neighsub;
19416   face checkseg;
19417   point pa, pb, pc, pd;
19418   REAL sign;
19419   int i;
19420 
19421   subloop = *testsub;
19422   subloop.shver = 0; // Keep the CCW orientation.
19423   // Get the abovepoint of the facet.
19424   abovepoint = facetabovepointarray[shellmark(subloop)];
19425   // Do we need to calculate the abovepoint?
19426   if (abovepoint == (point) NULL) {
19427     getfacetabovepoint(&subloop);
19428   }
19429   // Check the three edges of subloop.
19430   for (i = 0; i < 3; i++) {
19431     sspivot(subloop, checkseg);
19432     if (checkseg.sh == dummysh) {
19433       // It is not a segment, get the adjacent subface.
19434       spivot(subloop, neighsub);
19435       // assert(neighsub.sh != dummysh);
19436       if (!once || (once && (neighsub.sh > subloop.sh))) {
19437         pa = sorg(subloop);
19438         pb = sdest(subloop);
19439         pc = sapex(subloop);
19440         pd = sapex(neighsub);
19441         sign = insphere(pa, pb, pc, abovepoint, pd);
19442         if ((sign != 0.0) && (eps > 0.0)) {
19443           if (iscospheric(pa, pb, pc, abovepoint, pd, sign, eps)) sign = 0.0;
19444         }
19445         if (sign == 0.0) {
19446           // It's locally degenerate!
19447           if (enqflag && badsubfaces != (memorypool *) NULL) {
19448             // Save it.
19449             cocirsub = (badface *) badsubfaces->alloc();
19450             cocirsub->ss = subloop;
19451             cocirsub->forg = pa;
19452             cocirsub->fdest = pb;
19453             cocirsub->fapex = pc;
19454             cocirsub->foppo = pd;
19455             setshell2badface(cocirsub->ss, cocirsub);
19456           }
19457           if (b->verbose > 1) {
19458             printf("    Found set (%d, %d, %d, %d).\n", pointmark(pa),
19459                    pointmark(pb), pointmark(pc), pointmark(pd));
19460           }
19461           return true;
19462         }
19463       }
19464     }
19465     senextself(subloop);
19466   }
19467 
19468   return false;
19469 }
19470 
19472 //                                                                           //
19473 // tallcocirsubs()    Find all co-circular subfaces and save them in list.   //
19474 //                                                                           //
19476 
19477 void tetgenmesh::tallcocirsubs(REAL eps, bool enqflag)
19478 {
19479   face subloop;
19480 
19481   // Loop over all subfaces.
19482   subfaces->traversalinit();
19483   subloop.sh = shellfacetraverse(subfaces);
19484   while (subloop.sh != (shellface *) NULL) {
19485     checksub4cocir(&subloop, eps, true, enqflag);
19486     subloop.sh = shellfacetraverse(subfaces);
19487   }
19488 }
19489 
19491 //                                                                           //
19492 // tallencsegsfsubs()    Check for encroached segs from a list of subfaces.  //
19493 //                                                                           //
19495 
19496 bool tetgenmesh::tallencsegsfsubs(point testpt, list* cavsublist)
19497 {
19498   face startsub, checkseg;
19499   long oldencnum;
19500   int i, j;
19501 
19502   // Remember the current number of encroached segments.
19503   oldencnum = badsubsegs->items;
19504 
19505   // Check segments in the list of subfaces.
19506   for (i = 0; i < cavsublist->len(); i++) {
19507     startsub = * (face *)(* cavsublist)[i];
19508     // Test all three edges of startsub.
19509     for (j = 0; j < 3; j++) {
19510       sspivot(startsub, checkseg);
19511       if (checkseg.sh != dummysh) {
19512         if (!shell2badface(checkseg)) {
19513           checkseg4encroach(&checkseg, testpt, NULL, true);
19514         }
19515       }
19516       senextself(startsub);
19517     }
19518   }
19519 
19520   return (badsubsegs->items > oldencnum);
19521 }
19522 
19524 //                                                                           //
19525 // collectflipedges()    Collect edges of split subfaces for flip checking.  //
19526 //                                                                           //
19527 // 'inspoint' is a newly inserted segment point (inserted by insertsite()).  //
19528 // 'splitseg' is one of the two split subsegments. Some subfaces may be non- //
19529 // Delaunay since they're still not bonded to CDT. This routine collect all  //
19530 // such possible subfaces in 'flipqueue'.                                    //
19531 //                                                                           //
19533 
19534 void tetgenmesh::
19535 collectflipedges(point inspoint, face* splitseg, queue* flipqueue)
19536 {
19537   face startsh, spinsh, checksh;
19538   face nextseg;
19539   point pa, pb;
19540 
19541   // Let the dest of splitseg be inspoint.
19542   splitseg->shver = 0;
19543   if (sdest(*splitseg) != inspoint) {
19544     sesymself(*splitseg);
19545   }
19546 #ifdef SELF_CHECK
19547   assert(sdest(*splitseg) == inspoint);
19548 #endif
19549   pa = sorg(*splitseg);
19550   spivot(*splitseg, startsh);
19551   spinsh = startsh;
19552   do {
19553     findedge(&spinsh, pa, inspoint);
19554     senext2(spinsh, checksh);
19555     enqueueflipedge(checksh, flipqueue);
19556     spivotself(spinsh);
19557   } while (spinsh.sh != startsh.sh);
19558 
19559   // Get the next subsegment.
19560   senext(*splitseg, nextseg);
19561   spivotself(nextseg);
19562 #ifdef SELF_CHECK
19563   assert(nextseg.sh != (shellface *) NULL);
19564 #endif
19565 
19566   // Let the org of nextseg be inspoint.
19567   nextseg.shver = 0;
19568   if (sorg(nextseg) != inspoint) {
19569     sesymself(nextseg);
19570   }
19571 #ifdef SELF_CHECK
19572   assert(sorg(nextseg) == inspoint);
19573 #endif
19574   pb = sdest(nextseg);
19575   spivot(nextseg, startsh);
19576   spinsh = startsh;
19577   do {
19578     findedge(&spinsh, inspoint, pb);
19579     senext(spinsh, checksh);
19580     enqueueflipedge(checksh, flipqueue);
19581     spivotself(spinsh);
19582   } while (spinsh.sh != startsh.sh);
19583 }
19584 
19586 //                                                                           //
19587 // perturbrepairencsegs()    Repair all encroached segments.                 //
19588 //                                                                           //
19589 // All encroached segments are stored in 'badsubsegs'.  Each segment will be //
19590 // split by adding a perturbed point near its circumcenter.                  //
19591 //                                                                           //
19593 
19594 void tetgenmesh::perturbrepairencsegs(queue* flipqueue)
19595 {
19596   badface *encloop;
19597   tetrahedron encodedtet;
19598   triface splittet;
19599   face splitsub, symsplitsub;
19600   face splitseg, symsplitseg;
19601   point newpoint, sympoint;
19602   point pa, pb, pc;
19603   enum insertsiteresult success;
19604   enum locateresult loc, symloc;
19605   REAL cent[3], d1, ps, rs;
19606   int i, j;
19607 
19608   // Note that steinerleft == -1 if an unlimited number of Steiner points
19609   //   is allowed.  Loop until 'badsubsegs' is empty.
19610   badsubsegs->traversalinit();
19611   encloop = badfacetraverse(badsubsegs);
19612   while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19613     splitseg = encloop->ss;
19614 #ifdef SELF_CHECK
19615     assert(shell2badface(splitseg) == encloop);
19616 #endif
19617     setshell2badface(splitseg, NULL);
19618     pa = sorg(splitseg);
19619     pb = sdest(splitseg);
19620     if ((pa == encloop->forg) && (pb == encloop->fdest)) {
19621       if (b->verbose > 1) {
19622         printf("  Get seg (%d, %d).\n", pointmark(pa), pointmark(pb));
19623       }
19624       // Create the newpoint.
19625       makepoint(&newpoint);
19626       // Get the circumcenter and radius of ab.
19627       for (i = 0; i < 3; i++) cent[i] = 0.5 * (pa[i] + pb[i]);
19628       d1 = 0.5 * distance(pa, pb);
19629       // Add a random perturbation to newpoint along the vector ab.
19630       ps = randgenerator(d1 * 1.0e-3);
19631       rs = ps / d1;
19632       // Set newpoint (be at the perturbed circumcenter of ab).
19633       for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19634       setpointtype(newpoint, FREESEGVERTEX);
19635       // Set splitseg into the newpoint.
19636       setpoint2sh(newpoint, sencode(splitseg));
19637 
19638       // Is there periodic boundary condition?
19639       if (checkpbcs) {
19640         // Insert points on other segments of incident pbcgroups.
19641         i = shellmark(splitseg) - 1;
19642         for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
19643           makepoint(&sympoint);
19644           symloc = getsegpbcsympoint(newpoint, &splitseg, sympoint,
19645                                      &symsplitseg, segpglist[j]);
19646 #ifdef SELF_CHECK
19647           assert(symloc != OUTSIDE);
19648 #endif
19649           // Note: the symsplitseg and splitseg may be identical, in case
19650           //   when the the splitseg is the axis of the rotational sym.
19651           if ((symloc == ONEDGE) && (symsplitseg.sh != splitseg.sh)) {
19652             setpointtype(sympoint, FREESEGVERTEX);
19653             setpoint2sh(sympoint, sencode(symsplitseg));
19654             // Insert sympoint into DT.
19655             pc = sorg(symsplitseg);
19656             splittet.tet = dummytet;
19657             // Find a good start point to search.
19658             encodedtet = point2tet(pc);
19659             if (encodedtet != (tetrahedron) NULL) {
19660               decode(encodedtet, splittet);
19661               if (isdead(&splittet)) {
19662                 splittet.tet = dummytet;
19663               }
19664             }
19665             // Locate sympoint in DT.  Do exact location.
19666             success = insertsite(sympoint, &splittet, false, flipqueue);
19667 #ifdef SELF_CHECK
19668             assert(success != DUPLICATEPOINT);
19669 #endif
19670             if (success == OUTSIDEPOINT) {
19671               inserthullsite(sympoint, &splittet, flipqueue);
19672             }
19673             if (steinerleft > 0) steinerleft--;
19674             // Let sympoint remember splittet.
19675             setpoint2tet(sympoint, encode(splittet));
19676             // Do flip in DT.
19677             flip(flipqueue, NULL);
19678             // Insert sympoint into F.
19679             symloc = locateseg(sympoint, &symsplitseg);
19680             if (symloc == ONEDGE) {
19681               symsplitseg.shver = 0;
19682               spivot(symsplitseg, symsplitsub);
19683               // sympoint should on the edge of symsplitsub.
19684               splitsubedge(sympoint, &symsplitsub, flipqueue);
19685             } else {
19686               // insertsite() has done the whole job.
19687 #ifdef SELF_CHECK
19688               assert(symloc == ONVERTEX);
19689               assert(checksubfaces);
19690 #endif
19691               // Some edges may need to be flipped.
19692               collectflipedges(sympoint, &symsplitseg, flipqueue);
19693             }
19694             // Do flip in facet.
19695             flipsub(flipqueue);
19696           } else { // if (symloc == ONVERTEX) {
19697             // The symmtric point already exists. It is possible when two
19698             //   pbc group are idebtical. Omit sympoint.
19699             pointdealloc(sympoint);
19700           }
19701         }
19702       }
19703 
19704       // Insert newpoint into DT.
19705       splittet.tet = dummytet;
19706       // Find a good start point to search.
19707       encodedtet = point2tet(pa);
19708       if (encodedtet != (tetrahedron) NULL) {
19709         decode(encodedtet, splittet);
19710         if (isdead(&splittet)) {
19711           splittet.tet = dummytet;
19712         }
19713       }
19714       if (splittet.tet == dummytet) { // Try pb.
19715         encodedtet = point2tet(pb);
19716         if (encodedtet != (tetrahedron) NULL) {
19717           decode(encodedtet, splittet);
19718           if (isdead(&splittet)) {
19719             splittet.tet = dummytet;
19720           }
19721         }
19722       }
19723       // Locate the newpoint in DT.  Do exact location.
19724       success = insertsite(newpoint, &splittet, false, flipqueue);
19725 #ifdef SELF_CHECK
19726       assert(success != DUPLICATEPOINT);
19727 #endif
19728       if (success == OUTSIDEPOINT) {
19729         // A convex hull edge is mssing, and the inserting point lies
19730         //   (slightly) outside the convex hull due to the significant
19731         //   digits lost in the calculation. Enlarge the convex hull.
19732         inserthullsite(newpoint, &splittet, flipqueue);
19733       }
19734       if (steinerleft > 0) steinerleft--;
19735       // Let newpoint remember splittet.
19736       setpoint2tet(newpoint, encode(splittet));
19737       // Do flip in DT.
19738       flip(flipqueue, NULL);
19739       // Insert newpoint into F.
19740       loc = locateseg(newpoint, &splitseg);
19741       if (loc == ONEDGE) {
19742         splitseg.shver = 0;
19743         spivot(splitseg, splitsub);
19744         // newpoint should on the edge of splitsub.
19745         splitsubedge(newpoint, &splitsub, flipqueue);
19746       } else {
19747         // insertsite() has done the whole job.
19748 #ifdef SELF_CHECK
19749         assert(loc == ONVERTEX);
19750         assert(checksubfaces);
19751 #endif
19752         // Some edges may need to be flipped.
19753         collectflipedges(newpoint, &splitseg, flipqueue);
19754       }
19755       // Do flip in facet.
19756       flipsub(flipqueue);
19757     }
19758     // Remove this entry from list.
19759     badfacedealloc(badsubsegs, encloop);
19760     // Get the next encroached segments.
19761     encloop = badfacetraverse(badsubsegs);
19762   }
19763 }
19764 
19766 //                                                                           //
19767 // perturbrepairencsubs()    Repair all encroached subfaces.                 //
19768 //                                                                           //
19769 // All encroached subfaces are stored in 'badsubfaces'. Each subface will be //
19770 // split by adding a perturbed point near its circumcenter. However, if the  //
19771 // point encroaches some segments, it will not be inserted.  Instead, the    //
19772 // encroached segments are split.                                            //
19773 //                                                                           //
19775 
19776 void tetgenmesh::perturbrepairencsubs(list* cavsublist, queue* flipqueue)
19777 {
19778   badface *encloop, *encsubseg;
19779   tetrahedron encodedtet;
19780   triface splittet;
19781   face splitsub, symsplitsub;
19782   face checkseg, symsplitseg;
19783   point newpoint, sympoint;
19784   point pa, pb, pc, pd;
19785   enum insertsiteresult success;
19786   enum locateresult loc, symloc;
19787   REAL cent[3], d1, ps, rs;
19788   bool reject;
19789   int i;
19790 
19791   // Note that steinerleft == -1 if an unlimited number of Steiner points
19792   //   is allowed.  Loop until the list 'badsubfaces' is empty.
19793   while ((badsubfaces->items > 0) && (steinerleft != 0)) {
19794     badsubfaces->traversalinit();
19795     encloop = badfacetraverse(badsubfaces);
19796     while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19797       splitsub = encloop->ss;
19798 #ifdef SELF_CHECK
19799       assert(shell2badface(splitsub) == encloop);
19800 #endif
19801       setshell2badface(splitsub, NULL);
19802       pa = sorg(splitsub);
19803       pb = sdest(splitsub);
19804       pc = sapex(splitsub);
19805       // The subface may be not the same one when it was determined to be
19806       //   encroached.  If its adjacent encroached subface was split, the
19807       //   consequent flips may change it into another subface.
19808       if ((pa == encloop->forg) && (pb == encloop->fdest) &&
19809           (pc == encloop->fapex)) {
19810         if (b->verbose > 1) {
19811           printf("  Get subface (%d, %d, %d).\n", pointmark(pa),
19812                  pointmark(pb), pointmark(pc));
19813         }
19814         // Create the newpoint.
19815         makepoint(&newpoint);
19816         // Get the circumcenter of abc.
19817         circumsphere(pa, pb, pc, NULL, cent, &d1);
19818 #ifdef SELF_CHECK
19819         assert(d1 > 0.0);
19820 #endif
19821         // Add a random perturbation to newpoint along the vector a->cent.
19822         //   This way, the perturbed point still lies in the plane of abc.
19823         ps = randgenerator(d1 * 1.0e-3);
19824         rs = ps / d1;
19825         // Set newpoint (be at the perturbed circumcenter of abc).
19826         for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19827         // Get the abovepoint of the facet.
19828         abovepoint = facetabovepointarray[shellmark(splitsub)];
19829         // Do we need to calculate the abovepoint?
19830         if (abovepoint == (point) NULL) {
19831           getfacetabovepoint(&splitsub);
19832         }
19833         loc = locatesub(newpoint, &splitsub, 1, 0.0);
19834 #ifdef SELF_CHECK
19835         assert(loc != ONVERTEX);
19836 #endif
19837         if (loc != OUTSIDE) {
19838           // Add 'splitsub' into 'cavsublist'.
19839           cavsublist->append(&splitsub);
19840           // Collect all subfaces that encroached by newpoint.
19841           collectcavsubs(newpoint, cavsublist);
19842           // Find if there are encroached segments.
19843           reject = tallencsegsfsubs(newpoint, cavsublist);
19844           // Clear cavsublist for the next use.
19845           cavsublist->clear();
19846         } else {
19847           // newpoint lies outside. splitsub contains the boundary segment.
19848           sspivot(splitsub, checkseg);
19849 #ifdef SELF_CHECK
19850           assert(checkseg.sh != dummysh);
19851 #endif
19852           // Add this segment into list for splitting.
19853           if (b->verbose > 2) {
19854             printf("    Queuing boundary segment (%d, %d).\n",
19855                    pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
19856           }
19857           encsubseg = (badface *) badsubsegs->alloc();
19858           encsubseg->ss = checkseg;
19859           encsubseg->forg = sorg(checkseg);
19860           encsubseg->fdest = sdest(checkseg);
19861           encsubseg->foppo = (point) NULL;
19862           setshell2badface(encsubseg->ss, encsubseg);
19863           // Reject newpoint.
19864           reject = true;
19865         }
19866 
19867         if (!reject) {
19868           // newpoint is going to be inserted.
19869 
19870           // Is there periodic boundary condition?
19871           if (checkpbcs) {
19872             if (shellpbcgroup(splitsub) >= 0) {
19873               // Insert a point on another facet of the pbcgroup.
19874               makepoint(&sympoint);
19875               // Note: 'abovepoint' will be changed.
19876               symloc = getsubpbcsympoint(newpoint, &splitsub, sympoint,
19877                                          &symsplitsub);
19878 #ifdef SELF_CHECK
19879               assert(symloc != ONVERTEX);
19880 #endif
19881               setpoint2pbcpt(newpoint, sympoint);
19882               setpoint2pbcpt(sympoint, newpoint);
19883               setpointtype(sympoint, FREESUBVERTEX);
19884               // setpoint2sh(sympoint, sencode(symsplitsub));
19885               // Insert sympoint into DT.
19886               pd = sorg(symsplitsub);
19887               splittet.tet = dummytet;
19888               // Find a good start point to search.
19889               encodedtet = point2tet(pd);
19890               if (encodedtet != (tetrahedron) NULL) {
19891                 decode(encodedtet, splittet);
19892                 if (isdead(&splittet)) {
19893                   splittet.tet = dummytet;
19894                 }
19895               }
19896               // Locate sympoint in DT.  Do exact location.
19897               success = insertsite(sympoint, &splittet, false, flipqueue);
19898 #ifdef SELF_CHECK
19899               assert(success != DUPLICATEPOINT);
19900 #endif
19901               if (success == OUTSIDEPOINT) {
19902                 inserthullsite(sympoint, &splittet, flipqueue);
19903               }
19904               if (steinerleft > 0) steinerleft--;
19905               // Let sympoint remember splittet.
19906               setpoint2tet(sympoint, encode(splittet));
19907               // Do flip in DT.
19908               flip(flipqueue, NULL);
19909               // Insert sympoint into F.
19910               // getabovepoint(&symsplitsub);
19911               // symloc = locatesub(sympoint, &symsplitsub, 1, 0.0);
19912               if (symloc == ONFACE) {
19913                 splitsubface(sympoint, &symsplitsub, flipqueue);
19914               } else if (symloc == ONEDGE) {
19915                 splitsubedge(sympoint, &symsplitsub, flipqueue);
19916               } else {
19917                 // 'insertsite()' has done the whole job.
19918 #ifdef SELF_CHECK
19919                 assert(symloc == ONVERTEX);
19920                 assert(checksubfaces);
19921 #endif
19922                 // Split subfaces have been flipped.
19923                 flipqueue->clear();
19924               }
19925               // Do flip in facet.
19926               flipsub(flipqueue);
19927             }
19928           }
19929 
19930           // Insert newpoint into DT.
19931           splittet.tet = dummytet;
19932           // Find a good start point to search.
19933           encodedtet = point2tet(pa);
19934           if (encodedtet != (tetrahedron) NULL) {
19935             decode(encodedtet, splittet);
19936             if (isdead(&splittet)) {
19937               splittet.tet = dummytet;
19938             }
19939           }
19940           if (splittet.tet == dummytet) { // Try pb.
19941             encodedtet = point2tet(pb);
19942             if (encodedtet != (tetrahedron) NULL) {
19943               decode(encodedtet, splittet);
19944               if (isdead(&splittet)) {
19945                 splittet.tet = dummytet;
19946               }
19947             }
19948           }
19949           // Locate the newpoint in DT.  Do exact location.
19950           success = insertsite(newpoint, &splittet, false, flipqueue);
19951 #ifdef SELF_CHECK
19952           assert(success != DUPLICATEPOINT);
19953 #endif
19954           if (success == OUTSIDEPOINT) {
19955             inserthullsite(newpoint, &splittet, flipqueue);
19956           }
19957           if (steinerleft > 0) steinerleft--;
19958           // Let newpoint remember splittet.
19959           setpoint2tet(newpoint, encode(splittet));
19960           // Do flip in DT.
19961           flip(flipqueue, NULL);
19962           // Insert newpoint into F.
19963           // if (checkpbcs) {
19964             // 'abovepoint' has been changed.
19965             // getabovepoint(&splitsub);
19966             // loc = locatesub(newpoint, &splitsub, 1, 0.0);
19967           // }
19968           if (loc == ONFACE) {
19969             // Insert the newpoint in facet.
19970             splitsubface(newpoint, &splitsub, flipqueue);
19971           } else if (loc == ONEDGE) {
19972             // Insert the newpoint in facet.
19973             splitsubedge(newpoint, &splitsub, flipqueue);
19974           } else {
19975             // 'insertsite()' has done the whole job.
19976 #ifdef SELF_CHECK
19977             assert(loc == ONVERTEX);
19978             assert(checksubfaces);
19979 #endif
19980             // Split subfaces have been flipped.
19981             flipqueue->clear();
19982           }
19983           // Set the type of the newpoint.
19984           setpointtype(newpoint, FREESUBVERTEX);
19985           // Set splitsub into the newpoint.
19986           // setpoint2sh(newpoint, sencode(splitsub));
19987           // Do flip in the facet.
19988           flipsub(flipqueue);
19989 
19990           // Remove this entry from list.
19991           badfacedealloc(badsubfaces, encloop);
19992         } else {
19993           // newpoint is rejected. Remove it from points.
19994           pointdealloc(newpoint);
19995           // Repair all encroached segments.
19996           perturbrepairencsegs(flipqueue);
19997           // Do not remove 'encloop'. Later it will be tested again.
19998           setshell2badface(encloop->ss, encloop);
19999         }
20000       } else {
20001         // This subface has been changed. Remove this entry from list.
20002         badfacedealloc(badsubfaces, encloop);
20003         // It may be co-circular with its neighbors.
20004         // checksub4cocir(&splitsub, eps, false, true);
20005       }
20006       // Get the next encroached subfaces.
20007       encloop = badfacetraverse(badsubfaces);
20008     }
20009   }
20010 }
20011 
20013 //                                                                           //
20014 // incrperturbvertices()    Remove the local degeneracies in DT.             //
20015 //                                                                           //
20016 // A local degeneracy of a DT D is a set of 5 or more vertices which share a //
20017 // common sphere S and no other vertex of D in S.  D is not unique if it has //
20018 // local degeneracies. This routine removes the local degeneracies from D by //
20019 // inserting break points (as described in reference [2]).                   //
20020 //                                                                           //
20021 // 'eps' is a user-provided error tolerance. It is used to detect whether or //
20022 // not five points are approximate cospherical (evaluated in iscospheric()). //
20023 // Set it to 0.0 to disable it, i.e., only test pure degenerate point set.   //
20024 //                                                                           //
20026 
20027 void tetgenmesh::incrperturbvertices(REAL eps)
20028 {
20029   queue *flipqueue;
20030   list *cavsublist;
20031   long vertcount;
20032 
20033   if (!b->quiet) {
20034     printf("Perturbing vertices.\n");
20035   }
20036 
20037   vertcount = points->items;
20038   // Create a map from points to tets for fastening search.
20039   // makepoint2tetmap();  // This has been done in meshsurface().
20040 
20041   // Initialize working queues, lists.
20042   flipqueue = new queue(sizeof(badface));
20043   cavsublist = new list(sizeof(face), NULL, 256);
20044   // Initialize the pool of encroached subfaces and subsegments.
20045   badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20046   badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20047   // Find all pairs of co-circular subfaces.
20048   tallcocirsubs(eps, true);
20049   if (b->verbose && badsubfaces->items > 0) {
20050     printf("  Removing degenerate subfaces.\n");
20051   }
20052   perturbrepairencsubs(cavsublist, flipqueue);
20053 
20054   if (b->verbose > 0) {
20055     printf("  %ld break points.\n", points->items - vertcount);
20056   }
20057 
20058   delete cavsublist;
20059   delete flipqueue;
20060   delete badsubfaces;
20061   delete badsubsegs;
20062   badsubsegs = (memorypool *) NULL;
20063   badsubfaces = (memorypool *) NULL;
20064 }
20065 
20066 //
20067 // End of vertex perturbation routines
20068 //
20069 
20070 //
20071 // Begin of segment recovery routines
20072 //
20073 
20075 //                                                                           //
20076 // markacutevertices()    Mark acute vertices.                               //
20077 //                                                                           //
20078 // A vertex v is called acute if there are two segments sharing at v forming //
20079 // an acute angle (i.e. smaller than 90 degree).                             //
20080 //                                                                           //
20081 // This routine finds all acute vertices in the PLC and marks them as point- //
20082 // type ACUTEVERTEX. The other vertices of segments which are non-acute will //
20083 // be marked as NACUTEVERTEX.  Vertices which are not endpoints of segments  //
20084 // (such as DUPLICATEDVERTEX, UNUSEDVERTEX, etc) are not infected.           //
20085 //                                                                           //
20086 // NOTE: This routine should be called before Steiner points are introduced. //
20087 // That is, no point has type like FREESEGVERTEX, etc.                       //
20088 //                                                                           //
20090 
20091 void tetgenmesh::markacutevertices(REAL acuteangle)
20092 {
20093   shellface **segsperverlist;
20094   face segloop, nextseg;
20095   point pointloop, edest, eapex;
20096   REAL cosbound, anglearc;
20097   REAL v1[3], v2[3], L, D;
20098   bool isacute;
20099   int *idx2seglist;
20100   int acutecount;
20101   int idx, i, j, k;
20102 
20103   if (b->verbose > 0) {
20104     printf("  Marking acute vertices.\n");
20105   }
20106 
20107   anglearc = acuteangle * PI / 180.0;
20108   cosbound = cos(anglearc);
20109   acutecount = 0;
20110   // Constructing a map from vertex to segments.
20111   makesegmentmap(idx2seglist, segsperverlist);
20112 
20113   // Loop over the set of vertices.
20114   points->traversalinit();
20115   pointloop = pointtraverse();
20116   while (pointloop != (point) NULL) {
20117     idx = pointmark(pointloop) - in->firstnumber;
20118     // Only do test if p is an endpoint of some segments.
20119     if (idx2seglist[idx + 1] > idx2seglist[idx]) {
20120       // Init p to be non-acute.
20121       setpointtype(pointloop, NACUTEVERTEX);
20122       isacute = false;
20123       // Loop through all segments sharing at p.
20124       for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isacute; i++) {
20125         segloop.sh = segsperverlist[i];
20126         // segloop.shver = 0;
20127         if (sorg(segloop) != pointloop) sesymself(segloop);
20128         edest = sdest(segloop);
20129         for (j = i + 1; j < idx2seglist[idx + 1] && !isacute; j++) {
20130           nextseg.sh = segsperverlist[j];
20131           // nextseg.shver = 0;
20132           if (sorg(nextseg) != pointloop) sesymself(nextseg);
20133           eapex = sdest(nextseg);
20134           // Check the angle formed by segs (p, edest) and (p, eapex).
20135           for (k = 0; k < 3; k++) {
20136             v1[k] = edest[k] - pointloop[k];
20137             v2[k] = eapex[k] - pointloop[k];
20138           }
20139           L = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
20140           for (k = 0; k < 3; k++) v1[k] /= L;
20141           L = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
20142           for (k = 0; k < 3; k++) v2[k] /= L;
20143           D = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
20144           // Is D acute?
20145           isacute = (D >= cosbound);
20146         }
20147       }
20148       if (isacute) {
20149         // Mark p to be acute.
20150         setpointtype(pointloop, ACUTEVERTEX);
20151         acutecount++;
20152       }
20153     }
20154     pointloop = pointtraverse();
20155   }
20156 
20157   delete [] idx2seglist;
20158   delete [] segsperverlist;
20159 
20160   if ((b->verbose > 0) && (acutecount > 0)) {
20161     printf("  %d acute vertices.\n", acutecount);
20162   }
20163 }
20164 
20166 //                                                                           //
20167 // finddirection()    Find the first tetrahedron on the path from one point  //
20168 //                    to another.                                            //
20169 //                                                                           //
20170 // Find the tetrahedron that intersects a line segment L (from the origin of //
20171 // 'searchtet' to the point 'tend'), and returns the result in 'searchtet'.  //
20172 // The origin of 'searchtet' does not change, even though the tetrahedron    //
20173 // returned may differ from the one passed in.  This routine is used to find //
20174 // the direction to move in to get from one point to another.                //
20175 //                                                                           //
20176 // The return value notes the location of the line segment L with respect to //
20177 // 'searchtet':                                                              //
20178 //   - Returns RIGHTCOLLINEAR indicates L is collinear with the line segment //
20179 //     from the origin to the destination of 'searchtet'.                    //
20180 //   - Returns LEFTCOLLINEAR indicates L is collinear with the line segment  //
20181 //     from the origin to the apex of 'searchtet'.                           //
20182 //   - Returns TOPCOLLINEAR indicates L is collinear with the line segment   //
20183 //     from the origin to the opposite of 'searchtet'.                       //
20184 //   - Returns ACROSSEDGE indicates L intersects with the line segment from  //
20185 //     the destination to the apex of 'searchtet'.                           //
20186 //   - Returns ACROSSFACE indicates L intersects with the face opposite to   //
20187 //     the origin of 'searchtet'.                                            //
20188 //   - Returns BELOWHULL indicates L crosses outside the mesh domain. This   //
20189 //     can only happen when the domain is non-convex.                        //
20190 //                                                                           //
20191 // NOTE: This routine only works correctly when the mesh is exactly Delaunay.//
20192 //                                                                           //
20193 // If 'maxtetnumber' > 0, stop the searching process if the number of passed //
20194 // tets is larger than it. Return BELOWHULL.                                 //
20195 //                                                                           //
20197 
20198 enum tetgenmesh::finddirectionresult tetgenmesh::
20199 finddirection(triface *searchtet, point tend, long maxtetnumber)
20200 {
20201   triface neightet;
20202   point tstart, tdest, tapex, toppo;
20203   REAL ori1, ori2, ori3;
20204   long tetnumber;
20205 
20206   tstart = org(*searchtet);
20207 #ifdef SELF_CHECK
20208   assert(tstart != tend);
20209 #endif
20210   adjustedgering(*searchtet, CCW);
20211   if (tstart != org(*searchtet)) {
20212     enextself(*searchtet); // For keeping the same origin.
20213   }
20214   tdest = dest(*searchtet);
20215   if (tdest == tend) {
20216     return RIGHTCOLLINEAR;
20217   }
20218   tapex = apex(*searchtet);
20219   if (tapex == tend) {
20220     return LEFTCOLLINEAR;
20221   }
20222 
20223   ori1 = orient3d(tstart, tdest, tapex, tend);
20224   if (ori1 > 0.0) {
20225     // 'tend' is below the face, get the neighbor of this side.
20226     sym(*searchtet, neightet);
20227     if (neightet.tet != dummytet) {
20228       findorg(&neightet, tstart);
20229       adjustedgering(neightet, CCW);
20230       if (org(neightet) != tstart) {
20231         enextself(neightet); // keep the same origin.
20232       }
20233       // Set the changed configuratiuon.
20234       *searchtet = neightet;
20235       ori1 = -1.0;
20236       tdest = dest(*searchtet);
20237       tapex = apex(*searchtet);
20238     } else {
20239       // A hull face. Only possible for a nonconvex mesh.
20240 #ifdef SELF_CHECK
20241       assert(nonconvex);
20242 #endif
20243       return BELOWHULL;
20244     }
20245   }
20246 
20247   // Repeatedly change the 'searchtet', remain 'tstart' be its origin, until
20248   //   find a tetrahedron contains 'tend' or is crossed by the line segment
20249   //   from 'tstart' to 'tend'.
20250   tetnumber = 0l;
20251   while ((maxtetnumber > 0) && (tetnumber <= maxtetnumber)) {
20252     tetnumber++;
20253     toppo = oppo(*searchtet);
20254     if (toppo == tend) {
20255       return TOPCOLLINEAR;
20256     }
20257     ori2 = orient3d(tstart, toppo, tdest, tend);
20258     if (ori2 > 0.0) {
20259       // 'tend' is below the face, get the neighbor at this side.
20260       fnext(*searchtet, neightet);
20261       symself(neightet);
20262       if (neightet.tet != dummytet) {
20263         findorg(&neightet, tstart);
20264         adjustedgering(neightet, CCW);
20265         if (org(neightet) != tstart) {
20266           enextself(neightet); // keep the same origin.
20267         }
20268         // Set the changed configuration.
20269         *searchtet = neightet;
20270         ori1 = -1.0;
20271         tdest = dest(*searchtet);
20272         tapex = apex(*searchtet);
20273         // Continue the search from the changed 'searchtet'.
20274         continue;
20275       } else {
20276         // A hull face. Only possible for a nonconvex mesh.
20277 #ifdef SELF_CHECK
20278         assert(nonconvex);
20279 #endif
20280         return BELOWHULL;
20281       }
20282     }
20283     ori3 = orient3d(tapex, toppo, tstart, tend);
20284     if (ori3 > 0.0) {
20285       // 'tend' is below the face, get the neighbor at this side.
20286       enext2fnext(*searchtet, neightet);
20287       symself(neightet);
20288       if (neightet.tet != dummytet) {
20289         findorg(&neightet, tstart);
20290         adjustedgering(neightet, CCW);
20291         if (org(neightet) != tstart) {
20292           enextself(neightet); // keep the same origin.
20293         }
20294         // Set the changed configuration.
20295         *searchtet = neightet;
20296         ori1 = -1.0;
20297         tdest = dest(*searchtet);
20298         tapex = apex(*searchtet);
20299         // Continue the search from the changed 'searchtet'.
20300         continue;
20301       } else {
20302         // A hull face. Only possible for a nonconvex mesh.
20303 #ifdef SELF_CHECK
20304         assert(nonconvex);
20305 #endif
20306         return BELOWHULL;
20307       }
20308     }
20309     // Now 'ori1', 'ori2' and 'ori3' are possible be 0.0 or all < 0.0;
20310     if (ori1 < 0.0) {
20311       // Possible cases are: ACROSSFACE, ACROSSEDGE, TOPCOLLINEAR.
20312       if (ori2 < 0.0) {
20313         if (ori3 < 0.0) {
20314           return ACROSSFACE;
20315         } else { // ori3 == 0.0;
20316           // Cross edge (apex, oppo)
20317           enext2fnextself(*searchtet);
20318           esymself(*searchtet); // org(*searchtet) == tstart;
20319           return ACROSSEDGE;
20320         }
20321       } else { // ori2 == 0.0;
20322         if (ori3 < 0.0) {
20323           // Cross edge (dest, oppo)
20324           fnextself(*searchtet);
20325           esymself(*searchtet);
20326           enextself(*searchtet); // org(*searchtet) == tstart;
20327           return ACROSSEDGE;
20328         } else { // ori3 == 0.0;
20329           // Collinear with edge (org, oppo)
20330           return TOPCOLLINEAR;
20331         }
20332       }
20333     } else { // ori1 == 0.0;
20334       // Possible cases are: RIGHTCOLLINEAR, LEFTCOLLINEAR, ACROSSEDGE.
20335       if (ori2 < 0.0) {
20336         if (ori3 < 0.0) {
20337           // Cross edge (tdest, tapex)
20338           return ACROSSEDGE;
20339         } else { // ori3 == 0.0
20340           // Collinear with edge (torg, tapex)
20341           return LEFTCOLLINEAR;
20342         }
20343       } else { // ori2 == 0.0;
20344 #ifdef SELF_CHECK
20345         assert(ori3 != 0.0);
20346 #endif
20347         // Collinear with edge (torg, tdest)
20348         return RIGHTCOLLINEAR;
20349       }
20350     }
20351   }
20352   // Loop breakout. It may happen when the mesh is non-Delaunay.
20353   return BELOWHULL;
20354 }
20355 
20357 //                                                                           //
20358 // getsearchtet()    Find a tetrahedron whose origin is either 'p1' or 'p2'. //
20359 //                                                                           //
20360 // On return, the origin of 'searchtet' is either 'p1' or 'p2',  and 'tend'  //
20361 // returns the other point.  'searchtet' serves as the starting tetrahedron  //
20362 // for searching of the line segment from 'p1' to 'p2' or vice versa.        //
20363 //                                                                           //
20365 
20366 void tetgenmesh::getsearchtet(point p1, point p2, triface* searchtet,
20367   point* tend)
20368 {
20369   tetrahedron encodedtet1, encodedtet2;
20370 
20371   // Is there a valid handle provided by the user?
20372   if ((searchtet->tet != (tetrahedron *) NULL) && !isdead(searchtet)) {
20373     // Find which endpoint the handle holds.
20374     if (findorg(searchtet, p1)) {
20375       *tend = p2;
20376       return;
20377     } else {
20378       if (findorg(searchtet, p2)) {
20379         *tend = p1;
20380         return;
20381       }
20382     }
20383   }
20384   // If not, search the tet handle stored in 'p1' or 'p2'.
20385   *tend = (point) NULL;
20386   encodedtet1 = point2tet(p1);
20387   encodedtet2 = point2tet(p2);
20388   if (encodedtet1 != (tetrahedron) NULL) {
20389     decode(encodedtet1, *searchtet);
20390     // Be careful, here 'searchtet' may be dead.
20391     if (findorg(searchtet, p1)) {
20392       *tend = p2;
20393     }
20394   } else if (encodedtet2 != (tetrahedron) NULL) {
20395     decode(encodedtet2, *searchtet);
20396     // Be careful, here 'searchtet' may be dead.
20397     if (findorg(searchtet, p2)) {
20398       *tend = p1;
20399     }
20400   }
20401   // If still not, perform a full point location.  The starting tet is
20402   //   chosen as follows: Use the handle stored in 'p1' or 'p2' if it is
20403   //   alive; otherwise, start from a tet on the convex hull.
20404   if (*tend == (point) NULL) {
20405     if (encodedtet1 != (tetrahedron) NULL) {
20406       decode(encodedtet1, *searchtet);
20407       // Be careful, here 'searchtet' may be dead.
20408     }
20409     if (isdead(searchtet)) {
20410       if (encodedtet2 != (tetrahedron) NULL) {
20411         decode(encodedtet2, *searchtet);
20412         // Be careful, here 'searchtet' may be dead.
20413       }
20414       if (isdead(searchtet)) {
20415         searchtet->tet = dummytet;
20416         searchtet->loc = 0;
20417         symself(*searchtet);
20418       }
20419 #ifdef SELF_CHECK
20420       assert(!isdead(searchtet));
20421 #endif
20422     }
20423     if (locate(p1, searchtet) != ONVERTEX) {
20424       printf("Internal error in getsearchtet():  Failed to locate point\n");
20425       internalerror();
20426     }
20427     // Remember this handle in 'p1' to enhance the search speed.
20428     setpoint2tet(p1, encode(*searchtet));
20429     *tend = p2;
20430   }
20431 }
20432 
20434 //                                                                           //
20435 // isedgeencroached()    Check whether or not a subsegment is encroached.    //
20436 //                                                                           //
20437 // A segment with endpoints 'p1' and 'p2' is encroached by the point 'testpt'//
20438 // if it lies in the diametral sphere of this segment.  The degenerate case  //
20439 // that 'testpt' lies on the sphere is treated as encroached if 'degflag' is //
20440 // set to be TRUE.                                                           //
20441 //                                                                           //
20443 
20444 bool tetgenmesh::isedgeencroached(point p1, point p2, point testpt,
20445   bool degflag)
20446 {
20447   REAL dotproduct;
20448 
20449   // Check if the segment is facing an angle larger than 90 degree?
20450   dotproduct = (p1[0] - testpt[0]) * (p2[0] - testpt[0])
20451              + (p1[1] - testpt[1]) * (p2[1] - testpt[1])
20452              + (p1[2] - testpt[2]) * (p2[2] - testpt[2]);
20453   if (dotproduct < 0) {
20454     return true;
20455   } else if (dotproduct == 0 && degflag) {
20456     return true;
20457   } else {
20458     return false;
20459   }
20460 }
20461 
20463 //                                                                           //
20464 // scoutrefpoint()    Search the reference point of a missing segment.       //
20465 //                                                                           //
20466 // A segment S is missing in current Delaunay tetrahedralization DT and will //
20467 // be split by inserting a point V in it.  The two end points of S are the   //
20468 // origin of 'searchtet' and 'tend'. And we know that S is crossing the face //
20469 // of 'searchtet' opposite to its origin (may be intersecting with the edge  //
20470 // from the destination to the apex of the 'searchtet').  The search of P is //
20471 // completed by walking through all faces of DT across by S.                 //
20472 //                                                                           //
20473 // Warning:  This routine is correct when the tetrahedralization is Delaunay //
20474 // and convex. Otherwise, the search loop may not terminate.                 //
20475 //                                                                           //
20477 
20478 tetgenmesh::point tetgenmesh::scoutrefpoint(triface* searchtet, point tend)
20479 {
20480   triface checkface;
20481   point tstart, testpt, refpoint;
20482   REAL cent[3], radius, largest;
20483   REAL ahead;
20484   bool ncollinear;
20485   int sides;
20486 
20487   if (b->verbose > 2) {
20488     printf("  Scout the reference point of segment (%d, %d).\n",
20489            pointmark(org(*searchtet)), pointmark(tend));
20490   }
20491 
20492   tstart = org(*searchtet);
20493   refpoint = (point) NULL;
20494   largest = 0; // avoid compile warning.
20495 
20496   // Check the three vertices of the crossing face.
20497   testpt = apex(*searchtet);
20498   if (isedgeencroached(tstart, tend, testpt, true)) {
20499     ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20500 #ifdef SELF_CHECK
20501     assert(ncollinear);
20502 #endif
20503     refpoint = testpt;
20504     largest = radius;
20505   }
20506   testpt = dest(*searchtet);
20507   if (isedgeencroached(tstart, tend, testpt, true)) {
20508     ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20509 #ifdef SELF_CHECK
20510     assert(ncollinear);
20511 #endif
20512     if (refpoint == (point) NULL) {
20513       refpoint = testpt;
20514       largest = radius;
20515     } else {
20516       if (radius > largest) {
20517         refpoint = testpt;
20518         largest = radius;
20519       }
20520     }
20521   }
20522   testpt = oppo(*searchtet);
20523   if (isedgeencroached(tstart, tend, testpt, true)) {
20524     ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20525 #ifdef SELF_CHECK
20526     assert(ncollinear);
20527 #endif
20528     if (refpoint == (point) NULL) {
20529       refpoint = testpt;
20530       largest = radius;
20531     } else {
20532       if (radius > largest) {
20533         refpoint = testpt;
20534         largest = radius;
20535       }
20536     }
20537   }
20538   // Check the opposite vertex of the neighboring tet in case the segment
20539   //   crosses the edge (leftpoint, rightpoint) of the crossing face.
20540   sym(*searchtet, checkface);
20541   if (checkface.tet != dummytet) {
20542     testpt = oppo(checkface);
20543     if (isedgeencroached(tstart, tend, testpt, true)) {
20544       ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20545 #ifdef SELF_CHECK
20546       assert(ncollinear);
20547 #endif
20548       if (refpoint == (point) NULL) {
20549         refpoint = testpt;
20550         largest = radius;
20551       } else {
20552         if (radius > largest) {
20553           refpoint = testpt;
20554           largest = radius;
20555         }
20556       }
20557     }
20558   }
20559 
20560   // Walk through all crossing faces.
20561   enextfnext(*searchtet, checkface);
20562   sym(checkface, *searchtet);
20563   while (true) {
20564     // Check if we are reaching the boundary of the triangulation.
20565 #ifdef SELF_CHECK
20566     assert(searchtet->tet != dummytet);
20567 #endif
20568     // Search for an adjoining tetrahedron we can walk through.
20569     searchtet->ver = 0;
20570     // 'testpt' is the shared vertex for the following orientation tests.
20571     testpt = oppo(*searchtet);
20572     if (testpt == tend) {
20573       // The searching is finished.
20574       break;
20575     } else {
20576       // 'testpt' may encroach the segment.
20577       if ((testpt != tstart) && (testpt != refpoint)) {
20578         if (isedgeencroached(tstart, tend, testpt, true)) {
20579           ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20580           if (!ncollinear) {
20581             // 'testpt' is collinear with the segment. It may happen when a
20582             //   set of collinear and continuous segments is defined by two
20583             //   extreme endpoints.  In this case, we should choose 'testpt'
20584             //   as the splitting point immediately.  No new point should be
20585             //   created.
20586             refpoint = testpt;
20587             break;
20588           }
20589           if (refpoint == (point) NULL) {
20590             refpoint = testpt;
20591             largest = radius;
20592           } else {
20593             if (radius > largest) {
20594               refpoint = testpt;
20595               largest = radius;
20596             }
20597           }
20598         }
20599       }
20600     }
20601     // Check three side-faces of 'searchtet' to find the one through
20602     //   which we can walk next.
20603     for (sides = 0; sides < 3; sides++) {
20604       fnext(*searchtet, checkface);
20605       ahead = orient3d(org(checkface), dest(checkface), testpt, tend);
20606       if (ahead < 0.0) {
20607         // We can walk through this face and continue the searching.
20608         sym(checkface, *searchtet);
20609         break;
20610       }
20611       enextself(*searchtet);
20612     }
20613 #ifdef SELF_CHECK
20614     assert (sides < 3);
20615 #endif
20616   }
20617 
20618 #ifdef SELF_CHECK
20619   assert(refpoint != (point) NULL);
20620 #endif
20621   return refpoint;
20622 }
20623 
20625 //                                                                           //
20626 // getsegmentorigin()    Return the origin of the (unsplit) segment.         //
20627 //                                                                           //
20628 // After a segment (or a subsegment) is split. Two resulting subsegments are //
20629 // connecting each other through the pointers saved in their data fields.    //
20630 // With these pointers, the whole (unsplit) segment can be found. 'splitseg' //
20631 // may be a split subsegment.  Returns the origin of the unsplit segment.    //
20632 //                                                                           //
20634 
20635 tetgenmesh::point tetgenmesh::getsegmentorigin(face* splitseg)
20636 {
20637   face workseg;
20638   point farorg;
20639 
20640   farorg = sorg(*splitseg);
20641   if ((pointtype(farorg) != ACUTEVERTEX) &&
20642       (pointtype(farorg) != NACUTEVERTEX)) {
20643     workseg = *splitseg;
20644     do {
20645       senext2self(workseg);
20646       spivotself(workseg);
20647       if (workseg.sh != dummysh) {
20648         workseg.shver = 0;  // It's a subsegment.
20649         if (sdest(workseg) != farorg) {
20650           sesymself(workseg);
20651 #ifdef SELF_CHECK
20652           assert(sdest(workseg) == farorg);
20653 #endif
20654         }
20655         farorg = sorg(workseg);
20656         if ((pointtype(farorg) == ACUTEVERTEX) ||
20657             (pointtype(farorg) == NACUTEVERTEX)) break;
20658       }
20659     } while (workseg.sh != dummysh);
20660   }
20661 #ifdef SELF_CHECK
20662   assert((pointtype(farorg) == ACUTEVERTEX) ||
20663          (pointtype(farorg) == NACUTEVERTEX));
20664 #endif
20665   return farorg;
20666 }
20667 
20669 //                                                                           //
20670 // getsplitpoint()    Get a point for splitting a segment.                   //
20671 //                                                                           //
20672 // 'splitseg' is the segment will be split. 'refpoint' is a reference point  //
20673 // for splitting this segment. Moreover, it should not collinear with the    //
20674 // splitting segment. (The collinear case will be detected by iscollinear()  //
20675 // before entering this routine.)  The calculation of the splitting point is //
20676 // governed by three rules introduced in my paper.                           //
20677 //                                                                           //
20678 // After the position is calculated, a new point is created at this location.//
20679 // The new point has one of the two pointtypes: FREESEGVERTEX indicating it  //
20680 // is an inserting vertex on segment, and NACUTEVERTEX indicating it is an   //
20681 // endpoint of a segment which original has type-3 now becomes type-2.       //
20682 //                                                                           //
20684 
20685 tetgenmesh::point tetgenmesh::getsplitpoint(face* splitseg, point refpoint)
20686 {
20687   point splitpoint;
20688   point farorg, fardest;
20689   point ei, ej, ek, c;
20690   REAL v[3], r, split;
20691   REAL d1, d2, ps, rs;
20692   bool acuteorg, acutedest;
20693   int stype, rule;
20694   int i;
20695 
20696   // First determine the type of the segment (type-1, type-2, or type-3).
20697   farorg = getsegmentorigin(splitseg);
20698   acuteorg = (pointtype(farorg) == ACUTEVERTEX);
20699   sesymself(*splitseg);
20700   fardest = getsegmentorigin(splitseg);
20701   acutedest = (pointtype(fardest) == ACUTEVERTEX);
20702   sesymself(*splitseg);
20703 
20704   ek = (point) NULL; // avoid a compilation warning.
20705 
20706   if (acuteorg) {
20707     if (acutedest) {
20708       stype = 3;
20709     } else {
20710       stype = 2;
20711       ek = farorg;
20712     }
20713   } else {
20714     if (acutedest) {
20715       stype = 2;
20716       // Adjust splitseg, so that its origin is acute.
20717       sesymself(*splitseg);
20718       ek = fardest;
20719     } else {
20720       stype = 1;
20721     }
20722   }
20723   ei = sorg(*splitseg);
20724   ej = sdest(*splitseg);
20725 
20726   if (b->verbose > 1) {
20727     printf("  Splitting segment (%d, %d) type-%d with refpoint %d.\n",
20728            pointmark(ei), pointmark(ej), stype, pointmark(refpoint));
20729   }
20730 
20731   if (stype == 1 || stype == 3) {
20732     // Use rule-1.
20733     REAL eij, eip, ejp;
20734     eij = distance(ei, ej);
20735     eip = distance(ei, refpoint);
20736     ejp = distance(ej, refpoint);
20737     if ((eip < ejp) && (eip < 0.5 * eij)) {
20738       c = ei;
20739       r = eip;
20740     } else if ((eip > ejp) && (ejp < 0.5 * eij)) {
20741       c = ej;
20742       ej = ei;
20743       r = ejp;
20744     } else {
20745       c = ei;
20746       r = 0.5 * eij;
20747     }
20748     split = r / eij;
20749     for (i = 0; i < 3; i++) {
20750       v[i] = c[i] + split * (ej[i] - c[i]);
20751     }
20752     rule = 1;
20753   } else {
20754     // Use rule-2 or rule-3.
20755     REAL eki, ekj, ekp, evj, evp, eiv;
20756     c = ek;
20757     eki = distance(ek, ei);  // eki may equal zero.
20758     ekj = distance(ek, ej);
20759     ekp = distance(ek, refpoint);
20760     // Calculate v (the going to split position between ei, ej).
20761     r = ekp;
20762     // Check the validity of the position.
20763     if (!(eki < r && r < ekj)) {
20764       printf("Error:  Invalid PLC.\n");
20765       printf("  Hint:  Use -d switch to check it.\n");
20766       terminatetetgen(1);
20767     }
20768     split = r / ekj;
20769     for (i = 0; i < 3; i++) {
20770       v[i] = c[i] + split * (ej[i] - c[i]);
20771     }
20772     rule = 2;
20773     evj = ekj - r; // distance(v, ej);
20774     evp = distance(v, refpoint);
20775     if (evj < evp) {
20776       // v is rejected, use rule-3.
20777       eiv = distance(ei, v);
20778       if (evp <= 0.5 * eiv) {
20779         r = eki + eiv - evp;
20780       } else {
20781         r = eki + 0.5 * eiv;
20782       }
20783 #ifdef SELF_CHECK
20784       assert(eki < r && r < ekj);
20785 #endif
20786       split = r / ekj;
20787       for (i = 0; i < 3; i++) {
20788         v[i] = c[i] + split * (ej[i] - c[i]);
20789       }
20790       if (b->verbose > 1) {
20791         printf("    Using rule-3.\n");
20792       }
20793       rule = 3;
20794     }
20795   }
20796 
20797   // Accumulate the corresponding counters.
20798   if (rule == 1) r1count++;
20799   else if (rule == 2) r2count++;
20800   else if (rule == 3) r3count++;
20801 
20802   if (b->verbose > 1) {
20803     if (stype == 2) {
20804       printf("    Split = %.12g.\n", distance(ei, v) / distance(ei, ej));
20805     } else {
20806       printf("    Split = %.12g.\n", distance(c, v) / distance(c, ej));
20807     }
20808   }
20809 
20810   // Create the newpoint.
20811   makepoint(&splitpoint);
20812   // Add a random perturbation on splitpoint.
20813   d1 = distance(c, v);
20814   d2 = distance(refpoint, v);
20815   if (stype == 1 || stype == 3) {
20816     ps = randgenerator(d1 * 1.0e-3);
20817   } else {
20818     // For type-2 segment, add a smaller perturbation.
20819     // ps = randgenerator(d1 * 1.0e-5);
20820     // REAL d2 = distance(refpoint, v);
20821     ps = randgenerator(d2 * 1.0e-5);
20822   }
20823   rs = ps / d1;
20824   // Perturb splitpoint away from c.
20825   for (i = 0; i < 3; i++) {
20826     splitpoint[i] = c[i] + (1.0 + rs) * (v[i] - c[i]);
20827   }
20828   // for (i = 0; i < in->numberofpointattributes; i++) {
20829   //   splitpoint[i + 3] = c[i + 3] + (split + rs) * (ej[i + 3] - c[i + 3]);
20830   // }
20831   if (stype == 3) {
20832     // Change a type-3 segment into two type-2 segments.
20833     setpointtype(splitpoint, NACUTEVERTEX);
20834   } else {
20835     // Set it's type be FREESEGVERTEX.
20836     setpointtype(splitpoint, FREESEGVERTEX);
20837   }
20838   setpoint2sh(splitpoint, sencode(*splitseg));
20839 
20840   return splitpoint;
20841 }
20842 
20844 //                                                                           //
20845 // insertsegment()    Insert segment into DT. Queue it if it does not exist. //
20846 //                                                                           //
20848 
20849 bool tetgenmesh::insertsegment(face *insseg, list *misseglist)
20850 {
20851   badface *misseg;
20852   triface searchtet, spintet;
20853   point tend, checkpoint;
20854   point p1, p2;
20855   enum finddirectionresult collinear;
20856   int hitbdry;
20857 
20858   // Search segment ab in DT.
20859   p1 = (point) insseg->sh[3];
20860   p2 = (point) insseg->sh[4];
20861   getsearchtet(p1, p2, &searchtet, &tend);
20862   collinear = finddirection(&searchtet, tend, tetrahedrons->items);
20863   if (collinear == LEFTCOLLINEAR) {
20864     checkpoint = apex(searchtet);
20865     enext2self(searchtet);
20866     esymself(searchtet);
20867   } else if (collinear == RIGHTCOLLINEAR) {
20868     checkpoint = dest(searchtet);
20869   } else if (collinear == TOPCOLLINEAR) {
20870     checkpoint = oppo(searchtet);
20871     fnextself(searchtet);
20872     enext2self(searchtet);
20873     esymself(searchtet);
20874   } else {
20875     // assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
20876     checkpoint = (point) NULL;
20877   }
20878   if (checkpoint == tend) {
20879     // Segment exist. Bond it to all tets containing it.
20880     hitbdry = 0;
20881     adjustedgering(searchtet, CCW);
20882     fnextself(searchtet);
20883     spintet = searchtet;
20884     do {
20885       tssbond1(spintet, *insseg);
20886       if (!fnextself(spintet)) {
20887         hitbdry++;
20888         if (hitbdry < 2) {
20889           esym(searchtet, spintet);
20890           if (!fnextself(spintet)) {
20891             hitbdry++;
20892           }
20893         }
20894       }
20895     } while ((apex(spintet) != apex(searchtet)) && (hitbdry < 2));
20896     return true;
20897   } else {
20898     // Segment is missing.
20899     if (misseglist != (list *) NULL) {
20900       if (b->verbose > 2) {
20901         printf("    Queuing missing segment (%d, %d).\n", pointmark(p1),
20902                pointmark(p2));
20903       }
20904       misseg = (badface *) misseglist->append(NULL);
20905       misseg->ss = *insseg;
20906       misseg->forg = p1;
20907       misseg->fdest = p2;
20908       misseg->foppo = (point) NULL; // Not used.
20909       // setshell2badface(misseg->ss, misseg);
20910     }
20911     return false;
20912   }
20913 }
20914 
20916 //                                                                           //
20917 // tallmissegs()    Find and queue all missing segments in DT.               //
20918 //                                                                           //
20920 
20921 void tetgenmesh::tallmissegs(list *misseglist)
20922 {
20923   face segloop;
20924 
20925   if (b->verbose) {
20926     printf("  Queuing missing segments.\n");
20927   }
20928 
20929   subsegs->traversalinit();
20930   segloop.sh = shellfacetraverse(subsegs);
20931   while (segloop.sh != (shellface *) NULL) {
20932     insertsegment(&segloop, misseglist);
20933     segloop.sh = shellfacetraverse(subsegs);
20934   }
20935 }
20936 
20938 //                                                                           //
20939 // delaunizesegments()    Split segments repeatedly until they appear in a   //
20940 //                        Delaunay tetrahedralization.                       //
20941 //                                                                           //
20942 // Given a PLC X, which has a set V of vertices and a set of segments. Start //
20943 // from a Delaunay tetrahedralization D of V, this routine recovers segments //
20944 // of X in D by incrementally inserting points on missing segments, updating //
20945 // D with the newly inserted points into D', which remains to be a Delaunay  //
20946 // tetrahedralization and respects the segments of X. Hence, each segment of //
20947 // X appears as a union of edges in D'.                                      //
20948 //                                                                           //
20949 // This routine dynamically maintains two meshes, one is DT, another is the  //
20950 // surface mesh F of X.  DT and F have exactly the same vertices.  They are  //
20951 // updated simultaneously with the newly inserted points.                    //
20952 //                                                                           //
20953 // Missing segments are found by looping the set S of segments, checking the //
20954 // existence of each segment in DT.  Once a segment is found missing in DT,  //
20955 // it is split into two subsegments by inserting a point into both DT and F, //
20956 // and S is updated accordingly.  However, the inserted point may cause some //
20957 // other existing segments be non-Delaunay,  hence are missing from the DT.  //
20958 // In order to force all segments to appear in DT, we have to loop S again   //
20959 // after some segments are split. (A little ugly method)  Use a handle to    //
20960 // remember the last segment be split in one loop, hence all segments after  //
20961 // it are existing and need not be checked.                                  //
20962 //                                                                           //
20963 // In priciple, a segment on the convex hull should exist in DT. However, if //
20964 // there are four coplanar points on the convex hull, and the DT only can    //
20965 // contain one diagonal edge which is unfortunately not the segment, then it //
20966 // is missing. During the recovery of the segment, it is possible that the   //
20967 // calculated inserting point for recovering this convex hull segment is not //
20968 // exact enough and lies (slightly) outside the DT. In order to insert the   //
20969 // point, we enlarge the convex hull of the DT, so it can contain the point  //
20970 // and remains convex.  'inserthullsite()' is called for this case.          //
20971 //                                                                           //
20973 
20974 void tetgenmesh::delaunizesegments()
20975 {
20976   list *misseglist;
20977   queue *flipqueue;
20978   badface *misloop;
20979   tetrahedron encodedtet;
20980   triface searchtet, splittet;
20981   face splitsh, symsplitsub;
20982   face segloop, symsplitseg;
20983   point refpoint, splitpoint, sympoint;
20984   point tend, checkpoint;
20985   point p1, p2, pa;
20986   enum finddirectionresult collinear;
20987   enum insertsiteresult success;
20988   enum locateresult symloc;
20989   bool coll;
20990   long vertcount;
20991   int i, j;
20992 
20993   if (!b->quiet) {
20994     printf("Delaunizing segments.\n");
20995   }
20996 
20997   // Construct a map from points to tets for speeding point location.
20998   makepoint2tetmap();
20999   // Initialize a flipqueue.
21000   flipqueue = new queue(sizeof(badface));
21001   // Initialize the pool of missing segments.
21002   misseglist = new list(sizeof(badface), NULL, SUBPERBLOCK);
21003   // Looking for missing segments.
21004   tallmissegs(misseglist);
21005   // The DT contains segments now.
21006   checksubsegs = 1;
21007   // Remember the current number of points.
21008   vertcount = points->items;
21009   // Initialize the counters.
21010   r1count = r2count = r3count = 0l;
21011 
21012   // Loop until 'misseglist' is empty.
21013   while (misseglist->items > 0) {
21014     // Randomly pick a missing segment to recover.
21015     i = randomnation(misseglist->items);
21016     misloop = (badface *)(* misseglist)[i];
21017     segloop = misloop->ss;
21018     // Fill the "hole" in the list by filling the last one.
21019     *misloop = *(badface *)(* misseglist)[misseglist->items - 1];
21020     misseglist->items--;
21021     // Now recover the segment.
21022       p1 = (point) segloop.sh[3];
21023       p2 = (point) segloop.sh[4];
21024       if (b->verbose > 1) {
21025         printf("  Recover segment (%d, %d).\n", pointmark(p1), pointmark(p2));
21026       }
21027       getsearchtet(p1, p2, &searchtet, &tend);
21028       collinear = finddirection(&searchtet, tend, tetrahedrons->items);
21029       if (collinear == LEFTCOLLINEAR) {
21030         checkpoint = apex(searchtet);
21031       } else if (collinear == RIGHTCOLLINEAR) {
21032         checkpoint = dest(searchtet);
21033       } else if (collinear == TOPCOLLINEAR) {
21034         checkpoint = oppo(searchtet);
21035       } else {
21036 #ifdef SELF_CHECK
21037         assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
21038 #endif
21039         checkpoint = (point) NULL;
21040       }
21041       if (checkpoint != tend) {
21042         // ab is missing.
21043         splitpoint = (point) NULL;
21044         if (checkpoint != (point) NULL) {
21045           // An existing point c is found on the segment. It can happen when
21046           //   ab is defined by a long segment with c inside it. Use c to
21047           //   split ab. No new point is created.
21048           splitpoint = checkpoint;
21049           if (pointtype(checkpoint) == FREEVOLVERTEX) {
21050             // c is not a segment vertex yet. It becomes NACUTEVERTEX.
21051             setpointtype(splitpoint, NACUTEVERTEX);
21052           } else if (pointtype(checkpoint) == ACUTEVERTEX) {
21053             // c is an acute vertex. The definition of PLC is wrong.
21054           } else if (pointtype(checkpoint) == NACUTEVERTEX) {
21055             // c is an nonacute vertex. The definition of PLC is wrong.
21056           } else {
21057             // assert(0);
21058           }
21059         } else {
21060           // Find a reference point p of ab.
21061           refpoint = scoutrefpoint(&searchtet, tend);
21062           if (pointtype(refpoint) == FREEVOLVERTEX) {
21063             // p is an input point, check if it is nearly collinear with ab.
21064             coll = iscollinear(p1, p2, refpoint, b->epsilon);
21065             if (coll) {
21066               // a, b, and p are collinear. We insert p into ab. p becomes
21067               //   a segment vertex with type NACUTEVERTEX.
21068               splitpoint = refpoint;
21069               setpointtype(splitpoint, NACUTEVERTEX);
21070             }
21071           }
21072           if (splitpoint == (point) NULL) {
21073             // Calculate a split point v using rule 1, or 2, or 3.
21074             splitpoint = getsplitpoint(&segloop, refpoint);
21075 
21076             // Is there periodic boundary conditions?
21077             if (checkpbcs) {
21078               // Yes! Insert points on other segments of incident pbcgroups.
21079               i = shellmark(segloop) - 1;
21080               for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
21081                 makepoint(&sympoint);
21082                 symloc = getsegpbcsympoint(splitpoint, &segloop, sympoint,
21083                                            &symsplitseg, segpglist[j]);
21084 #ifdef SELF_CHECK
21085                 assert(symloc != OUTSIDE);
21086 #endif
21087                 if ((symloc == ONEDGE) && (symsplitseg.sh != segloop.sh)) {
21088 #ifdef SELF_CHECK
21089                   assert(symsplitseg.sh != dummysh);
21090 #endif
21091                   setpointtype(sympoint, FREESEGVERTEX);
21092                   setpoint2sh(sympoint, sencode(symsplitseg));
21093                   // Insert sympoint into DT.
21094                   pa = sorg(symsplitseg);
21095                   splittet.tet = dummytet;
21096                   // Find a good start point to search.
21097                   encodedtet = point2tet(pa);
21098                   if (encodedtet != (tetrahedron) NULL) {
21099                     decode(encodedtet, splittet);
21100                     if (isdead(&splittet)) {
21101                       splittet.tet = dummytet;
21102                     }
21103                   }
21104                   // Locate sympoint in DT.  Do exact location.
21105                   success = insertsite(sympoint, &splittet, false, flipqueue);
21106 #ifdef SELF_CHECK
21107                   assert(success != DUPLICATEPOINT);
21108 #endif
21109                   if (success == OUTSIDEPOINT) {
21110                     inserthullsite(sympoint, &splittet, flipqueue);
21111                   }
21112                   if (steinerleft > 0) steinerleft--;
21113                   // Let sympoint remember splittet.
21114                   setpoint2tet(sympoint, encode(splittet));
21115                   // Do flip in DT.
21116                   lawson(misseglist, flipqueue);
21117                   // Insert sympoint into F.
21118                   symsplitseg.shver = 0;
21119                   spivot(symsplitseg, symsplitsub);
21120                   // sympoint should on the edge of symsplitsub.
21121                   splitsubedge(sympoint, &symsplitsub, flipqueue);
21122                   // Do flip in facet.
21123                   flipsub(flipqueue);
21124                   // Insert the two subsegments.
21125                   symsplitseg.shver = 0;
21126                   insertsegment(&symsplitseg, misseglist);
21127                   senextself(symsplitseg);
21128                   spivotself(symsplitseg);
21129                   symsplitseg.shver = 0;
21130                   insertsegment(&symsplitseg, misseglist);
21131                 } else { // if (symloc == ONVERTEX) {
21132                   // The sympoint already exists. It is possible when two
21133                   //   pbc groups are exactly the same. Omit this point.
21134                   pointdealloc(sympoint);
21135                 }
21136               }
21137             }
21138 
21139             // Insert 'splitpoint' into DT.
21140             if (isdead(&searchtet)) searchtet.tet = dummytet;
21141             success = insertsite(splitpoint, &searchtet, false, flipqueue);
21142             if (success == OUTSIDEPOINT) {
21143               // A convex hull edge is missing, and the inserting point lies
21144               //   (slightly) outside the convex hull due to the significant
21145               //   digits lost in the calculation. Enlarge the convex hull.
21146               inserthullsite(splitpoint, &searchtet, flipqueue);
21147             }
21148             if (steinerleft > 0) steinerleft--;
21149             // Remember a handle in 'splitpoint' to enhance the speed of
21150             //   consequent point location.
21151             setpoint2tet(splitpoint, encode(searchtet));
21152             // Maintain Delaunayness in DT.
21153             lawson(misseglist, flipqueue);
21154           }
21155         }
21156         // Insert 'splitpoint' into F.
21157         spivot(segloop, splitsh);
21158         splitsubedge(splitpoint, &splitsh, flipqueue);
21159         flipsub(flipqueue);
21160         // Insert the two subsegments.
21161         segloop.shver = 0;
21162         insertsegment(&segloop, misseglist);
21163         senextself(segloop);
21164         spivotself(segloop);
21165         segloop.shver = 0;
21166         insertsegment(&segloop, misseglist);
21167       }
21168   }
21169 
21170   // Detach all segments from tets.
21171   tetrahedrons->traversalinit();
21172   searchtet.tet = tetrahedrontraverse();
21173   while (searchtet.tet != (tetrahedron *) NULL) {
21174     for (i = 0; i < 6; i++) {
21175       searchtet.tet[8 + i] = (tetrahedron) dummysh;
21176     }
21177     searchtet.tet = tetrahedrontraverse();
21178   }
21179   // No segments now.
21180   checksubsegs = 0;
21181 
21182   if (b->verbose > 0) {
21183     printf("  %ld protect points.\n", points->items - vertcount);
21184     printf("  R1: %ld,  R2: %ld,  R3: %ld.\n", r1count, r2count, r3count);
21185   }
21186 
21187   delete flipqueue;
21188   delete misseglist;
21189 }
21190 
21191 //
21192 // End of segments recovery routines
21193 //
21194 
21195 //
21196 // Begin of facet recovery routines
21197 //
21198 
21200 //                                                                           //
21201 // insertsubface()    Fix a subface in place.                                //
21202 //                                                                           //
21203 // Search a subface s in current tetrahedralization T.  If s is found a face //
21204 // face of T, it is inserted into T.  Return FALSE if s is not found in T.   //
21205 //                                                                           //
21207 
21208 bool tetgenmesh::insertsubface(face* insertsh, triface* searchtet)
21209 {
21210   triface spintet, symtet;
21211   face testsh, testseg;
21212   face spinsh, casin, casout;
21213   point tapex, checkpoint;
21214   enum finddirectionresult collinear;
21215   int hitbdry;
21216 
21217   // Search an edge of s.
21218   getsearchtet(sorg(*insertsh), sdest(*insertsh), searchtet, &checkpoint);
21219   collinear = finddirection(searchtet, checkpoint, tetrahedrons->items);
21220   if (collinear == LEFTCOLLINEAR) {
21221     enext2self(*searchtet);
21222     esymself(*searchtet);
21223   } else if (collinear == TOPCOLLINEAR) {
21224     fnextself(*searchtet);
21225     enext2self(*searchtet);
21226     esymself(*searchtet);
21227   }
21228   if (dest(*searchtet) != checkpoint) {
21229     // The edge doesn't exist => s is missing.
21230     return false;
21231   }
21232 
21233   // Search s by spinning faces around the edge.
21234   tapex = sapex(*insertsh);
21235   spintet = *searchtet;
21236   hitbdry = 0;
21237   do {
21238     if (apex(spintet) == tapex) {
21239       // Found s in T. Check if s has already been inserted.
21240       tspivot(spintet, testsh);
21241       if (testsh.sh == dummysh) {
21242         adjustedgering(spintet, CCW);
21243         findedge(insertsh, org(spintet), dest(spintet));
21244         tsbond(spintet, *insertsh);
21245         sym(spintet, symtet); // 'symtet' maybe outside, use it anyway.
21246         sesymself(*insertsh);
21247         tsbond(symtet, *insertsh);
21248       } else {
21249         // Found a duplicated subface (due to the redundant input).
21250         if (!b->quiet) {
21251           printf("Warning:  Two subfaces are found duplicated at ");
21252           printf("(%d, %d, %d)\n", pointmark(sorg(testsh)),
21253                  pointmark(sdest(testsh)), pointmark(sapex(testsh)));
21254           printf("  Subface of facet #%d is deleted.\n", shellmark(*insertsh));
21255           // printf("  Hint: -d switch can find all duplicated facets.\n");
21256         }
21257         shellfacedealloc(subfaces, insertsh->sh);
21258       }
21259       return true;
21260     }
21261     if (!fnextself(spintet)) {
21262       hitbdry ++;
21263       if (hitbdry < 2) {
21264         esym(*searchtet, spintet);
21265         if (!fnextself(spintet)) {
21266           hitbdry ++;
21267         }
21268       }
21269     }
21270   } while (hitbdry < 2 && apex(spintet) != apex(*searchtet));
21271 
21272   // s is missing.
21273   return false;
21274 }
21275 
21277 //                                                                           //
21278 // tritritest()    Test if two triangles are intersecting in their interior. //
21279 //                                                                           //
21280 // One triangle t1 is the face of 'checktet', the other t2 is given by three //
21281 // corners 'p1', 'p2' and 'p3'. This routine calls tri_tri_inter() to detect //
21282 // whether t1 and t2 exactly intersect in their interior. Cases like share a //
21283 // vertex, share an edge, or coincidence are considered not intersect.       //
21284 //                                                                           //
21286 
21287 bool tetgenmesh::tritritest(triface* checktet, point p1, point p2, point p3)
21288 {
21289   point forg, fdest, fapex;
21290   enum interresult intersect;
21291 
21292   forg = org(*checktet);
21293   fdest = dest(*checktet);
21294   fapex = apex(*checktet);
21295 
21296 #ifdef SELF_CHECK
21297   REAL ax, ay, az, bx, by, bz;
21298   REAL n[3];
21299   // face (torg, tdest, tapex) should not be degenerate. However p1, p2,
21300   //   and p3 may be collinear. Check it.
21301   ax = forg[0] - fdest[0];
21302   ay = forg[1] - fdest[1];
21303   az = forg[2] - fdest[2];
21304   bx = forg[0] - fapex[0];
21305   by = forg[1] - fapex[1];
21306   bz = forg[2] - fapex[2];
21307   n[0] = ay * bz - by * az;
21308   n[1] = az * bx - bz * ax;
21309   n[2] = ax * by - bx * ay;
21310   assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21311   // The components of n should not smaller than the machine epsilon.
21312 
21313   ax = p1[0] - p2[0];
21314   ay = p1[1] - p2[1];
21315   az = p1[2] - p2[2];
21316   bx = p1[0] - p3[0];
21317   by = p1[1] - p3[1];
21318   bz = p1[2] - p3[2];
21319   n[0] = ay * bz - by * az;
21320   n[1] = az * bx - bz * ax;
21321   n[2] = ax * by - bx * ay;
21322   assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21323   // The components of n should not smaller than the machine epsilon.
21324 #endif
21325 
21326   intersect = tri_tri_inter(forg, fdest, fapex, p1, p2, p3);
21327   return intersect == INTERSECT;
21328 }
21329 
21331 //                                                                           //
21332 // initializecavity()    Initialize the cavity.                              //
21333 //                                                                           //
21334 // A cavity C is bounded by a list of faces, called fronts.  Each front f is //
21335 // hold by a tet t adjacent to C, t is not in C (uninfected). If f is a hull //
21336 // face, t does't exist, a fake tet t' is created to hold f. t' has the same //
21337 // vertices as f but no opposite.  t' will be removed automatically after C  //
21338 // is filled with new tets (by carvecavity()).                               //
21339 //                                                                           //
21340 // The faces of C are given in two lists. 'floorlist' is a set of subfaces,  //
21341 // each subface has been oriented to face to the inside of C.  'ceillist' is //
21342 // a set of tetrahedral faces. 'frontlist' returns the initialized fronts.   //
21343 //                                                                           //
21345 
21346 void tetgenmesh::initializecavity(list* floorlist, list* ceillist,
21347   list* frontlist)
21348 {
21349   triface neightet, casingtet;
21350   triface faketet;
21351   face worksh;
21352   int i;
21353 
21354   // Initialize subfaces of C.
21355   for (i = 0; i < floorlist->len(); i++) {
21356     // Get a subface s.
21357     worksh = * (face *)(* floorlist)[i];
21358 #ifdef SELF_CHECK
21359     // Current side of s should be empty.
21360     stpivot(worksh, neightet);
21361     assert(neightet.tet == dummytet);
21362 #endif
21363     // Get the adjacent tet t.
21364     sesymself(worksh);
21365     stpivot(worksh, casingtet);
21366     // Does t exist?
21367     if (casingtet.tet == dummytet) {
21368       // Create a fake tet t' to hold f temporarily.
21369       maketetrahedron(&faketet);
21370       setorg(faketet, sorg(worksh));
21371       setdest(faketet, sdest(worksh));
21372       setapex(faketet, sapex(worksh));
21373       setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21374       tsbond(faketet, worksh);
21375       frontlist->append(&faketet);
21376     } else {
21377       frontlist->append(&casingtet);
21378     }
21379   }
21380   // Initialize tet faces of C.
21381   for (i = 0; i < ceillist->len(); i++) {
21382     // Get a tet face c.
21383     neightet = * (triface *) (* ceillist)[i];
21384 #ifdef SELF_CHECK
21385     // The tet of c must be inside C (going to be deleted).
21386     assert(infected(neightet));
21387 #endif
21388     // Get the adjacent tet t.
21389     sym(neightet, casingtet);
21390     // Does t exist?
21391     if (casingtet.tet == dummytet) {
21392       // No. Create a fake tet t' to hold f temporarily.
21393       maketetrahedron(&faketet);
21394       // Be sure that the vertices of t' are CCW oriented.
21395       adjustedgering(neightet, CW); // CW edge ring.
21396       setorg(faketet, org(neightet));
21397       setdest(faketet, dest(neightet));
21398       setapex(faketet, apex(neightet));
21399       setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21400       // Bond t' to a subface if it exists.
21401       tspivot(neightet, worksh);
21402       if (worksh.sh != dummysh) {
21403         sesymself(worksh);
21404         tsbond(faketet, worksh);
21405       }
21406       // Bond c <--> t'. So we're able to find t' and remove it.
21407       bond(faketet, neightet);
21408       // c may become uninfected due to the bond().
21409       infect(neightet);
21410       frontlist->append(&faketet);
21411     } else {
21412       frontlist->append(&casingtet);
21413     }
21414   }
21415 }
21416 
21418 //                                                                           //
21419 // retrievenewtets()    Retrieve the newly created tets.                     //
21420 //                                                                           //
21421 // On input, 'newtetlist' contains at least one alive new tet. From this tet,//
21422 // other new tets can be found by a broadth-first searching.                 //
21423 //                                                                           //
21425 
21426 void tetgenmesh::retrievenewtets(list* newtetlist)
21427 {
21428   triface searchtet, casingtet;
21429   int i;
21430 
21431   // There may be dead tets due to flip32(). Delete them first.
21432   for (i = 0; i < newtetlist->len(); i++) {
21433     searchtet = * (triface *)(* newtetlist)[i];
21434     if (isdead(&searchtet)) {
21435       newtetlist->del(i, 0); i--;
21436       continue;
21437     }
21438     infect(searchtet);
21439   }
21440   // Find all new tets.
21441   for (i = 0; i < newtetlist->len(); i++) {
21442     searchtet = * (triface *)(* newtetlist)[i];
21443     for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
21444       sym(searchtet, casingtet);
21445       if ((casingtet.tet != dummytet) && !infected(casingtet)) {
21446         infect(casingtet);
21447         newtetlist->append(&casingtet);
21448       }
21449     }
21450   }
21451   // Uninfect new tets.
21452   for (i = 0; i < newtetlist->len(); i++) {
21453     searchtet = * (triface *)(* newtetlist)[i];
21454     uninfect(searchtet);
21455   }
21456 }
21457 
21459 //                                                                           //
21460 // delaunizecavvertices()    Form a DT of the vertices of a cavity.          //
21461 //                                                                           //
21462 // 'floorptlist' and 'ceilptlist' are the vertices of the cavity.            //
21463 //                                                                           //
21464 // The tets of the DT are created directly in the pool 'tetrahedrons', i.e., //
21465 // no auxiliary data structure and memory are required.  The trick is at the //
21466 // time they're created, there are no connections between them to the other  //
21467 // tets in the pool. You can imagine they form an ioslated island.           //
21468 //                                                                           //
21470 
21471 void tetgenmesh::delaunizecavvertices(triface* oldtet, list* floorptlist,
21472   list* ceilptlist, list* newtetlist, queue* flipque)
21473 {
21474   point *insertarray;
21475   triface bakhulltet, newtet;
21476   long bakhullsize;
21477   long arraysize;
21478   int bakchksub;
21479   int i, j;
21480 
21481   // Prepare the array of points for inserting.
21482   arraysize = floorptlist->len();
21483   if (ceilptlist != (list *) NULL) {
21484     arraysize += ceilptlist->len();
21485   }
21486   insertarray = new point[arraysize];
21487   for (i = 0; i < floorptlist->len(); i++) {
21488     insertarray[i] = * (point *)(* floorptlist)[i];
21489   }
21490   if (ceilptlist != (list *) NULL) {
21491     for (j = 0; j < ceilptlist->len(); j++) {
21492       insertarray[i + j] = * (point *)(* ceilptlist)[j];
21493     }
21494   }
21495 
21496   // The incrflipdelaunay() is re-used. Backup global variables.
21497   decode(dummytet[0], bakhulltet);
21498   bakhullsize = hullsize;
21499   bakchksub = checksubfaces;
21500   checksubfaces = 0;
21501   b->verbose--;
21502 
21503   // Form the DT by incremental flip Delaunay algorithm. Do not jump for
21504   //   point location, do not merge points.
21505   incrflipdelaunay(oldtet, insertarray, arraysize, false, false, 0.0, flipque);
21506 
21507   // Get a tet in D.
21508   decode(dummytet[0], newtet);
21509   newtetlist->append(&newtet);
21510   // Get all tets of D.
21511   retrievenewtets(newtetlist);
21512 
21513   // Restore global variables.
21514   dummytet[0] = encode(bakhulltet);
21515   hullsize = bakhullsize;
21516   checksubfaces = bakchksub;
21517   b->verbose++;
21518 
21519   delete [] insertarray;
21520 }
21521 
21523 //                                                                           //
21524 // insertauxsubface()    Fix an auxilary subface in place.                   //
21525 //                                                                           //
21526 // An auxilary subface s is fixed in D as it is a real subface, but s has no //
21527 // vertices and neighbors. It has two uses: (1) it protects an identfied     //
21528 // front f in D; (2) it serves the link to bond a tet in C and f later. The  //
21529 // first neighbor of s (s->sh[0]) stores a pointer to f.                     //
21530 //                                                                           //
21531 // 'front' is a front f of C. idfront' t is a tet in D where f is identified //
21532 // be a face of it. s will be fixed between t and its neighbor.              //
21533 //                                                                           //
21535 
21536 void tetgenmesh::insertauxsubface(triface* front, triface* idfront)
21537 {
21538   triface neightet;
21539   face auxsh;
21540 
21541   // Create the aux subface s.
21542   makeshellface(subfaces, &auxsh);
21543   // Bond s <--> t.
21544   tsbond(*idfront, auxsh);
21545   // Does t's neighbor n exist?
21546   sym(*idfront, neightet);
21547   if (neightet.tet != dummytet) {
21548     // Bond s <--> n.
21549     sesymself(auxsh);
21550     tsbond(neightet, auxsh);
21551   }
21552   // Let s remember f.
21553   auxsh.sh[0] = (shellface) encode(*front);
21554 }
21555 
21557 //                                                                           //
21558 // scoutfront()    Scout a face in D.                                        //
21559 //                                                                           //
21560 // Search a 'front' f in D. If f is found, return TRUE and the face of D is  //
21561 // returned in 'idfront'. Otherwise, return FALSE.                           //
21562 //                                                                           //
21564 
21565 bool tetgenmesh::scoutfront(triface* front, triface* idfront, list* newtetlist)
21566 {
21567   triface spintet;
21568   point pa, pb, pc;
21569   enum locateresult loc;
21570   enum finddirectionresult col;
21571   int hitbdry;
21572   int i;
21573 
21574   // Let the front we're searching is abc.
21575   pa = org(*front);
21576   pb = dest(*front);
21577   // Get a tet in D for searching.
21578   *idfront = recenttet;
21579   // Make sure the tet is valid (it may be killed by flips).
21580   if (isdead(idfront)) {
21581     // The tet is dead. Search a live tet in D. !!!
21582     for (i = 0; i < newtetlist->len(); i++) {
21583       recenttet = * (triface *)(* newtetlist)[i];
21584       if (!isdead(&recenttet)) break;
21585     }
21586     assert(i < newtetlist->len());
21587   }
21588 
21589   // Search a tet having vertex a.
21590   loc = preciselocate(pa, idfront, (long) newtetlist->len());
21591   assert(loc == ONVERTEX);
21592   recenttet = *idfront;
21593   // Search a tet having edge ab.
21594   col = finddirection(idfront, pb, (long) newtetlist->len());
21595   if (col == RIGHTCOLLINEAR) {
21596     // b is just the destination.
21597   } else if (col == LEFTCOLLINEAR) {
21598     enext2self(*idfront);
21599     esymself(*idfront);
21600   } else if (col == TOPCOLLINEAR) {
21601     fnextself(*idfront);
21602     enext2self(*idfront);
21603     esymself(*idfront);
21604   }
21605 
21606   if (dest(*idfront) == pb) {
21607     // Search a tet having face abc
21608     pc = apex(*front);
21609     spintet = *idfront;
21610     hitbdry = 0;
21611     do {
21612       if (apex(spintet) == pc) {
21613         // Found abc. Insert an auxilary subface s at idfront.
21614         // insertauxsubface(front, &spintet);
21615         *idfront = spintet;
21616         return true;
21617       }
21618       if (!fnextself(spintet)) {
21619         hitbdry ++;
21620         if (hitbdry < 2) {
21621           esym(*idfront, spintet);
21622           if (!fnextself(spintet)) {
21623             hitbdry ++;
21624           }
21625         }
21626       }
21627       if (apex(spintet) == apex(*idfront)) break;
21628     } while (hitbdry < 2);
21629   }
21630 
21631   // f is missing in D.
21632   if (b->verbose > 2) {
21633     printf("    Front (%d, %d, %d) is missing.\n", pointmark(pa),
21634            pointmark(pb), pointmark(apex(*front)));
21635   }
21636   return false;
21637 }
21638 
21640 //                                                                           //
21641 // gluefronts()    Glue two fronts together.                                 //
21642 //                                                                           //
21643 // This is a support routine for identifyfront().  Two fronts f and f1 are   //
21644 // found indentical. This is caused by the non-coplanarity of vertices of a  //
21645 // facet. Hence f and f1 are a subface and a tet. They are not fronts of the //
21646 // cavity anymore. This routine glues f and f1 together.                     //
21647 //                                                                           //
21649 
21650 void tetgenmesh::gluefronts(triface* front, triface* front1)
21651 {
21652   face consh;
21653 
21654   // Glue f and f1 together. There're four cases:
21655   //   (1) both f and f1 are not fake;
21656   //   (2) f is not fake, f1 is fake;
21657   //   (3) f is fake and f1 is not fake;
21658   //   (4) both f and f1 are fake.
21659   // Case (4) should be not possible.
21660 
21661   // Is there a concrete subface c at f.
21662   tspivot(*front, consh);
21663   if (consh.sh != dummysh) {
21664     sesymself(consh);
21665     tsbond(*front1, consh); // Bond: f1 <--> c.
21666     sesymself(consh);
21667   }
21668   // Does f hold by a fake tet.
21669   if (oppo(*front) == (point) NULL) {
21670     // f is fake. Case (3) or (4).
21671     assert(oppo(*front1) != (point) NULL); // Eliminate (4).
21672     // Case (3).
21673     if (consh.sh != dummysh) {
21674       stdissolve(consh);  // Dissolve: c -x-> f.
21675     }
21676     // Dealloc f.
21677     tetrahedrondealloc(front->tet);
21678     // f1 becomes a hull. let 'dummytet' bond to it.
21679     dummytet[0] = encode(*front1);
21680   } else {
21681     // Case (1) or (2).
21682     bond(*front, *front1); // Bond f1 <--> f.
21683   }
21684   // Is f a fake tet?
21685   if (!isdead(front)) {
21686     // No. Check for case (2).
21687     tspivot(*front1, consh);
21688     // Is f1 fake?
21689     if (oppo(*front1) == (point) NULL) {
21690       // Case (2) or (4)
21691       assert(oppo(*front) != (point) NULL); // Eliminate (4).
21692       // Case (2).
21693       if (consh.sh != dummysh) {
21694         stdissolve(consh);  // Dissolve: c -x-> f1.
21695         sesymself(consh); // Bond: f <--> c.
21696         tsbond(*front, consh);
21697       }
21698       // Dissolve: f -x->f1.
21699       dissolve(*front);
21700       // Dealloc f1.
21701       tetrahedrondealloc(front1->tet);
21702       // f becomes a hull. let 'dummytet' bond to it.
21703       dummytet[0] = encode(*front);
21704     } else {
21705       // Case (1).
21706       if (consh.sh != dummysh) {
21707         sesymself(consh);
21708         tsbond(*front, consh); // Bond: f <--> c.
21709       }
21710     }
21711   }
21712 }
21713 
21715 //                                                                           //
21716 // identifyfronts()    Identify cavity faces in D.                           //
21717 //                                                                           //
21718 // 'frontlist' are fronts of C need indentfying.  This routine searches each //
21719 // front f in D. Once f is found, an auxilary subface s is inserted in D at  //
21720 // the face. If f is not found in D, remove it from frontlist and save it in //
21721 // 'misfrontlist'.                                                           //
21722 //                                                                           //
21724 
21725 bool tetgenmesh::identifyfronts(list* frontlist, list* misfrontlist,
21726   list* newtetlist)
21727 {
21728   triface front, front1, tfront;
21729   triface idfront, neightet;
21730   face auxsh;
21731   int len, i, j;
21732 
21733   misfrontlist->clear();
21734   // Set a new tet in D for searching.
21735   recenttet = * (triface *)(* newtetlist)[0];
21736 
21737   // Identify all fronts in D.
21738   for (i = 0; i < frontlist->len(); i++) {
21739     // Get a front f.
21740     front = * (triface *)( *frontlist)[i];
21741     if (scoutfront(&front, &idfront, newtetlist)) {
21742       // Found f. Insert an aux subface s.
21743       assert((idfront.tet != dummytet) && !isdead(&idfront));
21744       // Does s already exist?
21745       tspivot(idfront, auxsh);
21746       if (auxsh.sh != dummysh) {
21747         // There're two identical fronts, f (front) and f1 (s.sh[0])!
21748         decode((tetrahedron) auxsh.sh[0], front1);
21749         assert((front1.tet != dummytet) && !infected(front1));
21750         // Detach s in D.
21751         tsdissolve(idfront);
21752         sym(idfront, neightet);
21753         if (neightet.tet != dummytet) {
21754           tsdissolve(neightet);
21755         }
21756         // s has fulfilled its duty. Can be deleted.
21757         shellfacedealloc(subfaces, auxsh.sh);
21758         // Remove f from frontlist.
21759         frontlist->del(i, 1); i--;
21760         // Remove f1 from frontlist.
21761         len = frontlist->len();
21762         for (j = 0; j < frontlist->len(); j++) {
21763           tfront = * (triface *)(* frontlist)[j];
21764           if ((tfront.tet == front1.tet) && (tfront.loc == front1.loc)) {
21765             // Found f1 in list.  Check f1 != f.
21766             assert((tfront.tet != front.tet) || (tfront.loc != front.loc));
21767             frontlist->del(j, 1); i--;
21768             break;
21769           }
21770         }
21771         assert((frontlist->len() + 1) == len);
21772         // Glue f and f1 together.
21773         gluefronts(&front, &front1);
21774       } else {
21775         // Insert an aux subface to protect f in D.
21776         insertauxsubface(&front, &idfront);
21777       }
21778     } else {
21779       // f is missing.
21780       frontlist->del(i, 1); i--;
21781       // Are there two identical fronts, f (front) and f1 (front1)?
21782       for (j = 0; j < misfrontlist->len(); j++) {
21783         front1 = * (triface *)(* misfrontlist)[j];
21784         if (isfacehaspoint(&front1, org(front)) &&
21785             isfacehaspoint(&front1, dest(front)) &&
21786             isfacehaspoint(&front1, apex(front))) break;
21787       }
21788       if (j < misfrontlist->len()) {
21789         // Found an identical front f1. Remove f1 from the list.
21790         misfrontlist->del(j, 1);
21791         // Glue f and f1 together.
21792         gluefronts(&front, &front1);
21793       } else {
21794         // Add f into misfrontlist.
21795         misfrontlist->append(&front);
21796       }
21797     }
21798   }
21799   return misfrontlist->len() == 0;
21800 }
21801 
21803 //                                                                           //
21804 // detachauxsubfaces()    Detach auxilary subfaces in D.                     //
21805 //                                                                           //
21806 // This is a reverse routine of identifyfronts(). Some fronts are missing in //
21807 // D. C can not be easily tetrahedralized. It needs remediation (expansion,  //
21808 // or constrained flips, or adding a Steiner point).  This routine detaches  //
21809 // the auxilary subfaces have been inserted in D and delete them.            //
21810 //                                                                           //
21812 
21813 void tetgenmesh::detachauxsubfaces(list* newtetlist)
21814 {
21815   triface newtet, neightet;
21816   face auxsh;
21817   int i;
21818 
21819   for (i = 0; i < newtetlist->len(); i++) {
21820     // Get a new tet t.
21821     newtet = * (triface *)(* newtetlist)[i];
21822     // t may e dead due to flips.
21823     if (isdead(&newtet)) continue;
21824     assert(!infected(newtet));
21825     // Check the four faces of t.
21826     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
21827       tspivot(newtet, auxsh);
21828       if (auxsh.sh != dummysh) {
21829         // An auxilary subface s.
21830         assert(sorg(auxsh) == (point) NULL);
21831         tsdissolve(newtet);  // t -x-> s.
21832         sym(newtet, neightet);
21833         if (neightet.tet != dummytet) {
21834           assert(!isdead(&neightet));
21835           tsdissolve(neightet); // n -x-> s.
21836         }
21837         // Delete s.
21838         shellfacedealloc(subfaces, auxsh.sh);
21839       }
21840     }
21841   }
21842 }
21843 
21845 //                                                                           //
21846 // expandcavity()    Expand the cavity by adding new fronts.                 //
21847 //                                                                           //
21848 // This is the support routine for delaunizecavity().  Some fronts of C are  //
21849 // missing in D since they're not strongly Delaunay. Such fronts are removed //
21850 // and the faces of the tets abutting to them are added. C is then expanded. //
21851 // Some removed faces may be subfaces, they're queued to recover later. D is //
21852 // expanded simultaneously with the new vertices of the new fronts.          //
21853 //                                                                           //
21855 
21856 void tetgenmesh::expandcavity(list* frontlist, list* misfrontlist,
21857   list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
21858 {
21859   triface misfront, newfront, casingtet, crosstet;
21860   triface searchtet, faketet, bakhulltet;
21861   face checksh;
21862   point pd;
21863   enum insertsiteresult success;
21864   long bakhullsize;
21865   int bakchksub;
21866   int i, j, k;
21867 
21868   if (b->verbose > 1) {
21869     printf("    Expand cavity (%d missing fronts).\n", misfrontlist->len());
21870   }
21871   // Increase the number of expanded times.
21872   expcavcount++;
21873   // The incrflipdelaunay() is re-used. Backup global variables.
21874   decode(dummytet[0], bakhulltet);
21875   bakhullsize = hullsize;
21876   bakchksub = checksubfaces;
21877   checksubfaces = 0;
21878   b->verbose--;
21879 
21880   // Choose a tet in D for searching.
21881   recenttet = * (triface *)(* newtetlist)[0];
21882   assert((recenttet.tet != dummytet) && !isdead(&recenttet));
21883 
21884   // Loop through 'misfrontlist'.
21885   for (i = 0; i < misfrontlist->len(); i++) {
21886     // Get a missing front f.
21887     misfront = * (triface *)(* misfrontlist)[i];
21888     // C will be expanded at f.
21889     if (b->verbose > 1) {
21890       printf("    Get misfront (%d, %d, %d).\n", pointmark(org(misfront)),
21891              pointmark(dest(misfront)), pointmark(apex(misfront)));
21892     }
21893     // Is f has a subface s?
21894     tspivot(misfront, checksh);
21895     if (checksh.sh != dummysh) {
21896       // A subface s is found. Check whether f is expandable at s.
21897       sym(misfront, crosstet);
21898       if (!infected(crosstet)) {
21899         // f is not expandable. In principle is should not happen. However,
21900         //   it can happen when PBC is in use.
21901         assert(checkpbcs);
21902         // Skip expanding f. It will be processed later.
21903         continue;
21904       }
21905       // Temporarily remove s. Queue and recover it later.
21906       if (b->verbose > 1) {
21907         printf("    Queuing subface (%d, %d, %d).\n",
21908                pointmark(sorg(checksh)), pointmark(sdest(checksh)),
21909                pointmark(sapex(checksh)));
21910       }
21911       // Detach s from tets at its both sides.
21912       tsdissolve(misfront);
21913       tsdissolve(crosstet);
21914       // Detach tets at from s.
21915       stdissolve(checksh);
21916       sesymself(checksh);
21917       stdissolve(checksh);
21918       // Mark and queue it.
21919       sinfect(checksh);
21920       missingshqueue->push(&checksh);
21921     }
21922     // f may already be processed (become a cross tet of C).
21923     if (infected(misfront)) continue;
21924     // Get the point p = oppo(t), t is the tet holds f.
21925     pd = oppo(misfront);
21926 #ifdef SELF_CHECK
21927     // t must not be fake.
21928     assert(pd != (point) NULL);
21929 #endif
21930     // Insert p in D. p may not be inserted if it is one of the two cases:
21931     //   (1) p is already a vertex of D;
21932     //   (2) p lies outside the CH of D;
21933     searchtet = recenttet;
21934     // Make sure the tet is valid (it may be killed by flips).
21935     if (isdead(&searchtet)) {
21936       // The tet is dead. Get a live tet in D. !!!
21937       for (j = 0; j < newtetlist->len(); j++) {
21938         recenttet = * (triface *)(* newtetlist)[j];
21939         if (!isdead(&recenttet)) break;
21940       }
21941       assert(j < newtetlist->len());
21942       searchtet = recenttet;
21943     }
21944     success = insertsite(pd, &searchtet, false, flipque);
21945     if (success == OUTSIDEPOINT) {
21946       // case (2). Insert p onto CH of D.
21947       inserthullsite(pd, &searchtet, flipque);
21948     }
21949     if (success != DUPLICATEPOINT) {
21950       // p is inserted. Recover Delaunness of D by flips.
21951       flip(flipque, NULL);
21952     }
21953     // Expand C by adding new fronts. The three faces of t which have p as a
21954     //   vertex become new fronts. However, if a new front is coincident with
21955     //   an old front of C, it is not added and the old front is removed.
21956     adjustedgering(misfront, CCW);
21957     for (j = 0; j < 3; j++) {
21958       // Notice: Below I mis-used the names. 'newfront' is not exactly a new
21959       //   front, instead the 'casingtet' should be called new front.
21960       // Get a new front f_n.
21961       fnext(misfront, newfront);
21962       // Get the neighbor tet n at f_n.
21963       sym(newfront, casingtet);
21964       // Is n a cross tet?
21965       if (!infected(casingtet)) {
21966         // f_n becomes a new front of C.
21967         // Does n exist?
21968         if (casingtet.tet == dummytet) {
21969           // Create a fake tet n' to hold f_n temporarily.
21970           maketetrahedron(&faketet);
21971           // Be sure that the vertices of fake tet are CCW oriented.
21972           adjustedgering(newfront, CW); // CW edge ring.
21973           setorg(faketet, org(newfront));
21974           setdest(faketet, dest(newfront));
21975           setapex(faketet, apex(newfront));
21976           setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21977           // Bond n' to a subface if it exists.
21978           tspivot(newfront, checksh);
21979           if (checksh.sh != dummysh) {
21980             sesymself(checksh);
21981             tsbond(faketet, checksh);
21982           }
21983           // Bond f_n <--> n'. So we're able to find n' and remove it.
21984           bond(faketet, newfront);
21985           frontlist->append(&faketet);
21986         } else {
21987           // Add n to frontlist.
21988           frontlist->append(&casingtet);
21989         }
21990       } else {
21991         // f_n is coincident with an existing front f' of C. f' is no longer
21992         //   a front, remove it from frontlist.  Use the inverse order to
21993         //   search f' (most likely, a newly added front may be f').
21994         for (k = frontlist->len() - 1; k >= 0; k--) {
21995           searchtet = * (triface *)(* frontlist)[k];
21996           if ((newfront.tet == searchtet.tet) &&
21997               (newfront.loc == searchtet.loc)) {
21998             frontlist->del(k, 0);
21999             break;
22000           }
22001         }
22002         // Is f_n a subface?
22003         tspivot(newfront, checksh);
22004         if (checksh.sh != dummysh) {
22005           // Temporarily remove checksh. Make it missing. recover it later.
22006           if (b->verbose > 2) {
22007             printf("    Queuing subface (%d, %d, %d).\n",
22008                    pointmark(sorg(checksh)), pointmark(sdest(checksh)),
22009                    pointmark(sapex(checksh)));
22010           }
22011           tsdissolve(newfront);
22012           tsdissolve(casingtet);
22013           // Detach tets at the both sides of checksh.
22014           stdissolve(checksh);
22015           sesymself(checksh);
22016           stdissolve(checksh);
22017           sinfect(checksh);
22018           missingshqueue->push(&checksh);
22019         }
22020       }
22021       enextself(misfront);
22022     }
22023     // C has been expanded at f. t becomes a cross tet.
22024     if (!infected(misfront)) {
22025       // t will be deleted, queue it.
22026       infect(misfront);
22027       crosstetlist->append(&misfront);
22028     }
22029   }
22030 
22031   // Loop through misfrontlist, remove infected misfronts.
22032   for (i = 0; i < misfrontlist->len(); i++) {
22033     misfront = * (triface *)(* misfrontlist)[i];
22034     if (infected(misfront)) {
22035       // Remove f, keep original list order.
22036       misfrontlist->del(i, 1);
22037       i--;
22038     }
22039   }
22040 
22041   // Are we done?
22042   if (misfrontlist->len() > 0) {
22043     // No. There are unexpandable fronts.
22044     // expandcavity_sos(misfrontlist);
22045     assert(0); // Not done yet.
22046   }
22047 
22048   // D has been updated (by added new tets or dead tets) (due to flips).
22049   retrievenewtets(newtetlist);
22050 
22051   // Restore global variables.
22052   dummytet[0] = encode(bakhulltet);
22053   hullsize = bakhullsize;
22054   checksubfaces = bakchksub;
22055   b->verbose++;
22056 }
22057 
22059 //                                                                           //
22060 // carvecavity()    Remove redundant (outside) tetrahedra from D.            //
22061 //                                                                           //
22062 // The fronts of C have been identified in D. Hence C can be tetrahedralized //
22063 // by removing the tets outside C. The CDT is then updated by filling C with //
22064 // the remaining tets (inside C) of D.                                       //
22065 //                                                                           //
22066 // Each front is protected by an auxilary subface s in D. s has a pointer to //
22067 // f (s.sh[0]). f can be used to classified the in- and out- tets of C (the  //
22068 // CW orientation of f faces to the inside of C). The classified out-tets of //
22069 // C are marked (infected) for removing.                                     //
22070 //                                                                           //
22071 // Notice that the out-tets may not only the tets on the CH of C,  but also  //
22072 // tets completely inside D, eg., there is a "hole" in D.  Such tets must be //
22073 // marked during classification. The hole tets are poped up and removed too. //
22074 //                                                                           //
22076 
22077 void tetgenmesh::carvecavity(list* newtetlist, list* outtetlist,
22078   queue* flipque)
22079 {
22080   triface newtet, neightet, front, outtet;
22081   face auxsh, consh;
22082   point pointptr;
22083   REAL ori;
22084   int i;
22085 
22086   // Clear work list.
22087   outtetlist->clear();
22088 
22089   // Classify in- and out- tets in D. Mark and queue classified out-tets.
22090   for (i = 0; i < newtetlist->len(); i++) {
22091     // Get a new tet t.
22092     newtet = * (triface *)(* newtetlist)[i];
22093     assert(!isdead(&newtet));
22094     // Look for aux subfaces attached at t.
22095     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22096       tspivot(newtet, auxsh);
22097       if (auxsh.sh != dummysh) {
22098         // Has this side a neighbor n?
22099         sym(newtet, neightet);
22100         if (neightet.tet != dummytet) {
22101           // Classify t and n (one is "in" and another is "out").
22102           // Get the front f.
22103           decode((tetrahedron) auxsh.sh[0], front);
22104           // Let f face to the inside of C.
22105           adjustedgering(front, CW);
22106           ori = orient3d(org(front), dest(front), apex(front), oppo(newtet));
22107           assert(ori != 0.0);
22108           if (ori < 0.0) {
22109             // t is in-tet. n is out-tet.
22110             outtet = neightet;
22111           } else {
22112             // n is in-tet. t is out-tet.
22113             outtet = newtet;
22114           }
22115           // Add the out-tet into list.
22116           if (!infected(outtet)) {
22117             infect(outtet);
22118             outtetlist->append(&outtet);
22119           }
22120         }
22121       }
22122     }
22123   }
22124 
22125   // Find and mark all out-tets.
22126   for (i = 0; i < outtetlist->len(); i++) {
22127     outtet = * (triface *)(* outtetlist)[i];
22128     for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22129       sym(outtet, neightet);
22130       // Does the neighbor exist and unmarked?
22131       if ((neightet.tet != dummytet) && !infected(neightet)) {
22132         // Is it protected by an aux subface?
22133         tspivot(outtet, auxsh);
22134         if (auxsh.sh == dummysh) {
22135           // It's an out-tet.
22136           infect(neightet);
22137           outtetlist->append(&neightet);
22138         }
22139       }
22140     }
22141   }
22142 
22143   // Remove the out- (and hole) tets.
22144   for (i = 0; i < outtetlist->len(); i++) {
22145     // Get an out-tet t.
22146     outtet = * (triface *)(* outtetlist)[i];
22147     // Detach t from the in-tets.
22148     for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22149       // Is there an aux subface s?
22150       tspivot(outtet, auxsh);
22151       if (auxsh.sh != dummysh) {
22152         // Get the neighbor n.
22153         sym(outtet, neightet);
22154         assert(!infected(neightet)); // t must be in-tet.
22155         // Detach n -x-> t.
22156         dissolve(neightet);
22157       }
22158     }
22159     // Dealloc the tet.
22160     tetrahedrondealloc(outtet.tet);
22161   }
22162 
22163   // Connect the in-tets of C to fronts. Remove aux subfaces and fake tets.
22164   for (i = 0; i < newtetlist->len(); i++) {
22165     // Get a new tet t.
22166     newtet = * (triface *)(* newtetlist)[i];
22167     // t may be an out-tet and has got deleted.
22168     if (isdead(&newtet)) continue;
22169     // t is an in-tet. Look for aux subfaces attached at t.
22170     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22171       // Is there an aux subface s?
22172       tspivot(newtet, auxsh);
22173       if (auxsh.sh != dummysh) {
22174         // Get the front f.
22175         decode((tetrahedron) auxsh.sh[0], front);
22176         assert((front.tet != dummytet) && !infected(front));
22177         // s has fulfilled its duty. Can be deleted.
22178         tsdissolve(newtet); // dissolve: t -x-> s.
22179         // Delete s.
22180         shellfacedealloc(subfaces, auxsh.sh);
22181         // Connect the newtet t and front f.
22182         // Is there a concrete subface c at f.
22183         tspivot(front, consh);
22184         if (consh.sh != dummysh) {
22185           sesymself(consh);
22186           // Bond: t <--> c.
22187           tsbond(newtet, consh);
22188         }
22189         // Does f hold by a fake tet.
22190         if (oppo(front) == (point) NULL) {
22191           // f is fake.
22192           if (consh.sh != dummysh) {
22193             sesymself(consh);
22194             // Dissolve: c -x-> f.
22195             stdissolve(consh);
22196           }
22197           // Dealloc f.
22198           tetrahedrondealloc(front.tet);
22199           // f becomes a hull. let 'dummytet' bond to it.
22200           dummytet[0] = encode(newtet);
22201         } else {
22202           // Bond t <--> f.
22203           bond(newtet, front);
22204         }
22205         // t may be non-locally Delaunay and flipable.
22206         if (flipque != (queue *) NULL) {
22207           enqueueflipface(newtet, flipque);
22208         }
22209       }
22210     }
22211     // Let the corners of t2 point to it for fast searching.
22212     pointptr = org(newtet);
22213     setpoint2tet(pointptr, encode(newtet));
22214     pointptr = dest(newtet);
22215     setpoint2tet(pointptr, encode(newtet));
22216     pointptr = apex(newtet);
22217     setpoint2tet(pointptr, encode(newtet));
22218     pointptr = oppo(newtet);
22219     setpoint2tet(pointptr, encode(newtet));
22220   }
22221   // The cavity has been re-tetrahedralized.
22222 }
22223 
22225 //                                                                           //
22226 // delaunizecavity()    Tetrahedralize a cavity by Delaunay tetrahedra.      //
22227 //                                                                           //
22228 // The cavity C is bounded by a set of triangles in 'floorlist' (a list of   //
22229 // coplanar subfaces) and 'ceillist' (a list of tetrahedral faces lie above  //
22230 // the subfaces). 'floorptlist' and 'ceilptlist' are the vertices of C.      //
22231 //                                                                           //
22233 
22234 void tetgenmesh::delaunizecavity(list* floorlist, list* ceillist,
22235   list* ceilptlist, list* floorptlist, list* frontlist, list* misfrontlist,
22236   list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
22237 {
22238   int vertnum;
22239 
22240   vertnum = floorptlist->len();
22241   vertnum += (ceilptlist != (list *) NULL ? ceilptlist->len() : 0);
22242   if (b->verbose > 1) {
22243     printf("    Delaunizing cavity (%d floors, %d ceilings, %d vertices).\n",
22244            floorlist->len(), ceillist->len(), vertnum);
22245   }
22246   // Save the size of the largest cavity.
22247   if ((floorlist->len() + ceillist->len()) > maxcavfaces) {
22248     maxcavfaces = floorlist->len() + ceillist->len();
22249   }
22250   if (vertnum > maxcavverts) {
22251     maxcavverts = vertnum;
22252   }
22253 
22254   // Clear these lists.
22255   frontlist->clear();
22256   misfrontlist->clear();
22257   newtetlist->clear();
22258 
22259   // Initialize the cavity C.
22260   initializecavity(floorlist, ceillist, frontlist);
22261   // Form the D of the vertices of C.
22262   delaunizecavvertices(NULL, floorptlist, ceilptlist, newtetlist, flipque);
22263   // Identify faces of C in D.
22264   while (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
22265     // Remove protecting subfaces, keep new tets.
22266     detachauxsubfaces(newtetlist);
22267     // Expand C and updateing D.
22268     expandcavity(frontlist, misfrontlist, newtetlist, crosstetlist,
22269                  missingshqueue, flipque);
22270   }
22271   // All fronts have identified in D. Get the shape of C by removing out
22272   //   tets of C. 'misfrontlist' is reused for removing out tets.
22273   carvecavity(newtetlist, misfrontlist, NULL);
22274 }
22275 
22277 //                                                                           //
22278 // formmissingregion()    Form the missing region.                           //
22279 //                                                                           //
22280 // 'missingsh' is a missing subface.  Start from it we can form the missing  //
22281 // region R (a set of connected missing subfaces).  Because all missing sub- //
22282 // faces have been marked (infected) before. R can be formed by checking the //
22283 // neighbors of 'missingsh', and the neighbors of the neighbors, and so on.  //
22284 // Stop checking further at either a segment or an unmarked subface.         //
22285 //                                                                           //
22286 // 'missingshlist' returns R. The edge ring of subfaces of R are oriented in //
22287 // the same direction. 'equatptlist' returns the vertices of R, each vertex  //
22288 // is marked with '1' (in 'worklist').                                       //
22289 //                                                                           //
22291 
22292 void tetgenmesh::formmissingregion(face* missingsh, list* missingshlist,
22293   list* equatptlist, int* worklist)
22294 {
22295   face neighsh, worksh, workseg;
22296   point workpt[3];
22297   int idx, i, j;
22298 
22299   // Add 'missingsh' into 'missingshlist'.
22300   missingshlist->append(missingsh);
22301   // Save and mark its three vertices.
22302   workpt[0] = sorg(*missingsh);
22303   workpt[1] = sdest(*missingsh);
22304   workpt[2] = sapex(*missingsh);
22305   for (i = 0; i < 3; i++) {
22306     idx = pointmark(workpt[i]) - in->firstnumber;
22307     worklist[idx] = 1;
22308     equatptlist->append(&workpt[i]);
22309   }
22310   // Temporarily uninfect it (avoid to save it again).
22311   suninfect(*missingsh);
22312 
22313   // Find the other missing subfaces.
22314   for (i = 0; i < missingshlist->len(); i++) {
22315     // Get a missing subface.
22316     worksh = * (face *)(* missingshlist)[i];
22317     // Check three neighbors of this face.
22318     for (j = 0; j < 3; j++) {
22319       sspivot(worksh, workseg);
22320       if (workseg.sh == dummysh) {
22321         spivot(worksh, neighsh);
22322         if (sinfected(neighsh)) {
22323           // Find a missing subface, adjust the face orientation.
22324           if (sorg(neighsh) != sdest(worksh)) {
22325             sesymself(neighsh);
22326           }
22327           if (b->verbose > 2) {
22328             printf("    Add missing subface (%d, %d, %d).\n",
22329                    pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
22330                    pointmark(sapex(neighsh)));
22331           }
22332           missingshlist->append(&neighsh);
22333           // Save and mark its apex.
22334           workpt[0] = sapex(neighsh);
22335           idx = pointmark(workpt[0]) - in->firstnumber;
22336           // Has workpt[0] been added?
22337           if (worklist[idx] == 0) {
22338             worklist[idx] = 1;
22339             equatptlist->append(&workpt[0]);
22340           }
22341           // Temporarily uninfect it (avoid to save it again).
22342           suninfect(neighsh);
22343         }
22344       }
22345       senextself(worksh);
22346     }
22347   }
22348 
22349   // R has been formed. Infect missing subfaces again.
22350   for (i = 0; i < missingshlist->len(); i++) {
22351     worksh = * (face *)(* missingshlist)[i];
22352     sinfect(worksh);
22353   }
22354 }
22355 
22357 //                                                                           //
22358 // rearrangesubfaces()    Rearrange the set of subfaces of a missing region  //
22359 //                        so that they conform to the faces of DT.           //
22360 //                                                                           //
22361 // The missing region formed by subfaces of 'missingshlist' contains a set   //
22362 // of degenerate vertices, hence the set of subfaces don't match the set of  //
22363 // faces in DT.  Instead of forcing them to present in DT, we re-arrange the //
22364 // connection of them so that the new subfaces conform to the faces of DT.   //
22365 // 'boundedgelist' is a set of boundary edges of the region, these edges(may //
22366 // be subsegments) must exist in DT.                                         //
22367 //                                                                           //
22368 // On completion, we have created and inserted a set of new subfaces which   //
22369 // conform to faces of DT. The set of old subfaces in 'missingshlist' are    //
22370 // deleted. The region vertices in 'equatptlist' are unmarked.               //
22371 //                                                                           //
22373 
22374 void tetgenmesh::rearrangesubfaces(list* missingshlist, list* boundedgelist,
22375   list* equatptlist, int* worklist)
22376 {
22377   link *boundedgelink;
22378   link *newshlink;
22379   triface starttet, spintet, neightet, worktet;
22380   face shloop, newsh, neighsh, spinsh, worksh;
22381   face workseg, casingin, casingout;
22382   point torg, tdest, workpt;
22383   point spt1, spt2, spt3;
22384   enum finddirectionresult collinear;
22385   enum shestype shtype;
22386   REAL area;
22387   bool matchflag, finishflag;
22388   int shmark, pbcgp, idx, hitbdry;
22389   int i, j;
22390 
22391   // Initialize the boundary edge link.
22392   boundedgelink = new link(sizeof(face), NULL, 256);
22393   // Initialize the new subface link.
22394   newshlink = new link(sizeof(face), NULL, 256);
22395   // Remember the type (skinny or not) of replaced subfaces.  They should
22396   //   all have the same type since there is no segment inside the region.
22397   worksh = * (face *)(* missingshlist)[0];
22398   shtype = shelltype(worksh);
22399   // The following loop is only for checking purpose.
22400   for (i = 1; i < missingshlist->len(); i++) {
22401     worksh = * (face *)(* missingshlist)[i];
22402     assert(shelltype(worksh) == shtype);
22403   }
22404   // To avoid compilation warnings.
22405   shmark = pbcgp = 0;
22406   area = 0.0;
22407 
22408   // Create an initial boundary link.
22409   for (i = 0; i < boundedgelist->len(); i++) {
22410     shloop = * (face *)(* boundedgelist)[i];
22411     if (i == 0) {
22412       // 'shmark' will be set to all new created subfaces.
22413       shmark = shellmark(shloop);
22414       if (b->quality && varconstraint) {
22415         // area will be copied to all new created subfaces.
22416         area = areabound(shloop);
22417       }
22418       if (checkpbcs) {
22419         // pbcgp will be copied to all new created subfaces.
22420         pbcgp = shellpbcgroup(shloop);
22421       }
22422       // Get the abovepoint of this facet.
22423       abovepoint = facetabovepointarray[shellmark(shloop)];
22424       if (abovepoint == (point) NULL) {
22425         getfacetabovepoint(&shloop);
22426       }
22427     }
22428     sspivot(shloop, workseg);
22429     if (workseg.sh == dummysh) {
22430       // This edge is an interior edge.
22431       spivot(shloop, neighsh);
22432       boundedgelink->add(&neighsh);
22433     } else {
22434       // This side has a segment, the edge exists.
22435       boundedgelink->add(&shloop);
22436     }
22437   }
22438 
22439   // Each edge ab of boundedgelink will be finished by finding a vertex c
22440   //   which is a vertex of the missing region, such that:
22441   //   (1) abc is inside the missing region, i.e., abc intersects at least
22442   //       one of missing subfaces (saved in missingshlist);
22443   //   (2) abc is not intersect with any previously created new subfaces
22444   //       in the missing region (saved in newshlink).
22445   //   After abc is created, it will be inserted into both the surface mesh
22446   //   and the DT. The boundedgelink will be updated, ab is removed, bc and
22447   //   ca will be added if they are open.
22448 
22449   while (boundedgelink->len() > 0) {
22450     // Remove an edge (ab) from the link.
22451     shloop = * (face *) boundedgelink->del(1);
22452     // 'workseg' indicates it is a segment or not.
22453     sspivot(shloop, workseg);
22454     torg = sorg(shloop);  // torg = a;
22455     tdest = sdest(shloop);  // tdest = b;
22456     // Find a tetrahedron containing ab.
22457     getsearchtet(torg, tdest, &starttet, &workpt);
22458     collinear = finddirection(&starttet, workpt, tetrahedrons->items);
22459     if (collinear == LEFTCOLLINEAR) {
22460       enext2self(starttet);
22461       esymself(starttet);
22462     } else if (collinear == TOPCOLLINEAR) {
22463       fnextself(starttet);
22464       enext2self(starttet);
22465       esymself(starttet);
22466     }
22467     assert(dest(starttet) == workpt);
22468     // Checking faces around ab until a valid face is found.
22469     matchflag = false;
22470     spintet = starttet;
22471     hitbdry = 0;
22472     do {
22473       workpt = apex(spintet);
22474       idx = pointmark(workpt) - in->firstnumber;
22475       if (worklist[idx] == 1) {
22476         // (trog, tdest, workpt) is on the facet. Check if it satisfies (1).
22477         finishflag = false;
22478         for (i = 0; i < missingshlist->len(); i++) {
22479           worksh = * (face *)(* missingshlist)[i];
22480           spt1 = sorg(worksh);
22481           spt2 = sdest(worksh);
22482           spt3 = sapex(worksh);
22483           // Does bc intersect the face?
22484           if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22485               == INTERSECT) {
22486             finishflag = true; break;
22487           }
22488           // Does ca intersect the face?
22489           if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22490               == INTERSECT) {
22491             finishflag = true; break;
22492           }
22493           // Does c inside the face?
22494           if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22495               == INTERSECT) {
22496             finishflag = true; break;
22497           }
22498         }
22499         if (finishflag) {
22500           // Satisfying (1). Check if it satisfies (2).
22501           matchflag = true;
22502           for (i = 0; i < newshlink->len() && matchflag; i++) {
22503             worksh = * (face *) newshlink->getnitem(i + 1);
22504             spt1 = sorg(worksh);
22505             spt2 = sdest(worksh);
22506             spt3 = sapex(worksh);
22507             // Does bc intersect the face?
22508             if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22509                 == INTERSECT) {
22510               matchflag = false; break;
22511             }
22512             // Does ca intersect the face?
22513             if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22514                 == INTERSECT) {
22515               matchflag = false; break;
22516             }
22517             // Does c inside the face?
22518             if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22519                 == INTERSECT) {
22520               matchflag = false; break;
22521             }
22522           }
22523         }
22524         if (matchflag == true) {
22525           // Satisfying both (1) and (2). Find abc.
22526           break;
22527         }
22528       }
22529       if (!fnextself(spintet)) {
22530         hitbdry ++;
22531         if (hitbdry < 2) {
22532           esym(starttet, spintet);
22533           if (!fnextself(spintet)) {
22534             hitbdry ++;
22535           }
22536         }
22537       }
22538     } while (hitbdry < 2 && apex(spintet) != apex(starttet));
22539     assert(matchflag == true);
22540     tspivot(spintet, neighsh);
22541     if (neighsh.sh != dummysh) {
22542       printf("Error:  Invalid PLC.\n");
22543       printf("  Facet #%d and facet #%d overlap each other.\n",
22544              shellmark(neighsh), shellmark(shloop));
22545       printf("  It might be caused by a facet is defined more than once.\n");
22546       printf("  Hint:  Use -d switch to find all overlapping facets.\n");
22547       exit(1);
22548     }
22549     // The side of 'spintet' is at which a new subface will be attached.
22550     adjustedgering(spintet, CCW);
22551     // Create the new subface.
22552     makeshellface(subfaces, &newsh);
22553     setsorg(newsh, org(spintet));
22554     setsdest(newsh, dest(spintet));
22555     setsapex(newsh, apex(spintet));
22556     if (b->quality && varconstraint) {
22557       setareabound(newsh, area);
22558     }
22559     if (checkpbcs) {
22560       setshellpbcgroup(newsh, pbcgp);
22561     }
22562     setshellmark(newsh, shmark);
22563     setshelltype(newsh, shtype);  // It may be a skinny subface.
22564     // Add newsh into newshlink for intersecting checking.
22565     newshlink->add(&newsh);
22566     // Insert it into the current mesh.
22567     tsbond(spintet, newsh);
22568     sym(spintet, neightet);
22569     if (neightet.tet != dummytet) {
22570       sesym(newsh, neighsh);
22571       tsbond(neightet, neighsh);
22572     }
22573     // Insert it into the surface mesh.
22574     sspivot(shloop, workseg);
22575     if (workseg.sh == dummysh) {
22576       sbond(shloop, newsh);
22577     } else {
22578       // There is a subsegment, 'shloop' is the subface which is going to
22579       //   die. Insert the 'newsh' at the place of 'shloop' into its face
22580       //   link, so as to dettach 'shloop'.   The original connection is:
22581       //   -> casingin -> shloop -> casingout ->, it will be changed with:
22582       //   -> casingin ->  newsh -> casingout ->.  Pay attention to the
22583       //   case when this subsegment is dangling in the mesh, i.e., 'shloop'
22584       //   is bonded to itself.
22585       spivot(shloop, casingout);
22586       if (shloop.sh != casingout.sh) {
22587         // 'shloop' is not bonded to itself.
22588         spinsh = casingout;
22589         do {
22590           casingin = spinsh;
22591           spivotself(spinsh);
22592         } while (sapex(spinsh) != sapex(shloop));
22593         assert(casingin.sh != shloop.sh);
22594         // Bond casingin -> newsh -> casingout.
22595         sbond1(casingin, newsh);
22596         sbond1(newsh, casingout);
22597       } else {
22598         // Bond newsh -> newsh.
22599         sbond(newsh, newsh);
22600       }
22601       // Bond the segment.
22602       ssbond(newsh, workseg);
22603     }
22604     // Check other two sides of this new subface.  If a side is not bonded
22605     //   to any edge in the link, it will be added to the link.
22606     for (i = 0; i < 2; i++) {
22607       if (i == 0) {
22608         senext(newsh, worksh);
22609       } else {
22610         senext2(newsh, worksh);
22611       }
22612       torg = sorg(worksh);
22613       tdest = sdest(worksh);
22614       finishflag = false;
22615       for (j = 0; j < boundedgelink->len() && !finishflag; j++) {
22616         neighsh = * (face *) boundedgelink->getnitem(j + 1);
22617         if ((sorg(neighsh) == torg && sdest(neighsh) == tdest) ||
22618             (sorg(neighsh) == tdest && sdest(neighsh) == torg)) {
22619           // Find a boundary edge.  Bond them and exit the loop.
22620           sspivot(neighsh, workseg);
22621           if (workseg.sh == dummysh) {
22622             sbond(neighsh, worksh);
22623           } else {
22624             // There is a subsegment, 'neighsh' is the subface which is
22625             //   going to die. Do the same as above for 'worksh'.
22626             spivot(neighsh, casingout);
22627             if (neighsh.sh != casingout.sh) {
22628               // 'neighsh' is not bonded to itself.
22629               spinsh = casingout;
22630               do {
22631                 casingin = spinsh;
22632                 spivotself(spinsh);
22633               } while (sapex(spinsh) != sapex(neighsh));
22634               assert(casingin.sh != neighsh.sh);
22635               // Bond casingin -> worksh -> casingout.
22636               sbond1(casingin, worksh);
22637               sbond1(worksh, casingout);
22638             } else {
22639               // Bond worksh -> worksh.
22640               sbond(worksh, worksh);
22641             }
22642             // Bond the segment.
22643             ssbond(worksh, workseg);
22644           }
22645           // Remove this boundary edge from the link.
22646           boundedgelink->del(j + 1);
22647           finishflag = true;
22648         }
22649       }
22650       if (!finishflag) {
22651         // It's a new boundary edge, add it to link.
22652         boundedgelink->add(&worksh);
22653       }
22654     }
22655   }
22656 
22657   // Deallocate the set of old missing subfaces.
22658   for (i = 0; i < missingshlist->len(); i++) {
22659     worksh = * (face *)(* missingshlist)[i];
22660     shellfacedealloc(subfaces, worksh.sh);
22661   }
22662   // Unmark region vertices in 'worklist'.
22663   for (i = 0; i < equatptlist->len(); i++) {
22664     workpt = * (point *)(* equatptlist)[i];
22665     idx = pointmark(workpt) - in->firstnumber;
22666     worklist[idx] = 0;
22667   }
22668 
22669   delete boundedgelink;
22670   delete newshlink;
22671 }
22672 
22674 //                                                                           //
22675 // scoutcrossingedge()    Search an edge crossing the missing region.        //
22676 //                                                                           //
22677 // 'missingshlist' forms the missing region R. This routine searches for an  //
22678 // edge crossing R.  It first forms a 'boundedgelist' consisting of the      //
22679 // boundary edges of R. Such edges are existing in CDT.  A crossing edge is  //
22680 // found by rotating faces around one of the boundary edges. It is possible  //
22681 // there is no edge crosses R (e.g. R has a degenerate point set).           //
22682 //                                                                           //
22683 // If find a croosing edge, return TRUE, 'crossedgelist' contains this edge. //
22684 // Otherwise, return FALSE.                                                  //
22685 //                                                                           //
22687 
22688 bool tetgenmesh::scoutcrossingedge(list* missingshlist, list* boundedgelist,
22689   list* crossedgelist, int* worklist)
22690 {
22691   triface starttet, spintet, worktet;
22692   face startsh, neighsh, worksh, workseg;
22693   point torg, tdest, tapex;
22694   point workpt[3], pa, pb, pc;
22695   enum finddirectionresult collinear;
22696   REAL ori1, ori2;
22697   bool crossflag;
22698   int hitbdry;
22699   int i, j, k;
22700 
22701   // Form the 'boundedgelist'. Loop through 'missingshlist', check each
22702   //   edge of these subfaces. If an edge is a segment or the neighbor
22703   //   subface is uninfected, add it to 'boundedgelist'.
22704   for (i = 0; i < missingshlist->len(); i++) {
22705     worksh = * (face *)(* missingshlist)[i];
22706     for (j = 0; j < 3; j++) {
22707       sspivot(worksh, workseg);
22708       if (workseg.sh == dummysh) {
22709         spivot(worksh, neighsh);
22710         if (!sinfected(neighsh)) {
22711           boundedgelist->append(&worksh);
22712         }
22713       } else {
22714         boundedgelist->append(&worksh);
22715       }
22716       senextself(worksh);
22717     }
22718   }
22719 
22720   crossflag = false;
22721   // Find a crossing edge. It is possible there is no such edge. We need to
22722   //   loop through all edges of 'boundedgelist' for sure we don't miss any.
22723   for (i = 0; i < boundedgelist->len() && !crossflag; i++) {
22724     startsh = * (face *)(* boundedgelist)[i];
22725     // 'startsh' (abc) holds an existing edge of the DT, find it.
22726     torg = sorg(startsh);
22727     tdest = sdest(startsh);
22728     tapex = sapex(startsh);
22729     getsearchtet(torg, tdest, &starttet, &workpt[0]);
22730     collinear = finddirection(&starttet, workpt[0], tetrahedrons->items);
22731     if (collinear == LEFTCOLLINEAR) {
22732       enext2self(starttet);
22733       esymself(starttet);
22734     } else if (collinear == TOPCOLLINEAR) {
22735       fnextself(starttet);
22736       enext2self(starttet);
22737       esymself(starttet);
22738     }
22739 #ifdef SELF_CHECK
22740     assert(dest(starttet) == workpt[0]);
22741 #endif
22742     // Now starttet holds edge ab. Find is edge de crossing R.
22743     spintet = starttet;
22744     hitbdry = 0;
22745     do {
22746       if (fnextself(spintet)) {
22747         // splittet = abde. Check if de crosses abc.
22748         workpt[1] = apex(spintet);  // workpt[1] = d.
22749         workpt[2] = oppo(spintet);  // workpt[2] = e.
22750         j = pointmark(workpt[1]) - in->firstnumber;
22751         k = pointmark(workpt[2]) - in->firstnumber;
22752         if (worklist[j] == 1) {
22753           ori1 = 0.0; // d is a vertex of the missing region.
22754         } else {
22755           // Get the orientation of d wrt. abc.
22756           ori1 = orient3d(torg, tdest, tapex, workpt[1]);
22757         }
22758         if (worklist[k] == 1) {
22759           ori2 = 0.0; // e is a vertex of the missing region.
22760         } else {
22761           // Get the orientation of e wrt. abc.
22762           ori2 = orient3d(torg, tdest, tapex, workpt[2]);
22763         }
22764         // Only do check if d and e locate on different sides of abc.
22765         if (ori1 * ori2 < 0.0) {
22766           // Check if de crosses any subface of R.
22767           for (j = 0; j < missingshlist->len(); j++) {
22768             worksh = * (face *)(* missingshlist)[j];
22769             pa = sorg(worksh);
22770             pb = sdest(worksh);
22771             pc = sapex(worksh);
22772             crossflag = (tri_tri_inter(pa, pb, pc, workpt[0], workpt[1],
22773                                        workpt[2]) == INTERSECT);
22774             if (crossflag) {
22775               // Find a crossing edge. We're done.
22776               worktet = spintet;
22777               adjustedgering(worktet, CCW);
22778               enextfnextself(worktet);
22779               enextself(worktet);
22780               // Add this edge (worktet) into 'crossedgelist'.
22781               crossedgelist->append(&worktet);
22782               break;
22783             }
22784           }
22785           if (crossflag) break;
22786         }
22787         if (apex(spintet) == apex(starttet)) break;
22788       } else {
22789         hitbdry++;
22790         // It is only possible to hit boundary once.
22791         if (hitbdry < 2) {
22792           esym(starttet, spintet);
22793         }
22794       }
22795     } while (hitbdry < 2);
22796   }
22797 
22798   return crossflag;
22799 }
22800 
22802 //                                                                           //
22803 // formcavity()    Form the cavity for recovering the missing region.        //
22804 //                                                                           //
22805 // The cavity C is bounded by faces of current CDT.  All tetrahedra inside C //
22806 // will be removed, intead a set of constrained Delaunay tetrahedra will be  //
22807 // filled in and the missing region are recovered.                           //
22808 //                                                                           //
22809 // 'missingshlist' contains a set of subfaces forming the missing region R.  //
22810 // C is formed by first finding all the tetrahedra in CDT that intersect the //
22811 // relative interior of R; then deleting them from the CDT, this will form C //
22812 // inside the CDT. At the beginning, 'crossedgelist' contains an edge which  //
22813 // is crossing R. All tets containing this edge must cross R. Start from it, //
22814 // other crossing edges can be found incrementally.  The discovered crossing //
22815 // tets are saved in 'crosstetlist'.                                         //
22816 //                                                                           //
22817 // Notice that not all tets in 'crosstetlist' are crossing R. The discovered //
22818 // tets are connected each other. However, there may be other tets crossing  //
22819 // R but disjoint with the found tets. Due to this fact we need to check the //
22820 // 'missingshlist' once more. Only recover those subfaces which are crossed  //
22821 // by the set of discovered tets, i.e., R may be shrinked to conform the set //
22822 // of discovered tets. The extra subfaces of R will be recovered later.      //
22823 //                                                                           //
22824 // Notice that some previous recovered subfaces may completely included in C.//
22825 // This can happen when R is very big and these subfaces lie above R and so  //
22826 // close to it. Such subfaces have to be queued (and sinfected()) to recover //
22827 // them later. Otherwise, we lost the connection to these subfaces forever.  //
22828 //                                                                           //
22830 
22831 void tetgenmesh::formcavity(list* missingshlist, list* crossedgelist,
22832   list* equatptlist, list* crossshlist, list* crosstetlist,
22833   list* belowfacelist, list* abovefacelist, list* horizptlist,
22834   list* belowptlist, list* aboveptlist, queue* missingshqueue, int* worklist)
22835 {
22836   triface starttet, spintet, neightet, worktet;
22837   face startsh, neighsh, worksh, workseg;
22838   point torg, tdest, tapex, workpt[3];
22839   REAL checksign, orgori, destori;
22840   bool crossflag, inlistflag;
22841   bool belowflag, aboveflag;
22842   int idx, share;
22843   int i, j, k;
22844 
22845   // Get a face at horizon.
22846   startsh = * (face *)(* missingshlist)[0];
22847   torg = sorg(startsh);
22848   tdest = sdest(startsh);
22849   tapex = sapex(startsh);
22850 
22851   // Collect the set of crossing tetrahedra by rotating crossing edges.
22852   for (i = 0; i < crossedgelist->len(); i++) {
22853     // Get a tet abcd, ab is a crossing edge.
22854     starttet = * (triface *)(* crossedgelist)[i];
22855     adjustedgering(starttet, CCW);
22856     if (b->verbose > 2) {
22857       printf("    Collect tets containing edge (%d, %d).\n",
22858              pointmark(org(starttet)), pointmark(dest(starttet)));
22859     }
22860     orgori = orient3d(torg, tdest, tapex, org(starttet));
22861     destori = orient3d(torg, tdest, tapex, dest(starttet));
22862 #ifdef SELF_CHECK
22863     assert(orgori * destori < 0.0);
22864 #endif
22865     spintet = starttet;
22866     do {
22867       // The face rotation should not meet boundary.
22868       fnextself(spintet);
22869       // Check the validity of the PLC.
22870       tspivot(spintet, worksh);
22871       if (worksh.sh != dummysh) {
22872         printf("Error:  Invalid PLC.\n");
22873         printf("  Two subfaces (%d, %d, %d) and (%d, %d, %d)\n",
22874                pointmark(torg), pointmark(tdest), pointmark(tapex),
22875                pointmark(sorg(worksh)), pointmark(sdest(worksh)),
22876                pointmark(sapex(worksh)));
22877         printf("  are found intersecting each other.\n");
22878         printf("  Hint:  Use -d switch to find all intersecting facets.\n");
22879         terminatetetgen(1);
22880       }
22881       if (!infected(spintet)) {
22882         if (b->verbose > 2) {
22883           printf("      Add crossing tet (%d, %d, %d, %d).\n",
22884                  pointmark(org(spintet)), pointmark(dest(spintet)),
22885                  pointmark(apex(spintet)), pointmark(oppo(spintet)));
22886         }
22887         infect(spintet);
22888         crosstetlist->append(&spintet);
22889       }
22890       // Check whether other two edges of 'spintet' is a crossing edge.
22891       //   It can be quickly checked from the apex of 'spintet', if it is
22892       //   not on the facet, then there exists a crossing edge.
22893       workpt[0] = apex(spintet);
22894       idx = pointmark(workpt[0]) - in->firstnumber;
22895       if (worklist[idx] != 1) {
22896         // Either edge (dest, apex) or edge (apex, org) crosses.
22897         checksign = orient3d(torg, tdest, tapex, workpt[0]);
22898 #ifdef SELF_CHECK
22899         assert(checksign != 0.0);
22900 #endif
22901         if (checksign * orgori < 0.0) {
22902           enext2(spintet, worktet); // edge (apex, org).
22903           workpt[1] = org(spintet);
22904         } else {
22905 //#ifdef SELF_CHECK // commented out to get gcc 4.6 working
22906           assert(checksign * destori < 0.0);
22907 //#endif
22908           enext(spintet, worktet);  // edge (dest, apex).
22909           workpt[1] = dest(spintet);
22910         }
22911         // 'worktet' represents the crossing edge. Add it into list only
22912         //   it doesn't exist in 'crossedgelist'.
22913         inlistflag = false;
22914         for (j = 0; j < crossedgelist->len() && !inlistflag; j++) {
22915           neightet = * (triface *)(* crossedgelist)[j];
22916           if (org(neightet) == workpt[0]) {
22917             if (dest(neightet) == workpt[1]) inlistflag = true;
22918           } else if (org(neightet) == workpt[1]) {
22919             if (dest(neightet) == workpt[0]) inlistflag = true;
22920           }
22921         }
22922         if (!inlistflag) {
22923           crossedgelist->append(&worktet);
22924         }
22925       }
22926     } while (apex(spintet) != apex(starttet));
22927   }
22928 
22929   // Identifying the boundary faces and vertices of C. Sort them into
22930   //   'abovefacelist', 'aboveptlist, 'belowfacelist', and 'belowptlist',
22931   //    respectively. "above" and "below" are wrt.(torg, tdest, tapex).
22932   for (i = 0; i < crosstetlist->len(); i++) {
22933     // Get a tet abcd, ab is the crossing edge.
22934     starttet = * (triface *)(* crosstetlist)[i];
22935 #ifdef SELF_CHECK
22936     assert(infected(starttet));
22937 #endif
22938     adjustedgering(starttet, CCW);
22939     // abc and abd are sharing the crossing edge, the two neighbors must
22940     //   be crossing tetrahedra too. They can't be boundaries of C.
22941     for (j = 0; j < 2; j++) {
22942       if (j == 0) {
22943         enextfnext(starttet, worktet); // Check bcd.
22944       } else {
22945         enext2fnext(starttet, worktet); // Check acd.
22946       }
22947       sym(worktet, neightet);
22948       // If the neighbor doesn't exist or exists but doesn't be infected,
22949       //   it's a boundary face of C, save it.
22950       if ((neightet.tet == dummytet) || !infected(neightet)) {
22951         workpt[0] = org(worktet);
22952         workpt[1] = dest(worktet);
22953         workpt[2] = apex(worktet);
22954         belowflag = aboveflag = false;
22955         share = 0;
22956         for (k = 0; k < 3; k++) {
22957           idx = pointmark(workpt[k]) - in->firstnumber;
22958           if (worklist[idx] == 0) {
22959             // It's not a vertices of facet, find which side it lies.
22960             checksign = orient3d(torg, tdest, tapex, workpt[k]);
22961 #ifdef SELF_CHECK
22962             assert(checksign != 0.0);
22963 #endif
22964             if (checksign > 0.0) {
22965               // It lies "below" the facet wrt. 'startsh'.
22966               worklist[idx] = 2;
22967               belowptlist->append(&workpt[k]);
22968             } else if (checksign < 0.0) {
22969               // It lies "above" the facet wrt. 'startsh'.
22970               worklist[idx] = 3;
22971               aboveptlist->append(&workpt[k]);
22972             }
22973           }
22974           if (worklist[idx] == 2) {
22975             // This face lies "below" the facet wrt. 'startsh'.
22976             belowflag = true;
22977           } else if (worklist[idx] == 3) {
22978             // This face lies "above" the facet wrt. 'startsh'.
22979             aboveflag = true;
22980           } else {
22981 #ifdef SELF_CHECK
22982             // In degenerate case, this face may just be the equator.
22983             assert(worklist[idx] == 1);
22984 #endif
22985             share++;
22986           }
22987         }
22988 #ifdef SELF_CHECK
22989         // The degenerate case has been ruled out.
22990         assert(share < 3);
22991         // Only one flag is possible for a cavity face.
22992         assert(belowflag ^ aboveflag);
22993 #endif
22994         if (belowflag) {
22995           belowfacelist->append(&worktet);
22996         } else if (aboveflag) {
22997           abovefacelist->append(&worktet);
22998         }
22999       }
23000     }
23001   }
23002 
23003   // Shrink R if not all its subfaces are crossing by the discovered tets.
23004   //   'crossshlist' and 'horizptlist' represent the set of subfaces and
23005   //   vertices of the shrinked missing region, respectively.
23006   for (i = 0; i < missingshlist->len(); i++) {
23007     worksh = * (face *)(* missingshlist)[i];
23008 #ifdef SELF_CHECK
23009     assert(sinfected(worksh));
23010 #endif
23011     workpt[0] = sorg(worksh);
23012     workpt[1] = sdest(worksh);
23013     workpt[2] = sapex(worksh);
23014     crossflag = false;
23015     for (j = 0; j < crosstetlist->len() && !crossflag; j++) {
23016       // Get a tet abcd, ab is a crossing edge.
23017       starttet = * (triface *)(* crosstetlist)[j];
23018       adjustedgering(starttet, CCW);
23019       // Only need to check two sides of worktet.
23020       for (k = 0; k < 2 && !crossflag; k++) {
23021         if (k == 0) {
23022           worktet = starttet; // Check abc.
23023         } else {
23024           fnext(starttet, worktet); // Check abd.
23025         }
23026         crossflag = tritritest(&worktet, workpt[0], workpt[1], workpt[2]);
23027       }
23028     }
23029     if (crossflag) {
23030       // 'worksh' is crossed by 'worktet', uninfect it.
23031       suninfect(worksh);
23032       crossshlist->append(&worksh);
23033       // Add its corners into 'horizptlist'.
23034       for (k = 0; k < 3; k++) {
23035         idx = pointmark(workpt[k]) - in->firstnumber;
23036         if (worklist[idx] != 4) {
23037           worklist[idx] = 4;
23038           horizptlist->append(&workpt[k]);
23039         }
23040       }
23041     }
23042   }
23043 
23044   // Check 'crossingtetlist'. Queue subfaces inside them.
23045   for (i = 0; i < crosstetlist->len(); i++) {
23046     starttet = * (triface *)(* crosstetlist)[i];
23047     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
23048       sym(starttet, neightet);
23049       // If the neighbor exist and is infected, check it.
23050       if ((neightet.tet != dummytet) && infected(neightet)) {
23051         tspivot(starttet, worksh);
23052         if (worksh.sh != dummysh) {
23053           // Temporarily remove worksh. Make it missing. recover it later.
23054           if (b->verbose > 2) {
23055             printf("    Queuing subface (%d, %d, %d).\n",
23056                    pointmark(sorg(worksh)), pointmark(sdest(worksh)),
23057                    pointmark(sapex(worksh)));
23058           }
23059           tsdissolve(neightet);
23060           tsdissolve(starttet);
23061           // Detach tets at the both sides of this subface.
23062           stdissolve(worksh);
23063           sesymself(worksh);
23064           stdissolve(worksh);
23065           sinfect(worksh);
23066           missingshqueue->push(&worksh);
23067         }
23068       }
23069     }
23070   }
23071 
23072   // Clear flags set in 'worklist'.
23073   for (i = 0; i < equatptlist->len(); i++) {
23074     workpt[0] = * (point *)(* equatptlist)[i];
23075     idx = pointmark(workpt[0]) - in->firstnumber;
23076 #ifdef SELF_CHECK
23077     assert((worklist[idx] == 1) || (worklist[idx] == 4));
23078 #endif
23079     worklist[idx] = 0;
23080   }
23081   for (i = 0; i < belowptlist->len(); i++) {
23082     workpt[0] = * (point *)(* belowptlist)[i];
23083     idx = pointmark(workpt[0]) - in->firstnumber;
23084 #ifdef SELF_CHECK
23085     assert(worklist[idx] == 2);
23086 #endif
23087     worklist[idx] = 0;
23088   }
23089   for (i = 0; i < aboveptlist->len(); i++) {
23090     workpt[0] = * (point *)(* aboveptlist)[i];
23091     idx = pointmark(workpt[0]) - in->firstnumber;
23092 #ifdef SELF_CHECK
23093     assert(worklist[idx] == 3);
23094 #endif
23095     worklist[idx] = 0;
23096   }
23097 }
23098 
23100 //                                                                           //
23101 // insertallsubfaces()    Insert all subfaces, queue missing subfaces.       //
23102 //                                                                           //
23103 // Loop through all subfaces, insert each into the DT. If one already exists,//
23104 // bond it to the tetrahedra having it. Otherwise, it is missing, infect it  //
23105 // and save it in 'missingshqueue'.                                          //
23106 //                                                                           //
23108 
23109 void tetgenmesh::insertallsubfaces(queue* missingshqueue)
23110 {
23111   triface searchtet;
23112   face subloop;
23113 
23114   searchtet.tet = (tetrahedron *) NULL;
23115   subfaces->traversalinit();
23116   subloop.sh = shellfacetraverse(subfaces);
23117   while (subloop.sh != (shellface *) NULL) {
23118     if (!insertsubface(&subloop, &searchtet)) {
23119       if (b->verbose > 1) {
23120         printf("    Queuing subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23121                pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23122       }
23123       sinfect(subloop);
23124       missingshqueue->push(&subloop);
23125     }
23126     subloop.sh = shellfacetraverse(subfaces);
23127   }
23128 }
23129 
23131 //                                                                           //
23132 // constrainedfacets()    Recover subfaces in a Delaunay tetrahedralization. //
23133 //                                                                           //
23134 // This routine creates a CDT by incrementally updating a DT D into a CDT T. //
23135 // The process of recovering facets can be imagined by "merging" the surface //
23136 // mesh F into D. At the beginning, F and D are completely seperated.  Some  //
23137 // faces of them are matching some are not because they are crossed by some  //
23138 // tetrahedra of D. The non-matching subfaces will be forced to appear in T  //
23139 // by locally retetrahedralizing the regions where F and D are intersecting. //
23140 //                                                                           //
23141 // When a subface s of F is found missing in D, probably some other subfaces //
23142 // near to s are missing too.  The set of adjoining coplanar missing faces   //
23143 // forms a missing region R (R may not simply connected).                    //
23144 //                                                                           //
23145 // There are two possibilities can result a mssing region R: (1) Some edges  //
23146 // of D cross R; (2) No edge of D crosses R, but some faces of D spans R, ie,//
23147 // D is locally degenerate at R. In case (1), D is modified so that it resp- //
23148 // ects R (done by a cavity retetrahedralization algorithm).  In case (2), F //
23149 // is modified so that the set of subfaces of R matches faces in D (done by  //
23150 // a face rearrangment algorithm).                                           //
23151 //                                                                           //
23153 
23154 void tetgenmesh::constrainedfacets()
23155 {
23156   queue *missingshqueue, *flipque;
23157   list *missingshlist, *equatptlist;
23158   list *boundedgelist, *crossedgelist, *crosstetlist;
23159   list *crossshlist, *belowfacelist, *abovefacelist;
23160   list *horizptlist, *belowptlist, *aboveptlist;
23161   list *frontlist, *misfrontlist, *newtetlist;
23162   triface searchtet, worktet;
23163   face subloop, worksh;
23164   int *worklist;
23165   int i;
23166 
23167   if (!b->quiet) {
23168     printf("Constraining facets.\n");
23169   }
23170 
23171   // Initialize queues.
23172   missingshqueue = new queue(sizeof(face));
23173   flipque = new queue(sizeof(badface));
23174   // Initialize the working lists.
23175   missingshlist = new list(sizeof(face), NULL);
23176   boundedgelist = new list(sizeof(face), NULL);
23177   crossedgelist = new list(sizeof(triface), NULL);
23178   equatptlist = new list((char*) "point *");
23179   crossshlist = new list(sizeof(face), NULL);
23180   crosstetlist = new list(sizeof(triface), NULL);
23181   belowfacelist = new list(sizeof(triface), NULL);
23182   abovefacelist = new list(sizeof(triface), NULL);
23183   horizptlist = new list((char*)"point *");
23184   belowptlist = new list((char*)"point *");
23185   aboveptlist = new list((char*)"point *");
23186   frontlist = new list(sizeof(triface), NULL);
23187   misfrontlist = new list(sizeof(triface), NULL);
23188   newtetlist = new list(sizeof(triface), NULL);
23189   // Initialize the array for marking vertices.
23190   worklist = new int[points->items + 1];
23191   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
23192 
23193   // Compute a mapping from points to tetrahedra for fast searching.
23194   makepoint2tetmap();
23195 
23196   // Match subfaces in D, queue all missing subfaces.
23197   insertallsubfaces(missingshqueue);
23198 
23199   // Recover all missing subfaces.
23200   while (!missingshqueue->empty()) {
23201     // Get a queued face s.
23202     subloop = * (face *) missingshqueue->pop();
23203     // s may have been deleted in a face rearrangment operation.
23204     if (isdead(&subloop)) continue;
23205     // s may have been recovered in a previous missing region.
23206     if (!sinfected(subloop)) continue;
23207     // s may match a face in D now due to previous transformations.
23208     if (insertsubface(&subloop, &searchtet)) {
23209       suninfect(subloop);
23210       continue;
23211     }
23212     if (b->verbose > 1) {
23213       printf("    Recover subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23214              pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23215     }
23216     // Form the missing region R containing s.
23217     formmissingregion(&subloop, missingshlist, equatptlist, worklist);
23218     // Is R crossing by any tetrahedron?
23219     if (scoutcrossingedge(missingshlist, boundedgelist, crossedgelist,
23220                           worklist)) {
23221       // Form the cavity C containing R.
23222       formcavity(missingshlist, crossedgelist, equatptlist, crossshlist,
23223                  crosstetlist, belowfacelist, abovefacelist, horizptlist,
23224                  belowptlist, aboveptlist, missingshqueue, worklist);
23225       // Recover the above part of C.
23226       delaunizecavity(crossshlist, abovefacelist, aboveptlist, horizptlist,
23227                       frontlist, misfrontlist, newtetlist, crosstetlist,
23228                       missingshqueue, flipque);
23229       // Inverse the direction of subfaces in R.
23230       for (i = 0; i < crossshlist->len(); i++) {
23231         worksh = * (face *)(* crossshlist)[i];
23232         sesymself(worksh);
23233         * (face *)(* crossshlist)[i] = worksh;
23234       }
23235       // Recover the below part of C.
23236       delaunizecavity(crossshlist, belowfacelist, belowptlist, horizptlist,
23237                       frontlist, misfrontlist, newtetlist, crosstetlist,
23238                       missingshqueue, flipque);
23239       // Delete tetrahedra in C.
23240       for (i = 0; i < crosstetlist->len(); i++) {
23241         worktet = * (triface *)(* crosstetlist)[i];
23242         tetrahedrondealloc(worktet.tet);
23243       }
23244       // There may have some un-recovered subfaces of R. Put them back into
23245       //   queue. Otherwise, they will be missing on the boundary.
23246       for (i = 0; i < missingshlist->len(); i++) {
23247         worksh = * (face *)(* missingshlist)[i];
23248         if (sinfected(worksh)) {
23249           // An unrecovered subface, put it back into queue.
23250           missingshqueue->push(&worksh);
23251         }
23252       }
23253       crossshlist->clear();
23254       belowfacelist->clear();
23255       abovefacelist->clear();
23256       horizptlist->clear();
23257       belowptlist->clear();
23258       aboveptlist->clear();
23259       crosstetlist->clear();
23260     } else {
23261       // No. Rearrange subfaces of F conforming to that of D in R. It can
23262       //   happen when the facet has non-coplanar vertices.
23263       rearrangesubfaces(missingshlist, boundedgelist, equatptlist, worklist);
23264     }
23265     // Clear all working lists.
23266     missingshlist->clear();
23267     boundedgelist->clear();
23268     crossedgelist->clear();
23269     equatptlist->clear();
23270   }
23271 
23272   // Subfaces have been merged into D.
23273   checksubfaces = 1;
23274 
23275   if (b->verbose > 0) {
23276     printf("  The biggest cavity: %d faces, %d vertices\n", maxcavfaces,
23277            maxcavverts);
23278     printf("  Enlarged %d times\n", expcavcount);
23279   }
23280 
23281   delete missingshqueue;
23282   delete flipque;
23283   delete missingshlist;
23284   delete boundedgelist;
23285   delete crossedgelist;
23286   delete equatptlist;
23287   delete crossshlist;
23288   delete crosstetlist;
23289   delete belowfacelist;
23290   delete abovefacelist;
23291   delete horizptlist;
23292   delete belowptlist;
23293   delete aboveptlist;
23294   delete frontlist;
23295   delete misfrontlist;
23296   delete newtetlist;
23297   delete [] worklist;
23298 }
23299 
23300 //
23301 // End of facet recovery routines
23302 //
23303 
23304 //
23305 // Begin of carving out holes and concavities routines
23306 //
23307 
23309 //                                                                           //
23310 // infecthull()    Virally infect all of the tetrahedra of the convex hull   //
23311 //                 that are not protected by subfaces.  Where there are      //
23312 //                 subfaces, set boundary markers as appropriate.            //
23313 //                                                                           //
23314 // Memorypool 'viri' is used to return all the infected tetrahedra.          //
23315 //                                                                           //
23317 
23318 void tetgenmesh::infecthull(memorypool *viri)
23319 {
23320   triface tetloop, tsymtet;
23321   tetrahedron **deadtet;
23322   face hullface;
23323   // point horg, hdest, hapex;
23324 
23325   if (b->verbose > 0) {
23326     printf("  Marking concavities for elimination.\n");
23327   }
23328   tetrahedrons->traversalinit();
23329   tetloop.tet = tetrahedrontraverse();
23330   while (tetloop.tet != (tetrahedron *) NULL) {
23331     // Is this tetrahedron on the hull?
23332     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
23333       sym(tetloop, tsymtet);
23334       if (tsymtet.tet == dummytet) {
23335         // Is the tetrahedron protected by a subface?
23336         tspivot(tetloop, hullface);
23337         if (hullface.sh == dummysh) {
23338           // The tetrahedron is not protected; infect it.
23339           if (!infected(tetloop)) {
23340             infect(tetloop);
23341             deadtet = (tetrahedron **) viri->alloc();
23342             *deadtet = tetloop.tet;
23343             break;  // Go and get next tet.
23344           }
23345         } else {
23346           // The tetrahedron is protected; set boundary markers if appropriate.
23347           if (shellmark(hullface) == 0) {
23348             setshellmark(hullface, 1);
23349             /*
23350             horg = sorg(hullface);
23351             hdest = sdest(hullface);
23352             hapex = sapex(hullface);
23353             if (pointmark(horg) == 0) {
23354               setpointmark(horg, 1);
23355             }
23356             if (pointmark(hdest) == 0) {
23357               setpointmark(hdest, 1);
23358             }
23359             if (pointmark(hapex) == 0) {
23360               setpointmark(hapex, 1);
23361             }
23362             */
23363           }
23364         }
23365       }
23366     }
23367     tetloop.tet = tetrahedrontraverse();
23368   }
23369 }
23370 
23372 //                                                                           //
23373 // plague()    Spread the virus from all infected tets to any neighbors not  //
23374 //             protected by subfaces.                                        //
23375 //                                                                           //
23376 // This routine identifies all the tetrahedra that will die, and marks them  //
23377 // as infected.  They are marked to ensure that each tetrahedron is added to //
23378 // the virus pool only once, so the procedure will terminate. 'viri' returns //
23379 // all infected tetrahedra which are outside the domian.                     //
23380 //                                                                           //
23382 
23383 void tetgenmesh::plague(memorypool *viri)
23384 {
23385   tetrahedron **virusloop;
23386   tetrahedron **deadtet;
23387   triface testtet, neighbor;
23388   face neighsh, testseg;
23389   face spinsh, casingin, casingout;
23390   int firstdadsub;
23391   int i;
23392 
23393   if (b->verbose > 0) {
23394     printf("  Marking neighbors of marked tetrahedra.\n");
23395   }
23396   firstdadsub = 0;
23397   // Loop through all the infected tetrahedra, spreading the virus to
23398   //   their neighbors, then to their neighbors' neighbors.
23399   viri->traversalinit();
23400   virusloop = (tetrahedron **) viri->traverse();
23401   while (virusloop != (tetrahedron **) NULL) {
23402     testtet.tet = *virusloop;
23403     // Temporarily uninfect this tetrahedron, not necessary.
23404     uninfect(testtet);
23405     // Check each of the tetrahedron's four neighbors.
23406     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23407       // Find the neighbor.
23408       sym(testtet, neighbor);
23409       // Check for a shell between the tetrahedron and its neighbor.
23410       tspivot(testtet, neighsh);
23411       // Check if the neighbor is nonexistent or already infected.
23412       if ((neighbor.tet == dummytet) || infected(neighbor)) {
23413         if (neighsh.sh != dummysh) {
23414           // There is a subface separating the tetrahedron from its neighbor,
23415           //   but both tetrahedra are dying, so the subface dies too.
23416           // Before deallocte this subface, dissolve the connections between
23417           //   other subfaces, subsegments and tetrahedra.
23418           neighsh.shver = 0;
23419           if (!firstdadsub) {
23420             firstdadsub = 1; // Report the problem once.
23421             if (!b->quiet) {
23422               printf("Warning:  Detecting an open face (%d, %d, %d).\n",
23423                      pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
23424                      pointmark(sapex(neighsh)));
23425             }
23426           }
23427           // For keep the same enext() direction.
23428           findedge(&testtet, sorg(neighsh), sdest(neighsh));
23429           for (i = 0; i < 3; i++) {
23430             sspivot(neighsh, testseg);
23431             if (testseg.sh != dummysh) {
23432               // A subsegment is found at this side, dissolve this subface
23433               //   from the face link of this subsegment.
23434               testseg.shver = 0;
23435               spinsh = neighsh;
23436               if (sorg(spinsh) != sorg(testseg)) {
23437                 sesymself(spinsh);
23438               }
23439               spivot(spinsh, casingout);
23440               if (casingout.sh == spinsh.sh) {
23441                 // This is a trivial face link, only 'neighsh' itself,
23442                 //   the subsegment at this side is also died.
23443                 shellfacedealloc(subsegs, testseg.sh);
23444               } else {
23445                 spinsh = casingout;
23446                 do {
23447                   casingin = spinsh;
23448                   spivotself(spinsh);
23449                 } while (spinsh.sh != neighsh.sh);
23450                 // Set the link casingin->casingout.
23451                 sbond1(casingin, casingout);
23452                 // Bond the subsegment anyway.
23453                 ssbond(casingin, testseg);
23454               }
23455             }
23456             senextself(neighsh);
23457             enextself(testtet);
23458           }
23459           if (neighbor.tet != dummytet) {
23460             // Make sure the subface doesn't get deallocated again later
23461             //   when the infected neighbor is visited.
23462             tsdissolve(neighbor);
23463           }
23464           // This subface has been separated.
23465           if (in->mesh_dim > 2) {
23466             shellfacedealloc(subfaces, neighsh.sh);
23467           } else {
23468             // Dimension is 2. keep it for output.
23469             // Dissolve tets at both sides of this subface.
23470             stdissolve(neighsh);
23471             sesymself(neighsh);
23472             stdissolve(neighsh);
23473           }
23474         }
23475       } else {                   // The neighbor exists and is not infected.
23476         if (neighsh.sh == dummysh) {
23477           // There is no subface protecting the neighbor, infect it.
23478           infect(neighbor);
23479           // Ensure that the neighbor's neighbors will be infected.
23480           deadtet = (tetrahedron **) viri->alloc();
23481           *deadtet = neighbor.tet;
23482         } else {               // The neighbor is protected by a subface.
23483           // Remove this tetrahedron from the subface.
23484           stdissolve(neighsh);
23485           // The subface becomes a boundary.  Set markers accordingly.
23486           if (shellmark(neighsh) == 0) {
23487             setshellmark(neighsh, 1);
23488           }
23489           // This side becomes hull. Update the handle in dummytet.
23490           dummytet[0] = encode(neighbor);
23491         }
23492       }
23493     }
23494     // Remark the tetrahedron as infected, so it doesn't get added to the
23495     //   virus pool again.
23496     infect(testtet);
23497     virusloop = (tetrahedron **) viri->traverse();
23498   }
23499 }
23500 
23502 //                                                                           //
23503 // regionplague()    Spread regional attributes and/or volume constraints    //
23504 //                   (from a .poly file) throughout the mesh.                //
23505 //                                                                           //
23506 // This procedure operates in two phases.  The first phase spreads an attri- //
23507 // bute and/or a volume constraint through a (facet-bounded) region.  The    //
23508 // second phase uninfects all infected tetrahedra, returning them to normal. //
23509 //                                                                           //
23511 
23512 void tetgenmesh::
23513 regionplague(memorypool *regionviri, REAL attribute, REAL volume)
23514 {
23515   tetrahedron **virusloop;
23516   tetrahedron **regiontet;
23517   triface testtet, neighbor;
23518   face neighsh;
23519 
23520   if (b->verbose > 1) {
23521     printf("  Marking neighbors of marked tetrahedra.\n");
23522   }
23523   // Loop through all the infected tetrahedra, spreading the attribute
23524   //   and/or volume constraint to their neighbors, then to their neighbors'
23525   //   neighbors.
23526   regionviri->traversalinit();
23527   virusloop = (tetrahedron **) regionviri->traverse();
23528   while (virusloop != (tetrahedron **) NULL) {
23529     testtet.tet = *virusloop;
23530     // Temporarily uninfect this tetrahedron, not necessary.
23531     uninfect(testtet);
23532     if (b->regionattrib) {
23533       // Set an attribute.
23534       setelemattribute(testtet.tet, in->numberoftetrahedronattributes,
23535                        attribute);
23536     }
23537     if (b->varvolume) {
23538       // Set a volume constraint.
23539       setvolumebound(testtet.tet, volume);
23540     }
23541     // Check each of the tetrahedron's four neighbors.
23542     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23543       // Find the neighbor.
23544       sym(testtet, neighbor);
23545       // Check for a subface between the tetrahedron and its neighbor.
23546       tspivot(testtet, neighsh);
23547       // Make sure the neighbor exists, is not already infected, and
23548       //   isn't protected by a subface, or is protected by a nonsolid
23549       //   subface.
23550       if ((neighbor.tet != dummytet) && !infected(neighbor)
23551           && (neighsh.sh == dummysh)) {
23552         // Infect the neighbor.
23553         infect(neighbor);
23554         // Ensure that the neighbor's neighbors will be infected.
23555         regiontet = (tetrahedron **) regionviri->alloc();
23556         *regiontet = neighbor.tet;
23557       }
23558     }
23559     // Remark the tetrahedron as infected, so it doesn't get added to the
23560     //   virus pool again.
23561     infect(testtet);
23562     virusloop = (tetrahedron **) regionviri->traverse();
23563   }
23564 
23565   // Uninfect all tetrahedra.
23566   if (b->verbose > 1) {
23567     printf("  Unmarking marked tetrahedra.\n");
23568   }
23569   regionviri->traversalinit();
23570   virusloop = (tetrahedron **) regionviri->traverse();
23571   while (virusloop != (tetrahedron **) NULL) {
23572     testtet.tet = *virusloop;
23573     uninfect(testtet);
23574     virusloop = (tetrahedron **) regionviri->traverse();
23575   }
23576   // Empty the virus pool.
23577   regionviri->restart();
23578 }
23579 
23581 //                                                                           //
23582 // removeholetets()    Remove tetrahedra which are outside the domain.       //
23583 //                                                                           //
23585 
23586 void tetgenmesh::removeholetets(memorypool* viri)
23587 {
23588   tetrahedron **virusloop;
23589   triface testtet, neighbor;
23590   point checkpt;
23591   int *tetspernodelist;
23592   int i, j;
23593 
23594   if (b->verbose > 0) {
23595     printf("  Deleting marked tetrahedra.\n");
23596   }
23597 
23598   // Create and initialize 'tetspernodelist'.
23599   tetspernodelist = new int[points->items + 1];
23600   for (i = 0; i < points->items + 1; i++) tetspernodelist[i] = 0;
23601 
23602   // Loop the tetrahedra list, counter the number of tets sharing each node.
23603   tetrahedrons->traversalinit();
23604   testtet.tet = tetrahedrontraverse();
23605   while (testtet.tet != (tetrahedron *) NULL) {
23606     // Increment the number of sharing tets for each endpoint.
23607     for (i = 0; i < 4; i++) {
23608       j = pointmark((point) testtet.tet[4 + i]);
23609       tetspernodelist[j]++;
23610     }
23611     testtet.tet = tetrahedrontraverse();
23612   }
23613 
23614   viri->traversalinit();
23615   virusloop = (tetrahedron **) viri->traverse();
23616   while (virusloop != (tetrahedron **) NULL) {
23617     testtet.tet = *virusloop;
23618     // Record changes in the number of boundary faces, and disconnect
23619     //   dead tetrahedra from their neighbors.
23620     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23621       sym(testtet, neighbor);
23622       if (neighbor.tet == dummytet) {
23623         // There is no neighboring tetrahedron on this face, so this face
23624         //   is a boundary face.  This tetrahedron is being deleted, so this
23625         //   boundary face is deleted.
23626         hullsize--;
23627       } else {
23628         // Disconnect the tetrahedron from its neighbor.
23629         dissolve(neighbor);
23630         // There is a neighboring tetrahedron on this face, so this face
23631         //   becomes a boundary face when this tetrahedron is deleted.
23632         hullsize++;
23633       }
23634     }
23635     // Check the four corners of this tet if they're isolated.
23636     for (i = 0; i < 4; i++) {
23637       checkpt = (point) testtet.tet[4 + i];
23638       j = pointmark(checkpt);
23639       tetspernodelist[j]--;
23640       if (tetspernodelist[j] == 0) {
23641         // If it is added volume vertex or '-j' is not used, delete it.
23642         if ((pointtype(checkpt) == FREEVOLVERTEX) || !b->nojettison) {
23643           setpointtype(checkpt, UNUSEDVERTEX);
23644           unuverts++;
23645         }
23646       }
23647     }
23648     // Return the dead tetrahedron to the pool of tetrahedra.
23649     tetrahedrondealloc(testtet.tet);
23650     virusloop = (tetrahedron **) viri->traverse();
23651   }
23652 
23653   delete [] tetspernodelist;
23654 }
23655 
23657 //                                                                           //
23658 // assignregionattribs()    Assign each tetrahedron a region number.         //
23659 //                                                                           //
23660 // This routine is called when '-AA' switch is specified.  Every tetrahedron //
23661 // of a (bounded) region will get a integer number to that region.  Default, //
23662 // regions are numbered as 1, 2, 3, etc. However, if a number has already    //
23663 // been used (set by user in the region section in .poly or .smesh), it is   //
23664 // skipped and the next available number will be used.                       //
23665 //                                                                           //
23667 
23668 void tetgenmesh::assignregionattribs()
23669 {
23670   list *regionnumlist;
23671   list *regiontetlist;
23672   triface tetloop, regiontet, neightet;
23673   face checksh;
23674   bool flag;
23675   int regionnum, num;
23676   int attridx, count;
23677   int i;
23678 
23679   if (b->verbose > 0) {
23680     printf("  Assign region numbers.\n");
23681   }
23682 
23683   regionnumlist = new list(sizeof(int), NULL, 256);
23684   regiontetlist = new list(sizeof(triface), NULL, 1024);
23685   attridx = in->numberoftetrahedronattributes;
23686 
23687   // Loop through all tets. Infect tets which already have a region number,
23688   //   and save the used numbers in 'regionnumlist'.
23689   tetrahedrons->traversalinit();
23690   tetloop.tet = tetrahedrontraverse();
23691   while (tetloop.tet != (tetrahedron *) NULL) {
23692     if (!infected(tetloop)) {
23693       regionnum = (int) elemattribute(tetloop.tet, attridx);
23694       if (regionnum != 0.0) {
23695         // Found a numbered region tet.
23696         infect(tetloop);
23697         regiontetlist->append(&tetloop);
23698         // Found and infect all tets in this region.
23699         for (i = 0; i < regiontetlist->len(); i++) {
23700           regiontet = * (triface *)(* regiontetlist)[i];
23701           for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23702             // Is there a boundary face?
23703             tspivot(regiontet, checksh);
23704             if (checksh.sh == dummysh) {
23705               sym(regiontet, neightet);
23706               if ((neightet.tet != dummytet) && !infected(neightet)) {
23707 #ifdef SELF_CHECK
23708                 // neightet should have the same region number. Check it.
23709                 num = (int) elemattribute(neightet.tet, attridx);
23710                 assert(num == regionnum);
23711 #endif
23712                 infect(neightet);
23713                 regiontetlist->append(&neightet);
23714               }
23715             }
23716           }
23717         }
23718         // Add regionnum to list if it is not exist.
23719         flag = false;
23720         for (i = 0; i < regionnumlist->len() && !flag; i++) {
23721           num = * (int *)(* regionnumlist)[i];
23722           flag = (num == regionnum);
23723         }
23724         if (!flag) regionnumlist->append(&regionnum);
23725         // Clear list for the next region.
23726         regiontetlist->clear();
23727       }
23728     }
23729     tetloop.tet = tetrahedrontraverse();
23730   }
23731 
23732   if (b->verbose > 0) {
23733     printf("  %d user-specified regions.\n", regionnumlist->len());
23734   }
23735 
23736   // Now loop the tets again. Assign region numbers to uninfected tets.
23737   tetrahedrons->traversalinit();
23738   tetloop.tet = tetrahedrontraverse();
23739   regionnum = 1;  // Start region number.
23740   count = 0;
23741   while (tetloop.tet != (tetrahedron *) NULL) {
23742     if (!infected(tetloop)) {
23743       // An unassigned region tet.
23744       count++;
23745       do {
23746         flag = false;
23747         // Check if the region number has been used.
23748         for (i = 0; i < regionnumlist->len() && !flag; i++) {
23749           num = * (int *)(* regionnumlist)[i];
23750           flag = (num == regionnum);
23751         }
23752         if (flag) regionnum++;
23753       } while (flag);
23754       setelemattribute(tetloop.tet, attridx, (REAL) regionnum);
23755       infect(tetloop);
23756       regiontetlist->append(&tetloop);
23757       // Found and infect all tets in this region.
23758       for (i = 0; i < regiontetlist->len(); i++) {
23759         regiontet = * (triface *)(* regiontetlist)[i];
23760         for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23761           // Is there a boundary face?
23762           tspivot(regiontet, checksh);
23763           if (checksh.sh == dummysh) {
23764             sym(regiontet, neightet);
23765             if ((neightet.tet != dummytet) && !infected(neightet)) {
23766 #ifdef SELF_CHECK
23767               // neightet should have not been assigned yet. Check it.
23768               num = (int) elemattribute(neightet.tet, attridx);
23769               assert(num == 0);
23770 #endif
23771               setelemattribute(neightet.tet, attridx, (REAL) regionnum);
23772               infect(neightet);
23773               regiontetlist->append(&neightet);
23774             }
23775           }
23776         }
23777       }
23778       regiontetlist->clear();
23779       regionnum++; // The next region number.
23780     }
23781     tetloop.tet = tetrahedrontraverse();
23782   }
23783 
23784   // Uninfect all tets.
23785   tetrahedrons->traversalinit();
23786   tetloop.tet = tetrahedrontraverse();
23787   while (tetloop.tet != (tetrahedron *) NULL) {
23788 #ifdef SELF_CHECK
23789     assert(infected(tetloop));
23790 #endif
23791     uninfect(tetloop);
23792     tetloop.tet = tetrahedrontraverse();
23793   }
23794 
23795   if (b->verbose > 0) {
23796     printf("  %d regions are numbered.\n", count);
23797   }
23798 
23799   delete regionnumlist;
23800   delete regiontetlist;
23801 }
23802 
23804 //                                                                           //
23805 // carveholes()    Find the holes and infect them.  Find the volume          //
23806 //                 constraints and infect them.  Infect the convex hull.     //
23807 //                 Spread the infection and kill tetrahedra.  Spread the     //
23808 //                 volume constraints.                                       //
23809 //                                                                           //
23810 // This routine mainly calls other routines to carry out all these functions.//
23811 //                                                                           //
23813 
23814 void tetgenmesh::carveholes()
23815 {
23816   memorypool *holeviri, *regionviri;
23817   tetrahedron *tptr, **holetet, **regiontet;
23818   triface searchtet, *holetets, *regiontets;
23819   enum locateresult intersect;
23820   int i;
23821 
23822   if (!b->quiet) {
23823     printf("Removing unwanted tetrahedra.\n");
23824     if (b->verbose && (in->numberofholes > 0)) {
23825       printf("  Marking holes for elimination.\n");
23826     }
23827   }
23828 
23829   // Initialize a pool of viri to be used for holes, concavities.
23830   holeviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23831   // Mark as infected any unprotected tetrahedra on the boundary.
23832   infecthull(holeviri);
23833 
23834   if (in->numberofholes > 0) {
23835     // Allocate storage for the tetrahedra in which hole points fall.
23836     holetets = (triface *) new triface[in->numberofholes];
23837     // Infect each tetrahedron in which a hole lies.
23838     for (i = 0; i < 3 * in->numberofholes; i += 3) {
23839       // Ignore holes that aren't within the bounds of the mesh.
23840       if ((in->holelist[i] >= xmin) && (in->holelist[i] <= xmax)
23841           && (in->holelist[i + 1] >= ymin)
23842           && (in->holelist[i + 1] <= ymax)
23843           && (in->holelist[i + 2] >= zmin)
23844           && (in->holelist[i + 2] <= zmax)) {
23845         searchtet.tet = dummytet;
23846         // Find a tetrahedron that contains the hole.
23847         intersect = locate(&in->holelist[i], &searchtet);
23848         if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23849           // Record the tetrahedron for processing carve hole.
23850           holetets[i / 3] = searchtet;
23851         }
23852       }
23853     }
23854     // Infect the hole tetrahedron.  This is done by marking the tet as
23855     //   infected and including the tetrahedron in the virus pool.
23856     for (i = 0; i < in->numberofholes; i++) {
23857       infect(holetets[i]);
23858       holetet = (tetrahedron **) holeviri->alloc();
23859       *holetet = holetets[i].tet;
23860     }
23861     // Free up memory.
23862     delete [] holetets;
23863   }
23864 
23865   // Mark as infected all tets of the holes and concavities.
23866   plague(holeviri);
23867   // The virus pool contains all outside tets now.
23868 
23869   // Is -A switch in use.
23870   if (b->regionattrib) {
23871     // Assign every tetrahedron a regional attribute of zero.
23872     tetrahedrons->traversalinit();
23873     tptr = tetrahedrontraverse();
23874     while (tptr != (tetrahedron *) NULL) {
23875       setelemattribute(tptr, in->numberoftetrahedronattributes, 0.0);
23876       tptr = tetrahedrontraverse();
23877     }
23878   }
23879 
23880   if (in->numberofregions > 0) {
23881     if (!b->quiet) {
23882       if (b->regionattrib) {
23883         if (b->varvolume) {
23884           printf("Spreading regional attributes and volume constraints.\n");
23885         } else {
23886           printf("Spreading regional attributes.\n");
23887         }
23888       } else {
23889         printf("Spreading regional volume constraints.\n");
23890       }
23891     }
23892     // Allocate storage for the tetrahedra in which region points fall.
23893     regiontets = (triface *) new triface[in->numberofregions];
23894     // Find the starting tetrahedron for each region.
23895     for (i = 0; i < in->numberofregions; i++) {
23896       regiontets[i].tet = dummytet;
23897       // Ignore region points that aren't within the bounds of the mesh.
23898       if ((in->regionlist[5 * i] >= xmin)
23899            && (in->regionlist[5 * i] <= xmax)
23900            && (in->regionlist[5 * i + 1] >= ymin)
23901            && (in->regionlist[5 * i + 1] <= ymax)
23902            && (in->regionlist[5 * i + 2] >= zmin)
23903            && (in->regionlist[5 * i + 2] <= zmax)) {
23904         searchtet.tet = dummytet;
23905         // Find a tetrahedron that contains the region point.
23906         intersect = locate(&in->regionlist[5 * i], &searchtet);
23907         if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23908           // Record the tetrahedron for processing after the
23909           //   holes have been carved.
23910           regiontets[i] = searchtet;
23911         }
23912       }
23913     }
23914     // Initialize a pool to be used for regional attrs, and/or regional
23915     //   volume constraints.
23916     regionviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23917     // Find and set all regions.
23918     for (i = 0; i < in->numberofregions; i++) {
23919       if (regiontets[i].tet != dummytet) {
23920         // Make sure the tetrahedron under consideration still exists.
23921         //   It may have been eaten by the virus.
23922         if (!isdead(&(regiontets[i]))) {
23923           // Put one tetrahedron in the virus pool.
23924           infect(regiontets[i]);
23925           regiontet = (tetrahedron **) regionviri->alloc();
23926           *regiontet = regiontets[i].tet;
23927           // Apply one region's attribute and/or volume constraint.
23928           regionplague(regionviri, in->regionlist[5 * i + 3],
23929                        in->regionlist[5 * i + 4]);
23930           // The virus pool should be empty now.
23931         }
23932       }
23933     }
23934     // Free up memory.
23935     delete [] regiontets;
23936     delete regionviri;
23937   }
23938 
23939   // Now acutually remove the outside and hole tets.
23940   removeholetets(holeviri);
23941   // The mesh is nonconvex now.
23942   nonconvex = 1;
23943 
23944   if (b->regionattrib) {
23945     if (b->regionattrib > 1) {
23946       // -AA switch. Assign each tet a region number (> 0).
23947       assignregionattribs();
23948     }
23949     // Note the fact that each tetrahedron has an additional attribute.
23950     in->numberoftetrahedronattributes++;
23951   }
23952 
23953   // Free up memory.
23954   delete holeviri;
23955 }
23956 
23957 //
23958 // End of carving out holes and concavities routines
23959 //
23960 
23961 //
23962 // Begin of boundary Steiner points removing routines
23963 //
23964 
23966 //                                                                           //
23967 // replacepolygonsubs()    Substitute the subfaces of a polygon.             //
23968 //                                                                           //
23969 // 'oldshlist' (T_old) contains the old subfaces of P.  It will be replaced  //
23970 // by 'newshlist' (T_new) of new subfaces. Each boundary edge of P is bonded //
23971 // to 'dummysh' in T_new.                                                    //
23972 //                                                                           //
23973 // Notice that Not every boundary edge of T_new is able to bond to a subface,//
23974 // e.g., when it is a segment recovered by removing a Steiner point in it.   //
23975 //                                                                           //
23977 
23978 void tetgenmesh::replacepolygonsubs(list* oldshlist, list* newshlist)
23979 {
23980   face newsh, oldsh, spinsh;
23981   face casingout, casingin;
23982   face checkseg;
23983   point pa, pb;
23984   int i, j, k, l;
23985 
23986   for (i = 0; i < newshlist->len(); i++) {
23987     // Get a new subface s.
23988     newsh = * (face *)(* newshlist)[i];
23989     // Check the three edges of s.
23990     for (k = 0; k < 3; k++) {
23991       spivot(newsh, casingout);
23992       // Is it a boundary edge?
23993       if (casingout.sh == dummysh) {
23994         // Find the old subface s_o having the same edge as s.
23995         pa = sorg(newsh);
23996         pb = sdest(newsh);
23997         for (j = 0; j < oldshlist->len(); j++) {
23998           oldsh = * (face *)(* oldshlist)[j];
23999       for (l = 0; l < 3; l++) {
24000             if (((sorg(oldsh) == pa) && (sdest(oldsh) == pb)) ||
24001                 ((sorg(oldsh) == pb) && (sdest(oldsh) == pa))) break;
24002             senextself(oldsh);
24003           }
24004           if (l < 3) break;
24005         }
24006         // Is there a matched edge?
24007         if (j < oldshlist->len()) {
24008           // Get the neighbor subface s_out.
24009           spivot(oldsh, casingout);
24010           sspivot(oldsh, checkseg);
24011           if (checkseg.sh != dummysh) {
24012             // A segment. Insert s into the face ring, ie, s_in -> s -> s_out.
24013             if (oldsh.sh != casingout.sh) {
24014               // s is not bonded to itself.
24015               spinsh = casingout;
24016               do {
24017                 casingin = spinsh;
24018                 spivotself(spinsh);
24019               } while (sapex(spinsh) != sapex(oldsh));
24020               assert(casingin.sh != oldsh.sh);
24021               // Bond s_in -> s -> s_out (and dissolve s_in -> s_old -> s_out).
24022               sbond1(casingin, newsh);
24023               sbond1(newsh, casingout);
24024             } else {
24025               // Bond newsh -> newsh.
24026               sbond(newsh, newsh);
24027             }
24028             // Bond the segment.
24029             ssbond(newsh, checkseg);
24030           } else {
24031             // Bond s <-> s_out (and dissolve s_out -> s_old).
24032             sbond(newsh, casingout);
24033           }
24034           // Unbound oldsh to indicate it's neighbor has been replaced.
24035           //   It will be used to indentfy the edge in the inverse.
24036           sdissolve(oldsh);
24037           ssdissolve(oldsh);
24038         }
24039       }
24040       // Go to the next edge of s.
24041       senextself(newsh);
24042     }
24043   }
24044 }
24045 
24047 //                                                                           //
24048 // orientnewsubs()    Orient new subfaces facing to the inside of cavity.    //
24049 //                                                                           //
24050 // 'newshlist' contains new subfaces of the cavity C (created by re-triangu- //
24051 // lation the polygon P). They're not necessary facing to the inside of C.   //
24052 // 'orientsh', faces to the inside of C, is used to adjust new subfaces. The //
24053 // normal of the new subfaces is returned in 'norm'.                         //
24054 //                                                                           //
24056 
24057 void tetgenmesh::orientnewsubs(list* newshlist, face* orientsh, REAL* norm)
24058 {
24059   face *newsh;
24060   point pa, pb, pc;
24061   REAL ref[3], ori, len;
24062   int i;
24063 
24064   // Calculate the normal of 'orientsh'.
24065   pa = sorg(*orientsh);
24066   pb = sdest(*orientsh);
24067   pc = sapex(*orientsh);
24068   facenormal(pa, pb, pc, norm, &len);
24069   for (i = 0; i < 3; i++) ref[i] = pa[i] + norm[i];
24070   for (i = 0; i < 3; i++) norm[i] /= len;
24071 
24072   // Orient new subfaces. Let the normal above each one.
24073   for (i = 0; i < newshlist->len(); i++) {
24074     newsh = (face *)(* newshlist)[i];
24075     pa = sorg(*newsh);
24076     pb = sdest(*newsh);
24077     pc = sapex(*newsh);
24078     ori = orient3d(pa, pb, pc, ref);
24079     assert(ori != 0.0);
24080     if (ori > 0.0) {
24081       sesymself(*newsh);
24082     }
24083   }
24084 }
24085 
24087 //                                                                           //
24088 // constrainedflip()    Flip a non-constrained face.                         //
24089 //                                                                           //
24090 // 'flipface' f (abc) is a face we want to flip. In addition, if 'front' is  //
24091 // given (not a NULL), f is a crossface. f may not be flippable if it is one //
24092 // of the following cases:                                                   //
24093 //   (1) f has an aux subface attached;                                      //
24094 //   (2) f is on the convex hull;                                            //
24095 //   (3) f is not locally Delaunay (f must be recovered by a previous flip,  //
24096 //       we should keep it, otherwise, we may fall into a flip loop);        //
24097 //   (4) f is T32 at ab, but abd or abe has an aux subface attached;         //
24098 //   (5) f is T22 or T44 at ab, but abd, or abe, or abf has an aux subface   //
24099 //       attached;                                                           //
24100 //   (6) f is unflipable at ab, and abd, abe, ... are all unflippable due to //
24101 //       the cases (1) - (5).                                                //
24102 // If f is a crssface ('front' != NULL) and it is unflipable due to case (3),//
24103 // (4), (5) and (6). Try to flip the next crossing face of front first.      //
24104 //                                                                           //
24106 
24107 bool tetgenmesh::constrainedflip(triface* flipface, triface* front,
24108   queue* flipque)
24109 {
24110   triface symface, spintet;
24111   face checksh;
24112   point pa, pb, pc, pd, pe;
24113   enum fliptype fc;
24114   REAL sign;
24115   bool doflip;
24116   int ia, ib, ic, id, ie;
24117   int i;
24118 
24119   // (1) Is f protected by an (auxilary) subface?
24120   tspivot(*flipface, checksh);
24121   if (checksh.sh != dummysh) return false;
24122   // (2) Is f on the convex hull?
24123   sym(*flipface, symface);
24124   if (symface.tet == dummytet) return false;
24125   // (3) Is f not locally Delaunay?
24126   adjustedgering(*flipface, CCW);
24127   pa = dest(*flipface);
24128   pb = org(*flipface);
24129   pc = apex(*flipface);
24130   pd = oppo(*flipface);
24131   pe = oppo(symface);
24132   // if (symbolic) {
24133     ia = pointmark(pa);
24134     ib = pointmark(pb);
24135     ic = pointmark(pc);
24136     id = pointmark(pd);
24137     ie = pointmark(pe);
24138     sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24139     assert(sign != 0.0);
24140   // } else {
24141   //   sign = insphere(pa, pb, pc, pd, pe);
24142   // }
24143   if (sign <= 0.0) {
24144     // Get the fliptype of f.
24145     checksubfaces = 0; // switch off subface test.
24146     fc = categorizeface(*flipface);
24147     checksubfaces = 1; // switch on subface test.
24148     if (fc == T23) {
24149       doflip = true;
24150       // Avoid one tet created by the 2-3 flip is nearly degenerate.
24151       /* pc = oppo(*flipface);
24152       pd = oppo(symface);
24153       adjustedgering(*flipface, CCW);
24154       for (i = 0; i < 3; i++) {
24155         pa = org(*flipface);
24156         pb = dest(*flipface);
24157         ori = orient3d(pa, pb, pc, pd);
24158         if (iscoplanar(pa, pb, pc, pd, ori, b->epsilon)) {
24159           doflip = false; break;
24160         }
24161         enextself(*flipface);
24162       } */
24163       if (doflip) {
24164         flip23(flipface, flipque);
24165         return true;
24166       }
24167     } else if (fc == T32) {
24168       // (4) Is abd, or abe protected?
24169       doflip = true;
24170       spintet = *flipface;
24171       for (i = 0; i < 2; i++) {
24172         fnextself(spintet);
24173         tspivot(spintet, checksh);
24174         if (checksh.sh != dummysh) {
24175           doflip = false; break; // f is protected. Unflipable.
24176         }
24177       }
24178       if (doflip) {
24179         flip32(flipface, flipque);
24180         return true;
24181       }
24182     } else if (fc == T22 || fc == T44) {
24183       // (5) Is abd, abe, or abf protected?
24184       doflip = true;
24185       if (fc == T22) {
24186         for (i = 0; i < 2; i++) {
24187           spintet = *flipface;
24188           if (i == 1) {
24189             esymself(spintet);
24190           }
24191           fnextself(spintet);
24192           tspivot(spintet, checksh);
24193           if (checksh.sh != dummysh) {
24194             doflip = false; break; // f is protected. Unflipable.
24195           }
24196         }
24197       } else if (fc == T44) {
24198         spintet = *flipface;
24199         for (i = 0; i < 3; i++) {
24200           fnextself(spintet);
24201           tspivot(spintet, checksh);
24202           if (checksh.sh != dummysh) {
24203             doflip = false; break; // f is protected. Unflipable.
24204           }
24205         }
24206       }
24207       if (doflip) {
24208         flip22(flipface, flipque);
24209         return true;
24210       }
24211     } else if (fc == N32) {
24212       // Is f a crossface?
24213       if (front != (triface *) NULL) {
24214         // (6) Is any obstacle face (abd, or abe, ...) flipable?
24215         spintet = *flipface;
24216         while (fnextself(spintet)) {
24217           if (apex(spintet) == apex(*flipface)) break;
24218           // Check if spintet is flipable, no recursive.
24219           if (constrainedflip(&spintet, NULL, flipque)) {
24220             // One obstacle face has been flipped.
24221             return true;
24222           }
24223           // Unflipable. Go to the next obstacle face.
24224           findedge(&spintet, org(*flipface), dest(*flipface));
24225         }
24226       }
24227     }
24228   }
24229 
24230   // f is unflipable. Is f a crossface?
24231   if (front != (triface *) NULL) {
24232     // Look if there is another crossface.
24233     pa = org(*front);
24234     pb = dest(*front);
24235     pc = apex(*front);
24236     // sym(*flipface, symface);
24237     // Have we reach the end of abc (We've started from edge ab).
24238     if (oppo(symface) != pc) {
24239       adjustedgering(symface, CCW);
24240       for (i = 0; i < 3; i++) {
24241         fnext(symface, spintet);
24242         // Is c ahead of this face?
24243         sign = orient3d(org(spintet), dest(spintet), apex(spintet), pc);
24244         if (sign < 0.0) {
24245           if (tritritest(&spintet, pa, pb, pc)) {
24246             if (b->verbose > 2) {
24247               printf("    Next crossface (%d, %d, %d).\n",
24248                      pointmark(org(spintet)), pointmark(dest(spintet)),
24249                      pointmark(apex(spintet)));
24250             }
24251             return constrainedflip(&spintet, front, flipque);
24252             // return constrainedflip(&spintet, NULL, flipque);
24253           }
24254         }
24255         enextself(symface);
24256       }
24257     }
24258   }
24259   return false;
24260 }
24261 
24263 //                                                                           //
24264 // recoverfront()    Recover a missing front by flips.                       //
24265 //                                                                           //
24266 // 'front' f is missing in D - it was crossed by faces of D. The cross faces //
24267 // may be flippable, so f can be recovered by flipping them away.            //
24268 //                                                                           //
24270 
24271 bool tetgenmesh::recoverfront(triface* front, list* newtetlist, queue* flipque)
24272 {
24273   triface idfront, starttet, spintet;
24274   point pa, pb, pc, pd, ref;
24275   enum locateresult loc;
24276   enum finddirectionresult col;
24277   REAL ori, ori1, ori2, sign;
24278   int hitbdry;
24279   int i, j;
24280 
24281   // Find an existing edge of f in D to start with.
24282   for (i = 0; i < 3; i++) {
24283     pa = org(*front);
24284     pb = dest(*front);
24285     // Get a tet for searching.
24286     idfront = recenttet;
24287     // Make sure the tet is valid (flip32() may kill a tet).
24288     if (isdead(&idfront)) {
24289       // The tet is dead. Get a live tet in D. !!!
24290       for (j = 0; j < newtetlist->len(); j++) {
24291         recenttet = * (triface *)(* newtetlist)[j];
24292         if (!isdead(&recenttet)) break;
24293       }
24294       assert(j < newtetlist->len());
24295     }
24296     loc = preciselocate(pa, &idfront, (long) newtetlist->len());
24297     if (loc != ONVERTEX) {
24298       // Do a brute-force search in D.
24299       for (j = 0; j < newtetlist->len(); j++) {
24300         idfront = * (triface *)(* newtetlist)[j];
24301         if (isdead(&idfront)) continue;
24302         if (findorg(&idfront, pa)) break;
24303       }
24304       assert(j < newtetlist->len()); // a must belong to one tet.
24305     }
24306     recenttet = idfront;
24307     // Search for a tet having edge ab.
24308     col = finddirection(&idfront, pb, (long) newtetlist->len());
24309     if (col == BELOWHULL) {
24310       // Do a brute-force search in D.
24311       for (j = 0; j < newtetlist->len(); j++) {
24312         idfront = * (triface *)(* newtetlist)[j];
24313         if (isdead(&idfront)) continue;
24314         if (findorg(&idfront, pa)) {
24315           assert(org(idfront) == pa);
24316           if (dest(idfront) == pb) {
24317             col = RIGHTCOLLINEAR; break;
24318           } else if (apex(idfront) == pb) {
24319             col = LEFTCOLLINEAR; break;
24320           } else if (oppo(idfront) == pb) {
24321             col = TOPCOLLINEAR; break;
24322           }
24323         }
24324       }
24325     }
24326     if (col == RIGHTCOLLINEAR) {
24327       // b is just the destination.
24328     } else if (col == LEFTCOLLINEAR) {
24329       enext2self(idfront);
24330       esymself(idfront);
24331     } else if (col == TOPCOLLINEAR) {
24332       fnextself(idfront);
24333       enext2self(idfront);
24334       esymself(idfront);
24335     }
24336     if (dest(idfront) == pb) break; // Found.
24337     // Missing. Go to the next edge of f.
24338     enextself(*front);
24339   }
24340   if (i == 3) {
24341     // All three edges of f are missing - unrecoverable.
24342     return false;
24343   }
24344 
24345   // Search for a tet having f (abc).
24346   pc = apex(*front);
24347   spintet = idfront;
24348   hitbdry = 0;
24349   do {
24350     if (apex(spintet) == pc) {
24351       // Found abc. Insert an auxilary subface s at idfront.
24352       insertauxsubface(front, &spintet);
24353       return true;
24354     }
24355     if (!fnextself(spintet)) {
24356       hitbdry ++;
24357       if (hitbdry < 2) {
24358         esym(idfront, spintet);
24359         if (!fnextself(spintet)) {
24360           hitbdry ++;
24361         }
24362       }
24363     }
24364     if (apex(spintet) == apex(idfront)) break;
24365   } while (hitbdry < 2);
24366 
24367   // Search for a crossing face to flip.
24368   pd = apex(idfront);
24369   assert(pd != pc);
24370   // Decide the orientation of d with abc.
24371   ori = orient3d(pa, pb, pc, pd);
24372   if (ori < 0.0) {
24373     // d is above abc. Rotate downwards.
24374     esym(idfront, starttet);
24375     sign = -1.0;
24376   } else if (ori > 0.0) {
24377     // d is below abc. Rotate upwards.
24378     starttet = idfront;
24379     sign = 1.0;
24380   } else {
24381     assert(ori == 0.0);
24382     // d is coplanar with abc. Do abc and abd intersect?
24383     ref = oppo(idfront);
24384     ori1 = orient3d(pa, pb, ref, pc);
24385     ori2 = orient3d(pa, pb, ref, pd);
24386     assert(ori1 * ori2 != 0.0);
24387     if (ori1 * ori2 > 0) {
24388       // abc and abd intersect.  There're two possible intersections:
24389       //   ad and bc, or ac and bd.  Find it out.
24390       ori1 = orient3d(pb, pc, ref, pd);
24391       ori2 = orient3d(pb, pc, ref, pa);
24392       assert(ori1 * ori2 != 0.0);
24393       if (ori1 * ori2 > 0) {
24394         // ac intersects bd.
24395         enextself(idfront); // go to edge bd.
24396       } else {
24397         // ad intersects bc.
24398         enext2self(idfront); // go to edge ad.
24399       }
24400       adjustedgering(idfront, CCW);
24401       fnextself(idfront); // face ade or bce need a 4-to-4 flip.
24402       if (b->verbose > 2) {
24403         printf("    Get crossface (%d, %d, %d).\n", pointmark(org(idfront)),
24404                pointmark(dest(idfront)), pointmark(apex(idfront)));
24405       }
24406       if (constrainedflip(&idfront, front, flipque)) {
24407         // A crossface has been flipped. Continue to recover f.
24408         return recoverfront(front, newtetlist, flipque);
24409       }
24410       // Unable to recover f.
24411       return false; // sign = 0.0;
24412     } else {
24413       // Not intersect. We can go either direction.
24414       starttet = idfront;
24415       if (fnextself(starttet)) {
24416         // Choose to rotate upwards.
24417         sign = 1.0;
24418       } else {
24419         // Hit convex hull. Choose to rotate downwrads.
24420         esym(idfront, starttet);
24421         sign = -1.0;
24422       }
24423     }
24424   }
24425 
24426   assert(sign != 0.0);
24427   if (sign == -1) {
24428     // The edge ab has be changed. Reverse it.
24429     pa = org(starttet);
24430     pb = dest(starttet);
24431     // The sign has been reversed as well.
24432     sign = -sign;
24433   }
24434   // Rotate face abd around edge ab. Moreover, we've chosen the rotate
24435   //   direction such that no convex hull face will be reach.
24436   spintet = starttet;
24437   while (fnextself(spintet)) {
24438     pd = apex(spintet);
24439     assert(pd != pc);
24440     // Check if the orientation of d (with abc) has changed.
24441     ori = orient3d(pa, pb, pc, pd);
24442     if (ori == 0.0) {
24443       // abc and abd must coplanar intersect (4-to-4 flip is needed).
24444       ref = oppo(spintet);
24445       ori1 = orient3d(pb, pc, ref, pd);
24446       ori2 = orient3d(pb, pc, ref, pa);
24447       assert(ori1 * ori2 != 0.0);
24448       if (ori1 * ori2 > 0) {
24449         // ac intersects bd.
24450         enextself(spintet); // go to edge bd.
24451       } else {
24452         // ad intersects bc.
24453         enext2self(spintet); // go to edge ad.
24454       }
24455       adjustedgering(spintet, CCW);
24456       fnextself(spintet); // face ade or bce need a 4-to-4 flip.
24457       if (b->verbose > 2) {
24458         printf("    Get crossface (%d, %d, %d).\n", pointmark(org(spintet)),
24459                pointmark(dest(spintet)), pointmark(apex(spintet)));
24460       }
24461       if (constrainedflip(&spintet, front, flipque)) {
24462         // A crossface has been flipped. Continue to recover f.
24463         return recoverfront(front, newtetlist, flipque);
24464       }
24465       // Unable to recover f.
24466       return false; // sign = 0.0;
24467     } else if (ori * sign < 0.0) {
24468       // Sign has changed. The face dea or deb must cross abc.
24469       adjustedgering(spintet, CCW);
24470       enextself(spintet);
24471       for (i = 0; i < 2; i++) {
24472         // Get the face dea or deb.
24473         fnext(spintet, starttet);
24474         if (tritritest(&starttet, pa, pb, pc)) {
24475           if (b->verbose > 2) {
24476             printf("    Get crossface (%d, %d, %d).\n",
24477                    pointmark(org(starttet)), pointmark(dest(starttet)),
24478                    pointmark(apex(starttet)));
24479           }
24480           if (constrainedflip(&starttet, front, flipque)) {
24481             // A crossface has been flipped. Continue to recover f.
24482             return recoverfront(front, newtetlist, flipque);
24483           }
24484         }
24485         enextself(spintet);
24486       }
24487       // Unable to recover f.
24488       return false;
24489     }
24490   }
24491   // Impossible to be here.
24492   assert(0);
24493   return false;
24494 }
24495 
24497 //                                                                           //
24498 // repairflips()    Flip non-Delaunay and non-constrained faces.             //
24499 //                                                                           //
24501 
24502 void tetgenmesh::repairflips(queue* flipque)
24503 {
24504   badface *qface;
24505   triface flipface, symface, spintet;
24506   face checksh;
24507   point pa, pb, pc, pd, pe;
24508   enum fliptype fc;
24509   REAL sign;
24510   long flipcount;
24511   bool doflip;
24512   int ia, ib, ic, id, ie;
24513   int i;
24514 
24515   if (b->verbose > 1) {
24516     printf("    Repair flip %ld faces.\n", flipque->len());
24517   }
24518   flipcount = flip23s + flip32s + flip22s + flip44s;
24519   // Loop until the queue is empty.
24520   while (!flipque->empty()) {
24521     qface = (badface *) flipque->pop();
24522     flipface = qface->tt;
24523     // Check the validity of this face.
24524     if (isdead(&flipface) || flipface.tet == dummytet ||
24525         (org(flipface) != qface->forg) ||
24526         (dest(flipface) != qface->fdest) ||
24527         (apex(flipface) != qface->fapex) ||
24528         (oppo(flipface) == (point) NULL)) continue;
24529     // (1) Is f protected by an (auxilary) subface?
24530     tspivot(flipface, checksh);
24531     if (checksh.sh != dummysh) continue;
24532     // (2) Is f on the convex hull?
24533     sym(flipface, symface);
24534     if (symface.tet == dummytet) continue;
24535     // For positive orientation that insphere() test requires.
24536     adjustedgering(flipface, CW);
24537     pa = org(flipface);
24538     pb = dest(flipface);
24539     pc = apex(flipface);
24540     pd = oppo(flipface);
24541     pe = oppo(symface);
24542     // if (symbolic) {
24543       ia = pointmark(pa);
24544       ib = pointmark(pb);
24545       ic = pointmark(pc);
24546       id = pointmark(pd);
24547       ie = pointmark(pe);
24548       sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24549       assert(sign != 0.0);
24550     // } else {
24551     //   sign = insphere(pa, pb, pc, pd, pe);
24552     // }
24553     if (sign > 0.0) {
24554       // f is non-lcally Delaunay. Get the fliptype of f.
24555       checksubfaces = 0; // switch off subface test.
24556       fc = categorizeface(flipface);
24557       checksubfaces = 1; // switch on subface test.
24558       if (fc == T23) {
24559         doflip = true;
24560         // Avoid to create a nearly degenerate tet.
24561         /* pc = oppo(flipface);
24562         pd = oppo(symface);
24563         adjustedgering(flipface, CCW);
24564         for (i = 0; i < 3; i++) {
24565           pa = org(flipface);
24566           pb = dest(flipface);
24567           ori = orient3d(pa, pb, pc, pd);
24568           if (iscoplanar(pa, pb, pc, pd, ori, b->epsilon)) {
24569             doflip = false; break;
24570           }
24571           enextself(flipface);
24572         } */
24573         if (doflip) {
24574           flip23(&flipface, flipque);
24575         }
24576       } else if (fc == T32) {
24577         // (4) Is abd, or abe protected?
24578         doflip = true;
24579         spintet = flipface;
24580         for (i = 0; i < 2; i++) {
24581           fnextself(spintet);
24582           tspivot(spintet, checksh);
24583           if (checksh.sh != dummysh) {
24584             doflip = false; break; // f is protected. Unflipable.
24585           }
24586         }
24587         if (doflip) {
24588           flip32(&flipface, flipque);
24589         }
24590       } else if (fc == T22 || fc == T44) {
24591         // (5) Is abd, abe, or abf protected?
24592         doflip = true;
24593         if (fc == T22) {
24594           for (i = 0; i < 2; i++) {
24595             spintet = flipface;
24596             if (i == 1) {
24597               esymself(spintet);
24598             }
24599             fnextself(spintet);
24600             tspivot(spintet, checksh);
24601             if (checksh.sh != dummysh) {
24602               doflip = false; break; // f is protected. Unflipable.
24603             }
24604           }
24605         } else if (fc == T44) {
24606           spintet = flipface;
24607           for (i = 0; i < 3; i++) {
24608             fnextself(spintet);
24609             tspivot(spintet, checksh);
24610             if (checksh.sh != dummysh) {
24611               doflip = false; break; // f is protected. Unflipable.
24612             }
24613           }
24614         }
24615         if (doflip) {
24616           flip22(&flipface, flipque);
24617         }
24618       }
24619     }
24620   }
24621   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
24622   if (b->verbose > 1) {
24623     printf("    %ld flips.\n", flipcount);
24624   }
24625 }
24626 
24628 //                                                                           //
24629 // constrainedcavity()    Tetrahedralize a cavity by constrained tetrahedra. //
24630 //                                                                           //
24631 // The cavity C is bounded by faces F in 'floorlist' and 'ceillist'. 'ptlist'//
24632 // V is the set of vertices of C.                                            //
24633 //                                                                           //
24635 
24636 bool tetgenmesh::constrainedcavity(triface* oldtet, list* floorlist,
24637   list* ceillist, list* ptlist, list* frontlist, list* misfrontlist,
24638   list* newtetlist, queue* flipque)
24639 {
24640   triface misfront, newtet;
24641   long facenum;
24642   int i;
24643 
24644   if (b->verbose > 1) {
24645     printf("    Constrained cavity (%d floors, %d ceilings, %d vertices).\n",
24646            floorlist->len(), ceillist->len(), ptlist->len());
24647   }
24648 
24649   // symbolic = 1;
24650 
24651   // Initialize the cavity C.
24652   initializecavity(floorlist, ceillist, frontlist);
24653   // Form the D of the vertices of C.
24654   delaunizecavvertices(oldtet, ptlist, NULL, newtetlist, flipque);
24655 
24656   // Identify faces of C in D.
24657   if (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
24658     // Some faces are missing.
24659     recenttet = * (triface *)(* newtetlist)[0];
24660     assert((recenttet.tet != dummytet) && !isdead(&recenttet));
24661     // Try to recover missing faces by flips.
24662     do {
24663       facenum = misfrontlist->len();
24664       for (i = 0; i < misfrontlist->len(); i++) {
24665         // Get a missing front f.
24666         misfront = * (triface *)(* misfrontlist)[i];
24667         // Let f face toward the inside of C.
24668         adjustedgering(misfront, CW);
24669         if (b->verbose > 1) {
24670           printf("    Recover face (%d, %d, %d).\n", pointmark(org(misfront)),
24671                  pointmark(dest(misfront)), pointmark(apex(misfront)));
24672         }
24673         if (recoverfront(&misfront, newtetlist, flipque)) {
24674           // f has been recovered.
24675           frontlist->append(&misfront);
24676           misfrontlist->del(i, 0); i--;
24677         }
24678         // Flip non-locally non-constrained Delaunay faces.
24679         repairflips(flipque);
24680       }
24681       // Have all faces been recovered?
24682       if (misfrontlist->len() == 0) break;
24683       // No! There are still un-recovered faces. Continue the loop if any
24684       //   face has been recovered.
24685     } while (misfrontlist->len() < facenum);
24686     // Retrieve new tets and purge dead tets in D.
24687     retrievenewtets(newtetlist);
24688   }
24689 
24690   // symbolic = 0;
24691 
24692   if (misfrontlist->len() == 0) {
24693     // All fronts have identified in D. Get the shape of C by removing out
24694     //   tets of C. 'misfrontlist' is reused for removing out tets.
24695     //   Don't do flip since the new tets may get deleted later.
24696     carvecavity(newtetlist, misfrontlist, NULL);
24697     // Recover locally Delaunay faces.
24698     // flip(flipque, NULL);
24699     return true;
24700   } else {
24701     // Fail to tetrahedralize C.
24702     // Remove aux subfaces.
24703     detachauxsubfaces(newtetlist);
24704     // Remove new tets.
24705     for (i = 0; i < newtetlist->len(); i++) {
24706       newtet = * (triface *)(* newtetlist)[i];
24707       assert(!isdead(&newtet));
24708       tetrahedrondealloc(newtet.tet);
24709     }
24710     newtetlist->clear();
24711     // Restore faces of C in frontlist.
24712     for (i = 0; i < misfrontlist->len(); i++) {
24713       misfront = * (triface *)(* misfrontlist)[i];
24714       frontlist->append(&misfront);
24715     }
24716     return false;
24717   }
24718 }
24719 
24721 //                                                                           //
24722 // expandsteinercavity()    Expand the cavity of a Steiner point.            //
24723 //                                                                           //
24724 // Expand the cavity C if there fronts (except fronts having subfaces) which //
24725 // are either (nearly) coplanar or invisible by the Steiner point.           //
24726 //                                                                           //
24728 
24729 void tetgenmesh::expandsteinercavity(point steinpt, REAL eps, list* frontlist,
24730   list* oldtetlist)
24731 {
24732   triface front, symfront, newfront, oldfront;
24733   face frontsh;
24734   point pa, pb, pc;
24735   REAL ori;
24736   bool expflag, newflag;
24737   int i, j;
24738 
24739   do {
24740     expflag = false;
24741     for (i = 0; i < frontlist->len(); i++) {
24742       // Get a front f.
24743       front =  * (triface *)(* frontlist)[i];
24744       // f can be expanded if it is not a subface.
24745       tspivot(front, frontsh);
24746       if (frontsh.sh == dummysh) {
24747         // Let f face to the inside of C.
24748         adjustedgering(front, CW);
24749         pa = org(front);
24750         pb = dest(front);
24751         pc = apex(front);
24752         ori = orient3d(pa, pb, pc, steinpt);
24753         if (ori != 0.0) {
24754           if (iscoplanar(pa, pb, pc, steinpt, ori, eps)) {
24755             ori = 0.0; // f is nearly coplanar with p.
24756           }
24757         }
24758         if (ori >= 0.0) {
24759           // f is either invisible or coplanar with p.
24760           if (b->verbose > 2) {
24761             printf("    Remove front (%d, %d, %d).\n", pointmark(pa),
24762                    pointmark(pb), pointmark(pc));
24763           }
24764           frontlist->del(i, 1);
24765           expflag = true;
24766           break;
24767         }
24768       }
24769     }
24770     if (expflag) {
24771       assert(!infected(front) && (oppo(front) != NULL));
24772       // Expand C at f by including new fronts.
24773       adjustedgering(front, CCW);
24774       for (i = 0; i < 3; i++) {
24775         newflag = true;
24776         // Get a new boundary n of the cavity.
24777         fnext(front, symfront);
24778         tspivot(symfront, frontsh);
24779         sym(symfront, newfront);
24780         if (frontsh.sh == dummysh) {
24781           assert(newfront.tet != dummytet);
24782           // Is n a front of the unexp. cavity?
24783           if (infected(newfront)) {
24784             for (j = 0; j < frontlist->len(); j++) {
24785               oldfront = * (triface *)(* frontlist)[j];
24786               if ((oldfront.tet == symfront.tet) &&
24787                   (oldfront.loc == symfront.loc)) {
24788                 // n is not a front anymore.
24789                 if (b->verbose > 2) {
24790                   printf("    Remove front (%d, %d, %d).\n",
24791                          pointmark(org(oldfront)), pointmark(dest(oldfront)),
24792                          pointmark(apex(oldfront)));
24793                 }
24794                 frontlist->del(j, 1);
24795                 newflag = false;
24796                 break;
24797               }
24798             }
24799           }
24800         } else {
24801           // n is a subface.
24802           if (newfront.tet == dummytet) {
24803             sesymself(frontsh);
24804             // Create a fake tet to hold n.
24805             maketetrahedron(&newfront);
24806             setorg(newfront, sorg(frontsh));
24807             setdest(newfront, sdest(frontsh));
24808             setapex(newfront, sapex(frontsh));
24809             setoppo(newfront, (point) NULL);
24810             tsbond(newfront, frontsh);
24811           } else {
24812             // n should not be a front of cavity yet.
24813             assert(!infected(newfront));
24814           }
24815         }
24816         if (newflag) {
24817           if (b->verbose > 2) {
24818             printf("    Add front (%d, %d, %d).\n", pointmark(org(newfront)),
24819                    pointmark(dest(newfront)), pointmark(apex(newfront)));
24820           }
24821           frontlist->append(&newfront);
24822         }
24823         enextself(front);
24824       }
24825       // Add f into oldtetlist (to be deleted).
24826       infect(front);
24827       oldtetlist->append(&front);
24828       expcavcount++;
24829     }
24830   } while (expflag);
24831 }
24832 
24834 //                                                                           //
24835 // findrelocatepoint()    Find new location for relocating a point.          //
24836 //                                                                           //
24837 // 'frontlist' contains the boundary faces of the cavity C.  Some fronts are //
24838 // visible by 'stpt' p, some are coplanar with p.                            //
24839 //                                                                           //
24841 
24842 bool tetgenmesh::findrelocatepoint(point sp, point np, REAL* n,
24843   list* frontlist, list* oldtetlist)
24844 {
24845   triface front;
24846   point pa, pb, pc;
24847   REAL tp[3], tvol, mvol;
24848   REAL ori, eps;
24849   bool visible;
24850   int i, j, k;
24851 
24852   if (b->verbose > 1) {
24853     printf("    Find new location for point %d.\n", pointmark(sp));
24854   }
24855 
24856   // Avoid compilation warnings.
24857   tvol = mvol = 0.0;
24858   visible = false;
24859 
24860   eps = b->epsilon;
24861   // Initialize np far enough from p (outside C).
24862   for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24863   // Let tp = np;
24864   for (i = 0; i < 3; i++) tp[i] = np[i];
24865   // Interation to adjust np until it is visible by all fronts.
24866   j = 0;
24867   do {
24868     for (i = 0; i < frontlist->len(); i++) {
24869       // Get a front face f.
24870       front = * (triface *)(* frontlist)[i];
24871       // Let f face to the interior of C.
24872       adjustedgering(front, CW);
24873       pa = org(front);
24874       pb = dest(front);
24875       pc = apex(front);
24876       ori = orient3d(pa, pb, pc, np);
24877       visible = (ori < 0.0);
24878       if (!visible) {
24879         // A front is invisible by np. Move it towards p along the normal.
24880         for (i = 0; i < 3; i++) np[i] = sp[i] + 0.5 * (sp[i] - np[i]);
24881         // Failed if tp = np.
24882         if ((tp[0] == np[0]) && (tp[1] == np[1]) && (tp[2] == np[2])) {
24883           // Try to expand the cavity.
24884           expandsteinercavity(sp, eps, frontlist, oldtetlist);
24885           eps *= 10.0;
24886           if (eps > b->epsilon * 1000.0) {
24887           // printf("Internal error: Fail to relocate pt %d.\n",pointmark(sp));
24888             // internalerror();
24889             return false;
24890           }
24891           // Restart the point relocation.
24892           for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24893         }
24894         if (j % 2) {
24895           // Set tp = np (at every 2 steps) to catch the stop state.
24896           for (i = 0; i < 3; i++) tp[i] = np[i];
24897         }
24898         break;
24899       } else {
24900         // Save the smallest volume.
24901         if (i == 0) {
24902           mvol = fabs(ori);
24903         } else {
24904           mvol = fabs(ori) < mvol ? fabs(ori) : mvol;
24905         }
24906       }
24907     }
24908     j++;
24909   } while (!visible);
24910 
24911   if (b->verbose > 1) {
24912     printf("    %d iterations. minvol = %.12g.\n", j, mvol);
24913   }
24914 
24915   // Continue to adjust np until the minimal volume of tets formed by
24916   //   fronts and np doesn't increase (all fronts are visible by np).
24917   k = 0;
24918   do {
24919     j = 0;
24920     do {
24921       if (k == 0) {
24922         // Initial tp := np + 0.9 * (p - np). Move toward p.
24923         for (i = 0; i < 3; i++) tp[i] = sp[i] + 0.9 * (np[i] - sp[i]);
24924       } else {
24925         // Initial tp := np + 1.1 * (p - np). Move away from p.
24926         for (i = 0; i < 3; i++) tp[i] = sp[i] + 1.1 * (np[i] - sp[i]);
24927       }
24928       // Get the minial volume formed by tp with one of the fronts.
24929       for (i = 0; i < frontlist->len(); i++) {
24930         // Get a front face f.
24931         front = * (triface *)(* frontlist)[i];
24932         // Let f face to the interior of C.
24933         adjustedgering(front, CW);
24934         pa = org(front);
24935         pb = dest(front);
24936         pc = apex(front);
24937         ori = orient3d(pa, pb, pc, tp);
24938         visible = (ori < 0.0);
24939         if (visible) {
24940           // Save the smallest volume.
24941           if (i == 0) {
24942             tvol = fabs(ori);
24943           } else {
24944             tvol = fabs(ori) < tvol ? fabs(ori) : tvol;
24945           }
24946         } else {
24947           // A front is invisible by tp. Stop.
24948           tvol = 0.0;
24949           break;
24950         }
24951       }
24952       if (tvol > mvol) {
24953         // Get a larger minimal volume.
24954         for (i = 0; i < 3; i++) np[i] = tp[i];
24955         mvol = tvol;
24956       } else {
24957         // Minimal volume decreases. Stop.
24958         break;
24959       }
24960       // Continue to adjust np.
24961       j++;
24962     } while (true);
24963     // Has np been adjusted?
24964     if (j > 0) break;
24965     // Try to move np to anoter direction.
24966     k++;
24967   } while (k < 2);
24968 
24969   if (b->verbose > 1) {
24970     printf("    %d adjust iterations. minvol = %.12g.\n", j, mvol);
24971   }
24972   return true;
24973 }
24974 
24976 //                                                                           //
24977 // relocatepoint()    Relocate a point into the cavity.                      //
24978 //                                                                           //
24979 // 'frontlist' contains the boundary faces of the cavity C. All fronts must  //
24980 // be visible by 'steinpt'.  Some fronts may hold by 'fake' tets (they are   //
24981 // hull faces).  Fake tets will be removed when they're finished.            //
24982 //                                                                           //
24984 
24985 void tetgenmesh::relocatepoint(point steinpt, triface* oldtet, list* frontlist,
24986   list* newtetlist, queue* flipque)
24987 {
24988   triface front, newtet, newface, neightet;
24989   face checksh;
24990   point pa, pb;
24991   REAL attrib, volume;
24992   bool bdflag;
24993   int i, j, k, l;
24994 
24995   if (b->verbose > 1) {
24996     printf("    Insert Steiner point (%.12g, %.12g, %.12g) %d.\n",
24997            steinpt[0], steinpt[1], steinpt[2], pointmark(steinpt));
24998   }
24999   // Clear the list first.
25000   newtetlist->clear();
25001 
25002   // Create the tets formed by fronts and 'steinpt'.
25003   for (i = 0; i < frontlist->len(); i++) {
25004     // Get a front f.
25005     front = * (triface *)(* frontlist)[i];
25006     // Let f face inside C. (f is a face of tet adjacent to C).
25007     adjustedgering(front, CW);
25008     if (b->verbose > 2) {
25009       printf("    Get front (%d, %d, %d).\n", pointmark(org(front)),
25010              pointmark(dest(front)), pointmark(apex(front)));
25011     }
25012     maketetrahedron(&newtet);
25013     newtetlist->append(&newtet);
25014     setorg(newtet, org(front));
25015     setdest(newtet, dest(front));
25016     setapex(newtet, apex(front));
25017     setoppo(newtet, steinpt);
25018     if (oldtet != (triface *) NULL) {
25019       for (j = 0; j < in->numberoftetrahedronattributes; j++) {
25020         attrib = elemattribute(oldtet->tet, j);
25021         setelemattribute(newtet.tet, j, attrib);
25022       }
25023       if (b->varvolume) {
25024         volume = volumebound(oldtet->tet);
25025         setvolumebound(newtet.tet, volume);
25026       }
25027     }
25028     // 'front' may be a 'fake' tet.
25029     tspivot(front, checksh);
25030     if (oppo(front) == (point) NULL) {
25031       if (checksh.sh != dummysh) {
25032         stdissolve(checksh);
25033       }
25034       // Dealloc the 'fake' tet.
25035       tetrahedrondealloc(front.tet);
25036       // This side (newtet) is a boundary face, let 'dummytet' bond to it.
25037       //   Otherwise, 'dummytet' may point to a dead tetrahedron after the
25038       //   old cavity tets are removed.
25039       dummytet[0] = encode(newtet);
25040     } else {
25041       // Bond two tetrahedra, also dissolve the old bond at 'front'.
25042       bond(newtet, front);
25043     }
25044     if (checksh.sh != dummysh) {
25045       sesymself(checksh);
25046       tsbond(newtet, checksh);
25047     }
25048     if (flipque != (queue *) NULL) {
25049       // f may be non-locally Delaunay and flipable.
25050       enqueueflipface(newtet, flipque);
25051     }
25052     // The three neighbors are open. Will be finished later.
25053   }
25054 
25055   // Connect new tets in C. All connecting faces must contain 'steinpt'.
25056   for (i = 0; i < newtetlist->len(); i++) {
25057     newtet = * (triface *)(* newtetlist)[i];
25058     newtet.ver = 0;
25059     for (j = 0; j < 3; j++) {
25060       fnext(newtet, newface);
25061       sym(newface, neightet);
25062       if (neightet.tet == dummytet) {
25063         // Find a neightet to connect it.
25064         bdflag = false;
25065         pa = org(newface);
25066         pb = dest(newface);
25067         assert(apex(newface) == steinpt);
25068         for (k = i + 1; k < newtetlist->len() && !bdflag; k++) {
25069           neightet = * (triface *)(* newtetlist)[k];
25070           neightet.ver = 0;
25071           for (l = 0; l < 3; l++) {
25072             if ((org(neightet) == pa && dest(neightet) == pb) ||
25073                 (org(neightet) == pb && dest(neightet) == pa)) {
25074               // Find the neighbor.
25075               fnextself(neightet);
25076               assert(apex(neightet) == steinpt);
25077               // Now neightet is a face same as newface, bond them.
25078               bond(newface, neightet);
25079               bdflag = true;
25080               break;
25081             }
25082             enextself(neightet);
25083           }
25084         }
25085         assert(bdflag);
25086       }
25087       enextself(newtet);
25088     }
25089     // Let the corners of newtet point to it for fast searching.
25090     pa = org(newtet);
25091     setpoint2tet(pa, encode(newtet));
25092     pa = dest(newtet);
25093     setpoint2tet(pa, encode(newtet));
25094     pa = apex(newtet);
25095     setpoint2tet(pa, encode(newtet));
25096     pa = oppo(newtet);
25097     setpoint2tet(pa, encode(newtet));
25098   }
25099 
25100   if (flipque != (queue *) NULL) {
25101     // Recover locally Delaunay faces.
25102     flip(flipque, NULL);
25103   }
25104 }
25105 
25107 //                                                                           //
25108 // findcollapseedge()    Find collapseable edge to suppress an endpoint.     //
25109 //                                                                           //
25111 
25112 bool tetgenmesh::findcollapseedge(point suppt, point *conpt, list* oldtetlist,
25113   list* ptlist)
25114 {
25115   triface front;
25116   point pt, pa, pb, pc;
25117   REAL *lenarray, ltmp, ori;
25118   bool visflag;
25119   int *idxarray, itmp;
25120   int n, i, j;
25121 
25122   if (b->verbose > 2) {
25123     printf("    Search an edge (in %d edges) for collapse %d.\n",
25124            ptlist->len(), pointmark(suppt));
25125   }
25126 
25127   // Candidate edges are p to the points of B(p) (in 'ptlist').
25128   n = ptlist->len();
25129   lenarray = new REAL[n];
25130   idxarray = new int[n];
25131   // Sort the points of B(p) by distance to p.
25132   for (i = 0; i < n; i++) {
25133     pt = * (point *)(* ptlist)[i];
25134     lenarray[i] = distance(suppt, pt);
25135     idxarray[i] = i;
25136   }
25137   // Bubble sort.
25138   for (i = 0; i < n - 1; i++) {
25139     for (j = 0; j < n - 1 - i; j++) {
25140       if (lenarray[j + 1] < lenarray[j]) {  // compare the two neighbors
25141         ltmp = lenarray[j];           // swap a[j] and a[j + 1]
25142         lenarray[j] = lenarray[j + 1];
25143         lenarray[j + 1] = ltmp;
25144         itmp = idxarray[j];           // swap a[j] and a[j + 1]
25145         idxarray[j] = idxarray[j + 1];
25146         idxarray[j + 1] = itmp;
25147       }
25148     }
25149   }
25150   // For each point q of B(p), test if the edge (p, q) can be collapseed.
25151   for (i = 0; i < n; i++) {
25152     pt = * (point *)(* ptlist)[idxarray[i]];
25153     // Is q visible by faces of B(p) not with q as a vertex.
25154     lenarray[i] = 0.0; // zero volume.
25155     visflag = true;
25156     for (j = 0; j < oldtetlist->len() && visflag; j++) {
25157       front = * (triface *)(* oldtetlist)[j];
25158       // Let f face to inside of B(p).
25159       adjustedgering(front, CCW);
25160       pa = org(front);
25161       pb = dest(front);
25162       pc = apex(front);
25163       // Is f contains q?
25164       if ((pa != pt) && (pb != pt) && (pc != pt)) {
25165         ori = orient3d(pa, pb, pc, pt);
25166         if (ori != 0.0) {
25167           if (iscoplanar(pa, pb, pc, pt, ori, b->epsilon * 1e+2)) ori = 0.0;
25168         }
25169         visflag = ori < 0.0;
25170         if (visflag) {
25171           // Visible, set the smallest volume.
25172           if (j == 0) {
25173             lenarray[i] = fabs(ori);
25174           } else {
25175             lenarray[i] = fabs(ori) < lenarray[i] ? fabs(ori) : lenarray[i];
25176           }
25177         } else {
25178           // Invisible. Do not collapse (p, q).
25179           lenarray[i] = 0.0;
25180         }
25181       }
25182     }
25183     if ((b->verbose > 2) && visflag) {
25184       printf("    Got candidate %d vol(%g).\n", pointmark(pt), lenarray[i]);
25185     }
25186   }
25187 
25188   // Select the largest non-zero volume (result in ltmp).
25189   ltmp = lenarray[0];
25190   itmp = idxarray[0];
25191   for (i = 1; i < n; i++) {
25192     if (lenarray[i] != 0.0) {
25193       if (lenarray[i] > ltmp) {
25194         ltmp = lenarray[i];
25195         itmp = idxarray[i]; // The index to find the point.
25196       }
25197     }
25198   }
25199 
25200   delete [] lenarray;
25201   delete [] idxarray;
25202 
25203   if (ltmp == 0.0) {
25204     // No edge can be collapseed.
25205     *conpt = (point) NULL;
25206     return false;
25207   } else {
25208     pt = * (point *)(* ptlist)[itmp];
25209     *conpt = pt;
25210     return true;
25211   }
25212 }
25213 
25215 //                                                                           //
25216 // collapseedge()    Remove a point by edge collapse.                        //
25217 //                                                                           //
25219 
25220 void tetgenmesh::collapseedge(point suppt, point conpt, list* oldtetlist,
25221   list* deadtetlist)
25222 {
25223   triface oldtet, deadtet;
25224   triface adjtet1, adjtet2;
25225   face adjsh;
25226   point pa, pb, pc;
25227   int i, j;
25228 
25229   if (b->verbose > 2) {
25230     printf("    Collapse edge (%d,%d).\n", pointmark(suppt), pointmark(conpt));
25231   }
25232 
25233   // Loop in B(p), replace p with np, queue dead tets, uninfect old tets.
25234   for (i = 0; i < oldtetlist->len(); i++) {
25235     oldtet = * (triface *)(* oldtetlist)[i]; // assert(infected(oldtet));
25236     uninfect(oldtet);
25237     pa = org(oldtet);
25238     pb = dest(oldtet);
25239     pc = apex(oldtet);
25240     assert(oppo(oldtet) == suppt);
25241     setoppo(oldtet, conpt);
25242     if ((pa == conpt) || (pb == conpt) || (pc == conpt)) {
25243       deadtetlist->append(&oldtet); // a collpased tet.
25244     }
25245   }
25246   // Loop in deadtetlist, glue adjacent tets of dead tets.
25247   for (i = 0; i < deadtetlist->len(); i++) {
25248     deadtet = * (triface *)(* deadtetlist)[i];
25249     // Get the adjacent tet n1 (outside B(p)).
25250     sym(deadtet, adjtet1);
25251     tspivot(deadtet, adjsh);
25252     // Find the edge in deadtet opposite to conpt.
25253     adjustedgering(deadtet, CCW);
25254     for (j = 0; j < 3; j++) {
25255       if (apex(deadtet) == conpt) break;
25256       enextself(deadtet);
25257     }
25258     assert(j < 3);
25259     // Get another adjacent tet n2.
25260     fnext(deadtet, adjtet2);
25261     symself(adjtet2);
25262     assert(adjtet2.tet != dummytet); // n2 is inside B(p).
25263     if (adjtet1.tet != dummytet) {
25264       bond(adjtet1, adjtet2); // Bond n1 <--> n2.
25265     } else {
25266       dissolve(adjtet2); // Dissolve at n2.
25267       dummytet[0] = encode(adjtet2); // Let dummytet holds n2.
25268     }
25269     if (adjsh.sh != dummysh) {
25270       tsbond(adjtet2, adjsh); // Bond s <--> n2.
25271     }
25272     // Collapse deadtet.
25273     tetrahedrondealloc(deadtet.tet);
25274   }
25275   deadtetlist->clear();
25276 }
25277 
25279 //                                                                           //
25280 // deallocfaketets()    Deleted fake tets at fronts.                         //
25281 //                                                                           //
25282 // This routine is only called when the findrelocatepoint() routine fails.   //
25283 // In other cases, the fake tets are removed automatically in carvecavity()  //
25284 // or relocatepoint().                                                       //
25285 //                                                                           //
25287 
25288 void tetgenmesh::deallocfaketets(list* frontlist)
25289 {
25290   triface front, neightet;
25291   face checksh;
25292   bool infectflag;
25293   int i;
25294 
25295   for (i = 0; i < frontlist->len(); i++) {
25296     // Get a front f.
25297     front = * (triface *)(* frontlist)[i];
25298     // Let f face inside C. (f is a face of tet adjacent to C).
25299     adjustedgering(front, CW);
25300     sym(front, neightet);
25301     tspivot(front, checksh);
25302     if (oppo(front) == (point) NULL) {
25303       if (b->verbose > 2) {
25304         printf("    Get fake tet (%d, %d, %d).\n", pointmark(org(front)),
25305                pointmark(dest(front)), pointmark(apex(front)));
25306       }
25307       if (neightet.tet != dummytet) {
25308         // The neightet may be infected. After dissolve it, the infect flag
25309         //   will be lost. Save the flag and restore it later.
25310         infectflag = infected(neightet);
25311         dissolve(neightet);
25312         if (infectflag) {
25313           infect(neightet);
25314         }
25315       }
25316       if (checksh.sh != dummysh) {
25317         infectflag = sinfected(checksh);
25318         stdissolve(checksh);
25319         if (infectflag) {
25320           sinfect(checksh);
25321         }
25322       }
25323       // Dealloc the 'fake' tet.
25324       tetrahedrondealloc(front.tet);
25325       // If 'neightet' is a hull face, let 'dummytet' bond to it. It is
25326       //   a 'dummytet' when this front was created from a new subface.
25327       //   In such case, it should not be bounded.
25328       if (neightet.tet != dummytet) {
25329         dummytet[0] = encode(neightet);
25330       }
25331     }
25332   }
25333 }
25334 
25336 //                                                                           //
25337 // restorepolyhedron()    Restore the tetrahedralization in a polyhedron.    //
25338 //                                                                           //
25339 // This routine is only called when the operation of suppressing a point is  //
25340 // aborted (eg., findrelocatepoint() routine fails). The polyhedron has been //
25341 // remeshed by new tets. This routine restore the old tets in it.            //
25342 //                                                                           //
25343 // 'oldtetlist' contains the list of old tets. Each old tet t_o assumes that //
25344 // it still connects to a tet t_b of the mesh, however, t_b does not connect //
25345 // to t_o, this routine resets the connection such that t_b <--> t_o.        //
25346 //                                                                           //
25348 
25349 void tetgenmesh::restorepolyhedron(list* oldtetlist)
25350 {
25351   triface oldtet, neightet, neineitet;
25352   face checksh;
25353   int i;
25354 
25355   for (i = 0; i < oldtetlist->len(); i++) {
25356     // Get an old tet t_o.
25357     oldtet = * (triface *)(* oldtetlist)[i];
25358     // Check the four sides of t_o.
25359     for (oldtet.loc = 0; oldtet.loc < 4; oldtet.loc++) {
25360       sym(oldtet, neightet);
25361       tspivot(oldtet, checksh);
25362       if (neightet.tet != dummytet) {
25363         sym(neightet, neineitet);
25364         if (neineitet.tet != oldtet.tet) {
25365           // This face of t_o is a boundary of P.
25366           bond(neightet, oldtet);
25367           if (checksh.sh != dummysh) {
25368             tsbond(oldtet, checksh);
25369           }
25370         }
25371       } else {
25372         // t_o has a hull face. It should be the boundary of P.
25373 #ifdef SELF_CHECK
25374         assert(checksh.sh != dummysh);
25375         stpivot(checksh, neineitet);
25376         assert(neineitet.tet != oldtet.tet);
25377 #endif
25378         tsbond(oldtet, checksh);
25379         // Let dummytet[0] points to it.
25380         dummytet[0] = encode(oldtet);
25381       }
25382     }
25383   }
25384 }
25385 
25387 //                                                                           //
25388 // suppressfacetpoint()    Suppress a point inside a facet.                  //
25389 //                                                                           //
25390 // The point p inside a facet F will be suppressed from F by either being    //
25391 // deleted from the mesh or being relocated into the volume.                 //
25392 //                                                                           //
25393 // 'supsh' is a subface f of F, and p = sapex(f); the other parameters are   //
25394 // working lists which are empty at the beginning and the end.               //
25395 //                                                                           //
25396 // 'optflag' is used for mesh optimization. If it is set, after removing p,  //
25397 // test the object function on each new tet, queue bad tets.                 //
25398 //                                                                           //
25400 
25401 bool tetgenmesh::suppressfacetpoint(face* supsh, list* frontlist,
25402   list* misfrontlist, list* ptlist, list* conlist, memorypool* viri,
25403   queue* flipque, bool noreloc, bool optflag)
25404 {
25405   list *oldtetlist[2], *newtetlist[2];
25406   list *oldshlist, *newshlist;
25407   triface oldtet, newtet;
25408   face oldsh, newsh;
25409   point suppt, newpt[2];
25410   point *cons;
25411   REAL norm[3];
25412   bool success;
25413   int shmark;
25414   int i, j;
25415 
25416   suppt = sapex(*supsh);
25417   if (b->verbose > 1) {
25418     printf("    Suppress point %d in facet.\n", pointmark(suppt));
25419   }
25420 
25421   // Initialize working lists, variables.
25422   for (i = 0; i < 2; i++) {
25423     oldtetlist[i] = (list *) NULL;
25424     newtetlist[i] = (list *) NULL;
25425     newpt[i] = (point) NULL;
25426   }
25427   oldshlist = new list(sizeof(face), NULL, 256);
25428   newshlist = new list(sizeof(face), NULL, 256);
25429   success = true; // Assume p can be suppressed.
25430 
25431   // Find subs of C(p).
25432   oldshlist->append(supsh);
25433   formstarpolygon(suppt, oldshlist, ptlist);
25434   // Get the edges of C(p). They form a closed polygon.
25435   for (i = 0; i < oldshlist->len(); i++) {
25436     oldsh = * (face *)(* oldshlist)[i];
25437     cons = (point *) conlist->append(NULL);
25438     cons[0] = sorg(oldsh);
25439     cons[1] = sdest(oldsh);
25440   }
25441   // Re-triangulate the old C(p).
25442   shmark = shellmark(*supsh);
25443   triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25444   // Get new subs of C(p), remove protected segments.
25445   retrievenewsubs(newshlist, true);
25446   // Substitute the old C(p) with the new C(p)
25447   replacepolygonsubs(oldshlist, newshlist);
25448   // Clear work lists.
25449   ptlist->clear();
25450   conlist->clear();
25451   flipque->clear();
25452   viri->restart();
25453 
25454   // B(p) (tets with p as a vertex) has been separated into two parts
25455   //   (B_0(p) and B_1(p)) by F. Process them individually.
25456   for (i = 0; i < 2 && success; i++) {
25457     if (i == 1) sesymself(*supsh);
25458     // Get a tet containing p.
25459     stpivot(*supsh, oldtet);
25460     // Is this part empty?
25461     if (oldtet.tet == dummytet) continue;
25462     // Allocate spaces for storing (old and new) B_i(p).
25463     oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25464     newtetlist[i] = new list(sizeof(triface), NULL, 256);
25465     // Form old B_i(p) in oldtetlist[i].
25466     assert(!isdead(&oldtet));
25467     oldtetlist[i]->append(&oldtet);
25468     formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25469     // Infect the tets in old B_i(p) (they're going to be delete).
25470     for (j = 0; j < oldtetlist[i]->len(); j++) {
25471       oldtet = * (triface *)(* (oldtetlist[i]))[j];
25472       infect(oldtet);
25473     }
25474     // Preparation for re-tetrahedralzing old B_i(p).
25475     orientnewsubs(newshlist, supsh, norm);
25476     // Tetrahedralize old B_i(p).
25477     success = constrainedcavity(&oldtet, newshlist, oldtetlist[i], ptlist,
25478                 frontlist, misfrontlist, newtetlist[i], flipque);
25479     // If p is not suppressed, do relocation if 'noreloc' is not set.
25480     if (!success && !noreloc) {
25481       // Try to relocate p into the old B_i(p).
25482       makepoint(&(newpt[i]));
25483       success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25484                                   oldtetlist[i]);
25485       // Initialize newpt = suppt.
25486       // for (j = 0; j < 3; j++) newpt[i][j] = suppt[j];
25487       // success = smoothvolpoint(newpt[i], frontlist, true);
25488       if (success) {
25489         // p is relocated by newpt[i]. Now insert it. Don't do flip since
25490         //   the new tets may get deleted again.
25491         relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25492         setpointtype(newpt[i], FREEVOLVERTEX);
25493         relverts++;
25494       } else {
25495         // Fail to relocate p. Clean fake tets and quit this option.
25496         deallocfaketets(frontlist);
25497         pointdealloc(newpt[i]);
25498         newpt[i] = (point) NULL;
25499         assert(newtetlist[i]->len() == 0);
25500       }
25501     }
25502     if (!success && noreloc) {
25503       // Failed and no point relocation. Clean fake tets.
25504       deallocfaketets(frontlist);
25505     }
25506     // Clear work lists.
25507     ptlist->clear();
25508     frontlist->clear();
25509     misfrontlist->clear();
25510     flipque->clear();
25511   }
25512 
25513   if (success) {
25514     // p has been removed! (Still in the pool).
25515     setpointtype(suppt, UNUSEDVERTEX);
25516     unuverts++;
25517     // Delete old C(p).
25518     for (i = 0; i < oldshlist->len(); i++) {
25519       oldsh = * (face *)(* oldshlist)[i];
25520       if (i == 0) {
25521         // Update the 'hullsize' if C(p) is on the hull.
25522         stpivot(oldsh, oldtet);
25523         if (oldtet.tet != dummytet) {
25524           sesymself(oldsh);
25525           stpivot(oldsh, oldtet);
25526         }
25527         if (oldtet.tet == dummytet) {
25528           // A boundary face. Update the 'hullsize'.
25529           j = oldshlist->len() - newshlist->len();
25530           assert(j > 0);
25531           hullsize -= j;
25532         }
25533       }
25534       shellfacedealloc(subfaces, oldsh.sh);
25535     }
25536     // Delete old B_i(p).
25537     for (i = 0; i < 2; i++) {
25538       if (oldtetlist[i] != (list *) NULL) {
25539         // Delete tets of the old B_i(p).
25540         for (j = 0; j < oldtetlist[i]->len(); j++) {
25541           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25542           assert(!isdead(&oldtet));
25543           tetrahedrondealloc(oldtet.tet);
25544         }
25545       }
25546     }
25547     if (optflag) {
25548       // Check for new bad-quality tets.
25549       for (i = 0; i < 2; i++) {
25550         if (newtetlist[i] != (list *) NULL) {
25551           for (j = 0; j < newtetlist[i]->len(); j++) {
25552             newtet = * (triface *)(* (newtetlist[i]))[j];
25553             if (!isdead(&newtet)) checktet4opt(&newtet, true);
25554           }
25555         }
25556       }
25557     }
25558   } else {
25559     // p is not suppressed. Recover the original state.
25560     unsupverts++;
25561     // Restore the old C(p).
25562     replacepolygonsubs(newshlist, oldshlist);
25563     // Delete subs of the new C(p)
25564     for (i = 0; i < newshlist->len(); i++) {
25565       newsh = * (face *)(* newshlist)[i];
25566       shellfacedealloc(subfaces, newsh.sh);
25567     }
25568     // Restore old B_i(p).
25569     for (i = 0; i < 2; i++) {
25570       if (oldtetlist[i] != (list *) NULL) {
25571         // Uninfect tets of old B_i(p).
25572         for (j = 0; j < oldtetlist[i]->len(); j++) {
25573           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25574           assert(infected(oldtet));
25575           uninfect(oldtet);
25576         }
25577         // Has it been re-meshed?
25578         if (newtetlist[i]->len() > 0) {
25579           // Restore the old B_i(p).
25580           restorepolyhedron(oldtetlist[i]);
25581           // Delete tets of the new B_i(p);
25582           for (j = 0; j < newtetlist[i]->len(); j++) {
25583             newtet = * (triface *)(* (newtetlist[i]))[j];
25584             // Some new tets may already be deleted (by carvecavity()).
25585             if (!isdead(&newtet)) {
25586               tetrahedrondealloc(newtet.tet);
25587             }
25588           }
25589         }
25590         // Dealloc newpt[i] if it exists.
25591         if (newpt[i] != (point) NULL) {
25592           pointdealloc(newpt[i]);
25593           relverts--;
25594         }
25595       }
25596     }
25597   }
25598 
25599   // Delete work lists.
25600   delete oldshlist;
25601   delete newshlist;
25602   for (i = 0; i < 2; i++) {
25603     if (oldtetlist[i] != (list *) NULL) {
25604       delete oldtetlist[i];
25605       delete newtetlist[i];
25606     }
25607   }
25608 
25609   return success;
25610 }
25611 
25613 //                                                                           //
25614 // suppresssegpoint()    Suppress a point on a segment.                      //
25615 //                                                                           //
25616 // The point p on a segment S will be suppressed from S by either being      //
25617 // deleted from the mesh or being relocated into the volume.                 //
25618 //                                                                           //
25619 // 'supseg' is the segment S, and p = sdest(S); the other parameters are     //
25620 // working lists which are empty at the beginning and the end.               //
25621 //                                                                           //
25623 
25624 bool tetgenmesh::suppresssegpoint(face* supseg, list* spinshlist,
25625   list* newsegshlist, list* frontlist, list* misfrontlist, list* ptlist,
25626   list* conlist, memorypool* viri, queue* flipque, bool noreloc, bool optflag)
25627 {
25628   list **oldtetlist, **newtetlist;
25629   list **oldshlist, **newshlist;
25630   list *pnewshlist, *dnewshlist;
25631   triface oldtet, newtet;
25632   face oldsh, newsh;
25633   face startsh, spinsh, segsh1, segsh2;
25634   face nsupseg, newseg, prevseg, nextseg;
25635   point suppt, *newpt;
25636   point pa, pb, *cons;
25637   REAL pnorm[2][3], norm[3];
25638   bool success;
25639   int shmark;
25640   int n, i, j, k;
25641 
25642   // Get the Steiner point p.
25643   assert(supseg->shver < 2);
25644   suppt = sdest(*supseg);
25645   // Find the segment ab split by p.
25646   senext(*supseg, nsupseg);
25647   spivotself(nsupseg);
25648   assert(nsupseg.sh != dummysh);
25649   nsupseg.shver = 0;
25650   if (sorg(nsupseg) != suppt) sesymself(nsupseg);
25651   assert(sorg(nsupseg) == suppt);
25652   pa = sorg(*supseg);
25653   pb = sdest(nsupseg);
25654   if (b->verbose > 1) {
25655     printf("    Remove point %d on segment (%d, %d).\n",
25656            pointmark(suppt), pointmark(pa), pointmark(pb));
25657   }
25658 
25659   // Let startsh s containing p.
25660   spivot(*supseg, startsh);
25661   spinsh = startsh;
25662   do {
25663     // Save it in list.
25664     spinshlist->append(&spinsh);
25665     // Go to the next facet.
25666     spivotself(spinsh);
25667   } while (spinsh.sh != startsh.sh);
25668   if (spinshlist->len() == 1) {
25669     // This case has not handled yet.
25670     // printf("Unhandled case: segment only belongs to one facet.\n");
25671     spinshlist->clear();
25672     unsupverts++;
25673     return false;
25674   }
25675 
25676   // Suppose ab is shared by n facets (n > 1), then there are n B(p) (tets
25677   //   with p as a vertex). Some B(p) may be empty, eg, outside.
25678   n = spinshlist->len();
25679   oldtetlist = new list*[n];
25680   newtetlist = new list*[n];
25681   oldshlist = new list*[n];
25682   newshlist = new list*[n];
25683   newpt = new point[n];
25684   for (i = 0; i < n; i++) {
25685     oldtetlist[i] = (list *) NULL;
25686     newtetlist[i] = (list *) NULL;
25687     oldshlist[i] = (list *) NULL;
25688     newshlist[i] = (list *) NULL;
25689     newpt[i] = (point) NULL;
25690   }
25691 
25692   // Create a new segment ab (result in newseg).
25693   makeshellface(subsegs, &newseg);
25694   setsorg(newseg, pa);
25695   setsdest(newseg, pb);
25696   // ab gets the same mark and segment type as ap.
25697   setshellmark(newseg, shellmark(*supseg));
25698   setshelltype(newseg, shelltype(*supseg));
25699   if (b->quality && varconstraint) {
25700     // Copy the areabound into the new subsegment.
25701     setareabound(newseg, areabound(*supseg));
25702   }
25703   // Save the old connection at a.
25704   senext2(*supseg, prevseg);
25705   spivotself(prevseg);
25706   if (prevseg.sh != dummysh) {
25707     prevseg.shver = 0;
25708     if (sdest(prevseg) != pa) sesymself(prevseg);
25709     assert(sdest(prevseg) == pa);
25710     senextself(prevseg);
25711     senext2self(newseg);
25712     sbond(newseg, prevseg);
25713     newseg.shver = 0;
25714   }
25715   // Save the old connection at b.
25716   senext(nsupseg, nextseg);
25717   spivotself(nextseg);
25718   if (nextseg.sh != dummysh) {
25719     nextseg.shver = 0;
25720     if (sorg(nextseg) != pb) sesymself(nextseg);
25721     assert(sorg(nextseg) == pb);
25722     senext2self(nextseg);
25723     senextself(newseg);
25724     sbond(newseg, nextseg);
25725     newseg.shver = 0;
25726   }
25727 
25728   // Re-triangulate C(p) (subs with p as a vertex) to remove p.
25729   for (i = 0; i < spinshlist->len(); i++) {
25730     spinsh = * (face *)(* spinshlist)[i];
25731     // Allocate spaces for C_i(p).
25732     oldshlist[i] = new list(sizeof(face), NULL, 256);
25733     newshlist[i] = new list(sizeof(face), NULL, 256);
25734     // Get the subs of C_i(p).
25735     oldshlist[i]->append(&spinsh);
25736     formstarpolygon(suppt, oldshlist[i], ptlist);
25737     // Find the edges of C_i(p). It DOES NOT form a closed polygon.
25738     for (j = 0; j < oldshlist[i]->len(); j++) {
25739       oldsh = * (face *)(* (oldshlist[i]))[j];
25740       cons = (point *) conlist->append(NULL);
25741       cons[0] = sorg(oldsh);
25742       cons[1] = sdest(oldsh);
25743     }
25744     // The C_i(p) isn't closed without ab. Add it to it.
25745     cons = (point *) conlist->append(NULL);
25746     cons[0] = pa;
25747     cons[1] = pb;
25748     // Re-triangulate C_i(p).
25749     shmark = shellmark(spinsh);
25750     triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25751     // Get new subs of C_i(p), remove protected segments.
25752     retrievenewsubs(newshlist[i], true);
25753     // Substitute old C_i(p) with the new C_i(p). !IT IS NOT COMPLETE!
25754     replacepolygonsubs(oldshlist[i], newshlist[i]);
25755     // Find the new subface s having edge ab.
25756     for (j = 0; j < newshlist[i]->len(); j++) {
25757       segsh1 = * (face *)(* (newshlist[i]))[j];
25758       for (k = 0; k < 3; k++) {
25759         if (((sorg(segsh1) == pa) && (sdest(segsh1) == pb)) ||
25760             ((sorg(segsh1) == pb) && (sdest(segsh1) == pa))) break;
25761         senextself(segsh1);
25762       }
25763       if (k < 3) break; // Found.
25764     }
25765     assert(j < newshlist[i]->len()); // ab must exist.
25766     // Bond s and ab together. The C_i(p) is completedly substituted.
25767     ssbond(segsh1, newseg);
25768     // Save s for forming the face ring of ab.
25769     newsegshlist->append(&segsh1);
25770     // Clear work lists.
25771     ptlist->clear();
25772     conlist->clear();
25773     flipque->clear();
25774     viri->restart();
25775   }
25776   // Form the face ring of ab.
25777   for (i = 0; i < newsegshlist->len(); i++) {
25778     segsh1 = * (face *)(* newsegshlist)[i];
25779     if ((i + 1) == newsegshlist->len()) {
25780       segsh2 = * (face *)(* newsegshlist)[0];
25781     } else {
25782       segsh2 = * (face *)(* newsegshlist)[i + 1];
25783     }
25784     sbond1(segsh1, segsh2);
25785   }
25786 
25787   // A work list for keeping subfaces from two facets.
25788   dnewshlist = new list(sizeof(face), NULL, 256);
25789   success = true; // Assume p is suppressable.
25790 
25791   // Suppress p in all B(p). B_i(p) is looped wrt the right-hand rule of ab.
25792   for (i = 0; i < spinshlist->len() && success; i++) {
25793     // Get an old  subface s (ap) of a facet.
25794     spinsh = * (face *)(* spinshlist)[i];
25795     // Let the edge direction of s be a->b. Hence all subfaces follow
25796     //   the right-hand rule of ab.
25797     if (sorg(spinsh) != pa) sesymself(spinsh);
25798     // Get a tet t of B_i(p).
25799     stpivot(spinsh, oldtet);
25800     // Is B_i(p) empty?
25801     if (oldtet.tet == dummytet) continue;
25802     // Allocate spaces for B_i(p).
25803     oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25804     newtetlist[i] = new list(sizeof(triface), NULL, 256);
25805     // Find all tets of old B_i(p).
25806     oldtetlist[i]->append(&oldtet);
25807     formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25808     // Infect tets of old B_i(p) (they're going to be deleted).
25809     for (j = 0; j < oldtetlist[i]->len(); j++) {
25810       oldtet = * (triface *)(* (oldtetlist[i]))[j];
25811       infect(oldtet);
25812     }
25813     // Collect new subfaces (of two facets) bounded B_i(p).
25814     for (k = 0; k < 2; k++) {
25815       if ((i + k) < spinshlist->len()) {
25816         pnewshlist = newshlist[i + k];
25817         segsh1 = * (face *)(* spinshlist)[i + k];
25818       } else {
25819         pnewshlist = newshlist[0];
25820         segsh1 = * (face *)(* spinshlist)[0];
25821       }
25822       // Adjust the orientation of segsh1 to face to the inside of C.
25823       if (k == 0) {
25824         if (sorg(segsh1) != pa) sesymself(segsh1);
25825         assert(sorg(segsh1) == pa);
25826       } else {
25827         if (sdest(segsh1) != pa) sesymself(segsh1);
25828         assert(sdest(segsh1) == pa);
25829       }
25830       // Preparation for re-tetrahedralzing old B_i(p).
25831       orientnewsubs(pnewshlist, &segsh1, pnorm[k]);
25832       for (j = 0; j < pnewshlist->len(); j++) {
25833         dnewshlist->append((face *)(* pnewshlist)[j]);
25834       }
25835     }
25836     // Tetrahedralize B_i(p).
25837     success = constrainedcavity(&oldtet, dnewshlist, oldtetlist[i], ptlist,
25838                 frontlist, misfrontlist, newtetlist[i], flipque);
25839     if (!success && !noreloc) {
25840       // C must be finished by re-locating the steiner point.
25841       makepoint(&(newpt[i]));
25842       for (j = 0; j < 3; j++) norm[j] = 0.5 * (pnorm[0][j] + pnorm[1][j]);
25843       success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25844                                   oldtetlist[i]);
25845       // for (j = 0; j < 3; j++) newpt[i][j] = suppt[j];
25846       // success = smoothvolpoint(newpt[i], frontlist, true);
25847       if (success) {
25848         // p is relocated by newpt[i]. Now insert it. Don't do flip since
25849         //   the new tets may get deleted again.
25850         relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25851         setpointtype(newpt[i], FREEVOLVERTEX);
25852         relverts++;
25853       } else {
25854         // Fail to relocate p. Clean fake tets and quit this option.
25855         deallocfaketets(frontlist);
25856         pointdealloc(newpt[i]);
25857         newpt[i] = (point) NULL;
25858         assert(newtetlist[i]->len() == 0);
25859       }
25860     }
25861     if (!success && noreloc) {
25862       // Failed and no point relocation. Clean fake tets.
25863       deallocfaketets(frontlist);
25864     }
25865     // Clear work lists.
25866     dnewshlist->clear();
25867     ptlist->clear();
25868     frontlist->clear();
25869     misfrontlist->clear();
25870     flipque->clear();
25871   }
25872 
25873   if (success) {
25874     // p has been suppressed. (Still in the pool).
25875     setpointtype(suppt, UNUSEDVERTEX);
25876     unuverts++;
25877     // Update the segmnet pointers saved in a and b.
25878     setpoint2sh(pa, sencode(newseg));
25879     setpoint2sh(pb, sencode(newseg));
25880     // Delete old segments ap, pb.
25881     shellfacedealloc(subsegs, supseg->sh);
25882     shellfacedealloc(subsegs, nsupseg.sh);
25883     // Delete subs of old C_i(p).
25884     for (i = 0; i < spinshlist->len(); i++) {
25885       for (j = 0; j < oldshlist[i]->len(); j++) {
25886         oldsh = * (face *)(* (oldshlist[i]))[j];
25887         if (j == 0) {
25888           // Update 'hullsize' if C_i(p) is on the hull.
25889           stpivot(oldsh, oldtet);
25890           if (oldtet.tet != dummytet) {
25891             sesymself(oldsh);
25892             stpivot(oldsh, oldtet);
25893           }
25894           if (oldtet.tet == dummytet) {
25895             // Update 'hullsize'.
25896             k = oldshlist[i]->len() - newshlist[i]->len();
25897             assert(k > 0);
25898             hullsize -= k;
25899           }
25900         }
25901         shellfacedealloc(subfaces, oldsh.sh);
25902       }
25903     }
25904     // Delete tets old B_i(p).
25905     for (i = 0; i < spinshlist->len(); i++) {
25906       // Delete them if it is not empty.
25907       if (oldtetlist[i] != (list *) NULL) {
25908         for (j = 0; j < oldtetlist[i]->len(); j++) {
25909           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25910           assert(!isdead(&oldtet));
25911           tetrahedrondealloc(oldtet.tet);
25912         }
25913       }
25914     }
25915     if (optflag) {
25916       for (i = 0; i < spinshlist->len(); i++) {
25917         // Check for new bad-quality tets.
25918         if (newtetlist[i] != (list *) NULL) {
25919           for (j = 0; j < newtetlist[i]->len(); j++) {
25920             newtet = * (triface *)(* (newtetlist[i]))[j];
25921             if (!isdead(&newtet)) checktet4opt(&newtet, true);
25922           }
25923         }
25924       }
25925     }
25926   } else {
25927     // p is not suppressed. Recover the original state.
25928     unsupverts++;
25929     // Restore old connection at a.
25930     senext2(*supseg, prevseg);
25931     spivotself(prevseg);
25932     if (prevseg.sh != dummysh) {
25933       prevseg.shver = 0;
25934       if (sdest(prevseg) != pa) sesymself(prevseg);
25935       assert(sdest(prevseg) == pa);
25936       senextself(prevseg);
25937       senext2self(*supseg);
25938       sbond(*supseg, prevseg);
25939       senextself(*supseg); // Restore original state.
25940       assert(supseg->shver < 2);
25941     }
25942     // Restore old connection at b.
25943     senext(nsupseg, nextseg);
25944     spivotself(nextseg);
25945     if (nextseg.sh != dummysh) {
25946       nextseg.shver = 0;
25947       if (sorg(nextseg) != pb) sesymself(nextseg);
25948       assert(sorg(nextseg) == pb);
25949       senext2self(nextseg);
25950       senextself(nsupseg);
25951       sbond(nsupseg, nextseg);
25952       // nsupseg.shver = 0;
25953       senext2self(nsupseg); // Restore original state
25954       assert(nsupseg.shver < 2);
25955     }
25956     // Delete the new segment ab.
25957     shellfacedealloc(subsegs, newseg.sh);
25958     // Restore old C_i(p).
25959     for (i = 0; i < spinshlist->len(); i++) {
25960       replacepolygonsubs(newshlist[i], oldshlist[i]);
25961       // Delete subs of the new C_i(p)
25962       for (j = 0; j < newshlist[i]->len(); j++) {
25963         newsh = * (face *)(* (newshlist[i]))[j];
25964         shellfacedealloc(subfaces, newsh.sh);
25965       }
25966     }
25967     // Restore old B_i(p).
25968     for (i = 0; i < spinshlist->len(); i++) {
25969       if (oldtetlist[i] != (list *) NULL) {
25970         // Uninfect tets of old B_i(p).
25971         for (j = 0; j < oldtetlist[i]->len(); j++) {
25972           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25973           assert(infected(oldtet));
25974           uninfect(oldtet);
25975         }
25976         // Has it been re-meshed?
25977         if (newtetlist[i]->len() > 0) {
25978           // Restore the old B_i(p).
25979           restorepolyhedron(oldtetlist[i]);
25980           // Delete tets of the new B_i(p);
25981           for (j = 0; j < newtetlist[i]->len(); j++) {
25982             newtet = * (triface *)(* (newtetlist[i]))[j];
25983             // Some new tets may already be deleted (by carvecavity()).
25984             if (!isdead(&newtet)) {
25985               tetrahedrondealloc(newtet.tet);
25986             }
25987           }
25988         }
25989         // Dealloc newpt[i] if it exists.
25990         if (newpt[i] != (point) NULL) {
25991           pointdealloc(newpt[i]);
25992           relverts--;
25993         }
25994       }
25995     }
25996   }
25997 
25998   // Delete work lists.
25999   delete dnewshlist;
26000   for (i = 0; i < spinshlist->len(); i++) {
26001     delete oldshlist[i];
26002     delete newshlist[i];
26003   }
26004   delete [] oldshlist;
26005   delete [] newshlist;
26006   for (i = 0; i < spinshlist->len(); i++) {
26007     if (oldtetlist[i] != (list *) NULL) {
26008       delete oldtetlist[i];
26009       delete newtetlist[i];
26010     }
26011   }
26012   delete [] oldtetlist;
26013   delete [] newtetlist;
26014   // Clear work lists.
26015   newsegshlist->clear();
26016   spinshlist->clear();
26017 
26018   return success;
26019 }
26020 
26022 //                                                                           //
26023 // suppressvolpoint()    Suppress a point inside mesh.                       //
26024 //                                                                           //
26025 // The point p = org(suptet) is inside the mesh and will be suppressed from  //
26026 // the mesh. Note that p may not be suppressed.                              //
26027 //                                                                           //
26028 // 'optflag' is used for mesh optimization. If it is set, after removing p,  //
26029 // test the object function on each new tet, queue bad tets.                 //
26030 //                                                                           //
26032 
26033 bool tetgenmesh::suppressvolpoint(triface* suptet, list* frontlist,
26034   list* misfrontlist, list* ptlist, queue* flipque, bool optflag)
26035 {
26036   list *myfrontlist, *mymisfrontlist, *myptlist;
26037   list *oldtetlist, *newtetlist;
26038   list *newshlist; // a dummy list.
26039   queue *myflipque;
26040   triface oldtet, newtet;
26041   point suppt, conpt;
26042   bool success;
26043   int j;
26044 
26045   // Allocate spaces for storing (old and new) B(p).
26046   oldtetlist = new list(sizeof(triface), NULL, 256);
26047   newtetlist = new list(sizeof(triface), NULL, 256);
26048   newshlist = new list(sizeof(face), NULL, 256);
26049   // Allocate work lists if user doesn't supply them.
26050   myfrontlist = mymisfrontlist = myptlist = (list *) NULL;
26051   myflipque = (queue *) NULL;
26052   if (frontlist == (list *) NULL) {
26053     myfrontlist = new list(sizeof(triface), NULL, 256);
26054     frontlist = myfrontlist;
26055     mymisfrontlist = new list(sizeof(triface), NULL, 256);
26056     misfrontlist = mymisfrontlist;
26057     myptlist = new list(sizeof(point *), NULL, 256);
26058     ptlist = myptlist;
26059     myflipque = new queue(sizeof(badface));
26060     flipque = myflipque;
26061   }
26062 
26063   suppt = org(*suptet);
26064   oldtet = *suptet;
26065   success = true; // Assume p can be suppressed.
26066 
26067   if (b->verbose > 1) {
26068     printf("    Remove point %d in mesh.\n", pointmark(suppt));
26069   }
26070 
26071   // Form old B(p) in oldtetlist.
26072   oldtetlist->append(&oldtet);
26073   formstarpolyhedron(suppt, oldtetlist, ptlist, false);
26074   // Infect the tets in old B(p) (they're going to be delete).
26075   for (j = 0; j < oldtetlist->len(); j++) {
26076     oldtet = * (triface *)(* oldtetlist)[j];
26077     infect(oldtet);
26078   }
26079   // Tetrahedralize old B(p).
26080   success = constrainedcavity(&oldtet, newshlist, oldtetlist, ptlist,
26081               frontlist, misfrontlist, newtetlist, flipque);
26082   if (!success) {
26083     // Unable to suppress p.
26084     deallocfaketets(frontlist);
26085     // Try to collapse an edge at p.
26086     conpt = (point) NULL;
26087     assert(newtetlist->len() == 0);
26088     if (findcollapseedge(suppt, &conpt, oldtetlist, ptlist)) {
26089       // Collapse the edge suppt->conpt. Re-use newtetlist.
26090       collapseedge(suppt, conpt, oldtetlist, newtetlist);
26091       // The oldtetlist contains newtetlist.
26092       if (optflag) {
26093         assert(newtetlist->len() == 0);
26094         for (j = 0; j < oldtetlist->len(); j++) {
26095           newtet = * (triface *)(* oldtetlist)[j];
26096           newtetlist->append(&newtet);
26097         }
26098       }
26099       oldtetlist->clear(); // Do not delete them.
26100       collapverts++;
26101       success = true;
26102     }
26103   }
26104   if (success) {
26105     // p has been removed! (Still in the pool).
26106     setpointtype(suppt, UNUSEDVERTEX);
26107     unuverts++;
26108     suprelverts++;
26109     // Delete old B(p).
26110     for (j = 0; j < oldtetlist->len(); j++) {
26111       oldtet = * (triface *)(* oldtetlist)[j];
26112       assert(!isdead(&oldtet));
26113       tetrahedrondealloc(oldtet.tet);
26114     }
26115     if (optflag) {
26116       // Check for new bad tets.
26117       for (j = 0; j < newtetlist->len(); j++) {
26118         newtet = * (triface *)(* newtetlist)[j];
26119         if (!isdead(&newtet)) checktet4opt(&newtet, true);
26120       }
26121     }
26122   } else {
26123     // p is not suppressed. Recover the original state.
26124     // Uninfect tets of old B(p).
26125     for (j = 0; j < oldtetlist->len(); j++) {
26126       oldtet = * (triface *)(* oldtetlist)[j];
26127       assert(infected(oldtet));
26128       uninfect(oldtet);
26129     }
26130   }
26131 
26132   // Clear work lists.
26133   ptlist->clear();
26134   frontlist->clear();
26135   misfrontlist->clear();
26136   flipque->clear();
26137   // Deallocate work lists.
26138   if (myfrontlist != (list *) NULL) {
26139     delete myfrontlist;
26140     delete mymisfrontlist;
26141     delete myptlist;
26142     delete myflipque;
26143   }
26144   delete oldtetlist;
26145   delete newtetlist;
26146   delete newshlist;
26147 
26148   return success;
26149 }
26150 
26152 //                                                                           //
26153 // smoothpoint()    Smooth a volume/segment point.                           //
26154 //                                                                           //
26155 // 'smthpt' (p) is inside the polyhedron (C) bounded by faces in 'starlist'. //
26156 // This routine moves p inside C until an object function is maximized.      //
26157 //                                                                           //
26158 // Default, the CCW edge ring of the faces on C points to p. If 'invtori' is //
26159 // TRUE, the orientation is inversed.                                        //
26160 //                                                                           //
26161 // If 'key' != NULL, it contains an object value to be improved. Current it  //
26162 // means the cosine of the largest dihedral angle. In such case, the point   //
26163 // is smoothed only if the final configuration improves the object value, it //
26164 // is returned by the 'key'.                                                 //
26165 //                                                                           //
26167 
26168 bool tetgenmesh::smoothpoint(point smthpt, point e1, point e2, list *starlist,
26169   bool invtori, REAL *key)
26170 {
26171   triface starttet;
26172   point pa, pb, pc;
26173   REAL fcent[3], startpt[3], nextpt[3], bestpt[3];
26174   REAL iniTmax, oldTmax, newTmax;
26175   REAL ori, aspT, aspTmax, imprate;
26176   REAL cosd, maxcosd;
26177   bool segflag, randflag; //, subflag;
26178   int numdirs;
26179   int iter, i, j;
26180 
26181   // Is p a segment vertex?
26182   segflag = (e1 != (point) NULL);
26183   // Decide the number of moving directions.
26184   numdirs = segflag ? 2 : starlist->len();
26185   randflag = numdirs > 10;
26186   if (randflag) {
26187     numdirs = 10; // Maximum 10 directions.
26188   }
26189 
26190   aspTmax = 0.0;
26191   // Calculate the initial object value (the largest aspect ratio).
26192   for (i = 0; i < starlist->len(); i++) {
26193     starttet = * (triface *)(* starlist)[i];
26194     adjustedgering(starttet, !invtori ? CCW : CW);
26195     pa = org(starttet);
26196     pb = dest(starttet);
26197     pc = apex(starttet);
26198     aspT = tetaspectratio(pa, pb, pc, smthpt);
26199     if (i == 0) {
26200       aspTmax = aspT;
26201     } else {
26202       aspTmax = aspT > aspTmax ? aspT : aspTmax;
26203     }
26204   }
26205   iniTmax = aspTmax;
26206 
26207   if (b->verbose > 1) {
26208     printf("    Smooth %s point %d (%g, %g, %g).\n", segflag ? "seg" : "vol",
26209            pointmark(smthpt), smthpt[0], smthpt[1], smthpt[2]);
26210     printf("    Initial max L/h = %g.\n", iniTmax);
26211   }
26212   for (i = 0; i < 3; i++) {
26213     bestpt[i] = startpt[i] = smthpt[i];
26214   }
26215 
26216   // Do iteration until the new aspTmax does not decrease.
26217   newTmax = iniTmax;
26218   iter = 0;
26219   while (true) {
26220     // Find the best next location.
26221     oldTmax = newTmax;
26222     for (i = 0; i < numdirs; i++) {
26223       // Calculate the moved point (saved in 'nextpt').
26224       if (!segflag) {
26225         if (randflag) {
26226           // Randomly pick a direction.
26227           j = (int) randomnation(starlist->len());
26228         } else {
26229           j = i;
26230         }
26231         starttet = * (triface *)(* starlist)[j];
26232         adjustedgering(starttet, !invtori ? CCW : CW);
26233         pa = org(starttet);
26234         pb = dest(starttet);
26235         pc = apex(starttet);
26236         for (j = 0; j < 3; j++) {
26237           fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0;
26238         }
26239       } else {
26240         for (j = 0; j < 3; j++) {
26241           fcent[j] = (i == 0 ? e1[j] : e2[j]);
26242         }
26243       }
26244       for (j = 0; j < 3; j++) {
26245         nextpt[j] = startpt[j] + 0.01 * (fcent[j] - startpt[j]);
26246       }
26247       // Get the largest object value for the new location.
26248       for (j = 0; j < starlist->len(); j++) {
26249         starttet = * (triface *)(* starlist)[j];
26250         adjustedgering(starttet, !invtori ? CCW : CW);
26251         pa = org(starttet);
26252         pb = dest(starttet);
26253         pc = apex(starttet);
26254         ori = orient3d(pa, pb, pc, nextpt);
26255         if (ori < 0.0) {
26256           aspT = tetaspectratio(pa, pb, pc, nextpt);
26257           if (j == 0) {
26258             aspTmax = aspT;
26259           } else {
26260             aspTmax = aspT > aspTmax ? aspT : aspTmax;
26261           }
26262         } else {
26263           // An invalid new tet. Discard this point.
26264           aspTmax = newTmax;
26265         } // if (ori < 0.0)
26266         // Stop looping when the object value is bigger than before.
26267         if (aspTmax >= newTmax) break;
26268       } // for (j = 0; j < starlist->len(); j++)
26269       if (aspTmax < newTmax) {
26270         // Save the improved object value and the location.
26271         newTmax = aspTmax;
26272         for (j = 0; j < 3; j++) bestpt[j] = nextpt[j];
26273       }
26274     } // for (i = 0; i < starlist->len(); i++)
26275     // Does the object value improved much?
26276     imprate = fabs(oldTmax - newTmax) / oldTmax;
26277     if (imprate < 1e-3) break;
26278     // Yes, move p to the new location and continue.
26279     for (j = 0; j < 3; j++) startpt[j] = bestpt[j];
26280     iter++;
26281   } // while (true)
26282 
26283   if (iter > 0) {
26284     // The point is moved.
26285     if (key) {
26286       // Check if the quality is improved by the smoothed point.
26287       maxcosd = 0.0; // = cos(90).
26288       for (j = 0; j < starlist->len(); j++) {
26289         starttet = * (triface *)(* starlist)[j];
26290         adjustedgering(starttet, !invtori ? CCW : CW);
26291         pa = org(starttet);
26292         pb = dest(starttet);
26293         pc = apex(starttet);
26294         tetalldihedral(pa, pb, pc, startpt, NULL, &cosd, NULL);
26295         if (cosd < *key) {
26296           // This quality will not be improved. Stop.
26297           iter = 0; break;
26298         } else {
26299           // Remeber the worst quality value (of the new configuration).
26300           maxcosd = maxcosd < cosd ? maxcosd : cosd;
26301         }
26302       }
26303       if (iter > 0) *key = maxcosd;
26304     }
26305   }
26306 
26307   if (iter > 0) {
26308     segflag ? smoothsegverts++ : smoothvolverts++;
26309     for (i = 0; i < 3; i++) smthpt[i] = startpt[i];
26310     if (b->verbose > 1) {
26311       printf("    Move to new location (%g, %g, %g).\n", smthpt[0], smthpt[1],
26312              smthpt[2]);
26313       printf("    Final max L/h = %g. (%d iterations)\n", newTmax, iter);
26314       if (key) {
26315         printf("    Max. dihed = %g (degree).\n", acos(*key) / PI * 180.0);
26316       }
26317     }
26318     return true;
26319   } else {
26320     if (b->verbose > 1) {
26321       printf("    Not smoothed.\n");
26322     }
26323     return false;
26324   }
26325 }
26326 
26328 //                                                                           //
26329 // removesteiners()    Delete or relocate Steiner points on facets.          //
26330 //                                                                           //
26332 
26333 void tetgenmesh::removesteiners(bool coarseflag)
26334 {
26335   list *frontlist, *misfrontlist;
26336   list *spinshlist, *newsegshlist;
26337   list *ptlist, *conlist;
26338   memorypool *viri;
26339   queue *flipque;
26340   triface checktet;
26341   face shloop;
26342   face segloop, nextseg;
26343   point pa, neipt;
26344   REAL len;
26345   bool remflag;
26346   int *worklist;
26347   int oldnum, rmstein;
26348   int i, j;
26349 
26350   if (!b->quiet) {
26351     if (!coarseflag) {
26352       printf("Removing Steiner points.\n");
26353     } else {
26354       printf("Coarsening mesh.\n");
26355     }
26356   }
26357 
26358   // Initialize work lists.
26359   frontlist = new list(sizeof(triface), NULL);
26360   misfrontlist = new list(sizeof(triface), NULL);
26361   spinshlist = new list(sizeof(face), NULL);
26362   newsegshlist = new list(sizeof(face), NULL);
26363   ptlist = new list(sizeof(point *), NULL);
26364   conlist = new list(sizeof(point *) * 2, NULL);
26365   flipque = new queue(sizeof(badface));
26366   viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
26367   oldnum = unuverts;
26368   relverts = suprelverts = collapverts = unsupverts;
26369   smoothvolverts = 0;
26370   expcavcount = 0;
26371 
26372   // Suppress Steiner points inside facets.
26373   do {
26374     rmstein = unuverts;
26375     subfaces->traversalinit();
26376     shloop.sh = shellfacetraverse(subfaces);
26377     while (shloop.sh != (shellface *) NULL) {
26378       remflag = false;
26379       // Is s contains a Steiner point?
26380       shloop.shver = 0;
26381       for (i = 0; i < 3; i++) {
26382         pa = sapex(shloop);
26383         if (pointtype(pa) == FREESUBVERTEX) {
26384           if (!coarseflag) {
26385             // Remove it if it is not an input point.
26386             j = pointmark(pa) - in->firstnumber;
26387             if (j >= in->numberofpoints) {
26388               if (b->nobisect == 1) {
26389                 // '-Y'. Remove p if s is a hull face.
26390                 stpivot(shloop, checktet);
26391                 if (checktet.tet != dummytet) {
26392                   sesymself(shloop);
26393                   stpivot(shloop, checktet);
26394                 }
26395                 remflag = (checktet.tet == dummytet);
26396               } else {
26397                 // '-YY'. Remove p whatever s is a hull face or not.
26398                 remflag = true;
26399               }
26400             }
26401           } else {
26402             // Check if this vertex can be coarsed.
26403             if (b->nobisect == 0) {
26404               // Is a background mesh available?
26405               if (b->metric) {
26406                 // assert(pa[pointmtrindex] > 0.0);
26407                 // Form the star of pa.
26408                 spinshlist->append(&shloop);
26409                 formstarpolygon(pa, spinshlist, ptlist);
26410                 len = 0.0;
26411                 for (j = 0; j < ptlist->len(); j++) {
26412                   neipt = * (point *)(* ptlist)[j];
26413                   len += distance(pa, neipt);
26414                 }
26415                 len /= ptlist->len();
26416                 // Carse it if the average edge length is small.
26417                 remflag = len < pa[pointmtrindex];
26418                 spinshlist->clear();
26419                 ptlist->clear();
26420               } else {
26421                 // Coarse it if (1) it is an input point and its pointmarker
26422                 //   is zero, or (2) it is a Steiner point.
26423                 remflag = true;
26424                 j = pointmark(pa) - in->firstnumber;
26425                 if (j < in->numberofpoints) {
26426                   remflag = (in->pointmarkerlist[j] == 0);
26427                 }
26428               } // if (b->metric)
26429             } // if (b->nobisect == 0)
26430           } // if (!coarseflag)
26431           if (remflag) break;
26432         } // if (pointtype(pa) == FREESUBVERTEX)
26433         senextself(shloop);
26434       } // for (i = 0; i < 3; i++)
26435       if (remflag) {
26436         suppressfacetpoint(&shloop, frontlist, misfrontlist, ptlist, conlist,
26437                            viri, flipque, coarseflag, false);
26438       }
26439       shloop.sh = shellfacetraverse(subfaces);
26440     }
26441     // Continue if any Steiner point has been removed.
26442   } while (unuverts > rmstein);
26443 
26444   if (coarseflag) {
26445     shellface **segsperverlist;
26446     int *idx2seglist;
26447     face seg1, seg2;
26448     point e1, e2;
26449     // Connecting collinear segments. Hence the segment vertices may be
26450     //   removed. In fact, this should be done by reconstructmesh().
26451     makesegmentmap(idx2seglist, segsperverlist);
26452     subsegs->traversalinit();
26453     segloop.sh = shellfacetraverse(subsegs);
26454     while (segloop.sh != (shellface *) NULL) {
26455       for (i = 0; i < 2; i++) {
26456         segloop.shver = i;
26457         senext(segloop, nextseg);
26458         spivotself(nextseg);
26459         if ((nextseg.sh == dummysh) || (nextseg.sh > segloop.sh)) {
26460           // No neighbor segment connection or haven't been processed yet.
26461           pa = sdest(segloop);
26462           j = pointmark(pa) - in->firstnumber;
26463           if (idx2seglist[j + 1] - idx2seglist[j] == 2) {
26464             // pa is shared by only two segments. Get the other one.
26465             nextseg.sh = segsperverlist[idx2seglist[j]];
26466             if (nextseg.sh == segloop.sh) {
26467               nextseg.sh = segsperverlist[idx2seglist[j] + 1];
26468             }
26469             nextseg.shver = 0;
26470             if (sorg(nextseg) != pa) sesymself(nextseg);
26471             // Check if the two segments are collinear.
26472             e1 = sorg(segloop);
26473             e2 = sdest(nextseg);
26474             if (iscollinear(e1, pa, e2, b->epsilon)) {
26475               // Connect the two segments together.
26476               if (b->verbose > 1) {
26477                 printf("  Glue two insegs (%d, %d) at %d.\n", pointmark(e1),
26478                        pointmark(e2), pointmark(pa));
26479               }
26480               senext(segloop, seg1);
26481               senext2(nextseg, seg2);
26482               sbond(seg1, seg2);
26483             }
26484           }
26485         } // if (nextseg.sh == dummysh)
26486       } // for (i = 0;
26487       segloop.sh = shellfacetraverse(subsegs);
26488     }
26489     delete [] segsperverlist;
26490     delete [] idx2seglist;
26491   }
26492 
26493   // Suppress Steiner points on segments.
26494   do {
26495     rmstein = unuverts;
26496     subsegs->traversalinit();
26497     segloop.sh = shellfacetraverse(subsegs);
26498     while (segloop.sh != (shellface *) NULL) {
26499       remflag = false;
26500       // for (i = 0; i < 2; i++) {
26501         // Don't check the poinytype of pa, it may be a Steiner point but
26502         //   has type NACUTEVERTEX due to splitting a type-3 segment.
26503         segloop.shver = 0; // segloop.shver = i;
26504         senext(segloop, nextseg);
26505         spivotself(nextseg);
26506         if (nextseg.sh != dummysh) {
26507           pa = sdest(segloop); // p is going to be checked for removal.
26508           nextseg.shver = 0;
26509           if (sorg(nextseg) != pa) sesymself(nextseg);
26510           assert(sorg(nextseg) == pa);
26511           if (!coarseflag) {
26512             // try to remove it if it is not an input point.
26513             j = pointmark(pa) - in->firstnumber;
26514             if (j >= in->numberofpoints) {
26515               if (b->nobisect == 1) {
26516                 // '-Y'. Remove p if it is on the hull.
26517                 sstpivot(&segloop, &checktet);
26518                 assert(checktet.tet != dummytet);
26519                 pa = apex(checktet);
26520                 do {
26521                   if (!fnextself(checktet)) {
26522                     // Meet a boundary face - p is on the hull.
26523                     remflag = true; break;
26524                   }
26525                 } while (pa != apex(checktet));
26526               } else {
26527                 // '-YY'. Remove p whatever it is on the hull or not.
26528                 remflag = true;
26529               }
26530             }
26531           } else {
26532             // Check if this vertex can be coarsed.
26533             if (b->nobisect == 0) {
26534               if (b->metric) {
26535                 // assert(pa[pointmtrindex] > 0.0);
26536                 len = 0.0;
26537                 neipt = sorg(segloop);
26538                 for (j = 0; j < 2; j++) {
26539                   len += distance(pa, neipt);
26540                   /*// Is neipt inside the sparse ball of pa?
26541                   if (len < pa[pointmtrindex]) {
26542                     // Yes, the local of pa is too dense, corse it.
26543                     remflag = true; break;
26544                   } */
26545                   neipt = sdest(nextseg);
26546                 }
26547                 len /= 2.0;
26548                 // Carse it if the average edge lengh is small.
26549                 remflag = len < pa[pointmtrindex];
26550               } else {
26551                 // Coarse it if (1) it is an input point and its pointmarker
26552                 //   is zero, or (2) it is a Steiner point.
26553                 remflag = true;
26554                 j = pointmark(pa) - in->firstnumber;
26555                 if (j < in->numberofpoints) {
26556                   remflag = (in->pointmarkerlist[j] == 0);
26557                 }
26558               } // if (b->metric)
26559             } // if (b->nobisect == 0)
26560           } // if (!coarseflag)
26561         } // if (nextseg.sh != dummysh)
26562         // if (remflag) break;
26563       // } // for (i = 0; i < 2; i++)
26564       if (remflag) {
26565         suppresssegpoint(&segloop, spinshlist, newsegshlist, frontlist,
26566           misfrontlist, ptlist, conlist, viri, flipque, coarseflag, false);
26567       }
26568       segloop.sh = shellfacetraverse(subsegs);
26569     }
26570     // Continue if any Steiner point has been removed.
26571   } while (unuverts > rmstein);
26572 
26573   if ((relverts > 0) || coarseflag) {
26574     worklist = new int[points->items + 1];
26575     // Suppress relocated points & coarse free mesh points.
26576     do {
26577       // Initialize the work list. Each entry of the list counts how many
26578       //   times the point has been processed.
26579       for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26580       rmstein = unuverts;
26581       tetrahedrons->traversalinit();
26582       checktet.tet = tetrahedrontraverse();
26583       while (checktet.tet != (tetrahedron *) NULL) {
26584         remflag = false;
26585         for (i = 0; i < 4; i++) {
26586           pa = (point) checktet.tet[4 + i];
26587           if (pointtype(pa) == FREEVOLVERTEX) {
26588             // NOTE. Chenge the number 3 will change the number n of removed
26589             //   Steiner points. In my test, n is larger when it is 1. 3
26590             //   reduces n in a reasonable way (see example, mech_part,
26591             //   thepart), 5 results a larger n than 3 does. While the best
26592             //   result is no limit of this number, but it makes the code
26593             //   extremely slow.
26594             if (worklist[pointmark(pa)] < 3) {
26595               worklist[pointmark(pa)]++;
26596               if (!coarseflag) {
26597                 // Remove p if it is a Steiner point.
26598                 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26599                   remflag = true;
26600                 }
26601               } else {
26602                 if (b->metric) {
26603                   // assert(pa[pointmtrindex] > 0.0);
26604                   // Form the star of pa.
26605                   frontlist->append(&checktet);
26606                   formstarpolyhedron(pa, frontlist, ptlist, true);
26607                   len = 0.0;
26608                   for (j = 0; j < ptlist->len(); j++) {
26609                     neipt = * (point *)(* ptlist)[j];
26610                     len += distance(pa, neipt);
26611                   }
26612                   len /= ptlist->len();
26613                   // Carse it if the average edge length is small.
26614                   remflag = len < pa[pointmtrindex];
26615                   frontlist->clear();
26616                   ptlist->clear();
26617                 } else {
26618                   // Coarse it if (1) it is an input point and its pointmarker
26619                   //   is zero, or (2) it is a Steiner point.
26620                   remflag = true;
26621                   j = pointmark(pa) - in->firstnumber;
26622                   if (j < in->numberofpoints) {
26623                     remflag = (in->pointmarkerlist[j] == 0);
26624                   }
26625                 } // if (b->metric)
26626               } // if (!coarseflag)
26627               if (remflag) break;
26628             } // if (worklist[pointmark(pa)] == 0)
26629           } // if (pointtype(pa) == FREEVOLVERTEX)
26630         } // for (i = 0; i < 4; i++)
26631         if (remflag) {
26632           findorg(&checktet, pa);
26633           assert(org(checktet) == pa);
26634           suppressvolpoint(&checktet, frontlist, misfrontlist, ptlist, flipque,
26635                            false);
26636         }
26637         checktet.tet = tetrahedrontraverse();
26638       }
26639       // Continue if any relocated point has been suppressed.
26640     } while (unuverts > rmstein);
26641 
26642 
26643     // Smooth the unsuppressed points if it is not coarse mesh.
26644     if (!coarseflag && (relverts > suprelverts)) {
26645       if (b->verbose) {
26646         printf("  Smoothing relocated points.\n");
26647       }
26648       for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26649       tetrahedrons->traversalinit();
26650       checktet.tet = tetrahedrontraverse();
26651       while (checktet.tet != (tetrahedron *) NULL) {
26652         for (i = 0; i < 4; i++) {
26653           pa = (point) checktet.tet[4 + i];
26654           if (pointtype(pa) == FREEVOLVERTEX) {
26655             if (worklist[pointmark(pa)] == 0) {
26656               worklist[pointmark(pa)] = 1;
26657               if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26658                 // Smooth pa.
26659                 findorg(&checktet, pa);
26660                 frontlist->append(&checktet);
26661                 formstarpolyhedron(pa, frontlist, NULL, false);
26662                 smoothpoint(pa, NULL, NULL, frontlist, false, NULL);
26663                 frontlist->clear();
26664               }
26665             } // if (worklist[pointmark(pa)] == 0)
26666           } // if (pointtype(pa) == FREEVOLVERTEX)
26667         } // for (i = 0; i < 4; i++)
26668         checktet.tet = tetrahedrontraverse();
26669       }
26670     }
26671     delete [] worklist;
26672   }
26673 
26674   if (b->verbose > 0) {
26675     if (!coarseflag) {
26676       printf("  %d points removed from boundary", unuverts - oldnum);
26677       if (expcavcount > 0) {
26678         printf(" (%d cavity corrections)", expcavcount);
26679       }
26680       printf("\n");
26681       if (relverts > 0) {
26682         printf("  %d points relocated (%d suppressed, %d collapsed).\n",
26683                relverts, suprelverts - collapverts, collapverts);
26684         if (smoothvolverts > 0) {
26685           printf("  %d points are smoothed.\n", smoothvolverts);
26686         }
26687       }
26688       if (unsupverts > 0) {
26689         printf("  !! %d points are unsuppressed.\n", unsupverts);
26690       }
26691     } else {
26692       printf("  %d points are removed.\n", unuverts - oldnum);
26693     }
26694   }
26695 
26696   // Delete work lists.
26697   delete frontlist;
26698   delete misfrontlist;
26699   delete spinshlist;
26700   delete newsegshlist;
26701   delete ptlist;
26702   delete conlist;
26703   delete flipque;
26704   delete viri;
26705 }
26706 
26707 //
26708 // End of boundary Steiner points removing routines
26709 //
26710 
26712 //                                                                           //
26713 // reconstructmesh()    Reconstruct a tetrahedral mesh from a list of        //
26714 //                      tetrahedra and possibly a list of boundary faces.    //
26715 //                                                                           //
26716 // The list of tetrahedra is stored in 'in->tetrahedronlist',  the list of   //
26717 // boundary faces is stored in 'in->trifacelist'.  The tetrahedral mesh is   //
26718 // reconstructed in memorypool 'tetrahedrons', its boundary faces (subfaces) //
26719 // are reconstructed in 'subfaces', its boundary edges (subsegments) are     //
26720 // reconstructed in 'subsegs'. If the -a switch is used, this procedure will //
26721 // also read a list of REALs from 'in->tetrahedronvolumelist' and set a      //
26722 // maximum volume constraint on each tetrahedron.                            //
26723 //                                                                           //
26724 // If the user has provided the boundary faces in 'in->trifacelist', they    //
26725 // will be inserted the mesh. Otherwise subfaces will be identified from the //
26726 // mesh.  All hull faces (including faces of the internal holes) will be     //
26727 // recognized as subfaces, internal faces between two tetrahedra which have  //
26728 // different attributes will also be recognized as subfaces.                 //
26729 //                                                                           //
26730 // Subsegments will be identified after subfaces are reconstructed. Edges at //
26731 // the intersections of non-coplanar subfaces are recognized as subsegments. //
26732 // Edges between two coplanar subfaces with different boundary markers are   //
26733 // also recognized as subsegments.                                           //
26734 //                                                                           //
26735 // The facet index of each subface will be set automatically after we have   //
26736 // recovered subfaces and subsegments.  That is, the set of subfaces, which  //
26737 // are coplanar and have the same boundary marker will be recognized as a    //
26738 // facet and has a unique index, stored as the facet marker in each subface  //
26739 // of the set, the real boundary marker of each subface will be found in     //
26740 // 'in->facetmarkerlist' by the index.  Facet index will be used in Delaunay //
26741 // refinement for detecting two incident facets.                             //
26742 //                                                                           //
26743 // Points which are not corners of tetrahedra will be inserted into the mesh.//
26744 // Return the number of faces on the hull after the reconstruction.          //
26745 //                                                                           //
26747 
26748 long tetgenmesh::reconstructmesh()
26749 {
26750   tetrahedron **tetsperverlist;
26751   shellface **facesperverlist;
26752   triface tetloop, neightet, neineightet, spintet;
26753   face subloop, neighsh, neineighsh, subseg;
26754   face sface1, sface2;
26755   point *idx2verlist;
26756   point torg, tdest, tapex, toppo;
26757   point norg, ndest, napex;
26758   list *neighshlist, *markerlist;
26759   REAL sign, attrib, volume;
26760   REAL da1, da2;
26761   bool bondflag, insertsegflag;
26762   int *idx2tetlist;
26763   int *idx2facelist;
26764   int *worklist;
26765   int facetidx, marker;
26766   int iorg, idest, iapex, ioppo;
26767   int inorg, indest, inapex;
26768   int index, i, j;
26769 
26770   if (!b->quiet) {
26771     printf("Reconstructing mesh.\n");
26772   }
26773 
26774   // Create a map from index to points.
26775   makeindex2pointmap(idx2verlist);
26776 
26777   // Create the tetrahedra.
26778   for (i = 0; i < in->numberoftetrahedra; i++) {
26779     // Create a new tetrahedron and set its four corners, make sure that
26780     //   four corners form a positive orientation.
26781     maketetrahedron(&tetloop);
26782     index = i * in->numberofcorners;
26783     // Although there may be 10 nodes, we only read the first 4.
26784     iorg = in->tetrahedronlist[index] - in->firstnumber;
26785     idest = in->tetrahedronlist[index + 1] - in->firstnumber;
26786     iapex = in->tetrahedronlist[index + 2] - in->firstnumber;
26787     ioppo = in->tetrahedronlist[index + 3] - in->firstnumber;
26788     torg = idx2verlist[iorg];
26789     tdest = idx2verlist[idest];
26790     tapex = idx2verlist[iapex];
26791     toppo = idx2verlist[ioppo];
26792     sign = orient3d(torg, tdest, tapex, toppo);
26793     if (sign > 0.0) {
26794       norg = torg; torg = tdest; tdest = norg;
26795     } else if (sign == 0.0) {
26796       if (!b->quiet) {
26797         printf("Warning:  Tet %d is degenerate.\n", i + in->firstnumber);
26798       }
26799     }
26800     setorg(tetloop, torg);
26801     setdest(tetloop, tdest);
26802     setapex(tetloop, tapex);
26803     setoppo(tetloop, toppo);
26804     // Temporarily set the vertices be type FREEVOLVERTEX, to indicate that
26805     //   they belong to the mesh.  These types may be changed later.
26806     setpointtype(torg, FREEVOLVERTEX);
26807     setpointtype(tdest, FREEVOLVERTEX);
26808     setpointtype(tapex, FREEVOLVERTEX);
26809     setpointtype(toppo, FREEVOLVERTEX);
26810     // Set element attributes if they exist.
26811     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
26812       index = i * in->numberoftetrahedronattributes;
26813       attrib = in->tetrahedronattributelist[index + j];
26814       setelemattribute(tetloop.tet, j, attrib);
26815     }
26816     // If -a switch is used (with no number follows) Set a volume
26817     //   constraint if it exists.
26818     if (b->varvolume) {
26819       if (in->tetrahedronvolumelist != (REAL *) NULL) {
26820         volume = in->tetrahedronvolumelist[i];
26821       } else {
26822         volume = -1.0;
26823       }
26824       setvolumebound(tetloop.tet, volume);
26825     }
26826   }
26827 
26828   // Set the connection between tetrahedra.
26829   hullsize = 0l;
26830   // Create a map from nodes to tetrahedra.
26831   maketetrahedronmap(idx2tetlist, tetsperverlist);
26832   // Initialize the worklist.
26833   worklist = new int[points->items];
26834   for (i = 0; i < points->items; i++) worklist[i] = 0;
26835 
26836   // Loop all tetrahedra, bond two tetrahedra if they share a common face.
26837   tetrahedrons->traversalinit();
26838   tetloop.tet = tetrahedrontraverse();
26839   while (tetloop.tet != (tetrahedron *) NULL) {
26840     // Loop the four sides of the tetrahedron.
26841     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26842       sym(tetloop, neightet);
26843       if (neightet.tet != dummytet) continue; // This side has finished.
26844       torg = org(tetloop);
26845       tdest = dest(tetloop);
26846       tapex = apex(tetloop);
26847       iorg = pointmark(torg) - in->firstnumber;
26848       idest = pointmark(tdest) - in->firstnumber;
26849       iapex = pointmark(tapex) - in->firstnumber;
26850       worklist[iorg] = 1;
26851       worklist[idest] = 1;
26852       worklist[iapex] = 1;
26853       bondflag = false;
26854       // Search its neighbor in the adjacent tets of torg.
26855       for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26856            j++) {
26857         if (tetsperverlist[j] == tetloop.tet) continue; // Skip myself.
26858         neightet.tet = tetsperverlist[j];
26859         for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26860           sym(neightet, neineightet);
26861           if (neineightet.tet == dummytet) {
26862             norg = org(neightet);
26863             ndest = dest(neightet);
26864             napex = apex(neightet);
26865             inorg = pointmark(norg) - in->firstnumber;
26866             indest = pointmark(ndest) - in->firstnumber;
26867             inapex = pointmark(napex) - in->firstnumber;
26868             if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26869               // Find! Bond them together and break the loop.
26870               bond(tetloop, neightet);
26871               bondflag = true;
26872               break;
26873             }
26874           }
26875         }
26876       }
26877       if (!bondflag) {
26878         hullsize++;  // It's a hull face.
26879         // Bond this side to outer space.
26880         dummytet[0] = encode(tetloop);
26881         if ((in->pointmarkerlist != (int *) NULL) && !b->coarse) {
26882           // Set its three corners's markers be boundary (hull) vertices.
26883           if (in->pointmarkerlist[iorg] == 0) {
26884             in->pointmarkerlist[iorg] = 1;
26885           }
26886           if (in->pointmarkerlist[idest] == 0) {
26887             in->pointmarkerlist[idest] = 1;
26888           }
26889           if (in->pointmarkerlist[iapex] == 0) {
26890             in->pointmarkerlist[iapex] = 1;
26891           }
26892         }
26893       }
26894       worklist[iorg] = 0;
26895       worklist[idest] = 0;
26896       worklist[iapex] = 0;
26897     }
26898     tetloop.tet = tetrahedrontraverse();
26899   }
26900 
26901   // Subfaces will be inserted into the mesh. It has two phases:
26902   //   (1) Insert subfaces provided by user (in->trifacelist);
26903   //   (2) Create subfaces for hull faces (if they're not subface yet) and
26904   //       interior faces which separate two different materials.
26905 
26906   // Phase (1). Is there a list of user-provided subfaces?
26907   if (in->trifacelist != (int *) NULL) {
26908     // Recover subfaces from 'in->trifacelist'.
26909     for (i = 0; i < in->numberoftrifaces; i++) {
26910       index = i * 3;
26911       iorg = in->trifacelist[index] - in->firstnumber;
26912       idest = in->trifacelist[index + 1] - in->firstnumber;
26913       iapex = in->trifacelist[index + 2] - in->firstnumber;
26914       // Look for the location of this subface.
26915       worklist[iorg] = 1;
26916       worklist[idest] = 1;
26917       worklist[iapex] = 1;
26918       bondflag = false;
26919       // Search its neighbor in the adjacent tets of torg.
26920       for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26921            j++) {
26922         neightet.tet = tetsperverlist[j];
26923         for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26924           norg = org(neightet);
26925           ndest = dest(neightet);
26926           napex = apex(neightet);
26927           inorg = pointmark(norg) - in->firstnumber;
26928           indest = pointmark(ndest) - in->firstnumber;
26929           inapex = pointmark(napex) - in->firstnumber;
26930           if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26931             bondflag = true;  // Find!
26932             break;
26933           }
26934         }
26935       }
26936       if (bondflag) {
26937         // Create a new subface and insert it into the mesh.
26938         makeshellface(subfaces, &subloop);
26939         torg = idx2verlist[iorg];
26940         tdest = idx2verlist[idest];
26941         tapex = idx2verlist[iapex];
26942         setsorg(subloop, torg);
26943         setsdest(subloop, tdest);
26944         setsapex(subloop, tapex);
26945         // Set the vertices be FREESUBVERTEX to indicate they belong to a
26946         //   facet of the domain.  They may be changed later.
26947         setpointtype(torg, FREESUBVERTEX);
26948         setpointtype(tdest, FREESUBVERTEX);
26949         setpointtype(tapex, FREESUBVERTEX);
26950         if (in->trifacemarkerlist != (int *) NULL) {
26951           setshellmark(subloop, in->trifacemarkerlist[i]);
26952         }
26953         adjustedgering(neightet, CCW);
26954         findedge(&subloop, org(neightet), dest(neightet));
26955         tsbond(neightet, subloop);
26956         sym(neightet, neineightet);
26957         if (neineightet.tet != dummytet) {
26958           sesymself(subloop);
26959           tsbond(neineightet, subloop);
26960         }
26961       } else {
26962         if (!b->quiet) {
26963           printf("Warning:  Subface %d is discarded.\n", i + in->firstnumber);
26964         }
26965       }
26966       worklist[iorg] = 0;
26967       worklist[idest] = 0;
26968       worklist[iapex] = 0;
26969     }
26970   }
26971 
26972   // Phase (2). Indentify subfaces from the mesh.
26973   tetrahedrons->traversalinit();
26974   tetloop.tet = tetrahedrontraverse();
26975   while (tetloop.tet != (tetrahedron *) NULL) {
26976     // Loop the four sides of the tetrahedron.
26977     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26978       tspivot(tetloop, subloop);
26979       if (subloop.sh != dummysh) continue;
26980       bondflag = false;
26981       sym(tetloop, neightet);
26982       if (neightet.tet == dummytet) {
26983         // It's a hull face. Insert a subface at here.
26984         bondflag = true;
26985       } else {
26986         // It's an interior face. Insert a subface if two tetrahedra have
26987         //   different attributes (i.e., they belong to two regions).
26988         if (in->numberoftetrahedronattributes > 0) {
26989           if (elemattribute(neightet.tet,
26990               in->numberoftetrahedronattributes - 1) !=
26991               elemattribute(tetloop.tet,
26992               in->numberoftetrahedronattributes - 1)) {
26993             bondflag = true;
26994           }
26995         }
26996       }
26997       if (bondflag) {
26998         adjustedgering(tetloop, CCW);
26999         makeshellface(subfaces, &subloop);
27000         torg = org(tetloop);
27001         tdest = dest(tetloop);
27002         tapex = apex(tetloop);
27003         setsorg(subloop, torg);
27004         setsdest(subloop, tdest);
27005         setsapex(subloop, tapex);
27006         // Set the vertices be FREESUBVERTEX to indicate they belong to a
27007         //   facet of the domain.  They may be changed later.
27008         setpointtype(torg, FREESUBVERTEX);
27009         setpointtype(tdest, FREESUBVERTEX);
27010         setpointtype(tapex, FREESUBVERTEX);
27011         tsbond(tetloop, subloop);
27012         if (neightet.tet != dummytet) {
27013           sesymself(subloop);
27014           tsbond(neightet, subloop);
27015         }
27016       }
27017     }
27018     tetloop.tet = tetrahedrontraverse();
27019   }
27020 
27021   // Set the connection between subfaces. A subsegment may have more than
27022   //   two subfaces sharing it, 'neighshlist' stores all subfaces sharing
27023   //   one edge.
27024   neighshlist = new list(sizeof(face), NULL);
27025   // Create a map from nodes to subfaces.
27026   makesubfacemap(idx2facelist, facesperverlist);
27027 
27028   // Loop over the set of subfaces, setup the connection between subfaces.
27029   subfaces->traversalinit();
27030   subloop.sh = shellfacetraverse(subfaces);
27031   while (subloop.sh != (shellface *) NULL) {
27032     for (i = 0; i < 3; i++) {
27033       spivot(subloop, neighsh);
27034       if (neighsh.sh == dummysh) {
27035         // This side is 'empty', operate on it.
27036         torg = sorg(subloop);
27037         tdest = sdest(subloop);
27038         tapex = sapex(subloop);
27039         neighshlist->append(&subloop);
27040         iorg = pointmark(torg) - in->firstnumber;
27041         // Search its neighbor in the adjacent list of torg.
27042         for (j = idx2facelist[iorg]; j < idx2facelist[iorg + 1]; j++) {
27043           neighsh.sh = facesperverlist[j];
27044           if (neighsh.sh == subloop.sh) continue;
27045           neighsh.shver = 0;
27046           if (isfacehasedge(&neighsh, torg, tdest)) {
27047             findedge(&neighsh, torg, tdest);
27048             // Insert 'neighsh' into 'neighshlist'.
27049             if (neighshlist->len() < 2) {
27050               neighshlist->append(&neighsh);
27051             } else {
27052               for (index = 0; index < neighshlist->len() - 1; index++) {
27053                 sface1 = * (face *)(* neighshlist)[index];
27054                 sface2 = * (face *)(* neighshlist)[index + 1];
27055                 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(neighsh));
27056                 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
27057                 if (da1 < da2) {
27058                   break;  // Insert it after index.
27059                 }
27060               }
27061               neighshlist->insert(index + 1, &neighsh);
27062             }
27063           }
27064         }
27065         // Bond the subfaces in 'neighshlist'.
27066         if (neighshlist->len() > 1) {
27067           neighsh = * (face *)(* neighshlist)[0];
27068           for (j = 1; j <= neighshlist->len(); j++) {
27069             if (j < neighshlist->len()) {
27070               neineighsh = * (face *)(* neighshlist)[j];
27071             } else {
27072               neineighsh = * (face *)(* neighshlist)[0];
27073             }
27074             sbond1(neighsh, neineighsh);
27075             neighsh = neineighsh;
27076           }
27077         } else {
27078           // No neighbor subface be found, bond 'subloop' to itself.
27079           sbond(subloop, subloop);
27080         }
27081         neighshlist->clear();
27082       }
27083       senextself(subloop);
27084     }
27085     subloop.sh = shellfacetraverse(subfaces);
27086   }
27087 
27088   // Segments will be introudced. Each segment has a unique marker (1-based).
27089   marker = 1;
27090   subfaces->traversalinit();
27091   subloop.sh = shellfacetraverse(subfaces);
27092   while (subloop.sh != (shellface *) NULL) {
27093     for (i = 0; i < 3; i++) {
27094       sspivot(subloop, subseg);
27095       if (subseg.sh == dummysh) {
27096         // This side has no subsegment bonded, check it.
27097         torg = sorg(subloop);
27098         tdest = sdest(subloop);
27099         tapex = sapex(subloop);
27100         spivot(subloop, neighsh);
27101         spivot(neighsh, neineighsh);
27102         insertsegflag = false;
27103         if (subloop.sh == neighsh.sh || subloop.sh != neineighsh.sh) {
27104           // This side is either self-bonded or more than two subfaces,
27105           //   insert a subsegment at this side.
27106           insertsegflag = true;
27107         } else {
27108           // Only two subfaces case.
27109 #ifdef SELF_CHECK
27110           assert(subloop.sh != neighsh.sh);
27111 #endif
27112           napex = sapex(neighsh);
27113           sign = orient3d(torg, tdest, tapex, napex);
27114           if (iscoplanar(torg, tdest, tapex, napex, sign, b->epsilon)) {
27115             // Although they are coplanar, we still need to check if they
27116             //   have the same boundary marker.
27117             insertsegflag = (shellmark(subloop) != shellmark(neighsh));
27118           } else {
27119             // Non-coplanar.
27120             insertsegflag = true;
27121           }
27122         }
27123         if (insertsegflag) {
27124           // Create a subsegment at this side.
27125           makeshellface(subsegs, &subseg);
27126           setsorg(subseg, torg);
27127           setsdest(subseg, tdest);
27128           // The two vertices have been marked as FREESUBVERTEX. Now mark
27129           //   them as NACUTEVERTEX.
27130           setpointtype(torg, NACUTEVERTEX);
27131           setpointtype(tdest, NACUTEVERTEX);
27132           setshellmark(subseg, marker);
27133           marker++;
27134           // Bond all subfaces to this subsegment.
27135           neighsh = subloop;
27136           do {
27137             ssbond(neighsh, subseg);
27138             spivotself(neighsh);
27139           } while (neighsh.sh != subloop.sh);
27140         }
27141       }
27142       senextself(subloop);
27143     }
27144     subloop.sh = shellfacetraverse(subfaces);
27145   }
27146   // Remember the number of input segments.
27147   insegments = subsegs->items;
27148   // Find the acute vertices and set them be type ACUTEVERTEX.
27149 
27150   // Indentify facets and set the facet marker (1-based) for subfaces.
27151   markerlist = new list((char*)"int");
27152 
27153   subfaces->traversalinit();
27154   subloop.sh = shellfacetraverse(subfaces);
27155   while (subloop.sh != (shellface *) NULL) {
27156     // Only operate on uninfected subface, after operating, infect it.
27157     if (!sinfected(subloop)) {
27158       // A new facet is found.
27159       marker = shellmark(subloop);
27160       markerlist->append(&marker);
27161       facetidx = markerlist->len(); // 'facetidx' starts from 1.
27162       setshellmark(subloop, facetidx);
27163       sinfect(subloop);
27164       neighshlist->append(&subloop);
27165       // Find out all subfaces of this facet (bounded by subsegments).
27166       for (i = 0; i < neighshlist->len(); i++) {
27167         neighsh = * (face *) (* neighshlist)[i];
27168         for (j = 0; j < 3; j++) {
27169           sspivot(neighsh, subseg);
27170           if (subseg.sh == dummysh) {
27171             spivot(neighsh, neineighsh);
27172             if (!sinfected(neineighsh)) {
27173               // 'neineighsh' is in the same facet as 'subloop'.
27174 #ifdef SELF_CHECK
27175               assert(shellmark(neineighsh) == marker);
27176 #endif
27177               setshellmark(neineighsh, facetidx);
27178               sinfect(neineighsh);
27179               neighshlist->append(&neineighsh);
27180             }
27181           }
27182           senextself(neighsh);
27183         }
27184       }
27185       neighshlist->clear();
27186     }
27187     subloop.sh = shellfacetraverse(subfaces);
27188   }
27189   // Uninfect all subfaces.
27190   subfaces->traversalinit();
27191   subloop.sh = shellfacetraverse(subfaces);
27192   while (subloop.sh != (shellface *) NULL) {
27193 #ifdef SELF_CHECK
27194     assert(sinfected(subloop));
27195 #endif
27196     suninfect(subloop);
27197     subloop.sh = shellfacetraverse(subfaces);
27198   }
27199   // Save the facet markers in 'in->facetmarkerlist'.
27200   in->numberoffacets = markerlist->len();
27201   in->facetmarkerlist = new int[in->numberoffacets];
27202   for (i = 0; i < in->numberoffacets; i++) {
27203     marker = * (int *) (* markerlist)[i];
27204     in->facetmarkerlist[i] = marker;
27205   }
27206   // Initialize the 'facetabovepointlist'.
27207   facetabovepointarray = new point[in->numberoffacets + 1];
27208   for (i = 0; i < in->numberoffacets + 1; i++) {
27209     facetabovepointarray[i] = (point) NULL;
27210   }
27211 
27212   // The mesh contains boundary now.
27213   checksubfaces = 1;
27214   // The mesh is nonconvex now.
27215   nonconvex = 1;
27216 
27217   // Is there periodic boundary confitions?
27218   if (checkpbcs) {
27219     tetgenio::pbcgroup *pg;
27220     pbcdata *pd;
27221     // Initialize the global array 'subpbcgrouptable'.
27222     createsubpbcgrouptable();
27223     // Loop for each pbcgroup i.
27224     for (i = 0; i < in->numberofpbcgroups; i++) {
27225       pg = &(in->pbcgrouplist[i]);
27226       pd = &(subpbcgrouptable[i]);
27227       // Find all subfaces of pd, set each subface's group id be i.
27228       for (j = 0; j < 2; j++) {
27229         subfaces->traversalinit();
27230         subloop.sh = shellfacetraverse(subfaces);
27231         while (subloop.sh != (shellface *) NULL) {
27232           facetidx = shellmark(subloop);
27233           marker = in->facetmarkerlist[facetidx - 1];
27234           if (marker == pd->fmark[j]) {
27235             setshellpbcgroup(subloop, i);
27236             pd->ss[j] = subloop;
27237           }
27238           subloop.sh = shellfacetraverse(subfaces);
27239         }
27240       }
27241       if (pg->pointpairlist != (int *) NULL) {
27242         // Set the connections between pbc point pairs.
27243         for (j = 0; j < pg->numberofpointpairs; j++) {
27244           iorg = pg->pointpairlist[j * 2] - in->firstnumber;
27245           idest = pg->pointpairlist[j * 2 + 1] - in->firstnumber;
27246           torg = idx2verlist[iorg];
27247           tdest = idx2verlist[idest];
27248           setpoint2pbcpt(torg, tdest);
27249           setpoint2pbcpt(tdest, torg);
27250         }
27251       }
27252     }
27253     // Create the global array 'segpbcgrouptable'.
27254     createsegpbcgrouptable();
27255   }
27256 
27257   delete markerlist;
27258   delete neighshlist;
27259   delete [] worklist;
27260   delete [] idx2tetlist;
27261   delete [] tetsperverlist;
27262   delete [] idx2facelist;
27263   delete [] facesperverlist;
27264   delete [] idx2verlist;
27265 
27266   return hullsize;
27267 }
27268 
27270 //                                                                           //
27271 // insertconstrainedpoints()    Insert a list of constrained points.         //
27272 //                                                                           //
27274 
27275 void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
27276 {
27277   queue *flipqueue;
27278   triface searchtet;
27279   face checksh, checkseg;
27280   point newpoint;
27281   enum locateresult loc;
27282   REAL *attr;
27283   bool insertflag;
27284   int covertices, outvertices;
27285   int index;
27286   int i, j;
27287 
27288   if (!b->quiet) {
27289     printf("Insert additional points into mesh.\n");
27290   }
27291   // Initialize 'flipqueue'.
27292   flipqueue = new queue(sizeof(badface));
27293   recenttet.tet = dummytet;
27294   covertices = outvertices = 0;
27295 
27296   index = 0;
27297   for (i = 0; i < addio->numberofpoints; i++) {
27298     // Create a newpoint.
27299     makepoint(&newpoint);
27300     newpoint[0] = addio->pointlist[index++];
27301     newpoint[1] = addio->pointlist[index++];
27302     newpoint[2] = addio->pointlist[index++];
27303     // Read the add point attributes if current points have attributes.
27304     if ((addio->numberofpointattributes > 0) &&
27305         (in->numberofpointattributes > 0)) {
27306       attr = addio->pointattributelist + addio->numberofpointattributes * i;
27307       for (j = 0; j < in->numberofpointattributes; j++) {
27308         if (j < addio->numberofpointattributes) {
27309           newpoint[3 + j] = attr[j];
27310         }
27311       }
27312     }
27313     // Find the location of the inserted point.
27314     searchtet = recenttet;
27315     loc = locate(newpoint, &searchtet);
27316     if (loc != ONVERTEX) {
27317       loc = adjustlocate(newpoint, &searchtet, loc, b->epsilon2);
27318     }
27319     if (loc == OUTSIDE) {
27320       loc = hullwalk(newpoint, &searchtet);
27321       if (loc == OUTSIDE) {
27322         // Perform a brute-force search.
27323         tetrahedrons->traversalinit();
27324         searchtet.tet = tetrahedrontraverse();
27325         while (searchtet.tet != (tetrahedron *) NULL) {
27326           loc = adjustlocate(newpoint, &searchtet, OUTSIDE, b->epsilon2);
27327           if (loc != OUTSIDE) break;
27328           searchtet.tet = tetrahedrontraverse();
27329         }
27330       }
27331     }
27332     // Insert the point if it not lies outside or on a vertex.
27333     insertflag = true;
27334     switch (loc) {
27335     case INTETRAHEDRON:
27336       setpointtype(newpoint, FREEVOLVERTEX);
27337       splittetrahedron(newpoint, &searchtet, flipqueue);
27338       break;
27339     case ONFACE:
27340       tspivot(searchtet, checksh);
27341       if (checksh.sh != dummysh) {
27342         // It is a boundary face. Don't insert it if -Y option is used.
27343         if (b->nobisect) {
27344           insertflag = false;
27345         } else {
27346           setpointtype(newpoint, FREESUBVERTEX);
27347         }
27348       } else {
27349         setpointtype(newpoint, FREEVOLVERTEX);
27350       }
27351       if (insertflag) {
27352         splittetface(newpoint, &searchtet, flipqueue);
27353       }
27354       break;
27355     case ONEDGE:
27356       tsspivot(&searchtet, &checkseg);
27357       if (checkseg.sh != dummysh) {
27358         if (b->nobisect) {
27359           insertflag = false;
27360         } else {
27361           setpointtype(newpoint, FREESEGVERTEX);
27362           setpoint2sh(newpoint, sencode(checkseg));
27363         }
27364       } else {
27365         tspivot(searchtet, checksh);
27366         if (checksh.sh != dummysh) {
27367           if (b->nobisect) {
27368             insertflag = false;
27369           } else {
27370             setpointtype(newpoint, FREESUBVERTEX);
27371           }
27372         } else {
27373           setpointtype(newpoint, FREEVOLVERTEX);
27374         }
27375       }
27376       if (insertflag) {
27377         splittetedge(newpoint, &searchtet, flipqueue);
27378       }
27379       break;
27380     case ONVERTEX:
27381       insertflag = false;
27382       covertices++;
27383       break;
27384     case OUTSIDE:
27385       insertflag = false;
27386       outvertices++;
27387       break;
27388     }
27389     // Remember the tetrahedron for next point searching.
27390     recenttet = searchtet;
27391     if (!insertflag) {
27392       pointdealloc(newpoint);
27393     } else {
27394       flip(flipqueue, NULL);
27395     }
27396   }
27397 
27398   if (b->verbose) {
27399     if (covertices > 0) {
27400       printf("  %d constrained points already exist.\n", covertices);
27401     }
27402     if (outvertices > 0) {
27403       printf("  %d constrained points lie outside the mesh.\n", outvertices);
27404     }
27405     printf("  %d constrained points have been inserted.\n",
27406            addio->numberofpoints - covertices - outvertices);
27407   }
27408 
27409   delete flipqueue;
27410 }
27411 
27413 //                                                                           //
27414 // p1interpolatebgm()    Set pt size by p^1 interpolation in background mesh.//
27415 //                                                                           //
27416 // On input, 'bgmtet' is a suggesting tet in background mesh for searching   //
27417 // 'pt'. It returns the tet containing 'pt'.                                 //
27418 //                                                                           //
27420 
27421 bool tetgenmesh::p1interpolatebgm(point pt, triface* bgmtet, long *scount)
27422 {
27423   point bgmpt[4];
27424   enum locateresult loc;
27425   REAL vol, volpt[4], weights[4];
27426   int i;
27427 
27428   loc = bgm->preciselocate(pt, bgmtet, bgm->tetrahedrons->items);
27429   if (loc == OUTSIDE) {
27430     loc = bgm->hullwalk(pt, bgmtet);
27431     if (loc == OUTSIDE) {
27432       // Perform a brute-force search.
27433       if (b->verbose) {
27434         printf("Warning:  Global point location.\n");
27435       }
27436       if (scount) (*scount)++;
27437       bgm->tetrahedrons->traversalinit(); // in bgm
27438       bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
27439       while (bgmtet->tet != (tetrahedron *) NULL) {
27440         loc = bgm->adjustlocate(pt, bgmtet, OUTSIDE, b->epsilon);
27441         if (loc != OUTSIDE) break;
27442         bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
27443       }
27444     }
27445   }
27446   if (loc != OUTSIDE) {
27447     // Let p remember t.
27448     setpoint2bgmtet(pt, encode(*bgmtet)); // in m
27449     // get the corners of t.
27450     for (i = 0; i < 4; i++) bgmpt[i] = (point) bgmtet->tet[4 + i];
27451     // Calculate the weighted coordinates of p in t.
27452     vol = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], bgmpt[3]);
27453     volpt[0] = orient3d(pt, bgmpt[1], bgmpt[2], bgmpt[3]);
27454     volpt[1] = orient3d(bgmpt[0], pt, bgmpt[2], bgmpt[3]);
27455     volpt[2] = orient3d(bgmpt[0], bgmpt[1], pt, bgmpt[3]);
27456     volpt[3] = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], pt);
27457     for (i = 0; i < 4; i++) weights[i] = fabs(volpt[i] / vol);
27458     // Interpolate the solution for p.
27459     for (i = 0; i < bgm->in->numberofpointmtrs; i++) {
27460       pt[pointmtrindex + i] = weights[0] * bgmpt[0][bgm->pointmtrindex + i]
27461                             + weights[1] * bgmpt[1][bgm->pointmtrindex + i]
27462                             + weights[2] * bgmpt[2][bgm->pointmtrindex + i]
27463                             + weights[3] * bgmpt[3][bgm->pointmtrindex + i];
27464     }
27465   } else {
27466     setpoint2bgmtet(pt, (tetrahedron) NULL);  // in m
27467   }
27468   return loc != OUTSIDE;
27469 }
27470 
27472 //                                                                           //
27473 // interpolatesizemap()    Interpolate the point sizes in the given size map.//
27474 //                                                                           //
27475 // The size map is specified on each node of the background mesh. The points //
27476 // of current mesh get their sizes by interpolating.                         //
27477 //                                                                           //
27478 // This function operation on two meshes simultaneously, the current mesh m, //
27479 // and the background mesh bgm. After this function, each point p in m will  //
27480 // have a pointer to a tet of bgm.                                           //
27481 //                                                                           //
27483 
27484 void tetgenmesh::interpolatesizemap()
27485 {
27486   list *adjtetlist;
27487   triface tetloop, neightet, bgmtet;
27488   point searchpt;
27489   long scount;
27490   int *worklist;
27491   int sepcount;
27492   int i;
27493 
27494   if (b->verbose) {
27495     printf("  Interpolating size map.\n");
27496   }
27497 
27498   worklist = new int[points->items + 1];
27499   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
27500   sepcount = 0;
27501   scount = 0l;
27502 
27503   tetrahedrons->traversalinit();
27504   tetloop.tet = tetrahedrontraverse();
27505   while (tetloop.tet != (tetrahedron *) NULL) {
27506     if (!infected(tetloop)) {
27507       // Find a new subdomain.
27508       adjtetlist = new list(sizeof(triface), NULL, 1024);
27509       infect(tetloop);
27510       // Search the four corners in background mesh.
27511       for (i = 0; i < 4; i++) {
27512         searchpt = (point) tetloop.tet[4 + i];
27513         // Mark the point for avoiding multiple searchings.
27514         // assert(worklist[pointmark(searchpt)] == 0);
27515         worklist[pointmark(searchpt)] = 1;
27516         // Does it contain a pointer to bgm tet?
27517         bgm->decode(point2bgmtet(searchpt), bgmtet);
27518         if (bgm->isdead(&bgmtet)) {
27519           bgmtet = bgm->recenttet;
27520         }
27521         if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27522           bgm->recenttet = bgmtet;
27523         }
27524       } // for (i = 0; i < 4; i++)
27525       // Collect all tets in this region.
27526       adjtetlist->append(&tetloop);
27527       // Collect the tets in the subdomain.
27528       for (i = 0; i < adjtetlist->len(); i++) {
27529         tetloop = * (triface *)(* adjtetlist)[i];
27530         for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27531           sym(tetloop, neightet);
27532           if ((neightet.tet != dummytet) && !infected(neightet)) {
27533             // Only need to search for the opposite point.
27534             searchpt = oppo(neightet);
27535             if (worklist[pointmark(searchpt)] == 0) {
27536               worklist[pointmark(searchpt)] = 1;
27537               decode(point2bgmtet(searchpt), bgmtet);
27538               if (bgm->isdead(&bgmtet)) {
27539                 bgmtet = bgm->recenttet;
27540               }
27541               if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27542                 bgm->recenttet = bgmtet;
27543               }
27544             }
27545             infect(neightet);
27546             adjtetlist->append(&neightet);
27547           }
27548         }
27549       }
27550       // Increase the number of separated domains.
27551       sepcount++;
27552       delete adjtetlist;
27553     } // if (!infect())
27554     tetloop.tet = tetrahedrontraverse();
27555   }
27556 
27557   // Unmark all tets.
27558   tetrahedrons->traversalinit();
27559   tetloop.tet = tetrahedrontraverse();
27560   while (tetloop.tet != (tetrahedron *) NULL) {
27561     assert(infected(tetloop));
27562     uninfect(tetloop);
27563     tetloop.tet = tetrahedrontraverse();
27564   }
27565   delete [] worklist;
27566 
27567 #ifdef SELF_CHECK
27568   if (b->verbose && scount > 0l) {
27569     printf("  %ld brute-force searches.\n", scount);
27570   }
27571   if (b->verbose && sepcount > 0) {
27572     printf("  %d separate domains.\n", sepcount);
27573   }
27574 #endif
27575 }
27576 
27578 //                                                                           //
27579 // duplicatebgmesh()    Duplicate current mesh to background mesh.           //
27580 //                                                                           //
27581 // Current mesh 'this' is copied into 'this->bgm'.Both meshes share the same //
27582 // input tetgenio object, 'this->in', same tetgenbehavior object 'this->b'.  //
27583 //                                                                           //
27585 
27586 void tetgenmesh::duplicatebgmesh()
27587 {
27588   triface tetloop, btetloop;
27589   triface symtet, bsymtet;
27590   face bhullsh, bneighsh;
27591   point *idx2bplist, *tetptbaklist;
27592   point ploop, bploop;
27593   int idx, i;
27594 
27595   if (!b->quiet) {
27596     printf("Duplicating background mesh.\n");
27597   }
27598 
27599   // The background mesh itself has no background mesh.
27600   // assert(bgm->bgm == (tetgenmesh *) NULL);
27601   // The space for metric tensor should be allocated.
27602   // assert(bgm->sizeoftensor > 0);
27603 
27604   // Copy point list.
27605   idx2bplist = new point[points->items + 1];
27606   idx = in->firstnumber;
27607   points->traversalinit();
27608   ploop = pointtraverse();
27609   while (ploop != (point) NULL) {
27610     bgm->makepoint(&bploop);
27611     // Copy coordinates, attributes.
27612     for (i = 0; i < 3 + in->numberofpointattributes; i++) {
27613       bploop[i] = ploop[i];
27614     }
27615     // Transfer the metric tensor.
27616     for (i = 0; i < bgm->sizeoftensor; i++) {
27617       bploop[bgm->pointmtrindex + i] = ploop[pointmtrindex + i];
27618       // Metric tensor should have a positive value.
27619       if (bploop[bgm->pointmtrindex + i] <= 0.0) {
27620         printf("Error:  Point %d has non-positive size %g (-m option).\n",
27621                bgm->pointmark(bploop), bploop[bgm->pointmtrindex + i]);
27622         terminatetetgen(1);
27623       }
27624     }
27625     // Remember the point for searching.
27626     idx2bplist[idx++] = bploop;
27627     ploop = pointtraverse();
27628   }
27629 
27630   // Copy tetrahedra list.
27631   tetptbaklist = new point[tetrahedrons->items + 1];
27632   idx = in->firstnumber;
27633   tetrahedrons->traversalinit();
27634   tetloop.tet = tetrahedrontraverse();
27635   while (tetloop.tet != (tetrahedron *) NULL) {
27636     bgm->maketetrahedron(&btetloop);
27637     // Set the four corners.
27638     for (i = 0; i < 4; i++) {
27639       ploop = (point) tetloop.tet[4 + i];
27640       bploop = idx2bplist[pointmark(ploop)];
27641       btetloop.tet[4 + i] = (tetrahedron) bploop;
27642     }
27643     // Remember the tet for setting neighbor connections.
27644     tetptbaklist[idx++] = (point) tetloop.tet[4];
27645     tetloop.tet[4] = (tetrahedron) btetloop.tet;
27646     tetloop.tet = tetrahedrontraverse();
27647   }
27648 
27649   // Set the connections between background tetrahedra. Create background
27650   //   hull subfaces. Create the map of point-to-bgmtet.
27651   idx = in->firstnumber;
27652   tetrahedrons->traversalinit();
27653   tetloop.tet = tetrahedrontraverse();
27654   while (tetloop.tet != (tetrahedron *) NULL) {
27655     // Get the corresponding background tet.
27656     btetloop.tet = (tetrahedron *) tetloop.tet[4];
27657     // Set the four neighbors.
27658     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27659       btetloop.loc = tetloop.loc;
27660       sym(tetloop, symtet);
27661       if ((symtet.tet != dummytet) && (symtet.tet > tetloop.tet)) {
27662         // Operate on the un-connected interior face.
27663         bsymtet.tet = (tetrahedron *) symtet.tet[4]; // The saved bgm tet.
27664         bsymtet.loc = symtet.loc;
27665         bgm->bond(btetloop, bsymtet);
27666       } else if (symtet.tet == dummytet) {
27667         // Create a subface in background mesh.
27668         bgm->makeshellface(bgm->subfaces, &bhullsh);
27669         bgm->adjustedgering(btetloop, CCW); // face to inside.
27670         bgm->setsorg(bhullsh, bgm->org(btetloop));
27671         bgm->setsdest(bhullsh, bgm->dest(btetloop));
27672         bgm->setsapex(bhullsh, bgm->apex(btetloop));
27673         bgm->tsbond(btetloop, bhullsh);
27674         // Remember a hull face for point location.
27675         bgm->dummytet[0] = bgm->encode(btetloop);
27676       }
27677     }
27678     // Restore the backup tet point.
27679     tetloop.tet[4] = (tetrahedron) tetptbaklist[idx++];
27680     // Make the point-to-bgmtet map for size interpolation.
27681     btetloop.loc = 0;
27682     for (i = 0; i < 4; i++) {
27683       ploop = (point) tetloop.tet[4 + i];
27684       setpoint2bgmtet(ploop, bgm->encode(btetloop));
27685     }
27686     // Go to the next tet, btet.
27687     tetloop.tet = tetrahedrontraverse();
27688   }
27689 
27690   // Connect bgm hull subfaces. Note: all hull subfaces form a 2-manifold.
27691   bgm->subfaces->traversalinit();
27692   bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27693   while (bhullsh.sh != (shellface *) NULL) {
27694     bhullsh.shver = 0;
27695     bgm->stpivot(bhullsh, btetloop);
27696     assert(btetloop.tet != bgm->dummytet);
27697     bgm->adjustedgering(btetloop, CCW);
27698     for (i = 0; i < 3; i++) {
27699       bgm->spivot(bhullsh, bneighsh);
27700       if (bneighsh.sh == bgm->dummysh) {
27701         // This side is open, operate on it.
27702         bsymtet = btetloop;
27703         while (bgm->fnextself(bsymtet));
27704         bgm->tspivot(bsymtet, bneighsh);
27705         bgm->findedge(&bneighsh, bgm->sdest(bhullsh), bgm->sorg(bhullsh));
27706         bgm->sbond(bhullsh, bneighsh);
27707       }
27708       bgm->enextself(btetloop);
27709       bgm->senextself(bhullsh);
27710     }
27711     bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27712   }
27713 
27714   delete [] tetptbaklist;
27715   delete [] idx2bplist;
27716 }
27717 
27718 //
27719 // Begin of Delaunay refinement routines
27720 //
27721 
27723 //                                                                           //
27724 // marksharpsegments()    Mark sharp segments.                               //
27725 //                                                                           //
27726 // A segment s is called sharp if it is in one of the two cases:             //
27727 //  (1) There is a segment s' intersecting with s.  The internal angle (*)   //
27728 //      between s and s' is acute.                                           //
27729 //  (2) There are two facets f1 and f2 intersecting at s.  The internal      //
27730 //      dihedral angle (*) between f1 and f2 is acute.                       //
27731 // This routine finds the sharp segments and marked them as type SHARP.      //
27732 // The minimum angle between segments (minfaceang) and the minimum dihedral  //
27733 // angle between facets (minfacetdihed) are calulcated.                      //
27734 //                                                                           //
27735 // (*) The internal angle (or dihedral) bewteen two features means the angle //
27736 // inside the mesh domain.                                                   //
27737 //                                                                           //
27739 
27740 void tetgenmesh::marksharpsegments(REAL sharpangle)
27741 {
27742   triface adjtet;
27743   face startsh, spinsh, neighsh;
27744   face segloop, prevseg, nextseg;
27745   point eorg, edest;
27746   REAL ang, smallang;
27747   bool issharp;
27748   int sharpsegcount;
27749 
27750   if (b->verbose > 0) {
27751     printf("  Marking sharp segments.\n");
27752   }
27753 
27754   smallang = sharpangle * PI / 180.;
27755   sharpsegcount = 0;
27756   eorg = edest = (point) NULL; // To avoid compiler warnings.
27757 
27758   // A segment s may have been split into many subsegments. Operate the one
27759   //   which contains the origin of s. Then mark the rest of subsegments.
27760   subsegs->traversalinit();
27761   segloop.sh = shellfacetraverse(subsegs);
27762   while (segloop.sh != (shellface *) NULL) {
27763     segloop.shver = 0;
27764     senext2(segloop, prevseg);
27765     spivotself(prevseg);
27766     if (prevseg.sh == dummysh) {
27767       // Operate on this seg s.
27768       assert(shelltype(segloop) != SHARP); // It should be unmarked.
27769       issharp = false;
27770       spivot(segloop, startsh);
27771       if (startsh.sh != dummysh) {
27772         // First check if two facets form an acute dihedral angle at s.
27773         eorg = sorg(segloop);
27774         edest = sdest(segloop);
27775         spinsh = startsh;
27776         do {
27777           if (sorg(spinsh) != eorg) {
27778             sesymself(spinsh);
27779           }
27780           // Only do test when the spinsh is faceing inward.
27781           stpivot(spinsh, adjtet);
27782           if (adjtet.tet != dummytet) {
27783             // Get the subface on the adjacent facet.
27784             spivot(spinsh, neighsh);
27785             // Do not calculate if it is self-bonded.
27786             if (neighsh.sh != spinsh.sh) {
27787               // Calculate the dihedral angle between the two subfaces.
27788               ang = facedihedral(eorg, edest, sapex(spinsh), sapex(neighsh));
27789               // Only do check if a sharp angle has not been found.
27790               if (!issharp) issharp = (ang < smallang);
27791               // Remember the smallest facet dihedral angle.
27792               minfacetdihed = minfacetdihed < ang ? minfacetdihed : ang;
27793             }
27794           }
27795           // Go to the next facet.
27796           spivotself(spinsh);
27797         } while (spinsh.sh != startsh.sh);
27798         // if (!issharp) {
27799           // Second check if s forms an acute angle with another seg.
27800           spinsh = startsh;
27801           do {
27802             if (sorg(spinsh) != eorg) {
27803               sesymself(spinsh);
27804             }
27805             // Calculate the angle between s and s' of this facet.
27806             neighsh = spinsh;
27807             // Rotate edges around 'eorg' until meeting another seg s'. Such
27808             //   seg (s') must exist since the facet is segment-bounded.
27809             //   The sum of the angles of faces at 'eorg' gives the internal
27810             //   angle between the two segments.
27811             ang = 0.0;
27812             do {
27813               ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27814               senext2self(neighsh);
27815               sspivot(neighsh, nextseg);
27816               if (nextseg.sh != dummysh) break;
27817               // Go to the next coplanar subface.
27818               spivotself(neighsh);
27819               assert(neighsh.sh != dummysh);
27820               if (sorg(neighsh) != eorg) {
27821                 sesymself(neighsh);
27822               }
27823             } while (true);
27824             // Only do check if a sharp angle has not been found.
27825             if (!issharp) issharp = (ang < smallang);
27826             // Remember the smallest input face angle.
27827             minfaceang = minfaceang < ang ? minfaceang : ang;
27828             // Go to the next facet.
27829             spivotself(spinsh);
27830           } while (spinsh.sh != startsh.sh);
27831         // }
27832       }
27833       if (issharp) {
27834         setshelltype(segloop, SHARP);
27835         // Set the type for all subsegments at forwards.
27836         senext(segloop, nextseg);
27837         spivotself(nextseg);
27838         while (nextseg.sh != dummysh) {
27839           nextseg.shver = 0;
27840           setshelltype(nextseg, SHARP);
27841           senextself(nextseg);
27842           spivotself(nextseg);
27843         }
27844         sharpsegcount++;
27845       }
27846     }
27847     segloop.sh = shellfacetraverse(subsegs);
27848   }
27849 
27850   // So far we have marked all segments which have an acute dihedral angle
27851   //   or whose ORIGINs have an acute angle. In the un-marked subsegments,
27852   //   there are possible ones whose DESTINATIONs have an acute angle.
27853   subsegs->traversalinit();
27854   segloop.sh = shellfacetraverse(subsegs);
27855   while (segloop.sh != (shellface *) NULL) {
27856     // Only operate if s is non-sharp and contains the dest.
27857     segloop.shver = 0;
27858     senext(segloop, nextseg);
27859     spivotself(nextseg);
27860     // if ((nextseg.sh == dummysh) && (shelltype(segloop) != SHARP)) {
27861     if (nextseg.sh == dummysh) {
27862       // issharp = false;
27863       issharp = (shelltype(segloop) == SHARP);
27864       spivot(segloop, startsh);
27865       if (startsh.sh != dummysh) {
27866         // Check if s forms an acute angle with another seg.
27867         eorg = sdest(segloop);
27868         spinsh = startsh;
27869         do {
27870           if (sorg(spinsh) != eorg) {
27871             sesymself(spinsh);
27872           }
27873           // Calculate the angle between s and s' of this facet.
27874           neighsh = spinsh;
27875           ang = 0.0;
27876           do {
27877             ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27878             senext2self(neighsh);
27879             sspivot(neighsh, nextseg);
27880             if (nextseg.sh != dummysh) break;
27881             // Go to the next coplanar subface.
27882             spivotself(neighsh);
27883             assert(neighsh.sh != dummysh);
27884             if (sorg(neighsh) != eorg) {
27885               sesymself(neighsh);
27886             }
27887           } while (true);
27888           // Only do check if a sharp angle has not been found.
27889           if (!issharp) issharp = (ang < smallang);
27890           // Remember the smallest input face angle.
27891           minfaceang = minfaceang < ang ? minfaceang : ang;
27892           // Go to the next facet.
27893           spivotself(spinsh);
27894         } while (spinsh.sh != startsh.sh);
27895       }
27896       if (issharp) {
27897         setshelltype(segloop, SHARP);
27898         // Set the type for all subsegments at backwards.
27899         senext2(segloop, prevseg);
27900         spivotself(prevseg);
27901         while (prevseg.sh != dummysh) {
27902           prevseg.shver = 0;
27903           setshelltype(prevseg, SHARP);
27904           senext2self(prevseg);
27905           spivotself(prevseg);
27906         }
27907         sharpsegcount++;
27908       }
27909     }
27910     segloop.sh = shellfacetraverse(subsegs);
27911   }
27912 
27913   if ((b->verbose > 0) && (sharpsegcount > 0)) {
27914     printf("  %d sharp segments.\n", sharpsegcount);
27915   }
27916 }
27917 
27919 //                                                                           //
27920 // decidefeaturepointsizes()    Decide the sizes for all feature points.     //
27921 //                                                                           //
27922 // A feature point is a point on a sharp segment. Every feature point p will //
27923 // be assigned a positive size which is the radius of the protecting ball.   //
27924 //                                                                           //
27925 // The size of a feature point may be specified by one of the following ways://
27926 //   (1) directly specifying on an input vertex (by using .mtr file);        //
27927 //   (2) imposing a fixed maximal volume constraint ('-a__' option);         //
27928 //   (3) imposing a maximal volume constraint in a region ('-a' option);     //
27929 //   (4) imposing a maximal area constraint on a facet (in .var file);       //
27930 //   (5) imposing a maximal length constraint on a segment (in .var file);   //
27931 //   (6) combining (1) - (5).                                                //
27932 //   (7) automatically deriving a size if none of (1) - (6) is available.    //
27933 // In case (7),the size of p is set to be the smallest edge length among all //
27934 // edges connecting at p.  The final size of p is the minimum of (1) - (7).  //
27935 //                                                                           //
27937 
27938 void tetgenmesh::decidefeaturepointsizes()
27939 {
27940   list *tetlist, *verlist;
27941   shellface **segsperverlist;
27942   triface starttet;
27943   face shloop;
27944   face checkseg, prevseg, nextseg, testseg;
27945   point ploop, adjpt, e1, e2;
27946   REAL lfs_0, len, vol, maxlen, varlen;
27947   bool isfeature;
27948   int *idx2seglist;
27949   int featurecount;
27950   int idx, i, j;
27951 
27952   maxlen = 0.0;
27953 
27954   if (b->verbose > 0) {
27955     printf("  Deciding feature-point sizes.\n");
27956   }
27957 
27958   // Constructing a map from vertices to segments.
27959   makesegmentmap(idx2seglist, segsperverlist);
27960   // Initialize working lists.
27961   tetlist = new list(sizeof(triface), NULL, 256);
27962   verlist = new list(sizeof(point *), NULL, 256);
27963 
27964   if (b->fixedvolume) {
27965     // A fixed volume constraint is imposed. This gives an upper bound of
27966     //   the maximal radius of the protect ball of a vertex.
27967     maxlen = pow(6.0 * b->maxvolume, 1.0/3.0);
27968   }
27969 
27970   if (!b->refine) {
27971     // Initially correct types for Steiner points.
27972     featurecount = 0;
27973     points->traversalinit();
27974     ploop = pointtraverse();
27975     while (ploop != (point) NULL) {
27976       if (pointtype(ploop) == NACUTEVERTEX) {
27977         if (point2sh(ploop) != (shellface) NULL) {
27978           setpointtype(ploop, FREESEGVERTEX);
27979           featurecount++;
27980         }
27981       }
27982       ploop = pointtraverse();
27983     }
27984 #ifdef SELF_CHECK
27985     if ((b->verbose > 0) && (featurecount > 0)) {
27986       printf("  %d Steiner points correction.\n", featurecount);
27987     }
27988 #endif
27989   }
27990 
27991   // First only assign a size of p if p is not a Steiner point. The size of
27992   //   a Steiner point will be interpolated later from the endpoints of the
27993   //   segment on which it lies.
27994   featurecount = 0;
27995   points->traversalinit();
27996   ploop = pointtraverse();
27997   while (ploop != (point) NULL) {
27998     if (pointtype(ploop) != FREESEGVERTEX) {
27999       // Is p a feature point?
28000       isfeature = false;
28001       idx = pointmark(ploop) - in->firstnumber;
28002       for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; i++) {
28003         checkseg.sh = segsperverlist[i];
28004         isfeature = (shelltype(checkseg) == SHARP);
28005       }
28006       // Decide the size of p if it is on a sharp segment.
28007       if (isfeature) {
28008         // Find a tet containing p (checkseg is a sharp seg which contains p).
28009         sstpivot(&checkseg, &starttet);
28010         // Form star(p).
28011         tetlist->append(&starttet);
28012         formstarpolyhedron(ploop, tetlist, verlist, true);
28013         // Decide the size for p if no input size is given on input.
28014         if (ploop[pointmtrindex] == 0.0) {
28015           // Calculate lfs_0(p).
28016           lfs_0 = longest;
28017           for (i = 0; i < verlist->len(); i++) {
28018             adjpt = * (point *)(* verlist)[i];
28019             if (pointtype(adjpt) == FREESEGVERTEX) {
28020               // A Steiner point q. Find the seg it lies on.
28021               sdecode(point2sh(adjpt), checkseg);
28022               assert(checkseg.sh != dummysh);
28023               checkseg.shver = 0;
28024               // Find the origin of this seg.
28025               prevseg = checkseg;
28026               do {
28027                 senext2(prevseg, testseg);
28028                 spivotself(testseg);
28029                 if (testseg.sh == dummysh) break;
28030                 prevseg = testseg; // Go to the previous subseg.
28031                 prevseg.shver = 0;
28032               } while (true);
28033               // Find the dest of this seg.
28034               nextseg = checkseg;
28035               do {
28036                 senext(nextseg, testseg);
28037                 spivotself(testseg);
28038                 if (testseg.sh == dummysh) break;
28039                 nextseg = testseg; // Go to the next subseg.
28040                 nextseg.shver = 0;
28041               } while (true);
28042               e1 = sorg(prevseg);
28043               e2 = sdest(nextseg);
28044               // Check if p is the origin or the dest of this seg.
28045               if (ploop == e1) {
28046                 // Set q to be the dest of this seg.
28047                 adjpt = e2;
28048               } else if (ploop == e2) {
28049                 // Set q to be the org of this seg.
28050                 adjpt = e1;
28051               }
28052             }
28053             len = distance(ploop, adjpt);
28054             if (lfs_0 > len) lfs_0 = len;
28055           }
28056           ploop[pointmtrindex] = lfs_0;
28057         }
28058         if (b->fixedvolume) {
28059           // A fixed volume constraint is imposed. Adjust H(p) <= maxlen.
28060           if (ploop[pointmtrindex] > maxlen) {
28061             ploop[pointmtrindex] = maxlen;
28062           }
28063         }
28064         if (b->varvolume) {
28065           // Variant volume constraints are imposed. Adjust H(p) <= varlen.
28066           for (i = 0; i < tetlist->len(); i++) {
28067             starttet = * (triface *)(* tetlist)[i];
28068             vol = volumebound(starttet.tet);
28069             if (vol > 0.0) {
28070               varlen = pow(6 * vol, 1.0/3.0);
28071               if (ploop[pointmtrindex] > varlen) {
28072                 ploop[pointmtrindex] = varlen;
28073               }
28074             }
28075           }
28076         }
28077         // Clear working lists.
28078         tetlist->clear();
28079         verlist->clear();
28080         featurecount++;
28081       } else {
28082         // NO feature point, set the size of p be zero.
28083         ploop[pointmtrindex] = 0.0;
28084       }
28085     } // if (pointtype(ploop) != FREESEGVERTEX) {
28086     ploop = pointtraverse();
28087   }
28088 
28089   if (b->verbose > 0) {
28090     printf("  %d feature points.\n", featurecount);
28091   }
28092 
28093   if (!b->refine) {
28094     // Second only assign sizes for all Steiner points. A Steiner point p
28095     //   inserted on a sharp segment s is assigned a size by interpolating
28096     //   the sizes of the original endpoints of s.
28097     featurecount = 0;
28098     points->traversalinit();
28099     ploop = pointtraverse();
28100     while (ploop != (point) NULL) {
28101       if (pointtype(ploop) == FREESEGVERTEX) {
28102         if (ploop[pointmtrindex] == 0.0) {
28103           sdecode(point2sh(ploop), checkseg);
28104           assert(checkseg.sh != dummysh);
28105           if (shelltype(checkseg) == SHARP) {
28106             checkseg.shver = 0;
28107             // Find the origin of this seg.
28108             prevseg = checkseg;
28109             do {
28110               senext2(prevseg, testseg);
28111               spivotself(testseg);
28112               if (testseg.sh == dummysh) break;
28113               prevseg = testseg; // Go the previous subseg.
28114               prevseg.shver = 0;
28115             } while (true);
28116             // Find the dest of this seg.
28117             nextseg = checkseg;
28118             do {
28119               senext(nextseg, testseg);
28120               spivotself(testseg);
28121               if (testseg.sh == dummysh) break;
28122               nextseg = testseg; // Go the next subseg.
28123               nextseg.shver = 0;
28124             } while (true);
28125             e1 = sorg(prevseg);
28126             e2 = sdest(nextseg);
28127             len = distance(e1, e2);
28128             lfs_0 = distance(e1, ploop);
28129             // The following assert() happens when -Y option is used.
28130             if (b->nobisect == 0) {
28131               assert(lfs_0 < len);
28132             }
28133             ploop[pointmtrindex] = e1[pointmtrindex]
28134               + (lfs_0 / len) * (e2[pointmtrindex] - e1[pointmtrindex]);
28135             featurecount++;
28136           } else {
28137             // NO feature point, set the size of p be zero.
28138             ploop[pointmtrindex] = 0.0;
28139           } // if (shelltype(checkseg) == SHARP)
28140         } // if (ploop[pointmtrindex] == 0.0)
28141       } // if (pointtype(ploop) != FREESEGVERTEX)
28142       ploop = pointtraverse();
28143     }
28144     if ((b->verbose > 0) && (featurecount > 0)) {
28145       printf("  %d Steiner feature points.\n", featurecount);
28146     }
28147   }
28148 
28149   if (varconstraint) {
28150     // A .var file exists. Adjust feature sizes.
28151     if (in->facetconstraintlist) {
28152       // Have facet area constrains.
28153       subfaces->traversalinit();
28154       shloop.sh = shellfacetraverse(subfaces);
28155       while (shloop.sh != (shellface *) NULL) {
28156         varlen = areabound(shloop);
28157         if (varlen > 0.0) {
28158           // Check if the three corners are feature points.
28159           varlen = sqrt(varlen);
28160           for (j = 0; j < 3; j++) {
28161             ploop = (point) shloop.sh[3 + j];
28162             isfeature = false;
28163             idx = pointmark(ploop) - in->firstnumber;
28164             for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28165                  i++) {
28166               checkseg.sh = segsperverlist[i];
28167               isfeature = (shelltype(checkseg) == SHARP);
28168             }
28169             if (isfeature) {
28170               assert(ploop[pointmtrindex] > 0.0);
28171               if (ploop[pointmtrindex] > varlen) {
28172                 ploop[pointmtrindex] = varlen;
28173               }
28174             }
28175           } // for (j = 0; j < 3; j++)
28176         }
28177         shloop.sh = shellfacetraverse(subfaces);
28178       }
28179     }
28180     if (in->segmentconstraintlist) {
28181       // Have facet area constrains.
28182       subsegs->traversalinit();
28183       shloop.sh = shellfacetraverse(subsegs);
28184       while (shloop.sh != (shellface *) NULL) {
28185         varlen = areabound(shloop);
28186         if (varlen > 0.0) {
28187           // Check if the two endpoints are feature points.
28188           for (j = 0; j < 2; j++) {
28189             ploop = (point) shloop.sh[3 + j];
28190             isfeature = false;
28191             idx = pointmark(ploop) - in->firstnumber;
28192             for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28193                  i++) {
28194               checkseg.sh = segsperverlist[i];
28195               isfeature = (shelltype(checkseg) == SHARP);
28196             }
28197             if (isfeature) {
28198               assert(ploop[pointmtrindex] > 0.0);
28199               if (ploop[pointmtrindex] > varlen) {
28200                 ploop[pointmtrindex] = varlen;
28201               }
28202             }
28203           } // for (j = 0; j < 2; j++)
28204         }
28205         shloop.sh = shellfacetraverse(subsegs);
28206       }
28207     }
28208   } // if (varconstraint)
28209 
28210   delete [] segsperverlist;
28211   delete [] idx2seglist;
28212   delete tetlist;
28213   delete verlist;
28214 }
28215 
28217 //                                                                           //
28218 // enqueueencsub()    Add an encroached subface into the queue.              //
28219 //                                                                           //
28221 
28222 void tetgenmesh::enqueueencsub(face* testsub, point encpt, int quenumber,
28223   REAL* cent)
28224 {
28225   badface *encsub;
28226   int i;
28227 
28228   encsub = (badface *) badsubfaces->alloc();
28229   encsub->ss = *testsub;
28230   encsub->forg = sorg(*testsub);
28231   encsub->fdest = sdest(*testsub);
28232   encsub->fapex = sapex(*testsub);
28233   encsub->foppo = (point) encpt;
28234   for (i = 0; i < 3; i++) encsub->cent[i] = cent[i];
28235   encsub->nextitem = (badface *) NULL;
28236   // Set the pointer of 'encsubseg' into 'testsub'.  It has two purposes:
28237   //   (1) We can regonize it is encroached; (2) It is uniquely queued.
28238   setshell2badface(encsub->ss, encsub);
28239   // Add the subface to the end of a queue (quenumber = 2, high priority).
28240   *subquetail[quenumber] = encsub;
28241   // Maintain a pointer to the NULL pointer at the end of the queue.
28242   subquetail[quenumber] = &encsub->nextitem;
28243   if (b->verbose > 2) {
28244     printf("    Queuing subface (%d, %d, %d) [%d].\n", pointmark(encsub->forg),
28245            pointmark(encsub->fdest), pointmark(encsub->fapex), quenumber);
28246   }
28247 }
28248 
28250 //                                                                           //
28251 // dequeueencsub()    Remove an enc-subface from the front of the queue.     //
28252 //                                                                           //
28254 
28255 tetgenmesh::badface* tetgenmesh::dequeueencsub(int* pquenumber)
28256 {
28257   badface *result;
28258   int quenumber;
28259 
28260   // Look for a nonempty queue.
28261   for (quenumber = 2; quenumber >= 0; quenumber--) {
28262     result = subquefront[quenumber];
28263     if (result != (badface *) NULL) {
28264       // Remove the badface from the queue.
28265       subquefront[quenumber] = result->nextitem;
28266       // Maintain a pointer to the NULL pointer at the end of the queue.
28267       if (subquefront[quenumber] == (badface *) NULL) {
28268         subquetail[quenumber] = &subquefront[quenumber];
28269       }
28270       *pquenumber = quenumber;
28271       return result;
28272     }
28273   }
28274   return (badface *) NULL;
28275 }
28276 
28278 //                                                                           //
28279 // enqueuebadtet()    Add a tetrahedron into the queue.                      //
28280 //                                                                           //
28282 
28283 void tetgenmesh::enqueuebadtet(triface* testtet, REAL ratio2, REAL* cent)
28284 {
28285   badface *newbadtet;
28286   int queuenumber;
28287   int i;
28288 
28289   // Allocate space for the bad tetrahedron.
28290   newbadtet = (badface *) badtetrahedrons->alloc();
28291   newbadtet->tt = *testtet;
28292   newbadtet->key = ratio2;
28293   if (cent != NULL) {
28294     for (i = 0; i < 3; i++) newbadtet->cent[i] = cent[i];
28295   } else {
28296     for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
28297   }
28298   newbadtet->forg = org(*testtet);
28299   newbadtet->fdest = dest(*testtet);
28300   newbadtet->fapex = apex(*testtet);
28301   newbadtet->foppo = oppo(*testtet);
28302   newbadtet->nextitem = (badface *) NULL;
28303   // Determine the appropriate queue to put the bad tetrahedron into.
28304   if (ratio2 > b->goodratio) {
28305     // queuenumber = (int) ((ratio2 - b->goodratio) / 0.5);
28306     queuenumber = (int) (64.0 - 64.0 / ratio2);
28307     // 'queuenumber' may overflow (negative) caused by a very large ratio.
28308     if ((queuenumber > 63) || (queuenumber < 0)) {
28309       queuenumber = 63;
28310     }
28311   } else {
28312     // It's not a bad ratio; put the tet in the lowest-priority queue.
28313     queuenumber = 0;
28314   }
28315 
28316   // Are we inserting into an empty queue?
28317   if (tetquefront[queuenumber] == (badface *) NULL) {
28318     // Yes. Will this become the highest-priority queue?
28319     if (queuenumber > firstnonemptyq) {
28320       // Yes, this is the highest-priority queue.
28321       nextnonemptyq[queuenumber] = firstnonemptyq;
28322       firstnonemptyq = queuenumber;
28323     } else {
28324       // No. Find the queue with next higher priority.
28325       i = queuenumber + 1;
28326       while (tetquefront[i] == (badface *) NULL) {
28327         i++;
28328       }
28329       // Mark the newly nonempty queue as following a higher-priority queue.
28330       nextnonemptyq[queuenumber] = nextnonemptyq[i];
28331       nextnonemptyq[i] = queuenumber;
28332     }
28333     // Put the bad tetrahedron at the beginning of the (empty) queue.
28334     tetquefront[queuenumber] = newbadtet;
28335   } else {
28336     // Add the bad tetrahedron to the end of an already nonempty queue.
28337     tetquetail[queuenumber]->nextitem = newbadtet;
28338   }
28339   // Maintain a pointer to the last tetrahedron of the queue.
28340   tetquetail[queuenumber] = newbadtet;
28341 
28342   if (b->verbose > 2) {
28343     printf("    Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
28344            pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
28345            pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
28346            sqrt(ratio2), queuenumber);
28347   }
28348 }
28349 
28351 //                                                                           //
28352 // dequeuebadtet()    Remove a tetrahedron from the front of the queue.      //
28353 //                                                                           //
28355 
28356 tetgenmesh::badface* tetgenmesh::topbadtetra()
28357 {
28358   // Keep a record of which queue was accessed in case dequeuebadtetra()
28359   //   is called later.
28360   recentq = firstnonemptyq;
28361   // If no queues are nonempty, return NULL.
28362   if (firstnonemptyq < 0) {
28363     return (badface *) NULL;
28364   } else {
28365     // Return the first tetrahedron of the highest-priority queue.
28366     return tetquefront[firstnonemptyq];
28367   }
28368 }
28369 
28370 void tetgenmesh::dequeuebadtet()
28371 {
28372   badface *deadbadtet;
28373   int i;
28374 
28375   // If queues were empty last time topbadtetra() was called, do nothing.
28376   if (recentq >= 0) {
28377     // Find the tetrahedron last returned by topbadtetra().
28378     deadbadtet = tetquefront[recentq];
28379     // Remove the tetrahedron from the queue.
28380     tetquefront[recentq] = deadbadtet->nextitem;
28381     // If this queue is now empty, update the list of nonempty queues.
28382     if (deadbadtet == tetquetail[recentq]) {
28383       // Was this the highest-priority queue?
28384       if (firstnonemptyq == recentq) {
28385         // Yes; find the queue with next lower priority.
28386         firstnonemptyq = nextnonemptyq[firstnonemptyq];
28387       } else {
28388         // No; find the queue with next higher priority.
28389         i = recentq + 1;
28390         while (tetquefront[i] == (badface *) NULL) {
28391           i++;
28392         }
28393         nextnonemptyq[i] = nextnonemptyq[recentq];
28394       }
28395     }
28396     // Return the bad tetrahedron to the pool.
28397     badfacedealloc(badtetrahedrons, deadbadtet);
28398   }
28399 }
28400 
28402 //                                                                           //
28403 // checkseg4encroach()    Check a subsegment to see if it is encroached.     //
28404 //                                                                           //
28405 // A segment s is encroached if there is a vertex lies inside or on its dia- //
28406 // metral circumsphere, i.e., s faces an angle theta >= 90 degrees.          //
28407 //                                                                           //
28408 // If 'testpt' (p) != NULL, only test if 'testseg' (s) is encroached by it,  //
28409 // else, check all apexes of faces around s. Return TRUE if s is encroached. //
28410 // If and 'enqflag' is TRUE, add it into 'badsubsegs' if s is encroached.    //
28411 //                                                                           //
28412 // If 'prefpt' != NULL, it returns the reference point (defined in my paper) //
28413 // if it exists.  This point is will be used to split s.                     //
28414 //                                                                           //
28416 
28417 bool tetgenmesh::checkseg4encroach(face* testseg, point testpt, point* prefpt,
28418   bool enqflag)
28419 {
28420   badface *encsubseg;
28421   triface starttet, spintet;
28422   point eorg, edest, eapex, encpt;
28423   REAL cent[3], radius, dist, diff;
28424   REAL maxradius;
28425   bool enq;
28426   int hitbdry;
28427 
28428   enq = false;
28429   eorg = sorg(*testseg);
28430   edest = sdest(*testseg);
28431   cent[0] = 0.5 * (eorg[0] + edest[0]);
28432   cent[1] = 0.5 * (eorg[1] + edest[1]);
28433   cent[2] = 0.5 * (eorg[2] + edest[2]);
28434   radius = distance(cent, eorg);
28435 
28436   if (varconstraint && (areabound(*testseg) > 0.0)) {
28437     enq = (2.0 * radius) > areabound(*testseg);
28438   }
28439 
28440   if (!enq) {
28441     maxradius = 0.0;
28442     if (testpt == (point) NULL) {
28443       // Check if it is encroached by traversing all faces containing it.
28444       sstpivot(testseg, &starttet);
28445       eapex = apex(starttet);
28446       spintet = starttet;
28447       hitbdry = 0;
28448       do {
28449         dist = distance(cent, apex(spintet));
28450         diff = dist - radius;
28451         if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28452         if (diff <= 0.0) {
28453           // s is encroached.
28454           enq = true;
28455           if (prefpt != (point *) NULL) {
28456             // Find the reference point.
28457             encpt = apex(spintet);
28458             circumsphere(eorg, edest, encpt, NULL, NULL, &dist);
28459             if (dist > maxradius) {
28460               // Rememebr this point.
28461               *prefpt = encpt;
28462               maxradius = dist;
28463             }
28464           } else {
28465             break;
28466           }
28467         }
28468         if (!fnextself(spintet)) {
28469           hitbdry++;
28470           if (hitbdry < 2) {
28471             esym(starttet, spintet);
28472             if (!fnextself(spintet)) {
28473               hitbdry++;
28474             }
28475           }
28476         }
28477       } while (apex(spintet) != eapex && (hitbdry < 2));
28478     } else {
28479       // Only check if 'testseg' is encroached by 'testpt'.
28480       dist = distance(cent, testpt);
28481       diff = dist - radius;
28482       if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28483       enq = (diff <= 0.0);
28484     }
28485   }
28486 
28487   if (enq && enqflag) {
28488     if (b->verbose > 2) {
28489       printf("    Queuing encroaching subsegment (%d, %d).\n",
28490              pointmark(eorg), pointmark(edest));
28491     }
28492     encsubseg = (badface *) badsubsegs->alloc();
28493     encsubseg->ss = *testseg;
28494     encsubseg->forg = eorg;
28495     encsubseg->fdest = edest;
28496     encsubseg->foppo = (point) NULL; // Not used.
28497     // Set the pointer of 'encsubseg' into 'testseg'.  It has two purposes:
28498     //   (1) We can regonize it is encroached; (2) It is uniquely queued.
28499     setshell2badface(encsubseg->ss, encsubseg);
28500   }
28501 
28502   return enq;
28503 }
28504 
28506 //                                                                           //
28507 // checksub4encroach()    Check a subface to see if it is encroached.        //
28508 //                                                                           //
28509 // A subface f is encroached if there is a vertex inside or on its diametral //
28510 // circumsphere.                                                             //
28511 //                                                                           //
28512 // If 'testpt (p) != NULL', test if 'testsub' (f) is encroached by it, else, //
28513 // test if f is encroached by one of the two opposites of the adjacent tets. //
28514 // Return TRUE if f is encroached and queue it if 'enqflag' is set.          //
28515 //                                                                           //
28517 
28518 bool tetgenmesh::checksub4encroach(face* testsub, point testpt, bool enqflag)
28519 {
28520   triface abuttet;
28521   point pa, pb, pc, encpt;
28522   REAL A[4][4], rhs[4], D;
28523   REAL cent[3], area;
28524   REAL radius, dist, diff;
28525   bool enq;
28526   int indx[4];
28527   int quenumber;
28528 
28529   enq = false;
28530   radius = 0.0;
28531   encpt = (point) NULL;
28532 
28533   pa = sorg(*testsub);
28534   pb = sdest(*testsub);
28535   pc = sapex(*testsub);
28536 
28537   // Compute the coefficient matrix A (3x3).
28538   A[0][0] = pb[0] - pa[0];
28539   A[0][1] = pb[1] - pa[1];
28540   A[0][2] = pb[2] - pa[2]; // vector V1 (pa->pb)
28541   A[1][0] = pc[0] - pa[0];
28542   A[1][1] = pc[1] - pa[1];
28543   A[1][2] = pc[2] - pa[2]; // vector V2 (pa->pc)
28544   cross(A[0], A[1], A[2]); // vector V3 (V1 X V2)
28545 
28546   if (varconstraint && (areabound(*testsub) > 0.0)) {
28547     // Check if the subface has too big area.
28548     area = 0.5 * sqrt(dot(A[2], A[2]));
28549     enq = area > areabound(*testsub);
28550     if (enq) {
28551       quenumber = 2; // A queue of subfaces having too big area.
28552     }
28553   }
28554 
28555   // Compute the right hand side vector b (3x1).
28556   rhs[0] = 0.5 * dot(A[0], A[0]);
28557   rhs[1] = 0.5 * dot(A[1], A[1]);
28558   rhs[2] = 0.0;
28559   // Solve the 3 by 3 equations use LU decomposition with partial pivoting
28560   //   and backward and forward substitute..
28561   if (lu_decmp(A, 3, indx, &D, 0)) {
28562     lu_solve(A, 3, indx, rhs, 0);
28563     cent[0] = pa[0] + rhs[0];
28564     cent[1] = pa[1] + rhs[1];
28565     cent[2] = pa[2] + rhs[2];
28566     radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
28567   }
28568 
28569   if (!enq) {
28570     // Check if the subface is encroached.
28571     if (testpt == (point) NULL) {
28572       stpivot(*testsub, abuttet);
28573       if (abuttet.tet != dummytet) {
28574         dist = distance(cent, oppo(abuttet));
28575         diff = dist - radius;
28576         if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28577         enq = (diff <= 0.0);
28578         if (enq) encpt = oppo(abuttet);
28579       }
28580       if (!enq) {
28581         sesymself(*testsub);
28582         stpivot(*testsub, abuttet);
28583         if (abuttet.tet != dummytet) {
28584           dist = distance(cent, oppo(abuttet));
28585           diff = dist - radius;
28586           if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28587           enq = (diff <= 0.0);
28588           if (enq) encpt = oppo(abuttet);
28589         }
28590       }
28591     } else {
28592       dist = distance(cent, testpt);
28593       diff = dist - radius;
28594       if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28595       enq = (diff <= 0.0);
28596     }
28597     if (enq) {
28598       quenumber = 0; // A queue of encroached subfaces.
28599     }
28600   }
28601 
28602   if (enq && enqflag) {
28603     enqueueencsub(testsub, encpt, quenumber, cent);
28604   }
28605 
28606   return enq;
28607 }
28608 
28610 //                                                                           //
28611 // checktet4badqual()    Test a tetrahedron for quality measures.            //
28612 //                                                                           //
28613 // Tests a tetrahedron to see if it satisfies the minimum ratio condition    //
28614 // and the maximum volume condition. Tetrahedra that aren't upto spec are    //
28615 // added to the bad tetrahedron queue.                                       //
28616 //                                                                           //
28618 
28619 bool tetgenmesh::checktet4badqual(triface* testtet, bool enqflag)
28620 {
28621   point pa, pb, pc, pd, pe1, pe2;
28622   REAL vda[3], vdb[3], vdc[3];
28623   REAL vab[3], vbc[3], vca[3];
28624   REAL N[4][3], A[4][4], rhs[4], D;
28625   REAL elen[6], circumcent[3];
28626   REAL bicent[3], offcent[3];
28627   offcent[0] = 0.0; // Just to avoid uninitialised value warnings.
28628   offcent[1] = 0.0; // Just to avoid uninitialised value warnings.
28629   offcent[2] = 0.0; // Just to avoid uninitialised value warnings.
28630   REAL volume, L, cosd;
28631   REAL radius2, smlen2, ratio2;
28632   REAL dist, sdist, split;
28633   bool enq;
28634   int indx[4];
28635   int sidx, i, j;
28636 
28637   pa = (point) testtet->tet[4];
28638   pb = (point) testtet->tet[5];
28639   pc = (point) testtet->tet[6];
28640   pd = (point) testtet->tet[7];
28641 
28642   // Get the edge vectors vda: d->a, vdb: d->b, vdc: d->c.
28643   // Set the matrix A = [vda, vdb, vdc]^T.
28644   for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
28645   for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
28646   for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
28647   // Get the rest edge vectors
28648   for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
28649   for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i];
28650   for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i];
28651 
28652   // Lu-decompose the matrix A.
28653   lu_decmp(A, 3, indx, &D, 0);
28654   // Get the volume of abcd.
28655   volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
28656   if (volume < 0.0) volume = -volume;
28657   // Check the radiu-edge ratio of the tet.
28658   rhs[0] = 0.5 * dot(vda, vda);
28659   rhs[1] = 0.5 * dot(vdb, vdb);
28660   rhs[2] = 0.5 * dot(vdc, vdc);
28661   lu_solve(A, 3, indx, rhs, 0);
28662   // Get the circumcenter.
28663   for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
28664   // Get the square of the circumradius.
28665   radius2 = dot(rhs, rhs);
28666   // Find the square of the shortest edge length.
28667   elen[0] = dot(vda, vda);
28668   elen[1] = dot(vdb, vdb);
28669   elen[2] = dot(vdc, vdc);
28670   elen[3] = dot(vab, vab);
28671   elen[4] = dot(vbc, vbc);
28672   elen[5] = dot(vca, vca);
28673   smlen2 = elen[0]; sidx = 0;
28674   for (i = 1; i < 6; i++) {
28675     if (smlen2 > elen[i]) { smlen2 = elen[i]; sidx = i; }
28676   }
28677   // Calculate the square of radius-edge ratio.
28678   ratio2 = radius2 / smlen2;
28679   // Check whether the ratio is smaller than permitted.
28680   enq = ratio2 > b->goodratio;
28681   if (!enq) {
28682     // abcd has good ratio.
28683     // ratio2 = 0.0;
28684     // if (b->offcenter) {
28685       // Test if it is a sliver.
28686       // Compute the 4 face normals (N[0], ..., N[3]).
28687       for (j = 0; j < 3; j++) {
28688         for (i = 0; i < 3; i++) rhs[i] = 0.0;
28689         rhs[j] = 1.0;  // Positive means the inside direction
28690         lu_solve(A, 3, indx, rhs, 0);
28691         for (i = 0; i < 3; i++) N[j][i] = rhs[i];
28692       }
28693       // Get the fourth normal by summing up the first three.
28694       for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
28695       // Normalized the normals.
28696       for (i = 0; i < 4; i++) {
28697         L = sqrt(dot(N[i], N[i]));
28698         if (L > 0.0) {
28699           for (j = 0; j < 3; j++) N[i][j] /= L;
28700         }
28701       }
28702       // N[0] is the normal of face bcd. Test the dihedral angles at edge
28703       //   cd, bd, and bc to see if they are too small or too big.
28704       for (i = 1; i < 4 && !enq; i++) {
28705         cosd = -dot(N[0], N[i]); // Edge cd, bd, bc.
28706         enq = cosd > cosmindihed;
28707       }
28708       if (!enq) {
28709         for (i = 2; i < 4 && !enq; i++) {
28710           cosd = -dot(N[1], N[i]); // Edge ad, ac
28711           enq = cosd > cosmindihed;
28712         }
28713         if (!enq) {
28714           cosd = -dot(N[2], N[3]); // Edge ab
28715           enq = cosd > cosmindihed;
28716         }
28717       }
28718     // }
28719   } else if (b->offcenter) {
28720     // abcd has bad-quality. Use off-center instead of circumcenter.
28721     switch (sidx) {
28722     case 0: // edge da.
28723       pe1 = pd; pe2 = pa; break;
28724     case 1: // edge db.
28725       pe1 = pd; pe2 = pb; break;
28726     case 2: // edge dc.
28727       pe1 = pd; pe2 = pc; break;
28728     case 3: // edge ab.
28729       pe1 = pa; pe2 = pb; break;
28730     case 4: // edge bc.
28731       pe1 = pb; pe2 = pc; break;
28732     case 5: // edge ca.
28733       pe1 = pc; pe2 = pa; break;
28734     default:
28735       pe1 = pe2 = (point) NULL; // Avoid a compile warning.
28736     }
28737     // The shortest edge is e1->e2.
28738     for (i = 0; i < 3; i++) bicent[i] = 0.5 * (pe1[i] + pe2[i]);
28739     dist = distance(bicent, circumcent);
28740     // sdist = sqrt(smlen2) * sin(PI / 3.0); // A icoso-triangle.
28741     // The following formulae is from
28742     sdist = b->alpha3 * (b->minratio+sqrt(b->goodratio-0.25))* sqrt(smlen2);
28743     split = sdist / dist;
28744     if (split > 1.0) split = 1.0;
28745     // Get the off-center.
28746     for (i = 0; i < 3; i++) {
28747       offcent[i] = bicent[i] + split * (circumcent[i] - bicent[i]);
28748     }
28749   }
28750 
28751   if (!enq && (b->varvolume || b->fixedvolume)) {
28752     // Check if the tet has too big volume.
28753     enq = b->fixedvolume && (volume > b->maxvolume);
28754     if (!enq && b->varvolume) {
28755       enq = (volume > volumebound(testtet->tet)) &&
28756             (volumebound(testtet->tet) > 0.0);
28757     }
28758   }
28759 
28760   if (!enq) {
28761     // Check if the user-defined sizing function is satisfied.
28762     if (b->metric) {
28763       // assert(b->alpha1 > 0.0);
28764       sdist = sqrt(radius2) / b->alpha1;
28765       for (i = 0; i < 4; i++) {
28766         pa = (point) testtet->tet[4 + i];
28767         // Get the indicated size of p.
28768         dist = pa[pointmtrindex]; // dist = b->alpha1 * pa[pointmtrindex];
28769         enq = ((dist < sdist) && (dist > 0.0));
28770         if (enq) break; // It is bad wrt. a node constraint.
28771         // *** Experiment ! Stop test if c is inside H(a).
28772         // if ((dist > 0.0) && (dist > sdist)) break;
28773       }
28774       // *** Experiment !
28775       // enq = (i == 4); // Does c lies outside all sparse-ball?
28776     } // if (b->metric)
28777   }
28778 
28779   if (enq && enqflag) {
28780     if (b->offcenter && (ratio2 > b->goodratio)) {
28781       for (i = 0; i < 3; i++) circumcent[i] = offcent[i];
28782     }
28783     enqueuebadtet(testtet, ratio2, circumcent);
28784   }
28785 
28786   return enq;
28787 }
28788 
28790 //                                                                           //
28791 // acceptsegpt()    Check if a segment point can be inserted or not.         //
28792 //                                                                           //
28793 // Segment(ab) is indicated to be split by a point p (\in ab). This routine  //
28794 // decides whether p can be inserted or not.                                 //
28795 //                                                                           //
28796 // p can not be inserted either the '-Y' option is used and ab is a hull     //
28797 // segment or '-YY' option is used.                                          //
28798 //                                                                           //
28799 // p can be inserted if it is in one of the following cases:                 //
28800 //   (1) if L = |a - b| is too long wrt the edge constraint; or              //
28801 //   (2) if |x - p| > \alpha_2 H(x) for x = a, b; or                         //
28802 //   (3) if 'refpt' != NULL.                                                 //
28803 //                                                                           //
28805 
28806 bool tetgenmesh::acceptsegpt(point segpt, point refpt, face* splitseg)
28807 {
28808   point p[2];
28809   REAL L, lfs;
28810   int i, j;
28811 
28812   if (b->nobisect == 1) {
28813     // '-Y'. It can not be split if it is on the hull.
28814     triface spintet;
28815     point pc;
28816     sstpivot(splitseg, &spintet);
28817     assert(spintet.tet != dummytet);
28818     pc = apex(spintet);
28819     do {
28820       if (!fnextself(spintet)) {
28821         // Meet a boundary face - s is on the hull.
28822         return false;
28823       }
28824     } while (pc != apex(spintet));
28825   } else if (b->nobisect > 1) {
28826     // '-YY'. Do not split it.
28827     return false;
28828   }
28829 
28830   p[0] = sorg(*splitseg);
28831   p[1] = sdest(*splitseg);
28832   if (varconstraint && (areabound(*splitseg) > 0)) {
28833     lfs = areabound(*splitseg);
28834     L = distance(p[0], p[1]);
28835     if (L > lfs) {
28836       return true; // case (1)
28837     }
28838   }
28839 
28840   j = 0; // Use j to count the number of inside balls.
28841   for (i = 0; i < 2; i++) {
28842     // Check if p is inside the protect ball of q.
28843     if (p[i][pointmtrindex] > 0.0) {
28844       lfs = b->alpha2 * p[i][pointmtrindex];
28845       L = distance(p[i], segpt);
28846       if (L < lfs) j++; // p is inside ball.
28847     }
28848   }
28849   if (j == 0) return true; // case (3).
28850 
28851   // If 'refpt' != NULL, force p to be inserted.
28852   if (refpt != (point) NULL) {
28853     cdtenforcesegpts++;
28854     return true;
28855   }
28856 
28857   // Do not split it.
28858   rejsegpts++;
28859   return false;
28860 }
28861 
28863 //                                                                           //
28864 // acceptfacpt()    Check if a facet point can be inserted or not.           //
28865 //                                                                           //
28866 // 'subceillist' is CBC(p). 'verlist' (V) is empty on input, it returns the  //
28867 // set of vertices of CBC(p).                                                //
28868 //                                                                           //
28869 // p can not be inserted either the '-Y' option is used and the facet is on  //
28870 // the hull or '-YY' option is used.                                         //
28871 //                                                                           //
28872 // p can be inserted if |p - v| > \alpha_2 H(v), for all v \in V.            //
28873 //                                                                           //
28875 
28876 bool tetgenmesh::acceptfacpt(point facpt, list* subceillist, list* verlist)
28877 {
28878   face *testsh;
28879   point p[2], ploop;
28880   REAL L, lfs;
28881   int idx, i, j;
28882 
28883   if (b->nobisect == 1) {
28884     // '-Y'. p can not be inserted if CBC(p) is on the hull.
28885     triface testtet;
28886     testsh = (face *)(* subceillist)[0];
28887     stpivot(*testsh, testtet);
28888     if (testtet.tet != dummytet) {
28889       sesymself(*testsh);
28890       stpivot(*testsh, testtet);
28891     }
28892     if (testtet.tet == dummytet) return false;
28893   } else if (b->nobisect > 1) {
28894     // '-YY'. Do not split s.
28895     return false;
28896   }
28897 
28898   // Collect the vertices of CBC(p), save them in V.
28899   for (i = 0; i < subceillist->len(); i++) {
28900     testsh = (face *)(* subceillist)[i];
28901     p[0] = sorg(*testsh);
28902     p[1] = sdest(*testsh);
28903     for (j = 0; j < 2; j++) {
28904       idx = pointmark(p[j]);
28905       if (idx >= 0) {
28906         setpointmark(p[j], -idx - 1);
28907         verlist->append(&(p[j]));
28908       }
28909     }
28910   }
28911 
28912   j = 0; // Use j to count the number of inside balls.
28913   for (i = 0; i < verlist->len(); i++) {
28914     ploop = * (point *)(* verlist)[i];
28915     // Uninfect q.
28916     idx = pointmark(ploop);
28917     setpointmark(ploop, -(idx + 1));
28918     // Check if p is inside the protect ball of q.
28919     if (ploop[pointmtrindex] > 0.0) {
28920       lfs = b->alpha2 * ploop[pointmtrindex];
28921       L = distance(ploop, facpt);
28922       if (L < lfs) j++; // p is inside ball.
28923     }
28924   }
28925   verlist->clear();
28926 
28927   if (j == 0) return true; // case (3).
28928 
28929   rejsubpts++;
28930   return false;
28931 }
28932 
28934 //                                                                           //
28935 // acceptvolpt()    Check if a volume point can be inserted or not.          //
28936 //                                                                           //
28937 // 'ceillist' is B(p).  'verlist' (V) is empty on input, it returns the set  //
28938 // of vertices of B(p).                                                      //
28939 //                                                                           //
28940 // p can be split if |p - v| > \alpha_2 H(v), for all v \in V.               //
28941 //                                                                           //
28943 
28944 bool tetgenmesh::acceptvolpt(point volpt, list* ceillist, list* verlist)
28945 {
28946   triface* testtet;
28947   point p[3], ploop;
28948   REAL L, lfs;
28949   int idx, i, j;
28950 
28951   // Collect the vertices of CBC(p), save them in V.
28952   for (i = 0; i < ceillist->len(); i++) {
28953     testtet = (triface *)(* ceillist)[i];
28954     p[0] = org(*testtet);
28955     p[1] = dest(*testtet);
28956     p[2] = apex(*testtet);
28957     for (j = 0; j < 3; j++) {
28958       idx = pointmark(p[j]);
28959       if (idx >= 0) {
28960         setpointmark(p[j], -idx - 1);
28961         verlist->append(&(p[j]));
28962       }
28963     }
28964   }
28965 
28966   j = 0; // Use j to counte the number of inside balls.
28967   for (i = 0; i < verlist->len(); i++) {
28968     ploop = * (point *)(* verlist)[i];
28969     // Uninfect q.
28970     idx = pointmark(ploop);
28971     setpointmark(ploop, -(idx + 1));
28972     // Check if p is inside the protect ball of q.
28973     if (ploop[pointmtrindex] > 0.0) {
28974       lfs = b->alpha2 * ploop[pointmtrindex];
28975       L = distance(ploop, volpt);
28976       if (L < lfs) j++; // p is inside the protect ball.
28977     }
28978   }
28979   verlist->clear();
28980 
28981   if (j == 0) return true; // case (2).
28982 
28983   rejtetpts++;
28984   return false;
28985 }
28986 
28988 //                                                                           //
28989 // getsplitpoint()    Get the inserting point in a segment.                  //
28990 //                                                                           //
28992 
28993 void tetgenmesh::getsplitpoint(point e1, point e2, point refpt, point newpt)
28994 {
28995   point ei, ej;
28996   REAL split, L, d1, d2, ps, rs;
28997   bool acutea, acuteb;
28998   int i;
28999 
29000   if (refpt != (point) NULL) {
29001     // Use the CDT rules to split the segment.
29002     acutea = (pointtype(e1) == ACUTEVERTEX);
29003     acuteb = (pointtype(e2) == ACUTEVERTEX);
29004     if (acutea ^ acuteb) {
29005       // Only one endpoint is acute. Use rule-2 or rule-3.
29006       ei = acutea ? e1 : e2;
29007       ej = acutea ? e2 : e1;
29008       L = distance(ei, ej);
29009       // Apply rule-2.
29010       d1 = distance(ei, refpt);
29011       split = d1 / L;
29012       for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29013       // Check if rule-3 is needed.
29014       d2 = distance(refpt, newpt);
29015       if (d2 > (L - d1)) {
29016         // Apply rule-3.
29017         if ((d1 - d2) > (0.5 * d1)) {
29018           split = (d1 - d2) / L;
29019         } else {
29020           split = 0.5 * d1 / L;
29021         }
29022         for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29023         if (b->verbose > 1) {
29024           printf("    Found by rule-3:");
29025         }
29026         r3count++;
29027       } else {
29028         if (b->verbose > 1) {
29029           printf("    Found by rule-2:");
29030         }
29031         r2count++;
29032       }
29033       if (b->verbose > 1) {
29034         printf(" center %d, split = %.12g.\n", pointmark(ei), split);
29035       }
29036       // Add a random perturbation on newpt.
29037       d1 = distance(ei, newpt);
29038       d2 = distance(newpt, refpt);
29039       ps = randgenerator(d2 * b->epsilon2 * 1e+2);
29040       rs = ps / d1;
29041       // Perturb newpt away from ei.
29042       for (i = 0; i < 3; i++) newpt[i] = ei[i] + (1.0+rs) * (newpt[i] - ei[i]);
29043     } else {
29044       // Both endpoints are acute or not. Split it at the middle.
29045       for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29046       // Add a random perturbation on newpt.
29047       d1 = 0.5 * distance(e1, e2);
29048       ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29049       rs = ps / d1;
29050       for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29051     }
29052   } else {
29053     // Split the segment at its midpoint.
29054     for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29055     // Add a random perturbation on newpt.
29056     d1 = 0.5 * distance(e1, e2);
29057     ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29058     rs = ps / d1;
29059     for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29060   }
29061 }
29062 
29064 //                                                                           //
29065 // shepardinterpolation()    Interpolate the local size of a newpoint.       //
29066 //                                                                           //
29067 // The classical Shepard interoplation (inversed weighted distance) is used. //
29068 // (With the choice p = 2).                                                  //
29069 //                                                                           //
29070 // 'verlist' contains a list vertices neighboring to 'newpt'.                //
29071 //                                                                           //
29073 
29074 void tetgenmesh::shepardinterpolate(point newpt, list *verlist)
29075 {
29076   point neipt;
29077   REAL *weights, sumweight;
29078   REAL vec[3];
29079   int i, j;
29080 
29081   weights = new REAL[verlist->len()];
29082   sumweight = 0.0;
29083 
29084   // Calculate the weight of each point.
29085   for (i = 0; i < verlist->len(); i++) {
29086     neipt = * (point *)(* verlist)[i];
29087     for (j = 0; j < 3; j++) vec[j] = neipt[j] - newpt[j];
29088     weights[i] = 1.0 / dot(vec, vec);
29089     sumweight += weights[i];
29090   }
29091   // Interpolate.
29092   newpt[pointmtrindex] = 0.0;
29093   for (i = 0; i < verlist->len(); i++) {
29094     neipt = * (point *)(* verlist)[i];
29095     newpt[pointmtrindex] += (weights[i] * neipt[pointmtrindex]) / sumweight;
29096   }
29097 
29098   delete [] weights;
29099 }
29100 
29102 //                                                                           //
29103 // setnewpointsize()    Set the size for a new point.                        //
29104 //                                                                           //
29105 // The size of the new point p is interpolated either from a background mesh //
29106 // (b->bgmesh) or from the two input endpoints.                              //
29107 //                                                                           //
29109 
29110 void tetgenmesh::setnewpointsize(point newpt, point e1, point e2)
29111 {
29112   if (b->metric) {
29113     // Interpolate the point size in a background mesh.
29114     triface bgmtet;
29115     // Get a tet in background mesh for locating p.
29116     decode(point2bgmtet(e1), bgmtet);
29117     p1interpolatebgm(newpt, &bgmtet, NULL);
29118   } else {
29119     if (e2 != (point) NULL) {
29120       // Interpolate the size between the two endpoints.
29121       REAL split, l, d;
29122       l = distance(e1, e2);
29123       d = distance(e1, newpt);
29124       split = d / l;
29125 #ifdef SELF_CHECK
29126       // Check if e1 and e2 are endpoints of a sharp segment.
29127       assert(e1[pointmtrindex] > 0.0);
29128       assert(e2[pointmtrindex] > 0.0);
29129 #endif
29130       newpt[pointmtrindex] = (1.0 - split) * e1[pointmtrindex]
29131                            + split * e2[pointmtrindex];
29132     }
29133   }
29134 }
29135 
29137 //                                                                           //
29138 // splitencseg()    Split an enc-seg and recover the Delaunayness by flips.  //
29139 //                                                                           //
29141 
29142 void tetgenmesh::splitencseg(point newpt, face* splitseg, list* tetlist,
29143   list* sublist, list* verlist, queue* flipque, bool chkencsub, bool chkbadtet,
29144   bool optflag)
29145 {
29146   list *mytetlist;
29147   queue *myflipque;
29148   triface starttet;
29149   face startsh, spinsh, checksh;
29150   int i;
29151 
29152   mytetlist = NULL;
29153   myflipque = NULL;
29154 
29155   if (optflag) {
29156     mytetlist = new list(sizeof(triface), NULL, 1024);
29157     myflipque = new queue(sizeof(badface));
29158     tetlist = mytetlist;
29159     flipque = myflipque;
29160   }
29161 
29162   // Use the base orientation (important in this routine).
29163   splitseg->shver = 0;
29164   // Insert p, this should always success.
29165   sstpivot(splitseg, &starttet);
29166   splittetedge(newpt, &starttet, flipque);
29167   // Remove locally non-Delaunay faces by flipping.
29168   flip(flipque, NULL); // lawson(NULL, flipque);
29169 
29170   if (!optflag) {
29171     // Check the two new subsegs to see if they're encroached (not by p).
29172     for (i = 0; i < 2; i++) {
29173       if (!shell2badface(*splitseg)) {
29174         checkseg4encroach(splitseg, NULL, NULL, true);
29175       }
29176       if (i == 1) break; // Two new segs have been checked.
29177       senextself(*splitseg);
29178       spivotself(*splitseg);
29179 #ifdef SELF_CHECK
29180       assert(splitseg->sh != (shellface *) NULL);
29181 #endif
29182       splitseg->shver = 0;
29183     }
29184     // Check the new subfaces to see if they're encroached (not by p).
29185     if (chkencsub) {
29186       spivot(*splitseg, startsh);
29187       spinsh = startsh;
29188       do {
29189         sublist->append(&spinsh);
29190         formstarpolygon(newpt, sublist, verlist);
29191         for (i = 0; i < sublist->len(); i++) {
29192           checksh = * (face *)(* sublist)[i];
29193           if (!shell2badface(checksh)) {
29194             checksub4encroach(&checksh, NULL, true);
29195           }
29196         }
29197         sublist->clear();
29198         if (verlist) verlist->clear();
29199         spivotself(spinsh);
29200       } while (spinsh.sh != startsh.sh);
29201     }
29202   } // if (!optflag)
29203 
29204   // Collect the new tets connecting at p.
29205   sstpivot(splitseg, &starttet);
29206   tetlist->append(&starttet);
29207   formstarpolyhedron(newpt, tetlist, verlist, true);
29208 
29209   if (!optflag) {
29210     // Check if p encroaches adjacent segments.
29211     tallencsegs(newpt, 1, &tetlist);
29212     if (chkencsub) {
29213       // Check if p encroaches adjacent subfaces.
29214       tallencsubs(newpt, 1, &tetlist);
29215     }
29216     if (chkbadtet) {
29217       // Check if there are new bad quality tets at p.
29218       for (i = 0; i < tetlist->len(); i++) {
29219         starttet = * (triface *)(* tetlist)[i];
29220         checktet4badqual(&starttet, true);
29221       }
29222     }
29223     tetlist->clear();
29224   } else {
29225     // Check if new tets are non-optimal.
29226     for (i = 0; i < tetlist->len(); i++) {
29227       starttet = * (triface *)(* tetlist)[i];
29228       checktet4opt(&starttet, true);
29229     }
29230     delete mytetlist;
29231     delete myflipque;
29232   }
29233 }
29234 
29236 //                                                                           //
29237 // tallencsegs()    Check for encroached segments and save them in list.     //
29238 //                                                                           //
29239 // If 'testpt' (p) != NULL, only check if segments are encroached by p, else,//
29240 // check all the nearby mesh vertices.                                       //
29241 //                                                                           //
29242 // If 'ceillists' (B_i(p)) != NULL, there are 'n' B_i(p)s, only check the    //
29243 // segments which are on B_i(p)s, else, check the entire list of segments    //
29244 // (in the pool 'this->subsegs').                                            //
29245 //                                                                           //
29247 
29248 bool tetgenmesh::tallencsegs(point testpt, int n, list **ceillists)
29249 {
29250   list *ceillist;
29251   triface ceiltet;
29252   face checkseg;
29253   long oldencnum;
29254   int i, j, k;
29255 
29256   // Remember the current number of encroached segments.
29257   oldencnum = badsubsegs->items;
29258 
29259   if (ceillists != (list **) NULL) {
29260     for (k = 0; k < n; k++) {
29261       ceillist = ceillists[k];
29262       // Check the segments on B_i(p).
29263       for (i = 0; i < ceillist->len(); i++) {
29264         ceiltet = * (triface *)(* ceillist)[i];
29265         ceiltet.ver = 0;
29266         for (j = 0; j < 3; j++) {
29267           tsspivot(&ceiltet, &checkseg);
29268           if (checkseg.sh != dummysh) {
29269             // Found a segment. Test it if it isn't in enc-list.
29270             if (!shell2badface(checkseg)) {
29271               checkseg4encroach(&checkseg, testpt, NULL, true);
29272             }
29273           }
29274           enextself(ceiltet);
29275         }
29276       }
29277     }
29278   } else {
29279     // Check the entire list of segments.
29280     subsegs->traversalinit();
29281     checkseg.sh = shellfacetraverse(subsegs);
29282     while (checkseg.sh != (shellface *) NULL) {
29283       // Test it if it isn't in enc-list.
29284       if (!shell2badface(checkseg)) {
29285         checkseg4encroach(&checkseg, testpt, NULL, true);
29286       }
29287       checkseg.sh = shellfacetraverse(subsegs);
29288     }
29289   }
29290 
29291   return (badsubsegs->items > oldencnum);
29292 }
29293 
29295 //                                                                           //
29296 // tallencsubs()    Find all encroached subfaces and save them in list.      //
29297 //                                                                           //
29298 // If 'testpt' (p) != NULL, only check if subfaces are encroached by p, else,//
29299 // check the adjacent vertices of subfaces.                                  //
29300 //                                                                           //
29301 // If 'ceillists' (B_i(p)) != NULL, there are 'n' B_i(p)s, only check the    //
29302 // subfaces which are on B_i(p)s, else, check the entire list of subfaces    //
29303 // (in the pool 'this->subfaces').                                           //
29304 //                                                                           //
29306 
29307 bool tetgenmesh::tallencsubs(point testpt, int n, list** ceillists)
29308 {
29309   list *ceillist;
29310   triface ceiltet;
29311   face checksh;
29312   long oldencnum;
29313   int i, k;
29314 
29315   // Remember the current number of encroached segments.
29316   oldencnum = badsubfaces->items;
29317 
29318   if (ceillists != (list **) NULL) {
29319     for (k = 0; k < n; k++) {
29320       ceillist = ceillists[k];
29321       // Check the subfaces on B_i(p).
29322       for (i = 0; i < ceillist->len(); i++) {
29323         ceiltet = * (triface *)(* ceillist)[i];
29324         tspivot(ceiltet, checksh);
29325         if (checksh.sh != dummysh) {
29326           // Found a subface. Test it if it isn't in enc-list.
29327           if (!shell2badface(checksh)) {
29328             checksub4encroach(&checksh, testpt, true);
29329           }
29330         }
29331       }
29332     }
29333   } else {
29334     // Check the entire list of subfaces.
29335     subfaces->traversalinit();
29336     checksh.sh = shellfacetraverse(subfaces);
29337     while (checksh.sh != (shellface *) NULL) {
29338       // Test it if it isn't in enc-list.
29339       if (!shell2badface(checksh)) {
29340         checksub4encroach(&checksh, testpt, true);
29341       }
29342       checksh.sh = shellfacetraverse(subfaces);
29343     }
29344   }
29345 
29346   return (badsubfaces->items > oldencnum);
29347 }
29348 
29350 //                                                                           //
29351 // tallbadtetrahedrons()    Queue all the bad-quality tetrahedra in the mesh.//
29352 //                                                                           //
29354 
29355 void tetgenmesh::tallbadtetrahedrons()
29356 {
29357   triface tetloop;
29358 
29359   tetrahedrons->traversalinit();
29360   tetloop.tet = tetrahedrontraverse();
29361   while (tetloop.tet != (tetrahedron *) NULL) {
29362     checktet4badqual(&tetloop, true);
29363     tetloop.tet = tetrahedrontraverse();
29364   }
29365 }
29366 
29368 //                                                                           //
29369 // repairencsegs()    Repair (split) all the encroached segments.            //
29370 //                                                                           //
29371 // Each encroached segment is repaired by splitting it - inserting a vertex  //
29372 // at or near its midpoint.  Newly inserted vertices may encroach upon other //
29373 // subsegments, these are also repaired.                                     //
29374 //                                                                           //
29375 // 'chkencsub' and 'chkbadtet' are two flags that specify whether one should //
29376 // take note of new encroaced subfaces and bad quality tets that result from //
29377 // inserting vertices to repair encroached subsegments.                      //
29378 //                                                                           //
29380 
29381 void tetgenmesh::repairencsegs(bool chkencsub, bool chkbadtet)
29382 {
29383   list **tetlists, **ceillists;
29384   list **sublists, **subceillists;
29385   list *tetlist, *sublist;
29386   queue *flipque;
29387   badface *encloop;
29388   face splitseg, symsplitseg;
29389   point newpt, sympt, refpt;
29390   point e1, e2;
29391   enum locateresult symloc;
29392   int nmax, n, i, j;
29393 
29394   ceillists = NULL;
29395   flipque = NULL;
29396   subceillists = NULL;
29397   sublist = NULL;
29398   sublists = NULL;
29399   tetlist = NULL;
29400   tetlists = NULL;
29401 
29402   n = 0;
29403   nmax = 128;
29404   if (!b->fliprepair) {
29405     tetlists = new list*[nmax];
29406     ceillists = new list*[nmax];
29407     sublists = new list*[nmax];
29408     subceillists = new list*[nmax];
29409   } else {
29410     tetlist = new list(sizeof(triface), NULL, 1024);
29411     sublist = new list(sizeof(face), NULL, 256);
29412     flipque = new queue(sizeof(badface));
29413   }
29414 
29415   // Loop until the pool 'badsubsegs' is empty. Note that steinerleft == -1
29416   //   if an unlimited number of Steiner points is allowed.
29417   while ((badsubsegs->items > 0) && (steinerleft != 0)) {
29418     badsubsegs->traversalinit();
29419     encloop = badfacetraverse(badsubsegs);
29420     while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
29421       // Get an encroached subsegment s.
29422       splitseg = encloop->ss;
29423       // Clear the in-queue flag in s.
29424       setshell2badface(splitseg, NULL);
29425       if ((sorg(splitseg) == encloop->forg) &&
29426           (sdest(splitseg) == encloop->fdest)) {
29427         if (b->verbose > 1) {
29428           printf("  Get an enc-seg (%d, %d)\n", pointmark(encloop->forg),
29429                  pointmark(encloop->fdest));
29430         }
29431         refpt = (point) NULL;
29432         if (b->conformdel) {
29433           // Look for a reference point.
29434           checkseg4encroach(&splitseg, NULL, &refpt, false);
29435         }
29436         // Create the new point p (at the middle of s).
29437         makepoint(&newpt);
29438         getsplitpoint(encloop->forg, encloop->fdest, refpt, newpt);
29439         setpointtype(newpt, FREESEGVERTEX);
29440         setpoint2sh(newpt, sencode(splitseg));
29441         // Decide whether p can be inserted or not.
29442         if (acceptsegpt(newpt, refpt, &splitseg)) {
29443           // Is there periodic boundary condition?
29444           if (checkpbcs) {
29445             // Insert points on other segments of incident pbcgroups.
29446             i = shellmark(splitseg) - 1;
29447             for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
29448               makepoint(&sympt);
29449               symloc = getsegpbcsympoint(newpt, &splitseg, sympt, &symsplitseg,
29450                                          segpglist[j]);
29451               if (symloc == ONEDGE) {
29452                 if (symsplitseg.sh != splitseg.sh) {
29453                   // Insert sympt.
29454                   setpointtype(sympt, FREESEGVERTEX);
29455                   setpoint2sh(sympt, sencode(symsplitseg));
29456                   // Save the endpoints of the seg for size interpolation.
29457                   e1 = sorg(symsplitseg);
29458                   if (shelltype(symsplitseg) == SHARP) {
29459                     e2 = sdest(symsplitseg);
29460                   } else {
29461                     e2 = (point) NULL; // No need to do size interpolation.
29462                   }
29463                   if (!b->fliprepair) {
29464                     // Form BC(symp), B(symp), CBC(symp)s, C(symp)s.
29465                     formbowatcavity(sympt, &symsplitseg, NULL, &n, &nmax,
29466                       sublists, subceillists, tetlists, ceillists);
29467                     // Validate BC(symp), B(symp), CBC(symp)s, C(symp)s.
29468                     if (trimbowatcavity(sympt, &symsplitseg, n, sublists,
29469                           subceillists, tetlists, ceillists, -1.0)) {
29470                       bowatinsertsite(sympt, &symsplitseg, n, sublists,
29471                         subceillists, tetlists, ceillists, NULL, flipque,
29472                         true, chkencsub, chkbadtet);
29473                       setnewpointsize(sympt, e1, e2);
29474                       if (steinerleft > 0) steinerleft--;
29475                     } else {
29476                       // p did not insert for invalid BC(symp).
29477                       pointdealloc(sympt);
29478                     }
29479                     // Free the memory allocated in formbowatcavity().
29480                     releasebowatcavity(&symsplitseg, n, sublists, subceillists,
29481                                        tetlists, ceillists);
29482                   } else {
29483                     splitencseg(sympt, &symsplitseg, tetlist, sublist, NULL,
29484                                 flipque, chkencsub, chkbadtet, false);
29485                     setnewpointsize(sympt, e1, e2);
29486                     if (steinerleft > 0) steinerleft--;
29487                   }
29488                 } else {
29489                   // The sympt are on the same segment. It is possible when
29490                   //   splitseg is the symmetric rotating axes.
29491                   pointdealloc(sympt);
29492                 }
29493               } else if (symloc == ONVERTEX) {
29494                 // The sympt already exists. It is possible when two pbc
29495                 //   groups are exactly the same. Omit this point.
29496                 pointdealloc(sympt);
29497               } else {
29498                 // Do not isnert symp for unknown cases: ONFACE, OUTSIDE.
29499                 // assert(0);
29500                 pointdealloc(sympt);
29501               }
29502             } // for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++)
29503           } // if (checkpbcs)
29504           // Save the endpoints of the seg for size interpolation.
29505           e1 = sorg(splitseg);
29506           if (shelltype(splitseg) == SHARP) {
29507             e2 = sdest(splitseg);
29508           } else {
29509             e2 = (point) NULL; // No need to do size interoplation.
29510           }
29511           if (!b->fliprepair) {
29512             // Form BC(p), B(p), CBC(p)s, and C(p)s.
29513             formbowatcavity(newpt, &splitseg, NULL, &n, &nmax, sublists,
29514                             subceillists, tetlists, ceillists);
29515             // Validate/update BC(p), B(p), CBC(p)s, and C(p)s.
29516             if (trimbowatcavity(newpt, &splitseg, n, sublists, subceillists,
29517                                 tetlists, ceillists, -1.0)) {
29518               bowatinsertsite(newpt, &splitseg, n, sublists, subceillists,
29519                               tetlists, ceillists, NULL, flipque, true,
29520                               chkencsub, chkbadtet);
29521               setnewpointsize(newpt, e1, e2);
29522               if (steinerleft > 0) steinerleft--;
29523             } else {
29524               // p did not insert for invalid B(p).
29525               pointdealloc(newpt);
29526             }
29527             // Free the memory allocated in formbowatcavity().
29528             releasebowatcavity(&splitseg, n, sublists, subceillists, tetlists,
29529                                ceillists);
29530           } else {
29531             splitencseg(newpt, &splitseg, tetlist, sublist, NULL, flipque,
29532                         chkencsub, chkbadtet, false);
29533             setnewpointsize(newpt, e1, e2);
29534             if (steinerleft > 0) steinerleft--;
29535           }
29536         } else {
29537           // p did not accept for insertion.
29538           pointdealloc(newpt);
29539         } // if (checkseg4splitting(newpt, &splitseg))
29540       } // if ((encloop->forg == pa) && (encloop->fdest == pb))
29541       badfacedealloc(badsubsegs, encloop); // Remove this entry from list.
29542       encloop = badfacetraverse(badsubsegs); // Get the next enc-segment.
29543     } // while ((encloop != (badface *) NULL) && (steinerleft != 0))
29544   } // while ((badsubsegs->items > 0) && (steinerleft != 0))
29545 
29546   if (!b->fliprepair) {
29547     delete [] tetlists;
29548     delete [] ceillists;
29549     delete [] sublists;
29550     delete [] subceillists;
29551   } else {
29552     delete tetlist;
29553     delete sublist;
29554     delete flipque;
29555   }
29556 }
29557 
29559 //                                                                           //
29560 // repairencsubs()    Repair (split) all the encroached subfaces.            //
29561 //                                                                           //
29562 // Each encroached subface is repaired by splitting it - inserting a vertex  //
29563 // at or near its circumcenter.  Newly inserted vertices may encroach upon   //
29564 // other subfaces, these are also repaired.                                  //
29565 //                                                                           //
29566 // 'chkbadtet' is a flag that specifies whether one should take note of new  //
29567 // bad quality tets that result from inserted vertices.                      //
29568 //                                                                           //
29570 
29571 void tetgenmesh::repairencsubs(bool chkbadtet)
29572 {
29573   list *tetlists[2], *ceillists[2];
29574   list *sublist, *subceillist;
29575   list *verlist;
29576   badface *encloop;
29577   face splitsub, symsplitsub;
29578   point newpt, sympt, e1;
29579   enum locateresult loc, symloc;
29580   bool reject;
29581   long oldptnum;
29582   int quenumber, n, i;
29583 
29584   quenumber = 0;
29585   n = 0;
29586   sublist = (list *) NULL;
29587   subceillist = (list *) NULL;
29588   verlist = new list(sizeof(point *), NULL, 256);
29589 
29590   // Loop until the pool 'badsubfaces' is empty. Note that steinerleft == -1
29591   //   if an unlimited number of Steiner points is allowed.
29592   while ((badsubfaces->items > 0) && (steinerleft != 0)) {
29593     // Get an encroached subface f.
29594     encloop = dequeueencsub(&quenumber);
29595     splitsub = encloop->ss;
29596     // Clear the in-queue flag of f.
29597     setshell2badface(splitsub, NULL);
29598     // f may not be the same one when it was determined to be encroached.
29599     if (!isdead(&splitsub)
29600         && (sorg(splitsub) == encloop->forg)
29601         && (sdest(splitsub) == encloop->fdest)
29602         && (sapex(splitsub) == encloop->fapex)) {
29603       if (b->verbose > 1) {
29604         printf("    Dequeuing ensub (%d, %d, %d) [%d].\n",
29605                pointmark(encloop->forg), pointmark(encloop->fdest),
29606                pointmark(encloop->fapex), quenumber);
29607       }
29608       // Create a new point p at the circumcenter of f.
29609       makepoint(&newpt);
29610       for (i = 0; i < 3; i++) newpt[i] = encloop->cent[i];
29611       setpointtype(newpt, FREESUBVERTEX);
29612       setpoint2sh(newpt, sencode(splitsub));
29613       // Set the abovepoint of f for point location.
29614       abovepoint = facetabovepointarray[shellmark(splitsub)];
29615       if (abovepoint == (point) NULL) {
29616         getfacetabovepoint(&splitsub);
29617       }
29618       // Locate p, start from f, stop at segment (1), use a tolerance to
29619       //   detect ONVERTEX or OUTSIDE case. Update f on return.
29620       loc = locatesub(newpt, &splitsub, 1, b->epsilon * 1e+2);
29621       if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29622         // Form BC(p), B(p), CBC(p) and C(p).
29623         formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29624                         &subceillist, tetlists, ceillists);
29625         // Check for encroached subsegments (on B(p)).
29626         reject = tallencsegs(newpt, 2, ceillists);
29627         // Execute point accept rule if p does not encroach upon any segment.
29628         if (!reject) {
29629           reject = !acceptfacpt(newpt, subceillist, verlist);
29630         }
29631         if (!reject) {
29632           // Validate/update cavity.
29633           reject = !trimbowatcavity(newpt, NULL, n, &sublist, &subceillist,
29634                                     tetlists, ceillists, -1.0);
29635         }
29636         if (!reject) {
29637           // CBC(p) should include s, so that s can be removed after CBC(p)
29638           //   is remeshed. However, if there are locally non-Delaunay faces
29639           //   and encroached subsegments, s may not be collected in CBC(p).
29640           //   p should not be inserted in such case.
29641           reject = !sinfected(encloop->ss);
29642         }
29643         if (!reject) {
29644           if (checkpbcs) {
29645             if (shellpbcgroup(splitsub) >= 0) {
29646               // Check for splitting of the symmetric subface of f.
29647               makepoint(&sympt);
29648               symloc = getsubpbcsympoint(newpt,&splitsub,sympt,&symsplitsub);
29649               if (symloc != ONVERTEX) {
29650                 // Release CBC(p) and BC(p) and free the memory..
29651                 releasebowatcavity(NULL, 2, &sublist, &subceillist, tetlists,
29652                                    ceillists);
29653                 // Form CBC(symp), C(symp), BC(sympt) and B(sympt).
29654                 formbowatcavity(sympt, NULL, &symsplitsub, &n, NULL, &sublist,
29655                                 &subceillist, tetlists, ceillists);
29656                 reject = tallencsegs(sympt, 2, ceillists);
29657                 if (!reject) {
29658                   reject = !acceptfacpt(sympt, subceillist, verlist);
29659                 }
29660                 if (!reject) {
29661                   reject = !trimbowatcavity(sympt,NULL,n,&sublist,&subceillist,
29662                                             tetlists, ceillists, -1.0);
29663                 }
29664                 if (!reject) {
29665                   // Insert sympt.
29666                   setpoint2pbcpt(newpt, sympt);
29667                   setpoint2pbcpt(sympt, newpt);
29668                   setpointtype(sympt, FREESUBVERTEX);
29669                   setpoint2sh(sympt, sencode(symsplitsub));
29670                   // Save a point for size interpolation.
29671                   e1 = sorg(symsplitsub);
29672                   bowatinsertsite(sympt, NULL, n, &sublist, &subceillist,
29673                      tetlists,ceillists,NULL,NULL,false,true,chkbadtet);
29674                   setnewpointsize(sympt, e1, NULL);
29675                   if (steinerleft > 0) steinerleft--;
29676                   // Release CBC(symp) and BC(symp) and free the memory..
29677                   releasebowatcavity(NULL, n, &sublist, &subceillist, tetlists,
29678                                      ceillists);
29679                 } else {
29680                   // symp is rejected for one of the following reasons:
29681                   //   (1) BC(symp) is not valid; or
29682                   //   (2) symp encroaches upon some subsegments (queued); or
29683                   //   (3) symp is rejected by point accepting rule.
29684                   pointdealloc(sympt);
29685                   // Cavity will be released by the following code.
29686                 }
29687               } else {
29688                 // Do not insert sympt for invalid PBC data.
29689                 pointdealloc(sympt);
29690                 // p is rejected due to symp.
29691                 reject = true;
29692               }
29693             }
29694           } // if (checkpbcs)
29695         }
29696         if (!reject) {
29697           // Insert p.
29698           if (checkpbcs) {
29699             if (shellpbcgroup(splitsub) >= 0) {
29700               // Form CBC(p), C(p), BC(p) and B(p).
29701               formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29702                               &subceillist, tetlists, ceillists);
29703               trimbowatcavity(newpt, NULL, n, &sublist, &subceillist, tetlists,
29704                               ceillists, -1.0);
29705             }
29706           }
29707           // Save a point for size interpolation.
29708           e1 = sorg(splitsub);
29709           bowatinsertsite(newpt, NULL, n, &sublist, &subceillist, tetlists,
29710                           ceillists, NULL, NULL, true, true, chkbadtet);
29711           setnewpointsize(newpt, e1, NULL);
29712           if (steinerleft > 0) steinerleft--;
29713         } else {
29714           // p is rejected for the one of the following reasons:
29715           //   (1) BC(p) is not valid.
29716           //   (2) s does not in CBC(p).
29717           //   (3) p encroaches upon some segments (queued); or
29718           //   (4) p is rejected by point accepting rule, or
29719           //   (5) due to the rejection of symp (the PBC).
29720           pointdealloc(newpt);
29721         } // if (!reject)
29722         // Release the cavity and free the memory.
29723         releasebowatcavity(NULL,n,&sublist,&subceillist,tetlists,ceillists);
29724         if (reject) {
29725           // Are there queued encroached subsegments.
29726           if (badsubsegs->items > 0) {
29727             // Repair enc-subsegments.
29728             oldptnum = points->items;
29729             repairencsegs(true, chkbadtet);
29730             if (points->items > oldptnum) {
29731               // Some enc-subsegments got split. Try to repair f later.
29732               splitsub = encloop->ss;
29733               if (!isdead(&splitsub)) {
29734                 if (!shell2badface(splitsub)) {
29735                   checksub4encroach(&splitsub, NULL, true);
29736                 }
29737               }
29738             }
29739           }
29740         }
29741       } else {
29742         // Don't insert p for one of the following reasons:
29743         //   (1) Locate on an existing vertex; or
29744         //   (2) locate outside the domain.
29745         // Case (1) should not be possible. If such vertex v exists, it is
29746         //   the circumcenter of f, ie., f is non-Delaunay. Either f was got
29747         //   split before by v, but survived after v was inserted, or the
29748         //   same for a f' which is nearly co-circular with f.  Whatsoever,
29749         //   there are encroached segs by v, but the routine tallencsegs()
29750         //   did not find them out.
29751         if (loc == ONVERTEX) {
29752           printf("Internal error in repairencsubs():\n");
29753           printf("  During repairing encroached subface (%d, %d, %d)\n",
29754                  pointmark(encloop->forg), pointmark(encloop->fdest),
29755                  pointmark(encloop->fapex));
29756           printf("  New point %d is coincident with an existing vertex %d\n",
29757                  pointmark(newpt), pointmark(sorg(splitsub)));
29758           internalerror();
29759         }
29760         // Case (2) can happen when thers is a segment s which is close to f
29761         //   and is non-conforming Delaunay. The circumcenter of f encroaches
29762         //   upon s, but the circumcenter of s is rejected for insertion.
29763         pointdealloc(newpt);
29764       } // if ((loc != ONVERTEX) && (loc != OUTSIDE))
29765     } else {
29766       if (!isdead(&splitsub)) {
29767         // The subface has been changed, re-check it.
29768         checksub4encroach(&splitsub, NULL, true);
29769       }
29770     } // if (!isdead(&splitsub) && (sorg(splitsub) == encloop->forg) &&
29771     // Remove this entry from list.
29772     badfacedealloc(badsubfaces, encloop);
29773   } // while ((badsubfaces->items > 0) && (steinerleft != 0))
29774 
29775   delete verlist;
29776 }
29777 
29779 //                                                                           //
29780 // repairbadtets()    Repair all bad-quality tetrahedra.                     //
29781 //                                                                           //
29782 // All bad-quality tets are stored in pool 'badtetrahedrons'.  Each bad tet  //
29783 // is repaired by inserting a point at or near its circumcenter. However, if //
29784 // this point encroaches any subsegment or subface, it is not inserted. Ins- //
29785 // tead the encroached segment and subface are split.  Newly inserted points //
29786 // may create other bad-quality tets, these are also repaired.               //
29787 //                                                                           //
29789 
29790 void tetgenmesh::repairbadtets()
29791 {
29792   list *tetlist, *ceillist;
29793   list *verlist;
29794   badface *badtet;
29795   triface starttet;
29796   point newpt, e1;
29797   enum locateresult loc;
29798   bool reject;
29799   long oldptnum;
29800   int i;
29801 
29802   tetlist = new list(sizeof(triface), NULL, 1024);
29803   ceillist = new list(sizeof(triface), NULL, 1024);
29804   verlist = new list(sizeof(point *), NULL, 256);
29805 
29806   // Loop until pool 'badtetrahedrons' is empty. Note that steinerleft == -1
29807   //   if an unlimited number of Steiner points is allowed.
29808   while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
29809     // Get a bad-quality tet t.
29810     badtet = topbadtetra();
29811     // Make sure that the tet is still the same one when it was tested.
29812     //   Subsequent transformations may have made it a different tet.
29813     if ((badtet != (badface *) NULL) && !isdead(&badtet->tt)
29814          && org(badtet->tt) == badtet->forg
29815          && dest(badtet->tt) == badtet->fdest
29816          && apex(badtet->tt) == badtet->fapex
29817          && oppo(badtet->tt) == badtet->foppo) {
29818       if (b->verbose > 1) {
29819         printf("    Dequeuing btet (%d, %d, %d, %d).\n",
29820                pointmark(badtet->forg), pointmark(badtet->fdest),
29821                pointmark(badtet->fapex), pointmark(badtet->foppo));
29822       }
29823       // Create the new point p (at the circumcenter of t).
29824       makepoint(&newpt);
29825       for (i = 0; i < 3; i++) newpt[i] = badtet->cent[i];
29826       setpointtype(newpt, FREEVOLVERTEX);
29827       // Locate p.
29828       starttet = badtet->tt;
29829       loc = preciselocate(newpt, &starttet, tetrahedrons->items);
29830       if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29831         // For BC(p) and B(p).
29832         infect(starttet);
29833         tetlist->append(&starttet);
29834         formbowatcavityquad(newpt, tetlist, ceillist);
29835         // Check for encroached subsegments.
29836         reject = tallencsegs(newpt, 1, &ceillist);
29837         if (!reject) {
29838           // Check for encroached subfaces.
29839           reject = tallencsubs(newpt, 1, &ceillist);
29840         }
29841         // Execute point accepting rule if p does not encroach upon any
29842         //   subsegment and subface.
29843         if (!reject) {
29844           reject = !acceptvolpt(newpt, ceillist, verlist);
29845         }
29846         if (!reject) {
29847           reject = !trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist,
29848                                     &ceillist, -1.0);
29849         }
29850         if (!reject) {
29851           // BC(p) should include t, so that t can be removed after BC(p) is
29852           //   remeshed. However, if there are locally non-Delaunay faces
29853           //   and encroached subsegments/subfaces, t may not be collected
29854           //   in BC(p). p should not be inserted in such case.
29855           reject = !infected(badtet->tt);
29856           if (reject) outbowatcircumcount++;
29857         }
29858         if (!reject) {
29859           // Save a point for size interpolation.
29860           e1 = org(starttet);
29861           // Insert p.
29862           bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist,
29863                           NULL, NULL, false, false, true);
29864           setnewpointsize(newpt, e1, NULL);
29865           if (steinerleft > 0) steinerleft--;
29866         } else {
29867           // p is rejected for one of the following reasons:
29868           //   (1) BC(p) is not valid.
29869           //   (2) t does not in BC(p).
29870           //   (3) p encroaches upon some segments;
29871           //   (4) p encroaches upon some subfaces;
29872           //   (5) p is rejected by the point accepting rule.
29873           pointdealloc(newpt);
29874           // Uninfect tets of BC(p).
29875           for (i = 0; i < tetlist->len(); i++) {
29876             starttet = * (triface *)(* tetlist)[i];
29877             uninfect(starttet);
29878           }
29879         }
29880         tetlist->clear();
29881         ceillist->clear();
29882         // Split encroached subsegments/subfaces if there are.
29883         if (reject) {
29884           oldptnum = points->items;
29885           if (badsubsegs->items > 0) {
29886             repairencsegs(true, true);
29887           }
29888           if (badsubfaces->items > 0) {
29889             repairencsubs(true);
29890           }
29891           if (points->items > oldptnum) {
29892             // Some encroaching subsegments/subfaces got split. Re-queue the
29893             //   tet if it is still alive.
29894             starttet = badtet->tt;
29895             if (!isdead(&starttet)) {
29896               checktet4badqual(&starttet, true);
29897             }
29898           }
29899         }
29900       } else {
29901         // Do not insert p. The reason may be one of:
29902         //   (1) p is coincident (ONVERTEX) with an existing vertex; or
29903         //   (2) p is outside (OUTSIDE) the mesh.
29904         // Case (1) should not be possible. If such vertex v exists, it is
29905         //   the circumcenter of t, ie., t is non-Delaunay. Either t was got
29906         //   split before by v, but survived after v was inserted, or the
29907         //   same for a t' which is nearly co-spherical with t.  Whatsoever,
29908         //   there are encroached segments or subfaces by v but the routines
29909         //   tallencsegs() or tallencsubs() did not find them out.
29910         if (loc == ONVERTEX) {
29911           printf("Internal error in repairbadtets():\n");
29912           printf("  During repairing bad tet (%d, %d, %d, %d)\n",
29913                  pointmark(badtet->forg), pointmark(badtet->fdest),
29914                  pointmark(badtet->fapex), pointmark(badtet->foppo));
29915           printf("  New point %d is coincident with an existing vertex %d\n",
29916                  pointmark(newpt), pointmark(org(starttet)));
29917           internalerror();
29918         }
29919         // Case (2) can happen when there is a segment s (or subface f) which
29920         //   is close to f and is non-conforming Delaunay.  The circumcenter
29921         //   of t encroaches upon s (or f), but the circumcenter of s (or f)
29922         //   is rejected for insertion.
29923         pointdealloc(newpt);
29924       } // if ((loc != ONVERTEX) && (loc != OUTSIDE))
29925     } // if (!isdead(&badtet->tt) && org(badtet->tt) == badtet->forg &&
29926     // Remove the tet from the queue.
29927     dequeuebadtet();
29928   } // while ((badtetrahedrons->items > 0) && (steinerleft != 0))
29929 
29930   delete tetlist;
29931   delete ceillist;
29932   delete verlist;
29933 }
29934 
29936 //                                                                           //
29937 // enforcequality()    Refine the mesh.                                      //
29938 //                                                                           //
29940 
29941 void tetgenmesh::enforcequality()
29942 {
29943   long total, vertcount;
29944   int i;
29945 
29946   if (!b->quiet) {
29947     printf("Adding Steiner points to enforce quality.\n");
29948   }
29949 
29950   total = vertcount = 0l;
29951   if (b->conformdel) {
29952     r2count = r3count = 0l;
29953   }
29954 
29955   // If both '-D' and '-r' options are used.
29956   if (b->conformdel && b->refine) {
29957     markacutevertices(65.0);
29958   }
29959   // If '-m' is not used.
29960   if (!b->metric) {
29961     // Find and mark all sharp segments.
29962     marksharpsegments(65.0);
29963     // Decide the sizes for feature points.
29964     decidefeaturepointsizes();
29965   }
29966 
29967   // Initialize the pool of encroached subsegments.
29968   badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29969   // Looking for encroached subsegments.
29970   tallencsegs(NULL, 0, NULL);
29971   if (b->verbose && badsubsegs->items > 0) {
29972     printf("  Splitting encroached subsegments.\n");
29973   }
29974   vertcount = points->items;
29975   // Fix encroached segments without noting any enc subfaces.
29976   repairencsegs(false, false);
29977   if (b->verbose > 0) {
29978     printf("  %ld split points.\n", points->items - vertcount);
29979   }
29980   total += points->items - vertcount;
29981 
29982   // Initialize the pool of encroached subfaces.
29983   badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29984   // Initialize the priority queues of badfaces.
29985   for (i = 0; i < 3; i++) subquefront[i] = (badface *) NULL;
29986   for (i = 0; i < 3; i++) subquetail[i] = &subquefront[i];
29987   // Looking for encroached subfaces.
29988   tallencsubs(NULL, 0, NULL);
29989   if (b->verbose && badsubfaces->items > 0) {
29990     printf("  Splitting encroached subfaces.\n");
29991   }
29992   vertcount = points->items;
29993   // Fix encroached subfaces without noting bad tetrahedra.
29994   repairencsubs(false);
29995   if (b->verbose > 0) {
29996     printf("  %ld split points.\n", points->items - vertcount);
29997   }
29998   total += points->items - vertcount;
29999   // At this point, the mesh should be conforming Delaunay if no input
30000   //   angle is smaller than 90 degree.
30001 
30002   // Next, fix bad quality tetrahedra.
30003   if ((b->minratio > 0.0) || b->varvolume || b->fixedvolume) {
30004     // Initialize the pool of bad tets
30005     badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30006     // Initialize the priority queues of bad tets.
30007     for (i = 0; i < 64; i++) tetquefront[i] = (badface *) NULL;
30008     firstnonemptyq = -1;
30009     recentq = -1;
30010     // Looking for bad quality tets.
30011     cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30012     cosmindihed = cos(b->mindihedral * PI / 180.0);
30013     tallbadtetrahedrons();
30014     if (b->verbose && badtetrahedrons->items > 0) {
30015       printf("  Splitting bad tetrahedra.\n");
30016     }
30017     vertcount = points->items;
30018     repairbadtets();
30019     if (b->verbose > 0) {
30020       printf("  %ld refinement points.\n", points->items - vertcount);
30021     }
30022     total += points->items - vertcount;
30023     delete badtetrahedrons;
30024   }
30025 
30026   if (b->verbose > 0) {
30027     printf("  Totally added %ld points.\n", total);
30028   }
30029 
30030   delete badsubfaces;
30031   delete badsubsegs;
30032 }
30033 
30034 //
30035 // End of Delaunay refinement routines
30036 //
30037 
30038 //
30039 // Begin of mesh optimization routines
30040 //
30041 
30042 void tetgenmesh::dumpbadtets()
30043 {
30044   FILE *fout;
30045   badface *remtet;
30046 
30047   // Write out a file of remaining bad tets.
30048   printf("  Writing bad tets to file bad-dump.lua.\n");
30049   fout = fopen("bad-dump.lua", "w");
30050   fprintf(fout, "-- %ld remaining bad tets (> %g degree).\n",
30051           badtetrahedrons->items, b->maxdihedral);
30052   badtetrahedrons->traversalinit();
30053   remtet = badfacetraverse(badtetrahedrons);
30054   while (remtet != (badface *) NULL) {
30055     if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30056         dest(remtet->tt) == remtet->fdest &&
30057         apex(remtet->tt) == remtet->fapex &&
30058         oppo(remtet->tt) == remtet->foppo) {
30059       fprintf(fout, "p:draw_tet(%d, %d, %d, %d) -- %g\n",
30060               pointmark(remtet->forg), pointmark(remtet->fdest),
30061               pointmark(remtet->fapex), pointmark(remtet->foppo),
30062               acos(remtet->key) * 180.0 / PI);
30063     }
30064     remtet = badfacetraverse(badtetrahedrons);
30065   }
30066   fclose(fout);
30067 }
30068 
30070 //                                                                           //
30071 // checktet4ill()    Check a tet to see if it is illegal.                    //
30072 //                                                                           //
30073 // A tet is "illegal" if it spans on one input facet.  Save the tet in queue //
30074 // if it is illegal and the flag 'enqflag' is set.                           //
30075 //                                                                           //
30076 // Note: Such case can happen when the input facet has non-coplanar vertices //
30077 // and the Delaunay tetrahedralization of the vertices may creat such tets.  //
30078 //                                                                           //
30080 
30081 bool tetgenmesh::checktet4ill(triface* testtet, bool enqflag)
30082 {
30083   badface *newbadtet;
30084   triface checktet;
30085   face checksh1, checksh2;
30086   face checkseg;
30087   bool illflag;
30088   int i;
30089 
30090   illflag = false;
30091   for (testtet->loc = 0; testtet->loc < 4; testtet->loc++) {
30092     tspivot(*testtet, checksh1);
30093     if (checksh1.sh != dummysh) {
30094       testtet->ver = 0;
30095       findedge(&checksh1, org(*testtet), dest(*testtet));
30096       for (i = 0; i < 3; i++) {
30097         fnext(*testtet, checktet);
30098         tspivot(checktet, checksh2);
30099         if (checksh2.sh != dummysh) {
30100           // Two subfaces share this edge.
30101           sspivot(checksh1, checkseg);
30102           if (checkseg.sh == dummysh) {
30103             // The four corners of the tet are on one facet. Illegal! Try to
30104             //   flip the opposite edge of the current one.
30105             enextfnextself(*testtet);
30106             enextself(*testtet);
30107             illflag = true;
30108             break;
30109           }
30110         }
30111         enextself(*testtet);
30112         senextself(checksh1);
30113       }
30114     }
30115     if (illflag) break;
30116   }
30117 
30118   if (illflag && enqflag) {
30119     // Allocate space for the bad tetrahedron.
30120     newbadtet = (badface *) badtetrahedrons->alloc();
30121     newbadtet->tt = *testtet;
30122     newbadtet->key = -1.0; // = 180 degree.
30123     for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
30124     newbadtet->forg = org(*testtet);
30125     newbadtet->fdest = dest(*testtet);
30126     newbadtet->fapex = apex(*testtet);
30127     newbadtet->foppo = oppo(*testtet);
30128     newbadtet->nextitem = (badface *) NULL;
30129     if (b->verbose > 2) {
30130       printf("    Queueing illtet: (%d, %d, %d, %d).\n",
30131              pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30132              pointmark(newbadtet->fapex), pointmark(newbadtet->foppo));
30133     }
30134   }
30135 
30136   return illflag;
30137 }
30138 
30140 //                                                                           //
30141 // checktet4opt()    Check a tet to see if it needs to be optimized.         //
30142 //                                                                           //
30143 // A tet t needs to be optimized if it fails to certain quality measures.    //
30144 // The only quality measure currently used is the maximal dihedral angle at  //
30145 // edges. The desired maximal dihedral angle is b->maxdihed (set by the '-s' //
30146 // option.                                                                   //
30147 //                                                                           //
30148 // A tet may have one, two, or three big dihedral angles. Examples: Let the  //
30149 // tet t = abcd, and its four corners are nearly co-planar. Then t has one   //
30150 // big dihedral angle if d is very close to the edge ab; t has three big     //
30151 // dihedral angles if d's projection on the face abc is also inside abc, i.e.//
30152 // the shape of t likes a hat; finally, t has two big dihedral angles if d's //
30153 // projection onto abc is outside abc.                                       //
30154 //                                                                           //
30156 
30157 bool tetgenmesh::checktet4opt(triface* testtet, bool enqflag)
30158 {
30159   badface *newbadtet;
30160   point pa, pb, pc, pd;
30161   REAL N[4][3], len;
30162   REAL cosd;
30163   bool enq;
30164   int i, j;
30165 
30166   cosd = 0.0;
30167   enq = false;
30168   pa = (point) testtet->tet[4];
30169   pb = (point) testtet->tet[5];
30170   pc = (point) testtet->tet[6];
30171   pd = (point) testtet->tet[7];
30172   // Compute the 4 face normals: N[0] cbd, N[1] acd, N[2] bad, N[3] abc.
30173   tetallnormal(pa, pb, pc, pd, N, NULL);
30174   // Normalize the normals.
30175   for (i = 0; i < 4; i++) {
30176     len = sqrt(dot(N[i], N[i]));
30177     if (len != 0.0) {
30178       for (j = 0; j < 3; j++) N[i][j] /= len;
30179     }
30180   }
30181   // Find all large dihedral angles.
30182   for (i = 0; i < 6; i++) {
30183     // Locate the edge i and calculate the dihedral angle at the edge.
30184     testtet->loc = 0;
30185     testtet->ver = 0;
30186     switch (i) {
30187     case 0: // edge ab
30188       cosd = -dot(N[2], N[3]);
30189       break;
30190     case 1: // edge cd
30191       enextfnextself(*testtet);
30192       enextself(*testtet);
30193       cosd = -dot(N[0], N[1]);
30194       break;
30195     case 2: // edge bd
30196       enextfnextself(*testtet);
30197       enext2self(*testtet);
30198       cosd = -dot(N[0], N[2]);
30199       break;
30200     case 3: // edge bc
30201       enextself(*testtet);
30202       cosd = -dot(N[0], N[3]);
30203       break;
30204     case 4: // edge ad
30205       enext2fnextself(*testtet);
30206       enextself(*testtet);
30207       cosd = -dot(N[1], N[2]);
30208       break;
30209     case 5: // edge ac
30210       enext2self(*testtet);
30211       cosd = -dot(N[1], N[3]);
30212       break;
30213     }
30214     if (cosd < cosmaxdihed) {
30215       // A bigger dihedral angle.
30216       if (enqflag) {
30217         // Allocate space for the bad tetrahedron.
30218         newbadtet = (badface *) badtetrahedrons->alloc();
30219         newbadtet->tt = *testtet;
30220         newbadtet->key = cosd;
30221         for (j = 0; j < 3; j++) newbadtet->cent[j] = 0.0;
30222         newbadtet->forg = org(*testtet);
30223         newbadtet->fdest = dest(*testtet);
30224         newbadtet->fapex = apex(*testtet);
30225         newbadtet->foppo = oppo(*testtet);
30226         newbadtet->nextitem = (badface *) NULL;
30227         if (b->verbose > 2) {
30228           printf("    Queueing tet: (%d, %d, %d, %d), dihed %g (degree).\n",
30229                  pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30230                  pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
30231                  acos(cosd) * 180.0 / PI);
30232         }
30233       }
30234       enq = true;
30235     }
30236   }
30237 
30238   return enq;
30239 }
30240 
30242 //                                                                           //
30243 // removeedge()    Remove an edge                                            //
30244 //                                                                           //
30245 // 'remedge' is a tet (abcd) having the edge ab wanted to be removed.  Local //
30246 // reconnecting operations are used to remove edge ab.  The following opera- //
30247 // tion will be tryed.                                                       //
30248 //                                                                           //
30249 // If ab is on the hull, and abc and abd are both hull faces. Then ab can be //
30250 // removed by stripping abcd from the mesh. However, if ab is a segemnt, do  //
30251 // the operation only if 'b->optlevel' > 1 and 'b->nobisect == 0'.           //
30252 //                                                                           //
30253 // If ab is an internal edge, there are n tets contains it.  Then ab can be  //
30254 // removed if there exists another m tets which can replace the n tets with- //
30255 // out changing the boundary of the n tets.                                  //
30256 //                                                                           //
30257 // If 'optflag' is set.  The value 'remedge->key' means cos(theta), where    //
30258 // 'theta' is the maximal dishedral angle at ab. In this case, even if the   //
30259 // n-to-m flip exists, it will not be performed if the maximum dihedral of   //
30260 // the new tets is larger than 'theta'.                                      //
30261 //                                                                           //
30263 
30264 bool tetgenmesh::removeedge(badface* remedge, bool optflag)
30265 {
30266   triface abcd, badc;  // Tet configuration at edge ab.
30267   triface baccasing, abdcasing;
30268   triface abtetlist[11];  // Old configuration at ab, save maximum 10 tets.
30269   triface bftetlist[11];  // Old configuration at bf, save maximum 10 tets.
30270   triface newtetlist[33]; // New configuration after removing ab.
30271   face checksh;
30272   enum fliptype fty;
30273   REAL key;
30274   bool remflag, subflag;
30275   int n, n1, m, i, j;
30276 
30277   // First try to strip abcd from the mesh. This needs to check either ab
30278   //   or cd is on the hull. Try to strip it whichever is true.
30279   abcd = remedge->tt;
30280   adjustedgering(abcd, CCW);
30281   i = 0;
30282   do {
30283     sym(abcd, baccasing);
30284     // Is the tet on the hull?
30285     if (baccasing.tet == dummytet) {
30286       fnext(abcd, badc);
30287       sym(badc, abdcasing);
30288       if (abdcasing.tet == dummytet) {
30289         // Strip the tet from the mesh -> ab is removed as well.
30290         if (removetetbypeeloff(&abcd)) {
30291           if (b->verbose > 1) {
30292             printf("    Stripped tet from the mesh.\n");
30293           }
30294           optcount[0]++;
30295           return true;
30296         }
30297       }
30298     }
30299     // Check if the oppsite edge cd is on the hull.
30300     enext2fnextself(abcd);
30301     enext2self(abcd);
30302     esymself(abcd); // --> cdab
30303     i++;
30304   } while (i < 2);
30305 
30306   // Get the tets configuration at ab. Collect maximum 10 tets.
30307   subflag = false;
30308   abcd = remedge->tt;
30309   adjustedgering(abcd, CW);
30310   n = 0;
30311   abtetlist[n] = abcd;
30312   do {
30313     // Is the list full?
30314     if (n == 10) break;
30315     // Stop if a subface appears.
30316     tspivot(abtetlist[n], checksh);
30317     if (checksh.sh != dummysh) {
30318       // ab is either a segment or a facet edge. The latter case is not
30319       //   handled yet! An edge flip is needed.
30320       subflag = true; break; // return false;
30321     }
30322     // Get the next tet at ab.
30323     fnext(abtetlist[n], abtetlist[n + 1]);
30324     n++;
30325   } while (apex(abtetlist[n]) != apex(abcd));
30326 
30327   remflag = false;
30328   key = remedge->key;
30329 
30330   if (subflag && optflag) {
30331     abcd = remedge->tt;
30332     adjustedgering(abcd, CCW);
30333     // Try to flip face cda or cdb to improve quality.
30334     for (j = 0; j < 2; j++) {
30335       if (j == 0) {
30336         enext2fnext(abcd, abtetlist[0]); // Goto cda.
30337       } else {
30338         enextfnext(abcd, abtetlist[0]); // Goto cdb.
30339       }
30340       fty = categorizeface(abtetlist[0]);
30341       if (fty == T23) {
30342         // A 2-to-3 flip is possible.
30343         sym(abtetlist[0], abtetlist[1]);
30344         assert(abtetlist[1].tet != dummytet);
30345         n = 2;
30346         m = 3;
30347         remflag = removefacebyflip23(&key, abtetlist, newtetlist, NULL);
30348       } else if (fty == T22) {
30349         // A 2-to-2 or 4-to-4 flip is possible.
30350         n = 2;
30351         newtetlist[0] = abtetlist[0];
30352         adjustedgering(newtetlist[0], CW);
30353         fnext(newtetlist[0], newtetlist[1]);
30354         assert(newtetlist[1].tet != dummytet);
30355         // May it is 4-to-4 flip.
30356         if (fnext(newtetlist[1], newtetlist[2])) {
30357           fnext(newtetlist[2], newtetlist[3]);
30358           assert(newtetlist[3].tet != dummytet);
30359           n = 4;
30360         }
30361         m = n;
30362         remflag = removeedgebyflip22(&key, n, newtetlist, NULL);
30363       }
30364       // Has quality been improved?
30365       if (remflag) {
30366         if (b->verbose > 1) {
30367           printf("  Done flip %d-to-%d. Qual: %g -> %g.\n", n, m,
30368                  acos(remedge->key) / PI * 180.0, acos(key) / PI * 180.0);
30369         }
30370         // Delete the old tets. Note, flip22() does not create new tets.
30371         if (m == 3) {
30372           for (i = 0; i < n; i++) {
30373             tetrahedrondealloc(abtetlist[i].tet);
30374           }
30375         }
30376         for (i = 0; i < m; i++) {
30377           checktet4opt(&(newtetlist[i]), true);
30378         }
30379         optcount[1]++;
30380         return true;
30381       }
30382     } // if (j = 0; j < 2; j++)
30383     // Faces are not flipable. Return.
30384     return false;
30385   }
30386 
30387   // 2 <= n <= 10.
30388   if (n == 3) {
30389     // There are three tets at ab. Try to do a flip32 at ab.
30390     remflag = removeedgebyflip32(&key, abtetlist, newtetlist, NULL);
30391   } else if ((n == 4) || (n == 5) || (n == 6)) {
30392     // Four tets case. Try to do edge transformation.
30393     remflag = removeedgebytranNM(&key,n,abtetlist,newtetlist,NULL,NULL,NULL);
30394   } else {
30395     if (b->verbose > 1) {
30396       printf("  !! Unhandled case: n = %d.\n", n);
30397     }
30398   }
30399   if (remflag) {
30400     optcount[n]++;
30401     // Delete the old tets.
30402     for (i = 0; i < n; i++) {
30403       tetrahedrondealloc(abtetlist[i].tet);
30404     }
30405     m = (n - 2) * 2; // The numebr of new tets.
30406     if (b->verbose > 1) {
30407       printf("  Done flip %d-to-%d. ", n, m);
30408       if (optflag) {
30409         printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30410                acos(key) / PI * 180.0);
30411       }
30412       printf("\n");
30413     }
30414   }
30415 
30416   if (!remflag && (key == remedge->key) && (n < 7)) {
30417     // Try to do a combination of flips.
30418     n1 = 0;
30419     remflag = removeedgebycombNM(&key, n, abtetlist, &n1, bftetlist,
30420       newtetlist, NULL);
30421     if (remflag) {
30422       optcount[9]++;
30423       // Delete the old tets.
30424       for (i = 0; i < n; i++) {
30425         tetrahedrondealloc(abtetlist[i].tet);
30426       }
30427       for (i = 0; i < n1; i++) {
30428         if (!isdead(&(bftetlist[i]))) {
30429           tetrahedrondealloc(bftetlist[i].tet);
30430         }
30431       }
30432       m = ((n1 - 2) * 2 - 1) + (n - 3) * 2; // The number of new tets.
30433       if (b->verbose > 1) {
30434         printf("  Done flip %d-to-%d (n-1=%d, n1=%d). ", n+n1-2, m, n-1,n1);
30435         if (optflag) {
30436           printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30437                acos(key) / PI * 180.0);
30438         }
30439         printf("\n");
30440       }
30441     }
30442   }
30443 
30444   if (remflag) {
30445     // edge is removed. Test new tets for further optimization.
30446     for (i = 0; i < m; i++) {
30447       if (optflag) {
30448         checktet4opt(&(newtetlist[i]), true);
30449       } else {
30450         checktet4ill(&(newtetlist[i]), true);
30451       }
30452     }
30453   }
30454 
30455   return remflag;
30456 }
30457 
30459 //                                                                           //
30460 // smoothsliver()    Remove a sliver by smoothing a vertex of it.            //
30461 //                                                                           //
30462 // The 'slivtet' represents a sliver abcd, and ab is the current edge which  //
30463 // has a large dihedral angle (close to 180 degree).                         //
30464 //                                                                           //
30466 
30467 bool tetgenmesh::smoothsliver(badface* remedge, list *starlist)
30468 {
30469   triface checktet;
30470   point smthpt;
30471   bool smthed;
30472   int idx, i, j;
30473 
30474   // Find a Steiner volume point and smooth it.
30475   smthed = false;
30476   for (i = 0; i < 4 && !smthed; i++) {
30477     smthpt = (point) remedge->tt.tet[4 + i];
30478     // Is it a volume point?
30479     if (pointtype(smthpt) == FREEVOLVERTEX) {
30480       // Is it a Steiner point?
30481       idx = pointmark(smthpt) - in->firstnumber;
30482       if (!(idx < in->numberofpoints)) {
30483         // Smooth a Steiner volume point.
30484         starlist->append(&(remedge->tt.tet));
30485         formstarpolyhedron(smthpt, starlist, NULL, false);
30486         smthed = smoothpoint(smthpt,NULL,NULL,starlist,false,&remedge->key);
30487         // If it is smoothed. Queue new bad tets.
30488         if (smthed) {
30489           for (j = 0; j < starlist->len(); j++) {
30490             checktet = * (triface *)(* starlist)[j];
30491             checktet4opt(&checktet, true);
30492           }
30493         }
30494         starlist->clear();
30495       }
30496     }
30497   }
30498 
30499   /* Omit to smooth segment points. This may cause infinite loop.
30500   if (smthed) {
30501     return true;
30502   }
30503   face abseg, nextseg, prevseg;
30504   point pt[2];
30505   // Check if ab is a segment.
30506   tsspivot(slivtet, &abseg);
30507   if (abseg.sh == dummysh) {
30508     // ab is not a segment. Check if a or b is a Steiner segment point.
30509     for (i = 0; i < 2 && !smthed; i++) {
30510       smthpt = (i == 0 ? org(*slivtet) : dest(*slivtet));
30511       if (pointtype(smthpt) == FREESEGVERTEX) {
30512         // Is it a Steiner point?
30513         idx = pointmark(smthpt) - in->firstnumber;
30514         if (!(idx < in->numberofpoints)) {
30515           // Smooth a Steiner segment point. Get the segment.
30516           sdecode(point2sh(smthpt), nextseg);
30517           locateseg(smthpt, &nextseg);
30518           assert(sorg(nextseg) == smthpt);
30519           pt[0] = sdest(nextseg);
30520           senext2(nextseg, prevseg);
30521           spivotself(prevseg);
30522           prevseg.shver = 0;
30523           if (sorg(prevseg) == smthpt) sesymself(prevseg);
30524           assert(sdest(prevseg) == smthpt);
30525           pt[1] = sorg(prevseg);
30526           starlist->append(slivtet);
30527           formstarpolyhedron(smthpt, starlist, NULL, true);
30528           smthed = smoothpoint(smthpt, pt[0], pt[1], starlist, false);
30529           // If it is smoothed. Check if the tet is still a sliver.
30530           if (smthed) checktet4opt(slivtet, true);
30531           starlist->clear();
30532         }
30533       }
30534     }
30535   }
30536   */
30537 
30538   return smthed;
30539 }
30540 
30542 //                                                                           //
30543 // splitsliver()    Remove a sliver by inserting a point.                    //
30544 //                                                                           //
30545 // The 'remedge->tt' represents a sliver abcd, ab is the current edge which  //
30546 // has a large dihedral angle (close to 180 degree).                         //
30547 //                                                                           //
30549 
30550 bool tetgenmesh::splitsliver(badface *remedge, list *tetlist, list *ceillist)
30551 {
30552   triface starttet;
30553   face checkseg;
30554   point newpt, pt[4];
30555   bool remflag;
30556   int i;
30557 
30558   starttet = remedge->tt;
30559 
30560   // Check if cd is a segment.
30561   adjustedgering(starttet, CCW);
30562   enextfnextself(starttet);
30563   enextself(starttet);
30564   tsspivot(&starttet, &checkseg);
30565   if (b->nobisect == 0) {
30566     if (checkseg.sh != dummysh) {
30567       // cd is a segment. The seg will be split. BUT do not flip! Due to the
30568       //   exact predicates, lot of slivers ay be rsulted and hard to remove.
30569       checkseg.shver = 0;
30570       pt[0] = sorg(checkseg);
30571       pt[1] = sdest(checkseg);
30572       makepoint(&newpt);
30573       getsplitpoint(pt[0], pt[1], NULL, newpt);
30574       setpointtype(newpt, FREESEGVERTEX);
30575       setpoint2sh(newpt, sencode(checkseg));
30576       // Insert p, this should always success.
30577       sstpivot(&checkseg, &starttet);
30578       splittetedge(newpt, &starttet, NULL);
30579       // Collect the new tets connecting at p.
30580       sstpivot(&checkseg, &starttet);
30581       ceillist->append(&starttet);
30582       formstarpolyhedron(newpt, ceillist, NULL, true);
30583       setnewpointsize(newpt, pt[0], NULL);
30584       if (steinerleft > 0) steinerleft--;
30585       // Smooth p.
30586       smoothpoint(newpt, pt[0], pt[1], ceillist, false, NULL);
30587       // Queue new slivers.
30588       for (i = 0; i < ceillist->len(); i++) {
30589         starttet = * (triface *)(* ceillist)[i];
30590         checktet4opt(&starttet, true);
30591       }
30592       ceillist->clear();
30593       return true;
30594     }
30595   }
30596 
30597   // Get the four corners.
30598   for (i = 0; i < 4; i++) {
30599     pt[i] = (point) starttet.tet[4 + i];
30600   }
30601   // Create the new point p (at the circumcenter of t).
30602   makepoint(&newpt);
30603   for (i = 0; i < 3; i++) {
30604     newpt[i] = 0.25 * (pt[0][i] + pt[1][i] + pt[2][i] + pt[3][i]);
30605   }
30606   setpointtype(newpt, FREEVOLVERTEX);
30607 
30608   // Form the Bowyer-Watson cavity of p.
30609   remflag = false;
30610   infect(starttet);
30611   tetlist->append(&starttet);
30612   formbowatcavityquad(newpt, tetlist, ceillist);
30613   if (trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, -1.0)) {
30614     // Smooth p.
30615     if (smoothpoint( newpt, NULL, NULL, ceillist, false, &remedge->key)) {
30616       // Insert p.
30617       bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, NULL,
30618                       NULL, false, false, false);
30619       setnewpointsize(newpt, pt[0], NULL);
30620       if (steinerleft > 0) steinerleft--;
30621       // Queue new slivers.
30622       for (i = 0; i < ceillist->len(); i++) {
30623         starttet = * (triface *)(* ceillist)[i];
30624         checktet4opt(&starttet, true);
30625       }
30626       remflag = true;
30627     } // if (smoothpoint)
30628   } // if (trimbowatcavity)
30629 
30630   if (!remflag) {
30631     // p is rejected for BC(p) is not valid.
30632     pointdealloc(newpt);
30633     // Uninfect tets of BC(p).
30634     for (i = 0; i < tetlist->len(); i++) {
30635       starttet = * (triface *)(* tetlist)[i];
30636       uninfect(starttet);
30637     }
30638   }
30639   tetlist->clear();
30640   ceillist->clear();
30641 
30642   return remflag;
30643 }
30644 
30646 //                                                                           //
30647 // tallslivers()    Queue all the slivers in the mesh.                       //
30648 //                                                                           //
30650 
30651 void tetgenmesh::tallslivers(bool optflag)
30652 {
30653   triface tetloop;
30654 
30655   tetrahedrons->traversalinit();
30656   tetloop.tet = tetrahedrontraverse();
30657   while (tetloop.tet != (tetrahedron *) NULL) {
30658     if (optflag) {
30659       checktet4opt(&tetloop, true);
30660     } else {
30661       checktet4ill(&tetloop, true);
30662     }
30663     tetloop.tet = tetrahedrontraverse();
30664   }
30665 }
30666 
30668 //                                                                           //
30669 // optimizemesh()    Improve mesh quality by mesh optimizations.             //
30670 //                                                                           //
30671 // Available mesh optimizing operations are: (1) multiple edge flips (3-to-2,//
30672 // 4-to-4, 5-to-6, etc), (2) free vertex deletion, (3) new vertex insertion. //
30673 // (1) is mandatory, while (2) and (3) are optionally.                       //
30674 //                                                                           //
30675 // The variable 'b->optlevel' (set after '-s') determines the use of these   //
30676 // operations. If it is: 0, do no optimization; 1, only do (1) operation; 2, //
30677 // do (1) and (2) operations; 3, do all operations. Deault, b->optlvel = 2.  //
30678 //                                                                           //
30680 
30681 void tetgenmesh::optimizemesh(bool optflag)
30682 {
30683   list *splittetlist, *tetlist, *ceillist;
30684   badface *remtet, *lastentry;
30685   //REAL maxdihed, objdihed, curdihed; // maxdihead commented out to get gcc 4.6 working
30686   REAL objdihed, curdihed;
30687   long oldnum;
30688   int iter, i;
30689 
30690   objdihed = 0.0;
30691 
30692   if (!b->quiet) {
30693     if (optflag) {
30694       printf("Optimizing mesh.\n");
30695     } else {
30696       printf("Repairing mesh.\n");
30697     }
30698   }
30699 
30700 #ifdef SELF_CHECK
30701   if (optflag && (b->verbose)) {
30702     printf("  level = %d.\n", b->optlevel);
30703   }
30704 #endif
30705 
30706   // Initialize the pool of bad tets.
30707   badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30708   if (optflag) {
30709     cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30710     cosmindihed = cos(b->mindihedral * PI / 180.0);
30711     // The radian of the maximum dihedral angle.
30712     //maxdihed = b->maxdihedral / 180.0 * PI; // maxdihead commented out to get gcc 4.6 working
30713     // A sliver has an angle large than 'objdihed' will be split.
30714     objdihed = b->maxdihedral + 5.0;
30715     if (objdihed < 170.0) objdihed = 170.0;
30716     objdihed = objdihed / 180.0 * PI;
30717   }
30718   // Looking for non-optimal tets.
30719   tallslivers(optflag);
30720 
30721   optcount[0] = 0l;  // tet strip count.
30722   optcount[1] = 0l;  // face (2-3) and edge (2-2) flip count.
30723   optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l; // edge flips.
30724   optcount[9] = 0l;  // combined flip count.
30725 
30726   // Perform edge flip to improve quality.
30727   lastentry = (badface *) NULL;
30728   // Loop until pool 'badtetrahedrons' is empty.
30729   while (badtetrahedrons->items > 0) {
30730     badtetrahedrons->traversalinit();
30731     remtet = badfacetraverse(badtetrahedrons);
30732     while (remtet != (badface *) NULL) {
30733       // Make sure that the tet is still the same one when it was tested.
30734       //   Subsequent transformations may have made it a different tet.
30735       if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30736           dest(remtet->tt) == remtet->fdest &&
30737           apex(remtet->tt) == remtet->fapex &&
30738           oppo(remtet->tt) == remtet->foppo) {
30739         if (b->verbose > 1) {
30740           printf("    Repair tet (%d, %d, %d, %d) %g (degree).\n",
30741                  pointmark(remtet->forg), pointmark(remtet->fdest),
30742                  pointmark(remtet->fapex), pointmark(remtet->foppo),
30743                  acos(remtet->key) / PI * 180.0);
30744         }
30745         if (!removeedge(remtet, optflag)) {
30746           // An unremoveable tet. Check if it forms a loop.
30747           if (lastentry != (badface *) NULL) {
30748             if (remtet == lastentry) break;
30749           } else {
30750             // Remember this tet as a breakpoint.
30751             lastentry = remtet;
30752           }
30753         } else {
30754           // Clear the breakpoint.
30755           lastentry = (badface *) NULL;
30756           // Remove the entry from the queue.
30757           badfacedealloc(badtetrahedrons, remtet);
30758         }
30759       } else {
30760         // Remove the entry from the queue.
30761         badfacedealloc(badtetrahedrons, remtet);
30762       }
30763       remtet = badfacetraverse(badtetrahedrons);
30764     }
30765     // Stop if the above loop was out by force.
30766     if (remtet != (badface *) NULL) break;
30767   }
30768 
30769   if (b->verbose) {
30770     if (optcount[0] > 0l) {
30771       printf("  %ld tets are peeled off.\n", optcount[0]);
30772     }
30773     if (optcount[1] > 0l) {
30774       printf("  %ld faces are flipped.\n", optcount[1]);
30775     }
30776     if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30777         optcount[9] > 0l) {
30778       printf("  %ld edges are flipped.\n", optcount[3] + optcount[4] +
30779              optcount[5] + optcount[6] + optcount[9]);
30780     }
30781     // if (badtetrahedrons->items > 0l) {
30782     //   printf("  %ld edges remain.\n", badtetrahedrons->items);
30783     // }
30784   }
30785 
30786   if ((badtetrahedrons->items > 0l) && optflag  && (b->optlevel > 2)) {
30787     splittetlist = new list(sizeof(badface), NULL, 256);
30788     tetlist = new list(sizeof(triface), NULL, 256);
30789     ceillist = new list(sizeof(triface), NULL, 256);
30790     oldnum = points->items;
30791     smoothsegverts = smoothvolverts = 0;
30792     optcount[1] = 0l;
30793     optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l; // edge flips.
30794     optcount[9] = 0l;  // combined flip count.
30795     iter = 0;
30796 
30797     do {
30798       // Form a list of slivers to be split and clean the pool.
30799       badtetrahedrons->traversalinit();
30800       remtet = badfacetraverse(badtetrahedrons);
30801       while (remtet != (badface *) NULL) {
30802         splittetlist->append(remtet);
30803         // Remove the entry from the queue.
30804         badfacedealloc(badtetrahedrons, remtet);
30805         remtet = badfacetraverse(badtetrahedrons);
30806       }
30807       for (i = 0; i < splittetlist->len(); i++) {
30808         remtet = (badface *)(* splittetlist)[i];
30809         // Make sure that the tet is still the same one when it was tested.
30810         //   Subsequent transformations may have made it a different tet.
30811         if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30812             dest(remtet->tt) == remtet->fdest &&
30813             apex(remtet->tt) == remtet->fapex &&
30814             oppo(remtet->tt) == remtet->foppo) {
30815           // The sliver may get smoothed due to a neighboring tet.
30816           curdihed = facedihedral(remtet->forg, remtet->fdest, remtet->fapex,
30817                                   remtet->foppo);
30818           // The dihedral angle of a tet must less than PI, correct it.
30819           if (curdihed > PI) curdihed = 2 * PI - curdihed;
30820           // Is it a large angle?
30821           if (curdihed > objdihed) {
30822             remtet->key = cos(curdihed);
30823             if (b->verbose > 1) {
30824               printf("    Get sliver (%d, %d, %d, %d) %g (degree).\n",
30825                      pointmark(remtet->forg), pointmark(remtet->fdest),
30826                      pointmark(remtet->fapex), pointmark(remtet->foppo),
30827                      acos(remtet->key) / PI * 180.0);
30828             }
30829             if (!removeedge(remtet, optflag)) {
30830               if (!smoothsliver(remtet, tetlist)) {
30831                 splitsliver(remtet, tetlist, ceillist);
30832               }
30833             }
30834           }
30835         }
30836       }
30837       iter++;
30838     } while ((badtetrahedrons->items > 0l) && (iter < b->optpasses));
30839 
30840     if (b->verbose) {
30841       printf("  %d passes.\n", iter);
30842       if ((points->items - oldnum) > 0l) {
30843         printf("  %ld points are inserted (%d on segment).\n",
30844                points->items - oldnum, smoothsegverts);
30845       }
30846       if (optcount[1] > 0l) {
30847         printf("  %ld faces are flipped.\n", optcount[1]);
30848       }
30849       if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30850           optcount[9] > 0l) {
30851         printf("  %ld edges are flipped.\n", optcount[3] + optcount[4] +
30852                optcount[5] + optcount[6] + optcount[9]);
30853       }
30854       // if (badtetrahedrons->items > 0l) {
30855       //   printf("  %ld edges remain.\n", badtetrahedrons->items);
30856       // }
30857     }
30858     delete tetlist;
30859     delete ceillist;
30860     delete splittetlist;
30861   }
30862 
30863   delete badtetrahedrons;
30864   badtetrahedrons = (memorypool *) NULL;
30865 }
30866 
30867 //
30868 // End of mesh optimization routines
30869 //
30870 
30871 //
30872 // Begin of I/O rouitnes
30873 //
30874 
30876 //                                                                           //
30877 // transfernodes()    Transfer nodes from 'io->pointlist' to 'this->points'. //
30878 //                                                                           //
30879 // Initializing 'this->points'.  Transferring all points from 'in->pointlist'//
30880 // into it. All points are indexed (start from in->firstnumber).  Each point //
30881 // is initialized be UNUSEDVERTEX.  The bounding box (xmin, xmax, ymin, ymax,//
30882 // zmin, zmax) and the diameter (longest) of the point set are calculated.   //
30883 //                                                                           //
30885 
30886 void tetgenmesh::transfernodes()
30887 {
30888   point pointloop;
30889   REAL x, y, z;
30890   int coordindex;
30891   int attribindex;
30892   int mtrindex;
30893   int i, j;
30894 
30895   // Read the points.
30896   coordindex = 0;
30897   attribindex = 0;
30898   mtrindex = 0;
30899   for (i = 0; i < in->numberofpoints; i++) {
30900     makepoint(&pointloop);
30901     // Read the point coordinates.
30902     x = pointloop[0] = in->pointlist[coordindex++];
30903     y = pointloop[1] = in->pointlist[coordindex++];
30904     z = pointloop[2] = in->pointlist[coordindex++];
30905     // Read the point attributes.
30906     for (j = 0; j < in->numberofpointattributes; j++) {
30907       pointloop[3 + j] = in->pointattributelist[attribindex++];
30908     }
30909     // Read the point metric tensor.
30910     for (j = 0; j < in->numberofpointmtrs; j++) {
30911       pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
30912     }
30913     // Determine the smallest and largests x, y and z coordinates.
30914     if (i == 0) {
30915       xmin = xmax = x;
30916       ymin = ymax = y;
30917       zmin = zmax = z;
30918     } else {
30919       xmin = (x < xmin) ? x : xmin;
30920       xmax = (x > xmax) ? x : xmax;
30921       ymin = (y < ymin) ? y : ymin;
30922       ymax = (y > ymax) ? y : ymax;
30923       zmin = (z < zmin) ? z : zmin;
30924       zmax = (z > zmax) ? z : zmax;
30925     }
30926   }
30927   // 'longest' is the largest possible edge length formed by input vertices.
30928   x = xmax - xmin;
30929   y = ymax - ymin;
30930   z = zmax - zmin;
30931   longest = sqrt(x * x + y * y + z * z);
30932   if (longest == 0.0) {
30933     printf("Error:  The point set is trivial.\n");
30934     terminatetetgen(1);
30935   }
30936   // Two identical points are distinguished by 'lengthlimit'.
30937   lengthlimit = longest * b->epsilon * 1e+2;
30938 }
30939 
30941 //                                                                           //
30942 // jettisonnodes()    Jettison unused or duplicated vertices.                //
30943 //                                                                           //
30944 // Unused points are those input points which are outside the mesh domain or //
30945 // have no connection (isolated) to the mesh.  Duplicated points exist for   //
30946 // example if the input PLC is read from a .stl mesh file (marked during the //
30947 // Delaunay tetrahedralization step. This routine remove these points from   //
30948 // points list. All existing points are reindexed.                           //
30949 //                                                                           //
30951 
30952 void tetgenmesh::jettisonnodes()
30953 {
30954   point pointloop;
30955   bool jetflag;
30956   int oldidx, newidx;
30957   int remcount;
30958 
30959   if (!b->quiet) {
30960     printf("Jettisoning redundants points.\n");
30961   }
30962 
30963   points->traversalinit();
30964   pointloop = pointtraverse();
30965   oldidx = newidx = 0; // in->firstnumber;
30966   remcount = 0;
30967   while (pointloop != (point) NULL) {
30968     jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) ||
30969       (pointtype(pointloop) == UNUSEDVERTEX);
30970     if (jetflag) {
30971       // It is a duplicated point, delete it.
30972       pointdealloc(pointloop);
30973       remcount++;
30974     } else {
30975       // Re-index it.
30976       setpointmark(pointloop, newidx + in->firstnumber);
30977       if (in->pointmarkerlist != (int *) NULL) {
30978         if (oldidx < in->numberofpoints) {
30979           // Re-index the point marker as well.
30980           in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
30981         }
30982       }
30983       newidx++;
30984     }
30985     oldidx++;
30986     if (oldidx == in->numberofpoints) {
30987       // Update the numbe of input points (Because some were removed).
30988       in->numberofpoints -= remcount;
30989       // Remember this number for output original input nodes.
30990       jettisoninverts = remcount;
30991     }
30992     pointloop = pointtraverse();
30993   }
30994   if (b->verbose) {
30995     printf("  %d duplicated vertices have been removed.\n", dupverts);
30996     printf("  %d unused vertices have been removed.\n", unuverts);
30997   }
30998   dupverts = 0;
30999   unuverts = 0;
31000 
31001   // The following line ensures that dead items in the pool of nodes cannot
31002   //   be allocated for the new created nodes. This ensures that the input
31003   //   nodes will occur earlier in the output files, and have lower indices.
31004   points->deaditemstack = (void *) NULL;
31005 }
31006 
31008 //                                                                           //
31009 // highorder()   Create extra nodes for quadratic subparametric elements.    //
31010 //                                                                           //
31011 // 'highordertable' is an array (size = numberoftetrahedra * 6) for storing  //
31012 // high-order nodes of each tetrahedron.  This routine is used only when -o2 //
31013 // switch is used.                                                           //
31014 //                                                                           //
31016 
31017 void tetgenmesh::highorder()
31018 {
31019   triface tetloop, worktet;
31020   triface spintet, adjtet;
31021   point torg, tdest, tapex;
31022   point *extralist, *adjextralist;
31023   point newpoint;
31024   int hitbdry, ptmark;
31025   int i, j;
31026 
31027   if (!b->quiet) {
31028     printf("Adding vertices for second-order tetrahedra.\n");
31029   }
31030 
31031   // Initialize the 'highordertable'.
31032   highordertable = new point[tetrahedrons->items * 6];
31033   if (highordertable == (point *) NULL) {
31034     printf("Error:  Out of memory.\n");
31035     terminatetetgen(1);
31036   }
31037 
31038   // The following line ensures that dead items in the pool of nodes cannot
31039   //   be allocated for the extra nodes associated with high order elements.
31040   //   This ensures that the primary nodes (at the corners of elements) will
31041   //   occur earlier in the output files, and have lower indices, than the
31042   //   extra nodes.
31043   points->deaditemstack = (void *) NULL;
31044 
31045   // Assign an entry for each tetrahedron to find its extra nodes. At the
31046   //   mean while, initialize all extra nodes be NULL.
31047   i = 0;
31048   tetrahedrons->traversalinit();
31049   tetloop.tet = tetrahedrontraverse();
31050   while (tetloop.tet != (tetrahedron *) NULL) {
31051     tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
31052     for (j = 0; j < 6; j++) {
31053       highordertable[i + j] = (point) NULL;
31054     }
31055     i += 6;
31056     tetloop.tet = tetrahedrontraverse();
31057   }
31058 
31059   // To create a unique node on each edge. Loop over all tetrahedra, and
31060   //   look at the six edges of each tetrahedron.  If the extra node in
31061   //   the tetrahedron corresponding to this edge is NULL, create a node
31062   //   for this edge, at the same time, set the new node into the extra
31063   //   node lists of all other tetrahedra sharing this edge.
31064   tetrahedrons->traversalinit();
31065   tetloop.tet = tetrahedrontraverse();
31066   while (tetloop.tet != (tetrahedron *) NULL) {
31067     // Get the list of extra nodes.
31068     extralist = (point *) tetloop.tet[highorderindex];
31069     worktet.tet = tetloop.tet;
31070     for (i = 0; i < 6; i++) {
31071       if (extralist[i] == (point) NULL) {
31072         // Operate on this edge.
31073         worktet.loc = edge2locver[i][0];
31074         worktet.ver = edge2locver[i][1];
31075         // Create a new node on this edge.
31076         torg = org(worktet);
31077         tdest = dest(worktet);
31078         // Create a new node in the middle of the edge.
31079         newpoint = (point) points->alloc();
31080         // Interpolate its attributes.
31081         for (j = 0; j < 3 + in->numberofpointattributes; j++) {
31082           newpoint[j] = 0.5 * (torg[j] + tdest[j]);
31083         }
31084         ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
31085         setpointmark(newpoint, ptmark);
31086         // Add this node to its extra node list.
31087         extralist[i] = newpoint;
31088         // Set 'newpoint' into extra node lists of other tetrahedra
31089         //   sharing this edge.
31090         tapex = apex(worktet);
31091         spintet = worktet;
31092         hitbdry = 0;
31093         while (hitbdry < 2) {
31094           if (fnextself(spintet)) {
31095             // Get the extra node list of 'spintet'.
31096             adjextralist = (point *) spintet.tet[highorderindex];
31097             // Find the index of its extra node list.
31098             j = locver2edge[spintet.loc][spintet.ver];
31099             // Only set 'newpoint' into 'adjextralist' if it is a NULL.
31100             //   Because two faces can belong to the same tetrahedron.
31101             if (adjextralist[j] == (point) NULL) {
31102               adjextralist[j] = newpoint;
31103             }
31104             if (apex(spintet) == tapex) {
31105               break;
31106             }
31107           } else {
31108             hitbdry++;
31109             if (hitbdry < 2) {
31110               esym(worktet, spintet);
31111         }
31112           }
31113         }
31114       }
31115     }
31116     tetloop.tet = tetrahedrontraverse();
31117   }
31118 }
31119 
31121 //                                                                           //
31122 // outnodes()    Output the points to a .node file or a tetgenio structure.  //
31123 //                                                                           //
31124 // Note: each point has already been numbered on input (the first index is   //
31125 // 'in->firstnumber').                                                       //
31126 //                                                                           //
31128 
31129 void tetgenmesh::outnodes(tetgenio* out)
31130 {
31131   FILE *outfile;
31132   char outnodefilename[FILENAMESIZE];
31133   shellface subptr;
31134   triface adjtet;
31135   face subloop;
31136   point pointloop;
31137   point *extralist, ep[3];
31138   int nextras, bmark, shmark, marker;
31139   int coordindex, attribindex;
31140   int pointnumber, firstindex;
31141   int index, i;
31142 
31143   if (out == (tetgenio *) NULL) {
31144     strcpy(outnodefilename, b->outfilename);
31145     strcat(outnodefilename, ".node");
31146   }
31147 
31148   if (!b->quiet) {
31149     if (out == (tetgenio *) NULL) {
31150       printf("Writing %s.\n", outnodefilename);
31151     } else {
31152       printf("Writing nodes.\n");
31153     }
31154   }
31155 
31156   nextras = in->numberofpointattributes;
31157   bmark = !b->nobound && in->pointmarkerlist;
31158 
31159   // Avoid compile warnings.
31160   outfile = (FILE *) NULL;
31161   marker = coordindex = 0;
31162 
31163   if (out == (tetgenio *) NULL) {
31164     outfile = fopen(outnodefilename, "w");
31165     if (outfile == (FILE *) NULL) {
31166       printf("File I/O Error:  Cannot create file %s.\n", outnodefilename);
31167       terminatetetgen(1);
31168     }
31169     // Number of points, number of dimensions, number of point attributes,
31170     //   and number of boundary markers (zero or one).
31171     fprintf(outfile, "%ld  %d  %d  %d\n", points->items, 3, nextras, bmark);
31172   } else {
31173     // Allocate space for 'pointlist';
31174     out->pointlist = new REAL[points->items * 3];
31175     if (out->pointlist == (REAL *) NULL) {
31176       printf("Error:  Out of memory.\n");
31177       terminatetetgen(1);
31178     }
31179     // Allocate space for 'pointattributelist' if necessary;
31180     if (nextras > 0) {
31181       out->pointattributelist = new REAL[points->items * nextras];
31182       if (out->pointattributelist == (REAL *) NULL) {
31183         printf("Error:  Out of memory.\n");
31184         terminatetetgen(1);
31185       }
31186     }
31187     // Allocate space for 'pointmarkerlist' if necessary;
31188     if (bmark) {
31189       out->pointmarkerlist = new int[points->items];
31190       if (out->pointmarkerlist == (int *) NULL) {
31191         printf("Error:  Out of memory.\n");
31192         terminatetetgen(1);
31193       }
31194     }
31195     out->numberofpoints = points->items;
31196     out->numberofpointattributes = nextras;
31197     coordindex = 0;
31198     attribindex = 0;
31199   }
31200 
31201   if (bmark && (b->plc || b->refine)) {
31202     // Initialize the point2tet field of each point.
31203     points->traversalinit();
31204     pointloop = pointtraverse();
31205     while (pointloop != (point) NULL) {
31206       setpoint2tet(pointloop, (tetrahedron) NULL);
31207       pointloop = pointtraverse();
31208     }
31209     // Make a map point-to-subface. Hence a boundary point will get the
31210     //   facet marker from that facet where it lies on.
31211     subfaces->traversalinit();
31212     subloop.sh = shellfacetraverse(subfaces);
31213     while (subloop.sh != (shellface *) NULL) {
31214       subloop.shver = 0;
31215       // Check all three points of the subface.
31216       for (i = 0; i < 3; i++) {
31217         pointloop = (point) subloop.sh[3 + i];
31218         setpoint2tet(pointloop, (tetrahedron) sencode(subloop));
31219       }
31220       if (b->order == 2) {
31221         // '-o2' switch. Set markers for quadratic nodes of this subface.
31222         stpivot(subloop, adjtet);
31223         if (adjtet.tet == dummytet) {
31224           sesymself(subloop);
31225           stpivot(subloop, adjtet);
31226         }
31227         assert(adjtet.tet != dummytet);
31228         extralist = (point *) adjtet.tet[highorderindex];
31229         switch (adjtet.loc) {
31230         case 0:
31231           ep[0] = extralist[0];
31232           ep[1] = extralist[1];
31233           ep[2] = extralist[2];
31234           break;
31235         case 1:
31236           ep[0] = extralist[0];
31237           ep[1] = extralist[4];
31238           ep[2] = extralist[3];
31239           break;
31240         case 2:
31241           ep[0] = extralist[1];
31242           ep[1] = extralist[5];
31243           ep[2] = extralist[4];
31244           break;
31245         case 3:
31246           ep[0] = extralist[2];
31247           ep[1] = extralist[3];
31248           ep[2] = extralist[5];
31249           break;
31250         default: break;
31251         }
31252         for (i = 0; i < 3; i++) {
31253           setpoint2tet(ep[i], (tetrahedron) sencode(subloop));
31254         }
31255       }
31256       subloop.sh = shellfacetraverse(subfaces);
31257     }
31258   }
31259 
31260   // Determine the first index (0 or 1).
31261   firstindex = b->zeroindex ? 0 : in->firstnumber;
31262 
31263   points->traversalinit();
31264   pointloop = pointtraverse();
31265   pointnumber = firstindex; // in->firstnumber;
31266   index = 0;
31267   while (pointloop != (point) NULL) {
31268     if (bmark) {
31269       // Default the vertex has a zero marker.
31270       marker = 0;
31271       // Is it an input vertex?
31272       if (index < in->numberofpoints) {
31273         // Input point's marker is directly copied to output.
31274         marker = in->pointmarkerlist[index];
31275       }
31276       // Is it a boundary vertex has marker zero?
31277       if ((marker == 0) && (b->plc || b->refine)) {
31278         subptr = (shellface) point2tet(pointloop);
31279         if (subptr != (shellface) NULL) {
31280           // Default a boundary vertex has marker 1.
31281           marker = 1;
31282           if (in->facetmarkerlist != (int *) NULL) {
31283             // The vertex gets the marker from the facet it lies on.
31284             sdecode(subptr, subloop);
31285             shmark = shellmark(subloop);
31286             marker = in->facetmarkerlist[shmark - 1];
31287           }
31288         }
31289       }
31290     }
31291     if (out == (tetgenio *) NULL) {
31292       // Point number, x, y and z coordinates.
31293       fprintf(outfile, "%4d    %.17g  %.17g  %.17g", pointnumber,
31294               pointloop[0], pointloop[1], pointloop[2]);
31295       for (i = 0; i < nextras; i++) {
31296         // Write an attribute.
31297         fprintf(outfile, "  %.17g", pointloop[3 + i]);
31298       }
31299       if (bmark) {
31300         // Write the boundary marker.
31301         fprintf(outfile, "    %d", marker);
31302       }
31303       fprintf(outfile, "\n");
31304     } else {
31305       // X, y, and z coordinates.
31306       out->pointlist[coordindex++] = pointloop[0];
31307       out->pointlist[coordindex++] = pointloop[1];
31308       out->pointlist[coordindex++] = pointloop[2];
31309       // Point attributes.
31310       for (i = 0; i < nextras; i++) {
31311         // Output an attribute.
31312         out->pointattributelist[attribindex++] = pointloop[3 + i];
31313       }
31314       if (bmark) {
31315         // Output the boundary marker.
31316         out->pointmarkerlist[index] = marker;
31317       }
31318     }
31319     pointloop = pointtraverse();
31320     pointnumber++;
31321     index++;
31322   }
31323 
31324   if (out == (tetgenio *) NULL) {
31325     fprintf(outfile, "# Generated by %s\n", b->commandline);
31326     fclose(outfile);
31327   }
31328 }
31329 
31331 //                                                                           //
31332 // outmetrics()    Output the metric to a file (*.mtr) or a tetgenio obj.    //
31333 //                                                                           //
31335 
31336 void tetgenmesh::outmetrics(tetgenio* out)
31337 {
31338   FILE *outfile;
31339   char outmtrfilename[FILENAMESIZE];
31340   list *tetlist, *ptlist;
31341   triface tetloop;
31342   point ptloop, neipt;
31343   REAL lave, len; // lmin, lmax,
31344   int mtrindex;
31345   int i;
31346 
31347   lave = 0.0;
31348 
31349   if (out == (tetgenio *) NULL) {
31350     strcpy(outmtrfilename, b->outfilename);
31351     strcat(outmtrfilename, ".mtr");
31352   }
31353 
31354   if (!b->quiet) {
31355     if (out == (tetgenio *) NULL) {
31356       printf("Writing %s.\n", outmtrfilename);
31357     } else {
31358       printf("Writing metrics.\n");
31359     }
31360   }
31361 
31362   // Avoid compile warnings.
31363   outfile = (FILE *) NULL;
31364   mtrindex = 0;
31365 
31366   if (out == (tetgenio *) NULL) {
31367     outfile = fopen(outmtrfilename, "w");
31368     if (outfile == (FILE *) NULL) {
31369       printf("File I/O Error:  Cannot create file %s.\n", outmtrfilename);
31370       terminatetetgen(1);
31371     }
31372     // Number of points, number of point metrices,
31373     // fprintf(outfile, "%ld  %d\n", points->items, sizeoftensor + 3);
31374     fprintf(outfile, "%ld  %d\n", points->items, 1);
31375   } else {
31376     // Allocate space for 'pointmtrlist' if necessary;
31377     // out->pointmtrlist = new REAL[points->items * (sizeoftensor + 3)];
31378     out->pointmtrlist = new REAL[points->items];
31379     if (out->pointmtrlist == (REAL *) NULL) {
31380       printf("Error:  Out of memory.\n");
31381       terminatetetgen(1);
31382     }
31383     out->numberofpointmtrs = 1; // (sizeoftensor + 3);
31384     mtrindex = 0;
31385   }
31386 
31387   // Initialize the point2tet field of each point.
31388   points->traversalinit();
31389   ptloop = pointtraverse();
31390   while (ptloop != (point) NULL) {
31391     setpoint2tet(ptloop, (tetrahedron) NULL);
31392     ptloop = pointtraverse();
31393   }
31394   // Create the point-to-tet map.
31395   tetrahedrons->traversalinit();
31396   tetloop.tet = tetrahedrontraverse();
31397   while (tetloop.tet != (tetrahedron *) NULL) {
31398     for (i = 0; i < 4; i++) {
31399       ptloop = (point) tetloop.tet[4 + i];
31400       setpoint2tet(ptloop, encode(tetloop));
31401     }
31402     tetloop.tet = tetrahedrontraverse();
31403   }
31404 
31405   tetlist = new list(sizeof(triface), NULL, 256);
31406   ptlist = new list(sizeof(point *), NULL, 256);
31407 
31408   points->traversalinit();
31409   ptloop = pointtraverse();
31410   while (ptloop != (point) NULL) {
31411     decode(point2tet(ptloop), tetloop);
31412     if (!isdead(&tetloop)) {
31413       // Form the star of p.
31414       tetlist->append(&tetloop);
31415       formstarpolyhedron(ptloop, tetlist, ptlist, true);
31416       // lmin = longest;
31417       // lmax = 0.0;
31418       lave = 0.0;
31419       for (i = 0; i < ptlist->len(); i++) {
31420         neipt = * (point *)(* ptlist)[i];
31421         len = distance(ptloop, neipt);
31422         // lmin = lmin < len ? lmin : len;
31423         // lmax = lmax > len ? lmax : len;
31424         lave += len;
31425       }
31426       lave /= ptlist->len();
31427     }
31428     if (out == (tetgenio *) NULL) {
31429       // for (i = 0; i < sizeoftensor; i++) {
31430       //   fprintf(outfile, "%-16.8e ", ptloop[pointmtrindex + i]);
31431       // }
31432       if (ptlist->len() > 0) {
31433         // fprintf(outfile, "%-16.8e %-16.8e %-16.8e", lmin, lmax, lave);
31434         fprintf(outfile, "%-16.8e ", lave);
31435       } else {
31436         fprintf(outfile, "0.0 "); // fprintf(outfile, "0.0  0.0  0.0");
31437       }
31438       fprintf(outfile, "\n");
31439     } else {
31440       // for (i = 0; i < sizeoftensor; i++) {
31441       //   out->pointmtrlist[mtrindex++] = ptloop[pointmtrindex + i];
31442       // }
31443       if (ptlist->len() > 0) {
31444         // out->pointmtrlist[mtrindex++] = lmin;
31445         // out->pointmtrlist[mtrindex++] = lmax;
31446         out->pointmtrlist[mtrindex++] = lave;
31447       } else {
31448         // out->pointmtrlist[mtrindex++] = 0.0;
31449         // out->pointmtrlist[mtrindex++] = 0.0;
31450         out->pointmtrlist[mtrindex++] = 0.0;
31451       }
31452     }
31453     tetlist->clear();
31454     ptlist->clear();
31455     ptloop = pointtraverse();
31456   }
31457 
31458   delete tetlist;
31459   delete ptlist;
31460 
31461   if (out == (tetgenio *) NULL) {
31462     fprintf(outfile, "# Generated by %s\n", b->commandline);
31463     fclose(outfile);
31464   }
31465 }
31466 
31468 //                                                                           //
31469 // outelements()    Output the tetrahedra to an .ele file or a tetgenio      //
31470 //                  structure.                                               //
31471 //                                                                           //
31473 
31474 void tetgenmesh::outelements(tetgenio* out)
31475 {
31476   FILE *outfile;
31477   char outelefilename[FILENAMESIZE];
31478   tetrahedron* tptr;
31479   int *tlist;
31480   REAL *talist;
31481   int firstindex, shift;
31482   int pointindex;
31483   int attribindex;
31484   point p1, p2, p3, p4;
31485   point *extralist;
31486   int elementnumber;
31487   int eextras;
31488   int i;
31489 
31490   if (out == (tetgenio *) NULL) {
31491     strcpy(outelefilename, b->outfilename);
31492     strcat(outelefilename, ".ele");
31493   }
31494 
31495   if (!b->quiet) {
31496     if (out == (tetgenio *) NULL) {
31497       printf("Writing %s.\n", outelefilename);
31498     } else {
31499       printf("Writing elements.\n");
31500     }
31501   }
31502 
31503   // Avoid compile warnings.
31504   outfile = (FILE *) NULL;
31505   tlist = (int *) NULL;
31506   talist = (double *) NULL;
31507   pointindex = attribindex = 0;
31508 
31509   eextras = in->numberoftetrahedronattributes;
31510   if (out == (tetgenio *) NULL) {
31511     outfile = fopen(outelefilename, "w");
31512     if (outfile == (FILE *) NULL) {
31513       printf("File I/O Error:  Cannot create file %s.\n", outelefilename);
31514       terminatetetgen(1);
31515     }
31516     // Number of tetras, points per tetra, attributes per tetra.
31517     fprintf(outfile, "%ld  %d  %d\n", tetrahedrons->items,
31518             b->order == 1 ? 4 : 10, eextras);
31519   } else {
31520     // Allocate memory for output tetrahedra.
31521     out->tetrahedronlist = new int[tetrahedrons->items *
31522                                    (b->order == 1 ? 4 : 10)];
31523     if (out->tetrahedronlist == (int *) NULL) {
31524       printf("Error:  Out of memory.\n");
31525       terminatetetgen(1);
31526     }
31527     // Allocate memory for output tetrahedron attributes if necessary.
31528     if (eextras > 0) {
31529       out->tetrahedronattributelist = new REAL[tetrahedrons->items * eextras];
31530       if (out->tetrahedronattributelist == (REAL *) NULL) {
31531         printf("Error:  Out of memory.\n");
31532         terminatetetgen(1);
31533       }
31534     }
31535     out->numberoftetrahedra = tetrahedrons->items;
31536     out->numberofcorners = b->order == 1 ? 4 : 10;
31537     out->numberoftetrahedronattributes = eextras;
31538     tlist = out->tetrahedronlist;
31539     talist = out->tetrahedronattributelist;
31540     pointindex = 0;
31541     attribindex = 0;
31542   }
31543 
31544   // Determine the first index (0 or 1).
31545   firstindex = b->zeroindex ? 0 : in->firstnumber;
31546   shift = 0; // Default no shiftment.
31547   if ((in->firstnumber == 1) && (firstindex == 0)) {
31548     shift = 1; // Shift the output indices by 1.
31549   }
31550 
31551   tetrahedrons->traversalinit();
31552   tptr = tetrahedrontraverse();
31553   elementnumber = firstindex; // in->firstnumber;
31554   while (tptr != (tetrahedron *) NULL) {
31555     p1 = (point) tptr[4];
31556     p2 = (point) tptr[5];
31557     p3 = (point) tptr[6];
31558     p4 = (point) tptr[7];
31559     if (out == (tetgenio *) NULL) {
31560       // Tetrahedron number, indices for four points.
31561       fprintf(outfile, "%5d   %5d %5d %5d %5d", elementnumber,
31562               pointmark(p1) - shift, pointmark(p2) - shift,
31563               pointmark(p3) - shift, pointmark(p4) - shift);
31564       if (b->order == 2) {
31565         extralist = (point *) tptr[highorderindex];
31566         // Tetrahedron number, indices for four points plus six extra points.
31567         fprintf(outfile, "  %5d %5d %5d %5d %5d %5d",
31568           pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
31569           pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
31570           pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
31571       }
31572       for (i = 0; i < eextras; i++) {
31573         fprintf(outfile, "    %.17g", elemattribute(tptr, i));
31574       }
31575       fprintf(outfile, "\n");
31576     } else {
31577       tlist[pointindex++] = pointmark(p1) - shift;
31578       tlist[pointindex++] = pointmark(p2) - shift;
31579       tlist[pointindex++] = pointmark(p3) - shift;
31580       tlist[pointindex++] = pointmark(p4) - shift;
31581       if (b->order == 2) {
31582         extralist = (point *) tptr[highorderindex];
31583         tlist[pointindex++] = pointmark(extralist[0]) - shift;
31584         tlist[pointindex++] = pointmark(extralist[1]) - shift;
31585         tlist[pointindex++] = pointmark(extralist[2]) - shift;
31586         tlist[pointindex++] = pointmark(extralist[3]) - shift;
31587         tlist[pointindex++] = pointmark(extralist[4]) - shift;
31588         tlist[pointindex++] = pointmark(extralist[5]) - shift;
31589       }
31590       for (i = 0; i < eextras; i++) {
31591         talist[attribindex++] = elemattribute(tptr, i);
31592       }
31593     }
31594     if (b->neighout) {
31595       // Remember the index of this element.
31596       * (int *) (tptr + elemmarkerindex) = elementnumber;
31597     }
31598     tptr = tetrahedrontraverse();
31599     elementnumber++;
31600   }
31601   if (b->neighout) {
31602     // Set the outside element marker.
31603     * (int *) (dummytet + elemmarkerindex) = -1;
31604   }
31605 
31606   if (out == (tetgenio *) NULL) {
31607     fprintf(outfile, "# Generated by %s\n", b->commandline);
31608     fclose(outfile);
31609   }
31610 }
31611 
31613 //                                                                           //
31614 // outfaces()    Output all faces to a .face file or a tetgenio structure.   //
31615 //                                                                           //
31616 // This routines outputs all triangular faces (including outer boundary      //
31617 // faces and inner faces) of this mesh.                                      //
31618 //                                                                           //
31620 
31621 void tetgenmesh::outfaces(tetgenio* out)
31622 {
31623   FILE *outfile;
31624   char facefilename[FILENAMESIZE];
31625   int *elist;
31626   int *emlist;
31627   int neigh1, neigh2;
31628   int index;
31629   triface tface, tsymface;
31630   face checkmark;
31631   point torg, tdest, tapex;
31632   long faces;
31633   int bmark, faceid, marker;
31634   int firstindex, shift;
31635   int facenumber;
31636 
31637   neigh1 = 0;
31638   neigh2 = 0;
31639 
31640   if (out == (tetgenio *) NULL) {
31641     strcpy(facefilename, b->outfilename);
31642     strcat(facefilename, ".face");
31643   }
31644 
31645   if (!b->quiet) {
31646     if (out == (tetgenio *) NULL) {
31647       printf("Writing %s.\n", facefilename);
31648     } else {
31649       printf("Writing faces.\n");
31650     }
31651   }
31652 
31653   // Avoid compile warnings.
31654   outfile = (FILE *) NULL;
31655   elist = (int *) NULL;
31656   emlist = (int *) NULL;
31657   index =  marker = 0;
31658 
31659   faces = (4l * tetrahedrons->items + hullsize) / 2l;
31660   bmark = !b->nobound && in->facetmarkerlist;
31661 
31662   if (out == (tetgenio *) NULL) {
31663     outfile = fopen(facefilename, "w");
31664     if (outfile == (FILE *) NULL) {
31665       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31666       terminatetetgen(1);
31667     }
31668     fprintf(outfile, "%ld  %d\n", faces, bmark);
31669   } else {
31670     // Allocate memory for 'trifacelist'.
31671     out->trifacelist = new int[faces * 3];
31672     if (out->trifacelist == (int *) NULL) {
31673       printf("Error:  Out of memory.\n");
31674       terminatetetgen(1);
31675     }
31676     // Allocate memory for 'trifacemarkerlist' if necessary.
31677     if (bmark) {
31678       out->trifacemarkerlist = new int[faces];
31679       if (out->trifacemarkerlist == (int *) NULL) {
31680         printf("Error:  Out of memory.\n");
31681         terminatetetgen(1);
31682       }
31683     }
31684     if (b->neighout > 1) {
31685       // '-nn' switch.
31686       out->adjtetlist = new int[subfaces->items * 2];
31687       if (out->adjtetlist == (int *) NULL) {
31688         printf("Error:  Out of memory.\n");
31689         terminatetetgen(1);
31690       }
31691     }
31692     out->numberoftrifaces = faces;
31693     elist = out->trifacelist;
31694     emlist = out->trifacemarkerlist;
31695     index = 0;
31696   }
31697 
31698   // Determine the first index (0 or 1).
31699   firstindex = b->zeroindex ? 0 : in->firstnumber;
31700   shift = 0; // Default no shiftment.
31701   if ((in->firstnumber == 1) && (firstindex == 0)) {
31702     shift = 1; // Shift the output indices by 1.
31703   }
31704 
31705   tetrahedrons->traversalinit();
31706   tface.tet = tetrahedrontraverse();
31707   facenumber = firstindex; // in->firstnumber;
31708   // To loop over the set of faces, loop over all tetrahedra, and look at
31709   //   the four faces of each one. If there isn't another tetrahedron
31710   //   adjacent to this face, operate on the face.  If there is another
31711   //   adjacent tetrahedron, operate on the face only if the current
31712   //   tetrahedron has a smaller pointer than its neighbor.  This way, each
31713   //   face is considered only once.
31714   while (tface.tet != (tetrahedron *) NULL) {
31715     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31716       sym(tface, tsymface);
31717       if ((tsymface.tet == dummytet) || (tface.tet < tsymface.tet)) {
31718         torg = org(tface);
31719         tdest = dest(tface);
31720         tapex = apex(tface);
31721         if (bmark) {
31722           // Get the boundary marker of this face. If it is an inner face,
31723           //   it has no boundary marker, set it be zero.
31724           if (b->useshelles) {
31725             // Shell face is used.
31726             tspivot(tface, checkmark);
31727             if (checkmark.sh == dummysh) {
31728               marker = 0;  // It is an inner face.
31729             } else {
31730               faceid = shellmark(checkmark) - 1;
31731               marker = in->facetmarkerlist[faceid];
31732             }
31733           } else {
31734             // Shell face is not used, only distinguish outer and inner face.
31735             marker = tsymface.tet != dummytet ? 1 : 0;
31736           }
31737         }
31738         if (b->neighout > 1) {
31739           // '-nn' switch. Output adjacent tets indices.
31740           neigh1 = * (int *)(tface.tet + elemmarkerindex);
31741           if (tsymface.tet != dummytet) {
31742             neigh2 = * (int *)(tsymface.tet + elemmarkerindex);
31743           } else {
31744             neigh2 = -1;
31745           }
31746         }
31747         if (out == (tetgenio *) NULL) {
31748           // Face number, indices of three vertices.
31749           fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
31750                   pointmark(torg) - shift, pointmark(tdest) - shift,
31751                   pointmark(tapex) - shift);
31752           if (bmark) {
31753             // Output a boundary marker.
31754             fprintf(outfile, "  %d", marker);
31755           }
31756           if (b->neighout > 1) {
31757             fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
31758           }
31759           fprintf(outfile, "\n");
31760         } else {
31761           // Output indices of three vertices.
31762           elist[index++] = pointmark(torg) - shift;
31763           elist[index++] = pointmark(tdest) - shift;
31764           elist[index++] = pointmark(tapex) - shift;
31765           if (bmark) {
31766             emlist[facenumber - in->firstnumber] = marker;
31767           }
31768           if (b->neighout > 1) {
31769             out->adjtetlist[(facenumber - in->firstnumber) * 2]     = neigh1;
31770             out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
31771           }
31772         }
31773         facenumber++;
31774       }
31775     }
31776     tface.tet = tetrahedrontraverse();
31777   }
31778 
31779   if (out == (tetgenio *) NULL) {
31780     fprintf(outfile, "# Generated by %s\n", b->commandline);
31781     fclose(outfile);
31782   }
31783 }
31784 
31786 //                                                                           //
31787 // outhullfaces()    Output outer boundary faces to a .face file or a        //
31788 //                   tetgenio structure.                                     //
31789 //                                                                           //
31790 // The normal of each face is arranged to point inside of the domain (use    //
31791 // right-hand rule).  This routines will outputs convex hull faces if the    //
31792 // mesh is a Delaunay tetrahedralization.                                    //
31793 //                                                                           //
31795 
31796 void tetgenmesh::outhullfaces(tetgenio* out)
31797 {
31798   FILE *outfile;
31799   char facefilename[FILENAMESIZE];
31800   int *elist;
31801   int index;
31802   triface tface, tsymface;
31803   face checkmark;
31804   point torg, tdest, tapex;
31805   int firstindex, shift;
31806   int facenumber;
31807 
31808   if (out == (tetgenio *) NULL) {
31809     strcpy(facefilename, b->outfilename);
31810     strcat(facefilename, ".face");
31811   }
31812 
31813   if (!b->quiet) {
31814     if (out == (tetgenio *) NULL) {
31815       printf("Writing %s.\n", facefilename);
31816     } else {
31817       printf("Writing faces.\n");
31818     }
31819   }
31820 
31821   // Avoid compile warnings.
31822   outfile = (FILE *) NULL;
31823   elist = (int *) NULL;
31824   index = 0;
31825 
31826   if (out == (tetgenio *) NULL) {
31827     outfile = fopen(facefilename, "w");
31828     if (outfile == (FILE *) NULL) {
31829       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31830       terminatetetgen(1);
31831     }
31832     fprintf(outfile, "%ld  0\n", hullsize);
31833   } else {
31834     // Allocate memory for 'trifacelist'.
31835     out->trifacelist = new int[hullsize * 3];
31836     if (out->trifacelist == (int *) NULL) {
31837       printf("Error:  Out of memory.\n");
31838       terminatetetgen(1);
31839     }
31840     out->numberoftrifaces = hullsize;
31841     elist = out->trifacelist;
31842     index = 0;
31843   }
31844 
31845   // Determine the first index (0 or 1).
31846   firstindex = b->zeroindex ? 0 : in->firstnumber;
31847   shift = 0; // Default no shiftment.
31848   if ((in->firstnumber == 1) && (firstindex == 0)) {
31849     shift = 1; // Shift the output indices by 1.
31850   }
31851 
31852   tetrahedrons->traversalinit();
31853   tface.tet = tetrahedrontraverse();
31854   facenumber = firstindex; // in->firstnumber;
31855   // To loop over the set of hull faces, loop over all tetrahedra, and look
31856   //   at the four faces of each one. If there isn't another tetrahedron
31857   //   adjacent to this face, operate on the face.
31858   while (tface.tet != (tetrahedron *) NULL) {
31859     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31860       sym(tface, tsymface);
31861       if (tsymface.tet == dummytet) {
31862         torg = org(tface);
31863         tdest = dest(tface);
31864         tapex = apex(tface);
31865         if (out == (tetgenio *) NULL) {
31866           // Face number, indices of three vertices.
31867           fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
31868                   pointmark(torg) - shift, pointmark(tdest) - shift,
31869                   pointmark(tapex) - shift);
31870           fprintf(outfile, "\n");
31871         } else {
31872           // Output indices of three vertices.
31873           elist[index++] = pointmark(torg) - shift;
31874           elist[index++] = pointmark(tdest) - shift;
31875           elist[index++] = pointmark(tapex) - shift;
31876         }
31877         facenumber++;
31878       }
31879     }
31880     tface.tet = tetrahedrontraverse();
31881   }
31882 
31883   if (out == (tetgenio *) NULL) {
31884     fprintf(outfile, "# Generated by %s\n", b->commandline);
31885     fclose(outfile);
31886   }
31887 }
31888 
31890 //                                                                           //
31891 // outsubfaces()    Output subfaces (i.e. boundary faces) to a .face file or //
31892 //                  a tetgenio structure.                                    //
31893 //                                                                           //
31894 // The boundary faces are exist in 'subfaces'. For listing triangle vertices //
31895 // in the same sense for all triangles in the mesh, the direction determined //
31896 // by right-hand rule is pointer to the inside of the volume.                //
31897 //                                                                           //
31899 
31900 void tetgenmesh::outsubfaces(tetgenio* out)
31901 {
31902   FILE *outfile;
31903   char facefilename[FILENAMESIZE];
31904   int *elist;
31905   int *emlist;
31906   int index, index1, index2;
31907   triface abuttingtet;
31908   face faceloop;
31909   point torg, tdest, tapex;
31910   int bmark, faceid, marker;
31911   int firstindex, shift;
31912   int neigh1, neigh2;
31913   int facenumber;
31914 
31915   if (out == (tetgenio *) NULL) {
31916     strcpy(facefilename, b->outfilename);
31917     strcat(facefilename, ".face");
31918   }
31919 
31920   if (!b->quiet) {
31921     if (out == (tetgenio *) NULL) {
31922       printf("Writing %s.\n", facefilename);
31923     } else {
31924       printf("Writing faces.\n");
31925     }
31926   }
31927 
31928   // Avoid compile warnings.
31929   outfile = (FILE *) NULL;
31930   elist = (int *) NULL;
31931   emlist = (int *) NULL;
31932   index = index1 = index2 = 0;
31933   faceid = marker = 0;
31934   neigh1 = neigh2 = 0;
31935 
31936   bmark = !b->nobound && in->facetmarkerlist;
31937 
31938   if (out == (tetgenio *) NULL) {
31939     outfile = fopen(facefilename, "w");
31940     if (outfile == (FILE *) NULL) {
31941       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31942       terminatetetgen(1);
31943     }
31944     // Number of subfaces.
31945     fprintf(outfile, "%ld  %d\n", subfaces->items, bmark);
31946   } else {
31947     // Allocate memory for 'trifacelist'.
31948     out->trifacelist = new int[subfaces->items * 3];
31949     if (out->trifacelist == (int *) NULL) {
31950       printf("Error:  Out of memory.\n");
31951       terminatetetgen(1);
31952     }
31953     if (bmark) {
31954       // Allocate memory for 'trifacemarkerlist'.
31955       out->trifacemarkerlist = new int[subfaces->items];
31956       if (out->trifacemarkerlist == (int *) NULL) {
31957         printf("Error:  Out of memory.\n");
31958         terminatetetgen(1);
31959       }
31960     }
31961     if (b->neighout > 1) {
31962       // '-nn' switch.
31963       out->adjtetlist = new int[subfaces->items * 2];
31964       if (out->adjtetlist == (int *) NULL) {
31965         printf("Error:  Out of memory.\n");
31966         terminatetetgen(1);
31967       }
31968     }
31969     out->numberoftrifaces = subfaces->items;
31970     elist = out->trifacelist;
31971     emlist = out->trifacemarkerlist;
31972   }
31973 
31974   // Determine the first index (0 or 1).
31975   firstindex = b->zeroindex ? 0 : in->firstnumber;
31976   shift = 0; // Default no shiftment.
31977   if ((in->firstnumber == 1) && (firstindex == 0)) {
31978     shift = 1; // Shift the output indices by 1.
31979   }
31980 
31981   subfaces->traversalinit();
31982   faceloop.sh = shellfacetraverse(subfaces);
31983   facenumber = firstindex; // in->firstnumber;
31984   while (faceloop.sh != (shellface *) NULL) {
31985     stpivot(faceloop, abuttingtet);
31986     if (abuttingtet.tet == dummytet) {
31987       sesymself(faceloop);
31988       stpivot(faceloop, abuttingtet);
31989     }
31990     if (abuttingtet.tet != dummytet) {
31991       // If there is a tetrahedron containing this subface, orient it so
31992       //   that the normal of this face points to inside of the volume by
31993       //   right-hand rule.
31994       adjustedgering(abuttingtet, CCW);
31995       torg = org(abuttingtet);
31996       tdest = dest(abuttingtet);
31997       tapex = apex(abuttingtet);
31998     } else {
31999       // This may happen when only a surface mesh be generated.
32000       torg = sorg(faceloop);
32001       tdest = sdest(faceloop);
32002       tapex = sapex(faceloop);
32003     }
32004     if (bmark) {
32005       faceid = shellmark(faceloop) - 1;
32006       marker = in->facetmarkerlist[faceid];
32007     }
32008     if (b->neighout > 1) {
32009       // '-nn' switch. Output adjacent tets indices.
32010       neigh1 = -1;
32011       stpivot(faceloop, abuttingtet);
32012       if (abuttingtet.tet != dummytet) {
32013         neigh1 = * (int *)(abuttingtet.tet + elemmarkerindex);
32014       }
32015       neigh2 = -1;
32016       sesymself(faceloop);
32017       stpivot(faceloop, abuttingtet);
32018       if (abuttingtet.tet != dummytet) {
32019         neigh2 = * (int *)(abuttingtet.tet + elemmarkerindex);
32020       }
32021     }
32022     if (out == (tetgenio *) NULL) {
32023       fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
32024               pointmark(torg) - shift, pointmark(tdest) - shift,
32025               pointmark(tapex) - shift);
32026       if (bmark) {
32027         fprintf(outfile, "    %d", marker);
32028       }
32029       if (b->neighout > 1) {
32030         fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
32031       }
32032       fprintf(outfile, "\n");
32033     } else {
32034       // Output three vertices of this face;
32035       elist[index++] = pointmark(torg) - shift;
32036       elist[index++] = pointmark(tdest) - shift;
32037       elist[index++] = pointmark(tapex) - shift;
32038       if (bmark) {
32039         emlist[index1++] = marker;
32040       }
32041       if (b->neighout > 1) {
32042         out->adjtetlist[index2++] = neigh1;
32043         out->adjtetlist[index2++] = neigh2;
32044       }
32045     }
32046     facenumber++;
32047     faceloop.sh = shellfacetraverse(subfaces);
32048   }
32049 
32050   if (out == (tetgenio *) NULL) {
32051     fprintf(outfile, "# Generated by %s\n", b->commandline);
32052     fclose(outfile);
32053   }
32054 }
32055 
32057 //                                                                           //
32058 // outedges()    Output all edges to a .edge file or a structure.            //
32059 //                                                                           //
32061 
32062 void tetgenmesh::outedges(tetgenio* out)
32063 {
32064   FILE *outfile;
32065   char edgefilename[FILENAMESIZE];
32066   int *elist, *emlist;
32067   int index, index1;
32068   triface tetloop, worktet, spintet;
32069   face checksh;
32070   point torg, tdest;
32071   long faces, edges;
32072   int firstindex, shift;
32073   int edgenumber, faceid, marker;
32074   int hitbdry, i;
32075 
32076   if (out == (tetgenio *) NULL) {
32077     strcpy(edgefilename, b->outfilename);
32078     strcat(edgefilename, ".edge");
32079   }
32080 
32081   if (!b->quiet) {
32082     if (out == (tetgenio *) NULL) {
32083       printf("Writing %s.\n", edgefilename);
32084     } else {
32085       printf("Writing edges.\n");
32086     }
32087   }
32088 
32089   // Avoid compile warnings.
32090   outfile = (FILE *) NULL;
32091   elist = (int *) NULL;
32092   emlist = (int *) NULL;
32093   index = index1 = 0;
32094   faceid = marker = 0;
32095 
32096   // Using the Euler formula (V-E+F-T=1) to get the total number of edges.
32097   faces = (4l * tetrahedrons->items + hullsize) / 2l;
32098   edges = points->items + faces - tetrahedrons->items - 1l;
32099 
32100   if (out == (tetgenio *) NULL) {
32101     outfile = fopen(edgefilename, "w");
32102     if (outfile == (FILE *) NULL) {
32103       printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
32104       terminatetetgen(1);
32105     }
32106     // Write the number of edges, boundary markers (0 or 1).
32107     fprintf(outfile, "%ld  %d\n", edges, !b->nobound);
32108   } else {
32109     // Allocate memory for 'edgelist'.
32110     out->edgelist = new int[edges * 2];
32111     if (out->edgelist == (int *) NULL) {
32112       printf("Error:  Out of memory.\n");
32113       terminatetetgen(1);
32114     }
32115     if (!b->nobound) {
32116       out->edgemarkerlist = new int[edges];
32117     }
32118     out->numberofedges = edges;
32119     elist = out->edgelist;
32120     emlist = out->edgemarkerlist;
32121   }
32122 
32123   // Determine the first index (0 or 1).
32124   firstindex = b->zeroindex ? 0 : in->firstnumber;
32125   shift = 0; // Default no shiftment.
32126   if ((in->firstnumber == 1) && (firstindex == 0)) {
32127     shift = 1; // Shift (reduce) the output indices by 1.
32128   }
32129 
32130   tetrahedrons->traversalinit();
32131   tetloop.tet = tetrahedrontraverse();
32132   edgenumber = firstindex; // in->firstnumber;
32133   while (tetloop.tet != (tetrahedron *) NULL) {
32134     // Count the number of Voronoi faces. Look at the six edges of each
32135     //   tetrahedron. Count the edge only if the tetrahedron's pointer is
32136     //   smaller than those of all other tetrahedra that share the edge.
32137     worktet.tet = tetloop.tet;
32138     for (i = 0; i < 6; i++) {
32139       worktet.loc = edge2locver[i][0];
32140       worktet.ver = edge2locver[i][1];
32141       adjustedgering(worktet, CW);
32142       spintet = worktet;
32143       hitbdry = 0;
32144       while (hitbdry < 2) {
32145         if (fnextself(spintet)) {
32146           if (apex(spintet) == apex(worktet)) break;
32147           if (spintet.tet < worktet.tet) break;
32148         } else {
32149           hitbdry++;
32150           if (hitbdry < 2) {
32151             esym(worktet, spintet);
32152             fnextself(spintet); // In the same tet.
32153       }
32154         }
32155       }
32156       // Count this edge if no adjacent tets are smaller than this tet.
32157       if (spintet.tet >= worktet.tet) {
32158         torg = org(worktet);
32159         tdest = dest(worktet);
32160         if (out == (tetgenio *) NULL) {
32161           fprintf(outfile, "%5d   %4d  %4d", edgenumber,
32162                   pointmark(torg) - shift, pointmark(tdest) - shift);
32163         } else {
32164           // Output three vertices of this face;
32165           elist[index++] = pointmark(torg) - shift;
32166           elist[index++] = pointmark(tdest) - shift;
32167         }
32168         if (!b->nobound) {
32169           if (hitbdry > 0) {
32170             // It is a boundary edge. Get the boundary marker of the facet
32171             //   containing this edge. Note there may have more than one
32172             //   facet, choose one arbitrarily.
32173             if ((b->plc || b->refine) && in->facetmarkerlist) {
32174               tspivot(spintet, checksh);
32175               faceid = shellmark(checksh) - 1;
32176               marker = in->facetmarkerlist[faceid];
32177             } else {
32178               marker = 1;  // Indicate it's a boundary edge.
32179             }
32180           } else {
32181             marker = 0;
32182           }
32183           if (out == (tetgenio *) NULL) {
32184             fprintf(outfile, "  %d", marker);
32185           } else {
32186             emlist[index1++] = marker;
32187           }
32188         }
32189         if (out == (tetgenio *) NULL) {
32190           fprintf(outfile, "\n");
32191         }
32192         edgenumber++;
32193       }
32194     }
32195     tetloop.tet = tetrahedrontraverse();
32196   }
32197 
32198   if (out == (tetgenio *) NULL) {
32199     fprintf(outfile, "# Generated by %s\n", b->commandline);
32200     fclose(outfile);
32201   }
32202 }
32203 
32205 //                                                                           //
32206 // outsubsegments()    Output segments to a .edge file or a structure.       //
32207 //                                                                           //
32209 
32210 void tetgenmesh::outsubsegments(tetgenio* out)
32211 {
32212   FILE *outfile;
32213   char edgefilename[FILENAMESIZE];
32214   int *elist;
32215   int index;
32216   face edgeloop;
32217   point torg, tdest;
32218   int firstindex, shift;
32219   int edgenumber;
32220 
32221   if (out == (tetgenio *) NULL) {
32222     strcpy(edgefilename, b->outfilename);
32223     strcat(edgefilename, ".edge");
32224   }
32225 
32226   if (!b->quiet) {
32227     if (out == (tetgenio *) NULL) {
32228       printf("Writing %s.\n", edgefilename);
32229     } else {
32230       printf("Writing edges.\n");
32231     }
32232   }
32233 
32234   // Avoid compile warnings.
32235   outfile = (FILE *) NULL;
32236   elist = (int *) NULL;
32237   index = 0;
32238 
32239   if (out == (tetgenio *) NULL) {
32240     outfile = fopen(edgefilename, "w");
32241     if (outfile == (FILE *) NULL) {
32242       printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
32243       terminatetetgen(1);
32244     }
32245     // Number of subsegments.
32246     fprintf(outfile, "%ld\n", subsegs->items);
32247   } else {
32248     // Allocate memory for 'edgelist'.
32249     out->edgelist = new int[subsegs->items * 2];
32250     if (out->edgelist == (int *) NULL) {
32251       printf("Error:  Out of memory.\n");
32252       terminatetetgen(1);
32253     }
32254     out->numberofedges = subsegs->items;
32255     elist = out->edgelist;
32256   }
32257 
32258   // Determine the first index (0 or 1).
32259   firstindex = b->zeroindex ? 0 : in->firstnumber;
32260   shift = 0; // Default no shiftment.
32261   if ((in->firstnumber == 1) && (firstindex == 0)) {
32262     shift = 1; // Shift the output indices by 1.
32263   }
32264 
32265   subsegs->traversalinit();
32266   edgeloop.sh = shellfacetraverse(subsegs);
32267   edgenumber = firstindex; // in->firstnumber;
32268   while (edgeloop.sh != (shellface *) NULL) {
32269     torg = sorg(edgeloop);
32270     tdest = sdest(edgeloop);
32271     if (out == (tetgenio *) NULL) {
32272       fprintf(outfile, "%5d   %4d  %4d\n", edgenumber,
32273               pointmark(torg) - shift, pointmark(tdest) - shift);
32274     } else {
32275       // Output three vertices of this face;
32276       elist[index++] = pointmark(torg) - shift;
32277       elist[index++] = pointmark(tdest) - shift;
32278     }
32279     edgenumber++;
32280     edgeloop.sh = shellfacetraverse(subsegs);
32281   }
32282 
32283   if (out == (tetgenio *) NULL) {
32284     fprintf(outfile, "# Generated by %s\n", b->commandline);
32285     fclose(outfile);
32286   }
32287 }
32288 
32290 //                                                                           //
32291 // outneighbors()    Output tet neighbors to a .neigh file or a structure.   //
32292 //                                                                           //
32294 
32295 void tetgenmesh::outneighbors(tetgenio* out)
32296 {
32297   FILE *outfile;
32298   char neighborfilename[FILENAMESIZE];
32299   int *nlist;
32300   int index;
32301   triface tetloop, tetsym;
32302   int neighbor1, neighbor2, neighbor3, neighbor4;
32303   int firstindex;
32304   int elementnumber;
32305 
32306   if (out == (tetgenio *) NULL) {
32307     strcpy(neighborfilename, b->outfilename);
32308     strcat(neighborfilename, ".neigh");
32309   }
32310 
32311   if (!b->quiet) {
32312     if (out == (tetgenio *) NULL) {
32313       printf("Writing %s.\n", neighborfilename);
32314     } else {
32315       printf("Writing neighbors.\n");
32316     }
32317   }
32318 
32319   // Avoid compile warnings.
32320   outfile = (FILE *) NULL;
32321   nlist = (int *) NULL;
32322   index = 0;
32323 
32324   if (out == (tetgenio *) NULL) {
32325     outfile = fopen(neighborfilename, "w");
32326     if (outfile == (FILE *) NULL) {
32327       printf("File I/O Error:  Cannot create file %s.\n", neighborfilename);
32328       terminatetetgen(1);
32329     }
32330     // Number of tetrahedra, four faces per tetrahedron.
32331     fprintf(outfile, "%ld  %d\n", tetrahedrons->items, 4);
32332   } else {
32333     // Allocate memory for 'neighborlist'.
32334     out->neighborlist = new int[tetrahedrons->items * 4];
32335     if (out->neighborlist == (int *) NULL) {
32336       printf("Error:  Out of memory.\n");
32337       terminatetetgen(1);
32338     }
32339     nlist = out->neighborlist;
32340   }
32341 
32342   // Determine the first index (0 or 1).
32343   firstindex = b->zeroindex ? 0 : in->firstnumber;
32344 
32345   tetrahedrons->traversalinit();
32346   tetloop.tet = tetrahedrontraverse();
32347   elementnumber = firstindex; // in->firstnumber;
32348   while (tetloop.tet != (tetrahedron *) NULL) {
32349     tetloop.loc = 2;
32350     sym(tetloop, tetsym);
32351     neighbor1 = * (int *) (tetsym.tet + elemmarkerindex);
32352     tetloop.loc = 3;
32353     sym(tetloop, tetsym);
32354     neighbor2 = * (int *) (tetsym.tet + elemmarkerindex);
32355     tetloop.loc = 1;
32356     sym(tetloop, tetsym);
32357     neighbor3 = * (int *) (tetsym.tet + elemmarkerindex);
32358     tetloop.loc = 0;
32359     sym(tetloop, tetsym);
32360     neighbor4 = * (int *) (tetsym.tet + elemmarkerindex);
32361     if (out == (tetgenio *) NULL) {
32362       // Tetrahedra number, neighboring tetrahedron numbers.
32363       fprintf(outfile, "%4d    %4d  %4d  %4d  %4d\n", elementnumber,
32364               neighbor1, neighbor2, neighbor3, neighbor4);
32365     } else {
32366       nlist[index++] = neighbor1;
32367       nlist[index++] = neighbor2;
32368       nlist[index++] = neighbor3;
32369       nlist[index++] = neighbor4;
32370     }
32371     tetloop.tet = tetrahedrontraverse();
32372     elementnumber++;
32373   }
32374 
32375   if (out == (tetgenio *) NULL) {
32376     fprintf(outfile, "# Generated by %s\n", b->commandline);
32377     fclose(outfile);
32378   }
32379 }
32380 
32382 //                                                                           //
32383 // outvoronoi()    Output the Voronoi diagram to .v.node, .v.edge, v.face,   //
32384 //                 and .v.cell.                                              //
32385 //                                                                           //
32386 // The Voronoi diagram is the geometric dual of the Delaunay triangulation.  //
32387 // The Voronoi vertices are the circumcenters of Delaunay tetrahedra.  Each  //
32388 // Voronoi edge connects two Voronoi vertices at two sides of a common Dela- //
32389 // unay face. At a face of convex hull, it becomes a ray (goto the infinity).//
32390 // A Voronoi face is the convex hull of all Voronoi vertices around a common //
32391 // Delaunay edge. It is a closed polygon for any interal Delaunay edge. At a //
32392 // ridge, it is unbounded.  Each Voronoi cell is the convex hull of all Vor- //
32393 // onoi vertices around a common Delaunay vertex. It is a polytope for any   //
32394 // internal Delaunay vertex. It is an unbounded polyhedron for a Delaunay    //
32395 // vertex belonging to the convex hull.                                      //
32396 //                                                                           //
32398 
32399 void tetgenmesh::outvoronoi(tetgenio* out)
32400 {
32401   FILE *outfile;
32402   char outfilename[FILENAMESIZE];
32403   tetgenio::voroedge *vedge;
32404   tetgenio::vorofacet *vfacet;
32405   list *tetlist, *ptlist;
32406   triface tetloop, worktet, spintet;
32407   point pt[4], ptloop, neipt;
32408   REAL ccent[3], infvec[3], vec1[3], vec2[3], L;
32409   long faces, edges;
32410   int *tetfaceindexarray, *tetedgeindexarray;
32411   int arraysize, *vertarray;
32412   int vpointcount, vedgecount, vfacecount, tcount;
32413   int index, shift;
32414   int end1, end2;
32415   int hitbdry, i, j, k;
32416 
32417   vedge = NULL;
32418   vertarray = NULL;
32419   vfacet = NULL;
32420   k = 0;
32421 
32422   // Output Voronoi vertices to .v.node file.
32423   if (out == (tetgenio *) NULL) {
32424     strcpy(outfilename, b->outfilename);
32425     strcat(outfilename, ".v.node");
32426   }
32427 
32428   if (!b->quiet) {
32429     if (out == (tetgenio *) NULL) {
32430       printf("Writing %s.\n", outfilename);
32431     } else {
32432       printf("Writing Voronoi vertices.\n");
32433     }
32434   }
32435 
32436   // Determine the first index (0 or 1).
32437   shift = (b->zeroindex ? 0 : in->firstnumber);
32438   // The number of Delaunay faces (= the number of Voronoi edges).
32439   faces = (4l * tetrahedrons->items + hullsize) / 2l;
32440   // The number of Delaunay edges (= the number of Voronoi faces).
32441   edges = points->items + faces - tetrahedrons->items - 1;
32442   outfile = (FILE *) NULL; // Avoid compile warnings.
32443 
32444   if (out == (tetgenio *) NULL) {
32445     outfile = fopen(outfilename, "w");
32446     if (outfile == (FILE *) NULL) {
32447       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32448       terminatetetgen(1);
32449     }
32450     // Number of voronoi points, 3 dim, no attributes, no marker.
32451     fprintf(outfile, "%ld  3  0  0\n", tetrahedrons->items);
32452   } else {
32453     // Allocate space for 'vpointlist'.
32454     out->numberofvpoints = (int) tetrahedrons->items;
32455     out->vpointlist = new REAL[out->numberofvpoints * 3];
32456     if (out->vpointlist == (REAL *) NULL) {
32457       printf("Error:  Out of memory.\n");
32458       terminatetetgen(1);
32459     }
32460   }
32461 
32462   // Loop the tetrahedronlist once, do the following:
32463   //   (1) Output Voronoi vertices (the circumcenter of the tetrahedron).
32464   //   (2) Make a map from points-to-tetrahedra (for Voronoi cells).
32465   tetrahedrons->traversalinit();
32466   tetloop.tet = tetrahedrontraverse();
32467   vpointcount = 0;
32468   index = 0;
32469   while (tetloop.tet != (tetrahedron *) NULL) {
32470     // Calculate the circumcenter.
32471     for (i = 0; i < 4; i++) {
32472       pt[i] = (point) tetloop.tet[4 + i];
32473       setpoint2tet(pt[i], encode(tetloop));
32474     }
32475     circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
32476     if (out == (tetgenio *) NULL) {
32477       fprintf(outfile, "%4d  %16.8e %16.8e %16.8e\n", vpointcount + shift,
32478               ccent[0], ccent[1], ccent[2]);
32479     } else {
32480       out->vpointlist[index++] = ccent[0];
32481       out->vpointlist[index++] = ccent[1];
32482       out->vpointlist[index++] = ccent[2];
32483     }
32484     // Remember the index of this element.
32485     * (int *) (tetloop.tet + elemmarkerindex) = vpointcount;
32486     vpointcount++;
32487     tetloop.tet = tetrahedrontraverse();
32488   }
32489   // Set the outside element marker.
32490   * (int *) (dummytet + elemmarkerindex) = -1;
32491 
32492   if (out == (tetgenio *) NULL) {
32493     fprintf(outfile, "# Generated by %s\n", b->commandline);
32494     fclose(outfile);
32495   }
32496 
32497   // Output Voronoi edges to .v.edge file.
32498   if (out == (tetgenio *) NULL) {
32499     strcpy(outfilename, b->outfilename);
32500     strcat(outfilename, ".v.edge");
32501   }
32502 
32503   if (!b->quiet) {
32504     if (out == (tetgenio *) NULL) {
32505       printf("Writing %s.\n", outfilename);
32506     } else {
32507       printf("Writing Voronoi edges.\n");
32508     }
32509   }
32510 
32511   if (out == (tetgenio *) NULL) {
32512     outfile = fopen(outfilename, "w");
32513     if (outfile == (FILE *) NULL) {
32514       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32515       terminatetetgen(1);
32516     }
32517     // Number of Voronoi edges, no marker.
32518     fprintf(outfile, "%ld  0\n", faces);
32519   } else {
32520     // Allocate space for 'vpointlist'.
32521     out->numberofedges = (int) faces;
32522     out->vedgelist = new tetgenio::voroedge[out->numberofvedges];
32523   }
32524 
32525   // Loop the tetrahedronlist once, output the Voronoi edges. The index of
32526   //   each Voronoi edge corresponding to the index of the Delaunay face.
32527   //   The four faces' indices of each tetrahedron are saved in the list
32528   //   'tetfaceindexarray', in the entry of i,  where i (0-based) is the
32529   //   index of this tetrahedron (= vpointcount).
32530   tetfaceindexarray = new int[tetrahedrons->items * 4];
32531   tetrahedrons->traversalinit();
32532   tetloop.tet = tetrahedrontraverse();
32533   vedgecount = 0;
32534   index = 0;
32535   while (tetloop.tet != (tetrahedron *) NULL) {
32536     // Count the number of Voronoi edges. Look at the four faces of each
32537     //   tetrahedron. Count the face if the tetrahedron's pointer is
32538     //   smaller than its neighbor's or the neighbor is outside.
32539     end1 = * (int *) (tetloop.tet + elemmarkerindex);
32540     for (i = 0; i < 4; i++) {
32541       decode(tetloop.tet[i], worktet);
32542       if ((worktet.tet == dummytet) || (tetloop.tet < worktet.tet)) {
32543         if (out == (tetgenio *) NULL) {
32544           fprintf(outfile, "%4d  %4d", vedgecount + shift, end1 + shift);
32545         } else {
32546           vedge = &(out->vedgelist[index++]);
32547           vedge->v1 = end1 + shift;
32548         }
32549         end2 = * (int *) (worktet.tet + elemmarkerindex);
32550         // Note that end2 may be -1 (worktet.tet is outside).
32551         if (end2 == -1) {
32552           // Calculate the out normal of this hull face.
32553           worktet.tet = tetloop.tet;
32554           worktet.loc = i;
32555           worktet.ver = 1; // The CW edge ring.
32556           pt[0] = org(worktet);
32557           pt[1] = dest(worktet);
32558           pt[2] = apex(worktet);
32559           for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j];
32560           for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j];
32561           cross(vec1, vec2, infvec);
32562           // Normalize it.
32563           L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1]
32564                    + infvec[2] * infvec[2]);
32565           if (L > 0) for (j = 0; j < 3; j++) infvec[j] /= L;
32566           if (out == (tetgenio *) NULL) {
32567             fprintf(outfile, " -1");
32568             fprintf(outfile, " %g %g %g\n", infvec[0], infvec[1], infvec[2]);
32569           } else {
32570             vedge->v2 = -1;
32571             vedge->vnormal[0] = infvec[0];
32572             vedge->vnormal[1] = infvec[1];
32573             vedge->vnormal[2] = infvec[2];
32574           }
32575         } else {
32576           if (out == (tetgenio *) NULL) {
32577             fprintf(outfile, " %4d\n", end2 + shift);
32578           } else {
32579             vedge->v2 = end2 + shift;
32580             vedge->vnormal[0] = 0.0;
32581             vedge->vnormal[1] = 0.0;
32582             vedge->vnormal[2] = 0.0;
32583           }
32584         }
32585         // Save the face index in this tet and its neighbor if exists.
32586         tetfaceindexarray[end1 * 4 + i] = vedgecount;
32587         if (end2 != -1) {
32588           tetfaceindexarray[end2 * 4 + worktet.loc] = vedgecount;
32589         }
32590         vedgecount++;
32591       }
32592     }
32593     tetloop.tet = tetrahedrontraverse();
32594   }
32595 
32596   if (out == (tetgenio *) NULL) {
32597     fprintf(outfile, "# Generated by %s\n", b->commandline);
32598     fclose(outfile);
32599   }
32600 
32601   // Output Voronoi faces to .v.face file.
32602   if (out == (tetgenio *) NULL) {
32603     strcpy(outfilename, b->outfilename);
32604     strcat(outfilename, ".v.face");
32605   }
32606 
32607   if (!b->quiet) {
32608     if (out == (tetgenio *) NULL) {
32609       printf("Writing %s.\n", outfilename);
32610     } else {
32611       printf("Writing Voronoi faces.\n");
32612     }
32613   }
32614 
32615   if (out == (tetgenio *) NULL) {
32616     outfile = fopen(outfilename, "w");
32617     if (outfile == (FILE *) NULL) {
32618       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32619       terminatetetgen(1);
32620     }
32621     // Number of Voronoi faces.
32622     fprintf(outfile, "%ld  0\n", edges);
32623   } else {
32624     out->numberofvfacets = edges;
32625     out->vfacetlist = new tetgenio::vorofacet[out->numberofvfacets];
32626     if (out->vfacetlist == (tetgenio::vorofacet *) NULL) {
32627       printf("Error:  Out of memory.\n");
32628       terminatetetgen(1);
32629     }
32630   }
32631 
32632   // Loop the tetrahedronlist once, Output Voronoi facets. The index of each
32633   //   Voronoi facet corresponding to the index of the Delaunay edge.  The
32634   //   six edges' indices of each tetrahedron are saved in the list 'tetedge-
32635   //   indexarray', in the entry of i,  where i (0-based) is the index of
32636   //   this tetrahedron (= vpointcount).
32637   tetedgeindexarray = new int[tetrahedrons->items * 6];
32638   tetrahedrons->traversalinit();
32639   tetloop.tet = tetrahedrontraverse();
32640   vfacecount = 0;
32641   while (tetloop.tet != (tetrahedron *) NULL) {
32642     // Count the number of Voronoi faces. Look at the six edges of each
32643     //   tetrahedron. Count the edge only if the tetrahedron's pointer is
32644     //   smaller than those of all other tetrahedra that share the edge.
32645     worktet = tetloop;
32646     for (i = 0; i < 6; i++) {
32647       worktet.loc = edge2locver[i][0];
32648       worktet.ver = edge2locver[i][1];
32649       // Now count the number of tets surrounding this edge.
32650       tcount = 1;
32651       adjustedgering(worktet, CW);
32652       spintet = worktet;
32653       hitbdry = 0;
32654       while (hitbdry < 2) {
32655         if (fnextself(spintet)) {
32656           if (apex(spintet) == apex(worktet)) break;
32657           if (spintet.tet < worktet.tet) break;
32658           tcount++;
32659         } else {
32660           hitbdry++;
32661           if (hitbdry < 2) {
32662             esym(worktet, spintet);
32663             fnextself(spintet); // In the same tet.
32664       }
32665         }
32666       }
32667       // Count this edge if no adjacent tets are smaller than this tet.
32668       if (spintet.tet >= worktet.tet) {
32669         // Get the two endpoints of this edge.
32670         pt[0] = org(worktet);
32671         pt[1] = dest(worktet);
32672         end1 = pointmark(pt[0]) - in->firstnumber;
32673         end2 = pointmark(pt[1]) - in->firstnumber;
32674         if (out == (tetgenio *) NULL) {
32675           fprintf(outfile, "%4d  %4d %4d  %-2d ", vfacecount + shift,
32676                   end1 + shift, end2 + shift, tcount + (hitbdry > 0));
32677         } else {
32678           vfacet = &(out->vfacetlist[vfacecount]);
32679           vfacet->c1 = end1 + shift;
32680           vfacet->c2 = end2 + shift;
32681           vfacet->elist = new int[tcount + (hitbdry > 0) + 1];
32682           vfacet->elist[0] = tcount + (hitbdry > 0);
32683           index = 1;
32684         }
32685         // If hitbdry > 0, then spintet is a hull face.
32686         if (hitbdry > 0) {
32687           // The edge list starts with a ray.
32688           vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32689           vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32690           if (out == (tetgenio *) NULL) {
32691             fprintf(outfile, " %d", vedgecount + shift);
32692           } else {
32693             vfacet->elist[index++] = vedgecount + shift;
32694           }
32695           // Save this facet number in tet.
32696           tetedgeindexarray[vpointcount * 6 +
32697             locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32698           esymself(spintet);
32699           fnextself(spintet); // In the same tet.
32700         }
32701         // Output internal Voronoi edges.
32702         for (j = 0; j < tcount; j++) {
32703           vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32704           vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32705           if (out == (tetgenio *) NULL) {
32706             fprintf(outfile, " %d", vedgecount + shift);
32707           } else {
32708             vfacet->elist[index++] = vedgecount + shift;
32709           }
32710           // Save this facet number in tet.
32711           tetedgeindexarray[vpointcount * 6 +
32712             locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32713           fnextself(spintet);
32714         }
32715         if (out == (tetgenio *) NULL) {
32716           fprintf(outfile, "\n");
32717         }
32718         vfacecount++;
32719       }
32720     } // if (i = 0; i < 6; i++)
32721     tetloop.tet = tetrahedrontraverse();
32722   }
32723 
32724   if (out == (tetgenio *) NULL) {
32725     fprintf(outfile, "# Generated by %s\n", b->commandline);
32726     fclose(outfile);
32727   }
32728 
32729   // Output Voronoi cells to .v.cell file.
32730   if (out == (tetgenio *) NULL) {
32731     strcpy(outfilename, b->outfilename);
32732     strcat(outfilename, ".v.cell");
32733   }
32734 
32735   if (!b->quiet) {
32736     if (out == (tetgenio *) NULL) {
32737       printf("Writing %s.\n", outfilename);
32738     } else {
32739       printf("Writing Voronoi cells.\n");
32740     }
32741   }
32742 
32743   if (out == (tetgenio *) NULL) {
32744     outfile = fopen(outfilename, "w");
32745     if (outfile == (FILE *) NULL) {
32746       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32747       terminatetetgen(1);
32748     }
32749     // Number of Voronoi cells.
32750     fprintf(outfile, "%ld\n", points->items);
32751   } else {
32752     out->numberofvcells = points->items;
32753     out->vcelllist = new int*[out->numberofvcells];
32754     if (out->vcelllist == (int **) NULL) {
32755       printf("Error:  Out of memory.\n");
32756       terminatetetgen(1);
32757     }
32758   }
32759 
32760   // Loop through point list, for each point, output a Voronoi cell.
32761   tetlist = new list(sizeof(triface), NULL, 256);
32762   ptlist = new list(sizeof(point *), NULL, 256);
32763   points->traversalinit();
32764   ptloop = pointtraverse();
32765   vpointcount = 0;
32766   while (ptloop != (point) NULL) {
32767     decode(point2tet(ptloop), tetloop);
32768     // assert(!isdead(&tetloop));
32769     if (!isdead(&tetloop)) {
32770       // Form the star of p.
32771       tetlist->append(&tetloop);
32772       formstarpolyhedron(ptloop, tetlist, ptlist, true);
32773       tcount = ptlist->len();
32774       if (out == (tetgenio *) NULL) {
32775         fprintf(outfile, "%4d  %-2d ", vpointcount + shift, tcount);
32776       } else {
32777         arraysize = tcount;
32778         vertarray = out->vcelllist[vpointcount];
32779         vertarray = new int[arraysize + 1];
32780         vertarray[0] = arraysize;
32781         index = 1;
32782       }
32783       // List Voronoi facets bounding this cell.
32784       for (i = 0; i < ptlist->len(); i++) {
32785         neipt =  * (point *)(* ptlist)[i];
32786         // Find a tet in tetlist having edge (ptloop, neipt) -- Very Slow.
32787         for (j = 0; j < tetlist->len(); j++) {
32788           tetloop = * (triface *)(* tetlist)[j];
32789           for (k = 0; k < 6; k++) {
32790             tetloop.loc = edge2locver[k][0];
32791             tetloop.ver = edge2locver[k][1];
32792             if (org(tetloop) == ptloop) {
32793               if (dest(tetloop) == neipt) break;
32794             } else if (org(tetloop) == neipt) {
32795               if (dest(tetloop) == ptloop) break;
32796             }
32797           }
32798           if (k < 6) break; // Found this edge.
32799         }
32800         assert(j < tetlist->len());
32801         // k is the right edge number.
32802         end1 = * (int *) (tetloop.tet + elemmarkerindex);
32803         vfacecount = tetedgeindexarray[end1 * 6 + k];
32804         if (out == (tetgenio *) NULL) {
32805           fprintf(outfile, " %d", vfacecount + shift);
32806         } else {
32807           vertarray[index++] = vfacecount + shift;
32808         }
32809       } // for (i = 0; i < ptlist->len(); i++) {
32810       if (out == (tetgenio *) NULL) {
32811         fprintf(outfile, "\n");
32812       }
32813       vpointcount++;
32814     }
32815     tetlist->clear();
32816     ptlist->clear();
32817     ptloop = pointtraverse();
32818   }
32819   delete tetlist;
32820   delete ptlist;
32821   delete [] tetfaceindexarray;
32822   delete [] tetedgeindexarray;
32823 
32824   if (out == (tetgenio *) NULL) {
32825     fprintf(outfile, "# Generated by %s\n", b->commandline);
32826     fclose(outfile);
32827   }
32828 }
32829 
32831 //                                                                           //
32832 // outpbcnodes()    Output pbc node pairs to a .pbc file or a structure.     //
32833 //                                                                           //
32835 
32836 void tetgenmesh::outpbcnodes(tetgenio* out)
32837 {
32838   FILE *outfile;
32839   char pbcfilename[FILENAMESIZE];
32840   list *ptpairlist;
32841   tetgenio::pbcgroup *pgi, *pgo;
32842   pbcdata *pd;
32843   face faceloop;
32844   face checkseg, symseg;
32845   point *ptpair, pa, pb;
32846   enum locateresult loc;
32847   REAL sympt[3], d1, d2;
32848   int *worklist;
32849   int firstindex, shift;
32850   int index, idx;
32851   int i, j, k, l;
32852 
32853   if (out == (tetgenio *) NULL) {
32854     strcpy(pbcfilename, b->outfilename);
32855     strcat(pbcfilename, ".pbc");
32856   }
32857 
32858   if (!b->quiet) {
32859     if (out == (tetgenio *) NULL) {
32860       printf("Writing %s.\n", pbcfilename);
32861     } else {
32862       printf("Writing pbc nodes.\n");
32863     }
32864   }
32865 
32866   // Avoid compilation warnings.
32867   outfile = (FILE *) NULL;
32868   pgo = (tetgenio::pbcgroup *) NULL;
32869   index = 0;
32870 
32871   if (out == (tetgenio *) NULL) {
32872     outfile = fopen(pbcfilename, "w");
32873     if (outfile == (FILE *) NULL) {
32874       printf("File I/O Error:  Cannot create file %s.\n", pbcfilename);
32875       terminatetetgen(1);
32876     }
32877     // Number of pbc groups.
32878     fprintf(outfile, "# number of PBCs.\n");
32879     fprintf(outfile, "%d\n\n", in->numberofpbcgroups);
32880   } else {
32881     out->numberofpbcgroups = in->numberofpbcgroups;
32882     // Allocate memory for 'out->pbcgrouplist'.
32883     out->pbcgrouplist = new tetgenio::pbcgroup[in->numberofpbcgroups];
32884     // (Next line was a bug, reported by Murry Nigel).
32885     if (out->pbcgrouplist == (tetgenio::pbcgroup *) NULL) {
32886       printf("Error:  Out of memory.\n");
32887       terminatetetgen(1);
32888     }
32889   }
32890 
32891   ptpairlist = new list(2 * sizeof(point *), NULL, 256);
32892   worklist = new int[points->items + 1];
32893   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
32894 
32895   // Determine the first index (0 or 1).
32896   firstindex = b->zeroindex ? 0 : in->firstnumber;
32897   shift = 0; // Default no shiftment.
32898   if ((in->firstnumber == 1) && (firstindex == 0)) {
32899     shift = 1; // Shift the output indices by 1.
32900   }
32901 
32902   for (i = 0; i < in->numberofpbcgroups; i++) {
32903     // Group i.
32904     pgi = &(in->pbcgrouplist[i]);
32905     if (out == (tetgenio *) NULL) {
32906       fprintf(outfile, "# PBC %d\n", in->firstnumber + i);
32907       // Output facet markers.
32908       fprintf(outfile, "%d  %d\n", pgi->fmark1, pgi->fmark2);
32909       // Output transformation matrix.
32910       fprintf(outfile, "[\n");
32911       for (j = 0; j < 4; j++) {
32912         fprintf(outfile, "  %.12g %.12g %.12g %.12g\n", pgi->transmat[j][0],
32913                 pgi->transmat[j][1], pgi->transmat[j][2], pgi->transmat[j][3]);
32914       }
32915       fprintf(outfile, "]\n");
32916     } else {
32917       pgo = &(out->pbcgrouplist[i]);
32918       // Copy data from pgi to pgo.
32919       pgo->fmark1 = pgi->fmark1;
32920       pgo->fmark2 = pgi->fmark2;
32921       for (j = 0; j < 4; j++) {
32922         for (k = 0; k < 4; k++) pgo->transmat[j][k] = pgi->transmat[j][k];
32923       }
32924     }
32925 
32926     // Find the point pairs of group i.
32927     subfaces->traversalinit();
32928     faceloop.sh = shellfacetraverse(subfaces);
32929     while (faceloop.sh != (shellface *) NULL) {
32930       if (shellpbcgroup(faceloop) == i) {
32931         // It is in group i. Operate on it if it has pgi->fmark1.
32932         idx = shellmark(faceloop) - 1;
32933         if (in->facetmarkerlist[idx] == pgi->fmark1) {
32934           // Loop three edges of the subface.
32935           for (j = 0; j < 3; j++) {
32936             sspivot(faceloop, checkseg);
32937             // Loop two vertices of the edge.
32938             for (k = 0; k < 2; k++) {
32939               if (k == 0) pa = sorg(faceloop);
32940               else pa = sdest(faceloop);
32941               if (worklist[pointmark(pa)] == 0) {
32942                 pb = (point) NULL;
32943                 if (checkseg.sh != dummysh) {
32944                   // pa is on a segment. Find pb.
32945                   // Find the incident pbcgroup of checkseg.
32946                   idx = shellmark(checkseg) - 1;
32947                   for (l = idx2segpglist[idx]; l < idx2segpglist[idx + 1];
32948                        l++) {
32949                     pd = (pbcdata *)(* segpbcgrouptable)[segpglist[l]];
32950                     if (((pd->fmark[0] == pgi->fmark1) &&
32951                          (pd->fmark[1] == pgi->fmark2)) ||
32952                         ((pd->fmark[0] == pgi->fmark2) &&
32953                          (pd->fmark[1] == pgi->fmark1))) break;
32954                   }
32955 #ifdef SELF_CHECK
32956                   assert(l < idx2segpglist[idx + 1]);
32957 #endif
32958                   loc = getsegpbcsympoint(pa, &checkseg, sympt, &symseg,
32959                                           segpglist[l]);
32960                   if (loc != ONVERTEX) {
32961                     // Not found a match point! It may be caused by the
32962                     //   pair of input vertices don't have enough digits.
32963                     //   Choose a near vertex.
32964                     d1 = distance(sympt, sorg(symseg));
32965                     d2 = distance(sympt, sdest(symseg));
32966                     if (d1 > d2) sesymself(symseg);
32967                   }
32968                   pb = sorg(symseg);
32969                 } else {
32970                   // Operate on pa if it is inside the facet.
32971                   if (pointtype(pa) == FREESUBVERTEX) {
32972                     pb = point2pbcpt(pa);
32973                   }
32974                 }
32975                 if (pb != (point) NULL) {
32976                   // Add the pair (pa, pb) into list.
32977                   ptpair = (point *) ptpairlist->append(NULL);
32978                   ptpair[0] = pa;
32979                   ptpair[1] = pb;
32980                   // Mark pa (avoid to operate on it later).
32981                   worklist[pointmark(pa)] = 1;
32982                 }
32983               }
32984             }
32985             // Get the next edge.
32986             senextself(faceloop);
32987           }
32988         }
32989       }
32990       faceloop.sh = shellfacetraverse(subfaces);
32991     }
32992 
32993     // Output the list of pbc points.
32994     if (out == (tetgenio *) NULL) {
32995       fprintf(outfile, "%d\n", ptpairlist->len());
32996     } else {
32997       pgo->numberofpointpairs = ptpairlist->len();
32998       pgo->pointpairlist = new int[pgo->numberofpointpairs * 2];
32999       index = 0;
33000     }
33001     for (j = 0; j < ptpairlist->len(); j++) {
33002       ptpair = (point *)(* ptpairlist)[j];
33003       pa = ptpair[0];
33004       pb = ptpair[1];
33005       if (out == (tetgenio *) NULL) {
33006         fprintf(outfile, "  %4d %4d\n", pointmark(pa) - shift,
33007                 pointmark(pb) - shift);
33008       } else {
33009         pgo->pointpairlist[index++] = pointmark(pa) - shift;
33010         pgo->pointpairlist[index++] = pointmark(pb) - shift;
33011       }
33012       // Unmark pa.
33013       worklist[pointmark(pa)] = 0;
33014     }
33015     if (out == (tetgenio *) NULL) {
33016       fprintf(outfile, "\n");
33017     }
33018     ptpairlist->clear();
33019   }
33020 
33021   delete [] worklist;
33022   delete ptpairlist;
33023 
33024   if (out == (tetgenio *) NULL) {
33025     fprintf(outfile, "# Generated by %s\n", b->commandline);
33026     fclose(outfile);
33027   }
33028 }
33029 
33031 //                                                                           //
33032 // outsmesh()    Write surface mesh to a .smesh file, which can be read and  //
33033 //               tetrahedralized by TetGen.                                  //
33034 //                                                                           //
33035 // You can specify a filename (without suffix) in 'smfilename'. If you don't //
33036 // supply a filename (let smfilename be NULL), the default name stored in    //
33037 // 'tetgenbehavior' will be used.                                            //
33038 //                                                                           //
33040 
33041 void tetgenmesh::outsmesh(char* smfilename)
33042 {
33043   FILE *outfile;
33044   char nodfilename[FILENAMESIZE];
33045   char smefilename[FILENAMESIZE];
33046   face faceloop;
33047   point p1, p2, p3;
33048   int firstindex, shift;
33049   int bmark;
33050   int faceid, marker;
33051   int i;
33052 
33053   if (smfilename != (char *) NULL && smfilename[0] != '\0') {
33054     strcpy(smefilename, smfilename);
33055   } else if (b->outfilename[0] != '\0') {
33056     strcpy(smefilename, b->outfilename);
33057   } else {
33058     strcpy(smefilename, "unnamed");
33059   }
33060   strcpy(nodfilename, smefilename);
33061   strcat(smefilename, ".smesh");
33062   strcat(nodfilename, ".node");
33063 
33064   if (!b->quiet) {
33065     printf("Writing %s.\n", smefilename);
33066   }
33067   outfile = fopen(smefilename, "w");
33068   if (outfile == (FILE *) NULL) {
33069     printf("File I/O Error:  Cannot create file %s.\n", smefilename);
33070     return;
33071   }
33072 
33073   // Determine the first index (0 or 1).
33074   firstindex = b->zeroindex ? 0 : in->firstnumber;
33075   shift = 0; // Default no shiftment.
33076   if ((in->firstnumber == 1) && (firstindex == 0)) {
33077     shift = 1; // Shift the output indices by 1.
33078   }
33079 
33080   fprintf(outfile, "# %s.  TetGen's input file.\n", smefilename);
33081   fprintf(outfile, "\n# part 1: node list.\n");
33082   fprintf(outfile, "0  3  0  0  # nodes are found in %s.\n", nodfilename);
33083 
33084   marker = 0; // avoid compile warning.
33085   bmark = !b->nobound && in->facetmarkerlist;
33086 
33087   fprintf(outfile, "\n# part 2: facet list.\n");
33088   // Number of facets, boundary marker.
33089   fprintf(outfile, "%ld  %d\n", subfaces->items, bmark);
33090 
33091   subfaces->traversalinit();
33092   faceloop.sh = shellfacetraverse(subfaces);
33093   while (faceloop.sh != (shellface *) NULL) {
33094     p1 = sorg(faceloop);
33095     p2 = sdest(faceloop);
33096     p3 = sapex(faceloop);
33097     if (bmark) {
33098       faceid = shellmark(faceloop) - 1;
33099       if (faceid >= 0) {
33100         marker = in->facetmarkerlist[faceid];
33101       } else {
33102         marker = 0; // This subface must be added manually later.
33103       }
33104     }
33105     fprintf(outfile, "3    %4d  %4d  %4d", pointmark(p1) - shift,
33106             pointmark(p2) - shift, pointmark(p3) - shift);
33107     if (bmark) {
33108       fprintf(outfile, "    %d", marker);
33109     }
33110     fprintf(outfile, "\n");
33111     faceloop.sh = shellfacetraverse(subfaces);
33112   }
33113 
33114   // Copy input holelist.
33115   fprintf(outfile, "\n# part 3: hole list.\n");
33116   fprintf(outfile, "%d\n", in->numberofholes);
33117   for (i = 0; i < in->numberofholes; i++) {
33118     fprintf(outfile, "%d  %g  %g  %g\n", i + in->firstnumber,
33119             in->holelist[i * 3], in->holelist[i * 3 + 1],
33120             in->holelist[i * 3 + 2]);
33121   }
33122 
33123   // Copy input regionlist.
33124   fprintf(outfile, "\n# part 4: region list.\n");
33125   fprintf(outfile, "%d\n", in->numberofregions);
33126   for (i = 0; i < in->numberofregions; i++) {
33127     fprintf(outfile, "%d  %g  %g  %g  %d  %g\n", i + in->firstnumber,
33128             in->regionlist[i * 5], in->regionlist[i * 5 + 1],
33129             in->regionlist[i * 5 + 2], (int) in->regionlist[i * 5 + 3],
33130             in->regionlist[i * 5 + 4]);
33131   }
33132 
33133   fprintf(outfile, "# Generated by %s\n", b->commandline);
33134   fclose(outfile);
33135 }
33136 
33138 //                                                                           //
33139 // outmesh2medit()    Write mesh to a .mesh file, which can be read and      //
33140 //                    rendered by Medit (a free mesh viewer from INRIA).     //
33141 //                                                                           //
33142 // You can specify a filename (without suffix) in 'mfilename'.  If you don't //
33143 // supply a filename (let mfilename be NULL), the default name stored in     //
33144 // 'tetgenbehavior' will be used. The output file will have the suffix .mesh.//
33145 //                                                                           //
33147 
33148 void tetgenmesh::outmesh2medit(char* mfilename)
33149 {
33150   FILE *outfile;
33151   char mefilename[FILENAMESIZE];
33152   tetrahedron* tetptr;
33153   triface tface, tsymface;
33154   face segloop, checkmark;
33155   point ptloop, p1, p2, p3, p4;
33156   long faces;
33157   int pointnumber;
33158   int i;
33159 
33160   if (mfilename != (char *) NULL && mfilename[0] != '\0') {
33161     strcpy(mefilename, mfilename);
33162   } else if (b->outfilename[0] != '\0') {
33163     strcpy(mefilename, b->outfilename);
33164   } else {
33165     strcpy(mefilename, "unnamed");
33166   }
33167   strcat(mefilename, ".mesh");
33168 
33169   if (!b->quiet) {
33170     printf("Writing %s.\n", mefilename);
33171   }
33172   outfile = fopen(mefilename, "w");
33173   if (outfile == (FILE *) NULL) {
33174     printf("File I/O Error:  Cannot create file %s.\n", mefilename);
33175     return;
33176   }
33177 
33178   fprintf(outfile, "MeshVersionFormatted 1\n");
33179   fprintf(outfile, "\n");
33180   fprintf(outfile, "Dimension\n");
33181   fprintf(outfile, "3\n");
33182   fprintf(outfile, "\n");
33183 
33184   fprintf(outfile, "\n# Set of mesh vertices\n");
33185   fprintf(outfile, "Vertices\n");
33186   fprintf(outfile, "%ld\n", points->items);
33187 
33188   points->traversalinit();
33189   ptloop = pointtraverse();
33190   pointnumber = 1;                        // Medit need start number form 1.
33191   while (ptloop != (point) NULL) {
33192     // Point coordinates.
33193     fprintf(outfile, "%.17g  %.17g  %.17g", ptloop[0], ptloop[1], ptloop[2]);
33194     if (in->numberofpointattributes > 0) {
33195       // Write an attribute, ignore others if more than one.
33196       fprintf(outfile, "  %.17g\n", ptloop[3]);
33197     } else {
33198       fprintf(outfile, "    0\n");
33199     }
33200     setpointmark(ptloop, pointnumber);
33201     ptloop = pointtraverse();
33202     pointnumber++;
33203   }
33204 
33205   // Compute the number of edges.
33206   faces = (4l * tetrahedrons->items + hullsize) / 2l;
33207 
33208   fprintf(outfile, "\n# Set of Triangles\n");
33209   fprintf(outfile, "Triangles\n");
33210   fprintf(outfile, "%ld\n", faces);
33211 
33212   tetrahedrons->traversalinit();
33213   tface.tet = tetrahedrontraverse();
33214   // To loop over the set of faces, loop over all tetrahedra, and look at
33215   //   the four faces of each tetrahedron. If there isn't another tetrahedron
33216   //   adjacent to the face, operate on the face.  If there is another adj-
33217   //   acent tetrahedron, operate on the face only if the current tetrahedron
33218   //   has a smaller pointer than its neighbor.  This way, each face is
33219   //   considered only once.
33220   while (tface.tet != (tetrahedron *) NULL) {
33221     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33222       sym(tface, tsymface);
33223       if (tface.tet < tsymface.tet || tsymface.tet == dummytet) {
33224         p1 = org (tface);
33225         p2 = dest(tface);
33226         p3 = apex(tface);
33227         fprintf(outfile, "%5d  %5d  %5d",
33228                 pointmark(p1), pointmark(p2), pointmark(p3));
33229         fprintf(outfile, "    0\n");
33230       }
33231     }
33232     tface.tet = tetrahedrontraverse();
33233   }
33234 
33235   fprintf(outfile, "\n# Set of Tetrahedra\n");
33236   fprintf(outfile, "Tetrahedra\n");
33237   fprintf(outfile, "%ld\n", tetrahedrons->items);
33238 
33239   tetrahedrons->traversalinit();
33240   tetptr = tetrahedrontraverse();
33241   while (tetptr != (tetrahedron *) NULL) {
33242     p1 = (point) tetptr[4];
33243     p2 = (point) tetptr[5];
33244     p3 = (point) tetptr[6];
33245     p4 = (point) tetptr[7];
33246     fprintf(outfile, "%5d  %5d  %5d  %5d",
33247             pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33248     if (in->numberoftetrahedronattributes > 0) {
33249       fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
33250     } else {
33251       fprintf(outfile, "  0");
33252     }
33253     fprintf(outfile, "\n");
33254     tetptr = tetrahedrontraverse();
33255   }
33256 
33257   fprintf(outfile, "\nCorners\n");
33258   fprintf(outfile, "%d\n", in->numberofpoints);
33259 
33260   for (i = 0; i < in->numberofpoints; i++) {
33261     fprintf(outfile, "%4d\n", i + 1);
33262   }
33263 
33264   if (b->useshelles) {
33265     fprintf(outfile, "\nEdges\n");
33266     fprintf(outfile, "%ld\n", subsegs->items);
33267 
33268     subsegs->traversalinit();
33269     segloop.sh = shellfacetraverse(subsegs);
33270     while (segloop.sh != (shellface *) NULL) {
33271       p1 = sorg(segloop);
33272       p2 = sdest(segloop);
33273       fprintf(outfile, "%5d  %5d", pointmark(p1), pointmark(p2));
33274       fprintf(outfile, "    0\n");
33275       segloop.sh = shellfacetraverse(subsegs);
33276     }
33277   }
33278 
33279   fprintf(outfile, "\nEnd\n");
33280   fclose(outfile);
33281 }
33282 
33284 //                                                                           //
33285 // outmesh2gid()    Write mesh to a .ele.msh file and a .face.msh file,      //
33286 //                  which can be imported and rendered by Gid.               //
33287 //                                                                           //
33288 // You can specify a filename (without suffix) in 'gfilename'.  If you don't //
33289 // supply a filename (let gfilename be NULL), the default name stored in     //
33290 // 'tetgenbehavior' will be used. The suffixes (.ele.msh and .face.msh) will //
33291 // be automatically added.                                                   //
33292 //                                                                           //
33294 
33295 void tetgenmesh::outmesh2gid(char* gfilename)
33296 {
33297   FILE *outfile;
33298   char gidfilename[FILENAMESIZE];
33299   tetrahedron* tetptr;
33300   triface tface, tsymface;
33301   face sface;
33302   point ptloop, p1, p2, p3, p4;
33303   int pointnumber;
33304   int elementnumber;
33305 
33306   if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33307     strcpy(gidfilename, gfilename);
33308   } else if (b->outfilename[0] != '\0') {
33309     strcpy(gidfilename, b->outfilename);
33310   } else {
33311     strcpy(gidfilename, "unnamed");
33312   }
33313   strcat(gidfilename, ".ele.msh");
33314 
33315   if (!b->quiet) {
33316     printf("Writing %s.\n", gidfilename);
33317   }
33318   outfile = fopen(gidfilename, "w");
33319   if (outfile == (FILE *) NULL) {
33320     printf("File I/O Error:  Cannot create file %s.\n", gidfilename);
33321     return;
33322   }
33323 
33324   fprintf(outfile, "mesh dimension = 3 elemtype tetrahedron nnode = 4\n");
33325   fprintf(outfile, "coordinates\n");
33326 
33327   points->traversalinit();
33328   ptloop = pointtraverse();
33329   pointnumber = 1;                        // Gid need start number form 1.
33330   while (ptloop != (point) NULL) {
33331     // Point coordinates.
33332     fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
33333             ptloop[0], ptloop[1], ptloop[2]);
33334     if (in->numberofpointattributes > 0) {
33335       // Write an attribute, ignore others if more than one.
33336       fprintf(outfile, "  %.17g", ptloop[3]);
33337     }
33338     fprintf(outfile, "\n");
33339     setpointmark(ptloop, pointnumber);
33340     ptloop = pointtraverse();
33341     pointnumber++;
33342   }
33343 
33344   fprintf(outfile, "end coordinates\n");
33345   fprintf(outfile, "elements\n");
33346 
33347   tetrahedrons->traversalinit();
33348   tetptr = tetrahedrontraverse();
33349   elementnumber = 1;
33350   while (tetptr != (tetrahedron *) NULL) {
33351     p1 = (point) tetptr[4];
33352     p2 = (point) tetptr[5];
33353     p3 = (point) tetptr[6];
33354     p4 = (point) tetptr[7];
33355     fprintf(outfile, "%5d  %5d %5d %5d %5d", elementnumber,
33356             pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33357     if (in->numberoftetrahedronattributes > 0) {
33358       fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
33359     }
33360     fprintf(outfile, "\n");
33361     tetptr = tetrahedrontraverse();
33362     elementnumber++;
33363   }
33364 
33365   fprintf(outfile, "end elements\n");
33366   fclose(outfile);
33367 
33368   if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33369     strcpy(gidfilename, gfilename);
33370   } else if (b->outfilename[0] != '\0') {
33371     strcpy(gidfilename, b->outfilename);
33372   } else {
33373     strcpy(gidfilename, "unnamed");
33374   }
33375   strcat(gidfilename, ".face.msh");
33376 
33377   if (!b->quiet) {
33378     printf("Writing %s.\n", gidfilename);
33379   }
33380   outfile = fopen(gidfilename, "w");
33381   if (outfile == (FILE *) NULL) {
33382     printf("File I/O Error:  Cannot create file %s.\n", gidfilename);
33383     return;
33384   }
33385 
33386   fprintf(outfile, "mesh dimension = 3 elemtype triangle nnode = 3\n");
33387   fprintf(outfile, "coordinates\n");
33388 
33389   points->traversalinit();
33390   ptloop = pointtraverse();
33391   pointnumber = 1;                        // Gid need start number form 1.
33392   while (ptloop != (point) NULL) {
33393     // Point coordinates.
33394     fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
33395             ptloop[0], ptloop[1], ptloop[2]);
33396     if (in->numberofpointattributes > 0) {
33397       // Write an attribute, ignore others if more than one.
33398       fprintf(outfile, "  %.17g", ptloop[3]);
33399     }
33400     fprintf(outfile, "\n");
33401     setpointmark(ptloop, pointnumber);
33402     ptloop = pointtraverse();
33403     pointnumber++;
33404   }
33405 
33406   fprintf(outfile, "end coordinates\n");
33407   fprintf(outfile, "elements\n");
33408 
33409   tetrahedrons->traversalinit();
33410   tface.tet = tetrahedrontraverse();
33411   elementnumber = 1;
33412   while (tface.tet != (tetrahedron *) NULL) {
33413     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33414       sym(tface, tsymface);
33415       if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33416         p1 = org(tface);
33417         p2 = dest(tface);
33418         p3 = apex(tface);
33419         if (tsymface.tet == dummytet) {
33420           // It's a hull face, output it.
33421           fprintf(outfile, "%5d   %d  %d  %d\n", elementnumber,
33422                   pointmark(p1), pointmark(p2), pointmark(p3));
33423           elementnumber++;
33424         } else if (b->useshelles) {
33425           // Only output it if it's a subface.
33426           tspivot(tface, sface);
33427           if (sface.sh != dummysh) {
33428             fprintf(outfile, "%5d   %d  %d  %d\n", elementnumber,
33429                     pointmark(p1), pointmark(p2), pointmark(p3));
33430             elementnumber++;
33431           }
33432         }
33433       }
33434     }
33435     tface.tet = tetrahedrontraverse();
33436   }
33437 
33438   fprintf(outfile, "end elements\n");
33439   fclose(outfile);
33440 }
33441 
33443 //                                                                           //
33444 // outmesh2off()    Write the mesh to an .off file.                          //
33445 //                                                                           //
33446 // .off, the Object File Format, is one of the popular file formats from the //
33447 // Geometry Center's Geomview package (http://www.geomview.org).             //
33448 //                                                                           //
33450 
33451 void tetgenmesh::outmesh2off(char* ofilename)
33452 {
33453   FILE *outfile;
33454   char offfilename[FILENAMESIZE];
33455   triface tface, tsymface;
33456   point ptloop, p1, p2, p3;
33457   long faces;
33458   int shift;
33459 
33460   if (ofilename != (char *) NULL && ofilename[0] != '\0') {
33461     strcpy(offfilename, ofilename);
33462   } else if (b->outfilename[0] != '\0') {
33463     strcpy(offfilename, b->outfilename);
33464   } else {
33465     strcpy(offfilename, "unnamed");
33466   }
33467   strcat(offfilename, ".off");
33468 
33469   if (!b->quiet) {
33470     printf("Writing %s.\n", offfilename);
33471   }
33472   outfile = fopen(offfilename, "w");
33473   if (outfile == (FILE *) NULL) {
33474     printf("File I/O Error:  Cannot create file %s.\n", offfilename);
33475     return;
33476   }
33477 
33478   // Calculate the number of triangular faces in the tetrahedral mesh.
33479   faces = (4l * tetrahedrons->items + hullsize) / 2l;
33480 
33481   // Number of points, faces, and edges(not used, here show hullsize).
33482   fprintf(outfile, "OFF\n%ld  %ld  %ld\n", points->items, faces, hullsize);
33483 
33484   // Write the points.
33485   points->traversalinit();
33486   ptloop = pointtraverse();
33487   while (ptloop != (point) NULL) {
33488     fprintf(outfile, " %.17g  %.17g  %.17g\n",ptloop[0], ptloop[1], ptloop[2]);
33489     ptloop = pointtraverse();
33490   }
33491 
33492   // OFF always use zero as the first index.
33493   shift = in->firstnumber == 1 ? 1 : 0;
33494 
33495   tetrahedrons->traversalinit();
33496   tface.tet = tetrahedrontraverse();
33497   // To loop over the set of faces, loop over all tetrahedra, and look at
33498   //   the four faces of each tetrahedron. If there isn't another tetrahedron
33499   //   adjacent to the face, operate on the face.  If there is another adj-
33500   //   acent tetrahedron, operate on the face only if the current tetrahedron
33501   //   has a smaller pointer than its neighbor.  This way, each face is
33502   //   considered only once.
33503   while (tface.tet != (tetrahedron *) NULL) {
33504     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33505       sym(tface, tsymface);
33506       if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33507         p1 = org(tface);
33508         p2 = dest(tface);
33509         p3 = apex(tface);
33510         // Face number, indices of three vertexs.
33511         fprintf(outfile, "3   %4d  %4d  %4d\n", pointmark(p1) - shift,
33512                 pointmark(p2) - shift, pointmark(p3) - shift);
33513       }
33514     }
33515     tface.tet = tetrahedrontraverse();
33516   }
33517 
33518   fprintf(outfile, "# Generated by %s\n", b->commandline);
33519   fclose(outfile);
33520 }
33521 
33522 //
33523 // End of I/O rouitnes
33524 //
33525 
33526 //
33527 // Begin of user interaction routines
33528 //
33529 
33531 //                                                                           //
33532 // internalerror()    Ask the user to send me the defective product.  Exit.  //
33533 //                                                                           //
33535 
33536 void tetgenmesh::internalerror()
33537 {
33538   printf("  Please report this bug to sihang@mail.berlios.de. Include the\n");
33539   printf("    message above, your input data set, and the exact command\n");
33540   printf("    line you used to run this program, thank you.\n");
33541   terminatetetgen(2);
33542 }
33543 
33545 //                                                                           //
33546 // checkmesh()    Test the mesh for topological consistency.                 //
33547 //                                                                           //
33549 
33550 void tetgenmesh::checkmesh()
33551 {
33552   triface tetraloop;
33553   triface oppotet, oppooppotet;
33554   point tetorg, tetdest, tetapex, tetoppo;
33555   REAL oritest;
33556   int horrors;
33557 
33558   if (!b->quiet) {
33559     printf("  Checking consistency of mesh...\n");
33560   }
33561 
33562   horrors = 0;
33563   // Run through the list of tetrahedra, checking each one.
33564   tetrahedrons->traversalinit();
33565   tetraloop.tet = tetrahedrontraverse();
33566   while (tetraloop.tet != (tetrahedron *) NULL) {
33567     // Check all four faces of the tetrahedron.
33568     for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33569       tetorg = org(tetraloop);
33570       tetdest = dest(tetraloop);
33571       tetapex = apex(tetraloop);
33572       tetoppo = oppo(tetraloop);
33573       if (tetraloop.loc == 0) {             // Only test for inversion once.
33574         oritest = orient3d(tetorg, tetdest, tetapex, tetoppo);
33575         if (oritest >= 0.0) {
33576           printf("  !! !! %s ", oritest > 0.0 ? "Inverted" : "Degenerated");
33577           printtet(&tetraloop);
33578           printf("  orient3d = %.17g.\n", oritest);
33579           horrors++;
33580         }
33581       }
33582       // Find the neighboring tetrahedron on this face.
33583       sym(tetraloop, oppotet);
33584       if (oppotet.tet != dummytet) {
33585         // Check that the tetrahedron's neighbor knows it's a neighbor.
33586         sym(oppotet, oppooppotet);
33587         if ((tetraloop.tet != oppooppotet.tet)
33588             || (tetraloop.loc != oppooppotet.loc)) {
33589           printf("  !! !! Asymmetric tetra-tetra bond:\n");
33590           if (tetraloop.tet == oppooppotet.tet) {
33591             printf("   (Right tetrahedron, wrong orientation)\n");
33592           }
33593           printf("    First ");
33594           printtet(&tetraloop);
33595           printf("    Second (nonreciprocating) ");
33596           printtet(&oppotet);
33597           horrors++;
33598         }
33599       }
33600     }
33601     tetraloop.tet = tetrahedrontraverse();
33602   }
33603   if (horrors == 0) {
33604     if (!b->quiet) {
33605       printf("  In my studied opinion, the mesh appears to be consistent.\n");
33606     }
33607   } else if (horrors == 1) {
33608     printf("  !! !! !! !! Precisely one festering wound discovered.\n");
33609   } else {
33610     printf("  !! !! !! !! %d abominations witnessed.\n", horrors);
33611   }
33612 }
33613 
33615 //                                                                           //
33616 // checkshells()       Test the boundary mesh for topological consistency.   //
33617 //                                                                           //
33619 
33620 void tetgenmesh::checkshells()
33621 {
33622   triface oppotet, oppooppotet, testtet;
33623   face shloop, segloop, spin;
33624   face testsh, testseg, testshsh;
33625   point shorg, shdest, segorg, segdest;
33626   REAL checksign;
33627   bool same;
33628   int horrors;
33629   int i;
33630 
33631   if (!b->quiet) {
33632     printf("  Checking consistency of the mesh boundary...\n");
33633   }
33634   horrors = 0;
33635 
33636   // Run through the list of subfaces, checking each one.
33637   subfaces->traversalinit();
33638   shloop.sh = shellfacetraverse(subfaces);
33639   while (shloop.sh != (shellface *) NULL) {
33640     // Check two connected tetrahedra if they exist.
33641     shloop.shver = 0;
33642     stpivot(shloop, oppotet);
33643     if (oppotet.tet != dummytet) {
33644       tspivot(oppotet, testsh);
33645       if (testsh.sh != shloop.sh) {
33646         printf("  !! !! Wrong tetra-subface connection.\n");
33647         printf("    Tetra: ");
33648         printtet(&oppotet);
33649         printf("    Subface: ");
33650         printsh(&shloop);
33651         horrors++;
33652       }
33653       if (oppo(oppotet) != (point) NULL) {
33654         adjustedgering(oppotet, CCW);
33655         checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33656                              oppo(oppotet));
33657         if (checksign >= 0.0) {
33658           printf("  !! !! Wrong subface orientation.\n");
33659           printf("    Subface: ");
33660           printsh(&shloop);
33661           horrors++;
33662         }
33663       }
33664     }
33665     sesymself(shloop);
33666     stpivot(shloop, oppooppotet);
33667     if (oppooppotet.tet != dummytet) {
33668       tspivot(oppooppotet, testsh);
33669       if (testsh.sh != shloop.sh) {
33670         printf("  !! !! Wrong tetra-subface connection.\n");
33671         printf("    Tetra: ");
33672         printtet(&oppooppotet);
33673         printf("    Subface: ");
33674         printsh(&shloop);
33675         horrors++;
33676       }
33677       if (oppotet.tet != dummytet) {
33678         sym(oppotet, testtet);
33679         if (testtet.tet != oppooppotet.tet) {
33680           printf("  !! !! Wrong tetra-subface-tetra connection.\n");
33681           printf("    Tetra 1: ");
33682           printtet(&oppotet);
33683           printf("    Subface: ");
33684           printsh(&shloop);
33685           printf("    Tetra 2: ");
33686           printtet(&oppooppotet);
33687           horrors++;
33688         }
33689       }
33690       if (oppo(oppooppotet) != (point) NULL) {
33691         adjustedgering(oppooppotet, CCW);
33692         checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33693                              oppo(oppooppotet));
33694         if (checksign >= 0.0) {
33695           printf("  !! !! Wrong subface orientation.\n");
33696           printf("    Subface: ");
33697           printsh(&shloop);
33698           horrors++;
33699         }
33700       }
33701     }
33702     // Check connection between subfaces.
33703     shloop.shver = 0;
33704     for (i = 0; i < 3; i++) {
33705       shorg = sorg(shloop);
33706       shdest = sdest(shloop);
33707       sspivot(shloop, testseg);
33708       if (testseg.sh != dummysh) {
33709         segorg = sorg(testseg);
33710         segdest = sdest(testseg);
33711         same = ((shorg == segorg) && (shdest == segdest))
33712         || ((shorg == segdest) && (shdest == segorg));
33713         if (!same) {
33714           printf("  !! !! Wrong subface-subsegment connection.\n");
33715           printf("    Subface: ");
33716           printsh(&shloop);
33717           printf("    Subsegment: ");
33718           printsh(&testseg);
33719           horrors++;
33720         }
33721       }
33722       spivot(shloop, testsh);
33723       if (testsh.sh != dummysh) {
33724         segorg = sorg(testsh);
33725         segdest = sdest(testsh);
33726         same = ((shorg == segorg) && (shdest == segdest))
33727         || ((shorg == segdest) && (shdest == segorg));
33728         if (!same) {
33729           printf("  !! !! Wrong subface-subface connection.\n");
33730           printf("    Subface 1: ");
33731           printsh(&shloop);
33732           printf("    Subface 2: ");
33733           printsh(&testsh);
33734           horrors++;
33735         }
33736         spivot(testsh, testshsh);
33737         shorg = sorg(testshsh);
33738         shdest = sdest(testshsh);
33739         same = ((shorg == segorg) && (shdest == segdest))
33740         || ((shorg == segdest) && (shdest == segorg));
33741         if (!same) {
33742           printf("  !! !! Wrong subface-subface connection.\n");
33743           printf("    Subface 1: ");
33744           printsh(&testsh);
33745           printf("    Subface 2: ");
33746           printsh(&testshsh);
33747           horrors++;
33748         }
33749         if (testseg.sh == dummysh) {
33750           if (testshsh.sh != shloop.sh) {
33751             printf("  !! !! Wrong subface-subface connection.\n");
33752             printf("    Subface 1: ");
33753             printsh(&shloop);
33754             printf("    Subface 2: ");
33755             printsh(&testsh);
33756             horrors++;
33757           }
33758         }
33759       }
33760       senextself(shloop);
33761     }
33762     shloop.sh = shellfacetraverse(subfaces);
33763   }
33764 
33765   // Run through the list of subsegs, checking each one.
33766   subsegs->traversalinit();
33767   segloop.sh = shellfacetraverse(subsegs);
33768   while (segloop.sh != (shellface *) NULL) {
33769     segorg = sorg(segloop);
33770     segdest = sdest(segloop);
33771     spivot(segloop, testsh);
33772     if (testsh.sh == dummysh) {
33773       printf("  !! !! Wrong subsegment-subface connection.\n");
33774       printf("    Subsegment: ");
33775       printsh(&segloop);
33776       horrors++;
33777       segloop.sh = shellfacetraverse(subsegs);
33778       continue;
33779     }
33780     shorg = sorg(testsh);
33781     shdest = sdest(testsh);
33782     same = ((shorg == segorg) && (shdest == segdest))
33783         || ((shorg == segdest) && (shdest == segorg));
33784     if (!same) {
33785       printf("  !! !! Wrong subsegment-subface connection.\n");
33786       printf("    Subsegment : ");
33787       printsh(&segloop);
33788       printf("    Subface : ");
33789       printsh(&testsh);
33790       horrors++;
33791       segloop.sh = shellfacetraverse(subsegs);
33792       continue;
33793     }
33794     // Check the connection of face loop around this subsegment.
33795     spin = testsh;
33796     i = 0;
33797     do {
33798       spivotself(spin);
33799       shorg = sorg(spin);
33800       shdest = sdest(spin);
33801       same = ((shorg == segorg) && (shdest == segdest))
33802           || ((shorg == segdest) && (shdest == segorg));
33803       if (!same) {
33804         printf("  !! !! Wrong subsegment-subface connection.\n");
33805         printf("    Subsegment : ");
33806         printsh(&segloop);
33807         printf("    Subface : ");
33808         printsh(&testsh);
33809         horrors++;
33810         break;
33811       }
33812       i++;
33813     } while (spin.sh != testsh.sh && i < 1000);
33814     if (i >= 1000) {
33815       printf("  !! !! Wrong subsegment-subface connection.\n");
33816       printf("    Subsegment : ");
33817       printsh(&segloop);
33818       horrors++;
33819     }
33820     segloop.sh = shellfacetraverse(subsegs);
33821   }
33822   if (horrors == 0) {
33823     if (!b->quiet) {
33824       printf("  Mesh boundaries connected correctly.\n");
33825     }
33826   } else {
33827     printf("  !! !! !! !! %d boundary connection viewed with horror.\n",
33828            horrors);
33829     return;
33830   }
33831 }
33832 
33834 //                                                                           //
33835 // checkdelaunay()    Ensure that the mesh is constrained Delaunay.          //
33836 //                                                                           //
33837 // If 'flipqueue' is not NULL, non-locally Delaunay faces are saved in it.   //
33838 //                                                                           //
33840 
33841 void tetgenmesh::checkdelaunay(REAL eps, queue* flipqueue)
33842 {
33843   triface tetraloop;
33844   triface oppotet;
33845   face opposhelle;
33846   point tetorg, tetdest, tetapex, tetoppo;
33847   point oppooppo;
33848   enum fliptype fc;
33849   REAL sign;
33850   int shouldbedelaunay;
33851   int horrors;
33852 
33853   if (!b->quiet) {
33854     printf("  Checking Delaunay property of the mesh...\n");
33855   }
33856   horrors = 0;
33857   // Run through the list of triangles, checking each one.
33858   tetrahedrons->traversalinit();
33859   tetraloop.tet = tetrahedrontraverse();
33860   while (tetraloop.tet != (tetrahedron *) NULL) {
33861     // Check all four faces of the tetrahedron.
33862     for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33863       tetorg = org(tetraloop);
33864       tetdest = dest(tetraloop);
33865       tetapex = apex(tetraloop);
33866       tetoppo = oppo(tetraloop);
33867       sym(tetraloop, oppotet);
33868       oppooppo = oppo(oppotet);
33869       // Only do testif there is an adjoining tetrahedron whose pointer is
33870       //   larger (to ensure that each pair isn't tested twice).
33871       shouldbedelaunay = (oppotet.tet != dummytet)
33872                           && (tetoppo != (point) NULL)
33873                           && (oppooppo != (point) NULL)
33874                           && (tetraloop.tet < oppotet.tet);
33875       if (checksubfaces && shouldbedelaunay) {
33876         // If a shell face separates the tetrahedra, then the face is
33877         //   constrained, so no local Delaunay test should be done.
33878         tspivot(tetraloop, opposhelle);
33879         if (opposhelle.sh != dummysh){
33880           shouldbedelaunay = 0;
33881         }
33882       }
33883       if (shouldbedelaunay) {
33884         sign = insphere(tetdest, tetorg, tetapex, tetoppo, oppooppo);
33885         if ((sign > 0.0) && (eps > 0.0)) {
33886           if (iscospheric(tetdest, tetorg, tetapex, tetoppo, oppooppo, sign,
33887                           eps)) sign = 0.0;
33888         }
33889         if (sign > 0.0) {
33890           if (flipqueue) {
33891             enqueueflipface(tetraloop, flipqueue);
33892           } else {
33893             printf("  !! Non-locally Delaunay face (%d, %d, %d) ",
33894                    pointmark(tetorg), pointmark(tetdest), pointmark(tetapex));
33895             fc = categorizeface(tetraloop);
33896             switch (fc) {
33897             case T23: printf("\"T23\""); break;
33898             case T32: printf("\"T32\""); break;
33899             case T22: printf("\"T22\""); break;
33900             case T44: printf("\"T44\""); break;
33901             case N32: printf("\"N32\""); break;
33902             case N40: printf("\"N40\""); break;
33903             case FORBIDDENFACE:printf("\"FORBIDDENFACE\""); break;
33904             case FORBIDDENEDGE:printf("\"FORBIDDENEDGE\""); break;
33905             }
33906             printf("\n");
33907           }
33908           horrors++;
33909         }
33910       }
33911     }
33912     tetraloop.tet = tetrahedrontraverse();
33913   }
33914   if (flipqueue == (queue *) NULL) {
33915     if (horrors == 0) {
33916       if (!b->quiet) {
33917         printf("  The mesh is %s.\n",
33918                checksubfaces ? "constrained Delaunay" : "Delaunay");
33919       }
33920     } else {
33921       printf("  !! !! !! !! %d obscenities viewed with horror.\n", horrors);
33922     }
33923   }
33924 }
33925 
33927 //                                                                           //
33928 // checkconforming()    Ensure that the mesh is conforming Delaunay.         //
33929 //                                                                           //
33931 
33932 void tetgenmesh::checkconforming()
33933 {
33934   face segloop, shloop;
33935   int encsubsegs, encsubfaces;
33936 
33937   if (!b->quiet) {
33938     printf("  Checking conforming Delaunay property of mesh...\n");
33939   }
33940   encsubsegs = encsubfaces = 0;
33941   // Run through the list of subsegments, check each one.
33942   subsegs->traversalinit();
33943   segloop.sh = shellfacetraverse(subsegs);
33944   while (segloop.sh != (shellface *) NULL) {
33945     if (checkseg4encroach(&segloop, NULL, NULL, false)) {
33946       printf("  !! !! Non-conforming subsegment: (%d, %d)\n",
33947              pointmark(sorg(segloop)), pointmark(sdest(segloop)));
33948       encsubsegs++;
33949     }
33950     segloop.sh = shellfacetraverse(subsegs);
33951   }
33952   // Run through the list of subfaces, check each one.
33953   subfaces->traversalinit();
33954   shloop.sh = shellfacetraverse(subfaces);
33955   while (shloop.sh != (shellface *) NULL) {
33956     if (checksub4encroach(&shloop, NULL, false)) {
33957       printf("  !! !! Non-conforming subface: (%d, %d, %d)\n",
33958              pointmark(sorg(shloop)), pointmark(sdest(shloop)),
33959              pointmark(sapex(shloop)));
33960       encsubfaces++;
33961     }
33962     shloop.sh = shellfacetraverse(subfaces);
33963   }
33964   if (encsubsegs == 0 && encsubfaces == 0) {
33965     if (!b->quiet) {
33966       printf("  The mesh is conforming Delaunay.\n");
33967     }
33968   } else {
33969     if (encsubsegs > 0) {
33970       printf("  !! !! %d subsegments are non-conforming.\n", encsubsegs);
33971     }
33972     if (encsubfaces > 0) {
33973       printf("  !! !! %d subfaces are non-conforming.\n", encsubfaces);
33974     }
33975   }
33976 }
33977 
33979 //                                                                           //
33980 // algorithmicstatistics()    Print statistics about the mesh algorithms.    //
33981 //                                                                           //
33983 
33984 #ifdef SELF_CHECK
33985 
33986 void tetgenmesh::algorithmicstatistics()
33987 {
33988   /*
33989   printf("Algorithmic statistics:\n\n");
33990   printf("  Point location millisecond:  %g\n", (REAL) tloctime * 1e+3);
33991   printf("  Flip millisecond:  %g\n", (REAL) tfliptime * 1e+3);
33992   if (b->plc || b->refine) {
33993     printf("  Number of facet above points calculations: %ld\n", abovecount);
33994   }
33995   if (b->plc) {
33996     printf("  Segment split rules: R1 %ld, R2 %ld, R3 %ld\n", r1count, r2count,
33997            r3count);
33998   }
33999   if (b->quality) {
34000     printf("  Bowyer-Watson insertions: seg %ld, sub %ld, vol %ld.\n",
34001            bowatsegcount, bowatsubcount, bowatvolcount);
34002     printf("  Bowyer-Watson corrections: seg %ld, sub %ld, vol %ld\n",
34003            updsegcount, updsubcount, updvolcount);
34004     printf("  Bowyer-Watson failures: seg %ld, sub %ld, vol %ld\n",
34005            failsegcount, failsubcount, failvolcount);
34006     printf("  Number of repair flips: %ld.\n", repairflipcount);
34007     printf("  Number of circumcenters outside Bowat-cav.: %ld.\n",
34008            outbowatcircumcount);
34009     if (b->conformdel) {
34010       printf("  Segment split rules: R2 %ld, R3 %ld\n", r2count, r3count);
34011       printf("  Number of CDT enforcement points: %ld.\n", cdtenforcesegpts);
34012     }
34013     printf("  Number of Rejections: seg %ld, sub %ld, tet %ld.\n", rejsegpts,
34014            rejsubpts, rejtetpts);
34015     if (b->optlevel) {
34016       printf(
34017       "  Optimization flips: f32 %ld, f44 %ld, f56 %ld, f68 %ld, fnm %ld.\n",
34018              optcount[3], optcount[4], optcount[5], optcount[6], optcount[9]);
34019       printf("  Optimization segment deletions: %ld.\n", optcount[1]);
34020     }
34021   }
34022   printf("\n");
34023   */
34024 }
34025 
34026 #endif // #ifdef SELF_CHECK
34027 
34029 //                                                                           //
34030 // qualitystatistics()    Print statistics about the quality of the mesh.    //
34031 //                                                                           //
34033 
34034 void tetgenmesh::qualitystatistics()
34035 {
34036   triface tetloop, neightet;
34037   point p[4];
34038   char sbuf[128];
34039   REAL radiusratiotable[12];
34040   REAL aspectratiotable[12];
34041   REAL A[4][4], rhs[4], D;
34042   REAL V[6][3], N[4][3], H[4]; // edge-vectors, face-normals, face-heights.
34043   REAL edgelength[6], alldihed[6], faceangle[3];
34044   REAL shortest, longest;
34045   REAL smallestvolume, biggestvolume;
34046   REAL smallestdiangle, biggestdiangle;
34047   REAL smallestfaangle, biggestfaangle;
34048   REAL tetvol, minaltitude;
34049   REAL cirradius, minheightinv; // insradius;
34050   REAL shortlen, longlen;
34051   REAL tetaspect, tetradius;
34052   REAL smalldiangle, bigdiangle;
34053   REAL smallfaangle, bigfaangle;
34054   int radiustable[12];
34055   int aspecttable[16];
34056   int dihedangletable[18];
34057   int faceangletable[18];
34058   int indx[4];
34059   int radiusindex;
34060   int aspectindex;
34061   int tendegree;
34062   int i, j;
34063 
34064   smallfaangle = 0.0;
34065   bigfaangle = 0.0;
34066 
34067   printf("Mesh quality statistics:\n\n");
34068 
34069   // Avoid compile warnings.
34070   shortlen = longlen = 0.0;
34071   smalldiangle = bigdiangle = 0.0;
34072 
34073   radiusratiotable[0]  =    0.707;    radiusratiotable[1]  =     1.0;
34074   radiusratiotable[2]  =      1.1;    radiusratiotable[3]  =     1.2;
34075   radiusratiotable[4]  =      1.4;    radiusratiotable[5]  =     1.6;
34076   radiusratiotable[6]  =      1.8;    radiusratiotable[7]  =     2.0;
34077   radiusratiotable[8]  =      2.5;    radiusratiotable[9]  =     3.0;
34078   radiusratiotable[10] =     10.0;    radiusratiotable[11] =     0.0;
34079 
34080   aspectratiotable[0]  =      1.5;    aspectratiotable[1]  =     2.0;
34081   aspectratiotable[2]  =      2.5;    aspectratiotable[3]  =     3.0;
34082   aspectratiotable[4]  =      4.0;    aspectratiotable[5]  =     6.0;
34083   aspectratiotable[6]  =     10.0;    aspectratiotable[7]  =    15.0;
34084   aspectratiotable[8]  =     25.0;    aspectratiotable[9]  =    50.0;
34085   aspectratiotable[10] =    100.0;    aspectratiotable[11] =     0.0;
34086 
34087   for (i = 0; i < 12; i++) radiustable[i] = 0;
34088   for (i = 0; i < 12; i++) aspecttable[i] = 0;
34089   for (i = 0; i < 18; i++) dihedangletable[i] = 0;
34090   for (i = 0; i < 18; i++) faceangletable[i] = 0;
34091 
34092   minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
34093   minaltitude = minaltitude * minaltitude;
34094   shortest = minaltitude;
34095   longest = 0.0;
34096   smallestvolume = minaltitude;
34097   biggestvolume = 0.0;
34098   smallestdiangle = smallestfaangle = 180.0;
34099   biggestdiangle = biggestfaangle = 0.0;
34100 
34101   // Loop all elements, calculate quality parameters for each element.
34102   tetrahedrons->traversalinit();
34103   tetloop.tet = tetrahedrontraverse();
34104   while (tetloop.tet != (tetrahedron *) NULL) {
34105 
34106     // Get four vertices: p0, p1, p2, p3.
34107     for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i];
34108     // Set the edge vectors: V[0], ..., V[5]
34109     for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i]; // V[0]: p3->p0.
34110     for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i]; // V[1]: p3->p1.
34111     for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i]; // V[2]: p3->p2.
34112     for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i]; // V[3]: p0->p1.
34113     for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i]; // V[4]: p1->p2.
34114     for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i]; // V[5]: p2->p0.
34115     // Set the matrix A = [V[0], V[1], V[2]]^T.
34116     for (j = 0; j < 3; j++) {
34117       for (i = 0; i < 3; i++) A[j][i] = V[j][i];
34118     }
34119     // Decompose A just once.
34120     lu_decmp(A, 3, indx, &D, 0);
34121     // Get the tet volume.
34122     tetvol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
34123     // Get the three faces normals.
34124     for (j = 0; j < 3; j++) {
34125       for (i = 0; i < 3; i++) rhs[i] = 0.0;
34126       rhs[j] = 1.0;  // Positive means the inside direction
34127       lu_solve(A, 3, indx, rhs, 0);
34128       for (i = 0; i < 3; i++) N[j][i] = rhs[i];
34129     }
34130     // Get the fourth face normal by summing up the first three.
34131     for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
34132     // Get the radius of the circumsphere.
34133     for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]);
34134     lu_solve(A, 3, indx, rhs, 0);
34135     cirradius = sqrt(dot(rhs, rhs));
34136     // Normalize the face normals.
34137     for (i = 0; i < 4; i++) {
34138       // H[i] is the inverse of height of its corresponding face.
34139       H[i] = sqrt(dot(N[i], N[i]));
34140       for (j = 0; j < 3; j++) N[i][j] /= H[i];
34141     }
34142     // Get the radius of the inscribed sphere.
34143     // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]);
34144     // Get the biggest H[i] (corresponding to the smallest height).
34145     minheightinv = H[0];
34146     for (i = 1; i < 3; i++) {
34147       if (H[i] > minheightinv) minheightinv = H[i];
34148     }
34149     // Get the squares of the edge lengthes.
34150     for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
34151     // Get the dihedrals (in degree) at each edges.
34152     j = 0;
34153     for (i = 1; i < 4; i++) {
34154       alldihed[j] = -dot(N[0], N[i]); // Edge cd, bd, bc.
34155       if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34156       else if (alldihed[j] > 1.0) alldihed[j] = 1;
34157       alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34158       j++;
34159     }
34160     for (i = 2; i < 4; i++) {
34161       alldihed[j] = -dot(N[1], N[i]); // Edge ad, ac.
34162       if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34163       else if (alldihed[j] > 1.0) alldihed[j] = 1;
34164       alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34165       j++;
34166     }
34167     alldihed[j] = -dot(N[2], N[3]); // Edge ab.
34168     if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34169     else if (alldihed[j] > 1.0) alldihed[j] = 1;
34170     alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34171 
34172     // Calculate the longest and shortest edge length.
34173     for (i = 0; i < 6; i++) {
34174       if (i == 0) {
34175         shortlen = longlen = edgelength[i];
34176       } else {
34177         shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen;
34178         longlen  = edgelength[i] > longlen  ? edgelength[i] : longlen;
34179       }
34180       if (edgelength[i] > longest) {
34181         longest = edgelength[i];
34182       }
34183       if (edgelength[i] < shortest) {
34184         shortest = edgelength[i];
34185       }
34186     }
34187 
34188     // Calculate the largest and smallest volume.
34189     if (tetvol < smallestvolume) {
34190       smallestvolume = tetvol;
34191     }
34192     if (tetvol > biggestvolume) {
34193       biggestvolume = tetvol;
34194     }
34195 
34196     // Calculate the largest and smallest dihedral angles.
34197     for (i = 0; i < 6; i++) {
34198       if (i == 0) {
34199         smalldiangle = bigdiangle = alldihed[i];
34200       } else {
34201         smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle;
34202         bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle;
34203       }
34204       if (alldihed[i] < smallestdiangle) {
34205         smallestdiangle = alldihed[i];
34206       }
34207       if (alldihed[i] > biggestdiangle) {
34208         biggestdiangle = alldihed[i];
34209       }
34210     }
34211     // Accumulate the corresponding number in the dihedral angle histogram.
34212     if (smalldiangle < 5.0) {
34213       tendegree = 0;
34214     } else if (smalldiangle >= 5.0 && smalldiangle < 10.0) {
34215       tendegree = 1;
34216     } else if (smalldiangle >= 80.0 && smalldiangle < 110.0) {
34217       tendegree = 9; // Angles between 80 to 110 degree are in one entry.
34218     } else {
34219       tendegree = (int) (smalldiangle / 10.);
34220       if (smalldiangle < 80.0) {
34221         tendegree++;  // In the left column.
34222       } else {
34223         tendegree--;  // In the right column.
34224       }
34225     }
34226     dihedangletable[tendegree]++;
34227     if (bigdiangle >= 80.0 && bigdiangle < 110.0) {
34228       tendegree = 9; // Angles between 80 to 110 degree are in one entry.
34229     } else if (bigdiangle >= 170.0 && bigdiangle < 175.0) {
34230       tendegree = 16;
34231     } else if (bigdiangle >= 175.0) {
34232       tendegree = 17;
34233     } else {
34234       tendegree = (int) (bigdiangle / 10.);
34235       if (bigdiangle < 80.0) {
34236         tendegree++;  // In the left column.
34237       } else {
34238         tendegree--;  // In the right column.
34239       }
34240     }
34241     dihedangletable[tendegree]++;
34242 
34243     // Calulate the largest and smallest face angles.
34244     tetloop.ver = 0;
34245     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
34246       sym(tetloop, neightet);
34247       // Only do the calulation once for a face.
34248       if ((neightet.tet == dummytet) || (tetloop.tet < neightet.tet)) {
34249         p[0] = org(tetloop);
34250         p[1] = dest(tetloop);
34251         p[2] = apex(tetloop);
34252         faceangle[0] = interiorangle(p[0], p[1], p[2], NULL);
34253         faceangle[1] = interiorangle(p[1], p[2], p[0], NULL);
34254         faceangle[2] = PI - (faceangle[0] + faceangle[1]);
34255         // Translate angles into degrees.
34256         for (i = 0; i < 3; i++) {
34257           faceangle[i] = (faceangle[i] * 180.0) / PI;
34258         }
34259         // Calculate the largest and smallest face angles.
34260         for (i = 0; i < 3; i++) {
34261           if (i == 0) {
34262             smallfaangle = bigfaangle = faceangle[i];
34263           } else {
34264             smallfaangle = faceangle[i] < smallfaangle ?
34265               faceangle[i] : smallfaangle;
34266             bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle;
34267           }
34268           if (faceangle[i] < smallestfaangle) {
34269             smallestfaangle = faceangle[i];
34270           }
34271           if (faceangle[i] > biggestfaangle) {
34272             biggestfaangle = faceangle[i];
34273           }
34274         }
34275         tendegree = (int) (smallfaangle / 10.);
34276         faceangletable[tendegree]++;
34277         tendegree = (int) (bigfaangle / 10.);
34278         faceangletable[tendegree]++;
34279       }
34280     }
34281 
34282     // Calculate aspect ratio and radius-edge ratio for this element.
34283     tetradius = cirradius / sqrt(shortlen);
34284     // tetaspect = sqrt(longlen) / (2.0 * insradius);
34285     tetaspect = sqrt(longlen) * minheightinv;
34286     aspectindex = 0;
34287     while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) {
34288       aspectindex++;
34289     }
34290     aspecttable[aspectindex]++;
34291     radiusindex = 0;
34292     while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) {
34293       radiusindex++;
34294     }
34295     radiustable[radiusindex]++;
34296 
34297     tetloop.tet = tetrahedrontraverse();
34298   }
34299 
34300   shortest = sqrt(shortest);
34301   longest = sqrt(longest);
34302   minaltitude = sqrt(minaltitude);
34303 
34304   printf("  Smallest volume: %16.5g   |  Largest volume: %16.5g\n",
34305          smallestvolume, biggestvolume);
34306   printf("  Shortest edge:   %16.5g   |  Longest edge:   %16.5g\n",
34307          shortest, longest);
34308   sprintf(sbuf, "%.17g", biggestfaangle);
34309   if (strlen(sbuf) > 8) {
34310     sbuf[8] = '\0';
34311   }
34312   printf("  Smallest facangle: %14.5g   |  Largest facangle:       %s\n",
34313          smallestfaangle, sbuf);
34314   sprintf(sbuf, "%.17g", biggestdiangle);
34315   if (strlen(sbuf) > 8) {
34316     sbuf[8] = '\0';
34317   }
34318   printf("  Smallest dihedral: %14.5g   |  Largest dihedral:       %s\n\n",
34319          smallestdiangle, sbuf);
34320 
34321   /*
34322   printf("  Radius-edge ratio histogram:\n");
34323   printf("         < %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34324          radiusratiotable[0], radiustable[0], radiusratiotable[5],
34325          radiusratiotable[6], radiustable[6]);
34326   for (i = 1; i < 5; i++) {
34327     printf("  %6.6g - %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34328            radiusratiotable[i - 1], radiusratiotable[i], radiustable[i],
34329            radiusratiotable[i + 5], radiusratiotable[i + 6],
34330            radiustable[i + 6]);
34331   }
34332   printf("  %6.6g - %-6.6g    :  %8d      | %6.6g -            :  %8d\n",
34333          radiusratiotable[4], radiusratiotable[5], radiustable[5],
34334          radiusratiotable[10], radiustable[11]);
34335   printf("  (A tetrahedron's radius-edge ratio is its radius of ");
34336   printf("circumsphere divided\n");
34337   printf("    by its shortest edge length)\n\n");
34338   */
34339 
34340   printf("  Aspect ratio histogram:\n");
34341   printf("         < %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34342          aspectratiotable[0], aspecttable[0], aspectratiotable[5],
34343          aspectratiotable[6], aspecttable[6]);
34344   for (i = 1; i < 5; i++) {
34345     printf("  %6.6g - %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34346            aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i],
34347            aspectratiotable[i + 5], aspectratiotable[i + 6],
34348            aspecttable[i + 6]);
34349   }
34350   printf("  %6.6g - %-6.6g    :  %8d      | %6.6g -            :  %8d\n",
34351          aspectratiotable[4], aspectratiotable[5], aspecttable[5],
34352          aspectratiotable[10], aspecttable[11]);
34353   printf("  (A tetrahedron's aspect ratio is its longest edge length");
34354   printf(" divided by its\n");
34355   printf("    smallest side height)\n\n");
34356 
34357   printf("  Face angle histogram:\n");
34358   for (i = 0; i < 9; i++) {
34359     printf("    %3d - %3d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34360            i * 10, i * 10 + 10, faceangletable[i],
34361            i * 10 + 90, i * 10 + 100, faceangletable[i + 9]);
34362   }
34363   if (minfaceang != PI) {
34364     printf("  Minimum input face angle is %g (degree).\n",
34365            minfaceang / PI * 180.0);
34366   }
34367   printf("\n");
34368 
34369   printf("  Dihedral angle histogram:\n");
34370   // Print the three two rows:
34371   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34372          0, 5, dihedangletable[0], 80, 110, dihedangletable[9]);
34373   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34374          5, 10, dihedangletable[1], 110, 120, dihedangletable[10]);
34375   // Print the third to seventh rows.
34376   for (i = 2; i < 7; i++) {
34377     printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34378            (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i],
34379            (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]);
34380   }
34381   // Print the last two rows.
34382   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34383          60, 70, dihedangletable[7], 170, 175, dihedangletable[16]);
34384   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34385          70, 80, dihedangletable[8], 175, 180, dihedangletable[17]);
34386   if (minfacetdihed != PI) {
34387     printf("  Minimum input facet dihedral angle is %g (degree).\n",
34388            minfacetdihed / PI * 180.0);
34389   }
34390   printf("\n");
34391 }
34392 
34394 //                                                                           //
34395 // statistics()    Print all sorts of cool facts.                            //
34396 //                                                                           //
34398 
34399 void tetgenmesh::statistics()
34400 {
34401   printf("\nStatistics:\n\n");
34402   printf("  Input points: %d\n", in->numberofpoints + jettisoninverts);
34403   if (b->refine) {
34404     printf("  Input tetrahedra: %d\n", in->numberoftetrahedra);
34405   }
34406   if (b->plc) {
34407     printf("  Input facets: %d\n", in->numberoffacets);
34408     printf("  Input segments: %ld\n", insegments);
34409     printf("  Input holes: %d\n", in->numberofholes);
34410     printf("  Input regions: %d\n", in->numberofregions);
34411   }
34412 
34413   printf("\n  Mesh points: %ld\n", points->items);
34414   printf("  Mesh tetrahedra: %ld\n", tetrahedrons->items);
34415   if (b->plc || b->refine) {
34416     printf("  Mesh triangles: %ld\n", (4l*tetrahedrons->items+hullsize)/2l);
34417   }
34418   if (b->plc || b->refine) {
34419     printf("  Mesh subfaces: %ld\n", subfaces->items);
34420     printf("  Mesh subsegments: %ld\n\n", subsegs->items);
34421   } else {
34422     printf("  Convex hull triangles: %ld\n\n", hullsize);
34423   }
34424   if (b->verbose > 0) {
34425     qualitystatistics();
34426     unsigned long totalmeshbytes;
34427     printf("Memory allocation statistics:\n\n");
34428     printf("  Maximum number of vertices: %ld\n", points->maxitems);
34429     totalmeshbytes = points->maxitems * points->itembytes;
34430     printf("  Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems);
34431     totalmeshbytes += tetrahedrons->maxitems * tetrahedrons->itembytes;
34432     if (subfaces != (memorypool *) NULL) {
34433       printf("  Maximum number of subfaces: %ld\n", subfaces->maxitems);
34434       totalmeshbytes += subfaces->maxitems * subfaces->itembytes;
34435     }
34436     if (subsegs != (memorypool *) NULL) {
34437       printf("  Maximum number of segments: %ld\n", subsegs->maxitems);
34438       totalmeshbytes += subsegs->maxitems * subsegs->itembytes;
34439     }
34440     printf("  Approximate heap memory used by the mesh (K bytes): %g\n\n",
34441            (double) totalmeshbytes / 1024.0);
34442 #ifdef SELF_CHECK
34443     algorithmicstatistics();
34444 #endif
34445   }
34446 }
34447 
34448 //
34449 // End of user interaction routines
34450 //
34451 
34452 //
34453 // Begin of constructor and destructor of tetgenmesh
34454 //
34455 
34457 //                                                                           //
34458 // ~tetgenmesh()    Deallocte memory occupied by a tetgenmesh object.        //
34459 //                                                                           //
34461 
34462 tetgenmesh::~tetgenmesh()
34463 {
34464   bgm = (tetgenmesh *) NULL;
34465   in = (tetgenio *) NULL;
34466   b = (tetgenbehavior *) NULL;
34467 
34468   if (tetrahedrons != (memorypool *) NULL) {
34469     delete tetrahedrons;
34470   }
34471   if (subfaces != (memorypool *) NULL) {
34472     delete subfaces;
34473   }
34474   if (subsegs != (memorypool *) NULL) {
34475     delete subsegs;
34476   }
34477   if (points != (memorypool *) NULL) {
34478     delete points;
34479   }
34480   if (dummytetbase != (tetrahedron *) NULL) {
34481     delete [] dummytetbase;
34482   }
34483   if (dummyshbase != (shellface *) NULL) {
34484     delete [] dummyshbase;
34485   }
34486   if (facetabovepointarray != (point *) NULL) {
34487     delete [] facetabovepointarray;
34488   }
34489   if (highordertable != (point *) NULL) {
34490     delete [] highordertable;
34491   }
34492   if (subpbcgrouptable != (pbcdata *) NULL) {
34493     delete [] subpbcgrouptable;
34494   }
34495   if (segpbcgrouptable != (list *) NULL) {
34496     delete segpbcgrouptable;
34497     delete [] idx2segpglist;
34498     delete [] segpglist;
34499   }
34500 }
34501 
34503 //                                                                           //
34504 // tetgenmesh()    Initialize a tetgenmesh object.                           //
34505 //                                                                           //
34507 
34508 tetgenmesh::tetgenmesh()
34509 {
34510   bgm = (tetgenmesh *) NULL;
34511   in = (tetgenio *) NULL;
34512   b = (tetgenbehavior *) NULL;
34513 
34514   tetrahedrons = (memorypool *) NULL;
34515   subfaces = (memorypool *) NULL;
34516   subsegs = (memorypool *) NULL;
34517   points = (memorypool *) NULL;
34518   badsubsegs = (memorypool *) NULL;
34519   badsubfaces = (memorypool *) NULL;
34520   badtetrahedrons = (memorypool *) NULL;
34521   flipstackers = (memorypool *) NULL;
34522 
34523   dummytet = (tetrahedron *) NULL;
34524   dummytetbase = (tetrahedron *) NULL;
34525   dummysh = (shellface *) NULL;
34526   dummyshbase = (shellface *) NULL;
34527 
34528   facetabovepointarray = (point *) NULL;
34529   abovepoint = (point) NULL;
34530   highordertable = (point *) NULL;
34531   subpbcgrouptable = (pbcdata *) NULL;
34532   segpbcgrouptable = (list *) NULL;
34533   idx2segpglist = (int *) NULL;
34534   segpglist = (int *) NULL;
34535 
34536   xmax = xmin = ymax = ymin = zmax = zmin = 0.0;
34537   longest = 0.0;
34538   hullsize = 0l;
34539   insegments = 0l;
34540   pointmtrindex = 0;
34541   pointmarkindex = 0;
34542   point2simindex = 0;
34543   point2pbcptindex = 0;
34544   highorderindex = 0;
34545   elemattribindex = 0;
34546   volumeboundindex = 0;
34547   shmarkindex = 0;
34548   areaboundindex = 0;
34549   checksubfaces = 0;
34550   checksubsegs = 0;
34551   checkpbcs = 0;
34552   varconstraint = 0;
34553   nonconvex = 0;
34554   dupverts = 0;
34555   unuverts = 0;
34556   relverts = 0;
34557   suprelverts = 0;
34558   collapverts = 0;
34559   unsupverts = 0;
34560   jettisoninverts = 0;
34561   symbolic = 1;
34562   samples = 0l;
34563   randomseed = 1l;
34564   macheps = 0.0;
34565   minfaceang = minfacetdihed = PI;
34566   maxcavfaces = maxcavverts = 0;
34567   expcavcount = 0;
34568   abovecount = 0l;
34569   bowatvolcount = bowatsubcount = bowatsegcount = 0l;
34570   updvolcount = updsubcount = updsegcount = 0l;
34571   repairflipcount = 0l;
34572   outbowatcircumcount = 0l;
34573   failvolcount = failsubcount = failsegcount = 0l;
34574   r1count = r2count = r3count = 0l;
34575   cdtenforcesegpts = 0l;
34576   rejsegpts = rejsubpts = rejtetpts = 0l;
34577   flip23s = flip32s = flip22s = flip44s = 0l;
34578   tloctime = tfliptime = 0.0;
34579 }
34580 
34581 //
34582 // End of constructor and destructor of tetgenmesh
34583 //
34584 
34585 //
34586 // End of class 'tetgenmesh' implementation.
34587 //
34588 
34590 //                                                                           //
34591 // tetrahedralize()    The interface for users using TetGen library to       //
34592 //                     generate tetrahedral meshes with all features.        //
34593 //                                                                           //
34594 // The sequence is roughly as follows.  Many of these steps can be skipped,  //
34595 // depending on the command line switches.                                   //
34596 //                                                                           //
34597 // - Initialize constants and parse the command line.                        //
34598 // - Read the vertices from a file and either                                //
34599 //   - tetrahedralize them (no -r), or                                       //
34600 //   - read an old mesh from files and reconstruct it (-r).                  //
34601 // - Insert the PLC segments and facets (-p).                                //
34602 // - Read the holes (-p), regional attributes (-pA), and regional volume     //
34603 //   constraints (-pa).  Carve the holes and concavities, and spread the     //
34604 //   regional attributes and volume constraints.                             //
34605 // - Enforce the constraints on minimum quality bound (-q) and maximum       //
34606 //   volume (-a). Also enforce the conforming Delaunay property (-q and -a). //
34607 // - Promote the mesh's linear tetrahedra to higher order elements (-o).     //
34608 // - Write the output files and print the statistics.                        //
34609 // - Check the consistency and Delaunay property of the mesh (-C).           //
34610 //                                                                           //
34612 
34613 void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
34614   tetgenio *addin, tetgenio *bgmin)
34615 {
34616   tetgenmesh m;
34617   // Variables for timing the performance of TetGen (defined in time.h).
34618   clock_t tv[14];
34619 
34620   tv[0] = clock();
34621 
34622   m.b = b;
34623   m.in = in;
34624   m.macheps = exactinit();
34625   m.steinerleft = b->steiner;
34626   if (b->metric) {
34627     m.bgm = new tetgenmesh();
34628     m.bgm->b = b;
34629     m.bgm->in = bgmin;
34630     m.bgm->macheps = exactinit();
34631   }
34632   m.initializepools();
34633   m.transfernodes();
34634 
34635   tv[1] = clock();
34636 
34637   if (b->refine) {
34638     m.reconstructmesh();
34639   } else {
34640     m.delaunizevertices();
34641   }
34642 
34643   tv[2] = clock();
34644 
34645   if (!b->quiet) {
34646     if (b->refine) {
34647       printf("Mesh reconstruction seconds:");
34648     } else {
34649       printf("Delaunay seconds:");
34650     }
34651     printf("  %g\n", (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
34652   }
34653 
34654   if (b->metric) {
34655     if (bgmin != (tetgenio *) NULL) {
34656       m.bgm->initializepools();
34657       m.bgm->transfernodes();
34658       m.bgm->reconstructmesh();
34659     } else {
34660       m.bgm->in = in;
34661       m.bgm->initializepools();
34662       m.duplicatebgmesh();
34663     }
34664   }
34665 
34666   tv[3] = clock();
34667 
34668   if (!b->quiet) {
34669     if (b->metric) {
34670       printf("Background mesh reconstruct seconds:  %g\n",
34671              (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
34672     }
34673   }
34674 
34675   if (b->useshelles && !b->refine) {
34676     m.meshsurface();
34677     if (b->diagnose != 1) {
34678       m.markacutevertices(89.0);
34679       m.incrperturbvertices(b->epsilon);
34680       m.delaunizesegments();
34681       if (m.checkpbcs) {
34682         long oldnum;
34683         do {
34684           oldnum = m.points->items;
34685           m.incrperturbvertices(b->epsilon);
34686           if (m.points->items > oldnum) {
34687             oldnum = m.points->items;
34688             m.delaunizesegments();
34689           }
34690         } while (oldnum < m.points->items);
34691       }
34692       m.constrainedfacets();
34693     } else {
34694       m.detectinterfaces();
34695     }
34696   }
34697 
34698   tv[4] = clock();
34699 
34700   if (!b->quiet) {
34701     if (b->useshelles && !b->refine) {
34702       if (b->diagnose != 1) {
34703         printf("Segment and facet ");
34704       } else {
34705         printf("Intersection ");
34706       }
34707       printf("seconds:  %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
34708     }
34709   }
34710 
34711   if (b->plc && !(b->diagnose == 1)) {
34712     m.carveholes();
34713   }
34714 
34715   tv[5] = clock();
34716 
34717   if (!b->quiet) {
34718     if (b->plc && !(b->diagnose == 1)) {
34719       printf("Hole seconds:  %g\n", (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
34720     }
34721   }
34722 
34723   if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34724     m.optimizemesh(false);
34725   }
34726 
34727   tv[6] = clock();
34728 
34729   if (!b->quiet) {
34730     if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34731       printf("Repair seconds:  %g\n", (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
34732     }
34733   }
34734 
34735   if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34736     m.removesteiners(false);
34737   }
34738 
34739   tv[7] = clock();
34740 
34741   if (!b->quiet) {
34742     if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34743       printf("Steiner removal seconds:  %g\n",
34744              (tv[7] - tv[6]) / (REAL) CLOCKS_PER_SEC);
34745     }
34746   }
34747 
34748   if (b->insertaddpoints && (addin != (tetgenio *) NULL)) {
34749     if (addin->numberofpoints > 0) {
34750       m.insertconstrainedpoints(addin);
34751     }
34752   }
34753 
34754   tv[8] = clock();
34755 
34756   if (!b->quiet) {
34757     if ((b->plc || b->refine) && (b->insertaddpoints)) {
34758       printf("Constrained points seconds:  %g\n",
34759              (tv[8] - tv[7]) / (REAL) CLOCKS_PER_SEC);
34760     }
34761   }
34762 
34763   if (b->metric) {
34764     m.interpolatesizemap();
34765   }
34766 
34767   tv[9] = clock();
34768 
34769   if (!b->quiet) {
34770     if (b->metric) {
34771       printf("Size interpolating seconds:  %g\n",
34772              (tv[9] - tv[8]) / (REAL) CLOCKS_PER_SEC);
34773     }
34774   }
34775 
34776   if (b->coarse) {
34777     m.removesteiners(true);
34778   }
34779 
34780   tv[10] = clock();
34781 
34782   if (!b->quiet) {
34783     if (b->coarse) {
34784       printf("Mesh coarsening seconds:  %g\n",
34785              (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
34786     }
34787   }
34788 
34789   if (b->quality) {
34790     m.enforcequality();
34791   }
34792 
34793   tv[11] = clock();
34794 
34795   if (!b->quiet) {
34796     if (b->quality) {
34797       printf("Quality seconds:  %g\n",
34798              (tv[11] - tv[10]) / (REAL) CLOCKS_PER_SEC);
34799     }
34800   }
34801 
34802   if (b->quality && (b->optlevel > 0)) {
34803     m.optimizemesh(true);
34804   }
34805 
34806   tv[12] = clock();
34807 
34808   if (!b->quiet) {
34809     if (b->quality && (b->optlevel > 0)) {
34810       printf("Optimize seconds:  %g\n",
34811              (tv[12] - tv[11]) / (REAL) CLOCKS_PER_SEC);
34812     }
34813   }
34814 
34815   if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0)
34816       || (b->refine && (in->numberofcorners == 10)))) {
34817     m.jettisonnodes();
34818   }
34819 
34820   if (b->order > 1) {
34821     m.highorder();
34822   }
34823 
34824   if (!b->quiet) {
34825     printf("\n");
34826   }
34827 
34828   if (out != (tetgenio *) NULL) {
34829     out->firstnumber = in->firstnumber;
34830     out->mesh_dim = in->mesh_dim;
34831   }
34832 
34833   if (b->nonodewritten || b->noiterationnum) {
34834     if (!b->quiet) {
34835       printf("NOT writing a .node file.\n");
34836     }
34837   } else {
34838     if (b->diagnose == 1) {
34839       if (m.subfaces->items > 0l) {
34840         m.outnodes(out);  // Only output when self-intersecting faces exist.
34841       }
34842     } else {
34843       m.outnodes(out);
34844       if (b->quality || b->metric) {
34845         // m.outmetrics(out);
34846       }
34847     }
34848   }
34849 
34850   if (b->noelewritten) {
34851     if (!b->quiet) {
34852       printf("NOT writing an .ele file.\n");
34853     }
34854   } else {
34855     if (!(b->diagnose == 1)) {
34856       if (m.tetrahedrons->items > 0l) {
34857         m.outelements(out);
34858       }
34859     }
34860   }
34861 
34862   if (b->nofacewritten) {
34863     if (!b->quiet) {
34864       printf("NOT writing an .face file.\n");
34865     }
34866   } else {
34867     if (b->facesout) {
34868       if (m.tetrahedrons->items > 0l) {
34869         m.outfaces(out);  // Output all faces.
34870       }
34871     } else {
34872       if (b->diagnose == 1) {
34873         if (m.subfaces->items > 0l) {
34874           m.outsubfaces(out); // Only output self-intersecting faces.
34875         }
34876       } else if (b->plc || b->refine) {
34877         if (m.subfaces->items > 0l) {
34878           m.outsubfaces(out); // Output boundary faces.
34879         }
34880       } else {
34881         if (m.tetrahedrons->items > 0l) {
34882           m.outhullfaces(out); // Output convex hull faces.
34883         }
34884       }
34885     }
34886   }
34887 
34888   if (m.checkpbcs) {
34889     m.outpbcnodes(out);
34890   }
34891 
34892   if (b->edgesout) {
34893     if (b->edgesout > 1) {
34894       m.outedges(out); // -ee, output all mesh edges.
34895     } else {
34896       m.outsubsegments(out); // -e, only output subsegments.
34897     }
34898   }
34899 
34900   if (!out && b->plc &&
34901       ((b->object == tetgenbehavior::OFF) ||
34902        (b->object == tetgenbehavior::PLY) ||
34903        (b->object == tetgenbehavior::STL))) {
34904     m.outsmesh(b->outfilename);
34905   }
34906 
34907   if (!out && b->meditview) {
34908     m.outmesh2medit(b->outfilename);
34909   }
34910 
34911   if (!out && b->gidview) {
34912     m.outmesh2gid(b->outfilename);
34913   }
34914 
34915   if (!out && b->geomview) {
34916     m.outmesh2off(b->outfilename);
34917   }
34918 
34919   if (b->neighout) {
34920     m.outneighbors(out);
34921   }
34922 
34923   if (b->voroout) {
34924     m.outvoronoi(out);
34925   }
34926 
34927   tv[13] = clock();
34928 
34929   if (!b->quiet) {
34930     printf("\nOutput seconds:  %g\n",
34931            (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
34932     printf("Total running seconds:  %g\n",
34933            (tv[13] - tv[0]) / (REAL) CLOCKS_PER_SEC);
34934   }
34935 
34936   if (b->docheck) {
34937     m.checkmesh();
34938     if (m.checksubfaces) {
34939       m.checkshells();
34940     }
34941     if (b->docheck > 1) {
34942       m.checkdelaunay(0.0, NULL);
34943       if (b->docheck > 2) {
34944         if (b->quality || b->refine) {
34945           m.checkconforming();
34946         }
34947       }
34948     }
34949   }
34950 
34951   if (!b->quiet) {
34952     m.statistics();
34953   }
34954 
34955   if (b->metric) {
34956     delete m.bgm;
34957   }
34958 }
34959 
34960 #ifndef TETLIBRARY
34961 
34963 //                                                                           //
34964 // main()    The entrance for running TetGen from command line.              //
34965 //                                                                           //
34967 
34968 int main(int argc, char *argv[])
34969 
34970 #else // with TETLIBRARY
34971 
34973 //                                                                           //
34974 // tetrahedralize()    The entrance for calling TetGen from another program. //
34975 //                                                                           //
34977 
34978 void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
34979   tetgenio *addin, tetgenio *bgmin)
34980 
34981 #endif // not TETLIBRARY
34982 
34983 {
34984   tetgenbehavior b;
34985 
34986 #ifndef TETLIBRARY
34987 
34988   tetgenio in, addin, bgmin;
34989 
34990   if (!b.parse_commandline(argc, argv)) {
34991     terminatetetgen(1);
34992   }
34993   if (b.refine) {
34994     if (!in.load_tetmesh(b.infilename)) {
34995       terminatetetgen(1);
34996     }
34997   } else {
34998     if (!in.load_plc(b.infilename, (int) b.object)) {
34999       terminatetetgen(1);
35000     }
35001   }
35002   if (b.insertaddpoints) {
35003     if (!addin.load_node(b.addinfilename)) {
35004       addin.numberofpoints = 0l;
35005     }
35006   }
35007   if (b.metric) {
35008     if (!bgmin.load_tetmesh(b.bgmeshfilename)) {
35009       bgmin.numberoftetrahedra = 0l;
35010     }
35011   }
35012 
35013   if (bgmin.numberoftetrahedra > 0l) {
35014     tetrahedralize(&b, &in, NULL, &addin, &bgmin);
35015   } else {
35016     tetrahedralize(&b, &in, NULL, &addin, NULL);
35017   }
35018 
35019   return 0;
35020 
35021 #else // with TETLIBRARY
35022 
35023   if (!b.parse_commandline(switches)) {
35024     terminatetetgen(1);
35025   }
35026   tetrahedralize(&b, in, out, addin, bgmin);
35027 
35028 #endif // not TETLIBRARY
35029 }
35030 
35031 } //Added namespace to avoid clash with triangle
35032 
35033 #ifndef TETLIBRARY
35034 // Shim for entry point to main inside the namespace.  This is just in case we want to compile up a binary from this
35035 // source code.
35036 int main(int argc, char *argv[])
35037 {
35038     tetgen::main(argc, argv);
35039 }
35040 #endif // not TETLIBRARY