tetgen.cpp

Go to the documentation of this file.
00001 
00007 #ifndef UNUSED_OPT
00008 #ifdef NDEBUG
00009 #define UNUSED_OPT(var) var=var
00010 #else //NDEBUG
00011 #define UNUSED_OPT(var)
00012 #endif //NDEBUG
00013 #endif //UNUSED_OPT
00014 
00015 // This include is here so that the chaste_libs=0 build correctly links predicates.o.
00016 #include "predicates.hpp"
00017 
00019 //                                                                           //
00020 // TetGen                                                                    //
00021 //                                                                           //
00022 // A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
00023 //                                                                           //
00024 // Version 1.4                                                               //
00025 // April 16, 2007                                                            //
00026 //                                                                           //
00027 // Copyright (C) 2002--2007                                                  //
00028 // Hang Si                                                                   //
00029 // Research Group Numerical Mathematics and Scientific Computing             //
00030 // Weierstrass Institute for Applied Analysis and Stochastics                //
00031 // Mohrenstr. 39, 10117 Berlin, Germany                                      //
00032 // si@wias-berlin.de                                                         //
00033 //                                                                           //
00034 // TetGen is freely available through the website: http://tetgen.berlios.de. //
00035 //   It may be copied, modified, and redistributed for non-commercial use.   //
00036 //   Please consult the file LICENSE for the detailed copyright notices.     //
00037 //                                                                           //
00039 
00041 //                                                                           //
00042 // tetgen.cxx                                                                //
00043 //                                                                           //
00044 // The TetGen library and program.                                           //
00045 //                                                                           //
00047 
00048 #include "tetgen.h"
00049 namespace tetgen
00050 { //Added namespace to avoid clash with triangle
00051 
00053 //                                                                           //
00054 // terminatetetgen()    Terminate TetGen with a given exit code.             //
00055 //                                                                           //
00057 
00058 void terminatetetgen(int x)
00059 {
00060 #ifdef TETLIBRARY
00061   throw x;
00062 #else
00063   exit(x);
00064 #endif // #ifdef TETLIBRARY
00065 }
00066 
00067 //
00068 // Begin of class 'tetgenio' implementation
00069 //
00070 
00072 //                                                                           //
00073 // initialize()    Initialize all variables of 'tetgenio'.                   //
00074 //                                                                           //
00075 // It is called by the only class constructor 'tetgenio()' implicitly. Thus, //
00076 // all variables are guaranteed to be initialized. Each array is initialized //
00077 // to be a 'NULL' pointer, and its length is equal zero. Some variables have //
00078 // their default value, 'firstnumber' equals zero, 'mesh_dim' equals 3,  and //
00079 // 'numberofcorners' equals 4.  Another possible use of this routine is to   //
00080 // call it before to re-use an object.                                       //
00081 //                                                                           //
00083 
00084 void tetgenio::initialize()
00085 {
00086   firstnumber = 0;              // Default item index is numbered from Zero.
00087   mesh_dim = 3;                              // Default mesh dimension is 3.
00088   useindex = true;
00089 
00090   pointlist = (REAL *) NULL;
00091   pointattributelist = (REAL *) NULL;
00092   pointmtrlist = (REAL *) NULL;
00093   pointmarkerlist = (int *) NULL;
00094   numberofpoints = 0;
00095   numberofpointattributes = 0;
00096   numberofpointmtrs = 0;
00097 
00098   tetrahedronlist = (int *) NULL;
00099   tetrahedronattributelist = (REAL *) NULL;
00100   tetrahedronvolumelist = (REAL *) NULL;
00101   neighborlist = (int *) NULL;
00102   numberoftetrahedra = 0;
00103   numberofcorners = 4;                   // Default is 4 nodes per element.
00104   numberoftetrahedronattributes = 0;
00105 
00106   trifacelist = (int *) NULL;
00107   adjtetlist = (int *) NULL;
00108   trifacemarkerlist = (int *) NULL;
00109   numberoftrifaces = 0;
00110 
00111   facetlist = (facet *) NULL;
00112   facetmarkerlist = (int *) NULL;
00113   numberoffacets = 0;
00114 
00115   edgelist = (int *) NULL;
00116   edgemarkerlist = (int *) NULL;
00117   numberofedges = 0;
00118 
00119   holelist = (REAL *) NULL;
00120   numberofholes = 0;
00121 
00122   regionlist = (REAL *) NULL;
00123   numberofregions = 0;
00124 
00125   facetconstraintlist = (REAL *) NULL;
00126   numberoffacetconstraints = 0;
00127   segmentconstraintlist = (REAL *) NULL;
00128   numberofsegmentconstraints = 0;
00129 
00130   pbcgrouplist = (pbcgroup *) NULL;
00131   numberofpbcgroups = 0;
00132 
00133   vpointlist = (REAL *) NULL;
00134   vedgelist = (voroedge *) NULL;
00135   vfacetlist = (vorofacet *) NULL;
00136   vcelllist = (int **) NULL;
00137   numberofvpoints = 0;
00138   numberofvedges = 0;
00139   numberofvfacets = 0;
00140   numberofvcells = 0;
00141 }
00142 
00144 //                                                                           //
00145 // deinitialize()    Free the memory allocated in 'tetgenio'.                //
00146 //                                                                           //
00147 // It is called by the class destructor '~tetgenio()' implicitly. Hence, the //
00148 // occupied memory by arrays of an object will be automatically released on  //
00149 // the deletion of the object. However, this routine assumes that the memory //
00150 // is allocated by C++ memory allocation operator 'new', thus it is freed by //
00151 // the C++ array deletor 'delete []'. If one uses the C/C++ library function //
00152 // 'malloc()' to allocate memory for arrays, one has to free them with the   //
00153 // 'free()' function, and call routine 'initialize()' once to disable this   //
00154 // routine on deletion of the object.                                        //
00155 //                                                                           //
00157 
00158 void tetgenio::deinitialize()
00159 {
00160   facet *f;
00161   polygon *p;
00162   pbcgroup *pg;
00163   int i, j;
00164 
00165   if (pointlist != (REAL *) NULL) {
00166     delete [] pointlist;
00167   }
00168   if (pointattributelist != (REAL *) NULL) {
00169     delete [] pointattributelist;
00170   }
00171   if (pointmtrlist != (REAL *) NULL) {
00172     delete [] pointmtrlist;
00173   }
00174   if (pointmarkerlist != (int *) NULL) {
00175     delete [] pointmarkerlist;
00176   }
00177 
00178   if (tetrahedronlist != (int *) NULL) {
00179     delete [] tetrahedronlist;
00180   }
00181   if (tetrahedronattributelist != (REAL *) NULL) {
00182     delete [] tetrahedronattributelist;
00183   }
00184   if (tetrahedronvolumelist != (REAL *) NULL) {
00185     delete [] tetrahedronvolumelist;
00186   }
00187   if (neighborlist != (int *) NULL) {
00188     delete [] neighborlist;
00189   }
00190 
00191   if (trifacelist != (int *) NULL) {
00192     delete [] trifacelist;
00193   }
00194   if (adjtetlist != (int *) NULL) {
00195     delete [] adjtetlist;
00196   }
00197   if (trifacemarkerlist != (int *) NULL) {
00198     delete [] trifacemarkerlist;
00199   }
00200 
00201   if (edgelist != (int *) NULL) {
00202     delete [] edgelist;
00203   }
00204   if (edgemarkerlist != (int *) NULL) {
00205     delete [] edgemarkerlist;
00206   }
00207 
00208   if (facetlist != (facet *) NULL) {
00209     for (i = 0; i < numberoffacets; i++) {
00210       f = &facetlist[i];
00211       for (j = 0; j < f->numberofpolygons; j++) {
00212         p = &f->polygonlist[j];
00213         delete [] p->vertexlist;
00214       }
00215       delete [] f->polygonlist;
00216       if (f->holelist != (REAL *) NULL) {
00217         delete [] f->holelist;
00218       }
00219     }
00220     delete [] facetlist;
00221   }
00222   if (facetmarkerlist != (int *) NULL) {
00223     delete [] facetmarkerlist;
00224   }
00225 
00226   if (holelist != (REAL *) NULL) {
00227     delete [] holelist;
00228   }
00229   if (regionlist != (REAL *) NULL) {
00230     delete [] regionlist;
00231   }
00232   if (facetconstraintlist != (REAL *) NULL) {
00233     delete [] facetconstraintlist;
00234   }
00235   if (segmentconstraintlist != (REAL *) NULL) {
00236     delete [] segmentconstraintlist;
00237   }
00238   if (pbcgrouplist != (pbcgroup *) NULL) {
00239     for (i = 0; i < numberofpbcgroups; i++) {
00240       pg = &(pbcgrouplist[i]);
00241       if (pg->pointpairlist != (int *) NULL) {
00242         delete [] pg->pointpairlist;
00243       }
00244     }
00245     delete [] pbcgrouplist;
00246   }
00247   if (vpointlist != (REAL *) NULL) {
00248     delete [] vpointlist;
00249   }
00250   if (vedgelist != (voroedge *) NULL) {
00251     delete [] vedgelist;
00252   }
00253   if (vfacetlist != (vorofacet *) NULL) {
00254     for (i = 0; i < numberofvfacets; i++) {
00255       delete [] vfacetlist[i].elist;
00256     }
00257     delete [] vfacetlist;
00258   }
00259   if (vcelllist != (int **) NULL) {
00260     for (i = 0; i < numberofvcells; i++) {
00261       delete [] vcelllist[i];
00262     }
00263     delete [] vcelllist;
00264   }
00265 }
00266 
00268 //                                                                           //
00269 // load_node_call()    Load a list of nodes.                                 //
00270 //                                                                           //
00271 // It is a support routine for routines: 'load_nodes()', 'load_poly()', and  //
00272 // 'load_tetmesh()'.  'infile' is the file handle contains the node list. It //
00273 // may point to a .node, or .poly or .smesh file.  'markers' indicates each  //
00274 // node contains an additional marker (integer) or not. 'infilename' is the  //
00275 // name of the file being read,  it is only appeared in error message.       //
00276 //                                                                           //
00277 // The 'firstnumber' (0 or 1) is automatically determined by the number of   //
00278 // the first index of the first point.                                       //
00279 //                                                                           //
00281 
00282 bool tetgenio::load_node_call(FILE* infile, int markers, char* infilename)
00283 {
00284   char inputline[INPUTLINESIZE];
00285   char *stringptr;
00286   REAL x, y, z, attrib;
00287   int firstnode, currentmarker;
00288   int index, attribindex;
00289   int i, j;
00290 
00291   // Initialize 'pointlist', 'pointattributelist', and 'pointmarkerlist'.
00292   pointlist = new REAL[numberofpoints * 3];
00293   if (pointlist == (REAL *) NULL) {
00294     printf("Error:  Out of memory.\n");
00295     terminatetetgen(1);
00296   }
00297   if (numberofpointattributes > 0) {
00298     pointattributelist = new REAL[numberofpoints * numberofpointattributes];
00299     if (pointattributelist == (REAL *) NULL) {
00300       printf("Error:  Out of memory.\n");
00301       terminatetetgen(1);
00302     }
00303   }
00304   if (markers) {
00305     pointmarkerlist = new int[numberofpoints];
00306     if (pointmarkerlist == (int *) NULL) {
00307       printf("Error:  Out of memory.\n");
00308       terminatetetgen(1);
00309     }
00310   }
00311 
00312   // Read the point section.
00313   index = 0;
00314   attribindex = 0;
00315   for (i = 0; i < numberofpoints; i++) {
00316     stringptr = readnumberline(inputline, infile, infilename);
00317     if (useindex) {
00318       if (i == 0) {
00319         firstnode = (int) strtol (stringptr, &stringptr, 0);
00320         if ((firstnode == 0) || (firstnode == 1)) {
00321           firstnumber = firstnode;
00322         }
00323       }
00324       stringptr = findnextnumber(stringptr);
00325     } // if (useindex)
00326     if (*stringptr == '\0') {
00327       printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
00328       break;
00329     }
00330     x = (REAL) strtod(stringptr, &stringptr);
00331     stringptr = findnextnumber(stringptr);
00332     if (*stringptr == '\0') {
00333       printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
00334       break;
00335     }
00336     y = (REAL) strtod(stringptr, &stringptr);
00337     if (mesh_dim == 3) {
00338       stringptr = findnextnumber(stringptr);
00339       if (*stringptr == '\0') {
00340         printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
00341         break;
00342       }
00343       z = (REAL) strtod(stringptr, &stringptr);
00344     } else {
00345       z = 0.0; // mesh_dim == 2;
00346     }
00347     pointlist[index++] = x;
00348     pointlist[index++] = y;
00349     pointlist[index++] = z;
00350     // Read the point attributes.
00351     for (j = 0; j < numberofpointattributes; j++) {
00352       stringptr = findnextnumber(stringptr);
00353       if (*stringptr == '\0') {
00354         attrib = 0.0;
00355       } else {
00356         attrib = (REAL) strtod(stringptr, &stringptr);
00357       }
00358       pointattributelist[attribindex++] = attrib;
00359     }
00360     if (markers) {
00361       // Read a point marker.
00362       stringptr = findnextnumber(stringptr);
00363       if (*stringptr == '\0') {
00364         currentmarker = 0;
00365       } else {
00366         currentmarker = (int) strtol (stringptr, &stringptr, 0);
00367       }
00368       pointmarkerlist[i] = currentmarker;
00369     }
00370   }
00371   if (i < numberofpoints) {
00372     // Failed to read points due to some error.
00373     delete [] pointlist;
00374     pointlist = (REAL *) NULL;
00375     if (markers) {
00376       delete [] pointmarkerlist;
00377       pointmarkerlist = (int *) NULL;
00378     }
00379     if (numberofpointattributes > 0) {
00380       delete [] pointattributelist;
00381       pointattributelist = (REAL *) NULL;
00382     }
00383     numberofpoints = 0;
00384     return false;
00385   }
00386   return true;
00387 }
00388 
00390 //                                                                           //
00391 // load_node()    Load a list of nodes from a .node file.                    //
00392 //                                                                           //
00393 // 'filename' is the inputfile without suffix. The node list is in 'filename.//
00394 // node'. On completion, the node list is returned in 'pointlist'.           //
00395 //                                                                           //
00397 
00398 bool tetgenio::load_node(char* filename)
00399 {
00400   FILE *infile;
00401   char innodefilename[FILENAMESIZE];
00402   char inputline[INPUTLINESIZE];
00403   char *stringptr;
00404   int markers;
00405 
00406   markers = 0;
00407   // Assembling the actual file names we want to open.
00408   strcpy(innodefilename, filename);
00409   strcat(innodefilename, ".node");
00410 
00411   // Try to open a .node file.
00412   infile = fopen(innodefilename, "r");
00413   if (infile == (FILE *) NULL) {
00414     printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
00415     return false;
00416   }
00417   printf("Opening %s.\n", innodefilename);
00418   // Read the first line of the file.
00419   stringptr = readnumberline(inputline, infile, innodefilename);
00420   // Is this list of points generated from rbox?
00421   stringptr = strstr(inputline, "rbox");
00422   if (stringptr == NULL) {
00423     // Read number of points, number of dimensions, number of point
00424     //   attributes, and number of boundary markers.
00425     stringptr = inputline;
00426     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00427     stringptr = findnextnumber(stringptr);
00428     if (*stringptr == '\0') {
00429       mesh_dim = 3;
00430     } else {
00431       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00432     }
00433     stringptr = findnextnumber(stringptr);
00434     if (*stringptr == '\0') {
00435       numberofpointattributes = 0;
00436     } else {
00437       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00438     }
00439     stringptr = findnextnumber(stringptr);
00440     if (*stringptr == '\0') {
00441       markers = 0;
00442     } else {
00443       markers = (int) strtol (stringptr, &stringptr, 0);
00444     }
00445   } else {
00446     // It is a rbox (qhull) input file.
00447     stringptr = inputline;
00448     // Get the dimension.
00449     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00450     // Get the number of points.
00451     stringptr = readnumberline(inputline, infile, innodefilename);
00452     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00453     // There is no index column.
00454     useindex = 0;
00455   }
00456 
00457   // if ((mesh_dim != 3) && (mesh_dim != 2)) {
00458   //   printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
00459   //   fclose(infile);
00460   //   return false;
00461   // }
00462   if (numberofpoints < (mesh_dim + 1)) {
00463     printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
00464     fclose(infile);
00465     return false;
00466   }
00467 
00468   // Load the list of nodes.
00469   if (!load_node_call(infile, markers, innodefilename)) {
00470     fclose(infile);
00471     return false;
00472   }
00473   fclose(infile);
00474   return true;
00475 }
00476 
00478 //                                                                           //
00479 // load_pbc()    Load a list of pbc groups into 'pbcgrouplist'.              //
00480 //                                                                           //
00481 // 'filename' is the filename of the original inputfile without suffix. The  //
00482 // pbc groups are found in file 'filename.pbc'.                              //
00483 //                                                                           //
00484 // This routine will be called both in load_poly() and load_tetmesh().       //
00485 //                                                                           //
00487 
00488 bool tetgenio::load_pbc(char* filename)
00489 {
00490   FILE *infile;
00491   char pbcfilename[FILENAMESIZE];
00492   char inputline[INPUTLINESIZE];
00493   char *stringptr;
00494   pbcgroup *pg;
00495   int index, p1, p2;
00496   int i, j, k;
00497 
00498   // Pbc groups are saved in file "filename.pbc".
00499   strcpy(pbcfilename, filename);
00500   strcat(pbcfilename, ".pbc");
00501   infile = fopen(pbcfilename, "r");
00502   if (infile != (FILE *) NULL) {
00503     printf("Opening %s.\n", pbcfilename);
00504   } else {
00505     // No such file. Return.
00506     return false;
00507   }
00508 
00509   // Read the number of pbc groups.
00510   stringptr = readnumberline(inputline, infile, pbcfilename);
00511   numberofpbcgroups = (int) strtol (stringptr, &stringptr, 0);
00512   if (numberofpbcgroups == 0) {
00513     // It looks this file contains no point.
00514     fclose(infile);
00515     return false;
00516   }
00517   // Initialize 'pbcgrouplist';
00518   pbcgrouplist = new pbcgroup[numberofpbcgroups];
00519 
00520   // Read the list of pbc groups.
00521   for (i = 0; i < numberofpbcgroups; i++) {
00522     pg = &(pbcgrouplist[i]);
00523     // Initialize pbcgroup i;
00524     pg->numberofpointpairs = 0;
00525     pg->pointpairlist = (int *) NULL;
00526     // Read 'fmark1', 'fmark2'.
00527     stringptr = readnumberline(inputline, infile, pbcfilename);
00528     if (*stringptr == '\0') break;
00529     pg->fmark1 = (int) strtol(stringptr, &stringptr, 0);
00530     stringptr = findnextnumber(stringptr);
00531     if (*stringptr == '\0') break;
00532     pg->fmark2 = (int) strtol(stringptr, &stringptr, 0);
00533     // Read 'transmat'.
00534     do {
00535       stringptr = readline(inputline, infile, NULL);
00536     } while ((*stringptr != '[') && (*stringptr != '\0'));
00537     if (*stringptr == '\0') break;
00538     for (j = 0; j < 4; j++) {
00539       for (k = 0; k < 4; k++) {
00540         // Read the entry of [j, k].
00541         stringptr = findnextnumber(stringptr);
00542         if (*stringptr == '\0') {
00543           // Try to read another line.
00544           stringptr = readnumberline(inputline, infile, pbcfilename);
00545           if (*stringptr == '\0') break;
00546         }
00547         pg->transmat[j][k] = (REAL) strtod(stringptr, &stringptr);
00548       }
00549       if (k < 4) break; // Not complete!
00550     }
00551     if (j < 4) break; // Not complete!
00552     // Read 'numberofpointpairs'.
00553     stringptr = readnumberline(inputline, infile, pbcfilename);
00554     if (*stringptr == '\0') break;
00555     pg->numberofpointpairs = (int) strtol(stringptr, &stringptr, 0);
00556     if (pg->numberofpointpairs > 0) {
00557       pg->pointpairlist = new int[pg->numberofpointpairs * 2];
00558       // Read the point pairs.
00559       index = 0;
00560       for (j = 0; j < pg->numberofpointpairs; j++) {
00561         stringptr = readnumberline(inputline, infile, pbcfilename);
00562         p1 = (int) strtol(stringptr, &stringptr, 0);
00563         stringptr = findnextnumber(stringptr);
00564         p2 = (int) strtol(stringptr, &stringptr, 0);
00565         pg->pointpairlist[index++] = p1;
00566         pg->pointpairlist[index++] = p2;
00567       }
00568     }
00569   }
00570   fclose(infile);
00571 
00572   if (i < numberofpbcgroups) {
00573     // Failed to read to additional points due to some error.
00574     delete [] pbcgrouplist;
00575     pbcgrouplist = (pbcgroup *) NULL;
00576     numberofpbcgroups = 0;
00577     return false;
00578   }
00579   return true;
00580 }
00581 
00583 //                                                                           //
00584 // load_var()    Load variant constraints applied on facets, segments, nodes.//
00585 //                                                                           //
00586 // 'filename' is the filename of the original inputfile without suffix. The  //
00587 // constraints are found in file 'filename.var'.                             //
00588 //                                                                           //
00590 
00591 bool tetgenio::load_var(char* filename)
00592 {
00593   FILE *infile;
00594   char varfilename[FILENAMESIZE];
00595   char inputline[INPUTLINESIZE];
00596   char *stringptr;
00597   int index;
00598   int i;
00599 
00600   // Variant constraints are saved in file "filename.var".
00601   strcpy(varfilename, filename);
00602   strcat(varfilename, ".var");
00603   infile = fopen(varfilename, "r");
00604   if (infile != (FILE *) NULL) {
00605     printf("Opening %s.\n", varfilename);
00606   } else {
00607     // No such file. Return.
00608     return false;
00609   }
00610 
00611   // Read the facet constraint section.
00612   stringptr = readnumberline(inputline, infile, varfilename);
00613   if (*stringptr != '\0') {
00614     numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0);
00615   } else {
00616     numberoffacetconstraints = 0;
00617   }
00618   if (numberoffacetconstraints > 0) {
00619     // Initialize 'facetconstraintlist'.
00620     facetconstraintlist = new REAL[numberoffacetconstraints * 2];
00621     index = 0;
00622     for (i = 0; i < numberoffacetconstraints; i++) {
00623       stringptr = readnumberline(inputline, infile, varfilename);
00624       stringptr = findnextnumber(stringptr);
00625       if (*stringptr == '\0') {
00626         printf("Error:  facet constraint %d has no facet marker.\n",
00627                firstnumber + i);
00628         break;
00629       } else {
00630         facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00631       }
00632       stringptr = findnextnumber(stringptr);
00633       if (*stringptr == '\0') {
00634         printf("Error:  facet constraint %d has no maximum area bound.\n",
00635                firstnumber + i);
00636         break;
00637       } else {
00638         facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00639       }
00640     }
00641     if (i < numberoffacetconstraints) {
00642       // This must be caused by an error.
00643       fclose(infile);
00644       return false;
00645     }
00646   }
00647 
00648   // Read the segment constraint section.
00649   stringptr = readnumberline(inputline, infile, varfilename);
00650   if (*stringptr != '\0') {
00651     numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0);
00652   } else {
00653     numberofsegmentconstraints = 0;
00654   }
00655   if (numberofsegmentconstraints > 0) {
00656     // Initialize 'segmentconstraintlist'.
00657     segmentconstraintlist = new REAL[numberofsegmentconstraints * 3];
00658     index = 0;
00659     for (i = 0; i < numberofsegmentconstraints; i++) {
00660       stringptr = readnumberline(inputline, infile, varfilename);
00661       stringptr = findnextnumber(stringptr);
00662       if (*stringptr == '\0') {
00663         printf("Error:  segment constraint %d has no frist endpoint.\n",
00664                firstnumber + i);
00665         break;
00666       } else {
00667         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00668       }
00669       stringptr = findnextnumber(stringptr);
00670       if (*stringptr == '\0') {
00671         printf("Error:  segment constraint %d has no second endpoint.\n",
00672                firstnumber + i);
00673         break;
00674       } else {
00675         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00676       }
00677       stringptr = findnextnumber(stringptr);
00678       if (*stringptr == '\0') {
00679         printf("Error:  segment constraint %d has no maximum length bound.\n",
00680                firstnumber + i);
00681         break;
00682       } else {
00683         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00684       }
00685     }
00686     if (i < numberofsegmentconstraints) {
00687       // This must be caused by an error.
00688       fclose(infile);
00689       return false;
00690     }
00691   }
00692 
00693   fclose(infile);
00694   return true;
00695 }
00696 
00698 //                                                                           //
00699 // load_mtr()    Load a size specification map from file.                    //
00700 //                                                                           //
00701 // 'filename' is the filename of the original inputfile without suffix. The  //
00702 // size map is found in file 'filename.mtr'.                                 //
00703 //                                                                           //
00705 
00706 bool tetgenio::load_mtr(char* filename)
00707 {
00708   FILE *infile;
00709   char mtrfilename[FILENAMESIZE];
00710   char inputline[INPUTLINESIZE];
00711   char *stringptr;
00712   REAL mtr;
00713   int mtrindex;
00714   int i, j;
00715 
00716   strcpy(mtrfilename, filename);
00717   strcat(mtrfilename, ".mtr");
00718   infile = fopen(mtrfilename, "r");
00719   if (infile != (FILE *) NULL) {
00720     printf("Opening %s.\n", mtrfilename);
00721   } else {
00722     // No such file. Return.
00723     return false;
00724   }
00725 
00726   // Read number of points, number of columns (1, 3, or 6).
00727   stringptr = readnumberline(inputline, infile, mtrfilename);
00728   stringptr = findnextnumber(stringptr); // Skip number of points.
00729   if (*stringptr != '\0') {
00730     numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0);
00731   }
00732   if (numberofpointmtrs == 0) {
00733     // Column number doesn't match. Set a default number (1).
00734     numberofpointmtrs = 1;
00735   }
00736 
00737   // Allocate space for pointmtrlist.
00738   pointmtrlist = new REAL[numberofpoints * numberofpointmtrs];
00739   if (pointmtrlist == (REAL *) NULL) {
00740     printf("Error:  Out of memory.\n");
00741     terminatetetgen(1);
00742   }
00743   mtrindex = 0;
00744   for (i = 0; i < numberofpoints; i++) {
00745     // Read metrics.
00746     stringptr = readnumberline(inputline, infile, mtrfilename);
00747     for (j = 0; j < numberofpointmtrs; j++) {
00748       if (*stringptr == '\0') {
00749         printf("Error:  Metric %d is missing value #%d in %s.\n",
00750                i + firstnumber, j + 1, mtrfilename);
00751         terminatetetgen(1);
00752       }
00753       mtr = (REAL) strtod(stringptr, &stringptr);
00754       pointmtrlist[mtrindex++] = mtr;
00755       stringptr = findnextnumber(stringptr);
00756     }
00757   }
00758 
00759   fclose(infile);
00760   return true;
00761 }
00762 
00764 //                                                                           //
00765 // load_poly()    Load a piecewise linear complex from a .poly or .smesh.    //
00766 //                                                                           //
00767 // 'filename' is the inputfile without suffix. The PLC is in 'filename.poly' //
00768 // or 'filename.smesh', and possibly plus 'filename.node' (when the first    //
00769 // line of the file starts with a zero).                                     //
00770 //                                                                           //
00772 
00773 bool tetgenio::load_poly(char* filename)
00774 {
00775   FILE *infile, *polyfile;
00776   char innodefilename[FILENAMESIZE];
00777   char inpolyfilename[FILENAMESIZE];
00778   char insmeshfilename[FILENAMESIZE];
00779   char inputline[INPUTLINESIZE];
00780   char *stringptr, *infilename;
00781   int smesh, markers, currentmarker;
00782   int readnodefile, index;
00783   int i, j, k;
00784 
00785   // Assembling the actual file names we want to open.
00786   strcpy(innodefilename, filename);
00787   strcpy(inpolyfilename, filename);
00788   strcpy(insmeshfilename, filename);
00789   strcat(innodefilename, ".node");
00790   strcat(inpolyfilename, ".poly");
00791   strcat(insmeshfilename, ".smesh");
00792 
00793   // First assume it is a .poly file.
00794   smesh = 0;
00795   // Try to open a .poly file.
00796   polyfile = fopen(inpolyfilename, "r");
00797   if (polyfile == (FILE *) NULL) {
00798     // .poly doesn't exist! Try to open a .smesh file.
00799     polyfile = fopen(insmeshfilename, "r");
00800     if (polyfile == (FILE *) NULL) {
00801       printf("File I/O Error:  Cannot access file %s and %s.\n",
00802              inpolyfilename, insmeshfilename);
00803       return false;
00804     } else {
00805       printf("Opening %s.\n", insmeshfilename);
00806     }
00807     smesh = 1;
00808   } else {
00809     printf("Opening %s.\n", inpolyfilename);
00810   }
00811   // Initialize the default values.
00812   mesh_dim = 3;  // Three-dimemsional accoordinates.
00813   numberofpointattributes = 0;  // no point attribute.
00814   markers = 0;  // no boundary marker.
00815   // Read number of points, number of dimensions, number of point
00816   //   attributes, and number of boundary markers.
00817   stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00818   numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00819   stringptr = findnextnumber(stringptr);
00820   if (*stringptr != '\0') {
00821     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00822   }
00823   stringptr = findnextnumber(stringptr);
00824   if (*stringptr != '\0') {
00825     numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00826   }
00827   stringptr = findnextnumber(stringptr);
00828   if (*stringptr != '\0') {
00829     markers = (int) strtol (stringptr, &stringptr, 0);
00830   }
00831   if (numberofpoints > 0) {
00832     readnodefile = 0;
00833     if (smesh) {
00834       infilename = insmeshfilename;
00835     } else {
00836       infilename = inpolyfilename;
00837     }
00838     infile = polyfile;
00839   } else {
00840     // If the .poly or .smesh file claims there are zero points, that
00841     //   means the points should be read from a separate .node file.
00842     readnodefile = 1;
00843     infilename = innodefilename;
00844   }
00845 
00846   if (readnodefile) {
00847     // Read the points from the .node file.
00848     printf("Opening %s.\n", innodefilename);
00849     infile = fopen(innodefilename, "r");
00850     if (infile == (FILE *) NULL) {
00851       printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
00852       return false;
00853     }
00854     // Initialize the default values.
00855     mesh_dim = 3;  // Three-dimemsional accoordinates.
00856     numberofpointattributes = 0;  // no point attribute.
00857     markers = 0;  // no boundary marker.
00858     // Read number of points, number of dimensions, number of point
00859     //   attributes, and number of boundary markers.
00860     stringptr = readnumberline(inputline, infile, innodefilename);
00861     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00862     stringptr = findnextnumber(stringptr);
00863     if (*stringptr != '\0') {
00864       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00865     }
00866     stringptr = findnextnumber(stringptr);
00867     if (*stringptr != '\0') {
00868       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00869     }
00870     stringptr = findnextnumber(stringptr);
00871     if (*stringptr != '\0') {
00872       markers = (int) strtol (stringptr, &stringptr, 0);
00873     }
00874   }
00875 
00876   if ((mesh_dim != 3) && (mesh_dim != 2)) {
00877     printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
00878     fclose(infile);
00879     return false;
00880   }
00881   if (numberofpoints < (mesh_dim + 1)) {
00882     printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
00883     fclose(infile);
00884     return false;
00885   }
00886 
00887   // Load the list of nodes.
00888   if (!load_node_call(infile, markers, infilename)) {
00889     fclose(infile);
00890     return false;
00891   }
00892 
00893   if (readnodefile) {
00894     fclose(infile);
00895   }
00896 
00897   facet *f;
00898   polygon *p;
00899 
00900   if (mesh_dim == 3) {
00901 
00902     // Read number of facets and number of boundary markers.
00903     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00904     numberoffacets = (int) strtol (stringptr, &stringptr, 0);
00905     if (numberoffacets <= 0) {
00906       // No facet list, return.
00907       fclose(polyfile);
00908       return true;
00909     }
00910     stringptr = findnextnumber(stringptr);
00911     if (*stringptr == '\0') {
00912       markers = 0;  // no boundary marker.
00913     } else {
00914       markers = (int) strtol (stringptr, &stringptr, 0);
00915     }
00916 
00917     // Initialize the 'facetlist', 'facetmarkerlist'.
00918     facetlist = new facet[numberoffacets];
00919     if (markers == 1) {
00920       facetmarkerlist = new int[numberoffacets];
00921     }
00922 
00923     // Read data into 'facetlist', 'facetmarkerlist'.
00924     if (smesh == 0) {
00925       // Facets are in .poly file format.
00926       for (i = 1; i <= numberoffacets; i++) {
00927         f = &(facetlist[i - 1]);
00928         init(f);
00929         f->numberofholes = 0;
00930         currentmarker = 0;
00931         // Read number of polygons, number of holes, and a boundary marker.
00932         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00933         f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
00934         stringptr = findnextnumber(stringptr);
00935         if (*stringptr != '\0') {
00936           f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
00937           if (markers == 1) {
00938             stringptr = findnextnumber(stringptr);
00939             if (*stringptr != '\0') {
00940               currentmarker = (int) strtol(stringptr, &stringptr, 0);
00941             }
00942           }
00943         }
00944         // Initialize facetmarker if it needs.
00945         if (markers == 1) {
00946           facetmarkerlist[i - 1] = currentmarker;
00947         }
00948         // Each facet should has at least one polygon.
00949         if (f->numberofpolygons <= 0) {
00950           printf("Error:  Wrong number of polygon in %d facet.\n", i);
00951           break;
00952         }
00953         // Initialize the 'f->polygonlist'.
00954         f->polygonlist = new polygon[f->numberofpolygons];
00955         // Go through all polygons, read in their vertices.
00956         for (j = 1; j <= f->numberofpolygons; j++) {
00957           p = &(f->polygonlist[j - 1]);
00958           init(p);
00959           // Read number of vertices of this polygon.
00960           stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00961           p->numberofvertices = (int) strtol(stringptr, &stringptr, 0);
00962           if (p->numberofvertices < 1) {
00963             printf("Error:  Wrong polygon %d in facet %d\n", j, i);
00964             break;
00965           }
00966           // Initialize 'p->vertexlist'.
00967           p->vertexlist = new int[p->numberofvertices];
00968           // Read all vertices of this polygon.
00969           for (k = 1; k <= p->numberofvertices; k++) {
00970             stringptr = findnextnumber(stringptr);
00971             if (*stringptr == '\0') {
00972               // Try to load another non-empty line and continue to read the
00973               //   rest of vertices.
00974               stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00975               if (*stringptr == '\0') {
00976                 printf("Error: Missing %d endpoints of polygon %d in facet %d",
00977                        p->numberofvertices - k, j, i);
00978                 break;
00979               }
00980             }
00981             p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
00982           }
00983         }
00984         if (j <= f->numberofpolygons) {
00985           // This must be caused by an error. However, there're j - 1
00986           //   polygons have been read. Reset the 'f->numberofpolygon'.
00987           if (j == 1) {
00988             // This is the first polygon.
00989             delete [] f->polygonlist;
00990           }
00991           f->numberofpolygons = j - 1;
00992           // No hole will be read even it exists.
00993           f->numberofholes = 0;
00994           break;
00995         }
00996         // If this facet has hole pints defined, read them.
00997         if (f->numberofholes > 0) {
00998           // Initialize 'f->holelist'.
00999           f->holelist = new REAL[f->numberofholes * 3];
01000           // Read the holes' coordinates.
01001           index = 0;
01002           for (j = 1; j <= f->numberofholes; j++) {
01003             stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01004             for (k = 1; k <= 3; k++) {
01005               stringptr = findnextnumber(stringptr);
01006               if (*stringptr == '\0') {
01007                 printf("Error:  Hole %d in facet %d has no coordinates", j, i);
01008                 break;
01009               }
01010               f->holelist[index++] = (REAL) strtod (stringptr, &stringptr);
01011             }
01012             if (k <= 3) {
01013               // This must be caused by an error.
01014               break;
01015             }
01016           }
01017           if (j <= f->numberofholes) {
01018             // This must be caused by an error.
01019             break;
01020           }
01021         }
01022       }
01023       if (i <= numberoffacets) {
01024         // This must be caused by an error.
01025         numberoffacets = i - 1;
01026         fclose(polyfile);
01027         return false;
01028       }
01029     } else { // poly == 0
01030       // Read the facets from a .smesh file.
01031       for (i = 1; i <= numberoffacets; i++) {
01032         f = &(facetlist[i - 1]);
01033         init(f);
01034         // Initialize 'f->facetlist'. In a .smesh file, each facetlist only
01035         //   contains exactly one polygon, no hole.
01036         f->numberofpolygons = 1;
01037         f->polygonlist = new polygon[f->numberofpolygons];
01038         p = &(f->polygonlist[0]);
01039         init(p);
01040         // Read number of vertices of this polygon.
01041         stringptr = readnumberline(inputline, polyfile, insmeshfilename);
01042         p->numberofvertices = (int) strtol (stringptr, &stringptr, 0);
01043         if (p->numberofvertices < 1) {
01044           printf("Error:  Wrong number of vertex in facet %d\n", i);
01045           break;
01046         }
01047         // Initialize 'p->vertexlist'.
01048         p->vertexlist = new int[p->numberofvertices];
01049         for (k = 1; k <= p->numberofvertices; k++) {
01050           stringptr = findnextnumber(stringptr);
01051           if (*stringptr == '\0') {
01052             // Try to load another non-empty line and continue to read the
01053             //   rest of vertices.
01054             stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01055             if (*stringptr == '\0') {
01056               printf("Error:  Missing %d endpoints in facet %d",
01057                      p->numberofvertices - k, i);
01058               break;
01059             }
01060           }
01061           p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
01062         }
01063         if (k <= p->numberofvertices) {
01064           // This must be caused by an error.
01065           break;
01066         }
01067         // Read facet's boundary marker at last.
01068         if (markers == 1) {
01069           stringptr = findnextnumber(stringptr);
01070           if (*stringptr == '\0') {
01071             currentmarker = 0;
01072           } else {
01073             currentmarker = (int) strtol(stringptr, &stringptr, 0);
01074           }
01075           facetmarkerlist[i - 1] = currentmarker;
01076         }
01077       }
01078       if (i <= numberoffacets) {
01079         // This must be caused by an error.
01080         numberoffacets = i - 1;
01081         fclose(polyfile);
01082         return false;
01083       }
01084     }
01085 
01086     // Read the hole section.
01087     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01088     if (*stringptr != '\0') {
01089       numberofholes = (int) strtol (stringptr, &stringptr, 0);
01090     } else {
01091       numberofholes = 0;
01092     }
01093     if (numberofholes > 0) {
01094       // Initialize 'holelist'.
01095       holelist = new REAL[numberofholes * 3];
01096       for (i = 0; i < 3 * numberofholes; i += 3) {
01097         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01098         stringptr = findnextnumber(stringptr);
01099         if (*stringptr == '\0') {
01100           printf("Error:  Hole %d has no x coord.\n", firstnumber + (i / 3));
01101           break;
01102         } else {
01103           holelist[i] = (REAL) strtod(stringptr, &stringptr);
01104         }
01105         stringptr = findnextnumber(stringptr);
01106         if (*stringptr == '\0') {
01107           printf("Error:  Hole %d has no y coord.\n", firstnumber + (i / 3));
01108           break;
01109         } else {
01110           holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
01111         }
01112         stringptr = findnextnumber(stringptr);
01113         if (*stringptr == '\0') {
01114           printf("Error:  Hole %d has no z coord.\n", firstnumber + (i / 3));
01115           break;
01116         } else {
01117           holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
01118         }
01119       }
01120       if (i < 3 * numberofholes) {
01121         // This must be caused by an error.
01122         fclose(polyfile);
01123         return false;
01124       }
01125     }
01126 
01127     // Read the region section.  The 'region' section is optional, if we
01128     //   don't reach the end-of-file, try read it in.
01129     stringptr = readnumberline(inputline, polyfile, NULL);
01130     if (stringptr != (char *) NULL && *stringptr != '\0') {
01131       numberofregions = (int) strtol (stringptr, &stringptr, 0);
01132     } else {
01133       numberofregions = 0;
01134     }
01135     if (numberofregions > 0) {
01136       // Initialize 'regionlist'.
01137       regionlist = new REAL[numberofregions * 5];
01138       index = 0;
01139       for (i = 0; i < numberofregions; i++) {
01140         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01141         stringptr = findnextnumber(stringptr);
01142         if (*stringptr == '\0') {
01143           printf("Error:  Region %d has no x 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 y 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 z coordinate.\n", firstnumber + i);
01158           break;
01159         } else {
01160           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01161         }
01162         stringptr = findnextnumber(stringptr);
01163         if (*stringptr == '\0') {
01164           printf("Error:  Region %d has no region attrib.\n", firstnumber + i);
01165           break;
01166         } else {
01167           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01168         }
01169         stringptr = findnextnumber(stringptr);
01170         if (*stringptr == '\0') {
01171           regionlist[index] = regionlist[index - 1];
01172         } else {
01173           regionlist[index] = (REAL) strtod(stringptr, &stringptr);
01174         }
01175         index++;
01176       }
01177       if (i < numberofregions) {
01178         // This must be caused by an error.
01179         fclose(polyfile);
01180         return false;
01181       }
01182     }
01183 
01184   } else {
01185 
01186     // Read a PSLG from Triangle's poly file.
01187     assert(mesh_dim == 2);
01188     // A PSLG is a facet of a PLC.
01189     numberoffacets = 1;
01190     // Initialize the 'facetlist'.
01191     facetlist = new facet[numberoffacets];
01192     facetmarkerlist = (int *) NULL; // No facet markers.
01193     f = &(facetlist[0]);
01194     init(f);
01195     // Read number of segments.
01196     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01197     // Segments are degenerate polygons.
01198     f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
01199     if (f->numberofpolygons > 0) {
01200       f->polygonlist = new polygon[f->numberofpolygons];
01201     }
01202     // Go through all segments, read in their vertices.
01203     for (j = 0; j < f->numberofpolygons; j++) {
01204       p = &(f->polygonlist[j]);
01205       init(p);
01206       // Read in a segment.
01207       stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01208       stringptr = findnextnumber(stringptr); // Skip its index.
01209       p->numberofvertices = 2; // A segment always has two vertices.
01210       p->vertexlist = new int[p->numberofvertices];
01211       p->vertexlist[0] = (int) strtol (stringptr, &stringptr, 0);
01212       stringptr = findnextnumber(stringptr);
01213       p->vertexlist[1] = (int) strtol (stringptr, &stringptr, 0);
01214     }
01215     // Read number of holes.
01216     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01217     f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
01218     if (f->numberofholes > 0) {
01219       // Initialize 'f->holelist'.
01220       f->holelist = new REAL[f->numberofholes * 3];
01221       // Read the holes' coordinates.
01222       for (j = 0; j < f->numberofholes; j++) {
01223         // Read a 2D hole point.
01224         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01225         stringptr = findnextnumber(stringptr); // Skip its index.
01226         f->holelist[j * 3] = (REAL) strtod (stringptr, &stringptr);
01227         stringptr = findnextnumber(stringptr);
01228         f->holelist[j * 3 + 1] = (REAL) strtod (stringptr, &stringptr);
01229         f->holelist[j * 3 + 2] = 0.0; // The z-coord.
01230       }
01231     }
01232     // The regions are skipped.
01233 
01234   }
01235 
01236   // End of reading poly/smesh file.
01237   fclose(polyfile);
01238 
01239   // Try to load a .var file if it exists.
01240   load_var(filename);
01241   // Try to load a .mtr file if it exists.
01242   load_mtr(filename);
01243   // Try to read a .pbc file if it exists.
01244   load_pbc(filename);
01245 
01246   return true;
01247 }
01248 
01250 //                                                                           //
01251 // load_off()    Load a polyhedron described in a .off file.                 //
01252 //                                                                           //
01253 // The .off format is one of file formats of the Geomview, an interactive    //
01254 // program for viewing and manipulating geometric objects.  More information //
01255 // is available form: http://www.geomview.org.                               //
01256 //                                                                           //
01257 // 'filename' is a input filename with extension .off or without extension ( //
01258 // the .off will be added in this case). On completion, the polyhedron is    //
01259 // returned in 'pointlist' and 'facetlist'.                                  //
01260 //                                                                           //
01262 
01263 bool tetgenio::load_off(char* filename)
01264 {
01265   FILE *fp;
01266   tetgenio::facet *f;
01267   tetgenio::polygon *p;
01268   char infilename[FILENAMESIZE];
01269   char buffer[INPUTLINESIZE];
01270   char *bufferp;
01271   double *coord;
01272   int nverts = 0, iverts = 0;
01273   int nfaces = 0, ifaces = 0;
01274   int nedges = 0;
01275   int line_count = 0, i;
01276 
01277   strncpy(infilename, filename, 1024 - 1);
01278   infilename[FILENAMESIZE - 1] = '\0';
01279   if (infilename[0] == '\0') {
01280     printf("Error:  No filename.\n");
01281     return false;
01282   }
01283   if (strcmp(&infilename[strlen(infilename) - 4], ".off") != 0) {
01284     strcat(infilename, ".off");
01285   }
01286 
01287   if (!(fp = fopen(infilename, "r"))) {
01288     printf("File I/O Error:  Unable to open file %s\n", infilename);
01289     return false;
01290   }
01291   printf("Opening %s.\n", infilename);
01292 
01293   // OFF requires the index starts from '0'.
01294   firstnumber = 0;
01295 
01296   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01297     // Check section
01298     if (nverts == 0) {
01299       // Read header
01300       bufferp = strstr(bufferp, "OFF");
01301       if (bufferp != NULL) {
01302         // Read mesh counts
01303         bufferp = findnextnumber(bufferp); // Skip field "OFF".
01304         if (*bufferp == '\0') {
01305           // Read a non-empty line.
01306           bufferp = readline(buffer, fp, &line_count);
01307         }
01308         if ((sscanf(bufferp, "%d%d%d", &nverts, &nfaces, &nedges) != 3)
01309             || (nverts == 0)) {
01310           printf("Syntax error reading header on line %d in file %s\n",
01311                  line_count, infilename);
01312           fclose(fp);
01313           return false;
01314         }
01315         // Allocate memory for 'tetgenio'
01316         if (nverts > 0) {
01317           numberofpoints = nverts;
01318           pointlist = new REAL[nverts * 3];
01319         }
01320         if (nfaces > 0) {
01321           numberoffacets = nfaces;
01322           facetlist = new tetgenio::facet[nfaces];
01323         }
01324       }
01325     } else if (iverts < nverts) {
01326       // Read vertex coordinates
01327       coord = &pointlist[iverts * 3];
01328       for (i = 0; i < 3; i++) {
01329         if (*bufferp == '\0') {
01330           printf("Syntax error reading vertex coords on line %d in file %s\n",
01331                  line_count, infilename);
01332           fclose(fp);
01333           return false;
01334         }
01335         coord[i] = (REAL) strtod(bufferp, &bufferp);
01336         bufferp = findnextnumber(bufferp);
01337       }
01338       iverts++;
01339     } else if (ifaces < nfaces) {
01340       // Get next face
01341       f = &facetlist[ifaces];
01342       init(f);
01343       // In .off format, each facet has one polygon, no hole.
01344       f->numberofpolygons = 1;
01345       f->polygonlist = new tetgenio::polygon[1];
01346       p = &f->polygonlist[0];
01347       init(p);
01348       // Read the number of vertices, it should be greater than 0.
01349       p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01350       if (p->numberofvertices == 0) {
01351         printf("Syntax error reading polygon on line %d in file %s\n",
01352                line_count, infilename);
01353         fclose(fp);
01354         return false;
01355       }
01356       // Allocate memory for face vertices
01357       p->vertexlist = new int[p->numberofvertices];
01358       for (i = 0; i < p->numberofvertices; i++) {
01359         bufferp = findnextnumber(bufferp);
01360         if (*bufferp == '\0') {
01361           printf("Syntax error reading polygon on line %d in file %s\n",
01362                  line_count, infilename);
01363           fclose(fp);
01364           return false;
01365         }
01366         p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01367       }
01368       ifaces++;
01369     } else {
01370       // Should never get here
01371       printf("Found extra text starting at line %d in file %s\n", line_count,
01372              infilename);
01373       break;
01374     }
01375   }
01376 
01377   // Close file
01378   fclose(fp);
01379 
01380   // Check whether read all points
01381   if (iverts != nverts) {
01382     printf("Expected %d vertices, but read only %d vertices in file %s\n",
01383            nverts, iverts, infilename);
01384     return false;
01385   }
01386 
01387   // Check whether read all faces
01388   if (ifaces != nfaces) {
01389     printf("Expected %d faces, but read only %d faces in file %s\n",
01390            nfaces, ifaces, infilename);
01391     return false;
01392   }
01393 
01394   return true;
01395 }
01396 
01398 //                                                                           //
01399 // load_ply()    Load a polyhedron described in a .ply file.                 //
01400 //                                                                           //
01401 // 'filename' is the file name with extension .ply or without extension (the //
01402 // .ply will be added in this case).                                         //
01403 //                                                                           //
01404 // This is a simplified version of reading .ply files, which only reads the  //
01405 // set of vertices and the set of faces. Other informations (such as color,  //
01406 // material, texture, etc) in .ply file are ignored. Complete routines for   //
01407 // reading and writing ,ply files are available from: http://www.cc.gatech.  //
01408 // edu/projects/large_models/ply.html.  Except the header section, ply file  //
01409 // format has exactly the same format for listing vertices and polygons as   //
01410 // off file format.                                                          //
01411 //                                                                           //
01412 // On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
01413 //                                                                           //
01415 
01416 bool tetgenio::load_ply(char* filename)
01417 {
01418   FILE *fp;
01419   tetgenio::facet *f;
01420   tetgenio::polygon *p;
01421   char infilename[FILENAMESIZE];
01422   char buffer[INPUTLINESIZE];
01423   char *bufferp, *str;
01424   double *coord;
01425   int endheader = 0, format = 0;
01426   int nverts = 0, iverts = 0;
01427   int nfaces = 0, ifaces = 0;
01428   int line_count = 0, i;
01429 
01430   strncpy(infilename, filename, FILENAMESIZE - 1);
01431   infilename[FILENAMESIZE - 1] = '\0';
01432   if (infilename[0] == '\0') {
01433     printf("Error:  No filename.\n");
01434     return false;
01435   }
01436   if (strcmp(&infilename[strlen(infilename) - 4], ".ply") != 0) {
01437     strcat(infilename, ".ply");
01438   }
01439 
01440   if (!(fp = fopen(infilename, "r"))) {
01441     printf("Error:  Unable to open file %s\n", infilename);
01442     return false;
01443   }
01444   printf("Opening %s.\n", infilename);
01445 
01446   // PLY requires the index starts from '0'.
01447   firstnumber = 0;
01448 
01449   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01450     if (!endheader) {
01451       // Find if it is the keyword "end_header".
01452       str = strstr(bufferp, "end_header");
01453       // strstr() is case sensitive.
01454       if (!str) str = strstr(bufferp, "End_header");
01455       if (!str) str = strstr(bufferp, "End_Header");
01456       if (str) {
01457         // This is the end of the header section.
01458         endheader = 1;
01459         continue;
01460       }
01461       // Parse the number of vertices and the number of faces.
01462       if (nverts == 0 || nfaces == 0) {
01463         // Find if it si the keyword "element".
01464         str = strstr(bufferp, "element");
01465         if (!str) str = strstr(bufferp, "Element");
01466         if (str) {
01467           bufferp = findnextfield(str);
01468           if (*bufferp == '\0') {
01469             printf("Syntax error reading element type on line%d in file %s\n",
01470                    line_count, infilename);
01471             fclose(fp);
01472             return false;
01473           }
01474           if (nverts == 0) {
01475             // Find if it is the keyword "vertex".
01476             str = strstr(bufferp, "vertex");
01477             if (!str) str = strstr(bufferp, "Vertex");
01478             if (str) {
01479               bufferp = findnextnumber(str);
01480               if (*bufferp == '\0') {
01481                 printf("Syntax error reading vertex number on line");
01482                 printf(" %d in file %s\n", line_count, infilename);
01483                 fclose(fp);
01484                 return false;
01485               }
01486               nverts = (int) strtol(bufferp, &bufferp, 0);
01487               // Allocate memory for 'tetgenio'
01488               if (nverts > 0) {
01489                 numberofpoints = nverts;
01490                 pointlist = new REAL[nverts * 3];
01491               }
01492             }
01493           }
01494           if (nfaces == 0) {
01495             // Find if it is the keyword "face".
01496             str = strstr(bufferp, "face");
01497             if (!str) str = strstr(bufferp, "Face");
01498             if (str) {
01499               bufferp = findnextnumber(str);
01500               if (*bufferp == '\0') {
01501                 printf("Syntax error reading face number on line");
01502                 printf(" %d in file %s\n", line_count, infilename);
01503                 fclose(fp);
01504                 return false;
01505               }
01506               nfaces = (int) strtol(bufferp, &bufferp, 0);
01507               // Allocate memory for 'tetgenio'
01508               if (nfaces > 0) {
01509                 numberoffacets = nfaces;
01510                 facetlist = new tetgenio::facet[nfaces];
01511               }
01512             }
01513           }
01514         } // It is not the string "element".
01515       }
01516       if (format == 0) {
01517         // Find the keyword "format".
01518         str = strstr(bufferp, "format");
01519         if (!str) str = strstr(bufferp, "Format");
01520         if (str) {
01521           format = 1;
01522           bufferp = findnextfield(str);
01523           // Find if it is the string "ascii".
01524           str = strstr(bufferp, "ascii");
01525           if (!str) str = strstr(bufferp, "ASCII");
01526           if (!str) {
01527             printf("This routine only reads ascii format of ply files.\n");
01528             printf("Hint: You can convert the binary to ascii format by\n");
01529             printf("  using the provided ply tools:\n");
01530             printf("  ply2ascii < %s > ascii_%s\n", infilename, infilename);
01531             fclose(fp);
01532             return false;
01533           }
01534         }
01535       }
01536     } else if (iverts < nverts) {
01537       // Read vertex coordinates
01538       coord = &pointlist[iverts * 3];
01539       for (i = 0; i < 3; i++) {
01540         if (*bufferp == '\0') {
01541           printf("Syntax error reading vertex coords on line %d in file %s\n",
01542                  line_count, infilename);
01543           fclose(fp);
01544           return false;
01545         }
01546         coord[i] = (REAL) strtod(bufferp, &bufferp);
01547         bufferp = findnextnumber(bufferp);
01548       }
01549       iverts++;
01550     } else if (ifaces < nfaces) {
01551       // Get next face
01552       f = &facetlist[ifaces];
01553       init(f);
01554       // In .off format, each facet has one polygon, no hole.
01555       f->numberofpolygons = 1;
01556       f->polygonlist = new tetgenio::polygon[1];
01557       p = &f->polygonlist[0];
01558       init(p);
01559       // Read the number of vertices, it should be greater than 0.
01560       p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01561       if (p->numberofvertices == 0) {
01562         printf("Syntax error reading polygon on line %d in file %s\n",
01563                line_count, infilename);
01564         fclose(fp);
01565         return false;
01566       }
01567       // Allocate memory for face vertices
01568       p->vertexlist = new int[p->numberofvertices];
01569       for (i = 0; i < p->numberofvertices; i++) {
01570         bufferp = findnextnumber(bufferp);
01571         if (*bufferp == '\0') {
01572           printf("Syntax error reading polygon on line %d in file %s\n",
01573                  line_count, infilename);
01574           fclose(fp);
01575           return false;
01576         }
01577         p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01578       }
01579       ifaces++;
01580     } else {
01581       // Should never get here
01582       printf("Found extra text starting at line %d in file %s\n", line_count,
01583              infilename);
01584       break;
01585     }
01586   }
01587 
01588   // Close file
01589   fclose(fp);
01590 
01591   // Check whether read all points
01592   if (iverts != nverts) {
01593     printf("Expected %d vertices, but read only %d vertices in file %s\n",
01594            nverts, iverts, infilename);
01595     return false;
01596   }
01597 
01598   // Check whether read all faces
01599   if (ifaces != nfaces) {
01600     printf("Expected %d faces, but read only %d faces in file %s\n",
01601            nfaces, ifaces, infilename);
01602     return false;
01603   }
01604 
01605   return true;
01606 }
01607 
01609 //                                                                           //
01610 // load_stl()    Load a surface mesh described in a .stl file.               //
01611 //                                                                           //
01612 // 'filename' is the file name with extension .stl or without extension (the //
01613 // .stl will be added in this case).                                         //
01614 //                                                                           //
01615 // The .stl or stereolithography format is an ASCII or binary file used in   //
01616 // manufacturing.  It is a list of the triangular surfaces that describe a   //
01617 // computer generated solid model. This is the standard input for most rapid //
01618 // prototyping machines.                                                     //
01619 //                                                                           //
01620 // On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
01621 // Note: After load_stl(), there exist many duplicated points in 'pointlist'.//
01622 // They will be unified during the Delaunay tetrahedralization process.      //
01623 //                                                                           //
01625 
01626 bool tetgenio::load_stl(char* filename)
01627 {
01628   FILE *fp;
01629   tetgenmesh::list *plist;
01630   tetgenio::facet *f;
01631   tetgenio::polygon *p;
01632   char infilename[FILENAMESIZE];
01633   char buffer[INPUTLINESIZE];
01634   char *bufferp, *str;
01635   double *coord;
01636   int solid = 0;
01637   int nverts = 0, iverts = 0;
01638   int nfaces = 0;
01639   int line_count = 0, i;
01640 
01641   strncpy(infilename, filename, FILENAMESIZE - 1);
01642   infilename[FILENAMESIZE - 1] = '\0';
01643   if (infilename[0] == '\0') {
01644     printf("Error:  No filename.\n");
01645     return false;
01646   }
01647   if (strcmp(&infilename[strlen(infilename) - 4], ".stl") != 0) {
01648     strcat(infilename, ".stl");
01649   }
01650 
01651   if (!(fp = fopen(infilename, "r"))) {
01652     printf("Error:  Unable to open file %s\n", infilename);
01653     return false;
01654   }
01655   printf("Opening %s.\n", infilename);
01656 
01657   // STL file has no number of points available. Use a list to read points.
01658   plist = new tetgenmesh::list(sizeof(double) * 3, NULL, 1024);
01659 
01660   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01661     // The ASCII .stl file must start with the lower case keyword solid and
01662     //   end with endsolid.
01663     if (solid == 0) {
01664       // Read header
01665       bufferp = strstr(bufferp, "solid");
01666       if (bufferp != NULL) {
01667         solid = 1;
01668       }
01669     } else {
01670       // We're inside the block of the solid.
01671       str = bufferp;
01672       // Is this the end of the solid.
01673       bufferp = strstr(bufferp, "endsolid");
01674       if (bufferp != NULL) {
01675         solid = 0;
01676       } else {
01677         // Read the XYZ coordinates if it is a vertex.
01678         bufferp = str;
01679         bufferp = strstr(bufferp, "vertex");
01680         if (bufferp != NULL) {
01681           coord = (double *) plist->append(NULL);
01682           for (i = 0; i < 3; i++) {
01683             bufferp = findnextnumber(bufferp);
01684             if (*bufferp == '\0') {
01685               printf("Syntax error reading vertex coords on line %d\n",
01686                    line_count);
01687               delete plist;
01688               fclose(fp);
01689               return false;
01690             }
01691             coord[i] = (REAL) strtod(bufferp, &bufferp);
01692           }
01693         }
01694       }
01695     }
01696   }
01697   fclose(fp);
01698 
01699   nverts = plist->len();
01700   // nverts should be an integer times 3 (every 3 vertices denote a face).
01701   if (nverts == 0 || (nverts % 3 != 0)) {
01702     printf("Error:  Wrong number of vertices in file %s.\n", infilename);
01703     delete plist;
01704     return false;
01705   }
01706   numberofpoints = nverts;
01707   pointlist = new REAL[nverts * 3];
01708   for (i = 0; i < nverts; i++) {
01709     coord = (double *) (* plist)[i];
01710     iverts = i * 3;
01711     pointlist[iverts] = (REAL) coord[0];
01712     pointlist[iverts + 1] = (REAL) coord[1];
01713     pointlist[iverts + 2] = (REAL) coord[2];
01714   }
01715 
01716   nfaces = (int) (nverts / 3);
01717   numberoffacets = nfaces;
01718   facetlist = new tetgenio::facet[nfaces];
01719 
01720   // Default use '1' as the array starting index.
01721   firstnumber = 1;
01722   iverts = firstnumber;
01723   for (i = 0; i < nfaces; i++) {
01724     f = &facetlist[i];
01725     init(f);
01726     // In .stl format, each facet has one polygon, no hole.
01727     f->numberofpolygons = 1;
01728     f->polygonlist = new tetgenio::polygon[1];
01729     p = &f->polygonlist[0];
01730     init(p);
01731     // Each polygon has three vertices.
01732     p->numberofvertices = 3;
01733     p->vertexlist = new int[p->numberofvertices];
01734     p->vertexlist[0] = iverts;
01735     p->vertexlist[1] = iverts + 1;
01736     p->vertexlist[2] = iverts + 2;
01737     iverts += 3;
01738   }
01739 
01740   delete plist;
01741   return true;
01742 }
01743 
01745 //                                                                           //
01746 // load_medit()    Load a surface mesh described in .mesh file.              //
01747 //                                                                           //
01748 // 'filename' is the file name with extension .mesh or without entension (   //
01749 // the .mesh will be added in this case). .mesh is the file format of Medit, //
01750 // a user-friendly interactive mesh viewing program.                         //
01751 //                                                                           //
01752 // This routine ONLY reads the sections containing vertices, triangles, and  //
01753 // quadrilaters. Other sections (such as tetrahedra, edges, ...) are ignored.//
01754 //                                                                           //
01756 
01757 bool tetgenio::load_medit(char* filename)
01758 {
01759   FILE *fp;
01760   tetgenio::facet *tmpflist, *f;
01761   tetgenio::polygon *p;
01762   char infilename[FILENAMESIZE];
01763   char buffer[INPUTLINESIZE];
01764   char *bufferp, *str;
01765   double *coord;
01766   int *tmpfmlist;
01767   int dimension = 0;
01768   int nverts = 0;
01769   int nfaces = 0;
01770   int line_count = 0;
01771   int corners = 0; // 3 (triangle) or 4 (quad).
01772   int i, j;
01773 
01774   strncpy(infilename, filename, FILENAMESIZE - 1);
01775   infilename[FILENAMESIZE - 1] = '\0';
01776   if (infilename[0] == '\0') {
01777     printf("Error:  No filename.\n");
01778     return false;
01779   }
01780   if (strcmp(&infilename[strlen(infilename) - 5], ".mesh") != 0) {
01781     strcat(infilename, ".mesh");
01782   }
01783 
01784   if (!(fp = fopen(infilename, "r"))) {
01785     printf("Error:  Unable to open file %s\n", infilename);
01786     return false;
01787   }
01788   printf("Opening %s.\n", infilename);
01789 
01790   // Default uses the index starts from '1'.
01791   firstnumber = 1;
01792 
01793   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01794     if (*bufferp == '#') continue;  // A comment line is skipped.
01795     if (dimension == 0) {
01796       // Find if it is the keyword "Dimension".
01797       str = strstr(bufferp, "Dimension");
01798       if (!str) str = strstr(bufferp, "dimension");
01799       if (!str) str = strstr(bufferp, "DIMENSION");
01800       if (str) {
01801         // Read the dimensions
01802         bufferp = findnextnumber(str); // Skip field "Dimension".
01803         if (*bufferp == '\0') {
01804           // Read a non-empty line.
01805           bufferp = readline(buffer, fp, &line_count);
01806         }
01807         dimension = (int) strtol(bufferp, &bufferp, 0);
01808         if (dimension != 2 && dimension != 3) {
01809           printf("Unknown dimension in file on line %d in file %s\n",
01810                  line_count, infilename);
01811           fclose(fp);
01812           return false;
01813         }
01814         mesh_dim = dimension;
01815       }
01816     }
01817     if (nverts == 0) {
01818       // Find if it is the keyword "Vertices".
01819       str = strstr(bufferp, "Vertices");
01820       if (!str) str = strstr(bufferp, "vertices");
01821       if (!str) str = strstr(bufferp, "VERTICES");
01822       if (str) {
01823         // Read the number of vertices.
01824         bufferp = findnextnumber(str); // Skip field "Vertices".
01825         if (*bufferp == '\0') {
01826           // Read a non-empty line.
01827           bufferp = readline(buffer, fp, &line_count);
01828         }
01829         nverts = (int) strtol(bufferp, &bufferp, 0);
01830         // Allocate memory for 'tetgenio'
01831         if (nverts > 0) {
01832           numberofpoints = nverts;
01833           pointlist = new REAL[nverts * 3];
01834         }
01835         // Read the follwoing node list.
01836         for (i = 0; i < nverts; i++) {
01837           bufferp = readline(buffer, fp, &line_count);
01838           if (bufferp == NULL) {
01839             printf("Unexpected end of file on line %d in file %s\n",
01840                    line_count, infilename);
01841             fclose(fp);
01842             return false;
01843           }
01844           // Read vertex coordinates
01845           coord = &pointlist[i * 3];
01846           for (j = 0; j < 3; j++) {
01847             if (*bufferp == '\0') {
01848               printf("Syntax error reading vertex coords on line");
01849               printf(" %d in file %s\n", line_count, infilename);
01850               fclose(fp);
01851               return false;
01852             }
01853             if ((j < 2) || (dimension == 3)) {
01854               coord[j] = (REAL) strtod(bufferp, &bufferp);
01855             } else {
01856               assert((j == 2) && (dimension == 2));
01857               coord[j] = 0.0;
01858             }
01859             bufferp = findnextnumber(bufferp);
01860           }
01861         }
01862         continue;
01863       }
01864     }
01865     if (nfaces == 0) {
01866       // Find if it is the keyword "Triangles" or "Quadrilaterals".
01867       corners = 0;
01868       str = strstr(bufferp, "Triangles");
01869       if (!str) str = strstr(bufferp, "triangles");
01870       if (!str) str = strstr(bufferp, "TRIANGLES");
01871       if (str) {
01872         corners = 3;
01873       } else {
01874         str = strstr(bufferp, "Quadrilaterals");
01875         if (!str) str = strstr(bufferp, "quadrilaterals");
01876         if (!str) str = strstr(bufferp, "QUADRILATERALS");
01877         if (str) {
01878           corners = 4;
01879         }
01880       }
01881       if (corners == 3 || corners == 4) {
01882         // Read the number of triangles (or quadrilaterals).
01883         bufferp = findnextnumber(str); // Skip field "Triangles".
01884         if (*bufferp == '\0') {
01885           // Read a non-empty line.
01886           bufferp = readline(buffer, fp, &line_count);
01887         }
01888         nfaces = strtol(bufferp, &bufferp, 0);
01889         // Allocate memory for 'tetgenio'
01890         if (nfaces > 0) {
01891           if (numberoffacets > 0) {
01892             // facetlist has already been allocated. Enlarge arrays.
01893             tmpflist = new tetgenio::facet[numberoffacets + nfaces];
01894             tmpfmlist = new int[numberoffacets + nfaces];
01895             // Copy the data of old arrays into new arrays.
01896             for (i = 0; i < numberoffacets; i++) {
01897               f = &(tmpflist[i]);
01898               tetgenio::init(f);
01899               *f = facetlist[i];
01900               tmpfmlist[i] = facetmarkerlist[i];
01901             }
01902             // Release old arrays.
01903             delete [] facetlist;
01904             delete [] facetmarkerlist;
01905             // Remember the new arrays.
01906             facetlist = tmpflist;
01907             facetmarkerlist = tmpfmlist;
01908           } else {
01909             // This is the first time to allocate facetlist.
01910             facetlist = new tetgenio::facet[nfaces];
01911             facetmarkerlist = new int[nfaces];
01912           }
01913         }
01914         // Read the following list of faces.
01915         for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
01916           bufferp = readline(buffer, fp, &line_count);
01917           if (bufferp == NULL) {
01918             printf("Unexpected end of file on line %d in file %s\n",
01919                    line_count, infilename);
01920             fclose(fp);
01921             return false;
01922           }
01923           f = &facetlist[i];
01924           tetgenio::init(f);
01925           // In .mesh format, each facet has one polygon, no hole.
01926           f->numberofpolygons = 1;
01927           f->polygonlist = new tetgenio::polygon[1];
01928           p = &f->polygonlist[0];
01929           tetgenio::init(p);
01930           p->numberofvertices = corners;
01931           // Allocate memory for face vertices
01932           p->vertexlist = new int[p->numberofvertices];
01933           // Read the vertices of the face.
01934           for (j = 0; j < corners; j++) {
01935             if (*bufferp == '\0') {
01936               printf("Syntax error reading face on line %d in file %s\n",
01937                      line_count, infilename);
01938               fclose(fp);
01939               return false;
01940             }
01941             p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0);
01942             if (firstnumber == 1) {
01943               // Check if a '0' index appears.
01944               if (p->vertexlist[j] == 0) {
01945                 // The first index is set to be 0.
01946                 firstnumber = 0;
01947               }
01948             }
01949             bufferp = findnextnumber(bufferp);
01950           }
01951           // Read the marker of the face if it exists.
01952           facetmarkerlist[i] = 0;
01953           if (*bufferp != '\0') {
01954             facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
01955           }
01956         }
01957         // Have read in a list of triangles/quads.
01958         numberoffacets += nfaces;
01959         nfaces = 0;
01960       }
01961     }
01962     // if (nverts > 0 && nfaces > 0) break; // Ignore other data.
01963   }
01964 
01965   // Close file
01966   fclose(fp);
01967 
01968   return true;
01969 }
01970 
01972 //                                                                           //
01973 // load_plc()    Load a piecewise linear complex from file.                  //
01974 //                                                                           //
01975 // This is main entrance for loading plcs from different file formats into   //
01976 // tetgenio.  'filename' is the input file name without extention. 'object'  //
01977 // indicates which file format is used to describ the plc.                   //
01978 //                                                                           //
01980 
01981 bool tetgenio::load_plc(char* filename, int object)
01982 {
01983   enum tetgenbehavior::objecttype type;
01984 
01985   type = (enum tetgenbehavior::objecttype) object;
01986   switch (type) {
01987   case tetgenbehavior::NODES:
01988     return load_node(filename);
01989   case tetgenbehavior::POLY:
01990     return load_poly(filename);
01991   case tetgenbehavior::OFF:
01992     return load_off(filename);
01993   case tetgenbehavior::PLY:
01994     return load_ply(filename);
01995   case tetgenbehavior::STL:
01996     return load_stl(filename);
01997   case tetgenbehavior::MEDIT:
01998     return load_medit(filename);
01999   default:
02000     return load_poly(filename);
02001   }
02002 }
02003 
02005 //                                                                           //
02006 // load_tetmesh()    Load a tetrahedral mesh from files.                     //
02007 //                                                                           //
02008 // 'filename' is the inputfile without suffix.  The nodes of the tetrahedral //
02009 // mesh is in "filename.node",  the elements is in "filename.ele", if the    //
02010 // "filename.face" and "filename.vol" exists, they will also be read.        //
02011 //                                                                           //
02013 
02014 bool tetgenio::load_tetmesh(char* filename)
02015 {
02016   FILE *infile;
02017   char innodefilename[FILENAMESIZE];
02018   char inelefilename[FILENAMESIZE];
02019   char infacefilename[FILENAMESIZE];
02020   char inedgefilename[FILENAMESIZE];
02021   char involfilename[FILENAMESIZE];
02022   char inputline[INPUTLINESIZE];
02023   char *stringptr, *infilename;
02024   REAL attrib, volume;
02025   int volelements;
02026   int markers, corner;
02027   int index, attribindex;
02028   int i, j;
02029 
02030   markers = 0;
02031 
02032   // Assembling the actual file names we want to open.
02033   strcpy(innodefilename, filename);
02034   strcpy(inelefilename, filename);
02035   strcpy(infacefilename, filename);
02036   strcpy(inedgefilename, filename);
02037   strcpy(involfilename, filename);
02038   strcat(innodefilename, ".node");
02039   strcat(inelefilename, ".ele");
02040   strcat(infacefilename, ".face");
02041   strcat(inedgefilename, ".edge");
02042   strcat(involfilename, ".vol");
02043 
02044   // Read the points from a .node file.
02045   infilename = innodefilename;
02046   printf("Opening %s.\n", infilename);
02047   infile = fopen(infilename, "r");
02048   if (infile == (FILE *) NULL) {
02049     printf("File I/O Error:  Cannot access file %s.\n", infilename);
02050     return false;
02051   }
02052   // Read the first line of the file.
02053   stringptr = readnumberline(inputline, infile, infilename);
02054   // Is this list of points generated from rbox?
02055   stringptr = strstr(inputline, "rbox");
02056   if (stringptr == NULL) {
02057     // Read number of points, number of dimensions, number of point
02058     //   attributes, and number of boundary markers.
02059     stringptr = inputline;
02060     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02061     stringptr = findnextnumber(stringptr);
02062     if (*stringptr == '\0') {
02063       mesh_dim = 3;
02064     } else {
02065       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02066     }
02067     stringptr = findnextnumber(stringptr);
02068     if (*stringptr == '\0') {
02069       numberofpointattributes = 0;
02070     } else {
02071       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
02072     }
02073     stringptr = findnextnumber(stringptr);
02074     if (*stringptr == '\0') {
02075       markers = 0;  // Default value.
02076     } else {
02077       markers = (int) strtol (stringptr, &stringptr, 0);
02078     }
02079   } else {
02080     // It is a rbox (qhull) input file.
02081     stringptr = inputline;
02082     // Get the dimension.
02083     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02084     // Get the number of points.
02085     stringptr = readnumberline(inputline, infile, infilename);
02086     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02087     // There is no index column.
02088     useindex = 0;
02089   }
02090 
02091   // Load the list of nodes.
02092   if (!load_node_call(infile, markers, infilename)) {
02093     fclose(infile);
02094     return false;
02095   }
02096   fclose(infile);
02097 
02098   // Read the elements from an .ele file.
02099   if (mesh_dim == 3) {
02100     infilename = inelefilename;
02101     infile = fopen(infilename, "r");
02102     if (infile != (FILE *) NULL) {
02103       printf("Opening %s.\n", infilename);
02104       // Read number of elements, number of corners (4 or 10), number of
02105       //   element attributes.
02106       stringptr = readnumberline(inputline, infile, infilename);
02107       numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0);
02108       stringptr = findnextnumber(stringptr);
02109       if (*stringptr == '\0') {
02110         numberofcorners = 4;  // Default read 4 nodes per element.
02111       } else {
02112         numberofcorners = (int) strtol(stringptr, &stringptr, 0);
02113       }
02114       stringptr = findnextnumber(stringptr);
02115       if (*stringptr == '\0') {
02116         numberoftetrahedronattributes = 0; // Default no attribute.
02117       } else {
02118         numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0);
02119       }
02120       if (numberofcorners != 4 && numberofcorners != 10) {
02121         printf("Error:  Wrong number of corners %d (should be 4 or 10).\n",
02122                numberofcorners);
02123         fclose(infile);
02124         return false;
02125       }
02126       // Allocate memory for tetrahedra.
02127       if (numberoftetrahedra > 0) {
02128         tetrahedronlist = new int[numberoftetrahedra * numberofcorners];
02129         if (tetrahedronlist == (int *) NULL) {
02130           printf("Error:  Out of memory.\n");
02131           terminatetetgen(1);
02132         }
02133         // Allocate memory for output tetrahedron attributes if necessary.
02134         if (numberoftetrahedronattributes > 0) {
02135           tetrahedronattributelist = new REAL[numberoftetrahedra *
02136                                           numberoftetrahedronattributes];
02137           if (tetrahedronattributelist == (REAL *) NULL) {
02138             printf("Error:  Out of memory.\n");
02139             terminatetetgen(1);
02140           }
02141         }
02142       }
02143       // Read the list of tetrahedra.
02144       index = 0;
02145       attribindex = 0;
02146       for (i = 0; i < numberoftetrahedra; i++) {
02147         // Read tetrahedron index and the tetrahedron's corners.
02148         stringptr = readnumberline(inputline, infile, infilename);
02149         for (j = 0; j < numberofcorners; j++) {
02150           stringptr = findnextnumber(stringptr);
02151           if (*stringptr == '\0') {
02152             printf("Error:  Tetrahedron %d is missing vertex %d in %s.\n",
02153                    i + firstnumber, j + 1, infilename);
02154             terminatetetgen(1);
02155           }
02156           corner = (int) strtol(stringptr, &stringptr, 0);
02157           if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02158             printf("Error:  Tetrahedron %d has an invalid vertex index.\n",
02159                    i + firstnumber);
02160             terminatetetgen(1);
02161           }
02162           tetrahedronlist[index++] = corner;
02163         }
02164         // Read the tetrahedron's attributes.
02165         for (j = 0; j < numberoftetrahedronattributes; j++) {
02166           stringptr = findnextnumber(stringptr);
02167           if (*stringptr == '\0') {
02168             attrib = 0.0;
02169           } else {
02170             attrib = (REAL) strtod(stringptr, &stringptr);
02171           }
02172           tetrahedronattributelist[attribindex++] = attrib;
02173         }
02174       }
02175       fclose(infile);
02176     }
02177   } // if (meshdim == 3)
02178 
02179   // Read the hullfaces or subfaces from a .face file if it exists.
02180   if (mesh_dim == 3) {
02181     infilename = infacefilename;
02182   } else {
02183     infilename = inelefilename;
02184   }
02185   infile = fopen(infilename, "r");
02186   if (infile != (FILE *) NULL) {
02187     printf("Opening %s.\n", infilename);
02188     // Read number of faces, boundary markers.
02189     stringptr = readnumberline(inputline, infile, infilename);
02190     numberoftrifaces = (int) strtol (stringptr, &stringptr, 0);
02191     stringptr = findnextnumber(stringptr);
02192     if (mesh_dim == 2) {
02193       // Skip a number.
02194       stringptr = findnextnumber(stringptr);
02195     }
02196     if (*stringptr == '\0') {
02197       markers = 0;  // Default there is no marker per face.
02198     } else {
02199       markers = (int) strtol (stringptr, &stringptr, 0);
02200     }
02201     if (numberoftrifaces > 0) {
02202       trifacelist = new int[numberoftrifaces * 3];
02203       if (trifacelist == (int *) NULL) {
02204         printf("Error:  Out of memory.\n");
02205         terminatetetgen(1);
02206       }
02207       if (markers) {
02208         trifacemarkerlist = new int[numberoftrifaces * 3];
02209         if (trifacemarkerlist == (int *) NULL) {
02210           printf("Error:  Out of memory.\n");
02211           terminatetetgen(1);
02212         }
02213       }
02214     }
02215     // Read the list of faces.
02216     index = 0;
02217     for (i = 0; i < numberoftrifaces; i++) {
02218       // Read face index and the face's three corners.
02219       stringptr = readnumberline(inputline, infile, infilename);
02220       for (j = 0; j < 3; j++) {
02221         stringptr = findnextnumber(stringptr);
02222         if (*stringptr == '\0') {
02223           printf("Error:  Face %d is missing vertex %d in %s.\n",
02224                  i + firstnumber, j + 1, infilename);
02225           terminatetetgen(1);
02226         }
02227         corner = (int) strtol(stringptr, &stringptr, 0);
02228         if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02229           printf("Error:  Face %d has an invalid vertex index.\n",
02230                  i + firstnumber);
02231           terminatetetgen(1);
02232         }
02233         trifacelist[index++] = corner;
02234       }
02235       // Read the boundary marker if it exists.
02236       if (markers) {
02237         stringptr = findnextnumber(stringptr);
02238         if (*stringptr == '\0') {
02239           attrib = 0.0;
02240         } else {
02241           attrib = (REAL) strtod(stringptr, &stringptr);
02242         }
02243         trifacemarkerlist[i] = (int) attrib;
02244       }
02245     }
02246     fclose(infile);
02247   }
02248 
02249   // Read the boundary edges from a .edge file if it exists.
02250   infilename = inedgefilename;
02251   infile = fopen(infilename, "r");
02252   if (infile != (FILE *) NULL) {
02253     printf("Opening %s.\n", infilename);
02254     // Read number of boundary edges.
02255     stringptr = readnumberline(inputline, infile, infilename);
02256     numberofedges = (int) strtol (stringptr, &stringptr, 0);
02257     if (numberofedges > 0) {
02258       edgelist = new int[numberofedges * 2];
02259       if (edgelist == (int *) NULL) {
02260         printf("Error:  Out of memory.\n");
02261         terminatetetgen(1);
02262       }
02263     }
02264     // Read the list of faces.
02265     index = 0;
02266     for (i = 0; i < numberofedges; i++) {
02267       // Read face index and the edge's two endpoints.
02268       stringptr = readnumberline(inputline, infile, infilename);
02269       for (j = 0; j < 2; j++) {
02270         stringptr = findnextnumber(stringptr);
02271         if (*stringptr == '\0') {
02272           printf("Error:  Edge %d is missing vertex %d in %s.\n",
02273                  i + firstnumber, j + 1, infilename);
02274           terminatetetgen(1);
02275         }
02276         corner = (int) strtol(stringptr, &stringptr, 0);
02277         if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02278           printf("Error:  Edge %d has an invalid vertex index.\n",
02279                  i + firstnumber);
02280           terminatetetgen(1);
02281         }
02282         edgelist[index++] = corner;
02283       }
02284     }
02285     fclose(infile);
02286   }
02287 
02288   // Read the volume constraints from a .vol file if it exists.
02289   infilename = involfilename;
02290   infile = fopen(infilename, "r");
02291   if (infile != (FILE *) NULL) {
02292     printf("Opening %s.\n", infilename);
02293     // Read number of tetrahedra.
02294     stringptr = readnumberline(inputline, infile, infilename);
02295     volelements = (int) strtol (stringptr, &stringptr, 0);
02296     if (volelements != numberoftetrahedra) {
02297       printf("Warning:  %s and %s disagree on number of tetrahedra.\n",
02298              inelefilename, involfilename);
02299       volelements = 0;
02300     }
02301     if (volelements > 0) {
02302       tetrahedronvolumelist = new REAL[volelements];
02303       if (tetrahedronvolumelist == (REAL *) NULL) {
02304         printf("Error:  Out of memory.\n");
02305         terminatetetgen(1);
02306       }
02307     }
02308     // Read the list of volume constraints.
02309     for (i = 0; i < volelements; i++) {
02310       stringptr = readnumberline(inputline, infile, infilename);
02311       stringptr = findnextnumber(stringptr);
02312       if (*stringptr == '\0') {
02313         volume = -1.0; // No constraint on this tetrahedron.
02314       } else {
02315         volume = (REAL) strtod(stringptr, &stringptr);
02316       }
02317       tetrahedronvolumelist[i] = volume;
02318     }
02319     fclose(infile);
02320   }
02321 
02322   // Try to load a .mtr file if it exists.
02323   load_mtr(filename);
02324   // Try to read a .pbc file if it exists.
02325   load_pbc(filename);
02326 
02327   return true;
02328 }
02329 
02331 //                                                                           //
02332 // load_voronoi()    Load a Voronoi diagram from files.                      //
02333 //                                                                           //
02334 // 'filename' is the inputfile without suffix.  The Voronoi diagram is read  //
02335 // from files: filename.v.node, filename.v.edge, and filename.v.face.        //
02336 //                                                                           //
02338 
02339 bool tetgenio::load_voronoi(char* filename)
02340 {
02341   FILE *infile;
02342   char innodefilename[FILENAMESIZE];
02343   char inedgefilename[FILENAMESIZE];
02344   char inputline[INPUTLINESIZE];
02345   char *stringptr, *infilename;
02346   voroedge *vedge;
02347   REAL x, y, z;
02348   int firstnode, corner;
02349   int index;
02350   int i, j;
02351 
02352   // Assembling the actual file names we want to open.
02353   strcpy(innodefilename, filename);
02354   strcpy(inedgefilename, filename);
02355   strcat(innodefilename, ".v.node");
02356   strcat(inedgefilename, ".v.edge");
02357 
02358   // Read the points from a .v.node file.
02359   infilename = innodefilename;
02360   printf("Opening %s.\n", infilename);
02361   infile = fopen(infilename, "r");
02362   if (infile == (FILE *) NULL) {
02363     printf("File I/O Error:  Cannot access file %s.\n", infilename);
02364     return false;
02365   }
02366   // Read the first line of the file.
02367   stringptr = readnumberline(inputline, infile, infilename);
02368   // Is this list of points generated from rbox?
02369   stringptr = strstr(inputline, "rbox");
02370   if (stringptr == NULL) {
02371     // Read number of points, number of dimensions, number of point
02372     //   attributes, and number of boundary markers.
02373     stringptr = inputline;
02374     numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02375     stringptr = findnextnumber(stringptr);
02376     if (*stringptr == '\0') {
02377       mesh_dim = 3;  // Default.
02378     } else {
02379       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02380     }
02381     useindex = 1;  // There is an index column.
02382   } else {
02383     // It is a rbox (qhull) input file.
02384     stringptr = inputline;
02385     // Get the dimension.
02386     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02387     // Get the number of points.
02388     stringptr = readnumberline(inputline, infile, infilename);
02389     numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02390     useindex = 0;  // No index column.
02391   }
02392   // Initialize 'vpointlist'.
02393   vpointlist = new REAL[numberofvpoints * 3];
02394   if (vpointlist == (REAL *) NULL) {
02395     printf("Error:  Out of memory.\n");
02396     terminatetetgen(1);
02397   }
02398   // Read the point section.
02399   index = 0;
02400   for (i = 0; i < numberofvpoints; i++) {
02401     stringptr = readnumberline(inputline, infile, infilename);
02402     if (useindex) {
02403       if (i == 0) {
02404         firstnode = (int) strtol (stringptr, &stringptr, 0);
02405         if ((firstnode == 0) || (firstnode == 1)) {
02406           firstnumber = firstnode;
02407         }
02408       }
02409       stringptr = findnextnumber(stringptr);
02410     } // if (useindex)
02411     if (*stringptr == '\0') {
02412       printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
02413       terminatetetgen(1);
02414     }
02415     x = (REAL) strtod(stringptr, &stringptr);
02416     stringptr = findnextnumber(stringptr);
02417     if (*stringptr == '\0') {
02418       printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
02419       terminatetetgen(1);
02420     }
02421     y = (REAL) strtod(stringptr, &stringptr);
02422     if (mesh_dim == 3) {
02423       stringptr = findnextnumber(stringptr);
02424       if (*stringptr == '\0') {
02425         printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
02426         terminatetetgen(1);
02427       }
02428       z = (REAL) strtod(stringptr, &stringptr);
02429     } else {
02430       z = 0.0; // mesh_dim == 2;
02431     }
02432     vpointlist[index++] = x;
02433     vpointlist[index++] = y;
02434     vpointlist[index++] = z;
02435   }
02436   fclose(infile);
02437 
02438   // Read the Voronoi edges from a .v.edge file if it exists.
02439   infilename = inedgefilename;
02440   infile = fopen(infilename, "r");
02441   if (infile != (FILE *) NULL) {
02442     printf("Opening %s.\n", infilename);
02443     // Read number of boundary edges.
02444     stringptr = readnumberline(inputline, infile, infilename);
02445     numberofvedges = (int) strtol (stringptr, &stringptr, 0);
02446     if (numberofvedges > 0) {
02447       vedgelist = new voroedge[numberofvedges];
02448     }
02449     // Read the list of faces.
02450     index = 0;
02451     for (i = 0; i < numberofvedges; i++) {
02452       // Read edge index and the edge's two endpoints.
02453       stringptr = readnumberline(inputline, infile, infilename);
02454       vedge = &(vedgelist[i]);
02455       for (j = 0; j < 2; j++) {
02456         stringptr = findnextnumber(stringptr);
02457         if (*stringptr == '\0') {
02458           printf("Error:  Edge %d is missing vertex %d in %s.\n",
02459                  i + firstnumber, j + 1, infilename);
02460           terminatetetgen(1);
02461         }
02462         corner = (int) strtol(stringptr, &stringptr, 0);
02463         j == 0 ? vedge->v1 = corner : vedge->v2 = corner;
02464       }
02465       if (vedge->v2 < 0) {
02466         for (j = 0; j < mesh_dim; j++) {
02467           stringptr = findnextnumber(stringptr);
02468           if (*stringptr == '\0') {
02469             printf("Error:  Edge %d is missing normal in %s.\n",
02470                    i + firstnumber, infilename);
02471             terminatetetgen(1);
02472           }
02473           vedge->vnormal[j] = (REAL) strtod(stringptr, &stringptr);
02474         }
02475         if (mesh_dim == 2) {
02476           vedge->vnormal[2] = 0.0;
02477         }
02478       } else {
02479         vedge->vnormal[0] = 0.0;
02480         vedge->vnormal[1] = 0.0;
02481         vedge->vnormal[2] = 0.0;
02482       }
02483     }
02484     fclose(infile);
02485   }
02486 
02487   return true;
02488 }
02489 
02491 //                                                                           //
02492 // save_nodes()    Save points to a .node file.                              //
02493 //                                                                           //
02494 // 'filename' is a string containing the file name without suffix.           //
02495 //                                                                           //
02497 
02498 void tetgenio::save_nodes(char* filename)
02499 {
02500   FILE *fout;
02501   char outnodefilename[FILENAMESIZE];
02502   char outmtrfilename[FILENAMESIZE];
02503   int i, j;
02504 
02505   sprintf(outnodefilename, "%s.node", filename);
02506   printf("Saving nodes to %s\n", outnodefilename);
02507   fout = fopen(outnodefilename, "w");
02508   fprintf(fout, "%d  %d  %d  %d\n", numberofpoints, mesh_dim,
02509           numberofpointattributes, pointmarkerlist != NULL ? 1 : 0);
02510   for (i = 0; i < numberofpoints; i++) {
02511     if (mesh_dim == 2) {
02512       fprintf(fout, "%d  %.16g  %.16g", i + firstnumber, pointlist[i * 2],
02513               pointlist[i * 2 + 1]);
02514     } else {
02515       fprintf(fout, "%d  %.16g  %.16g  %.16g", i + firstnumber,
02516               pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
02517     }
02518     for (j = 0; j < numberofpointattributes; j++) {
02519       fprintf(fout, "  %.16g",
02520               pointattributelist[i * numberofpointattributes + j]);
02521     }
02522     if (pointmarkerlist != NULL) {
02523       fprintf(fout, "  %d", pointmarkerlist[i]);
02524     }
02525     fprintf(fout, "\n");
02526   }
02527   fclose(fout);
02528 
02529   // If the point metrics exist, output them to a .mtr file.
02530   if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
02531     sprintf(outmtrfilename, "%s.mtr", filename);
02532     printf("Saving metrics to %s\n", outmtrfilename);
02533     fout = fopen(outmtrfilename, "w");
02534     fprintf(fout, "%d  %d\n", numberofpoints, numberofpointmtrs);
02535     for (i = 0; i < numberofpoints; i++) {
02536       for (j = 0; j < numberofpointmtrs; j++) {
02537         fprintf(fout, "%.16g ", pointmtrlist[i * numberofpointmtrs + j]);
02538       }
02539       fprintf(fout, "\n");
02540     }
02541     fclose(fout);
02542   }
02543 }
02544 
02546 //                                                                           //
02547 // save_elements()    Save elements to a .ele file.                          //
02548 //                                                                           //
02549 // 'filename' is a string containing the file name without suffix.           //
02550 //                                                                           //
02552 
02553 void tetgenio::save_elements(char* filename)
02554 {
02555   FILE *fout;
02556   char outelefilename[FILENAMESIZE];
02557   int i, j;
02558 
02559   sprintf(outelefilename, "%s.ele", filename);
02560   printf("Saving elements to %s\n", outelefilename);
02561   fout = fopen(outelefilename, "w");
02562   fprintf(fout, "%d  %d  %d\n", numberoftetrahedra, numberofcorners,
02563           numberoftetrahedronattributes);
02564   for (i = 0; i < numberoftetrahedra; i++) {
02565     fprintf(fout, "%d", i + firstnumber);
02566     for (j = 0; j < numberofcorners; j++) {
02567       fprintf(fout, "  %5d", tetrahedronlist[i * numberofcorners + j]);
02568     }
02569     for (j = 0; j < numberoftetrahedronattributes; j++) {
02570       fprintf(fout, "  %g",
02571         tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
02572     }
02573     fprintf(fout, "\n");
02574   }
02575 
02576   fclose(fout);
02577 }
02578 
02580 //                                                                           //
02581 // save_faces()    Save faces to a .face file.                               //
02582 //                                                                           //
02583 // 'filename' is a string containing the file name without suffix.           //
02584 //                                                                           //
02586 
02587 void tetgenio::save_faces(char* filename)
02588 {
02589   FILE *fout;
02590   char outfacefilename[FILENAMESIZE];
02591   int i;
02592 
02593   sprintf(outfacefilename, "%s.face", filename);
02594   printf("Saving faces to %s\n", outfacefilename);
02595   fout = fopen(outfacefilename, "w");
02596   fprintf(fout, "%d  %d\n", numberoftrifaces,
02597           trifacemarkerlist != NULL ? 1 : 0);
02598   for (i = 0; i < numberoftrifaces; i++) {
02599     fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber, trifacelist[i * 3],
02600             trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
02601     if (trifacemarkerlist != NULL) {
02602       fprintf(fout, "  %d", trifacemarkerlist[i]);
02603     }
02604     fprintf(fout, "\n");
02605   }
02606 
02607   fclose(fout);
02608 }
02609 
02611 //                                                                           //
02612 // save_edges()    Save egdes to a .edge file.                               //
02613 //                                                                           //
02614 // 'filename' is a string containing the file name without suffix.           //
02615 //                                                                           //
02617 
02618 void tetgenio::save_edges(char* filename)
02619 {
02620   FILE *fout;
02621   char outedgefilename[FILENAMESIZE];
02622   int i;
02623 
02624   sprintf(outedgefilename, "%s.edge", filename);
02625   printf("Saving edges to %s\n", outedgefilename);
02626   fout = fopen(outedgefilename, "w");
02627   fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02628   for (i = 0; i < numberofedges; i++) {
02629     fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
02630             edgelist[i * 2 + 1]);
02631     if (edgemarkerlist != NULL) {
02632       fprintf(fout, "  %d", edgemarkerlist[i]);
02633     }
02634     fprintf(fout, "\n");
02635   }
02636 
02637   fclose(fout);
02638 }
02639 
02641 //                                                                           //
02642 // save_neighbors()    Save egdes to a .neigh file.                          //
02643 //                                                                           //
02644 // 'filename' is a string containing the file name without suffix.           //
02645 //                                                                           //
02647 
02648 void tetgenio::save_neighbors(char* filename)
02649 {
02650   FILE *fout;
02651   char outneighborfilename[FILENAMESIZE];
02652   int i;
02653 
02654   sprintf(outneighborfilename, "%s.neigh", filename);
02655   printf("Saving neighbors to %s\n", outneighborfilename);
02656   fout = fopen(outneighborfilename, "w");
02657   fprintf(fout, "%d  %d\n", numberoftetrahedra, mesh_dim + 1);
02658   for (i = 0; i < numberoftetrahedra; i++) {
02659     if (mesh_dim == 2) {
02660       fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber,  neighborlist[i * 3],
02661               neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]);
02662     } else {
02663       fprintf(fout, "%d  %5d  %5d  %5d  %5d", i + firstnumber,
02664               neighborlist[i * 4], neighborlist[i * 4 + 1],
02665               neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]);
02666     }
02667     fprintf(fout, "\n");
02668   }
02669 
02670   fclose(fout);
02671 }
02672 
02674 //                                                                           //
02675 // save_poly()    Save segments or facets to a .poly file.                   //
02676 //                                                                           //
02677 // 'filename' is a string containing the file name without suffix.  It only  //
02678 // save the facets, holes and regions.  The nodes are saved in a .node file  //
02679 // by routine save_nodes().                                                  //
02680 //                                                                           //
02682 
02683 void tetgenio::save_poly(char* filename)
02684 {
02685   FILE *fout;
02686   facet *f;
02687   polygon *p;
02688   char outpolyfilename[FILENAMESIZE];
02689   int i, j, k;
02690 
02691   sprintf(outpolyfilename, "%s.poly", filename);
02692   printf("Saving poly to %s\n", outpolyfilename);
02693   fout = fopen(outpolyfilename, "w");
02694 
02695   // The zero indicates that the vertices are in a separate .node file.
02696   //   Followed by number of dimensions, number of vertex attributes,
02697   //   and number of boundary markers (zero or one).
02698   fprintf(fout, "%d  %d  %d  %d\n", 0, mesh_dim, numberofpointattributes,
02699           pointmarkerlist != NULL ? 1 : 0);
02700 
02701   // Save segments or facets.
02702   if (mesh_dim == 2) {
02703     // Number of segments, number of boundary markers (zero or one).
02704     fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02705     for (i = 0; i < numberofedges; i++) {
02706       fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
02707               edgelist[i * 2 + 1]);
02708       if (edgemarkerlist != NULL) {
02709         fprintf(fout, "  %d", edgemarkerlist[i]);
02710       }
02711       fprintf(fout, "\n");
02712     }
02713   } else {
02714     // Number of facets, number of boundary markers (zero or one).
02715     fprintf(fout, "%d  %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0);
02716     for (i = 0; i < numberoffacets; i++) {
02717       f = &(facetlist[i]);
02718       fprintf(fout, "%d  %d  %d  # %d\n", f->numberofpolygons,f->numberofholes,
02719             facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber);
02720       // Output polygons of this facet.
02721       for (j = 0; j < f->numberofpolygons; j++) {
02722         p = &(f->polygonlist[j]);
02723         fprintf(fout, "%d  ", p->numberofvertices);
02724         for (k = 0; k < p->numberofvertices; k++) {
02725           if (((k + 1) % 10) == 0) {
02726             fprintf(fout, "\n  ");
02727           }
02728           fprintf(fout, "  %d", p->vertexlist[k]);
02729         }
02730         fprintf(fout, "\n");
02731       }
02732       // Output holes of this facet.
02733       for (j = 0; j < f->numberofholes; j++) {
02734         fprintf(fout, "%d  %.12g  %.12g  %.12g\n", j + firstnumber,
02735            f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]);
02736       }
02737     }
02738   }
02739 
02740   // Save holes.
02741   fprintf(fout, "%d\n", numberofholes);
02742   for (i = 0; i < numberofholes; i++) {
02743     // Output x, y coordinates.
02744     fprintf(fout, "%d  %.12g  %.12g", i + firstnumber, holelist[i * mesh_dim],
02745             holelist[i * mesh_dim + 1]);
02746     if (mesh_dim == 3) {
02747       // Output z coordinate.
02748       fprintf(fout, "  %.12g", holelist[i * mesh_dim + 2]);
02749     }
02750     fprintf(fout, "\n");
02751   }
02752 
02753   // Save regions.
02754   fprintf(fout, "%d\n", numberofregions);
02755   for (i = 0; i < numberofregions; i++) {
02756     if (mesh_dim == 2) {
02757       // Output the index, x, y coordinates, attribute (region number)
02758       //   and maximum area constraint (maybe -1).
02759       fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
02760               regionlist[i * 4], regionlist[i * 4 + 1],
02761               regionlist[i * 4 + 2], regionlist[i * 4 + 3]);
02762     } else {
02763       // Output the index, x, y, z coordinates, attribute (region number)
02764       //   and maximum volume constraint (maybe -1).
02765       fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
02766               regionlist[i * 5], regionlist[i * 5 + 1],
02767               regionlist[i * 5 + 2], regionlist[i * 5 + 3],
02768               regionlist[i * 5 + 4]);
02769     }
02770   }
02771 
02772   fclose(fout);
02773 }
02774 
02776 //                                                                           //
02777 // readline()   Read a nonempty line from a file.                            //
02778 //                                                                           //
02779 // A line is considered "nonempty" if it contains something more than white  //
02780 // spaces.  If a line is considered empty, it will be dropped and the next   //
02781 // line will be read, this process ends until reaching the end-of-file or a  //
02782 // non-empty line.  Return NULL if it is the end-of-file, otherwise, return  //
02783 // a pointer to the first non-whitespace character of the line.              //
02784 //                                                                           //
02786 
02787 char* tetgenio::readline(char *string, FILE *infile, int *linenumber)
02788 {
02789   char *result;
02790 
02791   // Search for a non-empty line.
02792   do {
02793     result = fgets(string, INPUTLINESIZE - 1, infile);
02794     if (linenumber) (*linenumber)++;
02795     if (result == (char *) NULL) {
02796       return (char *) NULL;
02797     }
02798     // Skip white spaces.
02799     while ((*result == ' ') || (*result == '\t')) result++;
02800     // If it's end of line, read another line and try again.
02801   } while (*result == '\0');
02802   return result;
02803 }
02804 
02806 //                                                                           //
02807 // findnextfield()   Find the next field of a string.                        //
02808 //                                                                           //
02809 // Jumps past the current field by searching for whitespace or a comma, then //
02810 // jumps past the whitespace or the comma to find the next field.            //
02811 //                                                                           //
02813 
02814 char* tetgenio::findnextfield(char *string)
02815 {
02816   char *result;
02817 
02818   result = string;
02819   // Skip the current field.  Stop upon reaching whitespace or a comma.
02820   while ((*result != '\0') && (*result != ' ') &&  (*result != '\t') &&
02821          (*result != ',') && (*result != ';')) {
02822     result++;
02823   }
02824   // Now skip the whitespace or the comma, stop at anything else that looks
02825   //   like a character, or the end of a line.
02826   while ((*result == ' ') || (*result == '\t') || (*result == ',') ||
02827          (*result == ';')) {
02828     result++;
02829   }
02830   return result;
02831 }
02832 
02834 //                                                                           //
02835 // readnumberline()   Read a nonempty number line from a file.               //
02836 //                                                                           //
02837 // A line is considered "nonempty" if it contains something that looks like  //
02838 // a number.  Comments (prefaced by `#') are ignored.                        //
02839 //                                                                           //
02841 
02842 char* tetgenio::readnumberline(char *string, FILE *infile, char *infilename)
02843 {
02844   char *result;
02845 
02846   // Search for something that looks like a number.
02847   do {
02848     result = fgets(string, INPUTLINESIZE, infile);
02849     if (result == (char *) NULL) {
02850       if (infilename != (char *) NULL) {
02851         printf("  Error:  Unexpected end of file in %s.\n", infilename);
02852         terminatetetgen(1);
02853       }
02854       return result;
02855     }
02856     // Skip anything that doesn't look like a number, a comment,
02857     //   or the end of a line.
02858     while ((*result != '\0') && (*result != '#')
02859            && (*result != '.') && (*result != '+') && (*result != '-')
02860            && ((*result < '0') || (*result > '9'))) {
02861       result++;
02862     }
02863     // If it's a comment or end of line, read another line and try again.
02864   } while ((*result == '#') || (*result == '\0'));
02865   return result;
02866 }
02867 
02869 //                                                                           //
02870 // findnextnumber()   Find the next field of a number string.                //
02871 //                                                                           //
02872 // Jumps past the current field by searching for whitespace or a comma, then //
02873 // jumps past the whitespace or the comma to find the next field that looks  //
02874 // like a number.                                                            //
02875 //                                                                           //
02877 
02878 char* tetgenio::findnextnumber(char *string)
02879 {
02880   char *result;
02881 
02882   result = string;
02883   // Skip the current field.  Stop upon reaching whitespace or a comma.
02884   while ((*result != '\0') && (*result != '#') && (*result != ' ') &&
02885          (*result != '\t') && (*result != ',')) {
02886     result++;
02887   }
02888   // Now skip the whitespace and anything else that doesn't look like a
02889   //   number, a comment, or the end of a line.
02890   while ((*result != '\0') && (*result != '#')
02891          && (*result != '.') && (*result != '+') && (*result != '-')
02892          && ((*result < '0') || (*result > '9'))) {
02893     result++;
02894   }
02895   // Check for a comment (prefixed with `#').
02896   if (*result == '#') {
02897     *result = '\0';
02898   }
02899   return result;
02900 }
02901 
02902 //
02903 // End of class 'tetgenio' implementation
02904 //
02905 
02906 static REAL PI = 3.14159265358979323846264338327950288419716939937510582;
02907 
02908 //
02909 // Begin of class 'tetgenbehavior' implementation
02910 //
02911 
02913 //                                                                           //
02914 // tetgenbehavior()    Initialize veriables of 'tetgenbehavior'.             //
02915 //                                                                           //
02917 
02918 tetgenbehavior::tetgenbehavior()
02919 {
02920   // Initialize command line switches.
02921   plc = 0;
02922   quality = 0;
02923   refine = 0;
02924   coarse = 0;
02925   metric = 0;
02926   minratio = 2.0;
02927   goodratio = 0.0;
02928   minangle = 20.0;
02929   goodangle = 0.0;
02930   maxdihedral = 165.0;
02931   mindihedral = 5.0;
02932   varvolume = 0;
02933   fixedvolume = 0;
02934   maxvolume = -1.0;
02935   regionattrib = 0;
02936   insertaddpoints = 0;
02937   diagnose = 0;
02938   offcenter = 0;
02939   conformdel = 0;
02940   alpha1 = sqrt(2.0);
02941   alpha2 = 1.0;
02942   alpha3 = 0.6;
02943   zeroindex = 0;
02944   facesout = 0;
02945   edgesout = 0;
02946   neighout = 0;
02947   voroout = 0;
02948   meditview = 0;
02949   gidview = 0;
02950   geomview = 0;
02951   optlevel = 3;
02952   optpasses = 3;
02953   order = 1;
02954   nojettison = 0;
02955   nobound = 0;
02956   nonodewritten = 0;
02957   noelewritten = 0;
02958   nofacewritten = 0;
02959   noiterationnum = 0;
02960   nobisect = 0;
02961   noflip = 0;
02962   steiner = -1;
02963   fliprepair = 1;
02964   nomerge = 0;
02965   docheck = 0;
02966   quiet = 0;
02967   verbose = 0;
02968   useshelles = 0;
02969   epsilon = 1.0e-8;
02970   epsilon2 = 1.0e-5;
02971   object = NONE;
02972   // Initialize strings
02973   commandline[0] = '\0';
02974   infilename[0] = '\0';
02975   outfilename[0] = '\0';
02976   addinfilename[0] = '\0';
02977   bgmeshfilename[0] = '\0';
02978 }
02979 
02981 //                                                                           //
02982 // versioninfo()    Print the version information of TetGen.                 //
02983 //                                                                           //
02985 
02986 void tetgenbehavior::versioninfo()
02987 {
02988   printf("Version 1.4.2 (April 16, 2007).\n");
02989   printf("\n");
02990   printf("Copyright (C) 2002 - 2007\n");
02991   printf("Hang Si\n");
02992   printf("Mohrenstr. 39, 10117 Berlin, Germany\n");
02993   printf("si@wias-berlin.de\n");
02994 }
02995 
02997 //                                                                           //
02998 // syntax()    Print list of command line switches and exit the program.     //
02999 //                                                                           //
03001 
03002 void tetgenbehavior::syntax()
03003 {
03004   printf("  tetgen [-prq_Ra_AiMYS_T_dzo_fenvgGOJBNEFICQVh] input_file\n");
03005   printf("    -p  Tetrahedralizes a piecewise linear complex (PLC).\n");
03006   printf("    -r  Reconstructs a previously generated mesh.\n");
03007   printf("    -q  Quality mesh generation (adding new mesh points to ");
03008   printf("improve mesh quality).\n");
03009   printf("    -R  Mesh coarsening (deleting redundant mesh points).\n");
03010   printf("    -a  Applies a maximum tetrahedron volume constraint.\n");
03011   printf("    -A  Assigns attributes to identify tetrahedra in different ");
03012   printf("regions.\n");
03013   printf("    -i  Inserts a list of additional points into mesh.\n");
03014   printf("    -M  Does not merge coplanar facets.\n");
03015   printf("    -Y  Suppresses boundary facets/segments splitting.\n");
03016   printf("    -S  Specifies maximum number of added points.\n");
03017   printf("    -T  Sets a tolerance for coplanar test (default 1e-8).\n");
03018   printf("    -d  Detects self-intersections of facets of the PLC.\n");
03019   printf("    -z  Numbers all output items starting from zero.\n");
03020   printf("    -o2 Generates second-order subparametric elements.\n");
03021   printf("    -f  Outputs all faces to .face file.");
03022   printf("file.\n");
03023   printf("    -e  Outputs all edges to .edge file.\n");
03024   printf("    -n  Outputs tetrahedra neighbors to .neigh file.\n");
03025   printf("    -v  Outputs Voronoi diagram to files.\n");
03026   printf("    -g  Outputs mesh to .mesh file for viewing by Medit.\n");
03027   printf("    -G  Outputs mesh to .msh file for viewing by Gid.\n");
03028   printf("    -O  Outputs mesh to .off file for viewing by Geomview.\n");
03029   printf("    -J  No jettison of unused vertices from output .node file.\n");
03030   printf("    -B  Suppresses output of boundary information.\n");
03031   printf("    -N  Suppresses output of .node file.\n");
03032   printf("    -E  Suppresses output of .ele file.\n");
03033   printf("    -F  Suppresses output of .face file.\n");
03034   printf("    -I  Suppresses mesh iteration numbers.\n");
03035   printf("    -C  Checks the consistency of the final mesh.\n");
03036   printf("    -Q  Quiet:  No terminal output except errors.\n");
03037   printf("    -V  Verbose:  Detailed information, more terminal output.\n");
03038   printf("    -h  Help:  A brief instruction for using TetGen.\n");
03039 }
03040 
03042 //                                                                           //
03043 // usage()    Print a brief instruction for using TetGen.                    //
03044 //                                                                           //
03046 
03047 void tetgenbehavior::usage()
03048 {
03049   printf("TetGen\n");
03050   printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
03051   printf("Triangulator\n");
03052   versioninfo();
03053   printf("\n");
03054   printf("What Can TetGen Do?\n");
03055   printf("\n");
03056   printf("  TetGen generates exact Delaunay tetrahedralizations, exact\n");
03057   printf("  constrained Delaunay tetrahedralizations, and quality ");
03058   printf("tetrahedral\n  meshes. The latter are nicely graded and whose ");
03059   printf("tetrahedra have\n  radius-edge ratio bounded, thus are suitable ");
03060   printf("for finite element and\n  finite volume analysis.\n");
03061   printf("\n");
03062   printf("Command Line Syntax:\n");
03063   printf("\n");
03064   printf("  Below is the command line syntax of TetGen with a list of ");
03065   printf("short\n");
03066   printf("  descriptions. Underscores indicate that numbers may optionally\n");
03067   printf("  follow certain switches.  Do not leave any space between a ");
03068   printf("switch\n");
03069   printf("  and its numeric parameter.  \'input_file\' contains input data\n");
03070   printf("  depending on the switches you supplied which may be a ");
03071   printf("  piecewise\n");
03072   printf("  linear complex or a list of nodes.  File formats and detailed\n");
03073   printf("  description of command line switches are found in user's ");
03074   printf("manual.\n");
03075   printf("\n");
03076   syntax();
03077   printf("\n");
03078   printf("Examples of How to Use TetGen:\n");
03079   printf("\n");
03080   printf("  \'tetgen object\' reads vertices from object.node, and writes ");
03081   printf("their\n  Delaunay tetrahedralization to object.1.node and ");
03082   printf("object.1.ele.\n");
03083   printf("\n");
03084   printf("  \'tetgen -p object\' reads a PLC from object.poly or object.");
03085   printf("smesh (and\n  possibly object.node) and writes its constrained ");
03086   printf("Delaunay\n  tetrahedralization to object.1.node, object.1.ele and ");
03087   printf("object.1.face.\n");
03088   printf("\n");
03089   printf("  \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
03090   printf("  object.smesh (and possibly object.node), generates a mesh ");
03091   printf("whose\n  tetrahedra have radius-edge ratio smaller than 1.414 and ");
03092   printf("have volume\n  of 0.1 or less, and writes the mesh to ");
03093   printf("object.1.node, object.1.ele\n  and object.1.face.\n");
03094   printf("\n");
03095   printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
03096 }
03097 
03099 //                                                                           //
03100 // parse_commandline()    Read the command line, identify switches, and set  //
03101 //                        up options and file names.                         //
03102 //                                                                           //
03103 // 'argc' and 'argv' are the same parameters passed to the function main()   //
03104 // of a C/C++ program. They together represent the command line user invoked //
03105 // from an environment in which TetGen is running.                           //
03106 //                                                                           //
03107 // When TetGen is invoked from an environment. 'argc' is nonzero, switches   //
03108 // and input filename should be supplied as zero-terminated strings in       //
03109 // argv[0] through argv[argc - 1] and argv[0] shall be the name used to      //
03110 // invoke TetGen, i.e. "tetgen".  Switches are previously started with a     //
03111 // dash '-' to identify them from the input filename.                        //
03112 //                                                                           //
03113 // When TetGen is called from within another program. 'argc' is set to zero. //
03114 // switches are given in one zero-terminated string (no previous dash is     //
03115 // required.), and 'argv' is a pointer points to this string.  No input      //
03116 // filename is required (usually the input data has been directly created by //
03117 // user in the 'tetgenio' structure).  A default filename 'tetgen-tmpfile'   //
03118 // will be created for debugging output purpose.                             //
03119 //                                                                           //
03121 
03122 bool tetgenbehavior::parse_commandline(int argc, char **argv)
03123 {
03124   int startindex;
03125   int increment;
03126   int meshnumber;
03127   int scount;
03128   int i, j, k;
03129   char workstring[1024];
03130 
03131   // First determine the input style of the switches.
03132   if (argc == 0) {
03133     startindex = 0;                    // Switches are given without a dash.
03134     argc = 1;                    // For running the following for-loop once.
03135     commandline[0] = '\0';
03136   } else {
03137     startindex = 1;
03138     strcpy(commandline, argv[0]);
03139     strcat(commandline, " ");
03140   }
03141 
03142   // Rcount used to count the number of '-R' be used.
03143   scount = 0;
03144 
03145   for (i = startindex; i < argc; i++) {
03146     // Remember the command line switches.
03147     strcat(commandline, argv[i]);
03148     strcat(commandline, " ");
03149     if (startindex == 1) {
03150       // Is this string a filename?
03151       if (argv[i][0] != '-') {
03152         strncpy(infilename, argv[i], 1024 - 1);
03153         infilename[1024 - 1] = '\0';
03154         // Go to the next string directly.
03155         continue;
03156       }
03157     }
03158     // Parse the individual switch from the string.
03159     for (j = startindex; argv[i][j] != '\0'; j++) {
03160       if (argv[i][j] == 'p') {
03161         plc = 1;
03162       } else if (argv[i][j] == 'r') {
03163         refine = 1;
03164       } else if (argv[i][j] == 'R') {
03165         coarse = 1;
03166       } else if (argv[i][j] == 'q') {
03167         quality++;
03168         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03169             (argv[i][j + 1] == '.')) {
03170           k = 0;
03171           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03172                  (argv[i][j + 1] == '.')) {
03173             j++;
03174             workstring[k] = argv[i][j];
03175             k++;
03176           }
03177           workstring[k] = '\0';
03178           if (quality == 1) {
03179             minratio = (REAL) strtod(workstring, (char **) NULL);
03180           } else if (quality == 2) {
03181             mindihedral = (REAL) strtod(workstring, (char **) NULL);
03182           } else if (quality == 3) {
03183             maxdihedral = (REAL) strtod(workstring, (char **) NULL);
03184           } else if (quality == 4) {
03185             alpha2 = (REAL) strtod(workstring, (char **) NULL);
03186           } else if (quality == 5) {
03187             alpha1 = (REAL) strtod(workstring, (char **) NULL);
03188           }
03189         }
03190       } else if (argv[i][j] == 'm') {
03191         metric++;
03192         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03193             (argv[i][j + 1] == '.')) {
03194           k = 0;
03195           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03196                  (argv[i][j + 1] == '.')) {
03197             j++;
03198             workstring[k] = argv[i][j];
03199             k++;
03200           }
03201           workstring[k] = '\0';
03202           if (metric == 1) {
03203             alpha1 = (REAL) strtod(workstring, (char **) NULL);
03204           } else if (metric == 2) {
03205             alpha2 = (REAL) strtod(workstring, (char **) NULL);
03206           }
03207         }
03208       } else if (argv[i][j] == 'a') {
03209         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03210             (argv[i][j + 1] == '.')) {
03211           fixedvolume = 1;
03212           k = 0;
03213           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03214                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03215                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03216             j++;
03217             workstring[k] = argv[i][j];
03218             k++;
03219           }
03220           workstring[k] = '\0';
03221           maxvolume = (REAL) strtod(workstring, (char **) NULL);
03222         } else {
03223           varvolume = 1;
03224         }
03225       } else if (argv[i][j] == 'A') {
03226         regionattrib++;
03227       } else if (argv[i][j] == 'i') {
03228         insertaddpoints = 1;
03229       } else if (argv[i][j] == 'd') {
03230         diagnose = 1;
03231       } else if (argv[i][j] == 'z') {
03232         zeroindex = 1;
03233       } else if (argv[i][j] == 'f') {
03234         facesout = 1;
03235       } else if (argv[i][j] == 'e') {
03236         edgesout++;
03237       } else if (argv[i][j] == 'n') {
03238         neighout++;
03239       } else if (argv[i][j] == 'v') {
03240         voroout = 1;
03241       } else if (argv[i][j] == 'g') {
03242         meditview = 1;
03243       } else if (argv[i][j] == 'G') {
03244         gidview = 1;
03245       } else if (argv[i][j] == 'O') {
03246         geomview = 1;
03247       } else if (argv[i][j] == 'M') {
03248         nomerge = 1;
03249       } else if (argv[i][j] == 'Y') {
03250         nobisect++;
03251       } else if (argv[i][j] == 'J') {
03252         nojettison = 1;
03253       } else if (argv[i][j] == 'B') {
03254         nobound = 1;
03255       } else if (argv[i][j] == 'N') {
03256         nonodewritten = 1;
03257       } else if (argv[i][j] == 'E') {
03258         noelewritten = 1;
03259       } else if (argv[i][j] == 'F') {
03260         nofacewritten = 1;
03261       } else if (argv[i][j] == 'I') {
03262         noiterationnum = 1;
03263       } else if (argv[i][j] == 'o') {
03264         if (argv[i][j + 1] == '2') {
03265           j++;
03266           order = 2;
03267         }
03268       } else if (argv[i][j] == 'S') {
03269         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03270             (argv[i][j + 1] == '.')) {
03271           k = 0;
03272           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03273                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03274                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03275             j++;
03276             workstring[k] = argv[i][j];
03277             k++;
03278           }
03279           workstring[k] = '\0';
03280           steiner = (int) strtol(workstring, (char **) NULL, 0);
03281         }
03282       } else if (argv[i][j] == 's') {
03283         scount++;
03284         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03285             (argv[i][j + 1] == '.')) {
03286           k = 0;
03287           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03288                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03289                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03290             j++;
03291             workstring[k] = argv[i][j];
03292             k++;
03293           }
03294           workstring[k] = '\0';
03295           if (scount == 1) {
03296             optlevel = (int) strtol(workstring, (char **) NULL, 0);
03297           } else if (scount == 2) {
03298             optpasses = (int) strtol(workstring, (char **) NULL, 0);
03299           }
03300         }
03301       } else if (argv[i][j] == 'D') {
03302         conformdel++;
03303       } else if (argv[i][j] == 'T') {
03304         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03305             (argv[i][j + 1] == '.')) {
03306           k = 0;
03307           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03308                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03309                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03310             j++;
03311             workstring[k] = argv[i][j];
03312             k++;
03313           }
03314           workstring[k] = '\0';
03315           epsilon = (REAL) strtod(workstring, (char **) NULL);
03316         }
03317       } else if (argv[i][j] == 'C') {
03318         docheck++;
03319       } else if (argv[i][j] == 'X') {
03320         fliprepair = 0;
03321       } else if (argv[i][j] == 'Q') {
03322         quiet = 1;
03323       } else if (argv[i][j] == 'V') {
03324         verbose++;
03325       // } else if (argv[i][j] == 'v') {
03326         // versioninfo();
03327         // terminatetetgen(0);
03328       } else if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
03329                  (argv[i][j] == '?')) {
03330         usage();
03331         terminatetetgen(0);
03332       } else {
03333         printf("Warning:  Unknown switch -%c.\n", argv[i][j]);
03334       }
03335     }
03336   }
03337 
03338   if (startindex == 0) {
03339     // Set a temporary filename for debugging output.
03340     strcpy(infilename, "tetgen-tmpfile");
03341   } else {
03342     if (infilename[0] == '\0') {
03343       // No input file name. Print the syntax and exit.
03344       syntax();
03345       terminatetetgen(0);
03346     }
03347     // Recognize the object from file extension if it is available.
03348     if (!strcmp(&infilename[strlen(infilename) - 5], ".node")) {
03349       infilename[strlen(infilename) - 5] = '\0';
03350       object = NODES;
03351     } else if (!strcmp(&infilename[strlen(infilename) - 5], ".poly")) {
03352       infilename[strlen(infilename) - 5] = '\0';
03353       object = POLY;
03354       plc = 1;
03355     } else if (!strcmp(&infilename[strlen(infilename) - 6], ".smesh")) {
03356       infilename[strlen(infilename) - 6] = '\0';
03357       object = POLY;
03358       plc = 1;
03359     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".off")) {
03360       infilename[strlen(infilename) - 4] = '\0';
03361       object = OFF;
03362       plc = 1;
03363     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ply")) {
03364       infilename[strlen(infilename) - 4] = '\0';
03365       object = PLY;
03366       plc = 1;
03367     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".stl")) {
03368       infilename[strlen(infilename) - 4] = '\0';
03369       object = STL;
03370       plc = 1;
03371     } else if (!strcmp(&infilename[strlen(infilename) - 5], ".mesh")) {
03372       infilename[strlen(infilename) - 5] = '\0';
03373       object = MEDIT;
03374       plc = 1;
03375     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ele")) {
03376       infilename[strlen(infilename) - 4] = '\0';
03377       object = MESH;
03378       refine = 1;
03379     }
03380   }
03381   plc = plc || diagnose;
03382   useshelles = plc || refine || coarse || quality;
03383   goodratio = minratio;
03384   goodratio *= goodratio;
03385 
03386   // Detect improper combinations of switches.
03387   if (plc && refine) {
03388     printf("Error:  Switch -r cannot use together with -p.\n");
03389     return false;
03390   }
03391   if (refine && (plc || noiterationnum)) {
03392     printf("Error:  Switches %s cannot use together with -r.\n",
03393            "-p, -d, and -I");
03394     return false;
03395   }
03396   if (diagnose && (quality || insertaddpoints || (order == 2) || neighout
03397       || docheck)) {
03398     printf("Error:  Switches %s cannot use together with -d.\n",
03399            "-q, -i, -o2, -n, and -C");
03400     return false;
03401   }
03402 
03403   // Be careful not to allocate space for element area constraints that
03404   //   will never be assigned any value (other than the default -1.0).
03405   if (!refine && !plc) {
03406     varvolume = 0;
03407   }
03408   // Be careful not to add an extra attribute to each element unless the
03409   //   input supports it (PLC in, but not refining a preexisting mesh).
03410   if (refine || !plc) {
03411     regionattrib = 0;
03412   }
03413   // If '-a' or '-aa' is in use, enable '-q' option too.
03414   if (fixedvolume || varvolume) {
03415     if (quality == 0) {
03416       quality = 1;
03417     }
03418   }
03419   // Calculate the goodangle for testing bad subfaces.
03420   goodangle = cos(minangle * PI / 180.0);
03421   goodangle *= goodangle;
03422 
03423   increment = 0;
03424   strcpy(workstring, infilename);
03425   j = 1;
03426   while (workstring[j] != '\0') {
03427     if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
03428       increment = j + 1;
03429     }
03430     j++;
03431   }
03432   meshnumber = 0;
03433   if (increment > 0) {
03434     j = increment;
03435     do {
03436       if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
03437         meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
03438       } else {
03439         increment = 0;
03440       }
03441       j++;
03442     } while (workstring[j] != '\0');
03443   }
03444   if (noiterationnum) {
03445     strcpy(outfilename, infilename);
03446   } else if (increment == 0) {
03447     strcpy(outfilename, infilename);
03448     strcat(outfilename, ".1");
03449   } else {
03450     workstring[increment] = '%';
03451     workstring[increment + 1] = 'd';
03452     workstring[increment + 2] = '\0';
03453     sprintf(outfilename, workstring, meshnumber + 1);
03454   }
03455   // Additional input file name has the end ".a".
03456   strcpy(addinfilename, infilename);
03457   strcat(addinfilename, ".a");
03458   // Background filename has the form "*.b.ele", "*.b.node", ...
03459   strcpy(bgmeshfilename, infilename);
03460   strcat(bgmeshfilename, ".b");
03461 
03462   return true;
03463 }
03464 
03465 //
03466 // End of class 'tetgenbehavior' implementation
03467 //
03468 
03469 //
03470 // Begin of class 'tetgenmesh' implementation
03471 //
03472 
03473 //
03474 // Begin of class 'list', 'memorypool' and 'link' implementation
03475 //
03476 
03477 // Following are predefined compare functions for primitive data types.
03478 //   These functions take two pointers of the corresponding date type,
03479 //   perform the comparation. Return -1, 0 or 1 indicating the default
03480 //   linear order of two operators.
03481 
03482 // Compare two 'integers'.
03483 int tetgenmesh::compare_2_ints(const void* x, const void* y) {
03484   if (* (int *) x < * (int *) y) {
03485     return -1;
03486   } else if (* (int *) x > * (int *) y) {
03487     return 1;
03488   } else {
03489     return 0;
03490   }
03491 }
03492 
03493 // Compare two 'longs'.  Note: in 64-bit machine the 'long' type is 64-bit
03494 //   (8-byte) where the 'int' only 32-bit (4-byte).
03495 int tetgenmesh::compare_2_longs(const void* x, const void* y) {
03496   if (* (long *) x < * (long *) y) {
03497     return -1;
03498   } else if (* (long *) x > * (long *) y) {
03499     return 1;
03500   } else {
03501     return 0;
03502   }
03503 }
03504 
03505 // Compare two 'unsigned longs'.
03506 int tetgenmesh::compare_2_unsignedlongs(const void* x, const void* y) {
03507   if (* (unsigned long *) x < * (unsigned long *) y) {
03508     return -1;
03509   } else if (* (unsigned long *) x > * (unsigned long *) y) {
03510     return 1;
03511   } else {
03512     return 0;
03513   }
03514 }
03515 
03517 //                                                                           //
03518 // set_compfunc()    Determine the size of primitive data types and set the  //
03519 //                   corresponding predefined linear order functions.        //
03520 //                                                                           //
03521 // 'str' is a zero-end string indicating a primitive data type, like 'int',  //
03522 // 'long' or 'unsigned long'.  Every string ending with a '*' is though as a //
03523 // type of pointer and the type 'unsign long' is used for it.                //
03524 //                                                                           //
03525 // When the type of 'str' is determined, the size of this type (in byte) is  //
03526 // returned in 'itbytes', and the pointer of corresponding predefined linear //
03527 // order functions is returned in 'pcomp'.                                   //
03528 //                                                                           //
03530 
03531 void tetgenmesh::set_compfunc(char* str, int* itbytes, compfunc* pcomp)
03532 {
03533   // First figure out whether it is a pointer or not.
03534   if (str[strlen(str) - 1] == '*') {
03535     *itbytes = sizeof(unsigned long);
03536     *pcomp = &compare_2_unsignedlongs;
03537     return;
03538   }
03539   // Then determine other types.
03540   if (strcmp(str, "int") == 0) {
03541     *itbytes = sizeof(int);
03542     *pcomp = &compare_2_ints;
03543   } else if (strcmp(str, "long") == 0) {
03544     *itbytes = sizeof(long);
03545     *pcomp = &compare_2_longs;
03546   } else if (strcmp(str, "unsigned long") == 0) {
03547     *itbytes = sizeof(unsigned long);
03548     *pcomp = &compare_2_unsignedlongs;
03549   } else {
03550     // It is an unknown type.
03551     printf("Error in set_compfunc():  unknown type %s.\n", str);
03552     terminatetetgen(1);
03553   }
03554 }
03555 
03557 //                                                                           //
03558 // listinit()    Initialize a list for storing a data type.                  //
03559 //                                                                           //
03560 // Determine the size of each item, set the maximum size allocated at onece, //
03561 // set the expand size in case the list is full, and set the linear order    //
03562 // function if it is provided (default is NULL).                             //
03563 //                                                                           //
03565 
03566 void tetgenmesh::list::
03567 listinit(int itbytes, compfunc pcomp, int mitems,int exsize)
03568 {
03569 #ifdef SELF_CHECK
03570   assert(itbytes > 0 && mitems > 0 && exsize > 0);
03571 #endif
03572   itembytes = itbytes;
03573   comp = pcomp;
03574   maxitems = mitems;
03575   expandsize = exsize;
03576   base = (char *) malloc(maxitems * itembytes);
03577   if (base == (char *) NULL) {
03578     printf("Error:  Out of memory.\n");
03579     terminatetetgen(1);
03580   }
03581   items = 0;
03582 }
03583 
03585 //                                                                           //
03586 // append()    Add a new item at the end of the list.                        //
03587 //                                                                           //
03588 // A new space at the end of this list will be allocated for storing the new //
03589 // item. If the memory is not sufficient, reallocation will be performed. If //
03590 // 'appitem' is not NULL, the contents of this pointer will be copied to the //
03591 // new allocated space.  Returns the pointer to the new allocated space.     //
03592 //                                                                           //
03594 
03595 void* tetgenmesh::list::append(void *appitem)
03596 {
03597   // Do we have enough space?
03598   if (items == maxitems) {
03599     char* newbase = (char *) realloc(base, (maxitems + expandsize) *
03600                                      itembytes);
03601     if (newbase == (char *) NULL) {
03602       printf("Error:  Out of memory.\n");
03603       terminatetetgen(1);
03604     }
03605     base = newbase;
03606     maxitems += expandsize;
03607   }
03608   if (appitem != (void *) NULL) {
03609     memcpy(base + items * itembytes, appitem, itembytes);
03610   }
03611   items++;
03612   return (void *) (base + (items - 1) * itembytes);
03613 }
03614 
03616 //                                                                           //
03617 // insert()    Insert an item before 'pos' (range from 0 to items - 1).      //
03618 //                                                                           //
03619 // A new space will be inserted at the position 'pos', that is, items lie    //
03620 // after pos (including the item at pos) will be moved one space downwords.  //
03621 // If 'insitem' is not NULL, its contents will be copied into the new        //
03622 // inserted space. Return a pointer to the new inserted space.               //
03623 //                                                                           //
03625 
03626 void* tetgenmesh::list::insert(int pos, void* insitem)
03627 {
03628   if (pos >= items) {
03629     return append(insitem);
03630   }
03631   // Do we have enough space.
03632   if (items == maxitems) {
03633     char* newbase = (char *) realloc(base, (maxitems + expandsize) *
03634                                      itembytes);
03635     if (newbase == (char *) NULL) {
03636       printf("Error:  Out of memory.\n");
03637       terminatetetgen(1);
03638     }
03639     base = newbase;
03640     maxitems += expandsize;
03641   }
03642   // Do block move.
03643   memmove(base + (pos + 1) * itembytes,   // dest
03644           base + pos * itembytes,         // src
03645           (items - pos) * itembytes);     // size in bytes
03646   // Insert the item.
03647   if (insitem != (void *) NULL) {
03648     memcpy(base + pos * itembytes, insitem, itembytes);
03649   }
03650   items++;
03651   return (void *) (base + pos * itembytes);
03652 }
03653 
03655 //                                                                           //
03656 // del()    Delete an item at 'pos' (range from 0 to items - 1).             //
03657 //                                                                           //
03658 // The space at 'pos' will be overlapped by other item. If 'order' is 1, the //
03659 // remaining items of the list have the same order as usual, i.e., items lie //
03660 // after pos will be moved one space upwords. If 'order' is 0, the last item //
03661 // of the list will be moved up to pos.                                      //
03662 //                                                                           //
03664 
03665 void tetgenmesh::list::del(int pos, int order)
03666 {
03667   // If 'pos' is the last item of the list, nothing need to do.
03668   if (pos >= 0 && pos < items - 1) {
03669     if (order == 1) {
03670       // Do block move.
03671       memmove(base + pos * itembytes,       // dest
03672               base + (pos + 1) * itembytes, // src
03673               (items - pos - 1) * itembytes);
03674     } else {
03675       // Use the last item to overlap the del item.
03676       memcpy(base + pos * itembytes, // item at pos
03677              base + (items - 1) * itembytes, // item at last
03678              itembytes);
03679     }
03680   }
03681   if (items > 0) {
03682     items--;
03683   }
03684 }
03685 
03687 //                                                                           //
03688 // hasitem()    Search in this list to find if 'checkitem' exists.           //
03689 //                                                                           //
03690 // This routine assumes that a linear order function has been set.  It loops //
03691 // through the entire list, compares each item to 'checkitem'. If it exists, //
03692 // return its position (between 0 to items - 1), otherwise, return -1.       //
03693 //                                                                           //
03695 
03696 int tetgenmesh::list::hasitem(void* checkitem)
03697 {
03698   int i;
03699 
03700   for (i = 0; i < items; i++) {
03701     if (comp != (compfunc) NULL) {
03702       if ((* comp)((void *)(base + i * itembytes), checkitem) == 0) {
03703         return i;
03704       }
03705     }
03706   }
03707   return -1;
03708 }
03709 
03711 //                                                                           //
03712 // sort()    Sort the items with respect to a linear order function.         //
03713 //                                                                           //
03714 // Uses QuickSort routines (qsort) of the standard C/C++ library (stdlib.h). //
03715 //                                                                           //
03717 
03718 void tetgenmesh::list::sort()
03719 {
03720   qsort((void *) base, (size_t) items, (size_t) itembytes, comp);
03721 }
03722 
03724 //                                                                           //
03725 // memorypool()   The constructors of memorypool.                            //
03726 //                                                                           //
03728 
03729 tetgenmesh::memorypool::memorypool()
03730 {
03731   firstblock = nowblock = (void **) NULL;
03732   nextitem = (void *) NULL;
03733   deaditemstack = (void *) NULL;
03734   pathblock = (void **) NULL;
03735   pathitem = (void *) NULL;
03736   itemwordtype = POINTER;
03737   alignbytes = 0;
03738   itembytes = itemwords = 0;
03739   itemsperblock = 0;
03740   items = maxitems = 0l;
03741   unallocateditems = 0;
03742   pathitemsleft = 0;
03743 }
03744 
03745 tetgenmesh::memorypool::
03746 memorypool(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03747 {
03748   poolinit(bytecount, itemcount, wtype, alignment);
03749 }
03750 
03752 //                                                                           //
03753 // ~memorypool()   Free to the operating system all memory taken by a pool.  //
03754 //                                                                           //
03756 
03757 tetgenmesh::memorypool::~memorypool()
03758 {
03759   while (firstblock != (void **) NULL) {
03760     nowblock = (void **) *(firstblock);
03761     free(firstblock);
03762     firstblock = nowblock;
03763   }
03764 }
03765 
03767 //                                                                           //
03768 // poolinit()    Initialize a pool of memory for allocation of items.        //
03769 //                                                                           //
03770 // A `pool' is created whose records have size at least `bytecount'.  Items  //
03771 // will be allocated in `itemcount'-item blocks.  Each item is assumed to be //
03772 // a collection of words, and either pointers or floating-point values are   //
03773 // assumed to be the "primary" word type.  (The "primary" word type is used  //
03774 // to determine alignment of items.)  If `alignment' isn't zero, all items   //
03775 // will be `alignment'-byte aligned in memory.  `alignment' must be either a //
03776 // multiple or a factor of the primary word size;  powers of two are safe.   //
03777 // `alignment' is normally used to create a few unused bits at the bottom of //
03778 // each item's pointer, in which information may be stored.                  //
03779 //                                                                           //
03781 
03782 void tetgenmesh::memorypool::
03783 poolinit(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03784 {
03785   int wordsize;
03786 
03787   // Initialize values in the pool.
03788   itemwordtype = wtype;
03789   wordsize = (itemwordtype == POINTER) ? sizeof(void *) : sizeof(REAL);
03790   // Find the proper alignment, which must be at least as large as:
03791   //   - The parameter `alignment'.
03792   //   - The primary word type, to avoid unaligned accesses.
03793   //   - sizeof(void *), so the stack of dead items can be maintained
03794   //       without unaligned accesses.
03795   if (alignment > wordsize) {
03796     alignbytes = alignment;
03797   } else {
03798     alignbytes = wordsize;
03799   }
03800   if ((int) sizeof(void *) > alignbytes) {
03801     alignbytes = (int) sizeof(void *);
03802   }
03803   itemwords = ((bytecount + alignbytes - 1) /  alignbytes)
03804             * (alignbytes / wordsize);
03805   itembytes = itemwords * wordsize;
03806   itemsperblock = itemcount;
03807 
03808   // Allocate a block of items.  Space for `itemsperblock' items and one
03809   //   pointer (to point to the next block) are allocated, as well as space
03810   //   to ensure alignment of the items.
03811   firstblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *)
03812                                 + alignbytes);
03813   if (firstblock == (void **) NULL) {
03814     printf("Error:  Out of memory.\n");
03815     terminatetetgen(1);
03816   }
03817   // Set the next block pointer to NULL.
03818   *(firstblock) = (void *) NULL;
03819   restart();
03820 }
03821 
03823 //                                                                           //
03824 // restart()   Deallocate all items in this pool.                            //
03825 //                                                                           //
03826 // The pool is returned to its starting state, except that no memory is      //
03827 // freed to the operating system.  Rather, the previously allocated blocks   //
03828 // are ready to be reused.                                                   //
03829 //                                                                           //
03831 
03832 void tetgenmesh::memorypool::restart()
03833 {
03834   unsigned long alignptr;
03835 
03836   items = 0;
03837   maxitems = 0;
03838 
03839   // Set the currently active block.
03840   nowblock = firstblock;
03841   // Find the first item in the pool.  Increment by the size of (void *).
03842   alignptr = (unsigned long) (nowblock + 1);
03843   // Align the item on an `alignbytes'-byte boundary.
03844   nextitem = (void *)
03845     (alignptr + (unsigned long) alignbytes -
03846      (alignptr % (unsigned long) alignbytes));
03847   // There are lots of unallocated items left in this block.
03848   unallocateditems = itemsperblock;
03849   // The stack of deallocated items is empty.
03850   deaditemstack = (void *) NULL;
03851 }
03852 
03854 //                                                                           //
03855 // alloc()   Allocate space for an item.                                     //
03856 //                                                                           //
03858 
03859 void* tetgenmesh::memorypool::alloc()
03860 {
03861   void *newitem;
03862   void **newblock;
03863   unsigned long alignptr;
03864 
03865   // First check the linked list of dead items.  If the list is not
03866   //   empty, allocate an item from the list rather than a fresh one.
03867   if (deaditemstack != (void *) NULL) {
03868     newitem = deaditemstack;                     // Take first item in list.
03869     deaditemstack = * (void **) deaditemstack;
03870   } else {
03871     // Check if there are any free items left in the current block.
03872     if (unallocateditems == 0) {
03873       // Check if another block must be allocated.
03874       if (*nowblock == (void *) NULL) {
03875         // Allocate a new block of items, pointed to by the previous block.
03876         newblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *)
03877                                     + alignbytes);
03878         if (newblock == (void **) NULL) {
03879           printf("Error:  Out of memory.\n");
03880           terminatetetgen(1);
03881         }
03882         *nowblock = (void *) newblock;
03883         // The next block pointer is NULL.
03884         *newblock = (void *) NULL;
03885       }
03886       // Move to the new block.
03887       nowblock = (void **) *nowblock;
03888       // Find the first item in the block.
03889       //   Increment by the size of (void *).
03890       alignptr = (unsigned long) (nowblock + 1);
03891       // Align the item on an `alignbytes'-byte boundary.
03892       nextitem = (void *)
03893         (alignptr + (unsigned long) alignbytes -
03894          (alignptr % (unsigned long) alignbytes));
03895       // There are lots of unallocated items left in this block.
03896       unallocateditems = itemsperblock;
03897     }
03898     // Allocate a new item.
03899     newitem = nextitem;
03900     // Advance `nextitem' pointer to next free item in block.
03901     if (itemwordtype == POINTER) {
03902       nextitem = (void *) ((void **) nextitem + itemwords);
03903     } else {
03904       nextitem = (void *) ((REAL *) nextitem + itemwords);
03905     }
03906     unallocateditems--;
03907     maxitems++;
03908   }
03909   items++;
03910   return newitem;
03911 }
03912 
03914 //                                                                           //
03915 // dealloc()   Deallocate space for an item.                                 //
03916 //                                                                           //
03917 // The deallocated space is stored in a queue for later reuse.               //
03918 //                                                                           //
03920 
03921 void tetgenmesh::memorypool::dealloc(void *dyingitem)
03922 {
03923   // Push freshly killed item onto stack.
03924   *((void **) dyingitem) = deaditemstack;
03925   deaditemstack = dyingitem;
03926   items--;
03927 }
03928 
03930 //                                                                           //
03931 // traversalinit()   Prepare to traverse the entire list of items.           //
03932 //                                                                           //
03933 // This routine is used in conjunction with traverse().                      //
03934 //                                                                           //
03936 
03937 void tetgenmesh::memorypool::traversalinit()
03938 {
03939   unsigned long alignptr;
03940 
03941   // Begin the traversal in the first block.
03942   pathblock = firstblock;
03943   // Find the first item in the block.  Increment by the size of (void *).
03944   alignptr = (unsigned long) (pathblock + 1);
03945   // Align with item on an `alignbytes'-byte boundary.
03946   pathitem = (void *)
03947     (alignptr + (unsigned long) alignbytes -
03948      (alignptr % (unsigned long) alignbytes));
03949   // Set the number of items left in the current block.
03950   pathitemsleft = itemsperblock;
03951 }
03952 
03954 //                                                                           //
03955 // traverse()   Find the next item in the list.                              //
03956 //                                                                           //
03957 // This routine is used in conjunction with traversalinit().  Be forewarned  //
03958 // that this routine successively returns all items in the list, including   //
03959 // deallocated ones on the deaditemqueue. It's up to you to figure out which //
03960 // ones are actually dead.  It can usually be done more space-efficiently by //
03961 // a routine that knows something about the structure of the item.           //
03962 //                                                                           //
03964 
03965 void* tetgenmesh::memorypool::traverse()
03966 {
03967   void *newitem;
03968   unsigned long alignptr;
03969 
03970   // Stop upon exhausting the list of items.
03971   if (pathitem == nextitem) {
03972     return (void *) NULL;
03973   }
03974   // Check whether any untraversed items remain in the current block.
03975   if (pathitemsleft == 0) {
03976     // Find the next block.
03977     pathblock = (void **) *pathblock;
03978     // Find the first item in the block.  Increment by the size of (void *).
03979     alignptr = (unsigned long) (pathblock + 1);
03980     // Align with item on an `alignbytes'-byte boundary.
03981     pathitem = (void *)
03982       (alignptr + (unsigned long) alignbytes -
03983        (alignptr % (unsigned long) alignbytes));
03984     // Set the number of items left in the current block.
03985     pathitemsleft = itemsperblock;
03986   }
03987   newitem = pathitem;
03988   // Find the next item in the block.
03989   if (itemwordtype == POINTER) {
03990     pathitem = (void *) ((void **) pathitem + itemwords);
03991   } else {
03992     pathitem = (void *) ((REAL *) pathitem + itemwords);
03993   }
03994   pathitemsleft--;
03995   return newitem;
03996 }
03997 
03999 //                                                                           //
04000 // linkinit()    Initialize a link for storing items.                        //
04001 //                                                                           //
04002 // The input parameters are the size of each item, a pointer of a linear     //
04003 // order function and the number of items allocating in one memory bulk.     //
04004 //                                                                           //
04006 
04007 void tetgenmesh::link::linkinit(int bytecount, compfunc pcomp, int itemcount)
04008 {
04009 #ifdef SELF_CHECK
04010   assert(bytecount > 0 && itemcount > 0);
04011 #endif
04012   // Remember the real size of each item.
04013   linkitembytes = bytecount;
04014   // Set the linear order function for this link.
04015   comp = pcomp;
04016 
04017   // Call the constructor of 'memorypool' to initialize its variables.
04018   //   like: itembytes, itemwords, items, ... Each node has size
04019   //   bytecount + 2 * sizeof(void **), and total 'itemcount + 2' (because
04020   //   link has additional two nodes 'head' and 'tail').
04021   poolinit(bytecount + 2 * sizeof(void **), itemcount + 2, POINTER, 0);
04022 
04023   // Initial state of this link.
04024   head = (void **) alloc();
04025   tail = (void **) alloc();
04026   *head = (void *) tail;
04027   *(head + 1) = NULL;
04028   *tail = NULL;
04029   *(tail + 1) = (void *) head;
04030   nextlinkitem = *head;
04031   curpos = 1;
04032   linkitems = 0;
04033 }
04034 
04036 //                                                                           //
04037 // clear()   Deallocate all nodes in this link.                              //
04038 //                                                                           //
04039 // The link is returned to its starting state, except that no memory is      //
04040 // freed to the operating system.  Rather, the previously allocated blocks   //
04041 // are ready to be reused.                                                   //
04042 //                                                                           //
04044 
04045 void tetgenmesh::link::clear()
04046 {
04047   // Reset the pool.
04048   restart();
04049 
04050   // Initial state of this link.
04051   head = (void **) alloc();
04052   tail = (void **) alloc();
04053   *head = (void *) tail;
04054   *(head + 1) = NULL;
04055   *tail = NULL;
04056   *(tail + 1) = (void *) head;
04057   nextlinkitem = *head;
04058   curpos = 1;
04059   linkitems = 0;
04060 }
04061 
04063 //                                                                           //
04064 // move()    Causes 'nextlinkitem' to traverse the specified number of nodes,//
04065 //           updates 'curpos' to be the node to which 'nextlinkitem' points. //
04066 //                                                                           //
04067 // 'numberofnodes' is a number indicating how many nodes need be traversed   //
04068 // (not counter the current node) need be traversed. It may be positive(move //
04069 // forward) or negative (move backward).  Return TRUE if it is successful.   //
04070 //                                                                           //
04072 
04073 bool tetgenmesh::link::move(int numberofnodes)
04074 {
04075   void **nownode;
04076   int i;
04077 
04078   nownode = (void **) nextlinkitem;
04079   if (numberofnodes > 0) {
04080     // Move forward.
04081     i = 0;
04082     while ((i < numberofnodes) && *nownode) {
04083       nownode = (void **) *nownode;
04084       i++;
04085     }
04086     if (*nownode == NULL) return false;
04087     nextlinkitem = (void *) nownode;
04088     curpos += numberofnodes;
04089   } else if (numberofnodes < 0) {
04090     // Move backward.
04091     i = 0;
04092     numberofnodes = -numberofnodes;
04093     while ((i < numberofnodes) && *(nownode + 1)) {
04094       nownode = (void **) *(nownode + 1);
04095       i++;
04096     }
04097     if (*(nownode + 1) == NULL) return false;
04098     nextlinkitem = (void *) nownode;
04099     curpos -= numberofnodes;
04100   }
04101   return true;
04102 }
04103 
04105 //                                                                           //
04106 // locate()    Locates the node at the specified position.                   //
04107 //                                                                           //
04108 // The number 'pos' (between 1 and 'linkitems') indicates the location. This //
04109 // routine first decides the shortest path traversing from 'curpos' to 'pos',//
04110 // i.e., from head, tail or 'curpos'.   Routine 'move()' is called to really //
04111 // traverse the link. If success, 'nextlinkitem' points to the node, 'curpos'//
04112 // and 'pos' are equal. Otherwise, return FALSE.                             //
04113 //                                                                           //
04115 
04116 bool tetgenmesh::link::locate(int pos)
04117 {
04118   int headdist, taildist, curdist;
04119   int abscurdist, mindist;
04120 
04121   if (pos < 1 || pos > linkitems) return false;
04122 
04123   headdist = pos - 1;
04124   taildist = linkitems - pos;
04125   curdist = pos - curpos;
04126   abscurdist = curdist >= 0 ? curdist : -curdist;
04127 
04128   if (headdist > taildist) {
04129     if (taildist > abscurdist) {
04130       mindist = curdist;
04131     } else {
04132       // taildist <= abs(curdist)
04133       mindist = -taildist;
04134       goend();
04135     }
04136   } else {
04137     // headdist <= taildist
04138     if (headdist > abscurdist) {
04139       mindist = curdist;
04140     } else {
04141       // headdist <= abs(curdist)
04142       mindist = headdist;
04143       rewind();
04144     }
04145   }
04146 
04147   return move(mindist);
04148 }
04149 
04151 //                                                                           //
04152 // add()    Add a node at the end of this link.                              //
04153 //                                                                           //
04154 // A new node is appended to the end of the link.  If 'newitem' is not NULL, //
04155 // its conents will be copied to the data slot of the new node. Returns the  //
04156 // pointer to the newest added node.                                         //
04157 //                                                                           //
04159 
04160 void* tetgenmesh::link::add(void* newitem)
04161 {
04162   void **newnode = tail;
04163   if (newitem != (void *) NULL) {
04164     memcpy((void *)(newnode + 2), newitem, linkitembytes);
04165   }
04166   tail = (void **) alloc();
04167   *tail = NULL;
04168   *newnode = (void*) tail;
04169   *(tail + 1) = (void*) newnode;
04170   linkitems++;
04171   return (void *)(newnode + 2);
04172 }
04173 
04175 //                                                                           //
04176 // insert()    Inserts a node before the specified position.                 //
04177 //                                                                           //
04178 // 'pos' (between 1 and 'linkitems') indicates the inserting position.  This //
04179 // routine inserts a new node before the node of 'pos'.  If 'newitem' is not //
04180 // NULL,  its conents will be copied into the data slot of the new node.  If //
04181 // 'pos' is larger than 'linkitems', it is equal as 'add()'.  A pointer to   //
04182 // the newest inserted item is returned.                                     //
04183 //                                                                           //
04185 
04186 void* tetgenmesh::link::insert(int pos, void* insitem)
04187 {
04188   if (!locate(pos)) {
04189     return add(insitem);
04190   }
04191 
04192   void **nownode = (void **) nextlinkitem;
04193 
04194   // Insert a node before 'nownode'.
04195   void **newnode = (void **) alloc();
04196   if (insitem != (void *) NULL) {
04197     memcpy((void *)(newnode + 2), insitem, linkitembytes);
04198   }
04199 
04200   *(void **)(*(nownode + 1)) = (void *) newnode;
04201   *newnode = (void *) nownode;
04202   *(newnode + 1) = *(nownode + 1);
04203   *(nownode + 1) = (void *) newnode;
04204 
04205   linkitems++;
04206 
04207   nextlinkitem = (void *) newnode;
04208   return (void *)(newnode + 2);
04209 }
04210 
04212 //                                                                           //
04213 // del()    Delete a node.                                                   //
04214 //                                                                           //
04215 // Returns a pointer of the deleted data. If you try to delete a non-existed //
04216 // node (e.g. link is empty or a wrong index is given) return NULL.          //
04217 //                                                                           //
04219 
04220 void* tetgenmesh::link::deletenode(void** deadnode)
04221 {
04222   void **nextnode = (void **) *deadnode;
04223   void **prevnode = (void **) *(deadnode + 1);
04224   *prevnode = (void *) nextnode;
04225   *(nextnode + 1) = (void *) prevnode;
04226 
04227   dealloc((void *) deadnode);
04228   linkitems--;
04229 
04230   nextlinkitem = (void *) nextnode;
04231   return (void *)(deadnode + 2);
04232 }
04233 
04235 //                                                                           //
04236 // del()    Delete a node at the specified position.                         //
04237 //                                                                           //
04238 // 'pos' between 1 and 'linkitems'.  Returns a pointer of the deleted data.  //
04239 // If you try to delete a non-existed node (e.g. link is empty or a wrong    //
04240 // index is given) return NULL.                                              //
04241 //                                                                           //
04243 
04244 void* tetgenmesh::link::del(int pos)
04245 {
04246   if (!locate(pos) || (linkitems == 0)) {
04247     return (void *) NULL;
04248   }
04249   return deletenode((void **) nextlinkitem);
04250 }
04251 
04253 //                                                                           //
04254 // getitem()    The link traversal routine.                                  //
04255 //                                                                           //
04256 // Returns the node to which 'nextlinkitem' points. Returns a 'NULL' if the  //
04257 // end of the link is reaching.  Both 'nextlinkitem' and 'curpos' will be    //
04258 // updated after this operation.                                             //
04259 //                                                                           //
04261 
04262 void* tetgenmesh::link::getitem()
04263 {
04264   if (nextlinkitem == (void *) tail) return NULL;
04265   void **nownode = (void **) nextlinkitem;
04266   nextlinkitem = *nownode;
04267   curpos += 1;
04268   return (void *)(nownode + 2);
04269 }
04270 
04272 //                                                                           //
04273 // getnitem()    Returns the node at a specified position.                   //
04274 //                                                                           //
04275 // 'pos' between 1 and 'linkitems'. After this operation, 'nextlinkitem' and //
04276 // 'curpos' will be updated to indicate this node.                           //
04277 //                                                                           //
04279 
04280 void* tetgenmesh::link::getnitem(int pos)
04281 {
04282   if (!locate(pos)) return NULL;
04283   return (void *)((void **) nextlinkitem + 2);
04284 }
04285 
04287 //                                                                           //
04288 // hasitem()    Search in this link to find if 'checkitem' exists.           //
04289 //                                                                           //
04290 // If 'checkitem' exists, return its position (between 1 to 'linkitems'),    //
04291 // otherwise, return -1. This routine requires the linear order function has //
04292 // been set.                                                                 //
04293 //                                                                           //
04295 
04296 int tetgenmesh::link::hasitem(void* checkitem)
04297 {
04298   void *pathitem;
04299   int count;
04300 
04301   rewind();
04302   pathitem = getitem();
04303   count = 0;
04304   while (pathitem) {
04305     count ++;
04306     if (comp) {
04307       if ((* comp)(pathitem, checkitem) == 0) {
04308         return count;
04309       }
04310     }
04311     pathitem = getitem();
04312   }
04313   return -1;
04314 }
04315 
04316 //
04317 // End of class 'list', 'memorypool' and 'link' implementation
04318 //
04319 
04320 //
04321 // Begin of mesh manipulation primitives
04322 //
04323 
04324 //
04325 // Begin of tables initialization.
04326 //
04327 
04328 // For enumerating three edges of a triangle.
04329 
04330 int tetgenmesh::plus1mod3[3] = {1, 2, 0};
04331 int tetgenmesh::minus1mod3[3] = {2, 0, 1};
04332 
04333 // Table 've' takes an edge version as input, returns the next edge version
04334 //   in the same edge ring.
04335 
04336 int tetgenmesh::ve[6] = { 2, 5, 4, 1, 0, 3 };
04337 
04338 // Tables 'vo', 'vd' and 'va' take an edge version, return the positions of
04339 //   the origin, destination and apex in the triangle.
04340 
04341 int tetgenmesh::vo[6] = { 0, 1, 1, 2, 2, 0 };
04342 int tetgenmesh::vd[6] = { 1, 0, 2, 1, 0, 2 };
04343 int tetgenmesh::va[6] = { 2, 2, 0, 0, 1, 1 };
04344 
04345 // The following tables are for tetrahedron primitives (operate on trifaces).
04346 
04347 // For 'org()', 'dest()' and 'apex()'.  Use 'loc' as the first index and
04348 //   'ver' as the second index.
04349 
04350 int tetgenmesh::locver2org[4][6]  = {
04351   {0, 1, 1, 2, 2, 0},
04352   {0, 3, 3, 1, 1, 0},
04353   {1, 3, 3, 2, 2, 1},
04354   {2, 3, 3, 0, 0, 2}
04355 };
04356 int tetgenmesh::locver2dest[4][6] = {
04357   {1, 0, 2, 1, 0, 2},
04358   {3, 0, 1, 3, 0, 1},
04359   {3, 1, 2, 3, 1, 2},
04360   {3, 2, 0, 3, 2, 0}
04361 };
04362 int tetgenmesh::locver2apex[4][6] = {
04363   {2, 2, 0, 0, 1, 1},
04364   {1, 1, 0, 0, 3, 3},
04365   {2, 2, 1, 1, 3, 3},
04366   {0, 0, 2, 2, 3, 3}
04367 };
04368 
04369 // For oppo() primitives, use 'loc' as the index.
04370 
04371 int tetgenmesh::loc2oppo[4] = { 3, 2, 0, 1 };
04372 
04373 // For fnext() primitive.  Use 'loc' as the first index and 'ver' as the
04374 //   second index. Returns a new 'loc' and new 'ver' in an array. (It is
04375 //   only valid for edge version equals one of {0, 2, 4}.)
04376 
04377 int tetgenmesh::locver2nextf[4][6][2] = {
04378   { {1, 5}, {-1, -1}, {2, 5}, {-1, -1}, {3, 5}, {-1, -1} },
04379   { {3, 3}, {-1, -1}, {2, 1}, {-1, -1}, {0, 1}, {-1, -1} },
04380   { {1, 3}, {-1, -1}, {3, 1}, {-1, -1}, {0, 3}, {-1, -1} },
04381   { {2, 3}, {-1, -1}, {1, 1}, {-1, -1}, {0, 5}, {-1, -1} }
04382 };
04383 
04384 // The edge number (from 0 to 5) of a tet is defined as follows:
04385 //   0 - (v0, v1), 1 - (v1, v2), 2 - (v2, v0)
04386 //   3 - (v3, v0), 4 - (v3, v1), 5 - (v3, v2).
04387 
04388 int tetgenmesh::locver2edge[4][6] = {
04389   {0, 0, 1, 1, 2, 2},
04390   {3, 3, 4, 4, 0, 0},
04391   {4, 4, 5, 5, 1, 1},
04392   {5, 5, 3, 3, 2, 2}
04393 };
04394 
04395 int tetgenmesh::edge2locver[6][2] = {
04396   {0, 0}, // 0  v0 -> v1
04397   {0, 2}, // 1  v1 -> v2
04398   {0, 4}, // 2  v2 -> v1
04399   {1, 0}, // 3  v0 -> v3
04400   {1, 2}, // 4  v1 -> v3
04401   {2, 2}  // 5  v2 -> v3
04402 };
04403 
04404 //
04405 // End of tables initialization.
04406 //
04407 
04408 // Some macros for convenience
04409 
04410 #define Div2  >> 1
04411 #define Mod2  & 01
04412 
04413 // NOTE: These bit operators should only be used in macros below.
04414 
04415 // Get orient(Range from 0 to 2) from face version(Range from 0 to 5).
04416 
04417 #define Orient(V)   ((V) Div2)
04418 
04419 // Determine edge ring(0 or 1) from face version(Range from 0 to 5).
04420 
04421 #define EdgeRing(V) ((V) Mod2)
04422 
04423 //
04424 // Begin of primitives for tetrahedra
04425 //
04426 
04427 // Each tetrahedron contains four pointers to its neighboring tetrahedra,
04428 //   with face indices.  To save memory, both information are kept in a
04429 //   single pointer. To make this possible, all tetrahedra are aligned to
04430 //   eight-byte boundaries, so that the last three bits of each pointer are
04431 //   zeros. A face index (in the range 0 to 3) is compressed into the last
04432 //   two bits of each pointer by the function 'encode()'.  The function
04433 //   'decode()' decodes a pointer, extracting a face index and a pointer to
04434 //   the beginning of a tetrahedron.
04435 
04436 inline void tetgenmesh::decode(tetrahedron ptr, triface& t) {
04437   t.loc = (int) ((unsigned long) (ptr) & (unsigned long) 3l);
04438   t.tet = (tetrahedron *) ((unsigned long) (ptr) & ~(unsigned long) 7l);
04439 }
04440 
04441 inline tetgenmesh::tetrahedron tetgenmesh::encode(triface& t) {
04442   return (tetrahedron) ((unsigned long) t.tet | (unsigned long) t.loc);
04443 }
04444 
04445 // sym() finds the abutting tetrahedron on the same face.
04446 
04447 inline void tetgenmesh::sym(triface& t1, triface& t2) {
04448   tetrahedron ptr = t1.tet[t1.loc];
04449   decode(ptr, t2);
04450 }
04451 
04452 inline void tetgenmesh::symself(triface& t) {
04453   tetrahedron ptr = t.tet[t.loc];
04454   decode(ptr, t);
04455 }
04456 
04457 // Bond two tetrahedra together at their faces.
04458 
04459 inline void tetgenmesh::bond(triface& t1, triface& t2) {
04460   t1.tet[t1.loc] = encode(t2);
04461   t2.tet[t2.loc] = encode(t1);
04462 }
04463 
04464 // Dissolve a bond (from one side).  Note that the other tetrahedron will
04465 //   still think it is connected to this tetrahedron.  Usually, however,
04466 //   the other tetrahedron is being deleted entirely, or bonded to another
04467 //   tetrahedron, so it doesn't matter.
04468 
04469 inline void tetgenmesh::dissolve(triface& t) {
04470   t.tet[t.loc] = (tetrahedron) dummytet;
04471 }
04472 
04473 // These primitives determine or set the origin, destination, apex or
04474 //   opposition of a tetrahedron with respect to 'loc' and 'ver'.
04475 
04476 inline tetgenmesh::point tetgenmesh::org(triface& t) {
04477   return (point) t.tet[locver2org[t.loc][t.ver] + 4];
04478 }
04479 
04480 inline tetgenmesh::point tetgenmesh::dest(triface& t) {
04481   return (point) t.tet[locver2dest[t.loc][t.ver] + 4];
04482 }
04483 
04484 inline tetgenmesh::point tetgenmesh::apex(triface& t) {
04485   return (point) t.tet[locver2apex[t.loc][t.ver] + 4];
04486 }
04487 
04488 inline tetgenmesh::point tetgenmesh::oppo(triface& t) {
04489   return (point) t.tet[loc2oppo[t.loc] + 4];
04490 }
04491 
04492 inline void tetgenmesh::setorg(triface& t, point pointptr) {
04493   t.tet[locver2org[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04494 }
04495 
04496 inline void tetgenmesh::setdest(triface& t, point pointptr) {
04497   t.tet[locver2dest[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04498 }
04499 
04500 inline void tetgenmesh::setapex(triface& t, point pointptr) {
04501   t.tet[locver2apex[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04502 }
04503 
04504 inline void tetgenmesh::setoppo(triface& t, point pointptr) {
04505   t.tet[loc2oppo[t.loc] + 4] = (tetrahedron) pointptr;
04506 }
04507 
04508 // These primitives were drived from Mucke's triangle-edge data structure
04509 //   to change face-edge relation in a tetrahedron (esym, enext and enext2)
04510 //   or between two tetrahedra (fnext).
04511 
04512 // If e0 = e(i, j), e1 = e(j, i), that is e0 and e1 are the two directions
04513 //   of the same undirected edge of a face. e0.sym() = e1 and vice versa.
04514 
04515 inline void tetgenmesh::esym(triface& t1, triface& t2) {
04516   t2.tet = t1.tet;
04517   t2.loc = t1.loc;
04518   t2.ver = t1.ver + (EdgeRing(t1.ver) ? -1 : 1);
04519 }
04520 
04521 inline void tetgenmesh::esymself(triface& t) {
04522   t.ver += (EdgeRing(t.ver) ? -1 : 1);
04523 }
04524 
04525 // If e0 and e1 are both in the same edge ring of a face, e1 = e0.enext().
04526 
04527 inline void tetgenmesh::enext(triface& t1, triface& t2) {
04528   t2.tet = t1.tet;
04529   t2.loc = t1.loc;
04530   t2.ver = ve[t1.ver];
04531 }
04532 
04533 inline void tetgenmesh::enextself(triface& t) {
04534   t.ver = ve[t.ver];
04535 }
04536 
04537 // enext2() is equal to e2 = e0.enext().enext()
04538 
04539 inline void tetgenmesh::enext2(triface& t1, triface& t2) {
04540   t2.tet = t1.tet;
04541   t2.loc = t1.loc;
04542   t2.ver = ve[ve[t1.ver]];
04543 }
04544 
04545 inline void tetgenmesh::enext2self(triface& t) {
04546   t.ver = ve[ve[t.ver]];
04547 }
04548 
04549 // If f0 and f1 are both in the same face ring of a face, f1 = f0.fnext().
04550 //   If f1 exists, return true. Otherwise, return false, i.e., f0 is a
04551 //   boundary or hull face.
04552 
04553 inline bool tetgenmesh::fnext(triface& t1, triface& t2)
04554 {
04555   // Get the next face.
04556   t2.loc = locver2nextf[t1.loc][t1.ver][0];
04557   // Is the next face in the same tet?
04558   if (t2.loc != -1) {
04559     // It's in the same tet. Get the edge version.
04560     t2.ver = locver2nextf[t1.loc][t1.ver][1];
04561     t2.tet = t1.tet;
04562   } else {
04563     // The next face is in the neigbhour of 't1'.
04564     sym(t1, t2);
04565     if (t2.tet != dummytet) {
04566       // Find the corresponding edge in t2.
04567       point torg;
04568       int tloc, tver, i;
04569       t2.ver = 0;
04570       torg = org(t1);
04571       for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04572         enextself(t2);
04573       }
04574       // Go to the next face in t2.
04575       tloc = t2.loc;
04576       tver = t2.ver;
04577       t2.loc = locver2nextf[tloc][tver][0];
04578       t2.ver = locver2nextf[tloc][tver][1];
04579     }
04580   }
04581   return t2.tet != dummytet;
04582 }
04583 
04584 inline bool tetgenmesh::fnextself(triface& t1)
04585 {
04586   triface t2;
04587 
04588   // Get the next face.
04589   t2.loc = locver2nextf[t1.loc][t1.ver][0];
04590   // Is the next face in the same tet?
04591   if (t2.loc != -1) {
04592     // It's in the same tet. Get the edge version.
04593     t2.ver = locver2nextf[t1.loc][t1.ver][1];
04594     t1.loc = t2.loc;
04595     t1.ver = t2.ver;
04596   } else {
04597     // The next face is in the neigbhour of 't1'.
04598     sym(t1, t2);
04599     if (t2.tet != dummytet) {
04600       // Find the corresponding edge in t2.
04601       point torg;
04602       int i;
04603       t2.ver = 0;
04604       torg = org(t1);
04605       for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04606         enextself(t2);
04607       }
04608       t1.loc = locver2nextf[t2.loc][t2.ver][0];
04609       t1.ver = locver2nextf[t2.loc][t2.ver][1];
04610       t1.tet = t2.tet;
04611     }
04612   }
04613   return t2.tet != dummytet;
04614 }
04615 
04616 // enextfnext() and enext2fnext() are combination primitives of enext(),
04617 //   enext2() and fnext().
04618 
04619 inline void tetgenmesh::enextfnext(triface& t1, triface& t2) {
04620   enext(t1, t2);
04621   fnextself(t2);
04622 }
04623 
04624 inline void tetgenmesh::enextfnextself(triface& t) {
04625   enextself(t);
04626   fnextself(t);
04627 }
04628 
04629 inline void tetgenmesh::enext2fnext(triface& t1, triface& t2) {
04630   enext2(t1, t2);
04631   fnextself(t2);
04632 }
04633 
04634 inline void tetgenmesh::enext2fnextself(triface& t) {
04635   enext2self(t);
04636   fnextself(t);
04637 }
04638 
04639 // Primitives to infect or cure a tetrahedron with the virus.   The last
04640 //   third bit of the pointer is marked for infection.  These rely on the
04641 //   assumption that all tetrahedron are aligned to eight-byte boundaries.
04642 
04643 inline void tetgenmesh::infect(triface& t) {
04644   t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] | (unsigned long) 4l);
04645 }
04646 
04647 inline void tetgenmesh::uninfect(triface& t) {
04648   t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] & ~ (unsigned long) 4l);
04649 }
04650 
04651 // Test a tetrahedron for viral infection.
04652 
04653 inline bool tetgenmesh::infected(triface& t) {
04654   return (((unsigned long) t.tet[0] & (unsigned long) 4l) != 0);
04655 }
04656 
04657 // Check or set a tetrahedron's attributes.
04658 
04659 inline REAL tetgenmesh::elemattribute(tetrahedron* ptr, int attnum) {
04660   return ((REAL *) (ptr))[elemattribindex + attnum];
04661 }
04662 
04663 inline void tetgenmesh::
04664 setelemattribute(tetrahedron* ptr, int attnum, REAL value){
04665   ((REAL *) (ptr))[elemattribindex + attnum] = value;
04666 }
04667 
04668 // Check or set a tetrahedron's maximum volume bound.
04669 
04670 inline REAL tetgenmesh::volumebound(tetrahedron* ptr) {
04671   return ((REAL *) (ptr))[volumeboundindex];
04672 }
04673 
04674 inline void tetgenmesh::setvolumebound(tetrahedron* ptr, REAL value) {
04675   ((REAL *) (ptr))[volumeboundindex] = value;
04676 }
04677 
04678 //
04679 // End of primitives for tetrahedra
04680 //
04681 
04682 //
04683 // Begin of primitives for subfaces/subsegments
04684 //
04685 
04686 // Each subface contains three pointers to its neighboring subfaces, with
04687 //   edge versions.  To save memory, both information are kept in a single
04688 //   pointer. To make this possible, all subfaces are aligned to eight-byte
04689 //   boundaries, so that the last three bits of each pointer are zeros. An
04690 //   edge version (in the range 0 to 5) is compressed into the last three
04691 //   bits of each pointer by 'sencode()'.  'sdecode()' decodes a pointer,
04692 //   extracting an edge version and a pointer to the beginning of a subface.
04693 
04694 inline void tetgenmesh::sdecode(shellface sptr, face& s) {
04695   s.shver = (int) ((unsigned long) (sptr) & (unsigned long) 7l);
04696   s.sh = (shellface *) ((unsigned long) (sptr) & ~ (unsigned long) 7l);
04697 }
04698 
04699 inline tetgenmesh::shellface tetgenmesh::sencode(face& s) {
04700   return (shellface) ((unsigned long) s.sh | (unsigned long) s.shver);
04701 }
04702 
04703 // spivot() finds the other subface (from this subface) that shares the
04704 //   same edge.
04705 
04706 inline void tetgenmesh::spivot(face& s1, face& s2) {
04707   shellface sptr = s1.sh[Orient(s1.shver)];
04708   sdecode(sptr, s2);
04709 }
04710 
04711 inline void tetgenmesh::spivotself(face& s) {
04712   shellface sptr = s.sh[Orient(s.shver)];
04713   sdecode(sptr, s);
04714 }
04715 
04716 // sbond() bonds two subfaces together, i.e., after bonding, both faces
04717 //   are pointing to each other.
04718 
04719 inline void tetgenmesh::sbond(face& s1, face& s2) {
04720   s1.sh[Orient(s1.shver)] = sencode(s2);
04721   s2.sh[Orient(s2.shver)] = sencode(s1);
04722 }
04723 
04724 // sbond1() only bonds s2 to s1, i.e., after bonding, s1 is pointing to s2,
04725 //   but s2 is not pointing to s1.
04726 
04727 inline void tetgenmesh::sbond1(face& s1, face& s2) {
04728   s1.sh[Orient(s1.shver)] = sencode(s2);
04729 }
04730 
04731 // Dissolve a subface bond (from one side).  Note that the other subface
04732 //   will still think it's connected to this subface.
04733 
04734 inline void tetgenmesh::sdissolve(face& s) {
04735   s.sh[Orient(s.shver)] = (shellface) dummysh;
04736 }
04737 
04738 // These primitives determine or set the origin, destination, or apex
04739 //   of a subface with respect to the edge version.
04740 
04741 inline tetgenmesh::point tetgenmesh::sorg(face& s) {
04742   return (point) s.sh[3 + vo[s.shver]];
04743 }
04744 
04745 inline tetgenmesh::point tetgenmesh::sdest(face& s) {
04746   return (point) s.sh[3 + vd[s.shver]];
04747 }
04748 
04749 inline tetgenmesh::point tetgenmesh::sapex(face& s) {
04750   return (point) s.sh[3 + va[s.shver]];
04751 }
04752 
04753 inline void tetgenmesh::setsorg(face& s, point pointptr) {
04754   s.sh[3 + vo[s.shver]] = (shellface) pointptr;
04755 }
04756 
04757 inline void tetgenmesh::setsdest(face& s, point pointptr) {
04758   s.sh[3 + vd[s.shver]] = (shellface) pointptr;
04759 }
04760 
04761 inline void tetgenmesh::setsapex(face& s, point pointptr) {
04762   s.sh[3 + va[s.shver]] = (shellface) pointptr;
04763 }
04764 
04765 // These primitives were drived from Mucke[2]'s triangle-edge data structure
04766 //   to change face-edge relation in a subface (sesym, senext and senext2).
04767 
04768 inline void tetgenmesh::sesym(face& s1, face& s2) {
04769   s2.sh = s1.sh;
04770   s2.shver = s1.shver + (EdgeRing(s1.shver) ? -1 : 1);
04771 }
04772 
04773 inline void tetgenmesh::sesymself(face& s) {
04774   s.shver += (EdgeRing(s.shver) ? -1 : 1);
04775 }
04776 
04777 inline void tetgenmesh::senext(face& s1, face& s2) {
04778   s2.sh = s1.sh;
04779   s2.shver = ve[s1.shver];
04780 }
04781 
04782 inline void tetgenmesh::senextself(face& s) {
04783   s.shver = ve[s.shver];
04784 }
04785 
04786 inline void tetgenmesh::senext2(face& s1, face& s2) {
04787   s2.sh = s1.sh;
04788   s2.shver = ve[ve[s1.shver]];
04789 }
04790 
04791 inline void tetgenmesh::senext2self(face& s) {
04792   s.shver = ve[ve[s.shver]];
04793 }
04794 
04795 // If f0 and f1 are both in the same face ring, then f1 = f0.fnext(),
04796 
04797 inline void tetgenmesh::sfnext(face& s1, face& s2) {
04798   getnextsface(&s1, &s2);
04799 }
04800 
04801 inline void tetgenmesh::sfnextself(face& s) {
04802   getnextsface(&s, NULL);
04803 }
04804 
04805 // These primitives read or set a pointer of the badface structure.  The
04806 //   pointer is stored sh[11].
04807 
04808 inline tetgenmesh::badface* tetgenmesh::shell2badface(face& s) {
04809   return (badface*) s.sh[11];
04810 }
04811 
04812 inline void tetgenmesh::setshell2badface(face& s, badface* value) {
04813   s.sh[11] = (shellface) value;
04814 }
04815 
04816 // Check or set a subface's maximum area bound.
04817 
04818 inline REAL tetgenmesh::areabound(face& s) {
04819   return ((REAL *) (s.sh))[areaboundindex];
04820 }
04821 
04822 inline void tetgenmesh::setareabound(face& s, REAL value) {
04823   ((REAL *) (s.sh))[areaboundindex] = value;
04824 }
04825 
04826 // These two primitives read or set a shell marker.  Shell markers are used
04827 //   to hold user boundary information.
04828 
04829 inline int tetgenmesh::shellmark(face& s) {
04830   return ((int *) (s.sh))[shmarkindex];
04831 }
04832 
04833 inline void tetgenmesh::setshellmark(face& s, int value) {
04834   ((int *) (s.sh))[shmarkindex] = value;
04835 }
04836 
04837 // These two primitives set or read the type of the subface or subsegment.
04838 
04839 inline enum tetgenmesh::shestype tetgenmesh::shelltype(face& s) {
04840   return (enum shestype) ((int *) (s.sh))[shmarkindex + 1];
04841 }
04842 
04843 inline void tetgenmesh::setshelltype(face& s, enum shestype value) {
04844   ((int *) (s.sh))[shmarkindex + 1] = (int) value;
04845 }
04846 
04847 // These two primitives set or read the pbc group of the subface.
04848 
04849 inline int tetgenmesh::shellpbcgroup(face& s) {
04850   return ((int *) (s.sh))[shmarkindex + 2];
04851 }
04852 
04853 inline void tetgenmesh::setshellpbcgroup(face& s, int value) {
04854   ((int *) (s.sh))[shmarkindex + 2] = value;
04855 }
04856 
04857 // Primitives to infect or cure a subface with the virus. These rely on the
04858 //   assumption that all tetrahedra are aligned to eight-byte boundaries.
04859 
04860 inline void tetgenmesh::sinfect(face& s) {
04861   s.sh[6] = (shellface) ((unsigned long) s.sh[6] | (unsigned long) 4l);
04862 }
04863 
04864 inline void tetgenmesh::suninfect(face& s) {
04865   s.sh[6] = (shellface)((unsigned long) s.sh[6] & ~(unsigned long) 4l);
04866 }
04867 
04868 // Test a subface for viral infection.
04869 
04870 inline bool tetgenmesh::sinfected(face& s) {
04871   return (((unsigned long) s.sh[6] & (unsigned long) 4l) != 0);
04872 }
04873 
04874 //
04875 // End of primitives for subfaces/subsegments
04876 //
04877 
04878 //
04879 // Begin of primitives for interacting between tetrahedra and subfaces
04880 //
04881 
04882 // tspivot() finds a subface abutting on this tetrahdera.
04883 
04884 inline void tetgenmesh::tspivot(triface& t, face& s) {
04885   shellface sptr = (shellface) t.tet[8 + t.loc];
04886   sdecode(sptr, s);
04887 }
04888 
04889 // stpivot() finds a tetrahedron abutting a subface.
04890 
04891 inline void tetgenmesh::stpivot(face& s, triface& t) {
04892   tetrahedron ptr = (tetrahedron) s.sh[6 + EdgeRing(s.shver)];
04893   decode(ptr, t);
04894 }
04895 
04896 // tsbond() bond a tetrahedron to a subface.
04897 
04898 inline void tetgenmesh::tsbond(triface& t, face& s) {
04899   t.tet[8 + t.loc] = (tetrahedron) sencode(s);
04900   s.sh[6 + EdgeRing(s.shver)] = (shellface) encode(t);
04901 }
04902 
04903 // tsdissolve() dissolve a bond (from the tetrahedron side).
04904 
04905 inline void tetgenmesh::tsdissolve(triface& t) {
04906   t.tet[8 + t.loc] = (tetrahedron) dummysh;
04907 }
04908 
04909 // stdissolve() dissolve a bond (from the subface side).
04910 
04911 inline void tetgenmesh::stdissolve(face& s) {
04912   s.sh[6 + EdgeRing(s.shver)] = (shellface) dummytet;
04913 }
04914 
04915 //
04916 // End of primitives for interacting between tetrahedra and subfaces
04917 //
04918 
04919 //
04920 // Begin of primitives for interacting between subfaces and subsegs
04921 //
04922 
04923 // sspivot() finds a subsegment abutting a subface.
04924 
04925 inline void tetgenmesh::sspivot(face& s, face& edge) {
04926   shellface sptr = (shellface) s.sh[8 + Orient(s.shver)];
04927   sdecode(sptr, edge);
04928 }
04929 
04930 // ssbond() bond a subface to a subsegment.
04931 
04932 inline void tetgenmesh::ssbond(face& s, face& edge) {
04933   s.sh[8 + Orient(s.shver)] = sencode(edge);
04934   edge.sh[0] = sencode(s);
04935 }
04936 
04937 // ssdisolve() dissolve a bond (from the subface side)
04938 
04939 inline void tetgenmesh::ssdissolve(face& s) {
04940   s.sh[8 + Orient(s.shver)] = (shellface) dummysh;
04941 }
04942 
04943 //
04944 // End of primitives for interacting between subfaces and subsegs
04945 //
04946 
04947 //
04948 // Begin of primitives for interacting between tet and subsegs.
04949 //
04950 
04951 inline void tetgenmesh::tsspivot1(triface& t, face& seg)
04952 {
04953   shellface sptr = (shellface) t.tet[8 + locver2edge[t.loc][t.ver]];
04954   sdecode(sptr, seg);
04955 }
04956 
04957 // Only bond/dissolve at tet's side, but not vice versa.
04958 
04959 inline void tetgenmesh::tssbond1(triface& t, face& seg)
04960 {
04961   t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) sencode(seg);
04962 }
04963 
04964 inline void tetgenmesh::tssdissolve1(triface& t)
04965 {
04966   t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) dummysh;
04967 }
04968 
04969 //
04970 // End of primitives for interacting between tet and subsegs.
04971 //
04972 
04973 //
04974 // Begin of primitives for points
04975 //
04976 
04977 inline int tetgenmesh::pointmark(point pt) {
04978   return ((int *) (pt))[pointmarkindex];
04979 }
04980 
04981 inline void tetgenmesh::setpointmark(point pt, int value) {
04982   ((int *) (pt))[pointmarkindex] = value;
04983 }
04984 
04985 // These two primitives set and read the type of the point.
04986 
04987 inline enum tetgenmesh::verttype tetgenmesh::pointtype(point pt) {
04988   return (enum verttype) ((int *) (pt))[pointmarkindex + 1];
04989 }
04990 
04991 inline void tetgenmesh::setpointtype(point pt, enum verttype value) {
04992   ((int *) (pt))[pointmarkindex + 1] = (int) value;
04993 }
04994 
04995 // These following primitives set and read a pointer to a tetrahedron
04996 //   a subface/subsegment, a point, or a tet of background mesh.
04997 
04998 inline tetgenmesh::tetrahedron tetgenmesh::point2tet(point pt) {
04999   return ((tetrahedron *) (pt))[point2simindex];
05000 }
05001 
05002 inline void tetgenmesh::setpoint2tet(point pt, tetrahedron value) {
05003   ((tetrahedron *) (pt))[point2simindex] = value;
05004 }
05005 
05006 inline tetgenmesh::shellface tetgenmesh::point2sh(point pt) {
05007   return (shellface) ((tetrahedron *) (pt))[point2simindex + 1];
05008 }
05009 
05010 inline void tetgenmesh::setpoint2sh(point pt, shellface value) {
05011   ((tetrahedron *) (pt))[point2simindex + 1] = (tetrahedron) value;
05012 }
05013 
05014 inline tetgenmesh::point tetgenmesh::point2ppt(point pt) {
05015   return (point) ((tetrahedron *) (pt))[point2simindex + 2];
05016 }
05017 
05018 inline void tetgenmesh::setpoint2ppt(point pt, point value) {
05019   ((tetrahedron *) (pt))[point2simindex + 2] = (tetrahedron) value;
05020 }
05021 
05022 inline tetgenmesh::tetrahedron tetgenmesh::point2bgmtet(point pt) {
05023   return ((tetrahedron *) (pt))[point2simindex + 3];
05024 }
05025 
05026 inline void tetgenmesh::setpoint2bgmtet(point pt, tetrahedron value) {
05027   ((tetrahedron *) (pt))[point2simindex + 3] = value;
05028 }
05029 
05030 // These primitives set and read a pointer to its pbc point.
05031 
05032 inline tetgenmesh::point tetgenmesh::point2pbcpt(point pt) {
05033   return (point) ((tetrahedron *) (pt))[point2pbcptindex];
05034 }
05035 
05036 inline void tetgenmesh::setpoint2pbcpt(point pt, point value) {
05037   ((tetrahedron *) (pt))[point2pbcptindex] = (tetrahedron) value;
05038 }
05039 
05040 //
05041 // End of primitives for points
05042 //
05043 
05044 //
05045 // Begin of advanced primitives
05046 //
05047 
05048 // adjustedgering() adjusts the edge version so that it belongs to the
05049 //   indicated edge ring.  The 'direction' only can be 0(CCW) or 1(CW).
05050 //   If the edge is not in the wanted edge ring, reverse it.
05051 
05052 inline void tetgenmesh::adjustedgering(triface& t, int direction) {
05053   if (EdgeRing(t.ver) != direction) {
05054     esymself(t);
05055   }
05056 }
05057 
05058 inline void tetgenmesh::adjustedgering(face& s, int direction) {
05059   if (EdgeRing(s.shver) != direction) {
05060     sesymself(s);
05061   }
05062 }
05063 
05064 // isdead() returns TRUE if the tetrahedron or subface has been dealloced.
05065 
05066 inline bool tetgenmesh::isdead(triface* t) {
05067   if (t->tet == (tetrahedron *) NULL) return true;
05068   else return t->tet[4] == (tetrahedron) NULL;
05069 }
05070 
05071 inline bool tetgenmesh::isdead(face* s) {
05072   if (s->sh == (shellface *) NULL) return true;
05073   else return s->sh[3] == (shellface) NULL;
05074 }
05075 
05076 // isfacehaspoint() returns TRUE if the 'testpoint' is one of the vertices
05077 //   of the tetface 't' subface 's'.
05078 
05079 inline bool tetgenmesh::isfacehaspoint(triface* t, point testpoint) {
05080   return ((org(*t) == testpoint) || (dest(*t) == testpoint) ||
05081           (apex(*t) == testpoint));
05082 }
05083 
05084 inline bool tetgenmesh::isfacehaspoint(face* s, point testpoint) {
05085   return (s->sh[3] == (shellface) testpoint) ||
05086          (s->sh[4] == (shellface) testpoint) ||
05087          (s->sh[5] == (shellface) testpoint);
05088 }
05089 
05090 // isfacehasedge() returns TRUE if the edge (given by its two endpoints) is
05091 //   one of the three edges of the subface 's'.
05092 
05093 inline bool tetgenmesh::isfacehasedge(face* s, point tend1, point tend2) {
05094   return (isfacehaspoint(s, tend1) && isfacehaspoint(s, tend2));
05095 }
05096 
05097 // issymexist() returns TRUE if the adjoining tetrahedron is not 'duumytet'.
05098 
05099 inline bool tetgenmesh::issymexist(triface* t) {
05100   tetrahedron *ptr = (tetrahedron *)
05101     ((unsigned long)(t->tet[t->loc]) & ~(unsigned long)7l);
05102   return ptr != dummytet;
05103 }
05104 
05106 //                                                                           //
05107 // getnextsface()    Finds the next subface in the face ring.                //
05108 //                                                                           //
05109 // For saving space in the data structure of subface, there only exists one  //
05110 // face ring around a segment (see programming manual).  This routine imple- //
05111 // ments the double face ring as desired in Muecke's data structure.         //
05112 //                                                                           //
05114 
05115 void tetgenmesh::getnextsface(face* s1, face* s2)
05116 {
05117   face neighsh, spinsh;
05118   face testseg;
05119 
05120   sspivot(*s1, testseg);
05121   if (testseg.sh != dummysh) {
05122     testseg.shver = 0;
05123     if (sorg(testseg) == sorg(*s1)) {
05124       spivot(*s1, neighsh);
05125     } else {
05126       spinsh = *s1;
05127       do {
05128         neighsh = spinsh;
05129         spivotself(spinsh);
05130       } while (spinsh.sh != s1->sh);
05131     }
05132   } else {
05133     spivot(*s1, neighsh);
05134   }
05135   if (sorg(neighsh) != sorg(*s1)) {
05136     sesymself(neighsh);
05137   }
05138   if (s2 != (face *) NULL) {
05139     *s2 = neighsh;
05140   } else {
05141     *s1 = neighsh;
05142   }
05143 }
05144 
05146 //                                                                           //
05147 // tsspivot()    Finds a subsegment abutting on a tetrahderon's edge.        //
05148 //                                                                           //
05149 // The edge is represented in the primary edge of 'checkedge'. If there is a //
05150 // subsegment bonded at this edge, it is returned in handle 'checkseg', the  //
05151 // edge direction of 'checkseg' is conformed to 'checkedge'. If there isn't, //
05152 // set 'checkseg.sh = dummysh' to indicate it is not a subsegment.           //
05153 //                                                                           //
05154 // To find whether an edge of a tetrahedron is a subsegment or not. First we //
05155 // need find a subface around this edge to see if it contains a subsegment.  //
05156 // The reason is there is no direct connection between a tetrahedron and its //
05157 // adjoining subsegments.                                                    //
05158 //                                                                           //
05160 
05161 void tetgenmesh::tsspivot(triface* checkedge, face* checkseg)
05162 {
05163   triface spintet;
05164   face parentsh;
05165   point tapex;
05166   int hitbdry;
05167 
05168   spintet = *checkedge;
05169   tapex = apex(*checkedge);
05170   hitbdry = 0;
05171   do {
05172     tspivot(spintet, parentsh);
05173     // Does spintet have a (non-fake) subface attached?
05174     if ((parentsh.sh != dummysh) && (sapex(parentsh) != NULL)) {
05175       // Find a subface! Find the edge in it.
05176       findedge(&parentsh, org(*checkedge), dest(*checkedge));
05177       sspivot(parentsh, *checkseg);
05178       if (checkseg->sh != dummysh) {
05179         // Find a subsegment! Correct its edge direction before return.
05180         if (sorg(*checkseg) != org(*checkedge)) {
05181           sesymself(*checkseg);
05182         }
05183       }
05184       return;
05185     }
05186     if (!fnextself(spintet)) {
05187       hitbdry++;
05188       if (hitbdry < 2) {
05189         esym(*checkedge, spintet);
05190         if (!fnextself(spintet)) {
05191           hitbdry++;
05192         }
05193       }
05194     }
05195   } while ((apex(spintet) != tapex) && (hitbdry < 2));
05196   // Not find.
05197   checkseg->sh = dummysh;
05198 }
05199 
05201 //                                                                           //
05202 // sstpivot()    Finds a tetrahedron abutting a subsegment.                  //
05203 //                                                                           //
05204 // This is the inverse operation of 'tsspivot()'.  One subsegment shared by  //
05205 // arbitrary number of tetrahedron, the returned tetrahedron is not unique.  //
05206 // The edge direction of the returned tetrahedron is conformed to the given  //
05207 // subsegment.                                                               //
05208 //                                                                           //
05210 
05211 void tetgenmesh::sstpivot(face* checkseg, triface* retedge)
05212 {
05213   face parentsh;
05214 
05215   // Get the subface which holds the subsegment.
05216   sdecode(checkseg->sh[0], parentsh);
05217 #ifdef SELF_CHECK
05218   assert(parentsh.sh != dummysh);
05219 #endif
05220   // Get a tetraheron to which the subface attches.
05221   stpivot(parentsh, *retedge);
05222   if (retedge->tet == dummytet) {
05223     sesymself(parentsh);
05224     stpivot(parentsh, *retedge);
05225 #ifdef SELF_CHECK
05226     assert(retedge->tet != dummytet);
05227 #endif
05228   }
05229   // Correct the edge direction before return.
05230   findedge(retedge, sorg(*checkseg), sdest(*checkseg));
05231 }
05232 
05234 //                                                                           //
05235 // findorg()    Finds a point in the given handle (tetrahedron or subface).  //
05236 //                                                                           //
05237 // If 'dorg' is a one of vertices of the given handle,  set the origin of    //
05238 // this handle be that point and return TRUE.  Otherwise, return FALSE and   //
05239 // 'tface' remains unchanged.                                                //
05240 //                                                                           //
05242 
05243 bool tetgenmesh::findorg(triface* tface, point dorg)
05244 {
05245   if (org(*tface) == dorg) {
05246     return true;
05247   } else {
05248     if (dest(*tface) == dorg) {
05249       enextself(*tface);
05250       return true;
05251     } else {
05252       if (apex(*tface) == dorg) {
05253         enext2self(*tface);
05254         return true;
05255       } else {
05256         if (oppo(*tface) == dorg) {
05257           // Keep 'tface' referring to the same tet after fnext().
05258           adjustedgering(*tface, CCW);
05259           fnextself(*tface);
05260           enext2self(*tface);
05261           return true;
05262         }
05263       }
05264     }
05265   }
05266   return false;
05267 }
05268 
05269 bool tetgenmesh::findorg(face* sface, point dorg)
05270 {
05271   if (sorg(*sface) == dorg) {
05272     return true;
05273   } else {
05274     if (sdest(*sface) == dorg) {
05275       senextself(*sface);
05276       return true;
05277     } else {
05278       if (sapex(*sface) == dorg) {
05279         senext2self(*sface);
05280         return true;
05281       }
05282     }
05283   }
05284   return false;
05285 }
05286 
05288 //                                                                           //
05289 // findedge()    Find an edge in the given handle (tetrahedron or subface).  //
05290 //                                                                           //
05291 // The edge is given in two points 'eorg' and 'edest'.  It is assumed that   //
05292 // the edge must exist in the given handle (tetrahedron or subface).  This   //
05293 // routine sets the right edge version for the input handle.                 //
05294 //                                                                           //
05296 
05297 void tetgenmesh::findedge(triface* tface, point eorg, point edest)
05298 {
05299   int i;
05300 
05301   for (i = 0; i < 3; i++) {
05302     if (org(*tface) == eorg) {
05303       if (dest(*tface) == edest) {
05304         // Edge is found, return.
05305         return;
05306       }
05307     } else {
05308       if (org(*tface) == edest) {
05309         if (dest(*tface) == eorg) {
05310           // Edge is found, inverse the direction and return.
05311           esymself(*tface);
05312           return;
05313         }
05314       }
05315     }
05316     enextself(*tface);
05317   }
05318   // It should never be here.
05319   printf("Internalerror in findedge():  Unable to find an edge in tet.\n");
05320   internalerror();
05321 }
05322 
05323 void tetgenmesh::findedge(face* sface, point eorg, point edest)
05324 {
05325   int i;
05326 
05327   for (i = 0; i < 3; i++) {
05328     if (sorg(*sface) == eorg) {
05329       if (sdest(*sface) == edest) {
05330         // Edge is found, return.
05331         return;
05332       }
05333     } else {
05334       if (sorg(*sface) == edest) {
05335         if (sdest(*sface) == eorg) {
05336           // Edge is found, inverse the direction and return.
05337           sesymself(*sface);
05338           return;
05339         }
05340       }
05341     }
05342     senextself(*sface);
05343   }
05344   printf("Internalerror in findedge():  Unable to find an edge in subface.\n");
05345   internalerror();
05346 }
05347 
05349 //                                                                           //
05350 // findface()    Find the face has the given origin, destination and apex.   //
05351 //                                                                           //
05352 // On input, 'fface' is a handle which may contain the three corners or may  //
05353 // not or may be dead.  On return, it represents exactly the face with the   //
05354 // given origin, destination and apex.                                       //
05355 //                                                                           //
05357 
05358 void tetgenmesh::findface(triface *fface, point forg, point fdest, point fapex)
05359 {
05360   triface spintet;
05361   enum finddirectionresult collinear;
05362   int hitbdry;
05363 
05364   if (!isdead(fface)) {
05365     // First check the easiest case, that 'fface' is just the right one.
05366     if (org(*fface) == forg && dest(*fface) == fdest &&
05367         apex(*fface) == fapex) return;
05368   } else {
05369     // The input handle is dead, use the 'recenttet' if it is alive.
05370     if (!isdead(&recenttet)) *fface = recenttet;
05371   }
05372 
05373   if (!isdead(fface)) {
05374     if (!findorg(fface, forg)) {
05375       // 'forg' is not a corner of 'fface', locate it.
05376       preciselocate(forg, fface, tetrahedrons->items);
05377     }
05378     // It is possible that forg is not found in a non-convex mesh.
05379     if (org(*fface) == forg) {
05380       collinear = finddirection(fface, fdest, tetrahedrons->items);
05381       if (collinear == RIGHTCOLLINEAR) {
05382         // fdest is just the destination.
05383       } else if (collinear == LEFTCOLLINEAR) {
05384         enext2self(*fface);
05385         esymself(*fface);
05386       } else if (collinear == TOPCOLLINEAR) {
05387         fnextself(*fface);
05388         enext2self(*fface);
05389         esymself(*fface);
05390       }
05391     }
05392     // It is possible taht fdest is not found in a non-convex mesh.
05393     if ((org(*fface) == forg) && (dest(*fface) == fdest)) {
05394       // Find the apex of 'fapex'.
05395       spintet = *fface;
05396       hitbdry = 0;
05397       do {
05398         if (apex(spintet) == fapex) {
05399           // We have done. Be careful the edge direction of 'spintet',
05400           //   it may reversed because of hitting boundary once.
05401           if (org(spintet) != org(*fface)) {
05402             esymself(spintet);
05403           }
05404           *fface = spintet;
05405           return;
05406         }
05407         if (!fnextself(spintet)) {
05408           hitbdry ++;
05409           if (hitbdry < 2) {
05410             esym(*fface, spintet);
05411             if (!fnextself(spintet)) {
05412               hitbdry ++;
05413             }
05414           }
05415         }
05416       } while (hitbdry < 2 && apex(spintet) != apex(*fface));
05417       // It is possible that fapex is not found in a non-convex mesh.
05418     }
05419   }
05420 
05421   if (isdead(fface) || (org(*fface) != forg) || (dest(*fface) != fdest) ||
05422       (apex(*fface) != fapex)) {
05423     // Too bad, the input handle is useless. We have to find a handle
05424     //   for 'fface' contains the 'forg' and 'fdest'. Here a brute force
05425     //   search is performed.
05426     if (b->verbose > 1) {
05427       printf("Warning in findface():  Perform a brute-force searching.\n");
05428     }
05429     enum verttype forgty, fdestty, fapexty;
05430     int share, i;
05431     forgty = pointtype(forg);
05432     fdestty = pointtype(fdest);
05433     fapexty = pointtype(fapex);
05434     setpointtype(forg, DEADVERTEX);
05435     setpointtype(fdest, DEADVERTEX);
05436     setpointtype(fapex, DEADVERTEX);
05437     tetrahedrons->traversalinit();
05438     fface->tet = tetrahedrontraverse();
05439     while (fface->tet != (tetrahedron *) NULL) {
05440       share = 0;
05441       for (i = 0; i < 4; i++) {
05442         if (pointtype((point) fface->tet[4 + i]) == DEADVERTEX) share ++;
05443       }
05444       if (share == 3) {
05445         // Found! Set the correct face and desired corners.
05446         if (pointtype((point) fface->tet[4]) != DEADVERTEX) {
05447           fface->loc = 2;
05448         } else if (pointtype((point) fface->tet[5]) != DEADVERTEX) {
05449           fface->loc = 3;
05450         } else if (pointtype((point) fface->tet[6]) != DEADVERTEX) {
05451           fface->loc = 1;
05452         } else { // pointtype((point) fface->tet[7]) != DEADVERTEX
05453           fface->loc = 0;
05454         }
05455         findedge(fface, forg, fdest);
05456         break;
05457       }
05458       fface->tet = tetrahedrontraverse();
05459     }
05460     setpointtype(forg, forgty);
05461     setpointtype(fdest, fdestty);
05462     setpointtype(fapex, fapexty);
05463     if (fface->tet == (tetrahedron *) NULL) {
05464       // It is impossible to reach here.
05465       printf("Internal error:  Fail to find the indicated face.\n");
05466       internalerror();
05467     }
05468   }
05469 }
05470 
05472 //                                                                           //
05473 // getonextseg()    Get the next SEGMENT counterclockwise with the same org. //
05474 //                                                                           //
05475 // 's' is a subface. This routine reteuns the segment which is counterclock- //
05476 // wise with the origin of s.                                                //
05477 //                                                                           //
05479 
05480 void tetgenmesh::getonextseg(face* s, face* lseg)
05481 {
05482   face checksh, checkseg;
05483   point forg;
05484 
05485   forg = sorg(*s);
05486   checksh = *s;
05487   do {
05488     // Go to the edge at forg's left side.
05489     senext2self(checksh);
05490     // Check if there is a segment attaching this edge.
05491     sspivot(checksh, checkseg);
05492     if (checkseg.sh != dummysh) break;
05493     // No segment! Go to the neighbor of this subface.
05494     spivotself(checksh);
05495 #ifdef SELF_CHECK
05496     // It should always meet a segment before come back.
05497     assert(checksh.sh != s->sh);
05498 #endif
05499     if (sorg(checksh) != forg) {
05500       sesymself(checksh);
05501 #ifdef SELF_CHECK
05502       assert(sorg(checksh) == forg);
05503 #endif
05504     }
05505   } while (true);
05506   if (sorg(checkseg) != forg) sesymself(checkseg);
05507   *lseg = checkseg;
05508 }
05509 
05511 //                                                                           //
05512 // getseghasorg()    Get the segment containing the given point.             //
05513 //                                                                           //
05514 // 'dorg' is an endpoint of a segment S. 'sseg' is a subsegment of S. This   //
05515 // routine search a subsegment (along sseg) of S containing dorg. On return, //
05516 // 'sseg' contains 'dorg' as its origin.                                     //
05517 //                                                                           //
05519 
05520 void tetgenmesh::getseghasorg(face* sseg, point dorg)
05521 {
05522   face nextseg;
05523   point checkpt;
05524 
05525   nextseg = *sseg;
05526   checkpt = sorg(nextseg);
05527   while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05528     // Search dorg along the original direction of sseg.
05529     senext2self(nextseg);
05530     spivotself(nextseg);
05531     nextseg.shver = 0;
05532     if (sdest(nextseg) != checkpt) sesymself(nextseg);
05533     checkpt = sorg(nextseg);
05534   }
05535   if (checkpt == dorg) {
05536     *sseg = nextseg;
05537     return;
05538   }
05539   nextseg = *sseg;
05540   checkpt = sdest(nextseg);
05541   while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05542     // Search dorg along the destinational direction of sseg.
05543     senextself(nextseg);
05544     spivotself(nextseg);
05545     nextseg.shver = 0;
05546     if (sorg(nextseg) != checkpt) sesymself(nextseg);
05547     checkpt = sdest(nextseg);
05548   }
05549   if (checkpt == dorg) {
05550     sesym(nextseg, *sseg);
05551     return;
05552   }
05553   // Should never be here.
05554   printf("Internalerror in getseghasorg():  Unable to find the subseg.\n");
05555   internalerror();
05556 }
05557 
05559 //                                                                           //
05560 // getsubsegfarorg()    Get the origin of the parent segment of a subseg.    //
05561 //                                                                           //
05563 
05564 tetgenmesh::point tetgenmesh::getsubsegfarorg(face* sseg)
05565 {
05566   face prevseg;
05567   point checkpt;
05568 
05569   checkpt = sorg(*sseg);
05570   senext2(*sseg, prevseg);
05571   spivotself(prevseg);
05572   // Search dorg along the original direction of sseg.
05573   while (prevseg.sh != dummysh) {
05574     prevseg.shver = 0;
05575     if (sdest(prevseg) != checkpt) sesymself(prevseg);
05576     checkpt = sorg(prevseg);
05577     senext2self(prevseg);
05578     spivotself(prevseg);
05579   }
05580   return checkpt;
05581 }
05582 
05584 //                                                                           //
05585 // getsubsegfardest()    Get the dest. of the parent segment of a subseg.    //
05586 //                                                                           //
05588 
05589 tetgenmesh::point tetgenmesh::getsubsegfardest(face* sseg)
05590 {
05591   face nextseg;
05592   point checkpt;
05593 
05594   checkpt = sdest(*sseg);
05595   senext(*sseg, nextseg);
05596   spivotself(nextseg);
05597   // Search dorg along the destinational direction of sseg.
05598   while (nextseg.sh != dummysh) {
05599     nextseg.shver = 0;
05600     if (sorg(nextseg) != checkpt) sesymself(nextseg);
05601     checkpt = sdest(nextseg);
05602     senextself(nextseg);
05603     spivotself(nextseg);
05604   }
05605   return checkpt;
05606 }
05607 
05609 //                                                                           //
05610 // printtet()    Print out the details of a tetrahedron on screen.           //
05611 //                                                                           //
05612 // It's also used when the highest level of verbosity (`-VVV') is specified. //
05613 //                                                                           //
05615 
05616 void tetgenmesh::printtet(triface* tface)
05617 {
05618   triface tmpface, prtface;
05619   point tmppt;
05620   face tmpsh;
05621   int facecount;
05622 
05623   printf("Tetra x%lx with loc(%i) and ver(%i):",
05624          (unsigned long)(tface->tet), tface->loc, tface->ver);
05625   if (infected(*tface)) {
05626     printf(" (infected)");
05627   }
05628   printf("\n");
05629 
05630   tmpface = *tface;
05631   facecount = 0;
05632   while(facecount < 4) {
05633     tmpface.loc = facecount;
05634     sym(tmpface, prtface);
05635     if(prtface.tet == dummytet) {
05636       printf("      [%i] Outer space.\n", facecount);
05637     } else {
05638       printf("      [%i] x%lx  loc(%i).", facecount,
05639              (unsigned long)(prtface.tet), prtface.loc);
05640       if (infected(prtface)) {
05641         printf(" (infected)");
05642       }
05643       printf("\n");
05644     }
05645     facecount ++;
05646   }
05647 
05648   tmppt = org(*tface);
05649   if(tmppt == (point) NULL) {
05650     printf("      Org [%i] NULL\n", locver2org[tface->loc][tface->ver]);
05651   } else {
05652     printf("      Org [%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05653            locver2org[tface->loc][tface->ver], (unsigned long)(tmppt),
05654            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05655   }
05656   tmppt = dest(*tface);
05657   if(tmppt == (point) NULL) {
05658     printf("      Dest[%i] NULL\n", locver2dest[tface->loc][tface->ver]);
05659   } else {
05660     printf("      Dest[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05661            locver2dest[tface->loc][tface->ver], (unsigned long)(tmppt),
05662            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05663   }
05664   tmppt = apex(*tface);
05665   if(tmppt == (point) NULL) {
05666     printf("      Apex[%i] NULL\n", locver2apex[tface->loc][tface->ver]);
05667   } else {
05668     printf("      Apex[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05669            locver2apex[tface->loc][tface->ver], (unsigned long)(tmppt),
05670            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05671   }
05672   tmppt = oppo(*tface);
05673   if(tmppt == (point) NULL) {
05674     printf("      Oppo[%i] NULL\n", loc2oppo[tface->loc]);
05675   } else {
05676     printf("      Oppo[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05677            loc2oppo[tface->loc], (unsigned long)(tmppt),
05678            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05679   }
05680 
05681   if (b->useshelles) {
05682     tmpface = *tface;
05683     facecount = 0;
05684     while(facecount < 6) {
05685       tmpface.loc = facecount;
05686       tspivot(tmpface, tmpsh);
05687       if(tmpsh.sh != dummysh) {
05688         printf("      [%i] x%lx  ID(%i) ", facecount,
05689                (unsigned long)(tmpsh.sh), shellmark(tmpsh));
05690         if (sorg(tmpsh) == (point) NULL) {
05691           printf("(fake)");
05692         }
05693         printf("\n");
05694       }
05695       facecount ++;
05696     }
05697   }
05698 }
05699 
05701 //                                                                           //
05702 // printsh()    Print out the details of a subface or subsegment on screen.  //
05703 //                                                                           //
05704 // It's also used when the highest level of verbosity (`-VVV') is specified. //
05705 //                                                                           //
05707 
05708 void tetgenmesh::printsh(face* sface)
05709 {
05710   face prtsh;
05711   triface prttet;
05712   point printpoint;
05713 
05714   if (sapex(*sface) != NULL) {
05715     printf("subface x%lx, ver %d, mark %d:",
05716            (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05717   } else {
05718     printf("Subsegment x%lx, ver %d, mark %d:",
05719            (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05720   }
05721   if (sinfected(*sface)) {
05722     printf(" (infected)");
05723   }
05724   if (shell2badface(*sface)) {
05725     printf(" (queued)");
05726   }
05727   if (sapex(*sface) != NULL) {
05728     if (shelltype(*sface) == SHARP) {
05729       printf(" (sharp)");
05730     }
05731   } else {
05732     if (shelltype(*sface) == SHARP) {
05733       printf(" (sharp)");
05734     }
05735   }
05736   if (checkpbcs) {
05737     if (shellpbcgroup(*sface) >= 0) {
05738       printf(" (pbc %d)", shellpbcgroup(*sface));
05739     }
05740   }
05741   printf("\n");
05742 
05743   sdecode(sface->sh[0], prtsh);
05744   if (prtsh.sh == dummysh) {
05745     printf("      [0] = No shell\n");
05746   } else {
05747     printf("      [0] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05748   }
05749   sdecode(sface->sh[1], prtsh);
05750   if (prtsh.sh == dummysh) {
05751     printf("      [1] = No shell\n");
05752   } else {
05753     printf("      [1] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05754   }
05755   sdecode(sface->sh[2], prtsh);
05756   if (prtsh.sh == dummysh) {
05757     printf("      [2] = No shell\n");
05758   } else {
05759     printf("      [2] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05760   }
05761 
05762   printpoint = sorg(*sface);
05763   if (printpoint == (point) NULL)
05764     printf("      Org [%d] = NULL\n", vo[sface->shver]);
05765   else
05766     printf("      Org [%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05767            vo[sface->shver], (unsigned long)(printpoint), printpoint[0],
05768            printpoint[1], printpoint[2], pointmark(printpoint));
05769   printpoint = sdest(*sface);
05770   if (printpoint == (point) NULL)
05771     printf("      Dest[%d] = NULL\n", vd[sface->shver]);
05772   else
05773     printf("      Dest[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05774             vd[sface->shver], (unsigned long)(printpoint), printpoint[0],
05775             printpoint[1], printpoint[2], pointmark(printpoint));
05776 
05777   if (sapex(*sface) != NULL) {
05778     printpoint = sapex(*sface);
05779     if (printpoint == (point) NULL)
05780       printf("      Apex[%d] = NULL\n", va[sface->shver]);
05781     else
05782       printf("      Apex[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05783              va[sface->shver], (unsigned long)(printpoint), printpoint[0],
05784              printpoint[1], printpoint[2], pointmark(printpoint));
05785 
05786     decode(sface->sh[6], prttet);
05787     if (prttet.tet == dummytet) {
05788       printf("      [6] = Outer space\n");
05789     } else {
05790       printf("      [6] = x%lx  %d\n",
05791              (unsigned long)(prttet.tet), prttet.loc);
05792     }
05793     decode(sface->sh[7], prttet);
05794     if (prttet.tet == dummytet) {
05795       printf("      [7] = Outer space\n");
05796     } else {
05797       printf("      [7] = x%lx  %d\n",
05798              (unsigned long)(prttet.tet), prttet.loc);
05799     }
05800 
05801     sdecode(sface->sh[8], prtsh);
05802     if (prtsh.sh == dummysh) {
05803       printf("      [8] = No subsegment\n");
05804     } else {
05805       printf("      [8] = x%lx  %d\n",
05806              (unsigned long)(prtsh.sh), prtsh.shver);
05807     }
05808     sdecode(sface->sh[9], prtsh);
05809     if (prtsh.sh == dummysh) {
05810       printf("      [9] = No subsegment\n");
05811     } else {
05812       printf("      [9] = x%lx  %d\n",
05813              (unsigned long)(prtsh.sh), prtsh.shver);
05814     }
05815     sdecode(sface->sh[10], prtsh);
05816     if (prtsh.sh == dummysh) {
05817       printf("      [10]= No subsegment\n");
05818     } else {
05819       printf("      [10]= x%lx  %d\n",
05820              (unsigned long)(prtsh.sh), prtsh.shver);
05821     }
05822   }
05823 }
05824 
05825 //
05826 // End of advanced primitives
05827 //
05828 
05829 //
05830 // End of mesh manipulation primitives
05831 //
05832 
05833 //
05834 // Begin of mesh items searching routines
05835 //
05836 
05838 //                                                                           //
05839 // makepoint2tetmap()    Construct a mapping from points to tetrahedra.      //
05840 //                                                                           //
05841 // Traverses all the tetrahedra,  provides each corner of each tetrahedron   //
05842 // with a pointer to that tetrahedera.  Some pointers will be overwritten by //
05843 // other pointers because each point may be a corner of several tetrahedra,  //
05844 // but in the end every point will point to a tetrahedron that contains it.  //
05845 //                                                                           //
05847 
05848 void tetgenmesh::makepoint2tetmap()
05849 {
05850   triface tetloop;
05851   point pointptr;
05852 
05853   if (b->verbose > 0) {
05854     printf("  Constructing mapping from points to tetrahedra.\n");
05855   }
05856 
05857   // Initialize the point2tet field of each point.
05858   points->traversalinit();
05859   pointptr = pointtraverse();
05860   while (pointptr != (point) NULL) {
05861     setpoint2tet(pointptr, (tetrahedron) NULL);
05862     pointptr = pointtraverse();
05863   }
05864 
05865   tetrahedrons->traversalinit();
05866   tetloop.tet = tetrahedrontraverse();
05867   while (tetloop.tet != (tetrahedron *) NULL) {
05868     // Check all four points of the tetrahedron.
05869     tetloop.loc = 0;
05870     pointptr = org(tetloop);
05871     setpoint2tet(pointptr, encode(tetloop));
05872     pointptr = dest(tetloop);
05873     setpoint2tet(pointptr, encode(tetloop));
05874     pointptr = apex(tetloop);
05875     setpoint2tet(pointptr, encode(tetloop));
05876     pointptr = oppo(tetloop);
05877     setpoint2tet(pointptr, encode(tetloop));
05878     // Get the next tetrahedron in the list.
05879     tetloop.tet = tetrahedrontraverse();
05880   }
05881 }
05882 
05884 //                                                                           //
05885 // makeindex2pointmap()    Create a map from index to vertices.              //
05886 //                                                                           //
05887 // 'idx2verlist' returns the created map.  Traverse all vertices, a pointer  //
05888 // to each vertex is set into the array.  The pointer to the first vertex is //
05889 // saved in 'idx2verlist[0]'.  Don't forget to minus 'in->firstnumber' when  //
05890 // to get the vertex form its index.                                         //
05891 //                                                                           //
05893 
05894 void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
05895 {
05896   point pointloop;
05897   int idx;
05898 
05899   if (b->verbose > 0) {
05900     printf("  Constructing mapping from indices to points.\n");
05901   }
05902 
05903   idx2verlist = new point[points->items];
05904 
05905   points->traversalinit();
05906   pointloop = pointtraverse();
05907   idx = 0;
05908   while (pointloop != (point) NULL) {
05909     idx2verlist[idx] = pointloop;
05910     idx++;
05911     pointloop = pointtraverse();
05912   }
05913 }
05914 
05916 //                                                                           //
05917 // makesegmentmap()    Create a map from vertices (their indices) to         //
05918 //                     segments incident at the same vertices.               //
05919 //                                                                           //
05920 // Two arrays 'idx2seglist' and 'segsperverlist' together return the map.    //
05921 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
05922 // number of segments.  idx2seglist contains row information and             //
05923 // segsperverlist contains all (non-zero) elements.  The i-th entry of       //
05924 // idx2seglist is the starting position of i-th row's (non-zero) elements in //
05925 // segsperverlist.  The number of elements of i-th row is calculated by the  //
05926 // (i+1)-th entry minus i-th entry of idx2seglist.                           //
05927 //                                                                           //
05928 // NOTE: These two arrays will be created inside this routine, don't forget  //
05929 // to free them after using.                                                 //
05930 //                                                                           //
05932 
05933 void tetgenmesh::makesegmentmap(int*& idx2seglist, shellface**& segsperverlist)
05934 {
05935   shellface *shloop;
05936   int i, j, k;
05937 
05938   if (b->verbose > 0) {
05939     printf("  Constructing mapping from points to segments.\n");
05940   }
05941 
05942   // Create and initialize 'idx2seglist'.
05943   idx2seglist = new int[points->items + 1];
05944   for (i = 0; i < points->items + 1; i++) idx2seglist[i] = 0;
05945 
05946   // Loop the set of segments once, counter the number of segments sharing
05947   //   each vertex.
05948   subsegs->traversalinit();
05949   shloop = shellfacetraverse(subsegs);
05950   while (shloop != (shellface *) NULL) {
05951     // Increment the number of sharing segments for each endpoint.
05952     for (i = 0; i < 2; i++) {
05953       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05954       idx2seglist[j]++;
05955     }
05956     shloop = shellfacetraverse(subsegs);
05957   }
05958 
05959   // Calculate the total length of array 'facesperverlist'.
05960   j = idx2seglist[0];
05961   idx2seglist[0] = 0;  // Array starts from 0 element.
05962   for (i = 0; i < points->items; i++) {
05963     k = idx2seglist[i + 1];
05964     idx2seglist[i + 1] = idx2seglist[i] + j;
05965     j = k;
05966   }
05967   // The total length is in the last unit of idx2seglist.
05968   segsperverlist = new shellface*[idx2seglist[i]];
05969   // Loop the set of segments again, set the info. of segments per vertex.
05970   subsegs->traversalinit();
05971   shloop = shellfacetraverse(subsegs);
05972   while (shloop != (shellface *) NULL) {
05973     for (i = 0; i < 2; i++) {
05974       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05975       segsperverlist[idx2seglist[j]] = shloop;
05976       idx2seglist[j]++;
05977     }
05978     shloop = shellfacetraverse(subsegs);
05979   }
05980   // Contents in 'idx2seglist' are shifted, now shift them back.
05981   for (i = points->items - 1; i >= 0; i--) {
05982     idx2seglist[i + 1] = idx2seglist[i];
05983   }
05984   idx2seglist[0] = 0;
05985 }
05986 
05988 //                                                                           //
05989 // makesubfacemap()    Create a map from vertices (their indices) to         //
05990 //                     subfaces incident at the same vertices.               //
05991 //                                                                           //
05992 // Two arrays 'idx2facelist' and 'facesperverlist' together return the map.  //
05993 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
05994 // number of subfaces.  idx2facelist contains row information and            //
05995 // facesperverlist contains all (non-zero) elements.  The i-th entry of      //
05996 // idx2facelist is the starting position of i-th row's(non-zero) elements in //
05997 // facesperverlist.  The number of elements of i-th row is calculated by the //
05998 // (i+1)-th entry minus i-th entry of idx2facelist.                          //
05999 //                                                                           //
06000 // NOTE: These two arrays will be created inside this routine, don't forget  //
06001 // to free them after using.                                                 //
06002 //                                                                           //
06004 
06005 void tetgenmesh::
06006 makesubfacemap(int*& idx2facelist, shellface**& facesperverlist)
06007 {
06008   shellface *shloop;
06009   int i, j, k;
06010 
06011   if (b->verbose > 0) {
06012     printf("  Constructing mapping from points to subfaces.\n");
06013   }
06014 
06015   // Create and initialize 'idx2facelist'.
06016   idx2facelist = new int[points->items + 1];
06017   for (i = 0; i < points->items + 1; i++) idx2facelist[i] = 0;
06018 
06019   // Loop the set of subfaces once, counter the number of subfaces sharing
06020   //   each vertex.
06021   subfaces->traversalinit();
06022   shloop = shellfacetraverse(subfaces);
06023   while (shloop != (shellface *) NULL) {
06024     // Increment the number of sharing segments for each endpoint.
06025     for (i = 0; i < 3; i++) {
06026       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06027       idx2facelist[j]++;
06028     }
06029     shloop = shellfacetraverse(subfaces);
06030   }
06031 
06032   // Calculate the total length of array 'facesperverlist'.
06033   j = idx2facelist[0];
06034   idx2facelist[0] = 0;  // Array starts from 0 element.
06035   for (i = 0; i < points->items; i++) {
06036     k = idx2facelist[i + 1];
06037     idx2facelist[i + 1] = idx2facelist[i] + j;
06038     j = k;
06039   }
06040   // The total length is in the last unit of idx2facelist.
06041   facesperverlist = new shellface*[idx2facelist[i]];
06042   // Loop the set of segments again, set the info. of segments per vertex.
06043   subfaces->traversalinit();
06044   shloop = shellfacetraverse(subfaces);
06045   while (shloop != (shellface *) NULL) {
06046     for (i = 0; i < 3; i++) {
06047       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06048       facesperverlist[idx2facelist[j]] = shloop;
06049       idx2facelist[j]++;
06050     }
06051     shloop = shellfacetraverse(subfaces);
06052   }
06053   // Contents in 'idx2facelist' are shifted, now shift them back.
06054   for (i = points->items - 1; i >= 0; i--) {
06055     idx2facelist[i + 1] = idx2facelist[i];
06056   }
06057   idx2facelist[0] = 0;
06058 }
06059 
06061 //                                                                           //
06062 // maketetrahedronmap()    Create a map from vertices (their indices) to     //
06063 //                         tetrahedra incident at the same vertices.         //
06064 //                                                                           //
06065 // Two arrays 'idx2tetlist' and 'tetsperverlist' together return the map.    //
06066 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
06067 // number of tetrahedra.  idx2tetlist contains row information and           //
06068 // tetsperverlist contains all (non-zero) elements.  The i-th entry of       //
06069 // idx2tetlist is the starting position of i-th row's (non-zero) elements in //
06070 // tetsperverlist.  The number of elements of i-th row is calculated by the  //
06071 // (i+1)-th entry minus i-th entry of idx2tetlist.                           //
06072 //                                                                           //
06073 // NOTE: These two arrays will be created inside this routine, don't forget  //
06074 // to free them after using.                                                 //
06075 //                                                                           //
06077 
06078 void tetgenmesh::
06079 maketetrahedronmap(int*& idx2tetlist, tetrahedron**& tetsperverlist)
06080 {
06081   tetrahedron *tetloop;
06082   int i, j, k;
06083 
06084   if (b->verbose > 0) {
06085     printf("  Constructing mapping from points to tetrahedra.\n");
06086   }
06087 
06088   // Create and initialize 'idx2tetlist'.
06089   idx2tetlist = new int[points->items + 1];
06090   for (i = 0; i < points->items + 1; i++) idx2tetlist[i] = 0;
06091 
06092   // Loop the set of tetrahedra once, counter the number of tetrahedra
06093   //   sharing each vertex.
06094   tetrahedrons->traversalinit();
06095   tetloop = tetrahedrontraverse();
06096   while (tetloop != (tetrahedron *) NULL) {
06097     // Increment the number of sharing tetrahedra for each endpoint.
06098     for (i = 0; i < 4; i++) {
06099       j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06100       idx2tetlist[j]++;
06101     }
06102     tetloop = tetrahedrontraverse();
06103   }
06104 
06105   // Calculate the total length of array 'tetsperverlist'.
06106   j = idx2tetlist[0];
06107   idx2tetlist[0] = 0;  // Array starts from 0 element.
06108   for (i = 0; i < points->items; i++) {
06109     k = idx2tetlist[i + 1];
06110     idx2tetlist[i + 1] = idx2tetlist[i] + j;
06111     j = k;
06112   }
06113   // The total length is in the last unit of idx2tetlist.
06114   tetsperverlist = new tetrahedron*[idx2tetlist[i]];
06115   // Loop the set of tetrahedra again, set the info. of tet. per vertex.
06116   tetrahedrons->traversalinit();
06117   tetloop = tetrahedrontraverse();
06118   while (tetloop != (tetrahedron *) NULL) {
06119     for (i = 0; i < 4; i++) {
06120       j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06121       tetsperverlist[idx2tetlist[j]] = tetloop;
06122       idx2tetlist[j]++;
06123     }
06124     tetloop = tetrahedrontraverse();
06125   }
06126   // Contents in 'idx2tetlist' are shifted, now shift them back.
06127   for (i = points->items - 1; i >= 0; i--) {
06128     idx2tetlist[i + 1] = idx2tetlist[i];
06129   }
06130   idx2tetlist[0] = 0;
06131 }
06132 
06133 //
06134 // End of mesh items searching routines
06135 //
06136 
06137 //
06138 // Begin of linear algebra functions
06139 //
06140 
06141 // dot() returns the dot product: v1 dot v2.
06142 
06143 inline REAL tetgenmesh::dot(REAL* v1, REAL* v2)
06144 {
06145   return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
06146 }
06147 
06148 // cross() computes the cross product: n = v1 cross v2.
06149 
06150 inline void tetgenmesh::cross(REAL* v1, REAL* v2, REAL* n)
06151 {
06152   n[0] =   v1[1] * v2[2] - v2[1] * v1[2];
06153   n[1] = -(v1[0] * v2[2] - v2[0] * v1[2]);
06154   n[2] =   v1[0] * v2[1] - v2[0] * v1[1];
06155 }
06156 
06157 // initm44() initializes a 4x4 matrix.
06158 static void initm44(REAL a00, REAL a01, REAL a02, REAL a03,
06159                     REAL a10, REAL a11, REAL a12, REAL a13,
06160                     REAL a20, REAL a21, REAL a22, REAL a23,
06161                     REAL a30, REAL a31, REAL a32, REAL a33,
06162                     REAL M[4][4])
06163 {
06164   M[0][0] = a00; M[0][1] = a01; M[0][2] = a02; M[0][3] = a03;
06165   M[1][0] = a10; M[1][1] = a11; M[1][2] = a12; M[1][3] = a13;
06166   M[2][0] = a20; M[2][1] = a21; M[2][2] = a22; M[2][3] = a23;
06167   M[3][0] = a30; M[3][1] = a31; M[3][2] = a32; M[3][3] = a33;
06168 }
06169 
06170 // m4xm4() multiplies 2 4x4 matrics:  m1 = m1 * m2.
06171 static void m4xm4(REAL m1[4][4], REAL m2[4][4])
06172 {
06173   REAL tmp[4];
06174   int i, j;
06175 
06176   for (i = 0; i < 4; i++) {   // i-th row
06177     for (j = 0; j < 4; j++) { // j-th col
06178       tmp[j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j]
06179              + m1[i][2] * m2[2][j] + m1[i][3] * m2[3][j];
06180     }
06181     for (j = 0; j < 4; j++)
06182       m1[i][j] = tmp[j];
06183   }
06184 }
06185 
06186 // m4xv4() multiplies a 4x4 matrix and 4x1 vector: v2 = m * v1
06187 static void m4xv4(REAL v2[4], REAL m[4][4], REAL v1[4])
06188 {
06189   v2[0] = m[0][0]*v1[0] + m[0][1]*v1[1] + m[0][2]*v1[2] + m[0][3]*v1[3];
06190   v2[1] = m[1][0]*v1[0] + m[1][1]*v1[1] + m[1][2]*v1[2] + m[1][3]*v1[3];
06191   v2[2] = m[2][0]*v1[0] + m[2][1]*v1[1] + m[2][2]*v1[2] + m[2][3]*v1[3];
06192   v2[3] = m[3][0]*v1[0] + m[3][1]*v1[1] + m[3][2]*v1[2] + m[3][3]*v1[3];
06193 }
06194 
06196 //                                                                           //
06197 // lu_decmp()    Compute the LU decomposition of a matrix.                   //
06198 //                                                                           //
06199 // Compute the LU decomposition of a (non-singular) square matrix A using    //
06200 // partial pivoting and implicit row exchanges.  The result is:              //
06201 //     A = P * L * U,                                                        //
06202 // where P is a permutation matrix, L is unit lower triangular, and U is     //
06203 // upper triangular.  The factored form of A is used in combination with     //
06204 // 'lu_solve()' to solve linear equations: Ax = b, or invert a matrix.       //
06205 //                                                                           //
06206 // The inputs are a square matrix 'lu[N..n+N-1][N..n+N-1]', it's size is 'n'.//
06207 // On output, 'lu' is replaced by the LU decomposition of a rowwise permuta- //
06208 // tion of itself, 'ps[N..n+N-1]' is an output vector that records the row   //
06209 // permutation effected by the partial pivoting, effectively,  'ps' array    //
06210 // tells the user what the permutation matrix P is; 'd' is output as +1/-1   //
06211 // depending on whether the number of row interchanges was even or odd,      //
06212 // respectively.                                                             //
06213 //                                                                           //
06214 // Return true if the LU decomposition is successfully computed, otherwise,  //
06215 // return false in case that A is a singular matrix.                         //
06216 //                                                                           //
06218 
06219 bool tetgenmesh::lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N)
06220 {
06221   REAL scales[4];
06222   REAL pivot, biggest, mult, tempf;
06223   int pivotindex = 0;
06224   int i, j, k;
06225 
06226   *d = 1.0;                                      // No row interchanges yet.
06227 
06228   for (i = N; i < n + N; i++) {                             // For each row.
06229     // Find the largest element in each row for row equilibration
06230     biggest = 0.0;
06231     for (j = N; j < n + N; j++)
06232       if (biggest < (tempf = fabs(lu[i][j])))
06233         biggest  = tempf;
06234     if (biggest != 0.0)
06235       scales[i] = 1.0 / biggest;
06236     else {
06237       scales[i] = 0.0;
06238       return false;                            // Zero row: singular matrix.
06239     }
06240     ps[i] = i;                                 // Initialize pivot sequence.
06241   }
06242 
06243   for (k = N; k < n + N - 1; k++) {                      // For each column.
06244     // Find the largest element in each column to pivot around.
06245     biggest = 0.0;
06246     for (i = k; i < n + N; i++) {
06247       if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
06248         biggest = tempf;
06249         pivotindex = i;
06250       }
06251     }
06252     if (biggest == 0.0) {
06253       return false;                         // Zero column: singular matrix.
06254     }
06255     if (pivotindex != k) {                         // Update pivot sequence.
06256       j = ps[k];
06257       ps[k] = ps[pivotindex];
06258       ps[pivotindex] = j;
06259       *d = -(*d);                          // ...and change the parity of d.
06260     }
06261 
06262     // Pivot, eliminating an extra variable  each time
06263     pivot = lu[ps[k]][k];
06264     for (i = k + 1; i < n + N; i++) {
06265       lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
06266       if (mult != 0.0) {
06267         for (j = k + 1; j < n + N; j++)
06268           lu[ps[i]][j] -= mult * lu[ps[k]][j];
06269       }
06270     }
06271   }
06272 
06273   // (lu[ps[n + N - 1]][n + N - 1] == 0.0) ==> A is singular.
06274   return lu[ps[n + N - 1]][n + N - 1] != 0.0;
06275 }
06276 
06278 //                                                                           //
06279 // lu_solve()    Solves the linear equation:  Ax = b,  after the matrix A    //
06280 //               has been decomposed into the lower and upper triangular     //
06281 //               matrices L and U, where A = LU.                             //
06282 //                                                                           //
06283 // 'lu[N..n+N-1][N..n+N-1]' is input, not as the matrix 'A' but rather as    //
06284 // its LU decomposition, computed by the routine 'lu_decmp'; 'ps[N..n+N-1]'  //
06285 // is input as the permutation vector returned by 'lu_decmp';  'b[N..n+N-1]' //
06286 // is input as the right-hand side vector, and returns with the solution     //
06287 // vector. 'lu', 'n', and 'ps' are not modified by this routine and can be   //
06288 // left in place for successive calls with different right-hand sides 'b'.   //
06289 //                                                                           //
06291 
06292 void tetgenmesh::lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N)
06293 {
06294   int i, j;
06295   REAL X[4], dot;
06296 
06297   for (i = N; i < n + N; i++) X[i] = 0.0;
06298 
06299   // Vector reduction using U triangular matrix.
06300   for (i = N; i < n + N; i++) {
06301     dot = 0.0;
06302     for (j = N; j < i + N; j++)
06303       dot += lu[ps[i]][j] * X[j];
06304     X[i] = b[ps[i]] - dot;
06305   }
06306 
06307   // Back substitution, in L triangular matrix.
06308   for (i = n + N - 1; i >= N; i--) {
06309     dot = 0.0;
06310     for (j = i + 1; j < n + N; j++)
06311       dot += lu[ps[i]][j] * X[j];
06312     X[i] = (X[i] - dot) / lu[ps[i]][i];
06313   }
06314 
06315   for (i = N; i < n + N; i++) b[i] = X[i];
06316 }
06317 
06318 //
06319 // End of linear algebra functions
06320 //
06321 
06322 //
06323 // Begin of geometric tests
06324 //
06325 
06326 // All the following routines require the input objects are not degenerate.
06327 //   i.e., a triangle must has three non-collinear corners; an edge must
06328 //   has two identical endpoints.  Degenerate cases should have to detect
06329 //   first and then handled as special cases.
06330 
06332 //                                                                           //
06333 // edge_vert_col_inter()    Test whether an edge (ab) and a collinear vertex //
06334 //                          (p) are intersecting or not.                     //
06335 //                                                                           //
06336 // Possible cases are p is coincident to a (p = a), or to b (p = b), or p is //
06337 // inside ab (a < p < b), or outside ab (p < a or p > b). These cases can be //
06338 // quickly determined by comparing the corresponding coords of a, b, and p   //
06339 // (which are not all equal).                                                //
06340 //                                                                           //
06341 // The return value indicates one of the three cases: DISJOINT, SHAREVERTEX  //
06342 // (p = a or p = b), and INTERSECT (a < p < b).                              //
06343 //                                                                           //
06345 
06346 enum tetgenmesh::interresult tetgenmesh::edge_vert_col_inter(REAL* A, REAL* B,
06347   REAL* P)
06348 {
06349   int i = 0;
06350   do {
06351     if (A[i] < B[i]) {
06352       if (P[i] < A[i]) {
06353         return DISJOINT;
06354       } else if (P[i] > A[i]) {
06355         if (P[i] < B[i]) {
06356           return INTERSECT;
06357         } else if (P[i] > B[i]) {
06358           return DISJOINT;
06359         } else {
06360           // assert(P[i] == B[i]);
06361           return SHAREVERTEX;
06362         }
06363       } else {
06364         // assert(P[i] == A[i]);
06365         return SHAREVERTEX;
06366       }
06367     } else if (A[i] > B[i]) {
06368       if (P[i] < B[i]) {
06369         return DISJOINT;
06370       } else if (P[i] > B[i]) {
06371         if (P[i] < A[i]) {
06372           return INTERSECT;
06373         } else if (P[i] > A[i]) {
06374           return DISJOINT;
06375         } else {
06376           // assert(P[i] == A[i]);
06377           return SHAREVERTEX;
06378         }
06379       } else {
06380         // assert(P[i] == B[i]);
06381         return SHAREVERTEX;
06382       }
06383     }
06384     // i-th coordinates are equal, try i+1-th;
06385     i++;
06386   } while (i < 3);
06387   // Should never be here.
06388   return DISJOINT;
06389 }
06390 
06392 //                                                                           //
06393 // edge_edge_cop_inter()    Test whether two coplanar edges (ab, and pq) are //
06394 //                          intersecting or not.                             //
06395 //                                                                           //
06396 // Possible cases are ab and pq are disjointed, or proper intersecting (int- //
06397 // ersect at a point other than their endpoints), or both collinear and int- //
06398 // ersecting, or sharing at a common endpoint, or are coincident.            //
06399 //                                                                           //
06400 // A reference point R is required, which is exactly not coplanar with these //
06401 // two edges.  Since the caller knows these two edges are coplanar, it must  //
06402 // be able to provide (or calculate) such a point.                           //
06403 //                                                                           //
06404 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06405 // SHAREEDGE, and INTERSECT.                                                 //
06406 //                                                                           //
06408 
06409 enum tetgenmesh::interresult tetgenmesh:: edge_edge_cop_inter(REAL* A, REAL* B,
06410   REAL* P, REAL* Q, REAL* R)
06411 {
06412   REAL s1, s2, s3, s4;
06413 
06414 #ifdef SELF_CHECK
06415   assert(R != NULL);
06416 #endif
06417   s1 = orient3d(A, B, R, P);
06418   s2 = orient3d(A, B, R, Q);
06419   if (s1 * s2 > 0.0) {
06420     // Both p and q are at the same side of ab.
06421     return DISJOINT;
06422   }
06423   s3 = orient3d(P, Q, R, A);
06424   s4 = orient3d(P, Q, R, B);
06425   if (s3 * s4 > 0.0) {
06426     // Both a and b are at the same side of pq.
06427     return DISJOINT;
06428   }
06429 
06430   // Possible degenerate cases are:
06431   //   (1) Only one of p and q is collinear with ab;
06432   //   (2) Both p and q are collinear with ab;
06433   //   (3) Only one of a and b is collinear with pq.
06434   enum interresult abp, abq;
06435   enum interresult pqa, pqb;
06436 
06437   if (s1 == 0.0) {
06438     // p is collinear with ab.
06439     abp = edge_vert_col_inter(A, B, P);
06440     if (abp == INTERSECT) {
06441       // p is inside ab.
06442       return INTERSECT;
06443     }
06444     if (s2 == 0.0) {
06445       // q is collinear with ab. Case (2).
06446       abq = edge_vert_col_inter(A, B, Q);
06447       if (abq == INTERSECT) {
06448         // q is inside ab.
06449         return INTERSECT;
06450       }
06451       if (abp == SHAREVERTEX && abq == SHAREVERTEX) {
06452         // ab and pq are identical.
06453         return SHAREEDGE;
06454       }
06455       pqa = edge_vert_col_inter(P, Q, A);
06456       if (pqa == INTERSECT) {
06457         // a is inside pq.
06458         return INTERSECT;
06459       }
06460       pqb = edge_vert_col_inter(P, Q, B);
06461       if (pqb == INTERSECT) {
06462         // b is inside pq.
06463         return INTERSECT;
06464       }
06465       if (abp == SHAREVERTEX || abq == SHAREVERTEX) {
06466         // either p or q is coincident with a or b.
06467 #ifdef SELF_CHECK
06468         // ONLY one case is possible, otherwise, shoule be SHAREEDGE.
06469         assert(abp ^ abq);
06470 #endif
06471         return SHAREVERTEX;
06472       }
06473       // The last case. They are disjointed.
06474 #ifdef SELF_CHECK
06475       assert((abp == DISJOINT) && (abp == abq && abq == pqa && pqa == pqb));
06476 #endif
06477       return DISJOINT;
06478     } else {
06479       // p is collinear with ab. Case (1).
06480 #ifdef SELF_CHECK
06481       assert(abp == SHAREVERTEX || abp == DISJOINT);
06482 #endif
06483       return abp;
06484     }
06485   }
06486   // p is NOT collinear with ab.
06487   if (s2 == 0.0) {
06488     // q is collinear with ab. Case (1).
06489     abq = edge_vert_col_inter(A, B, Q);
06490 #ifdef SELF_CHECK
06491     assert(abq == SHAREVERTEX || abq == DISJOINT || abq == INTERSECT);
06492 #endif
06493     return abq;
06494   }
06495 
06496   // We have found p and q are not collinear with ab. However, it is still
06497   //   possible that a or b is collinear with pq (ONLY one of a and b).
06498   if (s3 == 0.0) {
06499     // a is collinear with pq. Case (3).
06500 #ifdef SELF_CHECK
06501     assert(s4 != 0.0);
06502 #endif
06503     pqa = edge_vert_col_inter(P, Q, A);
06504 #ifdef SELF_CHECK
06505     // This case should have been detected in above.
06506     assert(pqa != SHAREVERTEX);
06507     assert(pqa == INTERSECT || pqa == DISJOINT);
06508 #endif
06509     return pqa;
06510   }
06511   if (s4 == 0.0) {
06512     // b is collinear with pq. Case (3).
06513 #ifdef SELF_CHECK
06514     assert(s3 != 0.0);
06515 #endif
06516     pqb = edge_vert_col_inter(P, Q, B);
06517 #ifdef SELF_CHECK
06518     // This case should have been detected in above.
06519     assert(pqb != SHAREVERTEX);
06520     assert(pqb == INTERSECT || pqb == DISJOINT);
06521 #endif
06522     return pqb;
06523   }
06524 
06525   // ab and pq are intersecting properly.
06526   return INTERSECT;
06527 }
06528 
06530 //                                                                           //
06531 // Notations                                                                 //
06532 //                                                                           //
06533 // Let ABC be the plane passes through a, b, and c;  ABC+ be the halfspace   //
06534 // including the set of all points x, such that orient3d(a, b, c, x) > 0;    //
06535 // ABC- be the other halfspace, such that for each point x in ABC-,          //
06536 // orient3d(a, b, c, x) < 0.  For the set of x which are on ABC, orient3d(a, //
06537 // b, c, x) = 0.                                                             //
06538 //                                                                           //
06540 
06542 //                                                                           //
06543 // tri_vert_copl_inter()    Test whether a triangle (abc) and a coplanar     //
06544 //                          point (p) are intersecting or not.               //
06545 //                                                                           //
06546 // Possible cases are p is inside abc, or on an edge of, or coincident with  //
06547 // a vertex of, or outside abc.                                              //
06548 //                                                                           //
06549 // A reference point R is required. R is exactly not coplanar with abc and p.//
06550 // Since the caller knows they are coplanar, it must be able to provide (or  //
06551 // calculate) such a point.                                                  //
06552 //                                                                           //
06553 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06554 // and INTERSECT.                                                            //
06555 //                                                                           //
06557 
06558 enum tetgenmesh::interresult tetgenmesh::tri_vert_cop_inter(REAL* A, REAL* B,
06559   REAL* C, REAL* P, REAL* R)
06560 {
06561   REAL s1, s2, s3;
06562   int sign;
06563 
06564 #ifdef SELF_CHECK
06565   assert(R != (REAL *) NULL);
06566 #endif
06567   // Adjust the orientation of a, b, c and r, so that we can assume that
06568   //   r is strictly in ABC- (i.e., r is above ABC wrt. right-hand rule).
06569   s1 = orient3d(A, B, C, R);
06570 #ifdef SELF_CHECK
06571   assert(s1 != 0.0);
06572 #endif
06573   sign = s1 < 0.0 ? 1 : -1;
06574 
06575   // Test starts from here.
06576   s1 = orient3d(A, B, R, P) * sign;
06577   if (s1 < 0.0) {
06578     // p is in ABR-.
06579     return DISJOINT;
06580   }
06581   s2 = orient3d(B, C, R, P) * sign;
06582   if (s2 < 0.0) {
06583     // p is in BCR-.
06584     return DISJOINT;
06585   }
06586   s3 = orient3d(C, A, R, P) * sign;
06587   if (s3 < 0.0) {
06588     // p is in CAR-.
06589     return DISJOINT;
06590   }
06591   if (s1 == 0.0) {
06592     // p is on ABR.
06593     if (s2 == 0.0) {
06594       // p is on BCR.
06595 #ifdef SELF_CHECK
06596       assert(s3 > 0.0);
06597 #endif
06598       // p is coincident with b.
06599       return SHAREVERTEX;
06600     }
06601     if (s3 == 0.0) {
06602       // p is on CAR.
06603       // p is coincident with a.
06604       return SHAREVERTEX;
06605     }
06606     // p is on edge ab.
06607     return INTERSECT;
06608   }
06609   // p is in ABR+.
06610   if (s2 == 0.0) {
06611     // p is on BCR.
06612     if (s3 == 0.0) {
06613       // p is on CAR.
06614       // p is coincident with c.
06615       return SHAREVERTEX;
06616     }
06617     // p is on edge bc.
06618     return INTERSECT;
06619   }
06620   if (s3 == 0.0) {
06621     // p is on CAR.
06622     // p is on edge ca.
06623     return INTERSECT;
06624   }
06625 
06626   // p is strictly inside abc.
06627   return INTERSECT;
06628 }
06629 
06631 //                                                                           //
06632 // tri_edge_cop_inter()    Test whether a triangle (abc) and a coplanar edge //
06633 //                         (pq) are intersecting or not.                     //
06634 //                                                                           //
06635 // A reference point R is required. R is exactly not coplanar with abc and   //
06636 // pq.  Since the caller knows they are coplanar, it must be able to provide //
06637 // (or calculate) such a point.                                              //
06638 //                                                                           //
06639 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06640 // SHAREEDGE, and INTERSECT.                                                 //
06641 //                                                                           //
06643 
06644 enum tetgenmesh::interresult tetgenmesh::tri_edge_cop_inter(REAL* A, REAL* B,
06645   REAL* C, REAL* P, REAL* Q, REAL* R)
06646 {
06647   enum interresult abpq, bcpq, capq;
06648   enum interresult abcp, abcq;
06649 
06650   // Test if pq is intersecting one of edges of abc.
06651   abpq = edge_edge_cop_inter(A, B, P, Q, R);
06652   if (abpq == INTERSECT || abpq == SHAREEDGE) {
06653     return abpq;
06654   }
06655   bcpq = edge_edge_cop_inter(B, C, P, Q, R);
06656   if (bcpq == INTERSECT || bcpq == SHAREEDGE) {
06657     return bcpq;
06658   }
06659   capq = edge_edge_cop_inter(C, A, P, Q, R);
06660   if (capq == INTERSECT || capq == SHAREEDGE) {
06661     return capq;
06662   }
06663 
06664   // Test if p and q is inside abc.
06665   abcp = tri_vert_cop_inter(A, B, C, P, R);
06666   if (abcp == INTERSECT) {
06667     return INTERSECT;
06668   }
06669   abcq = tri_vert_cop_inter(A, B, C, Q, R);
06670   if (abcq == INTERSECT) {
06671     return INTERSECT;
06672   }
06673 
06674   // Combine the test results of edge intersectings and triangle insides
06675   //   to detect whether abc and pq are sharing vertex or disjointed.
06676   if (abpq == SHAREVERTEX) {
06677     // p or q is coincident with a or b.
06678 #ifdef SELF_CHECK
06679     assert(abcp ^ abcq);
06680 #endif
06681     return SHAREVERTEX;
06682   }
06683   if (bcpq == SHAREVERTEX) {
06684     // p or q is coincident with b or c.
06685 #ifdef SELF_CHECK
06686     assert(abcp ^ abcq);
06687 #endif
06688     return SHAREVERTEX;
06689   }
06690   if (capq == SHAREVERTEX) {
06691     // p or q is coincident with c or a.
06692 #ifdef SELF_CHECK
06693     assert(abcp ^ abcq);
06694 #endif
06695     return SHAREVERTEX;
06696   }
06697 
06698   // They are disjointed.
06699   return DISJOINT;
06700 }
06701 
06703 //                                                                           //
06704 // tri_edge_inter_tail()    Test whether a triangle (abc) and an edge (pq)   //
06705 //                          are intersecting or not.                         //
06706 //                                                                           //
06707 // s1 and s2 are results of pre-performed orientation tests. s1 = orient3d(  //
06708 // a, b, c, p); s2 = orient3d(a, b, c, q).  To separate this routine from    //
06709 // tri_edge_inter() can save two orientation tests in tri_tri_inter().       //
06710 //                                                                           //
06711 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06712 // SHAREEDGE, and INTERSECT.                                                 //
06713 //                                                                           //
06715 
06716 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter_tail(REAL* A, REAL* B,
06717   REAL* C, REAL* P, REAL* Q, REAL s1, REAL s2)
06718 {
06719   REAL s3, s4, s5;
06720   int sign;
06721 
06722   if (s1 * s2 > 0.0) {
06723     // p, q are at the same halfspace of ABC, no intersection.
06724     return DISJOINT;
06725   }
06726 
06727   if (s1 * s2 < 0.0) {
06728     // p, q are both not on ABC (and not sharing vertices, edges of abc).
06729     // Adjust the orientation of a, b, c and p, so that we can assume that
06730     //   p is strictly in ABC-, and q is strictly in ABC+.
06731     sign = s1 < 0.0 ? 1 : -1;
06732     s3 = orient3d(A, B, P, Q) * sign;
06733     if (s3 < 0.0) {
06734       // q is at ABP-.
06735       return DISJOINT;
06736     }
06737     s4 = orient3d(B, C, P, Q) * sign;
06738     if (s4 < 0.0) {
06739       // q is at BCP-.
06740       return DISJOINT;
06741     }
06742     s5 = orient3d(C, A, P, Q) * sign;
06743     if (s5 < 0.0) {
06744       // q is at CAP-.
06745       return DISJOINT;
06746     }
06747     if (s3 == 0.0) {
06748       // q is on ABP.
06749       if (s4 == 0.0) {
06750         // q is on BCP (and q must in CAP+).
06751 #ifdef SELF_CHECK
06752         assert(s5 > 0.0);
06753 #endif
06754         // pq intersects abc at vertex b.
06755         return SHAREVERTEX;
06756       }
06757       if (s5 == 0.0) {
06758         // q is on CAP (and q must in BCP+).
06759         // pq intersects abc at vertex a.
06760         return SHAREVERTEX;
06761       }
06762       // q in both BCP+ and CAP+.
06763       // pq crosses ab properly.
06764       return INTERSECT;
06765     }
06766     // q is in ABP+;
06767     if (s4 == 0.0) {
06768       // q is on BCP.
06769       if (s5 == 0.0) {
06770         // q is on CAP.
06771         // pq intersects abc at vertex c.
06772         return SHAREVERTEX;
06773       }
06774       // pq crosses bc properly.
06775       return INTERSECT;
06776     }
06777     // q is in BCP+;
06778     if (s5 == 0.0) {
06779       // q is on CAP.
06780       // pq crosses ca properly.
06781       return INTERSECT;
06782     }
06783     // q is in CAP+;
06784     // pq crosses abc properly.
06785     return INTERSECT;
06786   }
06787 
06788   if (s1 != 0.0 || s2 != 0.0) {
06789     // Either p or q is coplanar with abc. ONLY one of them is possible.
06790     if (s1 == 0.0) {
06791       // p is coplanar with abc, q can be used as reference point.
06792 #ifdef SELF_CHECK
06793       assert(s2 != 0.0);
06794 #endif
06795       return tri_vert_cop_inter(A, B, C, P, Q);
06796     } else {
06797       // q is coplanar with abc, p can be used as reference point.
06798 #ifdef SELF_CHECK
06799       assert(s2 == 0.0);
06800 #endif
06801       return tri_vert_cop_inter(A, B, C, Q, P);
06802     }
06803   }
06804 
06805   // pq is coplanar with abc.  Calculate a point which is exactly not
06806   //   coplanar with a, b, and c.
06807   REAL R[3], N[3];
06808   REAL ax, ay, az, bx, by, bz;
06809 
06810   ax = A[0] - B[0];
06811   ay = A[1] - B[1];
06812   az = A[2] - B[2];
06813   bx = A[0] - C[0];
06814   by = A[1] - C[1];
06815   bz = A[2] - C[2];
06816   N[0] = ay * bz - by * az;
06817   N[1] = az * bx - bz * ax;
06818   N[2] = ax * by - bx * ay;
06819   // The normal should not be a zero vector (otherwise, abc are collinear).
06820 #ifdef SELF_CHECK
06821   assert((fabs(N[0]) + fabs(N[1]) + fabs(N[2])) > 0.0);
06822 #endif
06823   // The reference point R is lifted from A to the normal direction with
06824   //   a distance d = average edge length of the triangle abc.
06825   R[0] = N[0] + A[0];
06826   R[1] = N[1] + A[1];
06827   R[2] = N[2] + A[2];
06828   // Becareful the case: if the non-zero component(s) in N is smaller than
06829   //   the machine epsilon (i.e., 2^(-16) for double), R will exactly equal
06830   //   to A due to the round-off error.  Do check if it is.
06831   if (R[0] == A[0] && R[1] == A[1] && R[2] == A[2]) {
06832     int i, j;
06833     for (i = 0; i < 3; i++) {
06834 #ifdef SELF_CHECK
06835       assert (R[i] == A[i]);
06836 #endif
06837       j = 2;
06838       do {
06839         if (N[i] > 0.0) {
06840           N[i] += (j * macheps);
06841         } else {
06842           N[i] -= (j * macheps);
06843         }
06844         R[i] = N[i] + A[i];
06845         j *= 2;
06846       } while (R[i] == A[i]);
06847     }
06848   }
06849 
06850   return tri_edge_cop_inter(A, B, C, P, Q, R);
06851 }
06852 
06854 //                                                                           //
06855 // tri_edge_inter()    Test whether a triangle (abc) and an edge (pq) are    //
06856 //                     intersecting or not.                                  //
06857 //                                                                           //
06858 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06859 // SHAREEDGE, and INTERSECT.                                                 //
06860 //                                                                           //
06862 
06863 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter(REAL* A, REAL* B,
06864   REAL* C, REAL* P, REAL* Q)
06865 {
06866   REAL s1, s2;
06867 
06868   // Test the locations of p and q with respect to ABC.
06869   s1 = orient3d(A, B, C, P);
06870   s2 = orient3d(A, B, C, Q);
06871 
06872   return tri_edge_inter_tail(A, B, C, P, Q, s1, s2);
06873 }
06874 
06876 //                                                                           //
06877 // tri_tri_inter()    Test whether two triangle (abc) and (opq) are          //
06878 //                    intersecting or not.                                   //
06879 //                                                                           //
06880 // The return value indicates one of the five cases: DISJOINT, SHAREVERTEX,  //
06881 // SHAREEDGE, SHAREFACE, and INTERSECT.                                      //
06882 //                                                                           //
06884 
06885 enum tetgenmesh::interresult tetgenmesh::tri_tri_inter(REAL* A, REAL* B,
06886   REAL* C, REAL* O, REAL* P, REAL* Q)
06887 {
06888   REAL s_o, s_p, s_q;
06889   REAL s_a, s_b, s_c;
06890 
06891   s_o = orient3d(A, B, C, O);
06892   s_p = orient3d(A, B, C, P);
06893   s_q = orient3d(A, B, C, Q);
06894   if ((s_o * s_p > 0.0) && (s_o * s_q > 0.0)) {
06895     // o, p, q are all in the same halfspace of ABC.
06896     return DISJOINT;
06897   }
06898 
06899   s_a = orient3d(O, P, Q, A);
06900   s_b = orient3d(O, P, Q, B);
06901   s_c = orient3d(O, P, Q, C);
06902   if ((s_a * s_b > 0.0) && (s_a * s_c > 0.0)) {
06903     // a, b, c are all in the same halfspace of OPQ.
06904     return DISJOINT;
06905   }
06906 
06907   enum interresult abcop, abcpq, abcqo;
06908   int shareedge = 0;
06909 
06910   abcop = tri_edge_inter_tail(A, B, C, O, P, s_o, s_p);
06911   if (abcop == INTERSECT) {
06912     return INTERSECT;
06913   } else if (abcop == SHAREEDGE) {
06914     shareedge++;
06915   }
06916   abcpq = tri_edge_inter_tail(A, B, C, P, Q, s_p, s_q);
06917   if (abcpq == INTERSECT) {
06918     return INTERSECT;
06919   } else if (abcpq == SHAREEDGE) {
06920     shareedge++;
06921   }
06922   abcqo = tri_edge_inter_tail(A, B, C, Q, O, s_q, s_o);
06923   if (abcqo == INTERSECT) {
06924     return INTERSECT;
06925   } else if (abcqo == SHAREEDGE) {
06926     shareedge++;
06927   }
06928   if (shareedge == 3) {
06929     // opq are coincident with abc.
06930     return SHAREFACE;
06931   }
06932 #ifdef SELF_CHECK
06933   // It is only possible either no share edge or one.
06934   assert(shareedge == 0 || shareedge == 1);
06935 #endif
06936 
06937   // Continue to detect whether opq and abc are intersecting or not.
06938   enum interresult opqab, opqbc, opqca;
06939 
06940   opqab = tri_edge_inter_tail(O, P, Q, A, B, s_a, s_b);
06941   if (opqab == INTERSECT) {
06942     return INTERSECT;
06943   }
06944   opqbc = tri_edge_inter_tail(O, P, Q, B, C, s_b, s_c);
06945   if (opqbc == INTERSECT) {
06946     return INTERSECT;
06947   }
06948   opqca = tri_edge_inter_tail(O, P, Q, C, A, s_c, s_a);
06949   if (opqca == INTERSECT) {
06950     return INTERSECT;
06951   }
06952 
06953   // At this point, two triangles are not intersecting and not coincident.
06954   //   They may be share an edge, or share a vertex, or disjoint.
06955   if (abcop == SHAREEDGE) {
06956 #ifdef SELF_CHECK
06957     assert(abcpq == SHAREVERTEX && abcqo == SHAREVERTEX);
06958 #endif
06959     // op is coincident with an edge of abc.
06960     return SHAREEDGE;
06961   }
06962   if (abcpq == SHAREEDGE) {
06963 #ifdef SELF_CHECK
06964     assert(abcop == SHAREVERTEX && abcqo == SHAREVERTEX);
06965 #endif
06966     // pq is coincident with an edge of abc.
06967     return SHAREEDGE;
06968   }
06969   if (abcqo == SHAREEDGE) {
06970 #ifdef SELF_CHECK
06971     assert(abcop == SHAREVERTEX && abcpq == SHAREVERTEX);
06972 #endif
06973     // qo is coincident with an edge of abc.
06974     return SHAREEDGE;
06975   }
06976 
06977   // They may share a vertex or disjoint.
06978   if (abcop == SHAREVERTEX) {
06979     // o or p is coincident with a vertex of abc.
06980     if (abcpq == SHAREVERTEX) {
06981       // p is the coincident vertex.
06982 #ifdef SELF_CHECK
06983       assert(abcqo != SHAREVERTEX);
06984 #endif
06985     } else {
06986       // o is the coincident vertex.
06987 #ifdef SELF_CHECK
06988       assert(abcqo == SHAREVERTEX);
06989 #endif
06990     }
06991     return SHAREVERTEX;
06992   }
06993   if (abcpq == SHAREVERTEX) {
06994     // q is the coincident vertex.
06995 #ifdef SELF_CHECK
06996     assert(abcqo == SHAREVERTEX);
06997 #endif
06998     return SHAREVERTEX;
06999   }
07000 
07001   // They are disjoint.
07002   return DISJOINT;
07003 }
07004 
07006 //                                                                           //
07007 // insphere_sos()    Insphere test with symbolic perturbation.               //
07008 //                                                                           //
07009 // The input points a, b, c, and d should be non-coplanar. They must be ord- //
07010 // ered so that they have a positive orientation (as defined by orient3d()), //
07011 // or the sign of the result will be reversed.                               //
07012 //                                                                           //
07013 // Return a positive value if the point e lies inside the circumsphere of a, //
07014 // b, c, and d; a negative value if it lies outside.                         //
07015 //                                                                           //
07017 
07018 REAL tetgenmesh::insphere_sos(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
07019   int ia, int ib, int ic, int id, int ie)
07020 {
07021   REAL det;
07022 
07023   det = insphere(pa, pb, pc, pd, pe);
07024   if (det != 0.0) {
07025     return det;
07026   }
07027 
07028   // det = 0.0, use symbolic perturbation.
07029   REAL *p[5], *tmpp;
07030   REAL sign, det_c, det_d;
07031   int idx[5], perm, tmp;
07032   int n, i, j;
07033 
07034   p[0] = pa; idx[0] = ia;
07035   p[1] = pb; idx[1] = ib;
07036   p[2] = pc; idx[2] = ic;
07037   p[3] = pd; idx[3] = id;
07038   p[4] = pe; idx[4] = ie;
07039 
07040   // Bubble sort the points by the increasing order of the indices.
07041   n = 5;
07042   perm = 0; // The number of total swaps.
07043   for (i = 0; i < n - 1; i++) {
07044     for (j = 0; j < n - 1 - i; j++) {
07045       if (idx[j + 1] < idx[j]) {  // compare the two neighbors.
07046         tmp = idx[j];         // swap idx[j] and idx[j + 1]
07047         idx[j] = idx[j + 1];
07048         idx[j + 1] = tmp;
07049         tmpp = p[j];         // swap p[j] and p[j + 1]
07050         p[j] = p[j + 1];
07051         p[j + 1] = tmpp;
07052         perm++;
07053       }
07054     }
07055   }
07056 
07057   sign = (perm % 2 == 0) ? 1.0 : -1.0;
07058   det_c = orient3d(p[1], p[2], p[3], p[4]); // orient3d(b, c, d, e)
07059   if (det_c != 0.0) {
07060     return sign * det_c;
07061   }
07062   det_d = orient3d(p[0], p[2], p[3], p[4]); // orient3d(a, c, d, e)
07063   return -sign * det_d;
07064 }
07065 
07067 //                                                                           //
07068 // iscollinear()    Check if three points are approximately collinear.       //
07069 //                                                                           //
07070 // 'eps' is a relative error tolerance.  The collinearity is determined by   //
07071 // the value q = cos(theta), where theta is the angle between two vectors    //
07072 // A->B and A->C.  They're collinear if 1.0 - q <= epspp.                    //
07073 //                                                                           //
07075 
07076 bool tetgenmesh::iscollinear(REAL* A, REAL* B, REAL* C, REAL eps)
07077 {
07078   REAL abx, aby, abz;
07079   REAL acx, acy, acz;
07080   REAL Lv, Lw, dd;
07081   REAL d, q;
07082 
07083   // Limit of two closed points.
07084   q = longest * eps;
07085   q *= q;
07086 
07087   abx = A[0] - B[0];
07088   aby = A[1] - B[1];
07089   abz = A[2] - B[2];
07090   acx = A[0] - C[0];
07091   acy = A[1] - C[1];
07092   acz = A[2] - C[2];
07093   Lv = abx * abx + aby * aby + abz * abz;
07094   // Is AB (nearly) indentical?
07095   if (Lv < q) return true;
07096   Lw = acx * acx + acy * acy + acz * acz;
07097   // Is AC (nearly) indentical?
07098   if (Lw < q) return true;
07099   dd = abx * acx + aby * acy + abz * acz;
07100 
07101   d = (dd * dd) / (Lv * Lw);
07102   if (d > 1.0) d = 1.0; // Rounding.
07103   q = 1.0 - sqrt(d); // Notice 0 < q < 1.0.
07104 
07105   return q <= eps;
07106 }
07107 
07109 //                                                                           //
07110 // iscoplanar()    Check if four points are approximately coplanar.          //
07111 //                                                                           //
07112 // 'vol6' is six times of the signed volume of the tetrahedron formed by the //
07113 // four points. 'eps' is the relative error tolerance.  The coplanarity is   //
07114 // determined by the value: q = fabs(vol6) / L^3,  where L is the average    //
07115 // edge length of the tet. They're coplanar if q <= eps.                     //
07116 //                                                                           //
07118 
07119 bool tetgenmesh::
07120 iscoplanar(REAL* k, REAL* l, REAL* m, REAL* n, REAL vol6, REAL eps)
07121 {
07122   REAL L, q;
07123   REAL x, y, z;
07124 
07125   if (vol6 == 0.0) return true;
07126 
07127   x = k[0] - l[0];
07128   y = k[1] - l[1];
07129   z = k[2] - l[2];
07130   L = sqrt(x * x + y * y + z * z);
07131   x = l[0] - m[0];
07132   y = l[1] - m[1];
07133   z = l[2] - m[2];
07134   L += sqrt(x * x + y * y + z * z);
07135   x = m[0] - k[0];
07136   y = m[1] - k[1];
07137   z = m[2] - k[2];
07138   L += sqrt(x * x + y * y + z * z);
07139   x = k[0] - n[0];
07140   y = k[1] - n[1];
07141   z = k[2] - n[2];
07142   L += sqrt(x * x + y * y + z * z);
07143   x = l[0] - n[0];
07144   y = l[1] - n[1];
07145   z = l[2] - n[2];
07146   L += sqrt(x * x + y * y + z * z);
07147   x = m[0] - n[0];
07148   y = m[1] - n[1];
07149   z = m[2] - n[2];
07150   L += sqrt(x * x + y * y + z * z);
07151 #ifdef SELF_CHECK
07152   assert(L > 0.0);
07153 #endif
07154   L /= 6.0;
07155   q = fabs(vol6) / (L * L * L);
07156 
07157   return q <= eps;
07158 }
07159 
07161 //                                                                           //
07162 // iscospheric()    Check if five points are approximately coplanar.         //
07163 //                                                                           //
07164 // 'vol24' is the 24 times of the signed volume of the 4-dimensional simplex //
07165 // formed by the five points. 'eps' is the relative tolerance. The cosphere  //
07166 // case is determined by the value: q = fabs(vol24) / L^4,  where L is the   //
07167 // average edge length of the simplex. They're cosphere if q <= eps.         //
07168 //                                                                           //
07170 
07171 bool tetgenmesh::
07172 iscospheric(REAL* k, REAL* l, REAL* m, REAL* n, REAL* o, REAL vol24, REAL eps)
07173 {
07174   REAL L, q;
07175 
07176   // A 4D simplex has 10 edges.
07177   L = distance(k, l);
07178   L += distance(l, m);
07179   L += distance(m, k);
07180   L += distance(k, n);
07181   L += distance(l, n);
07182   L += distance(m, n);
07183   L += distance(k, o);
07184   L += distance(l, o);
07185   L += distance(m, o);
07186   L += distance(n, o);
07187 #ifdef SELF_CHECK
07188   assert(L > 0.0);
07189 #endif
07190   L /= 10.0;
07191   q = fabs(vol24) / (L * L * L * L);
07192 
07193   return q < eps;
07194 }
07195 
07196 //
07197 // End of geometric tests
07198 //
07199 
07200 //
07201 // Begin of Geometric quantities calculators
07202 //
07203 
07204 // distance() computs the Euclidean distance between two points.
07205 inline REAL tetgenmesh::distance(REAL* p1, REAL* p2)
07206 {
07207   return sqrt((p2[0] - p1[0]) * (p2[0] - p1[0]) +
07208               (p2[1] - p1[1]) * (p2[1] - p1[1]) +
07209               (p2[2] - p1[2]) * (p2[2] - p1[2]));
07210 }
07211 
07213 //                                                                           //
07214 // shortdistance()    Returns the shortest distance from point p to a line   //
07215 //                    defined by two points e1 and e2.                       //
07216 //                                                                           //
07217 // First compute the projection length l_p of the vector v1 = p - e1 along   //
07218 // the vector v2 = e2 - e1. Then Pythagoras' Theorem is used to compute the  //
07219 // shortest distance.                                                        //
07220 //                                                                           //
07221 // This routine allows that p is collinear with the line. In this case, the  //
07222 // return value is zero. The two points e1 and e2 should not be identical.   //
07223 //                                                                           //
07225 
07226 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2)
07227 {
07228   REAL v1[3], v2[3];
07229   REAL len, l_p;
07230 
07231   v1[0] = e2[0] - e1[0];
07232   v1[1] = e2[1] - e1[1];
07233   v1[2] = e2[2] - e1[2];
07234   v2[0] = p[0] - e1[0];
07235   v2[1] = p[1] - e1[1];
07236   v2[2] = p[2] - e1[2];
07237 
07238   len = sqrt(dot(v1, v1));
07239 #ifdef SELF_CHECK
07240   assert(len != 0.0);
07241 #endif
07242   v1[0] /= len;
07243   v1[1] /= len;
07244   v1[2] /= len;
07245   l_p = dot(v1, v2);
07246 
07247   return sqrt(dot(v2, v2) - l_p * l_p);
07248 }
07249 
07251 //                                                                           //
07252 // shortdistance()    Returns the shortest distance from point p to a face.  //
07253 //                                                                           //
07255 
07256 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2, REAL* e3)
07257 {
07258   REAL prj[3];
07259 
07260   projpt2face(p, e1, e2, e3, prj);
07261   return distance(p, prj);
07262 }
07263 
07265 //                                                                           //
07266 // interiorangle()    Return the interior angle (0 - 2 * PI) between vectors //
07267 //                    o->p1 and o->p2.                                       //
07268 //                                                                           //
07269 // 'n' is the normal of the plane containing face (o, p1, p2).  The interior //
07270 // angle is the total angle rotating from o->p1 around n to o->p2.  Exchange //
07271 // the position of p1 and p2 will get the complement angle of the other one. //
07272 // i.e., interiorangle(o, p1, p2) = 2 * PI - interiorangle(o, p2, p1).  Set  //
07273 // 'n' be NULL if you only want the interior angle between 0 - PI.           //
07274 //                                                                           //
07276 
07277 REAL tetgenmesh::interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n)
07278 {
07279   REAL v1[3], v2[3], np[3];
07280   REAL theta, costheta, lenlen;
07281   REAL ori, len1, len2;
07282 
07283   // Get the interior angle (0 - PI) between o->p1, and o->p2.
07284   v1[0] = p1[0] - o[0];
07285   v1[1] = p1[1] - o[1];
07286   v1[2] = p1[2] - o[2];
07287   v2[0] = p2[0] - o[0];
07288   v2[1] = p2[1] - o[1];
07289   v2[2] = p2[2] - o[2];
07290   len1 = sqrt(dot(v1, v1));
07291   len2 = sqrt(dot(v2, v2));
07292   lenlen = len1 * len2;
07293 #ifdef SELF_CHECK
07294   assert(lenlen != 0.0);
07295 #endif
07296   costheta = dot(v1, v2) / lenlen;
07297   if (costheta > 1.0) {
07298     costheta = 1.0; // Roundoff.
07299   } else if (costheta < -1.0) {
07300     costheta = -1.0; // Roundoff.
07301   }
07302   theta = acos(costheta);
07303   if (n != NULL) {
07304     // Get a point above the face (o, p1, p2);
07305     np[0] = o[0] + n[0];
07306     np[1] = o[1] + n[1];
07307     np[2] = o[2] + n[2];
07308     // Adjust theta (0 - 2 * PI).
07309     ori = orient3d(p1, o, np, p2);
07310     if (ori > 0.0) {
07311       theta = 2 * PI - theta;
07312     }
07313   }
07314 
07315   return theta;
07316 }
07317 
07319 //                                                                           //
07320 // projpt2edge()    Return the projection point from a point to an edge.     //
07321 //                                                                           //
07323 
07324 void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj)
07325 {
07326   REAL v1[3], v2[3];
07327   REAL len, l_p;
07328 
07329   v1[0] = e2[0] - e1[0];
07330   v1[1] = e2[1] - e1[1];
07331   v1[2] = e2[2] - e1[2];
07332   v2[0] = p[0] - e1[0];
07333   v2[1] = p[1] - e1[1];
07334   v2[2] = p[2] - e1[2];
07335 
07336   len = sqrt(dot(v1, v1));
07337 #ifdef SELF_CHECK
07338   assert(len != 0.0);
07339 #endif
07340   v1[0] /= len;
07341   v1[1] /= len;
07342   v1[2] /= len;
07343   l_p = dot(v1, v2);
07344 
07345   prj[0] = e1[0] + l_p * v1[0];
07346   prj[1] = e1[1] + l_p * v1[1];
07347   prj[2] = e1[2] + l_p * v1[2];
07348 }
07349 
07351 //                                                                           //
07352 // projpt2face()    Return the projection point from a point to a face.      //
07353 //                                                                           //
07355 
07356 void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj)
07357 {
07358   REAL fnormal[3], v1[3];
07359   REAL len, dist;
07360 
07361   // Get the unit face normal.
07362   facenormal(f1, f2, f3, fnormal, &len);
07363 #ifdef SELF_CHECK
07364   assert(len > 0.0);
07365 #endif
07366   fnormal[0] /= len;
07367   fnormal[1] /= len;
07368   fnormal[2] /= len;
07369   // Get the vector v1 = |p - f1|.
07370   v1[0] = p[0] - f1[0];
07371   v1[1] = p[1] - f1[1];
07372   v1[2] = p[2] - f1[2];
07373   // Get the project distance.
07374   dist = dot(fnormal, v1);
07375 
07376   // Get the project point.
07377   prj[0] = p[0] - dist * fnormal[0];
07378   prj[1] = p[1] - dist * fnormal[1];
07379   prj[2] = p[2] - dist * fnormal[2];
07380 }
07381 
07383 //                                                                           //
07384 // facenormal()    Calculate the normal of a face given by three points.     //
07385 //                                                                           //
07386 // In general, the face normal can be calculate by the cross product of any  //
07387 // pair of the three edge vectors.  However, if the three points are nearly  //
07388 // collinear, the rounding error may harm the result. To choose a good pair  //
07389 // of vectors is helpful to reduce the error.                                //
07390 //                                                                           //
07392 
07393 void tetgenmesh::facenormal(REAL* pa, REAL* pb, REAL* pc, REAL* n, REAL* nlen)
07394 {
07395   REAL v1[3], v2[3];
07396 
07397   v1[0] = pb[0] - pa[0];
07398   v1[1] = pb[1] - pa[1];
07399   v1[2] = pb[2] - pa[2];
07400   v2[0] = pc[0] - pa[0];
07401   v2[1] = pc[1] - pa[1];
07402   v2[2] = pc[2] - pa[2];
07403 
07404   cross(v1, v2, n);
07405   if (nlen != (REAL *) NULL) {
07406     *nlen = sqrt(dot(n, n));
07407   }
07408 }
07409 
07411 //                                                                           //
07412 // edgeorthonormal()    Return the unit normal of an edge in a given plane.  //
07413 //                                                                           //
07414 // The edge is from e1 to e2,  the plane is defined by given an additional   //
07415 // point op, which is non-collinear with the edge.  In addition, the side of //
07416 // the edge in which op lies defines the positive position of the normal.    //
07417 //                                                                           //
07418 // Let v1 be the unit vector from e1 to e2, v2 be the unit edge vector from  //
07419 // e1 to op, fn be the unit face normal calculated by fn = v1 x v2. Then the //
07420 // unit edge normal of e1e2 pointing to op is n = fn x v1.  Note, we should  //
07421 // not change the position of fn and v1, otherwise, we get the edge normal   //
07422 // pointing to the other side of op.                                         //
07423 //                                                                           //
07425 
07426 void tetgenmesh::edgeorthonormal(REAL* e1, REAL* e2, REAL* op, REAL* n)
07427 {
07428   REAL v1[3], v2[3], fn[3];
07429   REAL len;
07430 
07431   // Get the edge vector v1.
07432   v1[0] = e2[0] - e1[0];
07433   v1[1] = e2[1] - e1[1];
07434   v1[2] = e2[2] - e1[2];
07435   // Get the edge vector v2.
07436   v2[0] = op[0] - e1[0];
07437   v2[1] = op[1] - e1[1];
07438   v2[2] = op[2] - e1[2];
07439   // Get the face normal fn = v1 x v2.
07440   cross(v1, v2, fn);
07441   // Get the edge normal n pointing to op. n = fn x v1.
07442   cross(fn, v1, n);
07443   // Normalize the vector.
07444   len = sqrt(dot(n, n));
07445   n[0] /= len;
07446   n[1] /= len;
07447   n[2] /= len;
07448 }
07449 
07451 //                                                                           //
07452 // facedihedral()    Return the dihedral angle (in radian) between two       //
07453 //                   adjoining faces.                                        //
07454 //                                                                           //
07455 // 'pa', 'pb' are the shared edge of these two faces, 'pc1', and 'pc2' are   //
07456 // apexes of these two faces.  Return the angle (between 0 to 2*pi) between  //
07457 // the normal of face (pa, pb, pc1) and normal of face (pa, pb, pc2).        //
07458 //                                                                           //
07460 
07461 REAL tetgenmesh::facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2)
07462 {
07463   REAL n1[3], n2[3];
07464   REAL n1len, n2len;
07465   REAL costheta, ori;
07466   REAL theta;
07467 
07468   facenormal(pa, pb, pc1, n1, &n1len);
07469   facenormal(pa, pb, pc2, n2, &n2len);
07470   costheta = dot(n1, n2) / (n1len * n2len);
07471   // Be careful rounding error!
07472   if (costheta > 1.0) {
07473     costheta = 1.0;
07474   } else if (costheta < -1.0) {
07475     costheta = -1.0;
07476   }
07477   theta = acos(costheta);
07478   ori = orient3d(pa, pb, pc1, pc2);
07479   if (ori > 0.0) {
07480     theta = 2 * PI - theta;
07481   }
07482 
07483   return theta;
07484 }
07485 
07487 //                                                                           //
07488 // tetalldihedral()    Get all (six) dihedral angles of a tet.               //
07489 //                                                                           //
07490 // The tet is given by its four corners a, b, c, and d. If 'cosdd' is not    //
07491 // NULL, it returns the cosines of the 6 dihedral angles, the corresponding  //
07492 // edges are: ab, bc, ca, ad, bd, and cd. If 'cosmaxd' (or 'cosmind') is not //
07493 // NULL, it returns the cosine of the maximal (or minimal) dihedral angle.   //
07494 //                                                                           //
07496 
07497 void tetgenmesh::tetalldihedral(point pa, point pb, point pc, point pd,
07498   REAL* cosdd, REAL* cosmaxd, REAL* cosmind)
07499 {
07500   REAL N[4][3], cosd, len;
07501   int f1, f2, i, j;
07502 
07503   f1=0;
07504   f2=0;
07505 
07506   // Get four normals of faces of the tet.
07507   tetallnormal(pa, pb, pc, pd, N, NULL);
07508   // Normalize the normals.
07509   for (i = 0; i < 4; i++) {
07510     len = sqrt(dot(N[i], N[i]));
07511     if (len != 0.0) {
07512       for (j = 0; j < 3; j++) N[i][j] /= len;
07513     }
07514   }
07515 
07516   for (i = 0; i < 6; i++) {
07517     switch (i) {
07518     case 0: f1 = 2; f2 = 3; break; // edge ab.
07519     case 1: f1 = 0; f2 = 3; break; // edge bc.
07520     case 2: f1 = 1; f2 = 3; break; // edge ca.
07521     case 3: f1 = 1; f2 = 2; break; // edge ad.
07522     case 4: f1 = 2; f2 = 0; break; // edge bd.
07523     case 5: f1 = 0; f2 = 1; break; // edge cd.
07524     }
07525     cosd = -dot(N[f1], N[f2]);
07526     if (cosdd) cosdd[i] = cosd;
07527     if (i == 0) {
07528       if (cosmaxd) *cosmaxd = cosd;
07529       if (cosmind) *cosmind = cosd;
07530     } else {
07531       if (cosmaxd) *cosmaxd = cosd < *cosmaxd ? cosd : *cosmaxd;
07532       if (cosmind) *cosmind = cosd > *cosmind ? cosd : *cosmind;
07533     }
07534   }
07535 }
07536 
07538 //                                                                           //
07539 // tetallnormal()    Get the in-noramls of the four faces of a given tet.    //
07540 //                                                                           //
07541 // Let tet be abcd. N[4][3] returns the four normals, which are: N[0] cbd,   //
07542 // N[1] acd, N[2] bad, N[3] abc. These normals are unnormalized.             //
07543 //                                                                           //
07545 
07546 void tetgenmesh::tetallnormal(point pa, point pb, point pc, point pd,
07547   REAL N[4][3], REAL* volume)
07548 {
07549   REAL A[4][4], rhs[4], D;
07550   int indx[4];
07551   int i, j;
07552 
07553   // get the entries of A[3][3].
07554   for (i = 0; i < 3; i++) A[0][i] = pa[i] - pd[i];  // d->a vec
07555   for (i = 0; i < 3; i++) A[1][i] = pb[i] - pd[i];  // d->b vec
07556   for (i = 0; i < 3; i++) A[2][i] = pc[i] - pd[i];  // d->c vec
07557   // Compute the inverse of matrix A, to get 3 normals of the 4 faces.
07558   lu_decmp(A, 3, indx, &D, 0);     // Decompose the matrix just once.
07559   if (volume != NULL) {
07560     // Get the volume of the tet.
07561     *volume = fabs((A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2])) / 6.0;
07562   }
07563   for (j = 0; j < 3; j++) {
07564     for (i = 0; i < 3; i++) rhs[i] = 0.0;
07565     rhs[j] = 1.0;  // Positive means the inside direction
07566     lu_solve(A, 3, indx, rhs, 0);
07567     for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07568   }
07569   // Get the fourth normal by summing up the first three.
07570   for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07571 }
07572 
07574 //                                                                           //
07575 // tetaspectratio()    Calculate the aspect ratio of the tetrahedron.        //
07576 //                                                                           //
07577 // The aspect ratio of a tet is R/h, where R is the circumradius and h is    //
07578 // the shortest height of the tet.                                           //
07579 //                                                                           //
07581 
07582 REAL tetgenmesh::tetaspectratio(point pa, point pb, point pc, point pd)
07583 {
07584   REAL vda[3], vdb[3], vdc[3];
07585   REAL N[4][3], A[4][4], rhs[4], D;
07586   REAL H[4], volume, radius2, minheightinv;
07587   int indx[4];
07588   int i, j;
07589 
07590   // Set the matrix A = [vda, vdb, vdc]^T.
07591   for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
07592   for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
07593   for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
07594   // Lu-decompose the matrix A.
07595   lu_decmp(A, 3, indx, &D, 0);
07596   // Get the volume of abcd.
07597   volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
07598   // Check if it is zero.
07599   if (volume == 0.0) return 1.0e+200; // A degenerate tet.
07600   // if (volume < 0.0) volume = -volume;
07601   // Check the radiu-edge ratio of the tet.
07602   rhs[0] = 0.5 * dot(vda, vda);
07603   rhs[1] = 0.5 * dot(vdb, vdb);
07604   rhs[2] = 0.5 * dot(vdc, vdc);
07605   lu_solve(A, 3, indx, rhs, 0);
07606   // Get the circumcenter.
07607   // for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
07608   // Get the square of the circumradius.
07609   radius2 = dot(rhs, rhs);
07610 
07611   // Compute the 4 face normals (N[0], ..., N[3]).
07612   for (j = 0; j < 3; j++) {
07613     for (i = 0; i < 3; i++) rhs[i] = 0.0;
07614     rhs[j] = 1.0;  // Positive means the inside direction
07615     lu_solve(A, 3, indx, rhs, 0);
07616     for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07617   }
07618   // Get the fourth normal by summing up the first three.
07619   for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07620   // Normalized the normals.
07621   for (i = 0; i < 4; i++) {
07622     // H[i] is the inverse of the height of its corresponding face.
07623     H[i] = sqrt(dot(N[i], N[i]));
07624     // if (H[i] > 0.0) {
07625     //   for (j = 0; j < 3; j++) N[i][j] /= H[i];
07626     // }
07627   }
07628   // Get the radius of the inscribed sphere.
07629   // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]);
07630   // Get the biggest H[i] (corresponding to the smallest height).
07631   minheightinv = H[0];
07632   for (i = 1; i < 3; i++) {
07633     if (H[i] > minheightinv) minheightinv = H[i];
07634   }
07635 
07636   return sqrt(radius2) * minheightinv;
07637 }
07638 
07640 //                                                                           //
07641 // circumsphere()    Calculate the smallest circumsphere (center and radius) //
07642 //                   of the given three or four points.                      //
07643 //                                                                           //
07644 // The circumsphere of four points (a tetrahedron) is unique if they are not //
07645 // degenerate. If 'pd = NULL', the smallest circumsphere of three points is  //
07646 // the diametral sphere of the triangle if they are not degenerate.          //
07647 //                                                                           //
07648 // Return TRUE if the input points are not degenerate and the circumcenter   //
07649 // and circumradius are returned in 'cent' and 'radius' respectively if they //
07650 // are not NULLs. Otherwise, return FALSE indicated the points are degenrate.//
07651 //                                                                           //
07653 
07654 bool tetgenmesh::
07655 circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* cent, REAL* radius)
07656 {
07657   REAL A[4][4], rhs[4], D;
07658   int indx[4];
07659 
07660   // Compute the coefficient matrix A (3x3).
07661   A[0][0] = pb[0] - pa[0];
07662   A[0][1] = pb[1] - pa[1];
07663   A[0][2] = pb[2] - pa[2];
07664   A[1][0] = pc[0] - pa[0];
07665   A[1][1] = pc[1] - pa[1];
07666   A[1][2] = pc[2] - pa[2];
07667   if (pd != NULL) {
07668     A[2][0] = pd[0] - pa[0];
07669     A[2][1] = pd[1] - pa[1];
07670     A[2][2] = pd[2] - pa[2];
07671   } else {
07672     cross(A[0], A[1], A[2]);
07673   }
07674 
07675   // Compute the right hand side vector b (3x1).
07676   rhs[0] = 0.5 * dot(A[0], A[0]);
07677   rhs[1] = 0.5 * dot(A[1], A[1]);
07678   if (pd != NULL) {
07679     rhs[2] = 0.5 * dot(A[2], A[2]);
07680   } else {
07681     rhs[2] = 0.0;
07682   }
07683 
07684   // Solve the 3 by 3 equations use LU decomposition with partial pivoting
07685   //   and backward and forward substitute..
07686   if (!lu_decmp(A, 3, indx, &D, 0)) {
07687     if (radius != (REAL *) NULL) *radius = 0.0;
07688     return false;
07689   }
07690   lu_solve(A, 3, indx, rhs, 0);
07691   if (cent != (REAL *) NULL) {
07692     cent[0] = pa[0] + rhs[0];
07693     cent[1] = pa[1] + rhs[1];
07694     cent[2] = pa[2] + rhs[2];
07695   }
07696   if (radius != (REAL *) NULL) {
07697     *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
07698   }
07699   return true;
07700 }
07701 
07703 //                                                                           //
07704 // inscribedsphere()    Compute the radius and center of the biggest         //
07705 //                      inscribed sphere of a given tetrahedron.             //
07706 //                                                                           //
07707 // The tetrahedron is given by its four points, it must not be degenerate.   //
07708 // The center and radius are returned in 'cent' and 'radius' respectively if //
07709 // they are not NULLs.                                                       //
07710 //                                                                           //
07711 // Geometrical fact. For any simplex in d dimension,                         //
07712 //   r/h1 + r/h2 + ... r/hn = 1 (n <= d + 1);                                //
07713 // where r is the radius of inscribed ball, and h is the height of each side //
07714 // of the simplex. The value of 'r/h' is just the barycenter coordinates of  //
07715 // each vertex of the simplex. Therefore, we can compute the radius and      //
07716 // center of the smallest inscribed ball as following equations:             //
07717 //   r = 1.0 / (1/h1 + 1/h2 + ... + 1/hn);          (1)                      //
07718 //   C = r/h1 * P1 + r/h2 * P2 + ... + r/hn * Pn;   (2)                      //
07719 // where C is the vector of center, P1, P2, .. Pn are vectors of vertices.   //
07720 // Here (2) contains n linear equations with n variables.  (h, P) must be a  //
07721 // pair, h is the height from P to its opposite face.                        //
07722 //                                                                           //
07724 
07725 void tetgenmesh::inscribedsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
07726   REAL* cent, REAL* radius)
07727 {
07728   REAL N[4][3], H[4]; // Normals (colume vectors) and heights of each face.
07729   REAL rd;
07730   int i;
07731 
07732   // Get the all normals of the tet.
07733   tetallnormal(pa, pb, pc, pd, N, NULL);
07734   for (i = 0; i < 4; i++) {
07735     // H[i] is the inverse of height of its corresponding face.
07736     H[i] = sqrt(dot(N[i], N[i]));
07737   }
07738   // Compute the radius use eq. (1).
07739   rd = 1.0 / (H[0] + H[1] + H[2] + H[3]);
07740   if (radius != (REAL*) NULL) *radius = rd;
07741   if (cent != (REAL*) NULL) {
07742     // Compute the center use eq. (2).
07743     cent[0] = rd * (H[0] * pa[0] + H[1] * pb[0] + H[2] * pc[0] + H[3] * pd[0]);
07744     cent[1] = rd * (H[0] * pa[1] + H[1] * pb[1] + H[2] * pc[1] + H[3] * pd[1]);
07745     cent[2] = rd * (H[0] * pa[2] + H[1] * pb[2] + H[2] * pc[2] + H[3] * pd[2]);
07746   }
07747 }
07748 
07750 //                                                                           //
07751 // rotatepoint()    Create a point by rotating an existing point.            //
07752 //                                                                           //
07753 // Create a 3D point by rotating point 'p' with an angle 'rotangle' (in arc  //
07754 // degree) around a rotating axis given by a vector from point 'p1' to 'p2'. //
07755 // The rotation is according with right-hand rule, i.e., use your right-hand //
07756 // to grab the axis with your thumber pointing to its positive direction,    //
07757 // your fingers indicate the rotating direction.                             //
07758 //                                                                           //
07759 // The rotating steps are the following:                                     //
07760 //   1. Translate vector 'p1->p2' to origin, M1;                             //
07761 //   2. Rotate vector around the Y-axis until it lies in the YZ plane, M2;   //
07762 //   3. Rotate vector around the X-axis until it lies on the Z axis, M3;     //
07763 //   4. Perform the rotation of 'p' around the z-axis, M4;                   //
07764 //   5. Undo Step 3, M5;                                                     //
07765 //   6. Undo Step 2, M6;                                                     //
07766 //   7. Undo Step 1, M7;                                                     //
07767 // Use matrix multiplication to combine the above sequences, we get:         //
07768 //   p0' = T * p0, where T = M7 * M6 * M5 * M4 * M3 * M2 * M1                //
07769 //                                                                           //
07771 
07772 void tetgenmesh::rotatepoint(REAL* p, REAL rotangle, REAL* p1, REAL* p2)
07773 {
07774   REAL T[4][4], pp0[4], p0t[4], p2t[4];
07775   REAL roty, rotx, alphaR, projlen;
07776   REAL dx, dy, dz;
07777 
07778   initm44(1, 0, 0, -p1[0],
07779           0, 1, 0, -p1[1],
07780           0, 0, 1, -p1[2],
07781           0, 0, 0, 1, T);
07782   pp0[0] = p[0]; pp0[1] = p[1]; pp0[2] = p[2]; pp0[3] = 1.0;
07783   m4xv4(p0t, T, pp0); // Step 1
07784   pp0[0] = p2[0]; pp0[1] = p2[1]; pp0[2] = p2[2]; pp0[3] = 1.0;
07785   m4xv4(p2t, T, pp0); // Step 1
07786 
07787   // Get the rotation angle around y-axis;
07788   dx = p2t[0];
07789   dz = p2t[2];
07790   projlen = sqrt(dx * dx + dz * dz);
07791   if (projlen <= (b->epsilon * 1e-2) * longest) {
07792     roty = 0;
07793   } else {
07794     roty = acos(dz / projlen);
07795     if (dx < 0) {
07796       roty = -roty;
07797     }
07798   }
07799 
07800   initm44(cos(-roty), 0, sin(-roty), 0,
07801           0, 1, 0, 0,
07802           -sin(-roty), 0, cos(-roty), 0,
07803           0, 0, 0, 1, T);
07804   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07805   m4xv4(p0t, T, pp0); // Step 2
07806   pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
07807   m4xv4(p2t, T, pp0); // Step 2
07808 
07809   // Get the rotation angle around x-axis
07810   dy = p2t[1];
07811   dz = p2t[2];
07812   projlen = sqrt(dy * dy + dz * dz);
07813   if (projlen <= (b->epsilon * 1e-2) * longest) {
07814     rotx = 0;
07815   } else {
07816     rotx = acos(dz / projlen);
07817     if (dy < 0) {
07818       rotx = -rotx;
07819     }
07820   }
07821 
07822   initm44(1, 0, 0, 0,
07823           0, cos(rotx), -sin(rotx), 0,
07824           0, sin(rotx), cos(rotx), 0,
07825           0, 0, 0, 1, T);
07826   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07827   m4xv4(p0t, T, pp0); // Step 3
07828   // pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
07829   // m4xv4(p2t, T, pp0); // Step 3
07830 
07831   alphaR = rotangle;
07832   initm44(cos(alphaR), -sin(alphaR), 0, 0,
07833           sin(alphaR), cos(alphaR), 0, 0,
07834           0, 0, 1, 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 4
07838 
07839   initm44(1, 0, 0, 0,
07840           0, cos(-rotx), -sin(-rotx), 0,
07841           0, sin(-rotx), cos(-rotx), 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 5
07845 
07846   initm44(cos(roty), 0, sin(roty), 0,
07847           0, 1, 0, 0,
07848           -sin(roty), 0, cos(roty), 0,
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 6
07852 
07853   initm44(1, 0, 0, p1[0],
07854           0, 1, 0, p1[1],
07855           0, 0, 1, p1[2],
07856           0, 0, 0, 1, T);
07857   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07858   m4xv4(p0t, T, pp0); // Step 7
07859 
07860   p[0] = p0t[0];
07861   p[1] = p0t[1];
07862   p[2] = p0t[2];
07863 }
07864 
07866 //                                                                           //
07867 // spherelineint()    3D line sphere (or circle) intersection.               //
07868 //                                                                           //
07869 // The line is given by two points p1, and p2, the sphere is centered at c   //
07870 // with radius r.  This function returns a pointer array p which first index //
07871 // indicates the number of intersection point, followed by coordinate pairs. //
07872 //                                                                           //
07873 // The following code are adapted from: http://astronomy.swin.edu.au/pbourke //
07874 // /geometry/sphereline. Paul Bourke pbourke@swin.edu.au                     //
07875 //                                                                           //
07877 
07878 void tetgenmesh::spherelineint(REAL* p1, REAL* p2, REAL* C, REAL R, REAL p[7])
07879 {
07880   REAL x1, y1, z1; //  P1 coordinates (point of line)
07881   REAL x2, y2, z2; //  P2 coordinates (point of line)
07882   REAL x3, y3, z3, r; //  P3 coordinates and radius (sphere)
07883   REAL a, b, c, mu, i ;
07884 
07885   x1 = p1[0]; y1 = p1[1]; z1 = p1[2];
07886   x2 = p2[0]; y2 = p2[1]; z2 = p2[2];
07887   x3 = C[0];  y3 = C[1];  z3 = C[2];
07888   r = R;
07889 
07890   a =   (x2 - x1) * (x2 - x1)
07891       + (y2 - y1) * (y2 - y1)
07892       + (z2 - z1) * (z2 - z1);
07893   b = 2 * ( (x2 - x1) * (x1 - x3)
07894           + (y2 - y1) * (y1 - y3)
07895           + (z2 - z1) * (z1 - z3) ) ;
07896   c =   (x3 * x3) + (y3 * y3) + (z3 * z3)
07897       + (x1 * x1) + (y1 * y1) + (z1 * z1)
07898       - 2 * (x3 * x1 + y3 * y1 + z3 * z1) - (r * r) ;
07899   i = b * b - 4 * a * c ;
07900 
07901   if (i < 0.0) {
07902     // no intersection
07903     p[0] = 0.0;
07904   } else if (i == 0.0) {
07905     // one intersection
07906     p[0] = 1.0;
07907     mu = -b / (2 * a) ;
07908     p[1] = x1 + mu * (x2 - x1);
07909     p[2] = y1 + mu * (y2 - y1);
07910     p[3] = z1 + mu * (z2 - z1);
07911   } else {
07912     // two intersections
07913     p[0] = 2.0;
07914     // first intersection
07915     mu = (-b + sqrt((b * b) - 4 * a * c)) / (2 * a);
07916     p[1] = x1 + mu * (x2 - x1);
07917     p[2] = y1 + mu * (y2 - y1);
07918     p[3] = z1 + mu * (z2 - z1);
07919     // second intersection
07920     mu = (-b - sqrt((b * b) - 4 * a * c)) / (2 * a);
07921     p[4] = x1 + mu * (x2 - x1);
07922     p[5] = y1 + mu * (y2 - y1);
07923     p[6] = z1 + mu * (z2 - z1);
07924   }
07925 }
07926 
07928 //                                                                           //
07929 // linelineint()    Calculate the shortest line between two lines in 3D.     //
07930 //                                                                           //
07931 // Two 3D lines generally don't intersect at a point, they may be parallel ( //
07932 // no intersections), or coincident (infinite intersections) but most often  //
07933 // only their projections onto a plane intersect. If they don't exactly int- //
07934 // ersect at a point they can be connected by a line segment, the shortest   //
07935 // segment is unique and is often considered to be their intersection in 3D. //
07936 //                                                                           //
07937 // The following code are adapted from: http://astronomy.swin.edu.au/pbourke //
07938 // /geometry/lineline3d. Paul Bourke pbourke@swin.edu.au                     //
07939 //                                                                           //
07940 // Calculate the line segment PaPb that is the shortest route between two    //
07941 // lines P1P2 and P3P4. This function returns a pointer array p which first  //
07942 // index indicates there exists solution or not, 0 means no solution, 1 meas //
07943 // has solution followed by two coordinate pairs.                            //
07944 //                                                                           //
07946 
07947 void tetgenmesh::linelineint(REAL *p1,REAL *p2, REAL *p3, REAL *p4, REAL p[7])
07948 {
07949   REAL p13[3], p43[3], p21[3];
07950   REAL d1343, d4321, d1321, d4343, d2121;
07951   REAL numer, denom;
07952   REAL mua, mub;
07953 
07954   p13[0] = p1[0] - p3[0];
07955   p13[1] = p1[1] - p3[1];
07956   p13[2] = p1[2] - p3[2];
07957   p43[0] = p4[0] - p3[0];
07958   p43[1] = p4[1] - p3[1];
07959   p43[2] = p4[2] - p3[2];
07960   if (p43[0] == 0.0 && p43[1] == 0.0 && p43[2] == 0.0) {
07961     p[0] = 0.0;
07962     return;
07963   }
07964 
07965   p21[0] = p2[0] - p1[0];
07966   p21[1] = p2[1] - p1[1];
07967   p21[2] = p2[2] - p1[2];
07968   if (p21[0] == 0.0 && p21[1] == 0.0 && p21[2] == 0.0) {
07969     p[0] = 0.0;
07970     return;
07971   }
07972 
07973   d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
07974   d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
07975   d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
07976   d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
07977   d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
07978 
07979   denom = d2121 * d4343 - d4321 * d4321;
07980   if (denom == 0.0) {
07981     p[0] = 0.0;
07982     return;
07983   }
07984   numer = d1343 * d4321 - d1321 * d4343;
07985   mua = numer / denom;
07986   mub = (d1343 + d4321 * mua) / d4343;
07987 
07988   p[0] = 1.0;
07989   p[1] = p1[0] + mua * p21[0];
07990   p[2] = p1[1] + mua * p21[1];
07991   p[3] = p1[2] + mua * p21[2];
07992   p[4] = p3[0] + mub * p43[0];
07993   p[5] = p3[1] + mub * p43[1];
07994   p[6] = p3[2] + mub * p43[2];
07995 }
07996 
07998 //                                                                           //
07999 // planelineint()    Calculate the intersection of a line and a plane.       //
08000 //                                                                           //
08001 // The equation of a plane (points P are on the plane with normal N and P3   //
08002 // on the plane) can be written as: N dot (P - P3) = 0. The equation of the  //
08003 // line (points P on the line passing through P1 and P2) can be written as:  //
08004 // P = P1 + u (P2 - P1). The intersection of these two occurs when:          //
08005 //   N dot (P1 + u (P2 - P1)) = N dot P3.                                    //
08006 // Solving for u gives:                                                      //
08007 //         N dot (P3 - P1)                                                   //
08008 //   u = ------------------.                                                 //
08009 //         N dot (P2 - P1)                                                   //
08010 // If the denominator is 0 then N (the normal to the plane) is perpendicular //
08011 // to the line.  Thus the line is either parallel to the plane and there are //
08012 // no solutions or the line is on the plane in which case there are an infi- //
08013 // nite number of solutions.                                                 //
08014 //                                                                           //
08015 // The plane is given by three points pa, pb, and pc, e1 and e2 defines the  //
08016 // line. If u is non-zero, The intersection point (if exists) returns in ip. //
08017 //                                                                           //
08019 
08020 void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
08021   REAL* ip, REAL* u)
08022 {
08023   REAL n[3], det, det1;
08024 
08025   // Calculate N.
08026   facenormal(pa, pb, pc, n, NULL);
08027   // Calculate N dot (e2 - e1).
08028   det = n[0] * (e2[0] - e1[0]) + n[1] * (e2[1] - e1[1])
08029       + n[2] * (e2[2] - e1[2]);
08030   if (det != 0.0) {
08031     // Calculate N dot (pa - e1)
08032     det1 = n[0] * (pa[0] - e1[0]) + n[1] * (pa[1] - e1[1])
08033          + n[2] * (pa[2] - e1[2]);
08034     *u = det1 / det;
08035     ip[0] = e1[0] + *u * (e2[0] - e1[0]);
08036     ip[1] = e1[1] + *u * (e2[1] - e1[1]);
08037     ip[2] = e1[2] + *u * (e2[2] - e1[2]);
08038   } else {
08039     *u = 0.0;
08040   }
08041 }
08042 
08043 //
08044 // End of Geometric quantities calculators
08045 //
08046 
08047 //
08048 // Begin of memory management routines
08049 //
08050 
08052 //                                                                           //
08053 // dummyinit()    Initialize the tetrahedron that fills "outer space" and    //
08054 //                the omnipresent subface.                                   //
08055 //                                                                           //
08056 // The tetrahedron that fills "outer space" called 'dummytet', is pointed to //
08057 // by every tetrahedron and subface on a boundary (be it outer or inner) of  //
08058 // the tetrahedralization. Also, 'dummytet' points to one of the tetrahedron //
08059 // on the convex hull(until the holes and concavities are carved), making it //
08060 // possible to find a starting tetrahedron for point location.               //
08061 //                                                                           //
08062 // The omnipresent subface,'dummysh', is pointed to by every tetrahedron or  //
08063 // subface that doesn't have a full complement of real subface to point to.  //
08064 //                                                                           //
08066 
08067 void tetgenmesh::dummyinit(int tetwords, int shwords)
08068 {
08069   unsigned long alignptr;
08070 
08071   // Set up 'dummytet', the 'tetrahedron' that occupies "outer space".
08072   dummytetbase = (tetrahedron *) new char[tetwords * sizeof(tetrahedron)
08073                                           + tetrahedrons->alignbytes];
08074   // Align 'dummytet' on a 'tetrahedrons->alignbytes'-byte boundary.
08075   alignptr = (unsigned long) dummytetbase;
08076   dummytet = (tetrahedron *)
08077     (alignptr + (unsigned long) tetrahedrons->alignbytes
08078      - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08079   // Initialize the four adjoining tetrahedra to be "outer space". These
08080   //   will eventually be changed by various bonding operations, but their
08081   //   values don't really matter, as long as they can legally be
08082   //   dereferenced.
08083   dummytet[0] = (tetrahedron) dummytet;
08084   dummytet[1] = (tetrahedron) dummytet;
08085   dummytet[2] = (tetrahedron) dummytet;
08086   dummytet[3] = (tetrahedron) dummytet;
08087   // Four null vertex points.
08088   dummytet[4] = (tetrahedron) NULL;
08089   dummytet[5] = (tetrahedron) NULL;
08090   dummytet[6] = (tetrahedron) NULL;
08091   dummytet[7] = (tetrahedron) NULL;
08092 
08093   if (b->useshelles) {
08094     // Set up 'dummysh', the omnipresent "subface" pointed to by any
08095     //   tetrahedron side or subface end that isn't attached to a real
08096     //   subface.
08097     dummyshbase = (shellface *) new char[shwords * sizeof(shellface)
08098                                          + subfaces->alignbytes];
08099     // Align 'dummysh' on a 'subfaces->alignbytes'-byte boundary.
08100     alignptr = (unsigned long) dummyshbase;
08101     dummysh = (shellface *)
08102       (alignptr + (unsigned long) subfaces->alignbytes
08103        - (alignptr % (unsigned long) subfaces->alignbytes));
08104     // Initialize the three adjoining subfaces to be the omnipresent
08105     //   subface. These will eventually be changed by various bonding
08106     //   operations, but their values don't really matter, as long as they
08107     //   can legally be dereferenced.
08108     dummysh[0] = (shellface) dummysh;
08109     dummysh[1] = (shellface) dummysh;
08110     dummysh[2] = (shellface) dummysh;
08111     // Three null vertex points.
08112     dummysh[3] = (shellface) NULL;
08113     dummysh[4] = (shellface) NULL;
08114     dummysh[5] = (shellface) NULL;
08115     // Initialize the two adjoining tetrahedra to be "outer space".
08116     dummysh[6] = (shellface) dummytet;
08117     dummysh[7] = (shellface) dummytet;
08118     // Initialize the three adjoining subsegments to be "out boundary".
08119     dummysh[8]  = (shellface) dummysh;
08120     dummysh[9]  = (shellface) dummysh;
08121     dummysh[10] = (shellface) dummysh;
08122     // Initialize the pointer to badface structure.
08123     dummysh[11] = (shellface) NULL;
08124     // Initialize the four adjoining subfaces of 'dummytet' to be the
08125     //   omnipresent subface.
08126     dummytet[8 ] = (tetrahedron) dummysh;
08127     dummytet[9 ] = (tetrahedron) dummysh;
08128     dummytet[10] = (tetrahedron) dummysh;
08129     dummytet[11] = (tetrahedron) dummysh;
08130   }
08131 }
08132 
08134 //                                                                           //
08135 // initializepools()    Calculate the sizes of the point, tetrahedron, and   //
08136 //                      subface. Initialize their memory pools.              //
08137 //                                                                           //
08138 // This routine also computes the indices 'pointmarkindex', 'point2simindex',//
08139 // and 'point2pbcptindex' used to find values within each point;  computes   //
08140 // indices 'highorderindex', 'elemattribindex', and 'volumeboundindex' used  //
08141 // to find values within each tetrahedron.                                   //
08142 //                                                                           //
08143 // There are two types of boundary elements, which are subfaces and subsegs, //
08144 // they are stored in seperate pools. However, the data structures of them   //
08145 // are the same.  A subsegment can be regarded as a degenerate subface, i.e.,//
08146 // one of its three corners is not used. We set the apex of it be 'NULL' to  //
08147 // distinguish it's a subsegment.                                            //
08148 //                                                                           //
08150 
08151 void tetgenmesh::initializepools()
08152 {
08153   enum wordtype wtype;
08154   int pointsize, elesize, shsize;
08155 
08156   // Default checkpbc = 0;
08157   if ((b->plc || b->refine) && (in->pbcgrouplist != NULL)) {
08158     checkpbcs = 1;
08159   }
08160   // Default varconstraint = 0;
08161   if (in->segmentconstraintlist || in->facetconstraintlist) {
08162     varconstraint = 1;
08163   }
08164 
08165   // The index within each point at which its metric tensor is found. It is
08166   //   saved directly after the list of point attributes.
08167   pointmtrindex = 3 + in->numberofpointattributes;
08168   // Decide the size (1, 3, or 6) of the metric tensor.
08169   if (b->metric) {
08170     // For '-m' option. A tensor field is provided (*.mtr or *.b.mtr file).
08171     if (bgm != (tetgenmesh *) NULL) {
08172       // A background mesh is allocated. It may not exist though.
08173       sizeoftensor = (bgm->in != (tetgenio *) NULL) ?
08174         bgm->in->numberofpointmtrs : in->numberofpointmtrs;
08175     } else {
08176       // No given background mesh - Itself is a background mesh.
08177       sizeoftensor = in->numberofpointmtrs;
08178     }
08179     // Make sure sizeoftensor is at least 1.
08180     sizeoftensor = (sizeoftensor > 0) ? sizeoftensor : 1;
08181   } else {
08182     // For '-q' option. Make sure to have space for saving a scalar value.
08183     sizeoftensor = b->quality ? 1 : 0;
08184   }
08185   // The index within each point at which an element pointer is found, where
08186   //   the index is measured in pointers. Ensure the index is aligned to a
08187   //   sizeof(tetrahedron)-byte address.
08188   point2simindex = ((pointmtrindex + sizeoftensor) * sizeof(REAL)
08189                  + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08190   if (b->plc || b->refine) {
08191     // Increase the point size by three pointers, which are:
08192     //   - a pointer to a tet, read by point2tet();
08193     //   - a pointer to a subface/subsegment , read by point2sh();
08194     //   - a pointer to a parent point, read by point2ppt()).
08195     if (b->metric) {
08196       // Increase one pointer to a tet of the background mesh.
08197       pointsize = (point2simindex + 4) * sizeof(tetrahedron);
08198     } else {
08199       pointsize = (point2simindex + 3) * sizeof(tetrahedron);
08200     }
08201     // The index within each point at which a pbc point is found.
08202     point2pbcptindex = (pointsize + sizeof(tetrahedron) - 1)
08203                      / sizeof(tetrahedron);
08204     if (checkpbcs) {
08205       // Increase the size by one pointer to a corresponding pbc point,
08206       //   read by point2pbcpt().
08207       pointsize = (point2pbcptindex + 1) * sizeof(tetrahedron);
08208     }
08209   } else {
08210     pointsize = point2simindex * sizeof(tetrahedron);
08211   }
08212   // The index within each point at which the boundary marker is found,
08213   //   Ensure the point marker is aligned to a sizeof(int)-byte address.
08214   pointmarkindex = (pointsize + sizeof(int) - 1) / sizeof(int);
08215   // Now point size is the ints (inidcated by pointmarkindex) plus:
08216   //   - an integer for boundary marker;
08217   //   - an integer for vertex type;
08218   pointsize = (pointmarkindex + 2) * sizeof(int);
08219   // Decide the wordtype used in vertex pool.
08220   wtype = (sizeof(REAL) >= sizeof(tetrahedron)) ? FLOATINGPOINT : POINTER;
08221   // Initialize the pool of vertices.
08222   points = new memorypool(pointsize, VERPERBLOCK, wtype, 0);
08223 
08224   // The number of bytes occupied by a tetrahedron.  There are four pointers
08225   //   to other tetrahedra, four pointers to corners, and possibly four
08226   //   pointers to subfaces.
08227   elesize = (8 + b->useshelles * 6) * sizeof(tetrahedron);
08228   // If Voronoi diagram is wanted, make sure we have additional space.
08229   if (b->voroout && (b->useshelles == 0)) {
08230     elesize = (8 + 4) * sizeof(tetrahedron);
08231   }
08232   // The index within each element at which its attributes are found, where
08233   //   the index is measured in REALs.
08234   elemattribindex = (elesize + sizeof(REAL) - 1) / sizeof(REAL);
08235   // The index within each element at which the maximum voulme bound is
08236   //   found, where the index is measured in REALs.  Note that if the
08237   //   `b->regionattrib' flag is set, an additional attribute will be added.
08238   volumeboundindex = elemattribindex + in->numberoftetrahedronattributes
08239                    + (b->regionattrib > 0);
08240   // If element attributes or an constraint are needed, increase the number
08241   //   of bytes occupied by an element.
08242   if (b->varvolume) {
08243     elesize = (volumeboundindex + 1) * sizeof(REAL);
08244   } else if (in->numberoftetrahedronattributes + b->regionattrib > 0) {
08245     elesize = volumeboundindex * sizeof(REAL);
08246   }
08247   // If element neighbor graph is requested (-n switch), an additional
08248   //   integer is allocated for each element.
08249   elemmarkerindex = (elesize + sizeof(int) - 1) / sizeof(int);
08250   if (b->neighout || b->voroout) {
08251     elesize = (elemmarkerindex + 1) * sizeof(int);
08252   }
08253   // If -o2 switch is used, an additional pointer pointed to the list of
08254   //   higher order nodes is allocated for each element.
08255   highorderindex = (elesize + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08256   if (b->order == 2) {
08257     elesize = (highorderindex + 1) * sizeof(tetrahedron);
08258   }
08259   // Having determined the memory size of an element, initialize the pool.
08260   tetrahedrons = new memorypool(elesize, ELEPERBLOCK, POINTER, 8);
08261 
08262   if (b->useshelles) {
08263     // The number of bytes occupied by a subface.  The list of pointers
08264     //   stored in a subface are: three to other subfaces, three to corners,
08265     //   three to subsegments, two to tetrahedra, and one to a badface.
08266     shsize = 12 * sizeof(shellface);
08267     // The index within each subface at which the maximum area bound is
08268     //   found, where the index is measured in REALs.
08269     areaboundindex = (shsize + sizeof(REAL) - 1) / sizeof(REAL);
08270     // If -q switch is in use, increase the number of bytes occupied by
08271     //   a subface for saving maximum area bound.
08272     if (b->quality && varconstraint) {
08273       shsize = (areaboundindex + 1) * sizeof(REAL);
08274     } else {
08275       shsize = areaboundindex * sizeof(REAL);
08276     }
08277     // The index within subface at which the facet marker is found. Ensure
08278     //   the marker is aligned to a sizeof(int)-byte address.
08279     shmarkindex = (shsize + sizeof(int) - 1) / sizeof(int);
08280     // Increase the number of bytes by two or three integers, one for facet
08281     //   marker, one for shellface type, and optionally one for pbc group.
08282     shsize = (shmarkindex + 2 + checkpbcs) * sizeof(int);
08283     // Initialize the pool of subfaces. Each subface record is eight-byte
08284     //   aligned so it has room to store an edge version (from 0 to 5) in
08285     //   the least three bits.
08286     subfaces = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08287     // Initialize the pool of subsegments. The subsegment's record is same
08288     //   with subface.
08289     subsegs = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08290     // Initialize the "outer space" tetrahedron and omnipresent subface.
08291     dummyinit(tetrahedrons->itemwords, subfaces->itemwords);
08292   } else {
08293     // Initialize the "outer space" tetrahedron.
08294     dummyinit(tetrahedrons->itemwords, 0);
08295   }
08296 }
08297 
08299 //                                                                           //
08300 // tetrahedrondealloc()    Deallocate space for a tet., marking it dead.     //
08301 //                                                                           //
08303 
08304 void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
08305 {
08306   // Set tetrahedron's vertices to NULL. This makes it possible to detect
08307   //   dead tetrahedra when traversing the list of all tetrahedra.
08308   dyingtetrahedron[4] = (tetrahedron) NULL;
08309   dyingtetrahedron[5] = (tetrahedron) NULL;
08310   dyingtetrahedron[6] = (tetrahedron) NULL;
08311   dyingtetrahedron[7] = (tetrahedron) NULL;
08312   tetrahedrons->dealloc((void *) dyingtetrahedron);
08313 }
08314 
08316 //                                                                           //
08317 // tetrahedrontraverse()    Traverse the tetrahedra, skipping dead ones.     //
08318 //                                                                           //
08320 
08321 tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse()
08322 {
08323   tetrahedron *newtetrahedron;
08324 
08325   do {
08326     newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
08327     if (newtetrahedron == (tetrahedron *) NULL) {
08328       return (tetrahedron *) NULL;
08329     }
08330   } while (newtetrahedron[7] == (tetrahedron) NULL);      // Skip dead ones.
08331   return newtetrahedron;
08332 }
08333 
08335 //                                                                           //
08336 // shellfacedealloc()    Deallocate space for a shellface, marking it dead.  //
08337 //                       Used both for dealloc a subface and subsegment.     //
08338 //                                                                           //
08340 
08341 void tetgenmesh::shellfacedealloc(memorypool *pool, shellface *dyingsh)
08342 {
08343   // Set shellface's vertices to NULL. This makes it possible to detect dead
08344   //   shellfaces when traversing the list of all shellfaces.
08345   dyingsh[3] = (shellface) NULL;
08346   dyingsh[4] = (shellface) NULL;
08347   dyingsh[5] = (shellface) NULL;
08348   pool->dealloc((void *) dyingsh);
08349 }
08350 
08352 //                                                                           //
08353 // shellfacetraverse()    Traverse the subfaces, skipping dead ones. Used    //
08354 //                        for both subfaces and subsegments pool traverse.   //
08355 //                                                                           //
08357 
08358 tetgenmesh::shellface* tetgenmesh::shellfacetraverse(memorypool *pool)
08359 {
08360   shellface *newshellface;
08361 
08362   do {
08363     newshellface = (shellface *) pool->traverse();
08364     if (newshellface == (shellface *) NULL) {
08365       return (shellface *) NULL;
08366     }
08367   } while (newshellface[3] == (shellface) NULL);          // Skip dead ones.
08368   return newshellface;
08369 }
08370 
08372 //                                                                           //
08373 // badfacedealloc()    Deallocate space for a badface, marking it dead.      //
08374 //                                                                           //
08376 
08377 void tetgenmesh::badfacedealloc(memorypool *pool, badface *dying)
08378 {
08379   // Set badface's forg to NULL. This makes it possible to detect dead
08380   //   ones when traversing the list of all items.
08381   dying->forg = (point) NULL;
08382   pool->dealloc((void *) dying);
08383 }
08384 
08386 //                                                                           //
08387 // badfacetraverse()    Traverse the pools, skipping dead ones.              //
08388 //                                                                           //
08390 
08391 tetgenmesh::badface* tetgenmesh::badfacetraverse(memorypool *pool)
08392 {
08393   badface *newsh;
08394 
08395   do {
08396     newsh = (badface *) pool->traverse();
08397     if (newsh == (badface *) NULL) {
08398       return (badface *) NULL;
08399     }
08400   } while (newsh->forg == (point) NULL);               // Skip dead ones.
08401   return newsh;
08402 }
08403 
08405 //                                                                           //
08406 // pointdealloc()    Deallocate space for a point, marking it dead.          //
08407 //                                                                           //
08409 
08410 void tetgenmesh::pointdealloc(point dyingpoint)
08411 {
08412   // Mark the point as dead. This  makes it possible to detect dead points
08413   //   when traversing the list of all points.
08414   setpointtype(dyingpoint, DEADVERTEX);
08415   points->dealloc((void *) dyingpoint);
08416 }
08417 
08419 //                                                                           //
08420 // pointtraverse()    Traverse the points, skipping dead ones.               //
08421 //                                                                           //
08423 
08424 tetgenmesh::point tetgenmesh::pointtraverse()
08425 {
08426   point newpoint;
08427 
08428   do {
08429     newpoint = (point) points->traverse();
08430     if (newpoint == (point) NULL) {
08431       return (point) NULL;
08432     }
08433   } while (pointtype(newpoint) == DEADVERTEX);            // Skip dead ones.
08434   return newpoint;
08435 }
08436 
08438 //                                                                           //
08439 // maketetrahedron()    Create a new tetrahedron.                            //
08440 //                                                                           //
08442 
08443 void tetgenmesh::maketetrahedron(triface *newtet)
08444 {
08445   newtet->tet = (tetrahedron *) tetrahedrons->alloc();
08446   // Initialize the four adjoining tetrahedra to be "outer space".
08447   newtet->tet[0] = (tetrahedron) dummytet;
08448   newtet->tet[1] = (tetrahedron) dummytet;
08449   newtet->tet[2] = (tetrahedron) dummytet;
08450   newtet->tet[3] = (tetrahedron) dummytet;
08451   // Four NULL vertices.
08452   newtet->tet[4] = (tetrahedron) NULL;
08453   newtet->tet[5] = (tetrahedron) NULL;
08454   newtet->tet[6] = (tetrahedron) NULL;
08455   newtet->tet[7] = (tetrahedron) NULL;
08456   // Initialize the four adjoining subfaces to be the omnipresent subface.
08457   if (b->useshelles) {
08458     newtet->tet[8 ] = (tetrahedron) dummysh;
08459     newtet->tet[9 ] = (tetrahedron) dummysh;
08460     newtet->tet[10] = (tetrahedron) dummysh;
08461     newtet->tet[11] = (tetrahedron) dummysh;
08462     newtet->tet[12] = (tetrahedron) dummysh;
08463     newtet->tet[13] = (tetrahedron) dummysh;
08464   }
08465   for (int i = 0; i < in->numberoftetrahedronattributes; i++) {
08466     setelemattribute(newtet->tet, i, 0.0);
08467   }
08468   if (b->varvolume) {
08469     setvolumebound(newtet->tet, -1.0);
08470   }
08471   // Initialize the location and version to be Zero.
08472   newtet->loc = 0;
08473   newtet->ver = 0;
08474 }
08475 
08477 //                                                                           //
08478 // makeshellface()    Create a new shellface with version zero. Used for     //
08479 //                    both subfaces and seusegments.                         //
08480 //                                                                           //
08482 
08483 void tetgenmesh::makeshellface(memorypool *pool, face *newface)
08484 {
08485   newface->sh = (shellface *) pool->alloc();
08486   //Initialize the three adjoining subfaces to be the omnipresent subface.
08487   newface->sh[0] = (shellface) dummysh;
08488   newface->sh[1] = (shellface) dummysh;
08489   newface->sh[2] = (shellface) dummysh;
08490   // Three NULL vertices.
08491   newface->sh[3] = (shellface) NULL;
08492   newface->sh[4] = (shellface) NULL;
08493   newface->sh[5] = (shellface) NULL;
08494   // Initialize the two adjoining tetrahedra to be "outer space".
08495   newface->sh[6] = (shellface) dummytet;
08496   newface->sh[7] = (shellface) dummytet;
08497   // Initialize the three adjoining subsegments to be the omnipresent
08498   //   subsegments.
08499   newface->sh [8] = (shellface) dummysh;
08500   newface->sh [9] = (shellface) dummysh;
08501   newface->sh[10] = (shellface) dummysh;
08502   // Initialize the pointer to badface structure.
08503   newface->sh[11] = (shellface) NULL;
08504   if (b->quality && varconstraint) {
08505     // Initialize the maximum area bound.
08506     setareabound(*newface, 0.0);
08507   }
08508   // Set the boundary marker to zero.
08509   setshellmark(*newface, 0);
08510   // Set the type.
08511   setshelltype(*newface, NSHARP);
08512   if (checkpbcs) {
08513     // Set the pbcgroup be ivalid.
08514     setshellpbcgroup(*newface, -1);
08515   }
08516   // Initialize the version to be Zero.
08517   newface->shver = 0;
08518 }
08519 
08521 //                                                                           //
08522 // makepoint()    Create a new point.                                        //
08523 //                                                                           //
08525 
08526 void tetgenmesh::makepoint(point* pnewpoint)
08527 {
08528   int ptmark, i;
08529 
08530   *pnewpoint = (point) points->alloc();
08531   // Initialize three coordinates.
08532   (*pnewpoint)[0] = 0.0;
08533   (*pnewpoint)[1] = 0.0;
08534   (*pnewpoint)[2] = 0.0;
08535   // Initialize the list of user-defined attributes.
08536   for (i = 0; i < in->numberofpointattributes; i++) {
08537     (*pnewpoint)[3 + i] = 0.0;
08538   }
08539   // Initialize the metric tensor.
08540   for (i = 0; i < sizeoftensor; i++) {
08541     (*pnewpoint)[pointmtrindex + i] = 0.0;
08542   }
08543   if (b->plc || b->refine) {
08544     // Initialize the point-to-simplex filed.
08545     setpoint2tet(*pnewpoint, NULL);
08546     setpoint2sh(*pnewpoint, NULL);
08547     setpoint2ppt(*pnewpoint, NULL);
08548     if (b->metric) {
08549       setpoint2bgmtet(*pnewpoint, NULL);
08550     }
08551     if (checkpbcs) {
08552       // Initialize the other pointer to its pbc point.
08553       setpoint2pbcpt(*pnewpoint, NULL);
08554     }
08555   }
08556   // Initialize the point marker (starting from in->firstnumber).
08557   ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
08558   setpointmark(*pnewpoint, ptmark);
08559   // Initialize the point type.
08560   setpointtype(*pnewpoint, UNUSEDVERTEX);
08561 }
08562 
08563 //
08564 // End of memory management routines
08565 //
08566 
08567 //
08568 // Begin of point location routines
08569 //
08570 
08572 //                                                                           //
08573 // randomnation()    Generate a random number between 0 and 'choices' - 1.   //
08574 //                                                                           //
08576 
08577 unsigned long tetgenmesh::randomnation(unsigned int choices)
08578 {
08579   unsigned long newrandom;
08580 
08581   if (choices >= 714025l) {
08582     newrandom = (randomseed * 1366l + 150889l) % 714025l;
08583     randomseed = (newrandom * 1366l + 150889l) % 714025l;
08584     newrandom = newrandom * (choices / 714025l) + randomseed;
08585     if (newrandom >= choices) {
08586       return newrandom - choices;
08587     } else {
08588       return newrandom;
08589     }
08590   } else {
08591     randomseed = (randomseed * 1366l + 150889l) % 714025l;
08592     return randomseed % choices;
08593   }
08594   // Old function.
08595   // randomseed = (randomseed * 1366l + 150889l) % 714025l;
08596   // return randomseed / (714025l / choices + 1);
08597 }
08598 
08600 //                                                                           //
08601 // distance2()    Returns the square "distance" of a tetrahedron to point p. //
08602 //                                                                           //
08604 
08605 REAL tetgenmesh::distance2(tetrahedron* tetptr, point p)
08606 {
08607   point p1, p2, p3, p4;
08608   REAL dx, dy, dz;
08609 
08610   p1 = (point) tetptr[4];
08611   p2 = (point) tetptr[5];
08612   p3 = (point) tetptr[6];
08613   p4 = (point) tetptr[7];
08614 
08615   dx = p[0] - 0.25 * (p1[0] + p2[0] + p3[0] + p4[0]);
08616   dy = p[1] - 0.25 * (p1[1] + p2[1] + p3[1] + p4[1]);
08617   dz = p[2] - 0.25 * (p1[2] + p2[2] + p3[2] + p4[2]);
08618 
08619   return dx * dx + dy * dy + dz * dz;
08620 }
08621 
08623 //                                                                           //
08624 // preciselocate()    Find a simplex containing a given point.               //
08625 //                                                                           //
08626 // This routine implements the simple Walk-through point location algorithm. //
08627 // Begins its search from 'searchtet', assume there is a line segment L from //
08628 // a vertex of 'searchtet' to the query point 'searchpt', and simply walk    //
08629 // towards 'searchpt' by traversing all faces intersected by L.              //
08630 //                                                                           //
08631 // On completion, 'searchtet' is a tetrahedron that contains 'searchpt'. The //
08632 // returned value indicates one of the following cases:                      //
08633 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchtet' //
08634 //     is a handle whose origin is the existing vertex.                      //
08635 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchtet' is a    //
08636 //     handle whose primary edge is the edge on which the point lies.        //
08637 //   - Returns ONFACE if the point lies strictly within a face. 'searchtet'  //
08638 //     is a handle whose primary face is the face on which the point lies.   //
08639 //   - Returns INTETRAHEDRON if the point lies strictly in a tetrahededron.  //
08640 //     'searchtet' is a handle on the tetrahedron that contains the point.   //
08641 //   - Returns OUTSIDE if the point lies outside the mesh. 'searchtet' is a  //
08642 //     handle whose location is the face the point is to 'above' of.         //
08643 //                                                                           //
08644 // WARNING: This routine is designed for convex triangulations, and will not //
08645 // generally work after the holes and concavities have been carved.          //
08646 //                                                                           //
08647 // If 'maxtetnumber' > 0, stop the searching process if the number of passed //
08648 // tets is larger than it and return OUTSIDE.                                //
08649 //                                                                           //
08651 
08652 enum tetgenmesh::locateresult tetgenmesh::preciselocate(point searchpt,
08653   triface* searchtet, long maxtetnumber)
08654 {
08655   triface backtracetet;
08656   triface walkthroface;
08657   point forg, fdest, fapex, toppo;
08658   REAL ori1, ori2, ori3, ori4;
08659   long tetnumber;
08660   int side;
08661 
08662   if (isdead(searchtet)) searchtet->tet = dummytet;
08663   if (searchtet->tet == dummytet) {
08664     searchtet->loc = 0;
08665     symself(*searchtet);
08666   }
08667   // 'searchtet' should be a valid tetrahedron now.
08668 #ifdef SELF_CHECK
08669   // assert(!isdead(searchtet) && (searchtet->tet != dummytet));
08670 #endif
08671   if (isdead(searchtet)) {
08672     printf("Warning:  Point location failed.\n");
08673     return OUTSIDE;
08674   }
08675 
08676   searchtet->ver = 0; // Keep in CCW edge ring.
08677   // Find a face of 'searchtet' such that the 'searchpt' lies strictly
08678   //   above it.  Such face should always exist.
08679   for (searchtet->loc = 0; searchtet->loc < 4; searchtet->loc++) {
08680     forg = org(*searchtet);
08681     fdest = dest(*searchtet);
08682     fapex = apex(*searchtet);
08683     ori1 = orient3d(forg, fdest, fapex, searchpt);
08684     if (ori1 < 0.0) break;
08685   }
08686 #ifdef SELF_CHECK
08687   assert(searchtet->loc < 4);
08688 #endif
08689 
08690   // Define 'tetnumber' for exit the loop when it's running endless.
08691   tetnumber = 0l;
08692   while ((maxtetnumber > 0l) && (tetnumber <= maxtetnumber)) {
08693     // Check if we are reaching the boundary of the triangulation.
08694     if (searchtet->tet == dummytet) {
08695       *searchtet = backtracetet;
08696       return OUTSIDE;
08697     }
08698     // Initialize the face for returning the walk-through face.
08699     walkthroface.tet = (tetrahedron *) NULL;
08700     // Adjust the edge ring, so that 'ori1 < 0.0' holds.
08701     searchtet->ver = 0;
08702     // 'toppo' remains unchange for the following orientation tests.
08703     toppo = oppo(*searchtet);
08704     // Check the three sides of 'searchtet' to find the face through which
08705     //   we can walk next.
08706     for (side = 0; side < 3; side++) {
08707       forg = org(*searchtet);
08708       fdest = dest(*searchtet);
08709       ori2 = orient3d(forg, fdest, toppo, searchpt);
08710       if (ori2 == 0.0) {
08711         // They are coplanar, check if 'searchpt' lies inside, or on an edge,
08712         //   or coindice with a vertex of face (forg, fdest, toppo).
08713         fapex = apex(*searchtet);
08714         ori3 = orient3d(fdest, fapex, toppo, searchpt);
08715         if (ori3 < 0.0) {
08716           // Outside the face (fdest, fapex, toppo), walk through it.
08717           enextself(*searchtet);
08718           fnext(*searchtet, walkthroface);
08719           break;
08720         }
08721         ori4 = orient3d(fapex, forg, toppo, searchpt);
08722         if (ori4 < 0.0) {
08723           // Outside the face (fapex, forg, toppo), walk through it.
08724           enext2self(*searchtet);
08725           fnext(*searchtet, walkthroface);
08726           break;
08727         }
08728         // Remember, ori1 < 0.0, which means 'searchpt' will not on edge
08729         //   (forg, fdest) or on vertex forg or fdest.
08730 #ifdef SELF_CHECK
08731         assert(ori1 < 0.0);
08732 #endif
08733         // The rest possible cases are:
08734         //   (1) 'searchpt' lies on edge (fdest, toppo);
08735         //   (2) 'searchpt' lies on edge (toppo, forg);
08736         //   (3) 'searchpt' coincident with toppo;
08737         //   (4) 'searchpt' lies inside face (forg, fdest, toppo).
08738         fnextself(*searchtet);
08739         if (ori3 == 0.0) {
08740           if (ori4 == 0.0) {
08741             // Case (4).
08742             enext2self(*searchtet);
08743             return ONVERTEX;
08744           } else {
08745             // Case (1).
08746             enextself(*searchtet);
08747             return ONEDGE;
08748           }
08749         }
08750         if (ori4 == 0.0) {
08751           // Case (2).
08752           enext2self(*searchtet);
08753           return ONEDGE;
08754         }
08755         // Case (4).
08756         return ONFACE;
08757       } else if (ori2 < 0.0) {
08758         // Outside the face (forg, fdest, toppo), walk through it.
08759         fnext(*searchtet, walkthroface);
08760         break;
08761       }
08762       // Go to check next side.
08763       enextself(*searchtet);
08764     }
08765     if (side >= 3) {
08766       // Found! Inside tetrahedron.
08767       return INTETRAHEDRON;
08768     }
08769     // We walk through the face 'walkthroface' and continue the searching.
08770 #ifdef SELF_CHECK
08771     assert(walkthroface.tet != (tetrahedron *) NULL);
08772 #endif
08773     // Store the face handle in 'backtracetet' before we take the real walk.
08774     //   So we are able to restore the handle to 'searchtet' if we are
08775     //   reaching the outer boundary.
08776     backtracetet = walkthroface;
08777     sym(walkthroface, *searchtet);
08778     tetnumber++;
08779   }
08780 
08781   // Should never be here.
08782   // printf("Internal error in preciselocate(): Point location failed.\n");
08783   // internalerror();
08784   return OUTSIDE;
08785 }
08786 
08788 //                                                                           //
08789 // locate()    Find a simplex containing a given point.                      //
08790 //                                                                           //
08791 // This routine implements Muecke's Jump-and-walk point location algorithm.  //
08792 // It improves the simple walk-through by "jumping" to a good starting point //
08793 // via random sampling.  Searching begins from one of handles:  the input    //
08794 // 'searchtet', a recently encountered tetrahedron 'recenttet',  or from one //
08795 // chosen from a random sample.  The choice is made by determining which one //
08796 // 's barycenter is closest to the point we are searcing for.  Having chosen //
08797 // the starting tetrahedron, the simple Walk-through algorithm is used to do //
08798 // the real walking.                                                         //
08799 //                                                                           //
08800 // The return value indicates the location of the 'searchpt' (INTETRAHEDRON, //
08801 // or ONFACE, ...). 'searchtet' is adjusted to a tetrahedron corresponding   //
08802 // to that value. See the introduction part of preciselocate() for detail.   //
08803 //                                                                           //
08804 // WARNING: This routine is designed for convex triangulations, and will not //
08805 // generally work after the holes and concavities have been carved.          //
08806 //                                                                           //
08808 
08809 enum tetgenmesh::locateresult tetgenmesh::locate(point searchpt,
08810   triface *searchtet)
08811 {
08812   tetrahedron *firsttet, *tetptr;
08813   void **sampleblock;
08814   long sampleblocks, samplesperblock, samplenum;
08815   long tetblocks, i, j;
08816   unsigned long alignptr;
08817   REAL searchdist, dist;
08818 
08819   // 'searchtet' should be a valid tetrahedron.
08820   if (isdead(searchtet)) {
08821     searchtet->tet = dummytet;
08822   }
08823   if (searchtet->tet == dummytet) {
08824     // This is an 'Outer Space' handle, get a hull tetrahedron.
08825     searchtet->loc = 0;
08826     symself(*searchtet);
08827   }
08828 #ifdef SELF_CHECK
08829   // assert(!isdead(searchtet));
08830 #endif
08831   if (isdead(searchtet)) {
08832     printf("Warning:  Point location failed.\n");
08833     return OUTSIDE;
08834   }
08835 
08836   // Get the distance from the suggested starting tet to the point we seek.
08837   searchdist = distance2(searchtet->tet, searchpt);
08838 
08839   // If a recently encountered tetrahedron has been recorded and has not
08840   //   been deallocated, test it as a good starting point.
08841   if (!isdead(&recenttet) && (recenttet.tet != searchtet->tet)) {
08842     dist = distance2(recenttet.tet, searchpt);
08843     if (dist < searchdist) {
08844       *searchtet = recenttet;
08845       searchdist = dist;
08846     }
08847   }
08848 
08849   // Select "good" candidate using k random samples, taking the closest one.
08850   //   The number of random samples taken is proportional to the fourth root
08851   //   of the number of tetrahedra in the mesh. The next bit of code assumes
08852   //   that the number of tetrahedra increases monotonically.
08853   while (SAMPLEFACTOR * samples * samples * samples * samples <
08854          tetrahedrons->items) {
08855     samples++;
08856   }
08857   // Find how much blocks in current tet pool.
08858   tetblocks = (tetrahedrons->maxitems + ELEPERBLOCK - 1) / ELEPERBLOCK;
08859   // Find the average samles per block. Each block at least have 1 sample.
08860   samplesperblock = 1 + (samples / tetblocks);
08861   sampleblocks = samples / samplesperblock;
08862   sampleblock = tetrahedrons->firstblock;
08863   for (i = 0; i < sampleblocks; i++) {
08864     alignptr = (unsigned long) (sampleblock + 1);
08865     firsttet = (tetrahedron *)
08866                (alignptr + (unsigned long) tetrahedrons->alignbytes
08867                - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08868     for (j = 0; j < samplesperblock; j++) {
08869       if (i == tetblocks - 1) {
08870         // This is the last block.
08871         samplenum = randomnation((int)
08872                       (tetrahedrons->maxitems - (i * ELEPERBLOCK)));
08873       } else {
08874         samplenum = randomnation(ELEPERBLOCK);
08875       }
08876       tetptr = (tetrahedron *)
08877                (firsttet + (samplenum * tetrahedrons->itemwords));
08878       if (tetptr[4] != (tetrahedron) NULL) {
08879         dist = distance2(tetptr, searchpt);
08880         if (dist < searchdist) {
08881           searchtet->tet = tetptr;
08882           searchdist = dist;
08883         }
08884       }
08885     }
08886     sampleblock = (void **) *sampleblock;
08887   }
08888 
08889   // Call simple walk-through to locate the point.
08890   return preciselocate(searchpt, searchtet, tetrahedrons->items);
08891 }
08892 
08894 //                                                                           //
08895 // adjustlocate()    Adjust the precise location of a vertex.                //
08896 //                                                                           //
08897 // 'precise' is the value returned from preciselocate().  It indicates the   //
08898 // exact location of the point 'searchpt' with respect to the tetrahedron    //
08899 // 'searchtet'.  'epspp' is a given relative tolerance.                      //
08900 //                                                                           //
08901 // This routine re-evaluates the orientations of searchpt with respect to    //
08902 // the four sides of searchtet. Detects the coplanarities by additinal tests //
08903 // which are based on the given tolerance. If 'precise' is ONFACE or ONEDGE, //
08904 // we can save one or two orientation tests.                                 //
08905 //                                                                           //
08906 // The return value indicates the location of the 'searchpt' (INTETRAHEDRON, //
08907 // or ONFACE, ...). 'searchtet' is adjusted to a tetrahedron corresponding   //
08908 // to that value. See the introduction part of preciselocate() for detail.   //
08909 //                                                                           //
08910 // WARNING:  This routine detect degenerate case using relative tolerance.   //
08911 // It is better used after locate() or preciselocate().  For general inputs, //
08912 // it may not able to tell the correct location.                             //
08913 //                                                                           //
08915 
08916 enum tetgenmesh::locateresult tetgenmesh::adjustlocate(point searchpt,
08917   triface* searchtet, enum locateresult precise, REAL epspp)
08918 {
08919   point torg, tdest, tapex, toppo;
08920   REAL s1, s2, s3, s4;
08921 
08922   // For the given 'searchtet', the orientations tests are:
08923   //  s1: (tdest, torg, tapex, searchpt);
08924   //  s2: (torg, tdest, toppo, searchpt);
08925   //  s3: (tdest, tapex, toppo, searchpt);
08926   //  s4: (tapex, torg, toppo, searchpt);
08927   adjustedgering(*searchtet, CCW);
08928   torg = org(*searchtet);
08929   tdest = dest(*searchtet);
08930   tapex = apex(*searchtet);
08931   toppo = oppo(*searchtet);
08932 
08933   switch (precise) {
08934   case ONVERTEX:
08935     // This case we don't need do any further test.
08936     return ONVERTEX;
08937   case ONEDGE:
08938     // (torg, tdest);
08939     s1 = 0.0;
08940     s2 = 0.0;
08941     break;
08942   case ONFACE:
08943     // (tdest, torg, tapex);
08944     s1 = 0.0;
08945     s2 = orient3d(torg, tdest, toppo, searchpt);
08946     break;
08947   default: // INTETRAHEDRON or OUTSIDE
08948     s1 = orient3d(tdest, torg, tapex, searchpt);
08949     s2 = orient3d(torg, tdest, toppo, searchpt);
08950   }
08951 
08952   if (s1 != 0.0) {
08953     if (iscoplanar(tdest, torg, tapex, searchpt, s1, epspp)) {
08954       s1 = 0.0;
08955     }
08956   }
08957   if (s1 < 0.0) {
08958     return OUTSIDE;
08959   }
08960 
08961   if (s2 != 0.0) {
08962     if (iscoplanar(torg, tdest, toppo, searchpt, s2, epspp)) {
08963       s2 = 0.0;
08964     }
08965   }
08966   if (s2 < 0.0) {
08967     fnextself(*searchtet);
08968     return OUTSIDE;
08969   }
08970 
08971   s3 = orient3d(tdest, tapex, toppo, searchpt);
08972   if (s3 != 0.0) {
08973     if (iscoplanar(tdest, tapex, toppo, searchpt, s3, epspp)) {
08974       s3 = 0.0;
08975     }
08976   }
08977   if (s3 < 0.0) {
08978     enextfnextself(*searchtet);
08979     return OUTSIDE;
08980   }
08981 
08982   s4 = orient3d(tapex, torg, toppo, searchpt);
08983   if (s4 != 0.0) {
08984     if (iscoplanar(tapex, torg, toppo, searchpt, s4, epspp)) {
08985       s4 = 0.0;
08986     }
08987   }
08988   if (s4 < 0.0) {
08989     enext2fnextself(*searchtet);
08990     return OUTSIDE;
08991   }
08992 
08993   // Determine degenerate cases.
08994   if (s1 == 0.0) {
08995     if (s2 == 0.0) {
08996       if (s3 == 0.0) {
08997         // On tdest.
08998         enextself(*searchtet);
08999         return ONVERTEX;
09000       }
09001       if (s4 == 0.0) {
09002         // On torg.
09003         return ONVERTEX;
09004       }
09005       // On edge (torg, tdest).
09006       return ONEDGE;
09007     }
09008     if (s3 == 0.0) {
09009       if (s4 == 0.0) {
09010         // On tapex.
09011         enext2self(*searchtet);
09012         return ONVERTEX;
09013       }
09014       // On edge (tdest, tapex).
09015       enextself(*searchtet);
09016       return ONEDGE;
09017     }
09018     if (s4 == 0.0) {
09019       // On edge (tapex, torg).
09020       enext2self(*searchtet);
09021       return ONEDGE;
09022     }
09023     // On face (torg, tdest, tapex).
09024     return ONFACE;
09025   }
09026   if (s2 == 0.0) {
09027     fnextself(*searchtet);
09028     if (s3 == 0.0) {
09029       if (s4 == 0.0) {
09030         // On toppo.
09031         enext2self(*searchtet);
09032         return ONVERTEX;
09033       }
09034       // On edge (tdest, toppo).
09035       enextself(*searchtet);
09036       return ONEDGE;
09037     }
09038     if (s4 == 0.0) {
09039       // On edge (toppo, torg).
09040       enext2self(*searchtet);
09041       return ONEDGE;
09042     }
09043     // On face (torg, tdest, toppo).
09044     return ONFACE;
09045   }
09046   if (s3 == 0.0) {
09047     enextfnextself(*searchtet);
09048     if (s4 == 0.0) {
09049       // On edge (tapex, toppo).
09050       enextself(*searchtet);
09051       return ONEDGE;
09052     }
09053     // On face (tdest, tapex, toppo).
09054     return ONFACE;
09055   }
09056   if (s4 == 0.0) {
09057     enext2fnextself(*searchtet);
09058     // On face (tapex, torg, toppo).
09059     return ONFACE;
09060   }
09061 
09062   // Inside tetrahedron.
09063   return INTETRAHEDRON;
09064 }
09065 
09067 //                                                                           //
09068 // hullwalk()    Find a tetrahedron on the hull to continue search.          //
09069 //                                                                           //
09071 
09072 enum tetgenmesh::locateresult tetgenmesh::hullwalk(point searchpt,
09073   triface *hulltet)
09074 {
09075   list* travtetlist;
09076   triface travtet, neightet;
09077   point pa, pb, pc;
09078   enum locateresult loc;
09079   REAL ori;
09080   int i;
09081 
09082   travtetlist = new list(sizeof(triface), NULL, 256);
09083   travtet = *hulltet;
09084   infect(travtet);
09085   travtetlist->append(&travtet);
09086 
09087   loc = OUTSIDE;
09088   for (i = 0; i < travtetlist->len(); i++) {
09089     travtet = * (triface *)(* travtetlist)[i];
09090     // Choose the CCW-edgering in face.
09091     travtet.ver = 0;
09092     // Look for a side where pt lies below it.
09093     for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09094       pa = org(travtet);
09095       pb = dest(travtet);
09096       pc = apex(travtet);
09097       ori = orient3d(pa, pb, pc, searchpt);
09098       if (ori > 0.0) break;
09099     }
09100     // Is pt above all (or coplanar with some of) the four sides?
09101     if (travtet.loc == 4) {
09102       hulltet->tet = travtet.tet;
09103       loc = adjustlocate(searchpt, hulltet, INTETRAHEDRON, b->epsilon);
09104       assert(loc != OUTSIDE);
09105     } else { // ori > 0.0
09106       // pt is below (behind) this side. We want to walk through it.
09107       sym(travtet, neightet);
09108       if (neightet.tet == dummytet) {
09109         // This is a hull side. Is p approximately on this side.
09110         loc = adjustlocate(searchpt, &travtet, OUTSIDE, b->epsilon);
09111       }
09112       if (loc == OUTSIDE) {
09113         // Let's collect all the neighbors for next searching.
09114         for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09115           sym(travtet, neightet);
09116           if ((neightet.tet != dummytet) && !infected(neightet)) {
09117             // Neighbor exists and not visited.
09118             infect(neightet);
09119             travtetlist->append(&neightet);
09120           }
09121         } // for (travtet.loc = 0;
09122       } // if (loc == OUTSIDE)
09123     } // if (travtet.loc == 4)
09124     if (loc != OUTSIDE) break;
09125   } // for (i = 0; i < travtetlist->len(); i++)
09126 
09127   // Uninfect traversed tets.
09128   for (i = 0; i < travtetlist->len(); i++) {
09129     travtet = * (triface *)(* travtetlist)[i];
09130     uninfect(travtet);
09131   }
09132 
09133   delete travtetlist;
09134   return loc;
09135 }
09136 
09138 //                                                                           //
09139 // locatesub()    Find a point in the surface mesh of a facet.               //
09140 //                                                                           //
09141 // Searching begins from the input 'searchsh', it should be a handle on the  //
09142 // convex hull of the facet triangulation.                                   //
09143 //                                                                           //
09144 // If 'stopatseg' is nonzero, the search will stop if it tries to walk       //
09145 // through a subsegment, and will return OUTSIDE.                            //
09146 //                                                                           //
09147 // On completion, 'searchsh' is a subface that contains 'searchpt'.          //
09148 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchsh'  //
09149 //     is a handle whose origin is the existing vertex.                      //
09150 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchsh' is a     //
09151 //     handle whose primary edge is the edge on which the point lies.        //
09152 //   - Returns ONFACE if the point lies strictly within a subface.           //
09153 //     'searchsh' is a handle on which the point lies.                       //
09154 //   - Returns OUTSIDE if the point lies outside the triangulation.          //
09155 //                                                                           //
09156 // WARNING: This routine is designed for convex triangulations, and will not //
09157 // not generally work after the holes and concavities have been carved.      //
09158 //                                                                           //
09160 
09161 enum tetgenmesh::locateresult tetgenmesh::locatesub(point searchpt,
09162   face* searchsh, int stopatseg, REAL epspp)
09163 {
09164   face backtracksh, spinsh, checkedge;
09165   point forg, fdest, fapex;
09166   REAL orgori, destori;
09167   REAL ori, sign;
09168   int moveleft, i;
09169 
09170   if (searchsh->sh == dummysh) {
09171     searchsh->shver = 0;
09172     spivotself(*searchsh);
09173 #ifdef SELF_CHECK
09174     assert(searchsh->sh != dummysh);
09175 #endif
09176   }
09177   // Find the sign to simulate that abovepoint is 'above' the facet.
09178   adjustedgering(*searchsh, CCW);
09179   forg = sorg(*searchsh);
09180   fdest = sdest(*searchsh);
09181   fapex = sapex(*searchsh);
09182   ori = orient3d(forg, fdest, fapex, abovepoint);
09183   sign = ori > 0.0 ? -1 : 1;
09184 
09185   // Orient 'searchsh' so that 'searchpt' is below it (i.e., searchpt has
09186   //   CCW orientation with respect to searchsh in plane).  Such edge
09187   //   should always exist. Save it as (forg, fdest).
09188   for (i = 0; i < 3; i++) {
09189     forg = sorg(*searchsh);
09190     fdest = sdest(*searchsh);
09191     ori = orient3d(forg, fdest, abovepoint, searchpt) * sign;
09192     if (ori > 0.0) break;
09193     senextself(*searchsh);
09194   }
09195 #ifdef SELF_CHECK
09196   assert(i < 3);
09197 #endif
09198 
09199   while (1) {
09200     fapex = sapex(*searchsh);
09201     // Check whether the apex is the point we seek.
09202     if (fapex[0] == searchpt[0] && fapex[1] == searchpt[1] &&
09203         fapex[2] == searchpt[2]) {
09204       senext2self(*searchsh);
09205       return ONVERTEX;
09206     }
09207     // Does the point lie on the other side of the line defined by the
09208     //   triangle edge opposite the triangle's destination?
09209     destori = orient3d(forg, fapex, abovepoint, searchpt) * sign;
09210     if (epspp > 0.0) {
09211       if (iscoplanar(forg, fapex, abovepoint, searchpt, destori, epspp)) {
09212         destori = 0.0;
09213       }
09214     }
09215     // Does the point lie on the other side of the line defined by the
09216     //   triangle edge opposite the triangle's origin?
09217     orgori = orient3d(fapex, fdest, abovepoint, searchpt) * sign;
09218     if (epspp > 0.0) {
09219       if (iscoplanar(fapex, fdest, abovepoint, searchpt, orgori, epspp)) {
09220         orgori = 0.0;
09221       }
09222     }
09223     if (destori > 0.0) {
09224       moveleft = 1;
09225     } else {
09226       if (orgori > 0.0) {
09227         moveleft = 0;
09228       } else {
09229         // The point must be on the boundary of or inside this triangle.
09230         if (destori == 0.0) {
09231           senext2self(*searchsh);
09232           return ONEDGE;
09233         }
09234         if (orgori == 0.0) {
09235           senextself(*searchsh);
09236           return ONEDGE;
09237         }
09238         return ONFACE;
09239       }
09240     }
09241     // Move to another triangle.  Leave a trace `backtracksh' in case
09242     //   walking off a boundary of the triangulation.
09243     if (moveleft) {
09244       senext2(*searchsh, backtracksh);
09245       fdest = fapex;
09246     } else {
09247       senext(*searchsh, backtracksh);
09248       forg = fapex;
09249     }
09250     // Check if we meet a segment.
09251     sspivot(backtracksh, checkedge);
09252     if (checkedge.sh != dummysh) {
09253       if (stopatseg) {
09254         // The flag indicates we should not cross a segment. Stop.
09255         *searchsh = backtracksh;
09256         return OUTSIDE;
09257       }
09258       // Try to walk through a segment. We need to find a coplanar subface
09259       //   sharing this segment to get into.
09260       spinsh = backtracksh;
09261       do {
09262         spivotself(spinsh);
09263         if (spinsh.sh == backtracksh.sh) {
09264           // Turn back, no coplanar subface is found.
09265           break;
09266         }
09267         // Are they belong to the same facet.
09268         if (shellmark(spinsh) == shellmark(backtracksh)) {
09269           // Find a coplanar subface. Walk into it.
09270           *searchsh = spinsh;
09271           break;
09272         }
09273         // Are they (nearly) coplanar?
09274         ori = orient3d(forg, fdest, sapex(backtracksh), sapex(spinsh));
09275         if (iscoplanar(forg, fdest, sapex(backtracksh), sapex(spinsh), ori,
09276                        b->epsilon)) {
09277           // Find a coplanar subface. Walk into it.
09278           *searchsh = spinsh;
09279           break;
09280         }
09281       } while (spinsh.sh != backtracksh.sh);
09282     } else {
09283       spivot(backtracksh, *searchsh);
09284     }
09285     // Check for walking right out of the triangulation.
09286     if ((searchsh->sh == dummysh) || (searchsh->sh == backtracksh.sh)) {
09287       // Go back to the last triangle.
09288       *searchsh = backtracksh;
09289       return OUTSIDE;
09290     }
09291     // To keep the same orientation wrt abovepoint.
09292     if (sorg(*searchsh) != forg) sesymself(*searchsh);
09293 #ifdef SELF_CHECK
09294     assert((sorg(*searchsh) == forg) && (sdest(*searchsh) == fdest));
09295 #endif
09296   }
09297 }
09298 
09300 //                                                                           //
09301 // adjustlocatesub()    Adjust the precise location of a vertex.             //
09302 //                                                                           //
09303 // 'precise' is the precise location (returned from locatesub()) of 'searcht'//
09304 // with respect to 'searchsh'. 'epspp' is the given relative tolerance.      //
09305 //                                                                           //
09306 // This routine re-evaluates the orientations of 'searchpt' with respect to  //
09307 // the three edges of 'searchsh'. Detects the collinearities by additinal    //
09308 // tests based on the given tolerance. If 'precise' is ONEDGE, one can save  //
09309 // one orientation test for the current edge of 'searchsh'.                  //
09310 //                                                                           //
09311 // On completion, 'searchsh' is a subface contains 'searchpt'. The returned  //
09312 // value indicates one of the following cases:                               //
09313 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchsh'  //
09314 //     is a handle whose origin is the existing vertex.                      //
09315 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchsh' is a     //
09316 //     handle whose primary edge is the edge on which the point lies.        //
09317 //   - Returns ONFACE if the point lies strictly within a subface.           //
09318 //     'searchsh' is a handle on which the point lies.                       //
09319 //   - Returns OUTSIDE if the point lies outside 'searchsh'.                 //
09320 //                                                                           //
09322 
09323 enum tetgenmesh::locateresult tetgenmesh::
09324 adjustlocatesub(point searchpt, face* searchsh, enum locateresult precise,
09325                 REAL epspp)
09326 {
09327   point pa, pb, pc;
09328   bool s1, s2, s3;
09329 
09330   pa = sorg(*searchsh);
09331   pb = sdest(*searchsh);
09332   pc = sapex(*searchsh);
09333 
09334   if (precise == ONEDGE) {
09335     s1 = true;
09336   } else {
09337     s1 = iscollinear(pa, pb, searchpt, epspp);
09338   }
09339   s2 = iscollinear(pb, pc, searchpt, epspp);
09340   s3 = iscollinear(pc, pa, searchpt, epspp);
09341   if (s1) {
09342     if (s2) {
09343       // on vertex pb.
09344 #ifdef SELF_CHECK
09345       assert(!s3);
09346 #endif
09347       senextself(*searchsh);
09348       return ONVERTEX;
09349     } else if (s3) {
09350       // on vertex pa.
09351       return ONVERTEX;
09352     } else {
09353       // on edge pa->pb.
09354       return ONEDGE;
09355     }
09356   } else if (s2) {
09357     if (s3) {
09358       // on vertex pc.
09359       senext2self(*searchsh);
09360       return ONVERTEX;
09361     } else {
09362       // on edge pb->pc.
09363       senextself(*searchsh);
09364       return ONEDGE;
09365     }
09366   } else if (s3) {
09367     // on edge pc->pa.
09368     senext2self(*searchsh);
09369     return ONEDGE;
09370   } else {
09371     return precise;
09372   }
09373 }
09374 
09376 //                                                                           //
09377 // locateseg()    Find a point in subsegments.                               //
09378 //                                                                           //
09379 // Searching begins from the input 'searchseg', it should be a subsegment of //
09380 // the whole segment.                                                        //
09381 //                                                                           //
09382 // On completion, 'searchseg' is a subsegment that contains 'searchpt'.      //
09383 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchseg' //
09384 //     is a handle whose origin is the existing vertex.                      //
09385 //   - Returns ONEDGE if the point lies inside 'searchseg'.                  //
09386 //   - Returns OUTSIDE if the point lies outside the segment.                //
09387 //                                                                           //
09389 
09390 enum tetgenmesh::locateresult tetgenmesh::
09391 locateseg(point searchpt, face* searchseg)
09392 {
09393   face backtraceseg;
09394   point pa, pb;
09395   REAL dx, dy, dz;
09396   int moveleft;
09397   int i;
09398 
09399   moveleft = 0;
09400   while (1) {
09401     searchseg->shver = 0;
09402     pa = sorg(*searchseg);
09403     pb = sdest(*searchseg);
09404     // Find the biggest difference in x, y, and z coordinates of a and b.
09405     dx = fabs(pb[0] - pa[0]);
09406     dy = fabs(pb[1] - pa[1]);
09407     dz = fabs(pb[2] - pa[2]);
09408     if (dx > dy) {
09409       if (dx > dz) {
09410         i = 0;
09411       } else {
09412         i = 2;
09413       }
09414     } else {
09415       if (dy > dz) {
09416         i = 1;
09417       } else {
09418         i = 2;
09419       }
09420     }
09421     if (pa[i] < pb[i]) {
09422       if (searchpt[i] < pa[i]) {
09423         moveleft = 1;
09424       } else if (searchpt[i] > pa[i]) {
09425         if (searchpt[i] < pb[i]) {
09426           return ONEDGE;
09427         } else if (searchpt[i] > pb[i]) {
09428           moveleft = 0;
09429         } else {
09430 #ifdef SELF_CHECK
09431           assert(searchpt[i] == pb[i]);
09432 #endif
09433           sesymself(*searchseg);
09434           return ONVERTEX;
09435         }
09436       } else {
09437 #ifdef SELF_CHECK
09438         assert(searchpt[i] == pa[i]);
09439 #endif
09440         return ONVERTEX;
09441       }
09442     } else if (pa[i] > pb[i]) {
09443       if (searchpt[i] < pb[i]) {
09444         moveleft = 0;
09445       } else if (searchpt[i] > pb[i]) {
09446         if (searchpt[i] < pa[i]) {
09447           return ONEDGE;
09448         } else if (searchpt[i] > pa[i]) {
09449           moveleft = 1;
09450         } else {
09451 #ifdef SELF_CHECK
09452           assert(searchpt[i] == pa[i]);
09453 #endif
09454           return ONVERTEX;
09455         }
09456       } else {
09457 #ifdef SELF_CHECK
09458         assert(searchpt[i] == pb[i]);
09459 #endif
09460         sesymself(*searchseg);
09461         return ONVERTEX;
09462       }
09463     }
09464     backtraceseg = *searchseg;
09465     if (moveleft) {
09466       senext2self(*searchseg);
09467     } else {
09468       senextself(*searchseg);
09469     }
09470     spivotself(*searchseg);
09471     if (searchseg->sh == dummysh) {
09472       *searchseg = backtraceseg;
09473       break;
09474     }
09475   }
09476 
09477   return OUTSIDE;
09478 }
09479 
09481 //                                                                           //
09482 // adjustlocateseg()    Adjust the precise location of a vertex on segment.  //
09483 //                                                                           //
09484 // 'searchpt' is either inside or ouside the segment 'searchseg'. It will be //
09485 // adjusted to on vertex if it is very close to an endpoint of 'searchseg'.  //
09486 // 'epspp' is the given relative tolerance.                                  //
09487 //                                                                           //
09489 
09490 enum tetgenmesh::locateresult tetgenmesh::
09491 adjustlocateseg(point searchpt, face* searchseg, enum locateresult precise,
09492                 REAL epspp)
09493 {
09494   point pa, pb;
09495   REAL L, d, r;
09496 
09497   pa = sorg(*searchseg);
09498   pb = sdest(*searchseg);
09499   L = distance(pa, pb);
09500 
09501   // Is searchpt approximate to pa?
09502   d = distance(pa, searchpt);
09503   r = d / L;
09504   if (r <= epspp) {
09505     return ONVERTEX;
09506   }
09507   // Is searchpt approximate to pb?
09508   d = distance(pb, searchpt);
09509   r = d / L;
09510   if (r <= epspp) {
09511     sesymself(*searchseg);
09512     return ONVERTEX;
09513   }
09514 
09515   return precise;
09516 }
09517 
09518 //
09519 // End of point location routines
09520 //
09521 
09522 //
09523 // Begin of mesh transformation routines
09524 //
09525 
09527 //                                                                           //
09528 // Flip operations                                                           //
09529 //                                                                           //
09530 // If abc is a hull face, it is unflipable, and is locally Delaunay.  In the //
09531 // following, we assume abc is an interior face, and the other tetrahedron   //
09532 // adjoining at abc is bace.                                                 //
09533 //                                                                           //
09534 // If the convex hull CH of the set {a, b, c, d, e} only has four vertices,  //
09535 // i.e., one vertex lies inside CH, then abc is unflipable, and is locally   //
09536 // Delaunay. If CH is the vertex set itself, we have the following cases to  //
09537 // determine whether abc is flipable or not.                                 //
09538 //                                                                           //
09539 // If no four points of {a, b, c, d, e} are coplanar, a 2-to-3 flip can be   //
09540 // applied to abc if the edge de crosses the triangle abc; a 3-to-2 flip can //
09541 // be applied to abc if ab crosses cde, and abde exists, otherwise, face abc //
09542 // is unflipable, i.e., the tetrahedron abde is not present.                 //
09543 //                                                                           //
09544 // If four points of {a, b, c, d, e} are coplanar (two faces are coplanar).  //
09545 // Assume faces abd and abe are coplanar (it is impossible be abc). If a, b, //
09546 // d, e form a non-convex quadrilateral, then abc is unflipable, furthermore,//
09547 // it is locally Delaunay.  Assume they are convex quadrilateral, if abd and //
09548 // abe are hull faces, a 2-to-2 flip can be applied to abc;  if abd and abe  //
09549 // are interior faces,  assume two tetrahedra adjoining abd and abe at the   //
09550 // opposite sides are abdg and abef, respectively.  If g = f, a 4-to-4 flip  //
09551 // can be applied to abc, otherwise, abc is unflipable.                      //
09552 //                                                                           //
09553 // There are other cases which can cause abc unflipable. If abc is a subface,//
09554 // a 2-to-3 flip is forbidden;  if ab is a subsegment, flips 3-to-2, 2-to-2, //
09555 // and 4-to-4 are forbidden.                                                 //
09556 //                                                                           //
09558 
09560 //                                                                           //
09561 // categorizeface()    Determine the flip type of a given face.              //
09562 //                                                                           //
09563 // On input, 'horiz' represents the face abc we want to flip (imagine it is  //
09564 // parallel to the horizon).  Let the tet above it be abcd.                  //
09565 //                                                                           //
09566 // This routine determines the suitable type of flip operation for 'horiz'.  //
09567 //   - Returns T23 if a 2-to-3 flip is applicable. 'horiz' is same as input. //
09568 //   - Returns T32 if a 3-to-2 flip is applicable. 'horiz' returns the edge  //
09569 //     of abc which is the flipable.                                         //
09570 //   - Returns T22 if a 2-to-2 or 4-to-4 flip is applicable. 'horiz' returns //
09571 //     the edge of abc which is flipable.                                    //
09572 //   - Returns N32 indicates it is unflipable due to the absence of a tet.   //
09573 //     'horize' returns the unflipable edge.                                 //
09574 //   - Returns N40 indicates it is unflipable and is locally Delaunay.       //
09575 //   - Returns FORBIDDENFACE indicates abc is a subface.                     //
09576 //   - Returns FORBIDDENEDGE indicates the flipable edge of abc is a segment.//
09577 //     'horize' returns the flipable edge.                                   //
09578 //                                                                           //
09579 // Given a face abc, with two adjoining tetrahedra abcd and bace.  If abc is //
09580 // flipable, i.e., T23, T32, T22 or T44, its flip type can be determined by  //
09581 // doing five orientation tests: two tests for determining that d, e lie on  //
09582 // the different sides of abc, three tests for determining if the edge de    //
09583 // intersects the face abc.  However, if we use the neighbor information of  //
09584 // the mesh data structure, we can reduce the five orientation tests to at   //
09585 // most three tests, that is, the two tests for determining whether d and e  //
09586 // lie on the different sides of abc can be saved.                           //
09587 //                                                                           //
09589 
09590 enum tetgenmesh::fliptype tetgenmesh::categorizeface(triface& horiz)
09591 {
09592   triface symhoriz, casing;
09593   face checksh, checkseg;
09594   face cassh1, cassh2;
09595   point pa, pb, pc, pd, pe, pf, pg;
09596   point abdoppo, bcdoppo, cadoppo;
09597   REAL ori1, ori2, ori3;
09598   int adjtet;
09599 
09600   sym(horiz, symhoriz);
09601   if (symhoriz.tet == dummytet) {
09602     // A hull face is unflipable and locally Delaunay.
09603     return N40;
09604   }
09605 
09606   adjustedgering(horiz, CCW);
09607   findedge(&symhoriz, dest(horiz), org(horiz));
09608   pa = org(horiz);
09609   pb = dest(horiz);
09610   pc = apex(horiz);
09611   pd = oppo(horiz);
09612   pe = oppo(symhoriz);
09613 
09614   // Find the number of adjacent tetrahedra of abc, which have d, e, and one
09615   //   of corners of abc as their corners. This number can be 0, 1 and 2.
09616   abdoppo = bcdoppo = cadoppo = (point) NULL;
09617   adjtet = 0;
09618   fnext(horiz, casing); // at edge 'ab'.
09619   symself(casing);
09620   if (casing.tet != dummytet) {
09621     abdoppo = oppo(casing);
09622     if (abdoppo == pe) adjtet++;
09623   }
09624   enextfnext(horiz, casing); // at edge 'bc'.
09625   symself(casing);
09626   if (casing.tet != dummytet) {
09627     bcdoppo = oppo(casing);
09628     if (bcdoppo == pe) adjtet++;
09629   }
09630   enext2fnext(horiz, casing); // at edge 'ca'.
09631   symself(casing);
09632   if (casing.tet != dummytet) {
09633     cadoppo = oppo(casing);
09634     if (cadoppo == pe) adjtet++;
09635   }
09636 
09637   if (adjtet == 0) {
09638     // No adjacent tetrahedron. Types T23, T22 and T44 are possible.
09639     ori1 = orient3d(pa, pb, pd, pe);
09640     if (checksubfaces && ori1 != 0.0) {
09641       // Check if abd and abe are both boundary faces?
09642       fnext(horiz, casing);
09643       tspivot(casing, cassh1);
09644       fnext(symhoriz, casing);
09645       tspivot(casing, cassh2);
09646       if ((cassh1.sh != dummysh) && (cassh2.sh != dummysh)) {
09647         // abd and abe are both boundary faces. Check if ab is a segment.
09648         findedge(&cassh1, pa, pb);
09649         sspivot(cassh1, checkseg);
09650         if (checkseg.sh == dummysh) {
09651           // ab is not a segment - abd and abe belong to the same facet.
09652           //   The four points are forced to be coplanar.
09653           ori1 = 0.0;
09654         } else {
09655           // ab is a segment - abd and abe belong to two different facets.
09656           //   In principle, a, b, c and d can form a tetrahedron (since
09657           //   ori1 != 0.0).  However, we should avoid to create a very
09658           //   flat one which may form a sequence of extremely badly-shaped
09659           //   or even wrong orientational tets. Test with a larger epsilon.
09660           if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09661         }
09662       } else {
09663         // abd and abe are not both boundary faces. Check if abd and bae
09664         //   are approximately coplanar with respect to the epsilon.
09665         if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon)) ori1 = 0.0;
09666       }
09667     }
09668     if (ori1 < 0.0) {
09669       // e lies above abd, unflipable, tet abde is not present.
09670 #ifdef SELF_CHECK
09671       if (!nonconvex) {
09672         // abd and abe should not be hull faces, check it.
09673         fnext(horiz, casing);
09674         symself(casing);
09675         assert(casing.tet != dummytet);
09676         fnext(symhoriz, casing);
09677         symself(casing);
09678         assert(casing.tet != dummytet);
09679       }
09680 #endif
09681       if (checksubfaces) {
09682         // The nonconvexbility may be casued by existing an subsegment.
09683         tsspivot(&horiz, &checkseg);
09684         if (checkseg.sh != dummysh) {
09685           return FORBIDDENEDGE;
09686         }
09687       }
09688       return N32;
09689     }
09690     ori2 = orient3d(pb, pc, pd, pe);
09691     if (checksubfaces && ori2 != 0.0) {
09692       // Check if bcd and cbe are both boundary faces.
09693       enextfnext(horiz, casing);
09694       tspivot(casing, cassh1);
09695       enext2fnext(symhoriz, casing);
09696       tspivot(casing, cassh2);
09697       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09698         // bcd and cbe are both boundary faces. Check if bc is a segment.
09699         findedge(&cassh1, pb, pc);
09700         sspivot(cassh1, checkseg);
09701         if (checkseg.sh == dummysh) {
09702           // bc is not a segment - bcd and cbe belong to the same facet.
09703           //   The four points are forced to be coplanar.
09704           ori2 = 0.0;
09705         } else {
09706           if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09707         }
09708       } else {
09709         //  bcd and cbe are not both boundary faces. Check if bcd and cbe
09710         //   are approximately coplanar with respect to the epsilon.
09711         if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon)) ori2 = 0.0;
09712       }
09713     }
09714     if (ori2 < 0.0) {
09715       // e lies above bcd, unflipable, tet bcde is not present.
09716 #ifdef SELF_CHECK
09717       if (!nonconvex) {
09718         // bcd and cbe should not be hull faces, check it.
09719         enextfnext(horiz, casing);
09720         symself(casing);
09721         assert(casing.tet != dummytet);
09722         enext2fnext(symhoriz, casing);
09723         symself(casing);
09724         assert(casing.tet != dummytet);
09725       }
09726 #endif
09727       enextself(horiz);
09728       if (checksubfaces) {
09729         // The nonconvexbility may be casued by existing an subsegment.
09730         tsspivot(&horiz, &checkseg);
09731         if (checkseg.sh != dummysh) {
09732           return FORBIDDENEDGE;
09733         }
09734       }
09735       return N32;
09736     }
09737     ori3 = orient3d(pc, pa, pd, pe);
09738     if (checksubfaces && ori3 != 0.0) {
09739       // Check if cad and ace are both boundary faces.
09740       enext2fnext(horiz, casing);
09741       tspivot(casing, cassh1);
09742       enextfnext(symhoriz, casing);
09743       tspivot(casing, cassh2);
09744       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09745         // cad and ace are both boundary faces. Check if ca is a segment.
09746         findedge(&cassh1, pc, pa);
09747         sspivot(cassh1, checkseg);
09748         if (checkseg.sh == dummysh) {
09749           // ca is not a segment - cad and ace belong to the same facet.
09750           //   The four points are forced to be coplanar.
09751           ori3 = 0.0;
09752         } else {
09753           // ca is a segment - cad and ace belong to two different facets.
09754           //   In principle, c, a, d and e can form a tetrahedron (since
09755           //   ori3 != 0.0). Use a larger eps to test if they're coplanar.
09756           if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon * 1e+2)) ori3 = 0.0;
09757         }
09758       } else {
09759         // cad and ace are not both boundary faces. Check if cad and ace
09760         //   are approximately coplanar with respect to the epsilon.
09761         if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon)) ori3 = 0.0;
09762       }
09763     }
09764     if (ori3 < 0.0) {
09765       // e lies above cad, unflipable, tet cade is not present.
09766 #ifdef SELF_CHECK
09767       if (!nonconvex) {
09768         // cad and ace should not be hull faces, check it.
09769         enext2fnext(horiz, casing);
09770         symself(casing);
09771         assert(casing.tet != dummytet);
09772         enextfnext(symhoriz, casing);
09773         symself(casing);
09774         assert(casing.tet != dummytet);
09775       }
09776 #endif
09777       enext2self(horiz);
09778       if (checksubfaces) {
09779         // The nonconvexbility may be casued by existing an subsegment.
09780         tsspivot(&horiz, &checkseg);
09781         if (checkseg.sh != dummysh) {
09782           return FORBIDDENEDGE;
09783         }
09784       }
09785       return N32;
09786     }
09787     if (ori1 == 0.0) {
09788       // e is coplanar with abd.
09789       if (ori2 * ori3 == 0.0) {
09790         // only one zero is possible.
09791         // assert(!(ori2 == 0.0 && ori3 == 0.0));
09792         // Three points (d, e, and a or b) are collinear, abc is unflipable
09793         //   and locally Delaunay.
09794         return N40;
09795       }
09796     } else if (ori2 == 0.0) {
09797       // e is coplanar with bcd.
09798       if (ori1 * ori3 == 0.0) {
09799         // only one zero is possible.
09800         // assert(!(ori1 == 0.0 && ori3 == 0.0));
09801         // Three points (d, e, and b or c) are collinear, abc is unflipable
09802         //   and locally Delaunay.
09803         return N40;
09804       }
09805       // Adjust 'horiz' and 'symhoriz' be the edge bc.
09806       enextself(horiz);
09807       enext2self(symhoriz);
09808     } else if (ori3 == 0.0) {
09809       // e is coplanar with cad.
09810       if (ori1 * ori2 == 0.0) {
09811         // only one zero is possible.
09812         // assert(!(ori1 == 0.0 && ori2 == 0.0));
09813         // Three points (d, e, and c or a) are collinear, abc is unflipable
09814         //   and locally Delaunay.
09815         return N40;
09816       }
09817       // Adjust 'horiz' and 'symhoriz' be the edge ca.
09818       enext2self(horiz);
09819       enextself(symhoriz);
09820     } else {
09821       // e lies below all three faces, flipable.
09822       if (checksubfaces) {
09823         tspivot(horiz, checksh);
09824         if (checksh.sh != dummysh) {
09825           // To flip a subface is forbidden.
09826           return FORBIDDENFACE;
09827         }
09828       }
09829       return T23;
09830     }
09831     // Four points are coplanar, T22 or T44 is possible.
09832     if (checksubfaces) {
09833       tsspivot(&horiz, &checkseg);
09834       if (checkseg.sh != dummysh) {
09835         // To flip a subsegment is forbidden.
09836         return FORBIDDENEDGE;
09837       }
09838       tspivot(horiz, checksh);
09839       if (checksh.sh != dummysh) {
09840         // To flip a subface is forbidden.
09841         return FORBIDDENFACE;
09842       }
09843     }
09844     // Assume the four coplanar points are a, b, d, e, abd and abe are two
09845     //   coplanar faces. If both abd and abe are hull faces, flipable(T22).
09846     //   If they are interior faces, get the opposite tetrahedra abdf and
09847     //   abeg, if f = g, flipable (T44). Otherwise, unflipable.
09848     pf = pg = (point) NULL;
09849     fnext(horiz, casing);
09850     symself(casing);
09851     if (casing.tet != dummytet) {
09852       pf = oppo(casing);
09853     }
09854     fnext(symhoriz, casing);
09855     symself(casing);
09856     if (casing.tet != dummytet) {
09857       pg = oppo(casing);
09858     }
09859     if (pf == pg) {
09860       // Either T22 (pf == pg == NULL) or T44 (pf and pg) is possible.
09861       if (checksubfaces) {
09862         // Retreat the corner points a, b, and c.
09863         pa = org(horiz);
09864         pb = dest(horiz);
09865         pc = apex(horiz);
09866         // Be careful not to create an inverted tetrahedron. Check the case.
09867         ori1 = orient3d(pc, pd, pe, pa);
09868         if (ori1 <= 0) return N40;
09869         ori1 = orient3d(pd, pc, pe, pb);
09870         if (ori1 <= 0) return N40;
09871         if (pf != (point) NULL) {
09872           ori1 = orient3d(pd, pf, pe, pa);
09873           if (ori1 <= 0) return N40;
09874           ori1 = orient3d(pf, pd, pe, pb);
09875           if (ori1 <= 0) return N40;
09876         }
09877       }
09878       if (pf == (point) NULL) {
09879         // abd and abe are hull faces, flipable.
09880         return T22;
09881       } else {
09882         // abd and abe are interior faces, flipable.
09883 #ifdef SELF_CHECK
09884         assert(pf != (point) NULL);
09885 #endif
09886         return T44;
09887       }
09888     } else {
09889       // ab has more than four faces around it, unflipable.
09890       return N32;
09891     }
09892   } else if (adjtet == 1) {
09893     // One of its three edges is locally non-convex. Type T32 is possible.
09894     // Adjust current configuration so that edge ab is non-convex.
09895     if (bcdoppo == pe) {
09896       // Edge bc is non-convex. Adjust 'horiz' and 'symhoriz' be edge bc.
09897       enextself(horiz);
09898       enext2self(symhoriz);
09899       pa = org(horiz);
09900       pb = dest(horiz);
09901       pc = apex(horiz);
09902     } else if (cadoppo == pe) {
09903       // Edge ca is non-convex. Adjust 'horiz' and 'symhoriz' be edge ca.
09904       enext2self(horiz);
09905       enextself(symhoriz);
09906       pa = org(horiz);
09907       pb = dest(horiz);
09908       pc = apex(horiz);
09909     } else {
09910       // Edge ab is non-convex.
09911 #ifdef SELF_CHECK
09912       assert(abdoppo == pe);
09913 #endif
09914     } // Now ab is the non-convex edge.
09915     // In order to be flipable, ab should cross face cde. Check it.
09916     ori1 = orient3d(pc, pd, pe, pa);
09917     if (checksubfaces && ori1 != 0.0) {
09918       // Check if cad and ace are both boundary faces.
09919       enext2fnext(horiz, casing);
09920       tspivot(casing, cassh1);
09921       enextfnext(symhoriz, casing);
09922       tspivot(casing, cassh2);
09923       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09924         // cad and ace are both boundary faces. Check if ca is a segment.
09925         findedge(&cassh1, pc, pa);
09926         sspivot(cassh1, checkseg);
09927         if (checkseg.sh == dummysh) {
09928           // ca is not a segment. cad and ace belong to the same facet.
09929           //   The four points are forced to be coplanar.
09930           ori1 = 0.0;
09931         } else {
09932           // ca is a segment. cad and ace belong to different facets.
09933           //   In principle, c, d, e, and a can form a tetrahedron (since
09934           //   ori1 != 0.0).  However, we should avoid to create a very
09935           //   flat tet. Use a larger epsilon to test if they're coplanar.
09936           if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09937         }
09938       } else {
09939         // Check if c, d, e, and a are approximately coplanar.
09940         if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon)) ori1 = 0.0;
09941       }
09942     }
09943     if (ori1 <= 0.0) {
09944       // a lies above or is coplanar cde, abc is locally Delaunay.
09945       return N40;
09946     }
09947     ori2 = orient3d(pd, pc, pe, pb);
09948     if (checksubfaces && ori2 != 0.0) {
09949       // Check if bcd and cbe are both boundary faces.
09950       enextfnext(horiz, casing);
09951       tspivot(casing, cassh1);
09952       enext2fnext(symhoriz, casing);
09953       tspivot(casing, cassh2);
09954       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09955         // bcd and cbe are both boundary faces. Check if bc is a segment.
09956         findedge(&cassh1, pb, pc);
09957         sspivot(cassh1, checkseg);
09958         if (checkseg.sh == dummysh) {
09959           // bc is not a segment. bcd and cbe belong to the same facet.
09960           //   The four points are forced to be coplanar.
09961           ori2 = 0.0;
09962         } else {
09963           // bc is a segment. bcd and cbe belong to different facets.
09964           //   In principle, d, c, e, and b can form a tetrahedron (since
09965           //   ori2 != 0.0).  However, we should avoid to create a very
09966           //   flat tet. Use a larger epsilon to test if they're coplanar.
09967           if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09968         }
09969       } else {
09970         // Check if d, c, e, and b are approximately coplanar.
09971         if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon)) ori2 = 0.0;
09972       }
09973     }
09974     if (ori2 <= 0.0) {
09975       // b lies above dce, unflipable, and abc is locally Delaunay.
09976       return N40;
09977     }
09978     // Edge ab crosses face cde properly.
09979     if (checksubfaces) {
09980       // If abc is subface, then ab must be a subsegment (because abde is
09981       //   a tetrahedron and ab crosses cde properly).
09982       tsspivot(&horiz, &checkseg);
09983       if (checkseg.sh != dummysh) {
09984         // To flip a subsegment is forbidden.
09985         return FORBIDDENEDGE;
09986       }
09987       // Both abd and bae should not be subfaces (because they're not
09988       //   coplanar and ab is not a subsegment). However, they may be
09989       //   subfaces and belong to a facet (created during facet recovery),
09990       //   that is, abde is an invalid tetrahedron. Find this case out.
09991       fnext(horiz, casing);
09992       tspivot(casing, cassh1);
09993       fnext(symhoriz, casing);
09994       tspivot(casing, cassh2);
09995       if (cassh1.sh != dummysh || cassh2.sh != dummysh) {
09996         if (!b->quiet) {
09997           // Unfortunately, they're subfaces. Corrections need be done here.
09998           printf("Warning:  A tetrahedron spans two subfaces of a facet.\n");
09999         }
10000         // Temporarily, let it be there.
10001         return N32;
10002       }
10003     }
10004     return T32;
10005   } else {
10006     // The convex hull of {a, b, c, d, e} has only four vertices, abc is
10007     //   unflipable, furthermore, it is locally Delaunay.
10008     return N40;
10009   }
10010 }
10011 
10013 //                                                                           //
10014 // enqueueflipface(), enqueueflipedge()    Queue a face (or an edge).        //
10015 //                                                                           //
10016 // The face (or edge) may be non-locally Delaunay. It is queued for process- //
10017 // ing in flip() (or flipsub()). The vertices of the face (edge) are stored  //
10018 // seperatly to ensure the face (or edge) is still the same one when we save //
10019 // it since other flips will cause this face (or edge) be changed or dead.   //
10020 //                                                                           //
10022 
10023 void tetgenmesh::enqueueflipface(triface& checkface, queue* flipqueue)
10024 {
10025   badface *queface;
10026   triface symface;
10027 
10028   sym(checkface, symface);
10029   if (symface.tet != dummytet) {
10030     queface = (badface *) flipqueue->push((void *) NULL);
10031     queface->tt = checkface;
10032     queface->foppo = oppo(symface);
10033   }
10034 }
10035 
10036 void tetgenmesh::enqueueflipedge(face& checkedge, queue* flipqueue)
10037 {
10038   badface *queface;
10039 
10040   queface = (badface *) flipqueue->push((void *) NULL);
10041   queface->ss = checkedge;
10042   queface->forg = sorg(checkedge);
10043   queface->fdest = sdest(checkedge);
10044 }
10045 
10047 //                                                                           //
10048 // flip23()    Perform a 2-to-3 flip.                                        //
10049 //                                                                           //
10050 // On input, 'flipface' represents the face will be flipped.  Let it is abc, //
10051 // the two tetrahedra sharing abc are abcd, bace. abc is not a subface.      //
10052 //                                                                           //
10053 // A 2-to-3 flip is to change two tetrahedra abcd, bace to three tetrahedra  //
10054 // edab, edbc, and edca.  As a result, face abc has been removed and three   //
10055 // new faces eda, edb and edc have been created.                             //
10056 //                                                                           //
10057 // On completion, 'flipface' returns edab.  If 'flipqueue' is not NULL, all  //
10058 // possibly non-Delaunay faces are added into it.                            //
10059 //                                                                           //
10061 
10062 void tetgenmesh::flip23(triface* flipface, queue* flipqueue)
10063 {
10064   triface abcd, bace;                                  // Old configuration.
10065   triface oldabd, oldbcd, oldcad;
10066   triface abdcasing, bcdcasing, cadcasing;
10067   triface oldbae, oldcbe, oldace;
10068   triface baecasing, cbecasing, acecasing;
10069   triface worktet;
10070   face abdsh, bcdsh, cadsh;                   // The six subfaces on the CH.
10071   face baesh, cbesh, acesh;
10072   face abseg, bcseg, caseg;                      // The nine segs on the CH.
10073   face adseg, bdseg, cdseg;
10074   face aeseg, beseg, ceseg;
10075   triface edab, edbc, edca;                            // New configuration.
10076   point pa, pb, pc, pd, pe;
10077   REAL attrib, volume;
10078   int i;
10079 
10080   abcd = *flipface;
10081   adjustedgering(abcd, CCW); // abcd represents edge ab.
10082   pa = org(abcd);
10083   pb = dest(abcd);
10084   pc = apex(abcd);
10085   pd = oppo(abcd);
10086   // sym(abcd, bace);
10087   // findedge(&bace, dest(abcd), org(abcd)); // bace represents edge ba.
10088   sym(abcd, bace);
10089   bace.ver = 0; // CCW.
10090   for (i = 0; (i < 3) && (org(bace) != pb); i++) {
10091     enextself(bace);
10092   }
10093   pe = oppo(bace);
10094 
10095   if (b->verbose > 2) {
10096     printf("    Do T23 on face (%d, %d, %d) %d, %d.\n", pointmark(pa),
10097            pointmark(pb), pointmark(pc), pointmark(pd), pointmark(pe));
10098   }
10099   flip23s++;
10100 
10101   // Storing the old configuration outside the convex hull.
10102   fnext(abcd, oldabd);
10103   enextfnext(abcd, oldbcd);
10104   enext2fnext(abcd, oldcad);
10105   fnext(bace, oldbae);
10106   enext2fnext(bace, oldcbe);
10107   enextfnext(bace, oldace);
10108   sym(oldabd, abdcasing);
10109   sym(oldbcd, bcdcasing);
10110   sym(oldcad, cadcasing);
10111   sym(oldbae, baecasing);
10112   sym(oldcbe, cbecasing);
10113   sym(oldace, acecasing);
10114   if (checksubfaces) {
10115     tspivot(oldabd, abdsh);
10116     tspivot(oldbcd, bcdsh);
10117     tspivot(oldcad, cadsh);
10118     tspivot(oldbae, baesh);
10119     tspivot(oldcbe, cbesh);
10120     tspivot(oldace, acesh);
10121   } else if (checksubsegs) {
10122     tsspivot1(abcd, abseg);
10123     enext(abcd, worktet);
10124     tsspivot1(worktet, bcseg);
10125     enext2(abcd, worktet);
10126     tsspivot1(worktet, caseg);
10127     enext2(oldabd, worktet);
10128     tsspivot1(worktet, adseg);
10129     enext2(oldbcd, worktet);
10130     tsspivot1(worktet, bdseg);
10131     enext2(oldcad, worktet);
10132     tsspivot1(worktet, cdseg);
10133     enext(oldbae, worktet);
10134     tsspivot1(worktet, aeseg);
10135     enext(oldcbe, worktet);
10136     tsspivot1(worktet, beseg);
10137     enext(oldace, worktet);
10138     tsspivot1(worktet, ceseg);
10139   }
10140 
10141   // Creating the new configuration inside the convex hull.
10142   edab.tet = abcd.tet; // Update abcd to be edab.
10143   setorg (edab, pe);
10144   setdest(edab, pd);
10145   setapex(edab, pa);
10146   setoppo(edab, pb);
10147   edbc.tet = bace.tet; // Update bace to be edbc.
10148   setorg (edbc, pe);
10149   setdest(edbc, pd);
10150   setapex(edbc, pb);
10151   setoppo(edbc, pc);
10152   maketetrahedron(&edca); // Create edca.
10153   setorg (edca, pe);
10154   setdest(edca, pd);
10155   setapex(edca, pc);
10156   setoppo(edca, pa);
10157   // Set the element attributes of the new tetrahedron 'edca'.
10158   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
10159     attrib = elemattribute(abcd.tet, i);
10160     setelemattribute(edca.tet, i, attrib);
10161   }
10162   // Set the volume constraint of the new tetrahedron 'edca' if the -ra
10163   //   switches are not used together. In -ra case, the various volume
10164   //   constraints can be spreaded very far.
10165   if (b->varvolume && !b->refine) {
10166     volume = volumebound(abcd.tet);
10167     setvolumebound(edca.tet, volume);
10168   }
10169 
10170   // Clear old bonds in edab(was abcd) and edbc(was bace).
10171   for (i = 0; i < 4; i ++) {
10172     edab.tet[i] = (tetrahedron) dummytet;
10173   }
10174   for (i = 0; i < 4; i ++) {
10175     edbc.tet[i] = (tetrahedron) dummytet;
10176   }
10177   // Bond the faces inside the convex hull.
10178   edab.loc = 0;
10179   edca.loc = 1;
10180   bond(edab, edca);
10181   edab.loc = 1;
10182   edbc.loc = 0;
10183   bond(edab, edbc);
10184   edbc.loc = 1;
10185   edca.loc = 0;
10186   bond(edbc, edca);
10187   // Bond the faces on the convex hull.
10188   edab.loc = 2;
10189   bond(edab, abdcasing);
10190   edab.loc = 3;
10191   bond(edab, baecasing);
10192   edbc.loc = 2;
10193   bond(edbc, bcdcasing);
10194   edbc.loc = 3;
10195   bond(edbc, cbecasing);
10196   edca.loc = 2;
10197   bond(edca, cadcasing);
10198   edca.loc = 3;
10199   bond(edca, acecasing);
10200   // There may exist subfaces that need to be bonded to new configuarton.
10201   if (checksubfaces) {
10202     // Clear old flags in edab(was abcd) and edbc(was bace).
10203     for (i = 0; i < 4; i ++) {
10204       edab.loc = i;
10205       tsdissolve(edab);
10206       edbc.loc = i;
10207       tsdissolve(edbc);
10208     }
10209     if (abdsh.sh != dummysh) {
10210       edab.loc = 2;
10211       tsbond(edab, abdsh);
10212     }
10213     if (baesh.sh != dummysh) {
10214       edab.loc = 3;
10215       tsbond(edab, baesh);
10216     }
10217     if (bcdsh.sh != dummysh) {
10218       edbc.loc = 2;
10219       tsbond(edbc, bcdsh);
10220     }
10221     if (cbesh.sh != dummysh) {
10222       edbc.loc = 3;
10223       tsbond(edbc, cbesh);
10224     }
10225     if (cadsh.sh != dummysh) {
10226       edca.loc = 2;
10227       tsbond(edca, cadsh);
10228     }
10229     if (acesh.sh != dummysh) {
10230       edca.loc = 3;
10231       tsbond(edca, acesh);
10232     }
10233   } else if (checksubsegs) {
10234     for (i = 0; i < 6; i++) {
10235       edab.tet[8 + i] = (tetrahedron) dummysh;
10236     }
10237     for (i = 0; i < 6; i++) {
10238       edbc.tet[8 + i] = (tetrahedron) dummysh;
10239     }
10240     edab.loc = edab.ver = 0;
10241     edbc.loc = edab.ver = 0;
10242     edca.loc = edab.ver = 0;
10243     // Operate in tet edab (5 edges).
10244     enext(edab, worktet);
10245     tssbond1(worktet, adseg);
10246     enext2(edab, worktet);
10247     tssbond1(worktet, aeseg);
10248     fnext(edab, worktet);
10249     enextself(worktet);
10250     tssbond1(worktet, bdseg);
10251     enextself(worktet);
10252     tssbond1(worktet, beseg);
10253     enextfnext(edab, worktet);
10254     enextself(worktet);
10255     tssbond1(worktet, abseg);
10256     // Operate in tet edbc (5 edges)
10257     enext(edbc, worktet);
10258     tssbond1(worktet, bdseg);
10259     enext2(edbc, worktet);
10260     tssbond1(worktet, beseg);
10261     fnext(edbc, worktet);
10262     enextself(worktet);
10263     tssbond1(worktet, cdseg);
10264     enextself(worktet);
10265     tssbond1(worktet, ceseg);
10266     enextfnext(edbc, worktet);
10267     enextself(worktet);
10268     tssbond1(worktet, bcseg);
10269     // Operate in tet edca (5 edges)
10270     enext(edca, worktet);
10271     tssbond1(worktet, cdseg);
10272     enext2(edca, worktet);
10273     tssbond1(worktet, ceseg);
10274     fnext(edca, worktet);
10275     enextself(worktet);
10276     tssbond1(worktet, adseg);
10277     enextself(worktet);
10278     tssbond1(worktet, aeseg);
10279     enextfnext(edca, worktet);
10280     enextself(worktet);
10281     tssbond1(worktet, caseg);
10282   }
10283 
10284   edab.loc = 0;
10285   edbc.loc = 0;
10286   edca.loc = 0;
10287   if (b->verbose > 3) {
10288     printf("    Updating edab ");
10289     printtet(&edab);
10290     printf("    Updating edbc ");
10291     printtet(&edbc);
10292     printf("    Creating edca ");
10293     printtet(&edca);
10294   }
10295 
10296   if (flipqueue != (queue *) NULL) {
10297     enextfnext(edab, abdcasing);
10298     enqueueflipface(abdcasing, flipqueue);
10299     enext2fnext(edab, baecasing);
10300     enqueueflipface(baecasing, flipqueue);
10301     enextfnext(edbc, bcdcasing);
10302     enqueueflipface(bcdcasing, flipqueue);
10303     enext2fnext(edbc, cbecasing);
10304     enqueueflipface(cbecasing, flipqueue);
10305     enextfnext(edca, cadcasing);
10306     enqueueflipface(cadcasing, flipqueue);
10307     enext2fnext(edca, acecasing);
10308     enqueueflipface(acecasing, flipqueue);
10309   }
10310 
10311   // Save a live handle in 'recenttet'.
10312   recenttet = edbc;
10313   // Set the return handle be edab.
10314   *flipface = edab;
10315 }
10316 
10318 //                                                                           //
10319 // flip32()    Perform a 3-to-2 flip.                                        //
10320 //                                                                           //
10321 // On input, 'flipface' represents the face will be flipped.  Let it is eda, //
10322 // where edge ed is locally non-convex. Three tetrahedra sharing ed are edab,//
10323 // edbc, and edca.  ed is not a subsegment.                                  //
10324 //                                                                           //
10325 // A 3-to-2 flip is to change the three tetrahedra edab, edbc, and edca into //
10326 // another two tetrahedra abcd and bace.  As a result, the edge ed has been  //
10327 // removed and the face abc has been created.                                //
10328 //                                                                           //
10329 // On completion, 'flipface' returns abcd.  If 'flipqueue' is not NULL, all  //
10330 // possibly non-Delaunay faces are added into it.                            //
10331 //                                                                           //
10333 
10334 void tetgenmesh::flip32(triface* flipface, queue* flipqueue)
10335 {
10336   triface edab, edbc, edca;                            // Old configuration.
10337   triface oldabd, oldbcd, oldcad;
10338   triface abdcasing, bcdcasing, cadcasing;
10339   triface oldbae, oldcbe, oldace;
10340   triface baecasing, cbecasing, acecasing;
10341   triface worktet;
10342   face abdsh, bcdsh, cadsh;
10343   face baesh, cbesh, acesh;
10344   face abseg, bcseg, caseg;                      // The nine segs on the CH.
10345   face adseg, bdseg, cdseg;
10346   face aeseg, beseg, ceseg;
10347   triface abcd, bace;                                  // New configuration.
10348   point pa, pb, pc, pd, pe;
10349   int i;
10350 
10351   edab = *flipface;
10352   adjustedgering(edab, CCW);
10353   pa = apex(edab);
10354   pb = oppo(edab);
10355   pd = dest(edab);
10356   pe = org(edab);
10357   fnext(edab, edbc);
10358   symself(edbc);
10359   edbc.ver = 0;
10360   for (i = 0; (i < 3) && (org(edbc) != pe); i++) {
10361     enextself(edbc);
10362   }
10363   pc = oppo(edbc);
10364   fnext(edbc, edca);
10365   symself(edca);
10366   edca.ver = 0;
10367   for (i = 0; (i < 3) && (org(edca) != pe); i++) {
10368     enextself(edca);
10369   }
10370 
10371   if (b->verbose > 2) {
10372     printf("    Do T32 on edge (%d, %d) %d, %d, %d.\n", pointmark(pe),
10373            pointmark(pd), pointmark(pa), pointmark(pb), pointmark(pc));
10374   }
10375   flip32s++;
10376 
10377   // Storing the old configuration outside the convex hull.
10378   enextfnext(edab, oldabd);
10379   enext2fnext(edab, oldbae);
10380   enextfnext(edbc, oldbcd);
10381   enext2fnext(edbc, oldcbe);
10382   enextfnext(edca, oldcad);
10383   enext2fnext(edca, oldace);
10384   sym(oldabd, abdcasing);
10385   sym(oldbcd, bcdcasing);
10386   sym(oldcad, cadcasing);
10387   sym(oldbae, baecasing);
10388   sym(oldcbe, cbecasing);
10389   sym(oldace, acecasing);
10390   if (checksubfaces) {
10391     tspivot(oldabd, abdsh);
10392     tspivot(oldbcd, bcdsh);
10393     tspivot(oldcad, cadsh);
10394     tspivot(oldbae, baesh);
10395     tspivot(oldcbe, cbesh);
10396     tspivot(oldace, acesh);
10397   } else if (checksubsegs) {
10398     enext(edab, worktet);
10399     tsspivot1(worktet, adseg);
10400     enext2(edab, worktet);
10401     tsspivot1(worktet, aeseg);
10402     enext(edbc, worktet);
10403     tsspivot1(worktet, bdseg);
10404     enext2(edbc, worktet);
10405     tsspivot1(worktet, beseg);
10406     enext(edca, worktet);
10407     tsspivot1(worktet, cdseg);
10408     enext2(edca, worktet);
10409     tsspivot1(worktet, ceseg);
10410     enextfnext(edab, worktet);
10411     enextself(worktet);
10412     tsspivot1(worktet, abseg);
10413     enextfnext(edbc, worktet);
10414     enextself(worktet);
10415     tsspivot1(worktet, bcseg);
10416     enextfnext(edca, worktet);
10417     enextself(worktet);
10418     tsspivot1(worktet, caseg);
10419   }
10420 
10421   // Creating the new configuration inside the convex hull.
10422   abcd.tet = edab.tet; // Update edab to be abcd.
10423   setorg (abcd, pa);
10424   setdest(abcd, pb);
10425   setapex(abcd, pc);
10426   setoppo(abcd, pd);
10427   bace.tet = edbc.tet; // Update edbc to be bace.
10428   setorg (bace, pb);
10429   setdest(bace, pa);
10430   setapex(bace, pc);
10431   setoppo(bace, pe);
10432   // Dealloc a redundant tetrahedron (edca).
10433   tetrahedrondealloc(edca.tet);
10434 
10435   // Clear the old bonds in abcd (was edab) and bace (was edbc).
10436   for (i = 0; i < 4; i ++) {
10437     abcd.tet[i] = (tetrahedron) dummytet;
10438   }
10439   for (i = 0; i < 4; i ++) {
10440     bace.tet[i] = (tetrahedron) dummytet;
10441   }
10442   // Bond the inside face of the convex hull.
10443   abcd.loc = 0;
10444   bace.loc = 0;
10445   bond(abcd, bace);
10446   // Bond the outside faces of the convex hull.
10447   abcd.loc = 1;
10448   bond(abcd, abdcasing);
10449   abcd.loc = 2;
10450   bond(abcd, bcdcasing);
10451   abcd.loc = 3;
10452   bond(abcd, cadcasing);
10453   bace.loc = 1;
10454   bond(bace, baecasing);
10455   bace.loc = 3;
10456   bond(bace, cbecasing);
10457   bace.loc = 2;
10458   bond(bace, acecasing);
10459   if (checksubfaces) {
10460     // Clear old bonds in abcd(was edab) and bace(was edbc).
10461     for (i = 0; i < 4; i ++) {
10462       abcd.tet[8 + i] = (tetrahedron) dummysh;
10463     }
10464     for (i = 0; i < 4; i ++) {
10465       bace.tet[8 + i] = (tetrahedron) dummysh;
10466     }
10467     if (abdsh.sh != dummysh) {
10468       abcd.loc = 1;
10469       tsbond(abcd, abdsh);
10470     }
10471     if (bcdsh.sh != dummysh) {
10472       abcd.loc = 2;
10473       tsbond(abcd, bcdsh);
10474     }
10475     if (cadsh.sh != dummysh) {
10476       abcd.loc = 3;
10477       tsbond(abcd, cadsh);
10478     }
10479     if (baesh.sh != dummysh) {
10480       bace.loc = 1;
10481       tsbond(bace, baesh);
10482     }
10483     if (cbesh.sh != dummysh) {
10484       bace.loc = 3;
10485       tsbond(bace, cbesh);
10486     }
10487     if (acesh.sh != dummysh) {
10488       bace.loc = 2;
10489       tsbond(bace, acesh);
10490     }
10491   } else if (checksubsegs) {
10492     for (i = 0; i < 6; i++) {
10493       abcd.tet[8 + i] = (tetrahedron) dummysh;
10494     }
10495     for (i = 0; i < 6; i++) {
10496       bace.tet[8 + i] = (tetrahedron) dummysh;
10497     }
10498     abcd.loc = abcd.ver = 0;
10499     bace.loc = bace.ver = 0;
10500     tssbond1(abcd, abseg);     // 1
10501     enext(abcd, worktet);
10502     tssbond1(worktet, bcseg);  // 2
10503     enext2(abcd, worktet);
10504     tssbond1(worktet, caseg);  // 3
10505     fnext(abcd, worktet);
10506     enext2self(worktet);
10507     tssbond1(worktet, adseg);  // 4
10508     enextfnext(abcd, worktet);
10509     enext2self(worktet);
10510     tssbond1(worktet, bdseg);  // 5
10511     enext2fnext(abcd, worktet);
10512     enext2self(worktet);
10513     tssbond1(worktet, cdseg);  // 6
10514     tssbond1(bace, abseg);
10515     enext2(bace, worktet);
10516     tssbond1(worktet, bcseg);
10517     enext(bace, worktet);
10518     tssbond1(worktet, caseg);
10519     fnext(bace, worktet);
10520     enextself(worktet);
10521     tssbond1(worktet, aeseg);  // 7
10522     enext2fnext(bace, worktet);
10523     enextself(worktet);
10524     tssbond1(worktet, beseg);  // 8
10525     enextfnext(bace, worktet);
10526     enextself(worktet);
10527     tssbond1(worktet, ceseg);  // 9
10528   }
10529 
10530   abcd.loc = 0;
10531   bace.loc = 0;
10532   if (b->verbose > 3) {
10533     printf("    Updating abcd ");
10534     printtet(&abcd);
10535     printf("    Updating bace ");
10536     printtet(&bace);
10537     printf("    Deleting edca ");
10538     // printtet(&edca);
10539   }
10540 
10541   if (flipqueue != (queue *) NULL) {
10542     fnext(abcd, abdcasing);
10543     enqueueflipface(abdcasing, flipqueue);
10544     fnext(bace, baecasing);
10545     enqueueflipface(baecasing, flipqueue);
10546     enextfnext(abcd, bcdcasing);
10547     enqueueflipface(bcdcasing, flipqueue);
10548     enextfnext(bace, cbecasing);
10549     enqueueflipface(cbecasing, flipqueue);
10550     enext2fnext(abcd, cadcasing);
10551     enqueueflipface(cadcasing, flipqueue);
10552     enext2fnext(bace, acecasing);
10553     enqueueflipface(acecasing, flipqueue);
10554   }
10555 
10556   // Save a live handle in 'recenttet'.
10557   recenttet = abcd;
10558   // Set the return handle be abcd.
10559   *flipface = abcd;
10560 }
10561 
10563 //                                                                           //
10564 // flip22()    Perform a 2-to-2 (or 4-to-4) flip.                            //
10565 //                                                                           //
10566 // On input, 'flipface' represents the face will be flipped.  Let it is abe, //
10567 // ab is the flipable edge, the two tetrahedra sharing abe are abce and bade,//
10568 // hence a, b, c and d are coplanar. If abc, bad are interior faces, the two //
10569 // tetrahedra opposite to e are bacf and abdf.  ab is not a subsegment.      //
10570 //                                                                           //
10571 // A 2-to-2 flip is to change two tetrahedra abce and bade into another two  //
10572 // tetrahedra dcae and cdbe. If bacf and abdf exist, they're changed to cdaf //
10573 // and dcbf, thus a 4-to-4 flip.  As a result, two or four tetrahedra have   //
10574 // rotated counterclockwise (using right-hand rule with thumb points to e):  //
10575 // abce->dcae, bade->cdbe, and bacf->cdaf, abdf->dcbf.                       //
10576 //                                                                           //
10577 // If abc and bad are subfaces, a 2-to-2 flip is performed simultaneously by //
10578 // calling routine flip22sub(), hence abc->dca, bad->cdb.  The edge rings of //
10579 // the flipped subfaces dca and cdb have the same orientation as abc and bad.//
10580 // Hence, they have the same orientation as other subfaces of the facet with //
10581 // respect to the lift point of this facet.                                  //
10582 //                                                                           //
10583 // On completion, 'flipface' holds edge dc of tetrahedron dcae. 'flipqueue'  //
10584 // contains all possibly non-Delaunay faces if it is not NULL.               //
10585 //                                                                           //
10587 
10588 void tetgenmesh::flip22(triface* flipface, queue* flipqueue)
10589 {
10590   triface abce, bade;
10591   triface oldbce, oldcae, oldade, olddbe;
10592   triface bcecasing, caecasing, adecasing, dbecasing;
10593   face bcesh, caesh, adesh, dbesh;
10594   triface bacf, abdf;
10595   triface oldacf, oldcbf, oldbdf, olddaf;
10596   triface acfcasing, cbfcasing, bdfcasing, dafcasing;
10597   triface worktet;
10598   face acfsh, cbfsh, bdfsh, dafsh;
10599   face abc, bad;
10600   face adseg, dbseg, bcseg, caseg;  // Coplanar segs.
10601   face aeseg, deseg, beseg, ceseg;  // Above segs.
10602   face afseg, dfseg, bfseg, cfseg;  // Below segs.
10603   point pa, pb, pc, pd;
10604 #ifdef SELF_CHECK
10605   point pe, pf;
10606 #endif
10607   int mirrorflag, i;
10608 
10609   adjustedgering(*flipface, CCW); // 'flipface' is bae.
10610   fnext(*flipface, abce);
10611   esymself(abce);
10612   adjustedgering(*flipface, CW); // 'flipface' is abe.
10613   fnext(*flipface, bade);
10614 #ifdef SELF_CHECK
10615   assert(bade.tet != dummytet);
10616 #endif
10617   esymself(bade);
10618   pa = org(abce);
10619   pb = dest(abce);
10620   pc = apex(abce);
10621   pd = apex(bade);
10622 #ifdef SELF_CHECK
10623   pe = oppo(bade);
10624   assert(oppo(abce) == pe);
10625 #endif
10626   sym(abce, bacf);
10627   mirrorflag = bacf.tet != dummytet;
10628   if (mirrorflag) {
10629     // findedge(&bacf, pb, pa);
10630     bacf.ver = 0;
10631     for (i = 0; (i < 3) && (org(bacf) != pb); i++) {
10632       enextself(bacf);
10633     }
10634     sym(bade, abdf);
10635 #ifdef SELF_CHECK
10636     assert(abdf.tet != dummytet);
10637 #endif
10638     // findedge(&abdf, pa, pb);
10639     abdf.ver = 0;
10640     for (i = 0; (i < 3) && (org(abdf) != pa); i++) {
10641       enextself(abdf);
10642     }
10643 
10644 #ifdef SELF_CHECK
10645     pf = oppo(bacf);
10646     assert(oppo(abdf) == pf);
10647 #endif
10648   }
10649 
10650   if (b->verbose > 2) {
10651     printf("    Do %s on edge (%d, %d).\n", mirrorflag ? "T44" : "T22",
10652            pointmark(pa), pointmark(pb));
10653   }
10654   mirrorflag ? flip44s++ : flip22s++;
10655 
10656   // Save the old configuration at the convex hull.
10657   enextfnext(abce, oldbce);
10658   enext2fnext(abce, oldcae);
10659   enextfnext(bade, oldade);
10660   enext2fnext(bade, olddbe);
10661   sym(oldbce, bcecasing);
10662   sym(oldcae, caecasing);
10663   sym(oldade, adecasing);
10664   sym(olddbe, dbecasing);
10665   if (checksubfaces) {
10666     tspivot(oldbce, bcesh);
10667     tspivot(oldcae, caesh);
10668     tspivot(oldade, adesh);
10669     tspivot(olddbe, dbesh);
10670     tspivot(abce, abc);
10671     tspivot(bade, bad);
10672   } else if (checksubsegs) {
10673     // Coplanar segs: a->d->b->c.
10674     enext(bade, worktet);
10675     tsspivot1(worktet, adseg);
10676     enext2(bade, worktet);
10677     tsspivot1(worktet, dbseg);
10678     enext(abce, worktet);
10679     tsspivot1(worktet, bcseg);
10680     enext2(abce, worktet);
10681     tsspivot1(worktet, caseg);
10682     // Above segs: a->e, d->e, b->e, c->e.
10683     fnext(bade, worktet);
10684     enextself(worktet);
10685     tsspivot1(worktet, aeseg);
10686     enextfnext(bade, worktet);
10687     enextself(worktet);
10688     tsspivot1(worktet, deseg);
10689     enext2fnext(bade, worktet);
10690     enextself(worktet);
10691     tsspivot1(worktet, beseg);
10692     enextfnext(abce, worktet);
10693     enextself(worktet);
10694     tsspivot1(worktet, ceseg);
10695   }
10696   if (mirrorflag) {
10697     enextfnext(bacf, oldacf);
10698     enext2fnext(bacf, oldcbf);
10699     enextfnext(abdf, oldbdf);
10700     enext2fnext(abdf, olddaf);
10701     sym(oldacf, acfcasing);
10702     sym(oldcbf, cbfcasing);
10703     sym(oldbdf, bdfcasing);
10704     sym(olddaf, dafcasing);
10705     if (checksubfaces) {
10706       tspivot(oldacf, acfsh);
10707       tspivot(oldcbf, cbfsh);
10708       tspivot(oldbdf, bdfsh);
10709       tspivot(olddaf, dafsh);
10710     } else if (checksubsegs) {
10711       // Below segs: a->f, d->f, b->f, c->f.
10712       fnext(abdf, worktet);
10713       enext2self(worktet);
10714       tsspivot1(worktet, afseg);
10715       enext2fnext(abdf, worktet);
10716       enext2self(worktet);
10717       tsspivot1(worktet, dfseg);
10718       enextfnext(abdf, worktet);
10719       enext2self(worktet);
10720       tsspivot1(worktet, bfseg);
10721       enextfnext(bacf, worktet);
10722       enextself(worktet);
10723       tsspivot1(worktet, cfseg);
10724     }
10725   }
10726 
10727   // Rotate abce, bade one-quarter turn counterclockwise.
10728   bond(oldbce, caecasing);
10729   bond(oldcae, adecasing);
10730   bond(oldade, dbecasing);
10731   bond(olddbe, bcecasing);
10732   if (checksubfaces) {
10733     // Check for subfaces and rebond them to the rotated tets.
10734     if (caesh.sh == dummysh) {
10735       tsdissolve(oldbce);
10736     } else {
10737       tsbond(oldbce, caesh);
10738     }
10739     if (adesh.sh == dummysh) {
10740       tsdissolve(oldcae);
10741     } else {
10742       tsbond(oldcae, adesh);
10743     }
10744     if (dbesh.sh == dummysh) {
10745       tsdissolve(oldade);
10746     } else {
10747       tsbond(oldade, dbesh);
10748     }
10749     if (bcesh.sh == dummysh) {
10750       tsdissolve(olddbe);
10751     } else {
10752       tsbond(olddbe, bcesh);
10753     }
10754   } else if (checksubsegs) {
10755     // 5 edges in abce are changed.
10756     enext(abce, worktet);  // fit b->c into c->a.
10757     if (caseg.sh == dummysh) {
10758       tssdissolve1(worktet);
10759     } else {
10760       tssbond1(worktet, caseg);
10761     }
10762     enext2(abce, worktet); // fit c->a into a->d.
10763     if (adseg.sh == dummysh) {
10764       tssdissolve1(worktet);
10765     } else {
10766       tssbond1(worktet, adseg);
10767     }
10768     fnext(abce, worktet); // fit b->e into c->e.
10769     enextself(worktet);
10770     if (ceseg.sh == dummysh) {
10771       tssdissolve1(worktet);
10772     } else {
10773       tssbond1(worktet, ceseg);
10774     }
10775     enextfnext(abce, worktet); // fit c->e into a->e.
10776     enextself(worktet);
10777     if (aeseg.sh == dummysh) {
10778       tssdissolve1(worktet);
10779     } else {
10780       tssbond1(worktet, aeseg);
10781     }
10782     enext2fnext(abce, worktet); // fit a->e into d->e.
10783     enextself(worktet);
10784     if (deseg.sh == dummysh) {
10785       tssdissolve1(worktet);
10786     } else {
10787       tssbond1(worktet, deseg);
10788     }
10789     // 5 edges in bade are changed.
10790     enext(bade, worktet); // fit a->d into d->b.
10791     if (dbseg.sh == dummysh) {
10792       tssdissolve1(worktet);
10793     } else {
10794       tssbond1(worktet, dbseg);
10795     }
10796     enext2(bade, worktet); // fit d->b into b->c.
10797     if (bcseg.sh == dummysh) {
10798       tssdissolve1(worktet);
10799     } else {
10800       tssbond1(worktet, bcseg);
10801     }
10802     fnext(bade, worktet); // fit a->e into d->e.
10803     enextself(worktet);
10804     if (deseg.sh == dummysh) {
10805       tssdissolve1(worktet);
10806     } else {
10807       tssbond1(worktet, deseg);
10808     }
10809     enextfnext(bade, worktet); // fit d->e into b->e.
10810     enextself(worktet);
10811     if (beseg.sh == dummysh) {
10812       tssdissolve1(worktet);
10813     } else {
10814       tssbond1(worktet, beseg);
10815     }
10816     enext2fnext(bade, worktet); // fit b->e into c->e.
10817     enextself(worktet);
10818     if (ceseg.sh == dummysh) {
10819       tssdissolve1(worktet);
10820     } else {
10821       tssbond1(worktet, ceseg);
10822     }
10823   }
10824   if (mirrorflag) {
10825     // Rotate bacf, abdf one-quarter turn counterclockwise.
10826     bond(oldcbf, acfcasing);
10827     bond(oldacf, dafcasing);
10828     bond(olddaf, bdfcasing);
10829     bond(oldbdf, cbfcasing);
10830     if (checksubfaces) {
10831       // Check for subfaces and rebond them to the rotated tets.
10832       if (acfsh.sh == dummysh) {
10833         tsdissolve(oldcbf);
10834       } else {
10835         tsbond(oldcbf, acfsh);
10836       }
10837       if (dafsh.sh == dummysh) {
10838         tsdissolve(oldacf);
10839       } else {
10840         tsbond(oldacf, dafsh);
10841       }
10842       if (bdfsh.sh == dummysh) {
10843         tsdissolve(olddaf);
10844       } else {
10845         tsbond(olddaf, bdfsh);
10846       }
10847       if (cbfsh.sh == dummysh) {
10848         tsdissolve(oldbdf);
10849       } else {
10850         tsbond(oldbdf, cbfsh);
10851       }
10852     } else if (checksubsegs) {
10853       // 5 edges in bacf are changed.
10854       enext2(bacf, worktet); // fit b->c into c->a.
10855       if (caseg.sh == dummysh) {
10856         tssdissolve1(worktet);
10857       } else {
10858         tssbond1(worktet, caseg);
10859       }
10860       enext(bacf, worktet); // fit c->a into a->d.
10861       if (adseg.sh == dummysh) {
10862         tssdissolve1(worktet);
10863       } else {
10864         tssbond1(worktet, adseg);
10865       }
10866       fnext(bacf, worktet); // fit b->f into c->f.
10867       enext2self(worktet);
10868       if (cfseg.sh == dummysh) {
10869         tssdissolve1(worktet);
10870       } else {
10871         tssbond1(worktet, cfseg);
10872       }
10873       enext2fnext(bacf, worktet); // fit c->f into a->f.
10874       enext2self(worktet);
10875       if (afseg.sh == dummysh) {
10876         tssdissolve1(worktet);
10877       } else {
10878         tssbond1(worktet, afseg);
10879       }
10880       enextfnext(bacf, worktet); // fit a->f into d->f.
10881       enext2self(worktet);
10882       if (dfseg.sh == dummysh) {
10883         tssdissolve1(worktet);
10884       } else {
10885         tssbond1(worktet, dfseg);
10886       }
10887       // 5 edges in abdf are changed.
10888       enext2(abdf, worktet); // fit a->d into d->b.
10889       if (dbseg.sh == dummysh) {
10890         tssdissolve1(worktet);
10891       } else {
10892         tssbond1(worktet, dbseg);
10893       }
10894       enext(abdf, worktet); // fit d->b into b->c.
10895       if (bcseg.sh == dummysh) {
10896         tssdissolve1(worktet);
10897       } else {
10898         tssbond1(worktet, bcseg);
10899       }
10900       fnext(abdf, worktet); // fit a->f into d->f.
10901       enext2self(worktet);
10902       if (dfseg.sh == dummysh) {
10903         tssdissolve1(worktet);
10904       } else {
10905         tssbond1(worktet, dfseg);
10906       }
10907       enext2fnext(abdf, worktet); // fit d->f into b->f.
10908       enext2self(worktet);
10909       if (bfseg.sh == dummysh) {
10910         tssdissolve1(worktet);
10911       } else {
10912         tssbond1(worktet, bfseg);
10913       }
10914       enextfnext(abdf, worktet); // fit b->f into c->f.
10915       enext2self(worktet);
10916       if (cfseg.sh == dummysh) {
10917         tssdissolve1(worktet);
10918       } else {
10919         tssbond1(worktet, cfseg);
10920       }
10921     }
10922   }
10923 
10924   // New vertex assignments for the rotated tetrahedra.
10925   setorg(abce, pd); // Update abce to dcae
10926   setdest(abce, pc);
10927   setapex(abce, pa);
10928   setorg(bade, pc); // Update bade to cdbe
10929   setdest(bade, pd);
10930   setapex(bade, pb);
10931   if (mirrorflag) {
10932     setorg(bacf, pc); // Update bacf to cdaf
10933     setdest(bacf, pd);
10934     setapex(bacf, pa);
10935     setorg(abdf, pd); // Update abdf to dcbf
10936     setdest(abdf, pc);
10937     setapex(abdf, pb);
10938   }
10939 
10940   // Are there subfaces need to be flipped?
10941   if (checksubfaces && abc.sh != dummysh) {
10942 #ifdef SELF_CHECK
10943     assert(bad.sh != dummysh);
10944 #endif
10945     // Adjust the edge be ab, so the rotation of subfaces is according with
10946     //   the rotation of tetrahedra.
10947     findedge(&abc, pa, pb);
10948     // Flip an edge of two subfaces, ignore non-Delaunay edges.
10949     flip22sub(&abc, NULL);
10950   }
10951 
10952   if (b->verbose > 3) {
10953     printf("    Updating abce ");
10954     printtet(&abce);
10955     printf("    Updating bade ");
10956     printtet(&bade);
10957     if (mirrorflag) {
10958       printf("    Updating bacf ");
10959       printtet(&bacf);
10960       printf("    Updating abdf ");
10961       printtet(&abdf);
10962     }
10963   }
10964 
10965   if (flipqueue != (queue *) NULL) {
10966     enextfnext(abce, bcecasing);
10967     enqueueflipface(bcecasing, flipqueue);
10968     enext2fnext(abce, caecasing);
10969     enqueueflipface(caecasing, flipqueue);
10970     enextfnext(bade, adecasing);
10971     enqueueflipface(adecasing, flipqueue);
10972     enext2fnext(bade, dbecasing);
10973     enqueueflipface(dbecasing, flipqueue);
10974     if (mirrorflag) {
10975       enextfnext(bacf, acfcasing);
10976       enqueueflipface(acfcasing, flipqueue);
10977       enext2fnext(bacf, cbfcasing);
10978       enqueueflipface(cbfcasing, flipqueue);
10979       enextfnext(abdf, bdfcasing);
10980       enqueueflipface(bdfcasing, flipqueue);
10981       enext2fnext(abdf, dafcasing);
10982       enqueueflipface(dafcasing, flipqueue);
10983     }
10984     // The two new faces dcae (abce), cdbe (bade) may still not be locally
10985     //   Delaunay, and may need be flipped (flip23).  On the other hand, in
10986     //   conforming Delaunay algorithm, two new subfaces dca (abc), and cdb
10987     //   (bad) may be non-conforming Delaunay, they need be queued if they
10988     //   are locally Delaunay but non-conforming Delaunay.
10989     enqueueflipface(abce, flipqueue);
10990     enqueueflipface(bade, flipqueue);
10991   }
10992 
10993   // Save a live handle in 'recenttet'.
10994   recenttet = abce;
10995 }
10996 
10998 //                                                                           //
10999 // flip22sub()    Perform a 2-to-2 flip on a subface edge.                   //
11000 //                                                                           //
11001 // The flip edge is given by subface 'flipedge'.  Let it is abc, where ab is //
11002 // the flipping edge.  The other subface is bad,  where a, b, c, d form a    //
11003 // convex quadrilateral.  ab is not a subsegment.                            //
11004 //                                                                           //
11005 // A 2-to-2 subface flip is to change two subfaces abc and bad to another    //
11006 // two subfaces dca and cdb.  Hence, edge ab has been removed and dc becomes //
11007 // an edge. If a point e is above abc, this flip is equal to rotate abc and  //
11008 // bad counterclockwise using right-hand rule with thumb points to e. It is  //
11009 // important to know that the edge rings of the flipped subfaces dca and cdb //
11010 // are keeping the same orientation as their original subfaces. So they have //
11011 // the same orientation with respect to the lift point of this facet.        //
11012 //                                                                           //
11013 // During rotating, the face rings of the four edges bc, ca, ad, and de need //
11014 // be re-connected. If the edge is not a subsegment, then its face ring has  //
11015 // only two faces, a sbond() will bond them together. If it is a subsegment, //
11016 // one should use sbond1() twice to bond two different handles to the rotat- //
11017 // ing subface, one is predecssor (-casin), another is successor (-casout).  //
11018 //                                                                           //
11019 // If 'flipqueue' is not NULL, it returns four edges bc, ca, ad, de, which   //
11020 // may be non-Delaunay.                                                      //
11021 //                                                                           //
11023 
11024 void tetgenmesh::flip22sub(face* flipedge, queue* flipqueue)
11025 {
11026   face abc, bad;
11027   face oldbc, oldca, oldad, olddb;
11028   face bccasin, bccasout, cacasin, cacasout;
11029   face adcasin, adcasout, dbcasin, dbcasout;
11030   face bc, ca, ad, db;
11031   face spinsh;
11032   point pa, pb, pc, pd;
11033 
11034   abc = *flipedge;
11035   spivot(abc, bad);
11036   if (sorg(bad) != sdest(abc)) {
11037     sesymself(bad);
11038   }
11039   pa = sorg(abc);
11040   pb = sdest(abc);
11041   pc = sapex(abc);
11042   pd = sapex(bad);
11043 
11044   if (b->verbose > 2) {
11045     printf("    Flip sub edge (%d, %d).\n", pointmark(pa), pointmark(pb));
11046   }
11047 
11048   // Save the old configuration outside the quadrilateral.
11049   senext(abc, oldbc);
11050   senext2(abc, oldca);
11051   senext(bad, oldad);
11052   senext2(bad, olddb);
11053   // Get the outside connection. Becareful if there is a subsegment on the
11054   //   quadrilateral, two casings (casin and casout) are needed to save for
11055   //   keeping the face link.
11056   spivot(oldbc, bccasout);
11057   sspivot(oldbc, bc);
11058   if (bc.sh != dummysh) {
11059     // 'bc' is a subsegment.
11060     if (bccasout.sh != dummysh) {
11061       if (oldbc.sh != bccasout.sh) {
11062         // 'oldbc' is not self-bonded.
11063         spinsh = bccasout;
11064         do {
11065           bccasin = spinsh;
11066           spivotself(spinsh);
11067         } while (spinsh.sh != oldbc.sh);
11068       } else {
11069         bccasout.sh = dummysh;
11070       }
11071     }
11072     ssdissolve(oldbc);
11073   }
11074   spivot(oldca, cacasout);
11075   sspivot(oldca, ca);
11076   if (ca.sh != dummysh) {
11077     // 'ca' is a subsegment.
11078     if (cacasout.sh != dummysh) {
11079       if (oldca.sh != cacasout.sh) {
11080         // 'oldca' is not self-bonded.
11081         spinsh = cacasout;
11082         do {
11083           cacasin = spinsh;
11084           spivotself(spinsh);
11085         } while (spinsh.sh != oldca.sh);
11086       } else {
11087         cacasout.sh = dummysh;
11088       }
11089     }
11090     ssdissolve(oldca);
11091   }
11092   spivot(oldad, adcasout);
11093   sspivot(oldad, ad);
11094   if (ad.sh != dummysh) {
11095     // 'ad' is a subsegment.
11096     if (adcasout.sh != dummysh) {
11097       if (oldad.sh != adcasout.sh) {
11098         // 'adcasout' is not self-bonded.
11099         spinsh = adcasout;
11100         do {
11101           adcasin = spinsh;
11102           spivotself(spinsh);
11103         } while (spinsh.sh != oldad.sh);
11104       } else {
11105         adcasout.sh = dummysh;
11106       }
11107     }
11108     ssdissolve(oldad);
11109   }
11110   spivot(olddb, dbcasout);
11111   sspivot(olddb, db);
11112   if (db.sh != dummysh) {
11113     // 'db' is a subsegment.
11114     if (dbcasout.sh != dummysh) {
11115       if (olddb.sh != dbcasout.sh) {
11116         // 'dbcasout' is not self-bonded.
11117         spinsh = dbcasout;
11118         do {
11119           dbcasin = spinsh;
11120           spivotself(spinsh);
11121         } while (spinsh.sh != olddb.sh);
11122       } else {
11123         dbcasout.sh = dummysh;
11124       }
11125     }
11126     ssdissolve(olddb);
11127   }
11128 
11129   // Rotate abc and bad one-quarter turn counterclockwise.
11130   if (ca.sh != dummysh) {
11131     if (cacasout.sh != dummysh) {
11132       sbond1(cacasin, oldbc);
11133       sbond1(oldbc, cacasout);
11134     } else {
11135       // Bond 'oldbc' to itself.
11136       sbond(oldbc, oldbc);
11137       // Make sure that dummysh always correctly bonded.
11138       dummysh[0] = sencode(oldbc);
11139     }
11140     ssbond(oldbc, ca);
11141   } else {
11142     sbond(oldbc, cacasout);
11143   }
11144   if (ad.sh != dummysh) {
11145     if (adcasout.sh != dummysh) {
11146       sbond1(adcasin, oldca);
11147       sbond1(oldca, adcasout);
11148     } else {
11149       // Bond 'oldca' to itself.
11150       sbond(oldca, oldca);
11151       // Make sure that dummysh always correctly bonded.
11152       dummysh[0] = sencode(oldca);
11153     }
11154     ssbond(oldca, ad);
11155   } else {
11156     sbond(oldca, adcasout);
11157   }
11158   if (db.sh != dummysh) {
11159     if (dbcasout.sh != dummysh) {
11160       sbond1(dbcasin, oldad);
11161       sbond1(oldad, dbcasout);
11162     } else {
11163       // Bond 'oldad' to itself.
11164       sbond(oldad, oldad);
11165       // Make sure that dummysh always correctly bonded.
11166       dummysh[0] = sencode(oldad);
11167     }
11168     ssbond(oldad, db);
11169   } else {
11170     sbond(oldad, dbcasout);
11171   }
11172   if (bc.sh != dummysh) {
11173     if (bccasout.sh != dummysh) {
11174       sbond1(bccasin, olddb);
11175       sbond1(olddb, bccasout);
11176     } else {
11177       // Bond 'olddb' to itself.
11178       sbond(olddb, olddb);
11179       // Make sure that dummysh always correctly bonded.
11180       dummysh[0] = sencode(olddb);
11181     }
11182     ssbond(olddb, bc);
11183   } else {
11184     sbond(olddb, bccasout);
11185   }
11186 
11187   // New vertex assignments for the rotated subfaces.
11188   setsorg(abc, pd);  // Update abc to dca.
11189   setsdest(abc, pc);
11190   setsapex(abc, pa);
11191   setsorg(bad, pc);  // Update bad to cdb.
11192   setsdest(bad, pd);
11193   setsapex(bad, pb);
11194 
11195   if (flipqueue != (queue *) NULL) {
11196     enqueueflipedge(bccasout, flipqueue);
11197     enqueueflipedge(cacasout, flipqueue);
11198     enqueueflipedge(adcasout, flipqueue);
11199     enqueueflipedge(dbcasout, flipqueue);
11200   }
11201 }
11202 
11204 //                                                                           //
11205 // flip()    Flips non-locally Delaunay faces in flipqueue until it is empty.//
11206 //                                                                           //
11207 // Assumpation:  Current tetrahedralization is non-Delaunay after inserting  //
11208 // a point or performing a flip operation, all possibly non-Delaunay faces   //
11209 // are in 'flipqueue'.                                                       //
11210 //                                                                           //
11211 // If 'plastflip' is not NULL,  it is used to return a stack of recently     //
11212 // flipped faces.  This stack will be used to reverse the flips done in this //
11213 // routine later for removing a newly inserted point because it encroaches   //
11214 // any subfaces or subsegments.                                              //
11215 //                                                                           //
11216 // The return value is the total number of flips done during this invocation.//
11217 //                                                                           //
11219 
11220 long tetgenmesh::flip(queue* flipqueue, badface **plastflip)
11221 {
11222   badface *qface, *newflip;
11223   triface flipface, symface;
11224   point pa, pb, pc, pd, pe;
11225   enum fliptype fc;
11226   REAL sign, bakepsilon;
11227   long flipcount; //, maxfaces; - commented out to get gcc4.6 working
11228   int epscount, fcount;
11229   int ia, ib, ic, id, ie;
11230 
11231   if (b->verbose > 1) {
11232     printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
11233   }
11234 
11235   flipcount = flip23s + flip32s + flip22s + flip44s;
11236   if (checksubfaces) {
11237     //maxfaces = (4l * tetrahedrons->items + hullsize) / 2l; // commented out to get gcc 4.6 working
11238     fcount = 0;
11239   }
11240 
11241   if (plastflip != (badface **) NULL) {
11242     // Initialize the stack of the flip sequence.
11243     flipstackers->restart();
11244     *plastflip = (badface *) NULL;
11245   }
11246 
11247   // Loop until the queue is empty.
11248   while (!flipqueue->empty()) {
11249     qface = (badface *) flipqueue->pop();
11250     flipface = qface->tt;
11251     if (isdead(&flipface)) continue;
11252     sym(flipface, symface);
11253     // Only do check when the adjacent tet exists and it's not a "fake" tet.
11254     if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11255       // For positive orientation that insphere() test requires.
11256       adjustedgering(flipface, CW);
11257       pa = org(flipface);
11258       pb = dest(flipface);
11259       pc = apex(flipface);
11260       pd = oppo(flipface);
11261       pe = oppo(symface);
11262       if (symbolic) {
11263         ia = pointmark(pa);
11264         ib = pointmark(pb);
11265         ic = pointmark(pc);
11266         id = pointmark(pd);
11267         ie = pointmark(pe);
11268         sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
11269         assert(sign != 0.0);
11270       } else {
11271         sign = insphere(pa, pb, pc, pd, pe);
11272       }
11273     } else {
11274       sign = -1.0; // A hull face is locally Delaunay.
11275     }
11276     if (sign > 0.0) {
11277       // 'flipface' is non-locally Delaunay, try to flip it.
11278       if (checksubfaces) {
11279         fcount++;
11280         bakepsilon = b->epsilon;
11281         epscount = 0;
11282         while (epscount < 32) {
11283           fc = categorizeface(flipface);
11284           if (fc == N40) {
11285             b->epsilon *= 1e-1;
11286             epscount++;
11287             continue;
11288           }
11289           break;
11290         }
11291         b->epsilon = bakepsilon;
11292         if (epscount >= 32) {
11293           if (b->verbose > 0) {
11294             printf("Warning:  Can't flip a degenerate tetrahedron.\n");
11295           }
11296           fc = N40;
11297         }
11298       } else {
11299         fc = categorizeface(flipface);
11300 #ifdef SELF_CHECK
11301         assert(fc != N40);
11302 #endif
11303       }
11304       switch (fc) {
11305       // The following face types are flipable.
11306       case T44:
11307       case T22:
11308         flip22(&flipface, flipqueue);
11309         break;
11310       case T23:
11311         flip23(&flipface, flipqueue);
11312         break;
11313       case T32:
11314         flip32(&flipface, flipqueue);
11315         break;
11316       // The following face types are unflipable.
11317       case N32:
11318         break;
11319       case FORBIDDENFACE:
11320         break;
11321       case FORBIDDENEDGE:
11322         break;
11323       // This case is only possible when the domain is nonconvex.
11324       case N40:
11325         // assert(nonconvex);
11326         break;
11327       }
11328       if (plastflip != (badface **) NULL) {
11329         if ((fc == T44) || (fc == T22) || (fc == T23) || (fc == T32)) {
11330           // Push the flipped face into stack.
11331           newflip = (badface *) flipstackers->alloc();
11332           newflip->tt = flipface;
11333           newflip->key = (REAL) fc;
11334           newflip->forg = org(flipface);
11335           newflip->fdest = dest(flipface);
11336           newflip->fapex = apex(flipface);
11337           newflip->previtem = *plastflip;
11338           *plastflip = newflip;
11339         }
11340       }
11341     }
11342   }
11343 
11344   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11345   if (b->verbose > 1) {
11346     printf("    %ld flips.\n", flipcount);
11347   }
11348 
11349   return flipcount;
11350 }
11351 
11353 //                                                                           //
11354 // lawson()    Flip locally non-Delaunay faces by Lawson's algorithm.        //
11355 //                                                                           //
11357 
11358 long tetgenmesh::lawson(list *misseglist, queue* flipqueue)
11359 {
11360   badface *qface, *misseg;
11361   triface flipface, symface;
11362   triface starttet, spintet;
11363   face checksh, checkseg;
11364   point pa, pb, pc, pd, pe;
11365   point swappt;
11366   REAL sign, ori;
11367   long flipcount;
11368   int ia, ib, ic, id, ie;
11369   int hitbdry, i;
11370 
11371   if (b->verbose > 1) {
11372     printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
11373   }
11374   flipcount = flip23s + flip32s + flip22s + flip44s;
11375 
11376   // Go through the stack of possible flips and decide whether to do them.
11377   //   Note that during the loop new possible flips will be pushed onto
11378   //   this stack, while they popped in this loop.
11379   while (!flipqueue->empty()) {
11380     qface = (badface *) flipqueue->pop();
11381     flipface = qface->tt;
11382     // Check if tet has already been flipped out of existence.
11383     if (!isdead(&flipface)) {
11384       sym(flipface, symface);
11385       // Check if this tet is the same as the one which was stacked.
11386       if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11387         flipface.ver = 0; // Select the CCW ring.
11388         pa = org(flipface);
11389         pb = dest(flipface);
11390         pc = apex(flipface);
11391         pd = oppo(flipface);
11392         pe = oppo(symface);
11393         if (symbolic) {
11394           ia = pointmark(pa);
11395           ib = pointmark(pb);
11396           ic = pointmark(pc);
11397           id = pointmark(pd);
11398           ie = pointmark(pe);
11399           sign = insphere_sos(pb, pa, pc, pd, pe, ib, ia, ic, id, ie);
11400         } else {
11401           sign = insphere(pb, pa, pc, pd, pe);
11402         }
11403         if (sign > 0.0) {
11404           for (i = 0; i < 3; i++) {
11405             ori = orient3d(pa, pb, pd, pe);
11406             if (ori > 0.0) {
11407               // Goto and check the next edge.
11408               swappt = pa;
11409               pa = pb;
11410               pb = pc;
11411               pc = swappt;
11412               enextself(flipface);
11413             } else {
11414               break; // either (ori < 0.0) or (ori == 0.0)
11415             }
11416           } // for (i = 0; ....)
11417           if (ori > 0.0) {
11418             // All three edges are convex, a 2-3 flip is possible.
11419             if (checksubfaces) {
11420               tspivot(flipface, checksh);
11421               if (checksh.sh != dummysh) {
11422                 // A subface is not flipable.
11423                 continue;
11424               }
11425             }
11426             flip23(&flipface, flipqueue);
11427           } else if (ori < 0.0) {
11428             // The edge (a, b) is non-convex, check for a 3-2 flip.
11429             fnext(flipface, symface);
11430             symself(symface);
11431             if (oppo(symface) == pe) {
11432               // Only three tets adjoining this edge.
11433               if (checksubfaces) {
11434                 tsspivot(&flipface, &checkseg);
11435                 if (checkseg.sh != dummysh) {
11436                   // A subsegment is not flipable.
11437                   continue;
11438                 }
11439               } else if (checksubsegs) {
11440                 tsspivot1(flipface, checkseg);
11441                 if (checkseg.sh != dummysh) {
11442                   if (b->verbose > 2) {
11443                     printf("    Queuing missing segment (%d, %d).\n",
11444                       pointmark(org(flipface)), pointmark(dest(flipface)));
11445                   }
11446                   misseg = (badface *) misseglist->append(NULL);
11447                   misseg->ss = checkseg;
11448                   misseg->forg = sorg(checkseg);
11449                   misseg->fdest = sdest(checkseg);
11450                   // Detach all tets having this seg.
11451                   starttet = flipface;
11452                   adjustedgering(starttet, CCW);
11453                   fnextself(starttet);
11454                   spintet = starttet;
11455                   hitbdry = 0;
11456                   do {
11457                     tssdissolve1(spintet);
11458                     if (!fnextself(spintet)) {
11459                       hitbdry++;
11460                       if (hitbdry < 2) {
11461                         esym(starttet, spintet);
11462                         if (!fnextself(spintet)) {
11463                           hitbdry++;
11464                         }
11465                       }
11466                     }
11467                   } while ((apex(spintet) != apex(starttet)) && (hitbdry < 2));
11468                 }
11469               } // if (checksubfaces)
11470               flip32(&flipface, flipqueue);
11471             }
11472           } else {
11473             // Four points (a, b, d, e) are coplanar.
11474             fnext(flipface, symface);
11475             if (fnextself(symface)) {
11476               // Check for a 4-4 flip.
11477               fnextself(symface);
11478               if (apex(symface) == pe) {
11479                 if (checksubfaces) {
11480                   tsspivot(&flipface, &checkseg);
11481                   if (checkseg.sh != dummysh) {
11482                     // A subsegment is not flippable.
11483                     continue;
11484                   }
11485                 } else if (checksubsegs) {
11486                   tsspivot1(flipface, checkseg);
11487                   if (checkseg.sh != dummysh) {
11488                     if (b->verbose > 2) {
11489                       printf("    Queuing missing segment (%d, %d).\n",
11490                         pointmark(org(flipface)), pointmark(dest(flipface)));
11491                     }
11492                     misseg = (badface *) misseglist->append(NULL);
11493                     misseg->ss = checkseg;
11494                     misseg->forg = sorg(checkseg);
11495                     misseg->fdest = sdest(checkseg);
11496                     // Detach all tets having this seg.
11497                     starttet = flipface;
11498                     adjustedgering(starttet, CCW);
11499                     fnextself(starttet);
11500                     spintet = starttet;
11501                     hitbdry = 0;
11502                     do {
11503                       tssdissolve1(spintet);
11504                       if (!fnextself(spintet)) {
11505                         hitbdry++;
11506                         if (hitbdry < 2) {
11507                           esym(starttet, spintet);
11508                           if (!fnextself(spintet)) {
11509                             hitbdry++;
11510                           }
11511                         }
11512                       }
11513                     } while ((apex(spintet) != apex(starttet)) &&
11514                              (hitbdry < 2));
11515                   }
11516                 } // if (checksubfaces)
11517                 flip22(&flipface, flipqueue);
11518               }
11519             } else {
11520               // Check for a 2-2 flip.
11521               esym(flipface, symface);
11522               fnextself(symface);
11523               symself(symface);
11524               if (symface.tet == dummytet) {
11525                 if (checksubfaces) {
11526                   tsspivot(&flipface, &checkseg);
11527                   if (checkseg.sh != dummysh) {
11528                     // A subsegment is not flipable.
11529                     continue;
11530                   }
11531                 } else if (checksubsegs) {
11532                   tsspivot1(flipface, checkseg);
11533                   if (checkseg.sh != dummysh) {
11534                     if (b->verbose > 2) {
11535                       printf("    Queuing missing segment (%d, %d).\n",
11536                         pointmark(org(flipface)), pointmark(dest(flipface)));
11537                     }
11538                     misseg = (badface *) misseglist->append(NULL);
11539                     misseg->ss = checkseg;
11540                     misseg->forg = sorg(checkseg);
11541                     misseg->fdest = sdest(checkseg);
11542                     // Detach all tets having this seg.
11543                     starttet = flipface;
11544                     adjustedgering(starttet, CCW);
11545                     fnextself(starttet);
11546                     spintet = starttet;
11547                     hitbdry = 0;
11548                     do {
11549                       tssdissolve1(spintet);
11550                       if (!fnextself(spintet)) {
11551                         hitbdry++;
11552                         if (hitbdry < 2) {
11553                           esym(starttet, spintet);
11554                           if (!fnextself(spintet)) {
11555                             hitbdry++;
11556                           }
11557                         }
11558                       }
11559                     } while ((apex(spintet) != apex(starttet)) &&
11560                              (hitbdry < 2));
11561                   }
11562                 } // if (checksubfaces)
11563                 flip22(&flipface, flipqueue);
11564               }
11565             }
11566           } // if (ori > 0.0)
11567         } // if (sign > 0.0)
11568       }
11569     } // !isdead(&qface->tt)
11570   } // while (!flipqueue->empty())
11571 
11572   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11573   if (b->verbose > 1) {
11574     printf("    %ld flips.\n", flipcount);
11575   }
11576   return flipcount;
11577 }
11578 
11580 //                                                                           //
11581 // undoflip()    Undo the most recent flip sequence induced by flip().       //
11582 //                                                                           //
11583 // 'lastflip' is the stack of recently flipped faces. Walks through the list //
11584 // of flips, in the reverse of the order in which they were done, and undoes //
11585 // them.                                                                     //
11586 //                                                                           //
11588 
11589 void tetgenmesh::undoflip(badface *lastflip)
11590 {
11591   enum fliptype fc;
11592 
11593   while (lastflip != (badface *) NULL) {
11594     // Get the right flipped face.
11595     findface(&lastflip->tt, lastflip->forg, lastflip->fdest, lastflip->fapex);
11596     fc = (enum fliptype) (int) lastflip->key;
11597     switch (fc) {
11598     case T23:
11599       // The reverse operation of T23 is T32.
11600       flip32(&lastflip->tt, NULL);
11601       break;
11602     case T32:
11603       // The reverse operation of T32 is T23.
11604       flip23(&lastflip->tt, NULL);
11605       break;
11606     case T22:
11607     case T44:
11608       // The reverse operation of T22 or T44 is again T22 or T44.
11609       flip22(&lastflip->tt, NULL);
11610       break;
11611     default: // To omit compile warnings.
11612       break;
11613     }
11614     // Go on and process the next transformation.
11615     lastflip = lastflip->previtem;
11616   }
11617 }
11618 
11620 //                                                                           //
11621 // flipsub()    Flip non-Delaunay edges in a queue of (coplanar) subfaces.   //
11622 //                                                                           //
11623 // Assumpation:  Current triangulation T contains non-Delaunay edges (after  //
11624 // inserting a point or performing a flip). Non-Delaunay edges are queued in //
11625 // 'facequeue'. Returns the total number of flips done during this call.     //
11626 //                                                                           //
11628 
11629 long tetgenmesh::flipsub(queue* flipqueue)
11630 {
11631   badface *qedge;
11632   face flipedge, symedge;
11633   face checkseg;
11634   point pa, pb, pc, pd;
11635   REAL vab[3], vac[3], vad[3];
11636   REAL dot1, dot2, lac, lad;
11637   REAL sign, ori;
11638   int edgeflips;
11639   int i;
11640 
11641   if (b->verbose > 1) {
11642     printf("  Start do edge queue: %ld edges.\n", flipqueue->len());
11643   }
11644 
11645   edgeflips = 0;
11646 
11647   while (!flipqueue->empty()) {
11648     qedge = (badface *) flipqueue->pop();
11649     flipedge = qedge->ss;
11650     if (flipedge.sh == dummysh) continue;
11651     if ((sorg(flipedge) != qedge->forg) ||
11652         (sdest(flipedge) != qedge->fdest)) continue;
11653     sspivot(flipedge, checkseg);
11654     if (checkseg.sh != dummysh) continue;  // Can't flip a subsegment.
11655     spivot(flipedge, symedge);
11656     if (symedge.sh == dummysh) continue; // Can't flip a hull edge.
11657     pa = sorg(flipedge);
11658     pb = sdest(flipedge);
11659     pc = sapex(flipedge);
11660     pd = sapex(symedge);
11661     // Choose the triangle abc or abd as the base depending on the angle1
11662     //   (Vac, Vab) and angle2 (Vad, Vab).
11663     for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
11664     for (i = 0; i < 3; i++) vac[i] = pc[i] - pa[i];
11665     for (i = 0; i < 3; i++) vad[i] = pd[i] - pa[i];
11666     dot1 = dot(vac, vab);
11667     dot2 = dot(vad, vab);
11668     dot1 *= dot1;
11669     dot2 *= dot2;
11670     lac = dot(vac, vac);
11671     lad = dot(vad, vad);
11672     if (lad * dot1 <= lac * dot2) {
11673       // angle1 is closer to 90 than angle2, choose abc (flipedge).
11674       abovepoint = facetabovepointarray[shellmark(flipedge)];
11675       if (abovepoint == (point) NULL) {
11676         getfacetabovepoint(&flipedge);
11677       }
11678       sign = insphere(pa, pb, pc, abovepoint, pd);
11679       ori = orient3d(pa, pb, pc, abovepoint);
11680     } else {
11681       // angle2 is closer to 90 than angle1, choose abd (symedge).
11682       abovepoint = facetabovepointarray[shellmark(symedge)];
11683       if (abovepoint == (point) NULL) {
11684         getfacetabovepoint(&symedge);
11685       }
11686       sign = insphere(pa, pb, pd, abovepoint, pc);
11687       ori = orient3d(pa, pb, pd, abovepoint);
11688     }
11689     // Correct the sign.
11690     sign = ori > 0.0 ? sign : -sign;
11691     if (sign > 0.0) {
11692       // Flip the non-Delaunay edge.
11693       flip22sub(&flipedge, flipqueue);
11694       edgeflips++;
11695     }
11696   }
11697 
11698   if (b->verbose > 1) {
11699     printf("  Total %d flips.\n", edgeflips);
11700   }
11701 
11702   return edgeflips;
11703 }
11704 
11706 //                                                                           //
11707 // removetetbypeeloff()    Remove a boundary tet by peeling it off.          //
11708 //                                                                           //
11709 // 'striptet' (abcd) is on boundary and can be removed by stripping it off.  //
11710 // Let abc and bad are the external boundary faces.                          //
11711 //                                                                           //
11712 // To strip 'abcd' from the mesh is to detach its two interal faces (dca and //
11713 // cdb) from their adjoining tets together with a 2-to-2 flip to transform   //
11714 // two subfaces (abc and bad) into another two (dca and cdb).                //
11715 //                                                                           //
11716 // In mesh optimization. It is possible that ab is a segment and abcd is a   //
11717 // sliver on the hull. Strip abcd will also delete the segment ab.           //
11718 //                                                                           //
11720 
11721 bool tetgenmesh::removetetbypeeloff(triface *striptet)
11722 {
11723   triface abcd, badc;
11724   triface dcacasing, cdbcasing;
11725   face abc, bad;
11726   face abseg;
11727   REAL ang;
11728 
11729   abcd = *striptet;
11730   adjustedgering(abcd, CCW);
11731   // Get the casing tets at the internal sides.
11732   enextfnext(abcd, cdbcasing);
11733   enext2fnext(abcd, dcacasing);
11734   symself(cdbcasing);
11735   symself(dcacasing);
11736   // Do the neighboring tets exist?  During optimization. It is possible
11737   //   that the neighboring tets are already dead.
11738   if ((cdbcasing.tet == dummytet) || (dcacasing.tet == dummytet)) {
11739     // Do not strip this tet.
11740     return false;
11741   }
11742 
11743   // Are there subfaces?
11744   if (checksubfaces) {
11745     // Get the external subfaces abc, bad.
11746     fnext(abcd, badc);
11747     esymself(badc);
11748     tspivot(abcd, abc);
11749     tspivot(badc, bad);
11750     if (abc.sh != dummysh) {
11751       assert(bad.sh != dummysh);
11752       findedge(&abc, org(abcd), dest(abcd));
11753       findedge(&bad, org(badc), dest(badc));
11754       // Is ab a segment?
11755       sspivot(abc, abseg);
11756       if (abseg.sh != dummysh) {
11757         // Does a segment allow to be removed?
11758         if ((b->optlevel > 3) && (b->nobisect == 0)) {
11759           // Only remove this segment if the dihedal angle at ab is between
11760           //   [b->maxdihedral-9, 180] (deg).  This avoids mistakely fliping
11761           //   ab when it has actually no big dihedral angle while cd has.
11762           ang = facedihedral(org(abcd), dest(abcd), apex(abcd), oppo(abcd));
11763           ang = ang * 180.0 / PI;
11764           if ((ang + 9.0) > b->maxdihedral) {
11765             if (b->verbose > 1) {
11766               printf("    Remove a segment during peeling.\n");
11767             }
11768             face prevseg, nextseg;
11769             // It is only shared by abc and bad (abcd is a tet).
11770             ssdissolve(abc);
11771             ssdissolve(bad);
11772             abseg.shver = 0;
11773             senext(abseg, nextseg);
11774             spivotself(nextseg);
11775             if (nextseg.sh != dummysh) {
11776               ssdissolve(nextseg);
11777             }
11778             senext2(abseg, prevseg);
11779             spivotself(prevseg);
11780             if (prevseg.sh != dummysh) {
11781               ssdissolve(prevseg);
11782             }
11783             shellfacedealloc(subsegs, abseg.sh);
11784             optcount[1]++;
11785           } else {
11786             return false;
11787           }
11788         } else {
11789           return false;
11790         }
11791       }
11792       // Do a 2-to-2 flip on abc and bad, transform abc->dca, bad->cdb.
11793       flip22sub(&abc, NULL);
11794       // The two internal faces become boundary faces.
11795       tsbond(cdbcasing, bad);
11796       tsbond(dcacasing, abc);
11797     }
11798   }
11799 
11800   // Detach abcd from the two internal faces.
11801   dissolve(cdbcasing);
11802   dissolve(dcacasing);
11803   // Delete abcd.
11804   tetrahedrondealloc(abcd.tet);
11805   return true;
11806 }
11807 
11809 //                                                                           //
11810 // removeedgebyflip22()    Remove an edge by a 2-to-2 (or 4-to-4) flip.      //
11811 //                                                                           //
11812 // 'abtetlist' contains n tets (n is 2 or 4) sharing edge ab,  abtetlist[0]  //
11813 // and abtetlist[1] are tets abec and abde, respectively (NOTE, both are in  //
11814 // CW edge ring), where a, b, c, and d are coplanar.  If n = 4, abtetlist[2] //
11815 // and abtetlist[3] are tets abfd and abcf, respectively.  This routine uses //
11816 // flip22() to replace edge ab with cd, the surrounding tets are rotated.    //
11817 //                                                                           //
11818 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
11819 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
11820 // is the maximum dihedral angle in the old tets.                            //
11821 //                                                                           //
11823 
11824 bool tetgenmesh::removeedgebyflip22(REAL *key, int n, triface *abtetlist,
11825   queue *flipque)
11826 {
11827   point pa, pb, pc, pd, pe, pf;
11828   REAL cosmaxd, d1, d2, d3;
11829   bool doflip;
11830 
11831   cosmaxd = 0.0;
11832   pf = apex(abtetlist[2]);
11833   doflip = true;
11834   adjustedgering(abtetlist[0], CW);
11835   pa = org(abtetlist[0]);
11836   pb = dest(abtetlist[0]);
11837   pe = apex(abtetlist[0]);
11838   pc = oppo(abtetlist[0]);
11839   pd = apex(abtetlist[1]);
11840   if (n == 4) {
11841     pf = apex(abtetlist[2]);
11842   }
11843   if (key && (*key > -1.0)) {
11844     tetalldihedral(pc, pd, pe, pa, NULL, &d1, NULL);
11845     tetalldihedral(pd, pc, pe, pb, NULL, &d2, NULL);
11846     cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11847     if (n == 4) {
11848       tetalldihedral(pd, pc, pf, pa, NULL, &d1, NULL);
11849       tetalldihedral(pc, pd, pf, pb, NULL, &d2, NULL);
11850       d3 = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11851       cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
11852     }
11853     doflip = (*key < cosmaxd); // Can local quality be improved?
11854   }
11855 
11856   if (doflip) {
11857     flip22(&abtetlist[0], NULL);
11858     // Return the improved quality value.
11859     if (key) *key = cosmaxd;
11860   }
11861 
11862   return doflip;
11863 }
11864 
11866 //                                                                           //
11867 // removefacebyflip23()    Remove a face by a 2-to-3 flip.                   //
11868 //                                                                           //
11869 // 'abctetlist' contains 2 tets sharing abc, which are [0]abcd and [1]bace.  //
11870 // This routine forms three new tets that abc is not a face anymore. Save    //
11871 // them in 'newtetlist': [0]edab, [1]edbc, and [2]edca.  Note that the new   //
11872 // tets may not valid if one of them get inverted. return false if so.       //
11873 //                                                                           //
11874 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
11875 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
11876 // is the maximum dihedral angle in the old tets.                            //
11877 //                                                                           //
11878 // If the face is flipped, 'newtetlist' returns the three new tets. The two  //
11879 // tets in 'abctetlist' are NOT deleted.  The caller has the right to either //
11880 // delete them or reverse the operation.                                     //
11881 //                                                                           //
11883 
11884 bool tetgenmesh::removefacebyflip23(REAL *key, triface *abctetlist,
11885   triface *newtetlist, queue *flipque)
11886 {
11887   triface edab, edbc, edca; // new configuration.
11888   triface newfront, oldfront, adjfront;
11889   face checksh;
11890   point pa, pb, pc, pd, pe;
11891   REAL ori, cosmaxd, d1, d2, d3;
11892   REAL attrib, volume;
11893   bool doflip;
11894   int i;
11895 
11896   cosmaxd = 0.0;
11897 
11898   adjustedgering(abctetlist[0], CCW);
11899   pa = org(abctetlist[0]);
11900   pb = dest(abctetlist[0]);
11901   pc = apex(abctetlist[0]);
11902   pd = oppo(abctetlist[0]);
11903   pe = oppo(abctetlist[1]);
11904 
11905   // Check if the flip creates valid new tets.
11906   ori = orient3d(pe, pd, pa, pb);
11907   if (ori < 0.0) {
11908     ori = orient3d(pe, pd, pb, pc);
11909     if (ori < 0.0) {
11910       ori = orient3d(pe, pd, pc, pa);
11911     }
11912   }
11913   doflip = (ori < 0.0); // Can abc be flipped away?
11914   if (doflip && (key != (REAL *) NULL)) {
11915     if (*key > -1.0) {
11916       // Test if the new tets reduce the maximal dihedral angle.
11917       tetalldihedral(pe, pd, pa, pb, NULL, &d1, NULL);
11918       tetalldihedral(pe, pd, pb, pc, NULL, &d2, NULL);
11919       tetalldihedral(pe, pd, pc, pa, NULL, &d3, NULL);
11920       cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11921       cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
11922       doflip = (*key < cosmaxd); // Can local quality be improved?
11923     }
11924   }
11925 
11926   if (doflip) {
11927     // A valid (2-to-3) flip is found.
11928     flip23s++;
11929     // Create the new tets.
11930     maketetrahedron(&edab);
11931     setorg(edab, pe);
11932     setdest(edab, pd);
11933     setapex(edab, pa);
11934     setoppo(edab, pb);
11935     maketetrahedron(&edbc);
11936     setorg(edbc, pe);
11937     setdest(edbc, pd);
11938     setapex(edbc, pb);
11939     setoppo(edbc, pc);
11940     maketetrahedron(&edca);
11941     setorg(edca, pe);
11942     setdest(edca, pd);
11943     setapex(edca, pc);
11944     setoppo(edca, pa);
11945     // Transfer the element attributes.
11946     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
11947       attrib = elemattribute(abctetlist[0].tet, i);
11948       setelemattribute(edab.tet, i, attrib);
11949       setelemattribute(edbc.tet, i, attrib);
11950       setelemattribute(edca.tet, i, attrib);
11951     }
11952     // Transfer the volume constraints.
11953     if (b->varvolume && !b->refine) {
11954       volume = volumebound(abctetlist[0].tet);
11955       setvolumebound(edab.tet, volume);
11956       setvolumebound(edbc.tet, volume);
11957       setvolumebound(edca.tet, volume);
11958     }
11959     // Return two new tets.
11960     newtetlist[0] = edab;
11961     newtetlist[1] = edbc;
11962     newtetlist[2] = edca;
11963     // Glue the three new tets.
11964     for (i = 0; i < 3; i++) {
11965       fnext(newtetlist[i], newfront);
11966       bond(newfront, newtetlist[(i + 1) % 3]);
11967     }
11968     // Substitute the three new tets into the old cavity.
11969     for (i = 0; i < 3; i++) {
11970       fnext(abctetlist[0], oldfront);
11971       sym(oldfront, adjfront); // may be outside.
11972       enextfnext(newtetlist[i], newfront);
11973       bond(newfront, adjfront);
11974       if (checksubfaces) {
11975         tspivot(oldfront, checksh);
11976         if (checksh.sh != dummysh) {
11977           tsbond(newfront, checksh);
11978         }
11979       }
11980       if (flipque != (queue *) NULL) {
11981         enqueueflipface(newfront, flipque);
11982       }
11983       enextself(abctetlist[0]);
11984     }
11985     findedge(&(abctetlist[1]), pb, pa);
11986     for (i = 0; i < 3; i++) {
11987       fnext(abctetlist[1], oldfront);
11988       sym(oldfront, adjfront); // may be outside.
11989       enext2fnext(newtetlist[i], newfront);
11990       bond(newfront, adjfront);
11991       if (checksubfaces) {
11992         tspivot(oldfront, checksh);
11993         if (checksh.sh != dummysh) {
11994           tsbond(newfront, checksh);
11995         }
11996       }
11997       if (flipque != (queue *) NULL) {
11998         enqueueflipface(newfront, flipque);
11999       }
12000       enext2self(abctetlist[1]);
12001     }
12002     // Do not delete the old tets.
12003     // for (i = 0; i < 2; i++) {
12004     //   tetrahedrondealloc(abctetlist[i].tet);
12005     // }
12006     // Return the improved quality value.
12007     if (key != (REAL *) NULL) *key = cosmaxd;
12008     return true;
12009   }
12010 
12011   return false;
12012 }
12013 
12015 //                                                                           //
12016 // removeedgebyflip32()    Remove an edge by a 3-to-2 flip.                  //
12017 //                                                                           //
12018 // 'abtetlist' contains 3 tets sharing ab. Imaging that ab is perpendicular  //
12019 // to the screen, where a lies in front of and b lies behind it. The 3 tets  //
12020 // of the list are: [0]abce, [1]abdc, and [2]abed, respectively.             //
12021 //                                                                           //
12022 // This routine forms two new tets that ab is not an edge of them. Save them //
12023 // in 'newtetlist', [0]dcea, [1]cdeb. Note that the new tets may not valid   //
12024 // if one of them get inverted. return false if so.                          //
12025 //                                                                           //
12026 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
12027 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
12028 // is the maximum dihedral angle in the old tets.                            //
12029 //                                                                           //
12030 // If the edge is flipped, 'newtetlist' returns the two new tets. The three  //
12031 // tets in 'abtetlist' are NOT deleted.  The caller has the right to either  //
12032 // delete them or reverse the operation.                                     //
12033 //                                                                           //
12035 
12036 bool tetgenmesh::removeedgebyflip32(REAL *key, triface *abtetlist,
12037   triface *newtetlist, queue *flipque)
12038 {
12039   triface dcea, cdeb; // new configuration.
12040   triface newfront, oldfront, adjfront;
12041   face checksh;
12042   point pa, pb, pc, pd, pe;
12043   REAL ori, cosmaxd, d1, d2;
12044   REAL attrib, volume;
12045   bool doflip;
12046   int i;
12047 
12048   pa = org(abtetlist[0]);
12049   pb = dest(abtetlist[0]);
12050   pc = apex(abtetlist[0]);
12051   pd = apex(abtetlist[1]);
12052   pe = apex(abtetlist[2]);
12053 
12054   ori = orient3d(pd, pc, pe, pa);
12055   if (ori < 0.0) {
12056     ori = orient3d(pc, pd, pe, pb);
12057   }
12058   doflip = (ori < 0.0); // Can ab be flipped away?
12059 
12060   // Does the caller ensure a valid configuration?
12061   if (doflip && (key != (REAL *) NULL)) {
12062     if (*key > -1.0) {
12063       // Test if the new tets reduce the maximal dihedral angle.
12064       tetalldihedral(pd, pc, pe, pa, NULL, &d1, NULL);
12065       tetalldihedral(pc, pd, pe, pb, NULL, &d2, NULL);
12066       cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
12067       doflip = (*key < cosmaxd); // Can local quality be improved?
12068       // Return the key
12069       *key = cosmaxd;
12070     }
12071   }
12072 
12073   if (doflip) {
12074     // Create the new tets.
12075     maketetrahedron(&dcea);
12076     setorg(dcea, pd);
12077     setdest(dcea, pc);
12078     setapex(dcea, pe);
12079     setoppo(dcea, pa);
12080     maketetrahedron(&cdeb);
12081     setorg(cdeb, pc);
12082     setdest(cdeb, pd);
12083     setapex(cdeb, pe);
12084     setoppo(cdeb, pb);
12085     // Transfer the element attributes.
12086     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12087       attrib = elemattribute(abtetlist[0].tet, i);
12088       setelemattribute(dcea.tet, i, attrib);
12089       setelemattribute(cdeb.tet, i, attrib);
12090     }
12091     // Transfer the volume constraints.
12092     if (b->varvolume && !b->refine) {
12093       volume = volumebound(abtetlist[0].tet);
12094       setvolumebound(dcea.tet, volume);
12095       setvolumebound(cdeb.tet, volume);
12096     }
12097     // Return two new tets.
12098     newtetlist[0] = dcea;
12099     newtetlist[1] = cdeb;
12100     // Glue the two new tets.
12101     bond(dcea, cdeb);
12102     // Substitute the two new tets into the old three-tets cavity.
12103     for (i = 0; i < 3; i++) {
12104       fnext(dcea, newfront); // face dca, cea, eda.
12105       esym(abtetlist[(i + 1) % 3], oldfront);
12106       enextfnextself(oldfront);
12107       // Get the adjacent tet at the face (may be a dummytet).
12108       sym(oldfront, adjfront);
12109       bond(newfront, adjfront);
12110       if (checksubfaces) {
12111         tspivot(oldfront, checksh);
12112         if (checksh.sh != dummysh) {
12113           tsbond(newfront, checksh);
12114         }
12115       }
12116       if (flipque != (queue *) NULL) {
12117         enqueueflipface(newfront, flipque);
12118       }
12119       enext2self(dcea);
12120     }
12121     for (i = 0; i < 3; i++) {
12122       fnext(cdeb, newfront); // face cdb, deb, ecb.
12123       esym(abtetlist[(i + 1) % 3], oldfront);
12124       enext2fnextself(oldfront);
12125       // Get the adjacent tet at the face (may be a dummytet).
12126       sym(oldfront, adjfront);
12127       bond(newfront, adjfront);
12128       if (checksubfaces) {
12129         tspivot(oldfront, checksh);
12130         if (checksh.sh != dummysh) {
12131           tsbond(newfront, checksh);
12132         }
12133       }
12134       if (flipque != (queue *) NULL) {
12135         enqueueflipface(newfront, flipque);
12136       }
12137       enextself(cdeb);
12138     }
12139     // Do not delete the old tets.
12140     // for (i = 0; i < 3; i++) {
12141     //   tetrahedrondealloc(abtetlist[i].tet);
12142     // }
12143     return true;
12144   } // if (doflip)
12145 
12146   return false;
12147 }
12148 
12150 //                                                                           //
12151 // removeedgebytranNM()    Remove an edge by transforming n-to-m tets.       //
12152 //                                                                           //
12153 // This routine attempts to remove a given edge (ab) by transforming the set //
12154 // T of tets surrounding ab into another set T' of tets.  T and T' have the  //
12155 // same outer faces and ab is not an edge of T' anymore. Let |T|=n, and |T'| //
12156 // =m, it is actually a n-to-m flip for n > 3.  The relation between n and m //
12157 // depends on the method, ours is found below.                               //
12158 //                                                                           //
12159 // 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
12160 // to the screen, where a lies in front of and b lies behind it.  Let the    //
12161 // projections of the n apexes onto screen in clockwise order are: p_0, ...  //
12162 // p_n-1, respectively. The tets in the list are: [0]abp_0p_n-1,[1]abp_1p_0, //
12163 // ..., [n-1]abp_n-1p_n-2, respectively.                                     //
12164 //                                                                           //
12165 // The principle of the approach is: Recursively reduce the link of ab by    //
12166 // using flip23 until only three faces remain, hence a flip32 can be applied //
12167 // to remove ab. For a given face a.b.p_0, check a flip23 can be applied on  //
12168 // it, i.e, edge p_1.p_n-1 crosses it. NOTE*** We do the flip even p_1.p_n-1 //
12169 // intersects with a.b (they are coplanar). If so, a degenerate tet (a.b.p_1.//
12170 // p_n-1) is temporarily created, but it will be eventually removed by the   //
12171 // final flip32. This relaxation splits a flip44 into flip23 + flip32. *NOTE //
12172 // Now suppose a.b.p_0 gets flipped, p_0 is not on the link of ab anymore.   //
12173 // The link is then reduced (by 1). 2 of the 3 new tets, p_n-1.p_1.p_0.a and //
12174 // p_1.p_n-1.p_0.b, will be part of the new configuration.  The left new tet,//
12175 // a.b.p_1.p_n-1, goes into the new link of ab. A recurrence can be applied. //
12176 //                                                                           //
12177 // If 'e1' and 'e2' are not NULLs, they specify an wanted edge to appear in  //
12178 // the new tet configuration. In such case, only do flip23 if edge e1<->e2   //
12179 // can be recovered. It is used in removeedgebycombNM().                     //
12180 //                                                                           //
12181 // If ab gets removed. 'newtetlist' contains m new tets.  By using the above //
12182 // approach, the pairs (n, m) can be easily enumerated.  For example, (3, 2),//
12183 // (4, 4), (5, 6), (6, 8), (7, 10), (8, 12), (9, 14), (10, 16),  and so on.  //
12184 // It is easy to deduce, that m = (n - 2) * 2, when n >= 3.  The n tets in   //
12185 // 'abtetlist' are NOT deleted in this routine. The caller has the right to  //
12186 // either delete them or reverse this operation.                             //
12187 //                                                                           //
12189 
12190 bool tetgenmesh::removeedgebytranNM(REAL *key, int n, triface *abtetlist,
12191   triface *newtetlist, point e1, point e2, queue *flipque)
12192 {
12193   triface tmpabtetlist[9]; // Temporary max 9 tets configuration.
12194   triface newfront, oldfront, adjfront;
12195   face checksh;
12196   point pa, pb, p[10];
12197   REAL ori, cosmaxd, d1, d2;
12198   REAL tmpkey;
12199   REAL attrib, volume;
12200   bool doflip, copflag, success;
12201   int i, j, k;
12202 
12203   cosmaxd = 0.0;
12204   // Maximum 10 tets.
12205   assert(n <= 10);
12206   // Two points a and b are fixed.
12207   pa = org(abtetlist[0]);
12208   pb = dest(abtetlist[0]);
12209   // The points p_0, p_1, ..., p_n-1 are permuted in each new configuration.
12210   //   These permutations can be easily done in the following loop.
12211   // Loop through all the possible new tets configurations. Stop on finding
12212   //   a valid new tet configuration which also immproves the quality value.
12213   for (i = 0; i < n; i++) {
12214     // Get other n points for the current configuration.
12215     for (j = 0; j < n; j++) {
12216       p[j] = apex(abtetlist[(i + j) % n]);
12217     }
12218     // Is there a wanted edge?
12219     if ((e1 != (point) NULL) && (e2 != (point) NULL)) {
12220       // Yes. Skip this face if p[1]<->p[n-1] is not the edge.
12221       if (!(((p[1] == e1) && (p[n - 1] == e2)) ||
12222         ((p[1] == e2) && (p[n - 1] == e1)))) continue;
12223     }
12224     // Test if face a.b.p_0 can be flipped (by flip23), ie, to check if the
12225     //   edge p_n-1.p_1 crosses face a.b.p_0 properly.
12226     // Note. It is possible that face a.b.p_0 has type flip44, ie, a,b,p_1,
12227     //   and p_n-1 are coplanar. A trick is to split the flip44 into two
12228     //   steps: frist a flip23, then a flip32. The first step creates a
12229     //   degenerate tet (vol=0) which will be removed by the second flip.
12230     ori = orient3d(pa, pb, p[1], p[n - 1]);
12231     copflag = (ori == 0.0); // Are they coplanar?
12232     if (ori >= 0.0) {
12233       // Accept the coplanar case which supports flip44.
12234       ori = orient3d(pb, p[0], p[1], p[n - 1]);
12235       if (ori > 0.0) {
12236         ori = orient3d(p[0], pa, p[1], p[n - 1]);
12237       }
12238     }
12239     // Is face abc flipable?
12240     if (ori > 0.0) {
12241       // A valid (2-to-3) flip (or 4-to-4 flip) is found.
12242       copflag ? flip44s++ : flip23s++;
12243       doflip = true;
12244       if (key != (REAL *) NULL) {
12245         if (*key > -1.0) {
12246           // Test if the new tets reduce the maximal dihedral angle. Only 2
12247           //   tets, p_n-1.p_1.p_0.a and p_1.p_n-1.p_0.b, need to be tested
12248           //   The left one a.b.p_n-1.p_1 goes into the new link of ab.
12249           tetalldihedral(p[n - 1], p[1], p[0], pa, NULL, &d1, NULL);
12250           tetalldihedral(p[1], p[n - 1], p[0], pb, NULL, &d2, NULL);
12251           cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
12252           doflip = *key < cosmaxd; // Can the local quality be improved?
12253         }
12254       }
12255       if (doflip) {
12256         tmpkey = key != NULL ? *key : -1.0;
12257         // Create the two new tets.
12258         maketetrahedron(&(newtetlist[0]));
12259         setorg(newtetlist[0], p[n - 1]);
12260         setdest(newtetlist[0], p[1]);
12261         setapex(newtetlist[0], p[0]);
12262         setoppo(newtetlist[0], pa);
12263         maketetrahedron(&(newtetlist[1]));
12264         setorg(newtetlist[1], p[1]);
12265         setdest(newtetlist[1], p[n - 1]);
12266         setapex(newtetlist[1], p[0]);
12267         setoppo(newtetlist[1], pb);
12268         // Create the n - 1 temporary new tets (the new Star(ab)).
12269         maketetrahedron(&(tmpabtetlist[0]));
12270         setorg(tmpabtetlist[0], pa);
12271         setdest(tmpabtetlist[0], pb);
12272         setapex(tmpabtetlist[0], p[n - 1]);
12273         setoppo(tmpabtetlist[0], p[1]);
12274         for (j = 1; j < n - 1; j++) {
12275           maketetrahedron(&(tmpabtetlist[j]));
12276           setorg(tmpabtetlist[j], pa);
12277           setdest(tmpabtetlist[j], pb);
12278           setapex(tmpabtetlist[j], p[j]);
12279           setoppo(tmpabtetlist[j], p[j + 1]);
12280         }
12281         // Transfer the element attributes.
12282         for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12283           attrib = elemattribute(abtetlist[0].tet, j);
12284           setelemattribute(newtetlist[0].tet, j, attrib);
12285           setelemattribute(newtetlist[1].tet, j, attrib);
12286           for (k = 0; k < n - 1; k++) {
12287             setelemattribute(tmpabtetlist[k].tet, j, attrib);
12288           }
12289         }
12290         // Transfer the volume constraints.
12291         if (b->varvolume && !b->refine) {
12292           volume = volumebound(abtetlist[0].tet);
12293           setvolumebound(newtetlist[0].tet, volume);
12294           setvolumebound(newtetlist[1].tet, volume);
12295           for (k = 0; k < n - 1; k++) {
12296             setvolumebound(tmpabtetlist[k].tet, volume);
12297           }
12298         }
12299         // Glue the new tets at their internal faces: 2 + (n - 1).
12300         bond(newtetlist[0], newtetlist[1]); // p_n-1.p_1.p_0.
12301         fnext(newtetlist[0], newfront);
12302         enext2fnext(tmpabtetlist[0], adjfront);
12303         bond(newfront, adjfront); // p_n-1.p_1.a.
12304         fnext(newtetlist[1], newfront);
12305         enextfnext(tmpabtetlist[0], adjfront);
12306         bond(newfront, adjfront); // p_n-1.p_1.b.
12307         // Glue n - 1 internal faces around ab.
12308         for (j = 0; j < n - 1; j++) {
12309           fnext(tmpabtetlist[j], newfront);
12310           bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
12311         }
12312         // Substitute the old tets with the new tets by connecting the new
12313         //   tets to the adjacent tets in the mesh. There are n * 2 (outer)
12314         //   faces of the new tets need to be operated.
12315         // Note, after the substitution, the old tets still have pointers to
12316         //   their adjacent tets in the mesh.  These pointers can be re-used
12317         //   to inverse the substitution.
12318         for (j = 0; j < n; j++) {
12319           // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
12320           oldfront = abtetlist[(i + j) % n];
12321           esymself(oldfront);
12322           enextfnextself(oldfront);
12323           // Get an adjacent tet at face: [0]a.p_0.p_n-1 or [j]a.p_j.p_j-1.
12324           sym(oldfront, adjfront); // adjfront may be dummy.
12325           // Get the corresponding face from the new tets.
12326           if (j == 0) {
12327             enext2fnext(newtetlist[0], newfront); // a.p_0.n_n-1
12328           } else if (j == 1) {
12329             enextfnext(newtetlist[0], newfront); // a.p_1.p_0
12330           } else { // j >= 2.
12331             enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
12332           }
12333           bond(newfront, adjfront);
12334           if (checksubfaces) {
12335             tspivot(oldfront, checksh);
12336             if (checksh.sh != dummysh) {
12337               tsbond(newfront, checksh);
12338             }
12339           }
12340           if (flipque != (queue *) NULL) {
12341             // Only queue the faces of the two new tets.
12342             if (j < 2) enqueueflipface(newfront, flipque);
12343           }
12344         }
12345         for (j = 0; j < n; j++) {
12346           // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
12347           oldfront = abtetlist[(i + j) % n];
12348           esymself(oldfront);
12349           enext2fnextself(oldfront);
12350           // Get an adjacent tet at face: [0]b.p_0.p_n-1 or [j]b.p_j.p_j-1.
12351           sym(oldfront, adjfront); // adjfront may be dummy.
12352           // Get the corresponding face from the new tets.
12353           if (j == 0) {
12354             enextfnext(newtetlist[1], newfront); // b.p_0.n_n-1
12355           } else if (j == 1) {
12356             enext2fnext(newtetlist[1], newfront); // b.p_1.p_0
12357           } else { // j >= 2.
12358             enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
12359           }
12360           bond(newfront, adjfront);
12361           if (checksubfaces) {
12362             tspivot(oldfront, checksh);
12363             if (checksh.sh != dummysh) {
12364               tsbond(newfront, checksh);
12365             }
12366           }
12367           if (flipque != (queue *) NULL) {
12368             // Only queue the faces of the two new tets.
12369             if (j < 2) enqueueflipface(newfront, flipque);
12370           }
12371         }
12372         // Adjust the faces in the temporary new tets at ab for recursively
12373         //   processing on the n-1 tets.(See the description at beginning)
12374         for (j = 0; j < n - 1; j++) {
12375           fnextself(tmpabtetlist[j]);
12376         }
12377         if (n > 4) {
12378           success = removeedgebytranNM(&tmpkey, n-1, tmpabtetlist,
12379             &(newtetlist[2]), NULL, NULL, flipque);
12380         } else { // assert(n == 4);
12381           success = removeedgebyflip32(&tmpkey, tmpabtetlist,
12382             &(newtetlist[2]), flipque);
12383         }
12384         // No matter it was success or not, delete the temporary tets.
12385         for (j = 0; j < n - 1; j++) {
12386           tetrahedrondealloc(tmpabtetlist[j].tet);
12387         }
12388         if (success) {
12389           // The new configuration is good.
12390           // Do not delete the old tets.
12391           // for (j = 0; j < n; j++) {
12392           //   tetrahedrondealloc(abtetlist[j].tet);
12393           // }
12394           // Save the minimal improved quality value.
12395           if (key != (REAL *) NULL) {
12396             *key = (tmpkey < cosmaxd ? tmpkey : cosmaxd);
12397           }
12398           return true;
12399         } else {
12400           // The new configuration is bad, substitue back the old tets.
12401           for (j = 0; j < n; j++) {
12402             oldfront = abtetlist[(i + j) % n];
12403             esymself(oldfront);
12404             enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
12405             sym(oldfront, adjfront); // adjfront may be dummy.
12406             bond(oldfront, adjfront);
12407             if (checksubfaces) {
12408               tspivot(oldfront, checksh);
12409               if (checksh.sh != dummysh) {
12410                 tsbond(oldfront, checksh);
12411               }
12412             }
12413           }
12414           for (j = 0; j < n; j++) {
12415             oldfront = abtetlist[(i + j) % n];
12416             esymself(oldfront);
12417             enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12418             sym(oldfront, adjfront); // adjfront may be dummy
12419             bond(oldfront, adjfront);
12420             if (checksubfaces) {
12421               tspivot(oldfront, checksh);
12422               if (checksh.sh != dummysh) {
12423                 tsbond(oldfront, checksh);
12424               }
12425             }
12426           }
12427           // Delete the new tets.
12428           tetrahedrondealloc(newtetlist[0].tet);
12429           tetrahedrondealloc(newtetlist[1].tet);
12430           // If tmpkey has been modified, then the failure was not due to
12431           //   unflipable configuration, but the non-improvement.
12432           if (key && (tmpkey < *key)) {
12433             *key = tmpkey;
12434             return false;
12435           }
12436         } // if (success)
12437       } // if (doflip)
12438     } // if (ori > 0.0)
12439   } // for (i = 0; i < n; i++)
12440 
12441   return false;
12442 }
12443 
12445 //                                                                           //
12446 // removeedgebycombNM()    Remove an edge by combining two flipNMs.          //
12447 //                                                                           //
12448 // Given a set T of tets surrounding edge ab. The premise is that ab can not //
12449 // be removed by a flipNM. This routine attempts to remove ab by two flipNMs,//
12450 // i.e., first find and flip an edge af (or bf) by flipNM, then flip ab by   //
12451 // flipNM. If it succeeds, two sets T(ab) and T(af) of tets are replaced by  //
12452 // a new set T' and both ab and af are not edges in T' anymore.              //
12453 //                                                                           //
12454 // 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
12455 // to the screen, such that a lies in front of and b lies behind it. Let the //
12456 // projections of the n apexes on the screen in clockwise order are: p_0,...,//
12457 // p_n-1, respectively. So the list of tets are: [0]abp_0p_n-1, [1]abp_1p_0, //
12458 // ..., [n-1]abp_n-1p_n-2, respectively.                                     //
12459 //                                                                           //
12460 // The principle of the approach is: for a face a.b.p_0, check if edge b.p_0 //
12461 // is of type N32 (or N44). If it is, then try to do a flipNM on it. If the  //
12462 // flip is successful, then try to do another flipNM on a.b.  If one of the  //
12463 // two flipNMs fails, restore the old tets as they have never been flipped.  //
12464 // Then try the next face a.b.p_1.  The process can be looped for all faces  //
12465 // having ab. Stop if ab is removed or all faces have been visited. Note in  //
12466 // the above description only b.p_0 is considered, a.p_0 is done by swapping //
12467 // the position of a and b.                                                  //
12468 //                                                                           //
12469 // Similar operations have been described in [Joe,1995].  My approach checks //
12470 // more cases for finding flips than Joe's.  For instance, the cases (1)-(7) //
12471 // of Joe only consider abf for finding a flip (T23/T32).  My approach looks //
12472 // all faces at ab for finding flips. Moreover, the flipNM can flip an edge  //
12473 // whose star may have more than 3 tets while Joe's only works on 3-tet case.//
12474 //                                                                           //
12475 // If ab is removed, 'newtetlist' contains the new tets. Two sets 'abtetlist'//
12476 // (n tets) and 'bftetlist' (n1 tets) have been replaced.  The number of new //
12477 // tets can be calculated by follows: the 1st flip transforms n1 tets into   //
12478 // (n1 - 2) * 2 new tets, however,one of the new tets goes into the new link //
12479 // of ab, i.e., the reduced tet number in Star(ab) is n - 1;  the 2nd flip   //
12480 // transforms n - 1 tets into (n - 3) * 2 new tets. Hence the number of new  //
12481 // tets are: m = ((n1 - 2) * 2 - 1) + (n - 3) * 2.  The old tets are NOT del-//
12482 // eted. The caller has the right to delete them or reverse the operation.   //
12483 //                                                                           //
12485 
12486 bool tetgenmesh::removeedgebycombNM(REAL *key, int n, triface *abtetlist,
12487   int *n1, triface *bftetlist, triface *newtetlist, queue *flipque)
12488 {
12489   triface tmpabtetlist[11];
12490   triface newfront, oldfront, adjfront;
12491   face checksh;
12492   point pa, pb, p[10];
12493   REAL ori, tmpkey, tmpkey2;
12494   REAL attrib, volume;
12495   bool doflip, success;
12496   int twice, count;
12497   int i, j, k, m;
12498 
12499   // Maximal 10 tets in Star(ab).
12500   assert(n <= 10);
12501 
12502   // Do the following procedure twice, one for flipping edge b.p_0 and the
12503   //   other for p_0.a which is symmetric to the first.
12504   twice = 0;
12505   do {
12506     // Two points a and b are fixed.
12507     pa = org(abtetlist[0]);
12508     pb = dest(abtetlist[0]);
12509     // The points p_0, ..., p_n-1 are permuted in the following loop.
12510     for (i = 0; i < n; i++) {
12511       // Get the n points for the current configuration.
12512       for (j = 0; j < n; j++) {
12513         p[j] = apex(abtetlist[(i + j) % n]);
12514       }
12515       // Check if b.p_0 is of type N32 or N44.
12516       ori = orient3d(pb, p[0], p[1], p[n - 1]);
12517       if ((ori > 0) && (key != (REAL *) NULL)) {
12518         // b.p_0 is not N32. However, it is possible that the tet b.p_0.p_1.
12519         //   p_n-1 has worse quality value than the key. In such case, also
12520         //   try to flip b.p_0.
12521         tetalldihedral(pb, p[0], p[n - 1], p[1], NULL, &tmpkey, NULL);
12522         if (tmpkey < *key) ori = 0.0;
12523       }
12524       if (ori <= 0.0) {
12525         // b.p_0 is either N32 or N44. Try the 1st flipNM.
12526         bftetlist[0] = abtetlist[i];
12527         enextself(bftetlist[0]);// go to edge b.p_0.
12528         adjustedgering(bftetlist[0], CW); // edge p_0.b.
12529         assert(apex(bftetlist[0]) == pa);
12530         // Form Star(b.p_0).
12531         doflip = true;
12532         *n1 = 0;
12533         do {
12534           // Is the list full?
12535           if (*n1 == 10) break;
12536           if (checksubfaces) {
12537             // Stop if a subface appears.
12538             tspivot(bftetlist[*n1], checksh);
12539             if (checksh.sh != dummysh) {
12540               doflip = false; break;
12541             }
12542           }
12543           // Get the next tet at p_0.b.
12544           fnext(bftetlist[*n1], bftetlist[(*n1) + 1]);
12545           (*n1)++;
12546         } while (apex(bftetlist[*n1]) != pa);
12547         // 2 <= n1 <= 10.
12548         if (doflip) {
12549           success = false;
12550           tmpkey = -1.0;  // = acos(pi).
12551           if (key != (REAL *) NULL) tmpkey = *key;
12552           m = 0;
12553           if (*n1 == 3) {
12554             // Three tets case. Try flip32.
12555             success = removeedgebyflip32(&tmpkey,bftetlist,newtetlist,flipque);
12556             m = 2;
12557           } else if ((*n1 > 3) && (*n1 < 7)) {
12558             // Four or more tets case. Try flipNM.
12559             success = removeedgebytranNM(&tmpkey, *n1, bftetlist, newtetlist,
12560                                          p[1], p[n - 1], flipque);
12561             // If success, the number of new tets.
12562             m = ((*n1) - 2) * 2;
12563           } else {
12564             if (b->verbose > 1) {
12565               printf("  !! Unhandled case: n1 = %d.\n", *n1);
12566             }
12567           }
12568           if (success) {
12569             // b.p_0 is flipped. The link of ab is reduced (by 1), i.e., p_0
12570             //   is not on the link of ab. Two old tets a.b.p_0.p_n-1 and
12571             //   a.b.p_1.p_0 have been removed from the Star(ab) and one new
12572             //   tet t = a.b.p_1.p_n-1 belongs to Star(ab).
12573             // Find t in the 'newtetlist' and remove it from the list.
12574             setpointmark(pa, -pointmark(pa) - 1);
12575             setpointmark(pb, -pointmark(pb) - 1);
12576             assert(m > 0);
12577             for (j = 0; j < m; j++) {
12578               tmpabtetlist[0] = newtetlist[j];
12579               // Does it has ab?
12580               count = 0;
12581               for (k = 0; k < 4; k++) {
12582                 if (pointmark((point)(tmpabtetlist[0].tet[4+k])) < 0) count++;
12583               }
12584               if (count == 2) {
12585                 // It is. Adjust t to be the edge ab.
12586                 for (tmpabtetlist[0].loc = 0; tmpabtetlist[0].loc < 4;
12587                      tmpabtetlist[0].loc++) {
12588                   if ((oppo(tmpabtetlist[0]) != pa) &&
12589                       (oppo(tmpabtetlist[0]) != pb)) break;
12590                 }
12591                 // The face of t must contain ab.
12592                 assert(tmpabtetlist[0].loc < 4);
12593                 findedge(&(tmpabtetlist[0]), pa, pb);
12594                 break;
12595               }
12596             }
12597             assert(j < m); // The tet must exist.
12598             // Remove t from list. Fill t's position by the last tet.
12599             newtetlist[j] = newtetlist[m - 1];
12600             setpointmark(pa, -(pointmark(pa) + 1));
12601             setpointmark(pb, -(pointmark(pb) + 1));
12602             // Create the temporary Star(ab) for the next flipNM.
12603             adjustedgering(tmpabtetlist[0], CCW);
12604             if (org(tmpabtetlist[0]) != pa) {
12605               fnextself(tmpabtetlist[0]);
12606               esymself(tmpabtetlist[0]);
12607             }
12608 #ifdef SELF_CHECK
12609             // Make sure current edge is a->b.
12610             assert(org(tmpabtetlist[0]) == pa);
12611             assert(dest(tmpabtetlist[0]) == pb);
12612             assert(apex(tmpabtetlist[0]) == p[n - 1]);
12613             assert(oppo(tmpabtetlist[0]) == p[1]);
12614 #endif // SELF_CHECK
12615             // There are n - 2 left temporary tets.
12616             for (j = 1; j < n - 1; j++) {
12617               maketetrahedron(&(tmpabtetlist[j]));
12618               setorg(tmpabtetlist[j], pa);
12619               setdest(tmpabtetlist[j], pb);
12620               setapex(tmpabtetlist[j], p[j]);
12621               setoppo(tmpabtetlist[j], p[j + 1]);
12622             }
12623             // Transfer the element attributes.
12624             for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12625               attrib = elemattribute(abtetlist[0].tet, j);
12626               for (k = 0; k < n - 1; k++) {
12627                 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12628               }
12629             }
12630             // Transfer the volume constraints.
12631             if (b->varvolume && !b->refine) {
12632               volume = volumebound(abtetlist[0].tet);
12633               for (k = 0; k < n - 1; k++) {
12634                 setvolumebound(tmpabtetlist[k].tet, volume);
12635               }
12636             }
12637             // Glue n - 1 internal faces of Star(ab).
12638             for (j = 0; j < n - 1; j++) {
12639               fnext(tmpabtetlist[j], newfront);
12640               bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
12641             }
12642             // Substitute the old tets with the new tets by connecting the
12643             //   new tets to the adjacent tets in the mesh. There are (n-2)
12644             //   * 2 (outer) faces of the new tets need to be operated.
12645             // Note that the old tets still have the pointers to their
12646             //   adjacent tets in the mesh.  These pointers can be re-used
12647             //   to inverse the substitution.
12648             for (j = 2; j < n; j++) {
12649               // Get an old tet: [j]a.b.p_j.p_j-1, (j > 1).
12650               oldfront = abtetlist[(i + j) % n];
12651               esymself(oldfront);
12652               enextfnextself(oldfront);
12653               // Get an adjacent tet at face: [j]a.p_j.p_j-1.
12654               sym(oldfront, adjfront); // adjfront may be dummy.
12655               // Get the corresponding face from the new tets.
12656               // j >= 2.
12657               enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
12658               bond(newfront, adjfront);
12659               if (checksubfaces) {
12660                 tspivot(oldfront, checksh);
12661                 if (checksh.sh != dummysh) {
12662                   tsbond(newfront, checksh);
12663                 }
12664               }
12665             }
12666             for (j = 2; j < n; j++) {
12667               // Get an old tet: [j]a.b.p_j.p_j-1, (j > 2).
12668               oldfront = abtetlist[(i + j) % n];
12669               esymself(oldfront);
12670               enext2fnextself(oldfront);
12671               // Get an adjacent tet at face: [j]b.p_j.p_j-1.
12672               sym(oldfront, adjfront); // adjfront may be dummy.
12673               // Get the corresponding face from the new tets.
12674               // j >= 2.
12675               enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
12676               bond(newfront, adjfront);
12677               if (checksubfaces) {
12678                 tspivot(oldfront, checksh);
12679                 if (checksh.sh != dummysh) {
12680                   tsbond(newfront, checksh);
12681                 }
12682               }
12683             }
12684             // Adjust the faces in the temporary new tets at ab for
12685             //   recursively processing on the n-1 tets.
12686             for (j = 0; j < n - 1; j++) {
12687               fnextself(tmpabtetlist[j]);
12688             }
12689             tmpkey2 = -1;
12690             if (key) tmpkey2 = *key;
12691             if ((n - 1) == 3) {
12692               success = removeedgebyflip32(&tmpkey2, tmpabtetlist,
12693                 &(newtetlist[m - 1]), flipque);
12694             } else { // assert((n - 1) >= 4);
12695               success = removeedgebytranNM(&tmpkey2, n - 1, tmpabtetlist,
12696                 &(newtetlist[m - 1]), NULL, NULL, flipque);
12697             }
12698             // No matter it was success or not, delete the temporary tets.
12699             for (j = 0; j < n - 1; j++) {
12700               tetrahedrondealloc(tmpabtetlist[j].tet);
12701             }
12702             if (success) {
12703               // The new configuration is good.
12704               // Do not delete the old tets.
12705               // for (j = 0; j < n; j++) {
12706               //   tetrahedrondealloc(abtetlist[j].tet);
12707               // }
12708               // Return the bigger dihedral in the two sets of new tets.
12709               if (key != (REAL *) NULL) {
12710                 *key = tmpkey2 < tmpkey ? tmpkey2 : tmpkey;
12711               }
12712               return true;
12713             } else {
12714               // The new configuration is bad, substitue back the old tets.
12715               for (j = 0; j < n; j++) {
12716                 oldfront = abtetlist[(i + j) % n];
12717                 esymself(oldfront);
12718                 enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
12719                 sym(oldfront, adjfront); // adjfront may be dummy.
12720                 bond(oldfront, adjfront);
12721                 if (checksubfaces) {
12722                   tspivot(oldfront, checksh);
12723                   if (checksh.sh != dummysh) {
12724                     tsbond(oldfront, checksh);
12725                   }
12726                 }
12727               }
12728               for (j = 0; j < n; j++) {
12729                 oldfront = abtetlist[(i + j) % n];
12730                 esymself(oldfront);
12731                 enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12732                 sym(oldfront, adjfront); // adjfront may be dummy
12733                 bond(oldfront, adjfront);
12734                 if (checksubfaces) {
12735                   tspivot(oldfront, checksh);
12736                   if (checksh.sh != dummysh) {
12737                     tsbond(oldfront, checksh);
12738                   }
12739                 }
12740               }
12741               // Substitute back the old tets of the first flip.
12742               for (j = 0; j < *n1; j++) {
12743                 oldfront = bftetlist[j];
12744                 esymself(oldfront);
12745                 enextfnextself(oldfront);
12746                 sym(oldfront, adjfront); // adjfront may be dummy.
12747                 bond(oldfront, adjfront);
12748                 if (checksubfaces) {
12749                   tspivot(oldfront, checksh);
12750                   if (checksh.sh != dummysh) {
12751                     tsbond(oldfront, checksh);
12752                   }
12753                 }
12754               }
12755               for (j = 0; j < *n1; j++) {
12756                 oldfront = bftetlist[j];
12757                 esymself(oldfront);
12758                 enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12759                 sym(oldfront, adjfront); // adjfront may be dummy
12760                 bond(oldfront, adjfront);
12761                 if (checksubfaces) {
12762                   tspivot(oldfront, checksh);
12763                   if (checksh.sh != dummysh) {
12764                     tsbond(oldfront, checksh);
12765                   }
12766                 }
12767               }
12768               // Delete the new tets of the first flip. Note that one new
12769               //   tet has already been removed from the list.
12770               for (j = 0; j < m - 1; j++) {
12771                 tetrahedrondealloc(newtetlist[j].tet);
12772               }
12773             } // if (success)
12774           } // if (success)
12775         } // if (doflip)
12776       } // if (ori <= 0.0)
12777     } // for (i = 0; i < n; i++)
12778     // Inverse a and b and the tets configuration.
12779     for (i = 0; i < n; i++) newtetlist[i] = abtetlist[i];
12780     for (i = 0; i < n; i++) {
12781       oldfront = newtetlist[n - i - 1];
12782       esymself(oldfront);
12783       fnextself(oldfront);
12784       abtetlist[i] = oldfront;
12785     }
12786     twice++;
12787   } while (twice < 2);
12788 
12789   return false;
12790 }
12791 
12793 //                                                                           //
12794 // splittetrahedron()    Insert a point into a tetrahedron, split it into    //
12795 //                       four tetrahedra.                                    //
12796 //                                                                           //
12797 // The tetrahedron is given by 'splittet'.  Let it is abcd.  The inserting   //
12798 // point 'newpoint' v should lie strictly inside abcd.                       //
12799 //                                                                           //
12800 // Splitting a tetrahedron is to shrink abcd to abcv,  and create three new  //
12801 // tetrahedra badv, cbdv, and acdv.                                          //
12802 //                                                                           //
12803 // On completion, 'splittet' returns abcv.  If 'flipqueue' is not NULL, it   //
12804 // contains all possibly non-locally Delaunay faces.                         //
12805 //                                                                           //
12807 
12808 void tetgenmesh::splittetrahedron(point newpoint, triface* splittet,
12809   queue* flipqueue)
12810 {
12811   triface oldabd, oldbcd, oldcad;                      // Old configuration.
12812   triface abdcasing, bcdcasing, cadcasing;
12813   face abdsh, bcdsh, cadsh;
12814   triface abcv, badv, cbdv, acdv;                      // New configuration.
12815   triface worktet;
12816   face abseg, bcseg, caseg;
12817   face adseg, bdseg, cdseg;
12818   point pa, pb, pc, pd;
12819   REAL attrib, volume;
12820   int i;
12821 
12822   abcv = *splittet;
12823   abcv.ver = 0;
12824   // Set the changed vertices and new tetrahedron.
12825   pa = org(abcv);
12826   pb = dest(abcv);
12827   pc = apex(abcv);
12828   pd = oppo(abcv);
12829 
12830   if (b->verbose > 1) {
12831     printf("  Inserting point %d in tetrahedron (%d, %d, %d, %d).\n",
12832            pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc),
12833            pointmark(pd));
12834   }
12835 
12836   fnext(abcv, oldabd);
12837   enextfnext(abcv, oldbcd);
12838   enext2fnext(abcv, oldcad);
12839   sym(oldabd, abdcasing);
12840   sym(oldbcd, bcdcasing);
12841   sym(oldcad, cadcasing);
12842   maketetrahedron(&badv);
12843   maketetrahedron(&cbdv);
12844   maketetrahedron(&acdv);
12845 
12846   // Set 'badv' vertices.
12847   setorg (badv, pb);
12848   setdest(badv, pa);
12849   setapex(badv, pd);
12850   setoppo(badv, newpoint);
12851   // Set 'cbdv' vertices.
12852   setorg (cbdv, pc);
12853   setdest(cbdv, pb);
12854   setapex(cbdv, pd);
12855   setoppo(cbdv, newpoint);
12856   // Set 'acdv' vertices.
12857   setorg (acdv, pa);
12858   setdest(acdv, pc);
12859   setapex(acdv, pd);
12860   setoppo(acdv, newpoint);
12861   // Set 'abcv' vertices
12862   setoppo(abcv, newpoint);
12863 
12864   // Set the element attributes of the new tetrahedra.
12865   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12866     attrib = elemattribute(abcv.tet, i);
12867     setelemattribute(badv.tet, i, attrib);
12868     setelemattribute(cbdv.tet, i, attrib);
12869     setelemattribute(acdv.tet, i, attrib);
12870   }
12871   // Set the volume constraint of the new tetrahedra.
12872   if (b->varvolume) {
12873     volume = volumebound(abcv.tet);
12874     setvolumebound(badv.tet, volume);
12875     setvolumebound(cbdv.tet, volume);
12876     setvolumebound(acdv.tet, volume);
12877   }
12878 
12879   // Bond the new triangles to the surrounding tetrahedron.
12880   bond(badv, abdcasing);
12881   bond(cbdv, bcdcasing);
12882   bond(acdv, cadcasing);
12883   // There may exist subfaces need to be bonded to the new tetrahedra.
12884   if (checksubfaces) {
12885     tspivot(oldabd, abdsh);
12886     if (abdsh.sh != dummysh) {
12887       tsdissolve(oldabd);
12888       tsbond(badv, abdsh);
12889     }
12890     tspivot(oldbcd, bcdsh);
12891     if (bcdsh.sh != dummysh) {
12892       tsdissolve(oldbcd);
12893       tsbond(cbdv, bcdsh);
12894     }
12895     tspivot(oldcad, cadsh);
12896     if (cadsh.sh != dummysh) {
12897       tsdissolve(oldcad);
12898       tsbond(acdv, cadsh);
12899     }
12900   } else if (checksubsegs) {
12901     tsspivot1(abcv, abseg);
12902     if (abseg.sh != dummysh) {
12903       tssbond1(badv, abseg);
12904     }
12905     enext(abcv, worktet);
12906     tsspivot1(worktet, bcseg);
12907     if (bcseg.sh != dummysh) {
12908       tssbond1(cbdv, bcseg);
12909     }
12910     enext2(abcv, worktet);
12911     tsspivot1(worktet, caseg);
12912     if (caseg.sh != dummysh) {
12913       tssbond1(acdv, caseg);
12914     }
12915     fnext(abcv, worktet);
12916     enext2self(worktet);
12917     tsspivot1(worktet, adseg);
12918     if (adseg.sh != dummysh) {
12919       tssdissolve1(worktet);
12920       enext(badv, worktet);
12921       tssbond1(worktet, adseg);
12922       enext2(acdv, worktet);
12923       tssbond1(worktet, adseg);
12924     }
12925     enextfnext(abcv, worktet);
12926     enext2self(worktet);
12927     tsspivot1(worktet, bdseg);
12928     if (bdseg.sh != dummysh) {
12929       tssdissolve1(worktet);
12930       enext(cbdv, worktet);
12931       tssbond1(worktet, bdseg);
12932       enext2(badv, worktet);
12933       tssbond1(worktet, bdseg);
12934     }
12935     enext2fnext(abcv, worktet);
12936     enext2self(worktet);
12937     tsspivot1(worktet, cdseg);
12938     if (cdseg.sh != dummysh) {
12939       tssdissolve1(worktet);
12940       enext(acdv, worktet);
12941       tssbond1(worktet, cdseg);
12942       enext2(cbdv, worktet);
12943       tssbond1(worktet, cdseg);
12944     }
12945   }
12946   badv.loc = 3;
12947   cbdv.loc = 2;
12948   bond(badv, cbdv);
12949   cbdv.loc = 3;
12950   acdv.loc = 2;
12951   bond(cbdv, acdv);
12952   acdv.loc = 3;
12953   badv.loc = 2;
12954   bond(acdv, badv);
12955   badv.loc = 1;
12956   bond(badv, oldabd);
12957   cbdv.loc = 1;
12958   bond(cbdv, oldbcd);
12959   acdv.loc = 1;
12960   bond(acdv, oldcad);
12961 
12962   badv.loc = 0;
12963   cbdv.loc = 0;
12964   acdv.loc = 0;
12965   if (b->verbose > 3) {
12966     printf("    Updating abcv ");
12967     printtet(&abcv);
12968     printf("    Creating badv ");
12969     printtet(&badv);
12970     printf("    Creating cbdv ");
12971     printtet(&cbdv);
12972     printf("    Creating acdv ");
12973     printtet(&acdv);
12974   }
12975 
12976   if (flipqueue != (queue *) NULL) {
12977     enqueueflipface(abcv, flipqueue);
12978     enqueueflipface(badv, flipqueue);
12979     enqueueflipface(cbdv, flipqueue);
12980     enqueueflipface(acdv, flipqueue);
12981   }
12982 
12983   // Save a handle for quick point location.
12984   recenttet = abcv;
12985   // Set the return handle be abcv.
12986   *splittet = abcv;
12987 }
12988 
12990 //                                                                           //
12991 // unsplittetrahedron()    Reverse the operation of inserting a point into a //
12992 //                         tetrahedron, so as to remove the newly inserted   //
12993 //                         point from the mesh.                              //
12994 //                                                                           //
12995 // Assume the origional tetrahedron is abcd, it was split by v into four     //
12996 // tetrahedra abcv, badv, cbdv, and acdv. 'splittet' represents face abc of  //
12997 // abcv (i.e., its opposite is v).                                           //
12998 //                                                                           //
12999 // Point v is removed by expanding abcv to abcd, deleting three tetrahedra   //
13000 // badv, cbdv and acdv.  On return, point v is not deleted in this routine.  //
13001 //                                                                           //
13003 
13004 void tetgenmesh::unsplittetrahedron(triface* splittet)
13005 {
13006   triface abcv, badv, cbdv, acdv;
13007   triface oldabv, oldbcv, oldcav;
13008   triface badcasing, cbdcasing, acdcasing;
13009   face badsh, cbdsh, acdsh;
13010 
13011   abcv = *splittet;
13012   adjustedgering(abcv, CCW);  // for sure.
13013   fnext(abcv, oldabv);
13014   fnext(oldabv, badv);
13015   esymself(badv);
13016   enextfnext(abcv, oldbcv);
13017   fnext(oldbcv, cbdv);
13018   esymself(cbdv);
13019   enext2fnext(abcv, oldcav);
13020   fnext(oldcav, acdv);
13021   esymself(acdv);
13022 
13023   if (b->verbose > 1) {
13024     printf("  Removing point %d in tetrahedron (%d, %d, %d, %d).\n",
13025            pointmark(oppo(abcv)), pointmark(org(abcv)), pointmark(dest(abcv)),
13026            pointmark(apex(abcv)), pointmark(apex(badv)));
13027   }
13028 
13029   sym(badv, badcasing);
13030   tspivot(badv, badsh);
13031   sym(cbdv, cbdcasing);
13032   tspivot(cbdv, cbdsh);
13033   sym(acdv, acdcasing);
13034   tspivot(acdv, acdsh);
13035 
13036   // Expanding abcv to abcd.
13037   setoppo(abcv, apex(badv));
13038   bond(oldabv, badcasing);
13039   if (badsh.sh != dummysh) {
13040     tsbond(oldabv, badsh);
13041   }
13042   bond(oldbcv, cbdcasing);
13043   if (cbdsh.sh != dummysh) {
13044     tsbond(oldbcv, cbdsh);
13045   }
13046   bond(oldcav, acdcasing);
13047   if (acdsh.sh != dummysh) {
13048     tsbond(oldcav, acdsh);
13049   }
13050 
13051   // Delete the three split-out tetrahedra.
13052   tetrahedrondealloc(badv.tet);
13053   tetrahedrondealloc(cbdv.tet);
13054   tetrahedrondealloc(acdv.tet);
13055 }
13056 
13058 //                                                                           //
13059 // splittetface()    Insert a point on a face of a mesh.                     //
13060 //                                                                           //
13061 // 'splittet' is the splitting face.  Let it is abcd, where abc is the face  //
13062 // will be split. If abc is not a hull face, abce is the tetrahedron at the  //
13063 // opposite of d.                                                            //
13064 //                                                                           //
13065 // To split face abc by a point v is to shrink the tetrahedra abcd to abvd,  //
13066 // create two new tetrahedra bcvd, cavd.  If abc is not a hull face, shrink  //
13067 // the tetrahedra bace to bave, create two new tetrahedra cbve, acve.        //
13068 //                                                                           //
13069 // If abc is a subface, it is split into three subfaces simultaneously by    //
13070 // calling routine splitsubface(), hence, abv, bcv, cav.  The edge rings of  //
13071 // the split subfaces have the same orientation as abc's.                    //
13072 //                                                                           //
13073 // On completion, 'splittet' returns abvd.  If 'flipqueue' is not NULL, it   //
13074 // contains all possibly non-locally Delaunay faces.                         //
13075 //                                                                           //
13077 
13078 void tetgenmesh::splittetface(point newpoint, triface* splittet,
13079   queue* flipqueue)
13080 {
13081   triface abcd, bace;                                  // Old configuration.
13082   triface oldbcd, oldcad, oldace, oldcbe;
13083   triface bcdcasing, cadcasing, acecasing, cbecasing;
13084   face abcsh, bcdsh, cadsh, acesh, cbesh;
13085   triface abvd, bcvd, cavd, bave, cbve, acve;          // New configuration.
13086   triface worktet;
13087   face bcseg, caseg;
13088   face adseg, bdseg, cdseg;
13089   face aeseg, beseg, ceseg;
13090   point pa, pb, pc, pd, pe;
13091   REAL attrib, volume;
13092   bool mirrorflag;
13093   int i;
13094 
13095   abcd = *splittet;
13096   // abcd.ver = 0; // Adjust to be CCW edge ring.
13097   adjustedgering(abcd, CCW);
13098   pa = org(abcd);
13099   pb = dest(abcd);
13100   pc = apex(abcd);
13101   pd = oppo(abcd);
13102   pe = (point) NULL; // avoid a compile warning.
13103   // Is there a second tetrahderon?
13104   mirrorflag = issymexist(&abcd);
13105   if (mirrorflag) {
13106     // This is an interior face.
13107     sym(abcd, bace);
13108     findedge(&bace, dest(abcd), org(abcd));
13109     pe = oppo(bace);
13110   }
13111   if (checksubfaces) {
13112     // Is there a subface need to be split together?
13113     tspivot(abcd, abcsh);
13114     if (abcsh.sh != dummysh) {
13115       // Exists! Keep the edge ab of both handles be the same.
13116       findedge(&abcsh, org(abcd), dest(abcd));
13117     }
13118   }
13119 
13120   if (b->verbose > 1) {
13121     printf("  Inserting point %d on face (%d, %d, %d).\n", pointmark(newpoint),
13122            pointmark(pa), pointmark(pb), pointmark(pc));
13123   }
13124 
13125   // Save the old configuration at faces bcd and cad.
13126   enextfnext(abcd, oldbcd);
13127   enext2fnext(abcd, oldcad);
13128   sym(oldbcd, bcdcasing);
13129   sym(oldcad, cadcasing);
13130   // Create two new tetrahedra.
13131   maketetrahedron(&bcvd);
13132   maketetrahedron(&cavd);
13133   if (mirrorflag) {
13134     // Save the old configuration at faces bce and cae.
13135     enextfnext(bace, oldace);
13136     enext2fnext(bace, oldcbe);
13137     sym(oldace, acecasing);
13138     sym(oldcbe, cbecasing);
13139     // Create two new tetrahedra.
13140     maketetrahedron(&acve);
13141     maketetrahedron(&cbve);
13142   } else {
13143     // Splitting a boundary face increases the number of boundary faces.
13144     hullsize += 2;
13145   }
13146 
13147   // Set vertices to the changed tetrahedron and new tetrahedra.
13148   abvd = abcd;  // Update 'abcd' to 'abvd'.
13149   setapex(abvd, newpoint);
13150   setorg (bcvd, pb);  // Set 'bcvd'.
13151   setdest(bcvd, pc);
13152   setapex(bcvd, newpoint);
13153   setoppo(bcvd, pd);
13154   setorg (cavd, pc);  // Set 'cavd'.
13155   setdest(cavd, pa);
13156   setapex(cavd, newpoint);
13157   setoppo(cavd, pd);
13158   // Set the element attributes of the new tetrahedra.
13159   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13160     attrib = elemattribute(abvd.tet, i);
13161     setelemattribute(bcvd.tet, i, attrib);
13162     setelemattribute(cavd.tet, i, attrib);
13163   }
13164   if (b->varvolume) {
13165     // Set the area constraint of the new tetrahedra.
13166     volume = volumebound(abvd.tet);
13167     setvolumebound(bcvd.tet, volume);
13168     setvolumebound(cavd.tet, volume);
13169   }
13170   if (mirrorflag) {
13171     bave = bace;  // Update 'bace' to 'bave'.
13172     setapex(bave, newpoint);
13173     setorg (acve, pa);  // Set 'acve'.
13174     setdest(acve, pc);
13175     setapex(acve, newpoint);
13176     setoppo(acve, pe);
13177     setorg (cbve, pc);  // Set 'cbve'.
13178     setdest(cbve, pb);
13179     setapex(cbve, newpoint);
13180     setoppo(cbve, pe);
13181     // Set the element attributes of the new tetrahedra.
13182     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13183       attrib = elemattribute(bave.tet, i);
13184       setelemattribute(acve.tet, i, attrib);
13185       setelemattribute(cbve.tet, i, attrib);
13186     }
13187     if (b->varvolume) {
13188       // Set the area constraint of the new tetrahedra.
13189       volume = volumebound(bave.tet);
13190       setvolumebound(acve.tet, volume);
13191       setvolumebound(cbve.tet, volume);
13192     }
13193   }
13194 
13195   // Bond the new tetrahedra to the surrounding tetrahedra.
13196   bcvd.loc = 1;
13197   bond(bcvd, bcdcasing);
13198   cavd.loc = 1;
13199   bond(cavd, cadcasing);
13200   bcvd.loc = 3;
13201   bond(bcvd, oldbcd);
13202   cavd.loc = 2;
13203   bond(cavd, oldcad);
13204   bcvd.loc = 2;
13205   cavd.loc = 3;
13206   bond(bcvd, cavd);
13207   if (mirrorflag) {
13208     acve.loc = 1;
13209     bond(acve, acecasing);
13210     cbve.loc = 1;
13211     bond(cbve, cbecasing);
13212     acve.loc = 3;
13213     bond(acve, oldace);
13214     cbve.loc = 2;
13215     bond(cbve, oldcbe);
13216     acve.loc = 2;
13217     cbve.loc = 3;
13218     bond(acve, cbve);
13219     // Bond two new coplanar facets.
13220     bcvd.loc = 0;
13221     cbve.loc = 0;
13222     bond(bcvd, cbve);
13223     cavd.loc = 0;
13224     acve.loc = 0;
13225     bond(cavd, acve);
13226   }
13227 
13228   // There may exist subface needed to be bonded to the new tetrahedra.
13229   if (checksubfaces) {
13230     tspivot(oldbcd, bcdsh);
13231     if (bcdsh.sh != dummysh) {
13232       tsdissolve(oldbcd);
13233       bcvd.loc = 1;
13234       tsbond(bcvd, bcdsh);
13235     }
13236     tspivot(oldcad, cadsh);
13237     if (cadsh.sh != dummysh) {
13238       tsdissolve(oldcad);
13239       cavd.loc = 1;
13240       tsbond(cavd, cadsh);
13241     }
13242     if (mirrorflag) {
13243       tspivot(oldace, acesh);
13244       if (acesh.sh != dummysh) {
13245         tsdissolve(oldace);
13246         acve.loc = 1;
13247         tsbond(acve, acesh);
13248       }
13249       tspivot(oldcbe, cbesh);
13250       if (cbesh.sh != dummysh) {
13251         tsdissolve(oldcbe);
13252         cbve.loc = 1;
13253         tsbond(cbve, cbesh);
13254       }
13255     }
13256     // Is there a subface needs to be split together?
13257     if (abcsh.sh != dummysh) {
13258       // Split this subface 'abc' into three i.e, abv, bcv, cav.
13259       splitsubface(newpoint, &abcsh, (queue *) NULL);
13260     }
13261   } else if (checksubsegs) {
13262     // abvd.loc = abvd.ver = 0;
13263     bcvd.loc = bcvd.ver = 0;
13264     cavd.loc = cavd.ver = 0;
13265     if (mirrorflag) {
13266       // bave.loc = bave.ver = 0;
13267       cbve.loc = cbve.ver = 0;
13268       acve.loc = acve.ver = 0;
13269     }
13270     enext(abvd, worktet);
13271     tsspivot1(worktet, bcseg);
13272     if (bcseg.sh != dummysh) {
13273       tssdissolve1(worktet);
13274       tssbond1(bcvd, bcseg);
13275       if (mirrorflag) {
13276         enext2(bave, worktet);
13277         tssdissolve1(worktet);
13278         tssbond1(cbve, bcseg);
13279       }
13280     }
13281     enext2(abvd, worktet);
13282     tsspivot1(worktet, caseg);
13283     if (caseg.sh != dummysh) {
13284       tssdissolve1(worktet);
13285       tssbond1(cavd, caseg);
13286       if (mirrorflag) {
13287         enext(bave, worktet);
13288         tssdissolve1(worktet);
13289         tssbond1(acve, caseg);
13290       }
13291     }
13292     fnext(abvd, worktet);
13293     enext2self(worktet);
13294     tsspivot1(worktet, adseg);
13295     if (adseg.sh != dummysh) {
13296       fnext(cavd, worktet);
13297       enextself(worktet);
13298       tssbond1(worktet, adseg);
13299     }
13300     fnext(abvd, worktet);
13301     enextself(worktet);
13302     tsspivot1(worktet, bdseg);
13303     if (bdseg.sh != dummysh) {
13304       fnext(bcvd, worktet);
13305       enext2self(worktet);
13306       tssbond1(worktet, bdseg);
13307     }
13308     enextfnext(abvd, worktet);
13309     enextself(worktet);
13310     tsspivot1(worktet, cdseg);
13311     if (cdseg.sh != dummysh) {
13312       tssdissolve1(worktet);
13313       fnext(bcvd, worktet);
13314       enextself(worktet);
13315       tssbond1(worktet, cdseg);
13316       fnext(cavd, worktet);
13317       enext2self(worktet);
13318       tssbond1(worktet, cdseg);
13319     }
13320     if (mirrorflag) {
13321       fnext(bave, worktet);
13322       enextself(worktet);
13323       tsspivot1(worktet, aeseg);
13324       if (aeseg.sh != dummysh) {
13325         fnext(acve, worktet);
13326         enext2self(worktet);
13327         tssbond1(worktet, aeseg);
13328       }
13329       fnext(bave, worktet);
13330       enext2self(worktet);
13331       tsspivot1(worktet, beseg);
13332       if (beseg.sh != dummysh) {
13333         fnext(cbve, worktet);
13334         enextself(worktet);
13335         tssbond1(worktet, beseg);
13336       }
13337       enextfnext(bave, worktet);
13338       enextself(worktet);
13339       tsspivot1(worktet, ceseg);
13340       if (ceseg.sh != dummysh) {
13341         tssdissolve1(worktet);
13342         fnext(cbve, worktet);
13343         enext2self(worktet);
13344         tssbond1(worktet, ceseg);
13345         fnext(acve, worktet);
13346         enextself(worktet);
13347         tssbond1(worktet, ceseg);
13348       }
13349     }
13350   }
13351 
13352   // Save a handle for quick point location.
13353   recenttet = abvd;
13354   // Set the return handle be abvd.
13355   *splittet = abvd;
13356 
13357   bcvd.loc = 0;
13358   cavd.loc = 0;
13359   if (mirrorflag) {
13360     cbve.loc = 0;
13361     acve.loc = 0;
13362   }
13363   if (b->verbose > 3) {
13364     printf("    Updating abvd ");
13365     printtet(&abvd);
13366     printf("    Creating bcvd ");
13367     printtet(&bcvd);
13368     printf("    Creating cavd ");
13369     printtet(&cavd);
13370     if (mirrorflag) {
13371       printf("    Updating bave ");
13372       printtet(&bave);
13373       printf("    Creating cbve ");
13374       printtet(&cbve);
13375       printf("    Creating acve ");
13376       printtet(&acve);
13377     }
13378   }
13379 
13380   if (flipqueue != (queue *) NULL) {
13381     fnextself(abvd);
13382     enqueueflipface(abvd, flipqueue);
13383     fnextself(bcvd);
13384     enqueueflipface(bcvd, flipqueue);
13385     fnextself(cavd);
13386     enqueueflipface(cavd, flipqueue);
13387     if (mirrorflag) {
13388       fnextself(bave);
13389       enqueueflipface(bave, flipqueue);
13390       fnextself(cbve);
13391       enqueueflipface(cbve, flipqueue);
13392       fnextself(acve);
13393       enqueueflipface(acve, flipqueue);
13394     }
13395   }
13396 }
13397 
13399 //                                                                           //
13400 // unsplittetface()    Reverse the operation of inserting a point on a face, //
13401 //                     so as to remove the newly inserted point.             //
13402 //                                                                           //
13403 // Assume the original face is abc, the tetrahedron containing abc is abcd.  //
13404 // If abc is not a hull face, bace is the tetrahedron at the opposite of d.  //
13405 // After face abc was split by a point v, tetrahedron abcd had been split    //
13406 // into three tetrahedra, abvd, bcvd, cavd, and bace (if it exists) had been //
13407 // split into bave, cbve, acve. 'splittet' represents abvd (its apex is v).  //
13408 //                                                                           //
13409 // Point v is removed by expanding abvd to abcd, deleting two tetrahedra     //
13410 // bcvd, cavd. Expanding bave(if it exists) to bace, deleting two tetrahedra //
13411 // cbve, acve.  If abv is a subface, routine unsplitsubface() will be called //
13412 // to reverse the operation of splitting a subface. On completion, point v   //
13413 // is not deleted in this routine.                                           //
13414 //                                                                           //
13416 
13417 void tetgenmesh::unsplittetface(triface* splittet)
13418 {
13419   triface abvd, bcvd, cavd, bave, cbve, acve;
13420   triface oldbvd, oldvad, oldvbe, oldave;
13421   triface bcdcasing, cadcasing, cbecasing, acecasing;
13422   face bcdsh, cadsh, cbesh, acesh;
13423   face abvsh;
13424   bool mirrorflag;
13425 
13426   abvd = *splittet;
13427   adjustedgering(abvd, CCW); // for sure.
13428   enextfnext(abvd, oldbvd);
13429   fnext(oldbvd, bcvd);
13430   esymself(bcvd);
13431   enextself(bcvd);
13432   enext2fnext(abvd, oldvad);
13433   fnext(oldvad, cavd);
13434   esymself(cavd);
13435   enext2self(cavd);
13436   // Is there a second tetrahedron?
13437   sym(abvd, bave);
13438   mirrorflag = bave.tet != dummytet;
13439   if (mirrorflag) {
13440     findedge(&bave, dest(abvd), org(abvd));
13441     enextfnext(bave, oldave);
13442     fnext(oldave, acve);
13443     esymself(acve);
13444     enextself(acve);
13445     enext2fnext(bave, oldvbe);
13446     fnext(oldvbe, cbve);
13447     esymself(cbve);
13448     enext2self(cbve);
13449   } else {
13450     // Unsplit a hull face decrease the number of boundary faces.
13451     hullsize -= 2;
13452   }
13453   // Is there a subface at abv.
13454   tspivot(abvd, abvsh);
13455   if (abvsh.sh != dummysh) {
13456     // Exists! Keep the edge ab of both handles be the same.
13457     findedge(&abvsh, org(abvd), dest(abvd));
13458   }
13459 
13460   if (b->verbose > 1) {
13461     printf("  Removing point %d on face (%d, %d, %d).\n",
13462            pointmark(apex(abvd)), pointmark(org(abvd)), pointmark(dest(abvd)),
13463            pointmark(dest(bcvd)));
13464   }
13465 
13466   fnextself(bcvd); // bcvd has changed to bcdv.
13467   sym(bcvd, bcdcasing);
13468   tspivot(bcvd, bcdsh);
13469   fnextself(cavd); // cavd has changed to cadv.
13470   sym(cavd, cadcasing);
13471   tspivot(cavd, cadsh);
13472   if (mirrorflag) {
13473     fnextself(acve); // acve has changed to acev.
13474     sym(acve, acecasing);
13475     tspivot(acve, acesh);
13476     fnextself(cbve); // cbve has changed to cbev.
13477     sym(cbve, cbecasing);
13478     tspivot(cbve, cbesh);
13479   }
13480 
13481   // Expand abvd to abcd.
13482   setapex(abvd, dest(bcvd));
13483   bond(oldbvd, bcdcasing);
13484   if (bcdsh.sh != dummysh) {
13485     tsbond(oldbvd, bcdsh);
13486   }
13487   bond(oldvad, cadcasing);
13488   if (cadsh.sh != dummysh) {
13489     tsbond(oldvad, cadsh);
13490   }
13491   if (mirrorflag) {
13492     // Expanding bave to bace.
13493     setapex(bave, dest(acve));
13494     bond(oldave, acecasing);
13495     if (acesh.sh != dummysh) {
13496       tsbond(oldave, acesh);
13497     }
13498     bond(oldvbe, cbecasing);
13499     if (cbesh.sh != dummysh) {
13500       tsbond(oldvbe, cbesh);
13501     }
13502   }
13503 
13504   // Unsplit a subface if there exists.
13505   if (abvsh.sh != dummysh) {
13506     unsplitsubface(&abvsh);
13507   }
13508 
13509   // Delete the split-out tetrahedra.
13510   tetrahedrondealloc(bcvd.tet);
13511   tetrahedrondealloc(cavd.tet);
13512   if (mirrorflag) {
13513     tetrahedrondealloc(acve.tet);
13514     tetrahedrondealloc(cbve.tet);
13515   }
13516 }
13517 
13519 //                                                                           //
13520 // splitsubface()    Insert a point on a subface, split it into three.       //
13521 //                                                                           //
13522 // The subface is 'splitface'.  Let it is abc. The inserting point 'newpoint'//
13523 // v should lie inside abc.  If the neighbor tetrahedra of abc exist, i.e.,  //
13524 // abcd and bace, they should have been split by routine splittetface()      //
13525 // before calling this routine, so the connection between the new tetrahedra //
13526 // and new subfaces can be correctly set.                                    //
13527 //                                                                           //
13528 // To split subface abc by point v is to shrink abc to abv, create two new   //
13529 // subfaces bcv and cav.  Set the connection between updated and new created //
13530 // subfaces. If there is a subsegment at edge bc or ca, connection of new    //
13531 // subface (bcv or cav) to its casing subfaces is a face link, 'casingin' is //
13532 // the predecessor and 'casingout' is the successor. It is important to keep //
13533 // the orientations of the edge rings of the updated and created subfaces be //
13534 // the same as abc's. So they have the same orientation as other subfaces of //
13535 // this facet with respect to the lift point of this facet.                  //
13536 //                                                                           //
13537 // On completion, 'splitface' returns abv.  If 'flipqueue' is not NULL, it   //
13538 // returns all possibly non-Delaunay edges.                                  //
13539 //                                                                           //
13541 
13542 void tetgenmesh::splitsubface(point newpoint, face* splitface,
13543   queue* flipqueue)
13544 {
13545   triface abvd, bcvd, cavd, bave, cbve, acve;
13546   face abc, oldbc, oldca, bc, ca, spinsh;
13547   face bccasin, bccasout, cacasin, cacasout;
13548   face abv, bcv, cav;
13549   point pa, pb, pc;
13550 
13551   abc = *splitface;
13552   // The newly created subfaces will have the same edge ring as abc.
13553   adjustedgering(abc, CCW);
13554   pa = sorg(abc);
13555   pb = sdest(abc);
13556   pc = sapex(abc);
13557 
13558   if (b->verbose > 1) {
13559     printf("  Inserting point %d on subface (%d, %d, %d).\n",
13560            pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc));
13561   }
13562 
13563   // Save the old configuration at edge bc and ca.  Subsegments may appear
13564   //   at both sides, save the face links and dissolve them.
13565   senext(abc, oldbc);
13566   senext2(abc, oldca);
13567   spivot(oldbc, bccasout);
13568   sspivot(oldbc, bc);
13569   if (bc.sh != dummysh) {
13570     if (oldbc.sh != bccasout.sh) {
13571       // 'oldbc' is not self-bonded.
13572       spinsh = bccasout;
13573       do {
13574         bccasin = spinsh;
13575         spivotself(spinsh);
13576       } while (spinsh.sh != oldbc.sh);
13577     } else {
13578       bccasout.sh = dummysh;
13579     }
13580     ssdissolve(oldbc);
13581   }
13582   spivot(oldca, cacasout);
13583   sspivot(oldca, ca);
13584   if (ca.sh != dummysh) {
13585     if (oldca.sh != cacasout.sh) {
13586       // 'oldca' is not self-bonded.
13587       spinsh = cacasout;
13588       do {
13589         cacasin = spinsh;
13590         spivotself(spinsh);
13591       } while (spinsh.sh != oldca.sh);
13592     } else {
13593       cacasout.sh = dummysh;
13594     }
13595     ssdissolve(oldca);
13596   }
13597   // Create two new subfaces.
13598   makeshellface(subfaces, &bcv);
13599   makeshellface(subfaces, &cav);
13600 
13601   // Set the vertices of changed and new subfaces.
13602   abv = abc;  // Update 'abc' to 'abv'.
13603   setsapex(abv, newpoint);
13604   setsorg(bcv, pb);  // Set 'bcv'.
13605   setsdest(bcv, pc);
13606   setsapex(bcv, newpoint);
13607   setsorg(cav, pc);  // Set 'cav'.
13608   setsdest(cav, pa);
13609   setsapex(cav, newpoint);
13610   if (b->quality && varconstraint) {
13611     // Copy yhr area bound into the new subfaces.
13612     setareabound(bcv, areabound(abv));
13613     setareabound(cav, areabound(abv));
13614   }
13615   // Copy the boundary mark into the new subfaces.
13616   setshellmark(bcv, shellmark(abv));
13617   setshellmark(cav, shellmark(abv));
13618   // Copy the subface type into the new subfaces.
13619   setshelltype(bcv, shelltype(abv));
13620   setshelltype(cav, shelltype(abv));
13621   if (checkpbcs) {
13622     // Copy the pbcgroup into the new subfaces.
13623     setshellpbcgroup(bcv, shellpbcgroup(abv));
13624     setshellpbcgroup(cav, shellpbcgroup(abv));
13625   }
13626   // Bond the new subfaces to the surrounding subfaces.
13627   if (bc.sh != dummysh) {
13628     if (bccasout.sh != dummysh) {
13629       sbond1(bccasin, bcv);
13630       sbond1(bcv, bccasout);
13631     } else {
13632       // Bond 'bcv' to itsself.
13633       sbond(bcv, bcv);
13634     }
13635     ssbond(bcv, bc);
13636   } else {
13637     sbond(bcv, bccasout);
13638   }
13639   if (ca.sh != dummysh) {
13640     if (cacasout.sh != dummysh) {
13641       sbond1(cacasin, cav);
13642       sbond1(cav, cacasout);
13643     } else {
13644       // Bond 'cav' to itself.
13645       sbond(cav, cav);
13646     }
13647     ssbond(cav, ca);
13648   } else {
13649     sbond(cav, cacasout);
13650   }
13651   senext2self(bcv);
13652   sbond(bcv, oldbc);
13653   senextself(cav);
13654   sbond(cav, oldca);
13655   senext2self(bcv);
13656   senextself(cav);
13657   sbond(bcv, cav);
13658 
13659   // Bond the new subfaces to the new tetrahedra if they exist.
13660   stpivot(abv, abvd);
13661   if (abvd.tet != dummytet) {
13662     // Get two new tetrahedra and their syms.
13663     findedge(&abvd, sorg(abv), sdest(abv));
13664     enextfnext(abvd, bcvd);
13665 #ifdef SELF_CHECK
13666     assert(bcvd.tet != dummytet);
13667 #endif
13668     fnextself(bcvd);
13669     enext2fnext(abvd, cavd);
13670 #ifdef SELF_CHECK
13671     assert(cavd.tet != dummytet);
13672 #endif
13673     fnextself(cavd);
13674     // Bond two new subfaces to the two new tetrahedra.
13675     tsbond(bcvd, bcv);
13676     tsbond(cavd, cav);
13677   }
13678   // Set the connection at the other sides if the tetrahedra exist.
13679   sesymself(abv);  // bav
13680   stpivot(abv, bave);
13681   if (bave.tet != dummytet) {
13682     sesymself(bcv);  // cbv
13683     sesymself(cav);  // acv
13684     // Get two new tetrahedra and their syms.
13685     findedge(&bave, sorg(abv), sdest(abv));
13686     enextfnext(bave, acve);
13687 #ifdef SELF_CHECK
13688     assert(acve.tet != dummytet);
13689 #endif
13690     fnextself(acve);
13691     enext2fnext(bave, cbve);
13692 #ifdef SELF_CHECK
13693     assert(cbve.tet != dummytet);
13694 #endif
13695     fnextself(cbve);
13696     // Bond two new subfaces to the two new tetrahedra.
13697     tsbond(acve, cav);
13698     tsbond(cbve, bcv);
13699   }
13700 
13701   bcv.shver = 0;
13702   cav.shver = 0;
13703   if (b->verbose > 3) {
13704     printf("    Updating abv ");
13705     printsh(&abv);
13706     printf("    Creating bcv ");
13707     printsh(&bcv);
13708     printf("    Creating cav ");
13709     printsh(&cav);
13710   }
13711 
13712   if (flipqueue != (queue *) NULL) {
13713     enqueueflipedge(abv, flipqueue);
13714     enqueueflipedge(bcv, flipqueue);
13715     enqueueflipedge(cav, flipqueue);
13716   }
13717 
13718   // Set the return handle be abv.
13719   *splitface = abv;
13720 }
13721 
13723 //                                                                           //
13724 // unsplitsubface()    Reverse the operation of inserting a point on a       //
13725 //                     subface, so as to remove the newly inserted point.    //
13726 //                                                                           //
13727 // Assume the original subface is abc, it was split by a point v into three  //
13728 // subfaces abv, bcv and cav.  'splitsh' represents abv.                     //
13729 //                                                                           //
13730 // To remove point v is to expand abv to abc, delete bcv and cav. If edge bc //
13731 // or ca is a subsegment,  the connection at a subsegment is a subface link, //
13732 // '-casin' and '-casout' are used to save the predecessor and successor of  //
13733 // bcv or cav.  On completion, point v is not deleted in this routine.       //
13734 //                                                                           //
13736 
13737 void tetgenmesh::unsplitsubface(face* splitsh)
13738 {
13739   face abv, bcv, cav;
13740   face oldbv, oldva, bc, ca, spinsh;
13741   face bccasin, bccasout, cacasin, cacasout;
13742 
13743   abv = *splitsh;
13744   senext(abv, oldbv);
13745   spivot(oldbv, bcv);
13746   if (sorg(bcv) != sdest(oldbv)) {
13747     sesymself(bcv);
13748   }
13749   senextself(bcv);
13750   senext2(abv, oldva);
13751   spivot(oldva, cav);
13752   if (sorg(cav) != sdest(oldva)) {
13753     sesymself(cav);
13754   }
13755   senext2self(cav);
13756 
13757   if (b->verbose > 1) {
13758     printf("  Removing point %d on subface (%d, %d, %d).\n",
13759            pointmark(sapex(abv)), pointmark(sorg(abv)), pointmark(sdest(abv)),
13760            pointmark(sdest(bcv)));
13761   }
13762 
13763   spivot(bcv, bccasout);
13764   sspivot(bcv, bc);
13765   if (bc.sh != dummysh) {
13766     if (bcv.sh != bccasout.sh) {
13767       // 'bcv' is not self-bonded.
13768       spinsh = bccasout;
13769       do {
13770         bccasin = spinsh;
13771         spivotself(spinsh);
13772       } while (spinsh.sh != bcv.sh);
13773     } else {
13774       bccasout.sh = dummysh;
13775     }
13776   }
13777   spivot(cav, cacasout);
13778   sspivot(cav, ca);
13779   if (ca.sh != dummysh) {
13780     if (cav.sh != cacasout.sh) {
13781       // 'cav' is not self-bonded.
13782       spinsh = cacasout;
13783       do {
13784        cacasin = spinsh;
13785        spivotself(spinsh);
13786       } while (spinsh.sh != cav.sh);
13787     } else {
13788       cacasout.sh = dummysh;
13789     }
13790   }
13791 
13792   // Expand abv to abc.
13793   setsapex(abv, sdest(bcv));
13794   if (bc.sh != dummysh) {
13795     if (bccasout.sh != dummysh) {
13796       sbond1(bccasin, oldbv);
13797       sbond1(oldbv, bccasout);
13798     } else {
13799       // Bond 'oldbv' to itself.
13800       sbond(oldbv, oldbv);
13801     }
13802     ssbond(oldbv, bc);
13803   } else {
13804     sbond(oldbv, bccasout);
13805   }
13806   if (ca.sh != dummysh) {
13807     if (cacasout.sh != dummysh) {
13808       sbond1(cacasin, oldva);
13809       sbond1(oldva, cacasout);
13810     } else {
13811       // Bond 'oldva' to itself.
13812       sbond(oldva, oldva);
13813     }
13814     ssbond(oldva, ca);
13815   } else {
13816     sbond(oldva, cacasout);
13817   }
13818 
13819   // Delete two split-out subfaces.
13820   shellfacedealloc(subfaces, bcv.sh);
13821   shellfacedealloc(subfaces, cav.sh);
13822 }
13823 
13825 //                                                                           //
13826 // splittetedge()    Insert a point on an edge of the mesh.                  //
13827 //                                                                           //
13828 // The edge is given by 'splittet'. Assume its four corners are a, b, n1 and //
13829 // n2, where ab is the edge will be split. Around ab may exist any number of //
13830 // tetrahedra. For convenience, they're ordered in a sequence following the  //
13831 // right-hand rule with your thumb points from a to b. Let the vertex set of //
13832 // these tetrahedra be {a, b, n1, n2, ..., n(i)}. NOTE the tetrahedra around //
13833 // ab may not connect to each other (can only happen when ab is a subsegment,//
13834 // hence some faces abn(i) are subfaces).  If ab is a subsegment, abn1 must  //
13835 // be a subface.                                                             //
13836 //                                                                           //
13837 // To split edge ab by a point v is to split all tetrahedra containing ab by //
13838 // v.  More specifically, for each such tetrahedron, an1n2b, it is shrunk to //
13839 // an1n2v, and a new tetrahedra bn2n1v is created. If ab is a subsegment, or //
13840 // some faces of the splitting tetrahedra are subfaces, they must be split   //
13841 // either by calling routine 'splitsubedge()'.                               //
13842 //                                                                           //
13843 // On completion, 'splittet' returns avn1n2.  If 'flipqueue' is not NULL, it //
13844 // returns all faces which may become non-Delaunay after this operation.     //
13845 //                                                                           //
13847 
13848 void tetgenmesh::splittetedge(point newpoint, triface* splittet,
13849   queue* flipqueue)
13850 {
13851   triface *bots, *newtops;
13852   triface oldtop, topcasing;
13853   triface spintet, tmpbond0, tmpbond1;
13854   face abseg, splitsh, topsh, spinsh;
13855   triface worktet;
13856   face n1n2seg, n2vseg, n1vseg;
13857   point pa, pb, n1, n2;
13858   REAL attrib, volume;
13859   int wrapcount, hitbdry;
13860   int i, j;
13861 
13862   if (checksubfaces) {
13863     // Is there a subsegment need to be split together?
13864     tsspivot(splittet, &abseg);
13865     if (abseg.sh != dummysh) {
13866       abseg.shver = 0;
13867       // Orient the edge direction of 'splittet' be abseg.
13868       if (org(*splittet) != sorg(abseg)) {
13869         esymself(*splittet);
13870       }
13871     }
13872   }
13873   spintet = *splittet;
13874   pa = org(spintet);
13875   pb = dest(spintet);
13876 
13877   if (b->verbose > 1) {
13878     printf("  Inserting point %d on edge (%d, %d).\n",
13879            pointmark(newpoint), pointmark(pa), pointmark(pb));
13880   }
13881 
13882   // Collect the tetrahedra containing the splitting edge (ab).
13883   n1 = apex(spintet);
13884   hitbdry = 0;
13885   wrapcount = 1;
13886   if (checksubfaces && abseg.sh != dummysh) {
13887     // It may happen that some tetrahedra containing ab (a subsegment) are
13888     //   completely disconnected with others. If it happens, use the face
13889     //   link of ab to cross the boundary.
13890     while (true) {
13891       if (!fnextself(spintet)) {
13892         // Meet a boundary, walk through it.
13893         hitbdry ++;
13894         tspivot(spintet, spinsh);
13895 #ifdef SELF_CHECK
13896         assert(spinsh.sh != dummysh);
13897 #endif
13898         findedge(&spinsh, pa, pb);
13899         sfnextself(spinsh);
13900         stpivot(spinsh, spintet);
13901 #ifdef SELF_CHECK
13902         assert(spintet.tet != dummytet);
13903 #endif
13904         findedge(&spintet, pa, pb);
13905         // Remember this position (hull face) in 'splittet'.
13906         *splittet = spintet;
13907         // Split two hull faces increase the hull size;
13908         hullsize += 2;
13909       }
13910       if (apex(spintet) == n1) break;
13911       wrapcount ++;
13912     }
13913     if (hitbdry > 0) {
13914       wrapcount -= hitbdry;
13915     }
13916   } else {
13917     // All the tetrahedra containing ab are connected together. If there
13918     //   are subfaces, 'splitsh' keeps one of them.
13919     splitsh.sh = dummysh;
13920     while (hitbdry < 2) {
13921       if (checksubfaces && splitsh.sh == dummysh) {
13922         tspivot(spintet, splitsh);
13923       }
13924       if (fnextself(spintet)) {
13925         if (apex(spintet) == n1) break;
13926         wrapcount++;
13927       } else {
13928         hitbdry ++;
13929         if (hitbdry < 2) {
13930           esym(*splittet, spintet);
13931         }
13932       }
13933     }
13934     if (hitbdry > 0) {
13935       // ab is on the hull.
13936       wrapcount -= 1;
13937       // 'spintet' now is a hull face, inverse its edge direction.
13938       esym(spintet, *splittet);
13939       // Split two hull faces increases the number of hull faces.
13940       hullsize += 2;
13941     }
13942   }
13943 
13944   // Make arrays of updating (bot, oldtop) and new (newtop) tetrahedra.
13945   bots = new triface[wrapcount];
13946   newtops = new triface[wrapcount];
13947   // Spin around ab, gather tetrahedra and set up new tetrahedra.
13948   spintet = *splittet;
13949   for (i = 0; i < wrapcount; i++) {
13950     // Get 'bots[i] = an1n2b'.
13951     enext2fnext(spintet, bots[i]);
13952     esymself(bots[i]);
13953     // Create 'newtops[i]'.
13954     maketetrahedron(&(newtops[i]));
13955     // Go to the next.
13956     fnextself(spintet);
13957     if (checksubfaces && abseg.sh != dummysh) {
13958       if (!issymexist(&spintet)) {
13959         // We meet a hull face, walk through it.
13960         tspivot(spintet, spinsh);
13961 #ifdef SELF_CHECK
13962         assert(spinsh.sh != dummysh);
13963 #endif
13964         findedge(&spinsh, pa, pb);
13965         sfnextself(spinsh);
13966         stpivot(spinsh, spintet);
13967 #ifdef SELF_CHECK
13968         assert(spintet.tet != dummytet);
13969 #endif
13970         findedge(&spintet, pa, pb);
13971       }
13972     }
13973   }
13974 
13975   // Set the vertices of updated and new tetrahedra.
13976   for (i = 0; i < wrapcount; i++) {
13977     // Update 'bots[i] = an1n2v'.
13978     setoppo(bots[i], newpoint);
13979     // Set 'newtops[i] = bn2n1v'.
13980     n1 = dest(bots[i]);
13981     n2 = apex(bots[i]);
13982     // Set 'newtops[i]'.
13983     setorg(newtops[i], pb);
13984     setdest(newtops[i], n2);
13985     setapex(newtops[i], n1);
13986     setoppo(newtops[i], newpoint);
13987     // Set the element attributes of a new tetrahedron.
13988     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
13989       attrib = elemattribute(bots[i].tet, j);
13990       setelemattribute(newtops[i].tet, j, attrib);
13991     }
13992     if (b->varvolume) {
13993       // Set the area constraint of a new tetrahedron.
13994       volume = volumebound(bots[i].tet);
13995       setvolumebound(newtops[i].tet, volume);
13996     }
13997 #ifdef SELF_CHECK
13998     // Make sure no inversed tetrahedron has been created.
13999     // volume = orient3d(pa, n1, n2, newpoint);
14000     // if (volume >= 0.0) {
14001     //   printf("Internal error in splittetedge(): volume = %.12g.\n", volume);
14002     // }
14003     // volume = orient3d(pb, n2, n1, newpoint);
14004     // if (volume >= 0.0) {
14005     //   printf("Internal error in splittetedge(): volume = %.12g.\n", volume);
14006     // }
14007 #endif
14008   }
14009 
14010   // Bond newtops to topcasings and bots.
14011   for (i = 0; i < wrapcount; i++) {
14012     // Get 'oldtop = n1n2va' from 'bots[i]'.
14013     enextfnext(bots[i], oldtop);
14014     sym(oldtop, topcasing);
14015     bond(newtops[i], topcasing);
14016     if (checksubfaces) {
14017       tspivot(oldtop, topsh);
14018       if (topsh.sh != dummysh) {
14019         tsdissolve(oldtop);
14020         tsbond(newtops[i], topsh);
14021       }
14022     }
14023     enextfnext(newtops[i], tmpbond0);
14024     bond(oldtop, tmpbond0);
14025   }
14026   // Bond between newtops.
14027   fnext(newtops[0], tmpbond0);
14028   enext2fnext(bots[0], spintet);
14029   for (i = 1; i < wrapcount; i ++) {
14030     if (issymexist(&spintet)) {
14031       enext2fnext(newtops[i], tmpbond1);
14032       bond(tmpbond0, tmpbond1);
14033     }
14034     fnext(newtops[i], tmpbond0);
14035     enext2fnext(bots[i], spintet);
14036   }
14037   // Bond the last to the first if no boundary.
14038   if (issymexist(&spintet)) {
14039     enext2fnext(newtops[0], tmpbond1);
14040     bond(tmpbond0, tmpbond1);
14041   }
14042   if (checksubsegs) {
14043     for (i = 0; i < wrapcount; i++) {
14044       enextfnext(bots[i], worktet); // edge n1->n2.
14045       tsspivot1(worktet, n1n2seg);
14046       if (n1n2seg.sh != dummysh) {
14047         enext(newtops[i], tmpbond0);
14048         tssbond1(tmpbond0, n1n2seg);
14049       }
14050       enextself(worktet); // edge n2->v ==> n2->b
14051       tsspivot1(worktet, n2vseg);
14052       if (n2vseg.sh != dummysh) {
14053         tssdissolve1(worktet);
14054         tssbond1(newtops[i], n2vseg);
14055       }
14056       enextself(worktet); // edge v->n1 ==> b->n1
14057       tsspivot1(worktet, n1vseg);
14058       if (n1vseg.sh != dummysh) {
14059         tssdissolve1(worktet);
14060         enext2(newtops[i], tmpbond0);
14061         tssbond1(tmpbond0, n1vseg);
14062       }
14063     }
14064   }
14065 
14066   // Is there exist subfaces and subsegment need to be split?
14067   if (checksubfaces) {
14068     if (abseg.sh != dummysh) {
14069       // A subsegment needs be split.
14070       spivot(abseg, splitsh);
14071 #ifdef SELF_CHECK
14072       assert(splitsh.sh != dummysh);
14073 #endif
14074     }
14075     if (splitsh.sh != dummysh) {
14076       // Split subfaces (and subsegment).
14077       findedge(&splitsh, pa, pb);
14078       splitsubedge(newpoint, &splitsh, (queue *) NULL);
14079     }
14080   }
14081 
14082   if (b->verbose > 3) {
14083     for (i = 0; i < wrapcount; i++) {
14084       printf("    Updating bots[%i] ", i);
14085       printtet(&(bots[i]));
14086       printf("    Creating newtops[%i] ", i);
14087       printtet(&(newtops[i]));
14088     }
14089   }
14090 
14091   if (flipqueue != (queue *) NULL) {
14092     for (i = 0; i < wrapcount; i++) {
14093       enqueueflipface(bots[i], flipqueue);
14094       enqueueflipface(newtops[i], flipqueue);
14095     }
14096   }
14097 
14098   // Set the return handle be avn1n2.  It is got by transforming from
14099   //   'bots[0]' (which is an1n2v).
14100   fnext(bots[0], spintet); // spintet is an1vn2.
14101   esymself(spintet); // spintet is n1avn2.
14102   enextself(spintet); // spintet is avn1n2.
14103   *splittet = spintet;
14104 
14105   delete [] bots;
14106   delete [] newtops;
14107 }
14108 
14110 //                                                                           //
14111 // unsplittetedge()    Reverse the operation of splitting an edge, so as to  //
14112 //                     remove the newly inserted point.                      //
14113 //                                                                           //
14114 // Assume the original edge is ab, the tetrahedron containing ab is abn1n2.  //
14115 // After ab was split by a point v, every tetrahedron containing ab (e.g.,   //
14116 // abn1n2) has been split into two (e.g., an1n2v and bn2n1v). 'splittet'     //
14117 // represents avn1n2 (i.e., its destination is v).                           //
14118 //                                                                           //
14119 // To remove point v is to expand each split tetrahedron containing ab (e.g.,//
14120 // (avn1n2 to abn1n2), then delete the redundant one(e.g., vbn1n2). If there //
14121 // exists any subface around ab, routine unsplitsubedge() will be called to  //
14122 // reverse the operation of splitting a edge (or a subsegment) of subfaces.  //
14123 // On completion, point v is not deleted in this routine.                    //
14124 //                                                                           //
14126 
14127 void tetgenmesh::unsplittetedge(triface* splittet)
14128 {
14129   triface *bots, *newtops;
14130   triface oldtop, topcasing;
14131   triface spintet;
14132   face avseg, splitsh, topsh, spinsh;
14133   point pa, pv, n1;
14134   int wrapcount, hitbdry;
14135   int i;
14136 
14137   spintet = *splittet;
14138   pa = org(spintet);
14139   pv = dest(spintet);
14140   if (checksubfaces) {
14141     // Is there a subsegment need to be unsplit together?
14142     tsspivot(splittet, &avseg);
14143     if (avseg.sh != dummysh) {
14144       // The subsegment's direction should conform to 'splittet'.
14145       if (sorg(avseg) != pa) {
14146         sesymself(avseg);
14147       }
14148     }
14149   }
14150 
14151   n1 = apex(spintet);
14152   hitbdry = 0;
14153   wrapcount = 1;
14154   if (checksubfaces && avseg.sh != dummysh) {
14155     // It may happen that some tetrahedra containing ab (a subsegment) are
14156     //   completely disconnected with others. If it happens, use the face
14157     //   link of ab to cross the boundary.
14158     while (true) {
14159       if (!fnextself(spintet)) {
14160         // Meet a boundary, walk through it.
14161         hitbdry ++;
14162         tspivot(spintet, spinsh);
14163 #ifdef SELF_CHECK
14164         assert(spinsh.sh != dummysh);
14165 #endif
14166         findedge(&spinsh, pa, pv);
14167         sfnextself(spinsh);
14168         stpivot(spinsh, spintet);
14169 #ifdef SELF_CHECK
14170         assert(spintet.tet != dummytet);
14171 #endif
14172         findedge(&spintet, pa, pv);
14173         // Remember this position (hull face) in 'splittet'.
14174         *splittet = spintet;
14175         // Split two hull faces increase the hull size;
14176         hullsize += 2;
14177       }
14178       if (apex(spintet) == n1) break;
14179       wrapcount ++;
14180     }
14181     if (hitbdry > 0) {
14182       wrapcount -= hitbdry;
14183     }
14184   } else {
14185     // All the tetrahedra containing ab are connected together. If there
14186     //   are subfaces, 'splitsh' keeps one of them.
14187     splitsh.sh = dummysh;
14188     while (hitbdry < 2) {
14189       if (checksubfaces && splitsh.sh == dummysh) {
14190         tspivot(spintet, splitsh);
14191       }
14192       if (fnextself(spintet)) {
14193         if (apex(spintet) == n1) break;
14194         wrapcount++;
14195       } else {
14196         hitbdry ++;
14197         if (hitbdry < 2) {
14198           esym(*splittet, spintet);
14199         }
14200       }
14201     }
14202     if (hitbdry > 0) {
14203       // ab is on the hull.
14204       wrapcount -= 1;
14205       // 'spintet' now is a hull face, inverse its edge direction.
14206       esym(spintet, *splittet);
14207       // Split two hull faces increases the number of hull faces.
14208       hullsize += 2;
14209     }
14210   }
14211 
14212   // Make arrays of updating (bot, oldtop) and new (newtop) tetrahedra.
14213   bots = new triface[wrapcount];
14214   newtops = new triface[wrapcount];
14215   // Spin around av, gather tetrahedra and set up new tetrahedra.
14216   spintet = *splittet;
14217   for (i = 0; i < wrapcount; i++) {
14218     // Get 'bots[i] = an1n2v'.
14219     enext2fnext(spintet, bots[i]);
14220     esymself(bots[i]);
14221     // Get 'oldtop = n1n2va'.
14222     enextfnext(bots[i], oldtop);
14223     // Get 'newtops[i] = 'bn1n2v'
14224     fnext(oldtop, newtops[i]); // newtop = n1n2bv
14225     esymself(newtops[i]); // newtop = n2n1bv
14226     enext2self(newtops[i]); // newtop = bn2n1v
14227     // Go to the next.
14228     fnextself(spintet);
14229     if (checksubfaces && avseg.sh != dummysh) {
14230       if (!issymexist(&spintet)) {
14231         // We meet a hull face, walk through it.
14232         tspivot(spintet, spinsh);
14233 #ifdef SELF_CHECK
14234         assert(spinsh.sh != dummysh);
14235 #endif
14236         findedge(&spinsh, pa, pv);
14237         sfnextself(spinsh);
14238         stpivot(spinsh, spintet);
14239 #ifdef SELF_CHECK
14240         assert(spintet.tet != dummytet);
14241 #endif
14242         findedge(&spintet, pa, pv);
14243       }
14244     }
14245   }
14246 
14247   if (b->verbose > 1) {
14248     printf("  Removing point %d from edge (%d, %d).\n",
14249            pointmark(oppo(bots[0])), pointmark(org(bots[0])),
14250            pointmark(org(newtops[0])));
14251   }
14252 
14253   for (i = 0; i < wrapcount; i++) {
14254     // Expand an1n2v to an1n2b.
14255     setoppo(bots[i], org(newtops[i]));
14256     // Get 'oldtop = n1n2va' from 'bot[i]'.
14257     enextfnext(bots[i], oldtop);
14258     // Get 'topcasing' from 'newtop[i]'
14259     sym(newtops[i], topcasing);
14260     // Bond them.
14261     bond(oldtop, topcasing);
14262     if (checksubfaces) {
14263       tspivot(newtops[i], topsh);
14264       if (topsh.sh != dummysh) {
14265         tsbond(oldtop, topsh);
14266       }
14267     }
14268     // Delete the tetrahedron above an1n2v.
14269     tetrahedrondealloc(newtops[i].tet);
14270   }
14271 
14272   // If there exists any subface, unsplit them.
14273   if (checksubfaces) {
14274     if (avseg.sh != dummysh) {
14275       spivot(avseg, splitsh);
14276 #ifdef SELF_CHECK
14277       assert(splitsh.sh != dummysh);
14278 #endif
14279     }
14280     if (splitsh.sh != dummysh) {
14281       findedge(&splitsh, pa, pv);
14282       unsplitsubedge(&splitsh);
14283     }
14284   }
14285 
14286   delete [] bots;
14287   delete [] newtops;
14288 }
14289 
14291 //                                                                           //
14292 // splitsubedge()    Insert a point on an edge of the surface mesh.          //
14293 //                                                                           //
14294 // The splitting edge is given by 'splitsh'. Assume its three corners are a, //
14295 // b, c, where ab is the edge will be split. ab may be a subsegment.         //
14296 //                                                                           //
14297 // To split edge ab is to split all subfaces conatining ab. If ab is not a   //
14298 // subsegment, there are only two subfaces need be split, otherwise, there   //
14299 // may have any number of subfaces need be split. Each splitting subface abc //
14300 // is shrunk to avc, a new subface vbc is created.  It is important to keep  //
14301 // the orientations of edge rings of avc and vbc be the same as abc's. If ab //
14302 // is a subsegment, it is shrunk to av and a new subsegment vb is created.   //
14303 //                                                                           //
14304 // If there are tetrahedra adjoining to the splitting subfaces, they should  //
14305 // be split before calling this routine, so the connection between the new   //
14306 // tetrahedra and the new subfaces can be correctly set.                     //
14307 //                                                                           //
14308 // On completion, 'splitsh' returns avc.  If 'flipqueue' is not NULL, it     //
14309 // returns all edges which may be non-Delaunay.                              //
14310 //                                                                           //
14312 
14313 void tetgenmesh::splitsubedge(point newpoint, face* splitsh, queue* flipqueue)
14314 {
14315   triface abcd, bace, vbcd, bvce;
14316   face startabc, spinabc, spinsh;
14317   face oldbc, bccasin, bccasout;
14318   face ab, bc;
14319   face avc, vbc, vbc1;
14320   face av, vb;
14321   point pa, pb;
14322 
14323   startabc = *splitsh;
14324   // Is there a subsegment?
14325   sspivot(startabc, ab);
14326   if (ab.sh != dummysh) {
14327     ab.shver = 0;
14328     if (sorg(startabc) != sorg(ab)) {
14329       sesymself(startabc);
14330     }
14331   }
14332   pa = sorg(startabc);
14333   pb = sdest(startabc);
14334 
14335   if (b->verbose > 1) {
14336     printf("  Inserting point %d on subedge (%d, %d) %s.\n",
14337            pointmark(newpoint), pointmark(pa), pointmark(pb),
14338            (ab.sh != dummysh ? "(seg)" : " "));
14339   }
14340 
14341   // Spin arround ab, split every subface containing ab.
14342   spinabc = startabc;
14343   do {
14344     // Adjust spinabc be edge ab.
14345     if (sorg(spinabc) != pa) {
14346       sesymself(spinabc);
14347     }
14348     // Save old configuration at edge bc, if bc has a subsegment, save the
14349     //   face link of it and dissolve it from bc.
14350     senext(spinabc, oldbc);
14351     spivot(oldbc, bccasout);
14352     sspivot(oldbc, bc);
14353     if (bc.sh != dummysh) {
14354       if (spinabc.sh != bccasout.sh) {
14355         // 'spinabc' is not self-bonded.
14356         spinsh = bccasout;
14357         do {
14358           bccasin = spinsh;
14359           spivotself(spinsh);
14360         } while (spinsh.sh != oldbc.sh);
14361       } else {
14362         bccasout.sh = dummysh;
14363       }
14364       ssdissolve(oldbc);
14365     }
14366     // Create a new subface.
14367     makeshellface(subfaces, &vbc);
14368     // Split abc.
14369     avc = spinabc;  // Update 'abc' to 'avc'.
14370     setsdest(avc, newpoint);
14371     // Make 'vbc' be in the same edge ring as 'avc'.
14372     vbc.shver = avc.shver;
14373     setsorg(vbc, newpoint); // Set 'vbc'.
14374     setsdest(vbc, pb);
14375     setsapex(vbc, sapex(avc));
14376     if (b->quality && varconstraint) {
14377       // Copy the area bound into the new subface.
14378       setareabound(vbc, areabound(avc));
14379     }
14380     // Copy the shell marker and shell type into the new subface.
14381     setshellmark(vbc, shellmark(avc));
14382     setshelltype(vbc, shelltype(avc));
14383     if (checkpbcs) {
14384       // Copy the pbcgroup into the new subface.
14385       setshellpbcgroup(vbc, shellpbcgroup(avc));
14386     }
14387     // Set the connection between updated and new subfaces.
14388     senext2self(vbc);
14389     sbond(vbc, oldbc);
14390     // Set the connection between new subface and casings.
14391     senext2self(vbc);
14392     if (bc.sh != dummysh) {
14393       if (bccasout.sh != dummysh) {
14394         // Insert 'vbc' into face link.
14395         sbond1(bccasin, vbc);
14396         sbond1(vbc, bccasout);
14397       } else {
14398         // Bond 'vbc' to itself.
14399         sbond(vbc, vbc);
14400       }
14401       ssbond(vbc, bc);
14402     } else {
14403       sbond(vbc, bccasout);
14404     }
14405     // Go to next subface at edge ab.
14406     spivotself(spinabc);
14407     if (spinabc.sh == dummysh) {
14408       break; // 'ab' is a hull edge.
14409     }
14410   } while (spinabc.sh != startabc.sh);
14411 
14412   // Get the new subface vbc above the updated subface avc (= startabc).
14413   senext(startabc, oldbc);
14414   spivot(oldbc, vbc);
14415   if (sorg(vbc) == newpoint) {
14416     sesymself(vbc);
14417   }
14418 #ifdef SELF_CHECK
14419   assert(sorg(vbc) == sdest(oldbc) && sdest(vbc) == sorg(oldbc));
14420 #endif
14421   senextself(vbc);
14422   // Set the face link for the new created subfaces around edge vb.
14423   spinabc = startabc;
14424   do {
14425     // Go to the next subface at edge av.
14426     spivotself(spinabc);
14427     if (spinabc.sh == dummysh) {
14428       break; // 'ab' is a hull edge.
14429     }
14430     if (sorg(spinabc) != pa) {
14431       sesymself(spinabc);
14432     }
14433     // Get the new subface vbc1 above the updated subface avc (= spinabc).
14434     senext(spinabc, oldbc);
14435     spivot(oldbc, vbc1);
14436     if (sorg(vbc1) == newpoint) {
14437       sesymself(vbc1);
14438     }
14439 #ifdef SELF_CHECK
14440     assert(sorg(vbc1) == sdest(oldbc) && sdest(vbc1) == sorg(oldbc));
14441 #endif
14442     senextself(vbc1);
14443     // Set the connection: vbc->vbc1.
14444     sbond1(vbc, vbc1);
14445     // For the next connection.
14446     vbc = vbc1;
14447   } while (spinabc.sh != startabc.sh);
14448 
14449   // Split ab if it is a subsegment.
14450   if (ab.sh != dummysh) {
14451     // Update subsegment ab to av.
14452     av = ab;
14453     setsdest(av, newpoint);
14454     // Create a new subsegment vb.
14455     makeshellface(subsegs, &vb);
14456     setsorg(vb, newpoint);
14457     setsdest(vb, pb);
14458     // vb gets the same mark and segment type as av.
14459     setshellmark(vb, shellmark(av));
14460     setshelltype(vb, shelltype(av));
14461     if (b->quality && varconstraint) {
14462       // Copy the area bound into the new subsegment.
14463       setareabound(vb, areabound(av));
14464     }
14465     // Save the old connection at ab (re-use the handles oldbc, bccasout).
14466     senext(av, oldbc);
14467     spivot(oldbc, bccasout);
14468     // Bond av and vb (bonded at their "fake" edges).
14469     senext2(vb, bccasin);
14470     sbond(bccasin, oldbc);
14471     if (bccasout.sh != dummysh) {
14472       // There is a subsegment connecting with ab at b. It will connect
14473       //   to vb at b after splitting.
14474       bccasout.shver = 0;
14475       if (sorg(bccasout) != pb) sesymself(bccasout);
14476 #ifdef SELF_CHECK
14477       assert(sorg(bccasout) == pb);
14478 #endif
14479       senext2self(bccasout);
14480       senext(vb, bccasin);
14481       sbond(bccasin, bccasout);
14482     }
14483     // Bond all new subfaces (vbc) to vb.
14484     spinabc = startabc;
14485     do {
14486       // Adjust spinabc be edge av.
14487       if (sorg(spinabc) != pa) {
14488         sesymself(spinabc);
14489       }
14490       // Get new subface vbc above the updated subface avc (= spinabc).
14491       senext(spinabc, oldbc);
14492       spivot(oldbc, vbc);
14493       if (sorg(vbc) == newpoint) {
14494         sesymself(vbc);
14495       }
14496       senextself(vbc);
14497       // Bond the new subface and the new subsegment.
14498       ssbond(vbc, vb);
14499       // Go to the next.
14500       spivotself(spinabc);
14501 #ifdef SELF_CHECK
14502       assert(spinabc.sh != dummysh);
14503 #endif
14504     } while (spinabc.sh != startabc.sh);
14505   }
14506 
14507   // Bond the new subfaces to new tetrahedra if they exist.  New tetrahedra
14508   //   should have been created before calling this routine.
14509   spinabc = startabc;
14510   do {
14511     // Adjust spinabc be edge av.
14512     if (sorg(spinabc) != pa) {
14513       sesymself(spinabc);
14514     }
14515     // Get new subface vbc above the updated subface avc (= spinabc).
14516     senext(spinabc, oldbc);
14517     spivot(oldbc, vbc);
14518     if (sorg(vbc) == newpoint) {
14519       sesymself(vbc);
14520     }
14521     senextself(vbc);
14522     // Get the adjacent tetrahedra at 'spinabc'.
14523     stpivot(spinabc, abcd);
14524     if (abcd.tet != dummytet) {
14525       findedge(&abcd, sorg(spinabc), sdest(spinabc));
14526       enextfnext(abcd, vbcd);
14527       fnextself(vbcd);
14528 #ifdef SELF_CHECK
14529       assert(vbcd.tet != dummytet);
14530 #endif
14531       tsbond(vbcd, vbc);
14532       sym(vbcd, bvce);
14533       sesymself(vbc);
14534       tsbond(bvce, vbc);
14535     } else {
14536       // One side is empty, check the other side.
14537       sesymself(spinabc);
14538       stpivot(spinabc, bace);
14539       if (bace.tet != dummytet) {
14540         findedge(&bace, sorg(spinabc), sdest(spinabc));
14541         enext2fnext(bace, bvce);
14542         fnextself(bvce);
14543 #ifdef SELF_CHECK
14544         assert(bvce.tet != dummytet);
14545 #endif
14546         sesymself(vbc);
14547         tsbond(bvce, vbc);
14548       }
14549     }
14550     // Go to the next.
14551     spivotself(spinabc);
14552     if (spinabc.sh == dummysh) {
14553       break; // 'ab' is a hull edge.
14554     }
14555   } while (spinabc.sh != startabc.sh);
14556 
14557   if (b->verbose > 3) {
14558     spinabc = startabc;
14559     do {
14560       // Adjust spinabc be edge av.
14561       if (sorg(spinabc) != pa) {
14562         sesymself(spinabc);
14563       }
14564       printf("    Updating abc:\n");
14565       printsh(&spinabc);
14566       // Get new subface vbc above the updated subface avc (= spinabc).
14567       senext(spinabc, oldbc);
14568       spivot(oldbc, vbc);
14569       if (sorg(vbc) == newpoint) {
14570         sesymself(vbc);
14571       }
14572       senextself(vbc);
14573       printf("    Creating vbc:\n");
14574       printsh(&vbc);
14575       // Go to the next.
14576       spivotself(spinabc);
14577       if (spinabc.sh == dummysh) {
14578         break; // 'ab' is a hull edge.
14579       }
14580     } while (spinabc.sh != startabc.sh);
14581   }
14582 
14583   if (flipqueue != (queue *) NULL) {
14584     spinabc = startabc;
14585     do {
14586       // Adjust spinabc be edge av.
14587       if (sorg(spinabc) != pa) {
14588         sesymself(spinabc);
14589       }
14590       senext2(spinabc, oldbc); // Re-use oldbc.
14591       enqueueflipedge(oldbc, flipqueue);
14592       // Get new subface vbc above the updated subface avc (= spinabc).
14593       senext(spinabc, oldbc);
14594       spivot(oldbc, vbc);
14595       if (sorg(vbc) == newpoint) {
14596         sesymself(vbc);
14597       }
14598       senextself(vbc);
14599       senext(vbc, oldbc); // Re-use oldbc.
14600       enqueueflipedge(oldbc, flipqueue);
14601       // Go to the next.
14602       spivotself(spinabc);
14603       if (spinabc.sh == dummysh) {
14604         break; // 'ab' is a hull edge.
14605       }
14606     } while (spinabc.sh != startabc.sh);
14607   }
14608 }
14609 
14611 //                                                                           //
14612 // unsplitsubedge()    Reverse the operation of splitting an edge of subface,//
14613 //                     so as to remove a point from the edge.                //
14614 //                                                                           //
14615 // Assume the original edge is ab, the subface containing it is abc. It was  //
14616 // split by a point v into avc, and vbc.  'splitsh' represents avc, further- //
14617 // more, if av is a subsegment, av should be the zero version of the split   //
14618 // subsegment (i.e., av.shver = 0), so we are sure that the destination (v)  //
14619 // of both avc and av is the deleting point.                                 //
14620 //                                                                           //
14621 // To remove point v is to expand avc to abc, delete vbc, do the same for    //
14622 // other subfaces containing av and vb. If av and vb are subsegments, expand //
14623 // av to ab, delete vb.  On completion, point v is not deleted.              //
14624 //                                                                           //
14626 
14627 void tetgenmesh::unsplitsubedge(face* splitsh)
14628 {
14629   face startavc, spinavc, spinbcv;
14630   face oldvc, bccasin, bccasout, spinsh;
14631   face av, vb, bc;
14632   point pa, pv, pb;
14633 
14634   startavc = *splitsh;
14635   sspivot(startavc, av);
14636   if (av.sh != dummysh) {
14637     // Orient the direction of subsegment to conform the subface.
14638     if (sorg(av) != sorg(startavc)) {
14639       sesymself(av);
14640     }
14641 #ifdef SELF_CHECK
14642     assert(av.shver == 0);
14643 #endif
14644   }
14645   senext(startavc, oldvc);
14646   spivot(oldvc, vb);  // vb is subface vbc
14647   if (sorg(vb) != sdest(oldvc)) {
14648     sesymself(vb);
14649   }
14650   senextself(vb);
14651   pa = sorg(startavc);
14652   pv = sdest(startavc);
14653   pb = sdest(vb);
14654 
14655   if (b->verbose > 1) {
14656     printf("  Removing point %d from subedge (%d, %d).\n",
14657            pointmark(pv), pointmark(pa), pointmark(pb));
14658   }
14659 
14660   // Spin arround av, unsplit every subface containing av.
14661   spinavc = startavc;
14662   do {
14663     // Adjust spinavc be edge av.
14664     if (sorg(spinavc) != pa) {
14665       sesymself(spinavc);
14666     }
14667     // Save old configuration at edge bc, if bc has a subsegment, save the
14668     //   face link of it.
14669     senext(spinavc, oldvc);
14670     spivot(oldvc, spinbcv);
14671     if (sorg(spinbcv) != sdest(oldvc)) {
14672       sesymself(spinbcv);
14673     }
14674     senext2self(spinbcv);
14675     spivot(spinbcv, bccasout);
14676     sspivot(spinbcv, bc);
14677     if (bc.sh != dummysh) {
14678       if (spinbcv.sh != bccasout.sh) {
14679         // 'spinbcv' is not self-bonded.
14680         spinsh = bccasout;
14681         do {
14682           bccasin = spinsh;
14683           spivotself(spinsh);
14684         } while (spinsh.sh != spinbcv.sh);
14685       } else {
14686         bccasout.sh = dummysh;
14687       }
14688     }
14689     // Expand avc to abc.
14690     setsdest(spinavc, pb);
14691     if (bc.sh != dummysh) {
14692       if (bccasout.sh != dummysh) {
14693         sbond1(bccasin, oldvc);
14694         sbond1(oldvc, bccasout);
14695       } else {
14696         // Bond 'oldbc' to itself.
14697         sbond(oldvc, oldvc);
14698       }
14699       ssbond(oldvc, bc);
14700     } else {
14701       sbond(oldvc, bccasout);
14702     }
14703     // Delete bcv.
14704     shellfacedealloc(subfaces, spinbcv.sh);
14705     // Go to next subface at edge av.
14706     spivotself(spinavc);
14707     if (spinavc.sh == dummysh) {
14708       break; // 'av' is a hull edge.
14709     }
14710   } while (spinavc.sh != startavc.sh);
14711 
14712   // Is there a subsegment need to be unsplit?
14713   if (av.sh != dummysh) {
14714     senext(av, oldvc);  // Re-use oldvc.
14715     spivot(oldvc, vb);
14716     vb.shver = 0;
14717 #ifdef SELF_CHECK
14718     assert(sdest(av) == sorg(vb));
14719 #endif
14720     senext(vb, spinbcv); // Re-use spinbcv.
14721     spivot(spinbcv, bccasout);
14722     // Expand av to ab.
14723     setsdest(av, pb);
14724     sbond(oldvc, bccasout);
14725     // Delete vb.
14726     shellfacedealloc(subsegs, vb.sh);
14727   }
14728 }
14729 
14731 //                                                                           //
14732 // insertsite()    Insert a point into the mesh.                             //
14733 //                                                                           //
14734 // The 'newpoint' is located.  If 'searchtet->tet' is not NULL, the search   //
14735 // for the containing tetrahedron begins from 'searchtet', otherwise, a full //
14736 // point location procedure is called.  If 'newpoint' is found inside a      //
14737 // tetrahedron, the tetrahedron is split into four (by splittetrahedron());  //
14738 // if 'newpoint' lies on a face, the face is split into three, thereby       //
14739 // splitting the two adjacent tetrahedra into six (by splittetface()); if    //
14740 // 'newpoint' lies on an edge, the edge is split into two, thereby, every    //
14741 // tetrahedron containing this edge is split into two. If 'newpoint' lies on //
14742 // an existing vertex, no action is taken, and the value DUPLICATEPOINT  is  //
14743 // returned and 'searchtet' is set to a handle whose origin is the vertex.   //
14744 //                                                                           //
14745 // If 'flipqueue' is not NULL, after 'newpoint' is inserted, it returns all  //
14746 // faces which may become non-Delaunay due to the newly inserted point. Flip //
14747 // operations can be performed as necessary on them to maintain the Delaunay //
14748 // property.                                                                 //
14749 //                                                                           //
14751 
14752 enum tetgenmesh::insertsiteresult tetgenmesh::insertsite(point newpoint,
14753   triface* searchtet, bool approx, queue* flipqueue)
14754 {
14755   enum locateresult intersect, exactloc;
14756   point checkpt;
14757   REAL epspp, checklen;
14758   int count;
14759 
14760   if (b->verbose > 1) {
14761     printf("  Insert point to mesh: (%.12g, %.12g, %.12g) %d.\n",
14762            newpoint[0], newpoint[1], newpoint[2], pointmark(newpoint));
14763   }
14764 
14765   if (searchtet->tet == (tetrahedron *) NULL) {
14766     // Search for a tetrahedron containing 'newpoint'.
14767     searchtet->tet = dummytet;
14768     exactloc = locate(newpoint, searchtet);
14769   } else {
14770     // Start searching from the tetrahedron provided by the caller.
14771     exactloc = preciselocate(newpoint, searchtet, tetrahedrons->items);
14772   }
14773   intersect = exactloc;
14774   if (approx && (exactloc != ONVERTEX)) {
14775     // Adjust the exact location to an approx. location wrt. epsilon.
14776     epspp = b->epsilon;
14777     count = 0;
14778     while (count < 16) {
14779       intersect = adjustlocate(newpoint, searchtet, exactloc, epspp);
14780       if (intersect == ONVERTEX) {
14781         checkpt = org(*searchtet);
14782         checklen = distance(checkpt, newpoint);
14783         if (checklen / longest > b->epsilon) {
14784           epspp *= 1e-2;
14785           count++;
14786           continue;
14787         }
14788       }
14789       break;
14790     }
14791   }
14792   // Keep current search state for next searching.
14793   recenttet = *searchtet;
14794 
14795   // Insert the point using the right routine
14796   switch (intersect) {
14797   case ONVERTEX:
14798     // There's already a vertex there. Return in 'searchtet' a tetrahedron
14799     //   whose origin is the existing vertex.
14800     if (b->verbose > 1) {
14801       printf("  Not insert for duplicating point.\n");
14802     }
14803     return DUPLICATEPOINT;
14804 
14805   case OUTSIDE:
14806     if (b->verbose > 1) {
14807       printf("  Not insert for locating outside the mesh.\n");
14808     }
14809     return OUTSIDEPOINT;
14810 
14811   case ONEDGE:
14812     // 'newpoint' falls on an edge.
14813     splittetedge(newpoint, searchtet, flipqueue);
14814     return SUCCESSONEDGE;
14815 
14816   case ONFACE:
14817     // 'newpoint' falls on a face.
14818     splittetface(newpoint, searchtet, flipqueue);
14819     return SUCCESSONFACE;
14820 
14821   case INTETRAHEDRON:
14822     // 'newpoint' falls inside a tetrahedron.
14823     splittetrahedron(newpoint, searchtet, flipqueue);
14824     return SUCCESSINTET;
14825 
14826   default:
14827     // Impossible case.
14828     return OUTSIDEPOINT;
14829   }
14830 }
14831 
14833 //                                                                           //
14834 // undosite()    Undo the most recently point insertion.                     //
14835 //                                                                           //
14836 // 'insresult' indicates in where the newpoint has been inserted, i.e., in a //
14837 // tetrahedron, on a face, or on an edge.  A correspoding routine will be    //
14838 // called to undo the point insertion.  'splittet' is a handle represent one //
14839 // of the resulting tetrahedra, but it may be changed after transformation,  //
14840 // even may be dead.  Four points 'torg', ... 'toppo' are the corners which  //
14841 // 'splittet' should have. On finish, 'newpoint' is not removed.             //
14842 //                                                                           //
14844 
14845 void tetgenmesh::undosite(enum insertsiteresult insresult, triface* splittet,
14846   point torg, point tdest, point tapex, point toppo)
14847 {
14848   // Set the four corners of 'splittet' exactly be 'torg', ... 'toppo'.
14849   findface(splittet, torg, tdest, tapex);
14850   if (oppo(*splittet) != toppo) {
14851     symself(*splittet);
14852 #ifdef SELF_CHECK
14853     assert(oppo(*splittet) == toppo);
14854 #endif
14855     // The sym() operation may inverse the edge, correct it if so.
14856     findedge(splittet, torg, tdest);
14857   }
14858 
14859   // Unsplit the tetrahedron according to 'insresult'.
14860   switch (insresult) {
14861   case SUCCESSINTET:
14862     // 'splittet' should be the face with 'newpoint' as its opposite.
14863     unsplittetrahedron(splittet);
14864     break;
14865   case SUCCESSONFACE:
14866     // 'splittet' should be the one of three splitted face with 'newpoint'
14867     //   as its apex.
14868     unsplittetface(splittet);
14869     break;
14870   case SUCCESSONEDGE:
14871     // 'splittet' should be the tet with destination is 'newpoint'.
14872     unsplittetedge(splittet);
14873     break;
14874   default: // To omit compile warnings.
14875     break;
14876   }
14877 }
14878 
14880 //                                                                           //
14881 // closeopenface()    Close "open" faces recursively.                        //
14882 //                                                                           //
14883 // This is the support routine of inserthullsite(). A point p which lies out-//
14884 // side of CH(T). p is inserted to T by forming a tet t from p and a visible //
14885 // CH face f. The three sides of f which have p as a vertex is called "open" //
14886 // face. Each open face will be closed by either creating a tet on top of it //
14887 // or become a new CH face.                                                  //
14888 //                                                                           //
14890 
14891 void tetgenmesh::closeopenface(triface* openface, queue* flipque)
14892 {
14893   triface newtet, oldhull;
14894   triface newopenface, closeface;
14895   point inspoint, pa, pb, pc;
14896   REAL attrib, volume;
14897   int i;
14898 
14899   // Get the new point p.
14900   inspoint = apex(*openface);
14901   // Find the old CH face f_o (f and f_o share the same edge).
14902   esym(*openface, oldhull);
14903   while (fnextself(oldhull)) ;
14904   if (apex(oldhull) != inspoint) {
14905     // Is f_o visible by p?
14906     pa = org(oldhull);
14907     pb = dest(oldhull);
14908     pc = apex(oldhull);
14909     if (orient3d(pa, pb, pc, inspoint) < 0.0) {
14910       // Yes. Create a new tet t above f_o.
14911       maketetrahedron(&newtet);
14912       setorg(newtet, pa);
14913       setdest(newtet, pb);
14914       setapex(newtet, pc);
14915       setoppo(newtet, inspoint);
14916       for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14917         attrib = elemattribute(oldhull.tet, i);
14918         setelemattribute(newtet.tet, i, attrib);
14919       }
14920       if (b->varvolume) {
14921         volume = volumebound(oldhull.tet);
14922         setvolumebound(newtet.tet, volume);
14923       }
14924       // Connect t to T.
14925       bond(newtet, oldhull);
14926       // Close f.
14927       fnext(newtet, newopenface);
14928       bond(newopenface, *openface);
14929       // f_o becomes an interior face.
14930       enqueueflipface(oldhull, flipque);
14931       // Hull face number decreases.
14932       hullsize--;
14933       // Two faces of t become open face.
14934       enextself(newtet);
14935       for (i = 0; i < 2; i++) {
14936         fnext(newtet, newopenface);
14937         sym(newopenface, closeface);
14938         if (closeface.tet == dummytet) {
14939           closeopenface(&newopenface, flipque);
14940         }
14941         enextself(newtet);
14942       }
14943     } else {
14944       // Inivisible. f becomes a new CH face.
14945       hullsize++;
14946       // Let 'dummytet' holds f for the next point location.
14947       dummytet[0] = encode(*openface);
14948     }
14949   } else {
14950     // f_o is co-incident with f --> f is closed by f_o.
14951     bond(*openface, oldhull);
14952     // f is an interior face.
14953     enqueueflipface(*openface, flipque);
14954   }
14955 }
14956 
14958 //                                                                           //
14959 // inserthullsite()    Insert a point which lies outside the convex hull.    //
14960 //                                                                           //
14961 // The 'inspoint' p lies outside the tetrahedralization T.  The 'horiz' f is //
14962 // on the convex hull of T, CH(T), which is visible by p (Imagine f is para- //
14963 // llel to the horizon). To insert p into T we have to enlarge the CH(T) and //
14964 // update T so that p is on the new CH(T).                                   //
14965 //                                                                           //
14966 // To enlarge the CH(T).  We need to find the set F of faces which are on CH //
14967 // (T) and visible by p (F can be formed by a depth-first search from f).  p //
14968 // is then inserted into T by mounting new tets formed by p and these faces. //
14969 // Faces of F become interior faces and may non-locally Delaunay.  They are  //
14970 // queued in 'flipqueue' for flip tests.                                     //
14971 //                                                                           //
14973 
14974 void tetgenmesh::inserthullsite(point inspoint, triface* horiz, queue* flipque)
14975 {
14976   triface firstnewtet;
14977   triface openface, closeface;
14978   REAL attrib, volume;
14979   int i;
14980 
14981   // Let f face to p.
14982   adjustedgering(*horiz, CW);
14983   // Create the first tet t (from f and p).
14984   maketetrahedron(&firstnewtet);
14985   setorg (firstnewtet, org(*horiz));
14986   setdest(firstnewtet, dest(*horiz));
14987   setapex(firstnewtet, apex(*horiz));
14988   setoppo(firstnewtet, inspoint);
14989   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14990     attrib = elemattribute(horiz->tet, i);
14991     setelemattribute(firstnewtet.tet, i, attrib);
14992   }
14993   if (b->varvolume) {
14994     volume = volumebound(horiz->tet);
14995     setvolumebound(firstnewtet.tet, volume);
14996   }
14997   // Connect t to T.
14998   bond(firstnewtet, *horiz);
14999   // f is not on CH(T) anymore.
15000   enqueueflipface(*horiz, flipque);
15001   // Hull face number decreases.
15002   hullsize--;
15003 
15004   // Call the faces of t which have p as a vertex "open" face.
15005   for (i = 0; i < 3; i++) {
15006     // Get an open face f_i of t.
15007     fnext(firstnewtet, openface);
15008     // Close f_i if it is still open.
15009     sym(openface, closeface);
15010     if (closeface.tet == dummytet) {
15011       closeopenface(&openface, flipque);
15012     }
15013     // Go to the next open face of t.
15014     enextself(firstnewtet);
15015   }
15016 }
15017 
15019 //                                                                           //
15020 // Terminology: BC(p) and CBC(p), B(p) and C(p).                             //
15021 //                                                                           //
15022 // Given an arbitrary point p,  the Bowyer-Watson cavity BC(p) is formed by  //
15023 // tets whose circumspheres containing p.  The outer faces of BC(p) form a   //
15024 // polyhedron B(p).                                                          //
15025 //                                                                           //
15026 // If p is on a facet F, the constrained Bowyer-Watson cavity CBC(p) on F is //
15027 // formed by subfaces of F whose circumspheres containing p. The outer edges //
15028 // of CBC(p) form a polygon C(p).  B(p) is separated into two parts by C(p), //
15029 // denoted as B_1(p) and B_2(p), one of them may be empty (F is on the hull).//
15030 //                                                                           //
15031 // If p is on a segment S which is shared by n facets.  There exist n C(p)s, //
15032 // each one is a non-closed polygon (without S). B(p) is split into n parts, //
15033 // each of them is denoted as B_i(p), some B_i(p) may be empty.              //
15034 //                                                                           //
15036 
15038 //                                                                           //
15039 // formbowatcavitysub()    Form CBC(p) and C(p) on a facet F.                //
15040 //                                                                           //
15041 // Parameters: bp = p, bpseg = S, sublist = CBC(p), subceillist = C(p).      //
15042 //                                                                           //
15043 // CBC(p) contains at least one subface on input; S may be NULL which means  //
15044 // that p is inside a facet. On output, all subfaces of CBC(p) are infected, //
15045 // and the edge rings are oriented to the same halfspace.                    //
15046 //                                                                           //
15048 
15049 void tetgenmesh::formbowatcavitysub(point bp, face* bpseg, list* sublist,
15050   list* subceillist)
15051 {
15052   triface adjtet;
15053   face startsh, neighsh;
15054   face checkseg;
15055   point pa, pb, pc, pd;
15056   REAL sign;
15057   int i, j;
15058 
15059   // Form CBC(p) and C(p) by a broadth-first searching.
15060   for (i = 0; i < sublist->len(); i++) {
15061     startsh = * (face *)(* sublist)[i]; // startsh = f.
15062     // Look for three neighbors of f.
15063     for (j = 0; j < 3; j++) {
15064       sspivot(startsh, checkseg);
15065       if (checkseg.sh == dummysh) {
15066         // Get its neighbor n.
15067         spivot(startsh, neighsh);
15068         // Is n already in CBC(p)?
15069         if (!sinfected(neighsh)) {
15070           stpivot(neighsh, adjtet);
15071           if (adjtet.tet == dummytet) {
15072             sesymself(neighsh);
15073             stpivot(neighsh, adjtet);
15074           }
15075           // For positive orientation that insphere() test requires.
15076           adjustedgering(adjtet, CW);
15077           pa = org(adjtet);
15078           pb = dest(adjtet);
15079           pc = apex(adjtet);
15080           pd = oppo(adjtet);
15081           sign = insphere(pa, pb, pc, pd, bp);
15082           if (sign >= 0.0) {
15083             // Orient edge ring of n according to that of f.
15084             if (sorg(neighsh) != sdest(startsh)) sesymself(neighsh);
15085             // Collect it into CBC(p).
15086             sinfect(neighsh);
15087             sublist->append(&neighsh);
15088           } else {
15089             subceillist->append(&startsh); // Found an edge of C(p).
15090           }
15091         }
15092       } else {
15093         // Do not cross a segment.
15094         if (bpseg != (face *) NULL) {
15095           if (checkseg.sh != bpseg->sh) {
15096             subceillist->append(&startsh); // Found an edge of C(p).
15097           }
15098         } else {
15099           subceillist->append(&startsh); // Found an edge of C(p).
15100         }
15101       }
15102       senextself(startsh);
15103     }
15104   }
15105 
15106   if (b->verbose > 2) {
15107     printf("    Collect CBC(%d): %d subfaces, %d edges.\n", pointmark(bp),
15108            sublist->len(), subceillist->len());
15109   }
15110 }
15111 
15113 //                                                                           //
15114 // formbowatcavityquad()    Form BC_i(p) and B_i(p) in a quadrant.           //
15115 //                                                                           //
15116 // Parameters: bp = p, tetlist = BC_i(p), ceillist = B_i(p).                 //
15117 //                                                                           //
15118 // BC_i(p) contains at least one tet on input. On finish, all tets collected //
15119 // in BC_i(p) are infected. B_i(p) may not closed when p is on segment or in //
15120 // facet. C(p) must be formed before this routine.  Check the infect flag of //
15121 // a subface to identify the unclosed side of B_i(p).  These sides will be   //
15122 // closed by new subfaces of C(p)s.                                          //
15123 //                                                                           //
15125 
15126 void tetgenmesh::formbowatcavityquad(point bp, list* tetlist, list* ceillist)
15127 {
15128   triface starttet, neightet;
15129   face checksh;
15130   point pa, pb, pc, pd;
15131   REAL sign;
15132   int i;
15133 
15134   // Form BC_i(p) and B_i(p) by a broadth-first searching.
15135   for (i = 0; i < tetlist->len(); i++) {
15136     starttet = * (triface *)(* tetlist)[i];
15137     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15138       // Try to collect the neighbor of the face (f).
15139       tspivot(starttet, checksh);
15140       if (checksh.sh == dummysh) {
15141         // Get its neighbor n.
15142         sym(starttet, neightet);
15143         // Is n already in BC_i(p)?
15144         if (!infected(neightet)) {
15145           // For positive orientation that insphere() test requires.
15146           adjustedgering(neightet, CW);
15147           pa = org(neightet);
15148           pb = dest(neightet);
15149           pc = apex(neightet);
15150           pd = oppo(neightet);
15151           sign = insphere(pa, pb, pc, pd, bp);
15152           if (sign >= 0.0) {
15153             // Collect it into BC_i(p).
15154             infect(neightet);
15155             tetlist->append(&neightet);
15156           } else {
15157             ceillist->append(&starttet); // Found a face of B_i(p).
15158           }
15159         }
15160       } else {
15161         // Do not cross a boundary face.
15162         if (!sinfected(checksh)) {
15163           ceillist->append(&starttet); // Found a face of B_i(p).
15164         }
15165       }
15166     }
15167   }
15168 
15169   if (b->verbose > 2) {
15170     printf("    Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15171            tetlist->len(), ceillist->len());
15172   }
15173 }
15174 
15176 //                                                                           //
15177 // formbowatcavitysegquad()    Form BC_i(p) and B_i(p) in a segment quadrant.//
15178 //                                                                           //
15179 // Parameters: bp = p, tetlist = BC_i(p), ceillist = B_i(p).                 //
15180 //                                                                           //
15181 // BC_i(p) contains at least one tet on input. On finish, all tets collected //
15182 // in BC_i(p) are infected. B_i(p) is not closed. C(p) must be formed before //
15183 // this routine. Check the infect flag of a subface to identify the unclosed //
15184 // sides of B_i(p).  These sides will be closed by new subfaces of C(p)s.    //
15185 //                                                                           //
15186 // During the repair of encroaching subsegments, there may exist locally non-//
15187 // Delaunay faces. These faces are collected in BC_i(p) either.  B_i(p) has  //
15188 // to be formed later than BC_i(p).                                          //
15189 //                                                                           //
15191 
15192 void tetgenmesh::formbowatcavitysegquad(point bp, list* tetlist,list* ceillist)
15193 {
15194   triface starttet, neightet, cavtet;
15195   face checksh;
15196   point pa, pb, pc, pd, pe;
15197   REAL sign;
15198   int i;
15199 
15200   // Form BC_i(p) by a broadth-first searching.
15201   for (i = 0; i < tetlist->len(); i++) {
15202     starttet = * (triface *)(* tetlist)[i];
15203     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15204       // Try to collect the neighbor of the face f.
15205       tspivot(starttet, checksh);
15206       if (checksh.sh == dummysh) {
15207         // Get its neighbor n.
15208         sym(starttet, neightet);
15209         // Is n already in BC_i(p)?
15210         if (!infected(neightet)) {
15211           // For positive orientation that insphere() test requires.
15212           adjustedgering(neightet, CW);
15213           pa = org(neightet);
15214           pb = dest(neightet);
15215           pc = apex(neightet);
15216           pd = oppo(neightet);
15217           sign = insphere(pa, pb, pc, pd, bp);
15218           if (sign >= 0.0) {
15219             // Collect it into BC_i(p).
15220             infect(neightet);
15221             tetlist->append(&neightet);
15222           } else {
15223             // Check if the face is locally non-Delaunay.
15224             pe = oppo(starttet);
15225             sign = insphere(pa, pb, pc, pd, pe);
15226             if (sign >= 0.0) {
15227               // Collect it into BC_i(p).
15228               infect(neightet);
15229               tetlist->append(&neightet);
15230             }
15231           }
15232         }
15233       }
15234     }
15235   }
15236 
15237   // Generate B_i(p).
15238   for (i = 0; i < tetlist->len(); i++) {
15239     cavtet = * (triface *)(* tetlist)[i];
15240     for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15241       tspivot(cavtet, checksh);
15242       if (checksh.sh == dummysh) {
15243         sym(cavtet, neightet);
15244         if (!infected(neightet)) {
15245           ceillist->append(&cavtet); // Found a face of B(p).
15246         }
15247       } else {
15248         // Do not cross a boundary face.
15249         if (!sinfected(checksh)) {
15250           ceillist->append(&cavtet); // Found a face of B(p).
15251         }
15252       }
15253     }
15254   }
15255 
15256   if (b->verbose > 2) {
15257     printf("    Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15258            tetlist->len(), ceillist->len());
15259   }
15260 }
15261 
15263 //                                                                           //
15264 // formbowatcavity()    Form BC(p), B(p), CBC(p)s, and C(p)s.                //
15265 //                                                                           //
15266 // If 'bpseg'(S) != NULL, p is on segment S, else, p is on facet containing  //
15267 // 'bpsh' (F).  'n' returns the number of quadrants in BC(p). 'nmax' is the  //
15268 // maximum pre-allocated array length for the lists.                         //
15269 //                                                                           //
15271 
15272 void tetgenmesh::formbowatcavity(point bp, face* bpseg, face* bpsh, int* n,
15273   int* nmax, list** sublists, list** subceillists, list** tetlists,
15274   list** ceillists)
15275 {
15276   list *sublist;
15277   triface adjtet;
15278   face startsh, spinsh;
15279   point pa, pb;
15280   int i, j;
15281 
15282   *n = 0;
15283   if (bpseg != (face *) NULL) {
15284     // p is on segment S.
15285     bpseg->shver = 0;
15286     pa = sorg(*bpseg);
15287     pb = sdest(*bpseg);
15288     // Count the number of facets sharing at S.
15289     spivot(*bpseg, startsh);
15290     spinsh = startsh;
15291     do {
15292       (*n)++; // spinshlist->append(&spinsh);
15293       spivotself(spinsh);
15294     } while (spinsh.sh != startsh.sh);
15295     // *n is the number of quadrants around S.
15296     if (*n > *nmax) {
15297       // Reallocate arrays. Should not happen very often.
15298       delete [] tetlists;
15299       delete [] ceillists;
15300       delete [] sublists;
15301       delete [] subceillists;
15302       tetlists = new list*[*n];
15303       ceillists = new list*[*n];
15304       sublists = new list*[*n];
15305       subceillists = new list*[*n];
15306       *nmax = *n;
15307     }
15308     // Form CBC(p)s and C(p)s.
15309     spinsh = startsh;
15310     for (i = 0; i < *n; i++) {
15311       sublists[i] = new list(sizeof(face), NULL, 256);
15312       subceillists[i] = new list(sizeof(face), NULL, 256);
15313       // Set a subface f to start search.
15314       startsh = spinsh;
15315       // Let f face to the quadrant of interest (used in forming BC(p)).
15316       findedge(&startsh, pa, pb);
15317       sinfect(startsh);
15318       sublists[i]->append(&startsh);
15319       formbowatcavitysub(bp, bpseg, sublists[i], subceillists[i]);
15320       // Go to the next facet.
15321       spivotself(spinsh);
15322     }
15323   } else if (sublists != (list **) NULL) {
15324     // p is on a facet.
15325     *n = 2;
15326     // Form CBC(p) and C(p).
15327     sublists[0] = new list(sizeof(face), NULL, 256);
15328     subceillists[0] = new list(sizeof(face), NULL, 256);
15329     sinfect(*bpsh);
15330     sublists[0]->append(bpsh);
15331     formbowatcavitysub(bp, NULL, sublists[0], subceillists[0]);
15332   } else {
15333     // p is inside a tet.
15334     *n = 1;
15335   }
15336 
15337   // Form BC_i(p) and B_i(p).
15338   for (i = 0; i < *n; i++) {
15339     tetlists[i] = new list(sizeof(triface), NULL, 256);
15340     ceillists[i] = new list(sizeof(triface), NULL, 256);
15341     if (sublists != (list **) NULL) {
15342       // There are C(p)s.
15343       sublist = ((bpseg == (face *) NULL) ? sublists[0] : sublists[i]);
15344       // Add all adjacent tets of C_i(p) into BC_i(p).
15345       for (j = 0; j < sublist->len(); j++) {
15346         startsh = * (face *)(* sublist)[j];
15347         // Adjust the side facing to the right quadrant for C(p).
15348         if ((bpseg == (face *) NULL) && (i == 1)) sesymself(startsh);
15349         stpivot(startsh, adjtet);
15350         if (adjtet.tet != dummytet) {
15351           if (!infected(adjtet)) {
15352             infect(adjtet);
15353             tetlists[i]->append(&adjtet);
15354           }
15355         }
15356       }
15357       if (bpseg != (face *) NULL) {
15358         // The quadrant is bounded by another facet.
15359         sublist = ((i < *n - 1) ? sublists[i + 1] : sublists[0]);
15360         for (j = 0; j < sublist->len(); j++) {
15361           startsh = * (face *)(* sublist)[j];
15362           // Adjust the side facing to the right quadrant for C(p).
15363           sesymself(startsh);
15364           stpivot(startsh, adjtet);
15365           if (adjtet.tet != dummytet) {
15366             if (!infected(adjtet)) {
15367               infect(adjtet);
15368               tetlists[i]->append(&adjtet);
15369             }
15370           }
15371         }
15372       }
15373     }
15374     // It is possible that BC_i(p) is empty.
15375     if (tetlists[i]->len() == 0) continue;
15376     // Collect the rest of tets of BC_i(p) and form B_i(p).
15377     // if (b->conformdel) {
15378       // formbowatcavitysegquad(bp, tetlists[i], ceillists[i]);
15379     // } else {
15380       formbowatcavityquad(bp, tetlists[i], ceillists[i]);
15381     // }
15382   }
15383 }
15384 
15386 //                                                                           //
15387 // releasebowatcavity()    Undo and free the memory allocated in routine     //
15388 //                         formbowatcavity().                                //
15389 //                                                                           //
15391 
15392 void tetgenmesh::releasebowatcavity(face* bpseg, int n, list** sublists,
15393   list** subceillist, list** tetlists, list** ceillists)
15394 {
15395   triface oldtet;
15396   face oldsh;
15397   int i, j;
15398 
15399   if (sublists != (list **) NULL) {
15400     // Release CBC(p)s.
15401     for (i = 0; i < n; i++) {
15402       // Uninfect subfaces of CBC(p).
15403       for (j = 0; j < sublists[i]->len(); j++) {
15404         oldsh = * (face *)(* (sublists[i]))[j];
15405 #ifdef SELF_CHECK
15406         assert(sinfected(oldsh));
15407 #endif
15408         suninfect(oldsh);
15409       }
15410       delete sublists[i];
15411       delete subceillist[i];
15412       sublists[i] = (list *) NULL;
15413       subceillist[i] = (list *) NULL;
15414       if (bpseg == (face *) NULL) break;
15415     }
15416   }
15417   // Release BC(p).
15418   for (i = 0; i < n; i++) {
15419     // Uninfect tets of BC_i(p).
15420     for (j = 0; j < tetlists[i]->len(); j++) {
15421       oldtet = * (triface *)(* (tetlists[i]))[j];
15422 #ifdef SELF_CHECK
15423       assert(infected(oldtet));
15424 #endif
15425       uninfect(oldtet);
15426     }
15427     delete tetlists[i];
15428     delete ceillists[i];
15429     tetlists[i] = (list *) NULL;
15430     ceillists[i] = (list *) NULL;
15431   }
15432 }
15433 
15435 //                                                                           //
15436 // validatebowatcavityquad()    Valid B_i(p).                                //
15437 //                                                                           //
15438 // B_i(p) is valid if all faces of B_i(p) are visible by p, else B_i(p) is   //
15439 // invalid.  Each tet of BC_i(p) which has such a face is marked (uninfect). //
15440 // They will be removed in updatebowatcavityquad().                          //
15441 //                                                                           //
15442 // Return TRUE if B(p) is valid, else, return FALSE.                         //
15443 //                                                                           //
15445 
15446 bool tetgenmesh::validatebowatcavityquad(point bp,list* ceillist,REAL maxcosd)
15447 {
15448   triface ceiltet;
15449   point pa, pb, pc;
15450   REAL ori, cosd;
15451   int remcount, i;
15452 
15453   // Check the validate of B(p), cut tets having invisible faces.
15454   remcount = 0;
15455   for (i = 0; i < ceillist->len(); i++) {
15456     ceiltet = * (triface *)(* ceillist)[i];
15457     if (infected(ceiltet)) {
15458       adjustedgering(ceiltet, CCW);
15459       pa = org(ceiltet);
15460       pb = dest(ceiltet);
15461       pc = apex(ceiltet);
15462       ori = orient3d(pa, pb, pc, bp);
15463       if (ori >= 0.0) {
15464         // Found an invisible face.
15465         uninfect(ceiltet);
15466         remcount++;
15467         continue;
15468       }
15469       // If a non-trival 'maxcosd' is given.
15470       if (maxcosd > -1.0) {
15471         // Get the maximal dihedral angle of tet abcp.
15472         tetalldihedral(pa, pb, pc, bp, NULL, &cosd, NULL);
15473         // Do not form the tet if the maximal dihedral angle is not reduced.
15474         if (cosd < maxcosd) {
15475           uninfect(ceiltet);
15476           remcount++;
15477         }
15478       }
15479     }
15480   }
15481   return remcount == 0;
15482 }
15483 
15485 //                                                                           //
15486 // updatebowatcavityquad()    Update BC_i(p) and reform B_i(p).              //
15487 //                                                                           //
15488 // B_i(p) is invalid and some tets in BC_i(p) have been marked to be removed //
15489 // in validatebowatcavityquad().  This routine actually remove the cut tets  //
15490 // of BC_i(p) and re-form the B_i(p).                                        //
15491 //                                                                           //
15493 
15494 void tetgenmesh::updatebowatcavityquad(list* tetlist, list* ceillist)
15495 {
15496   triface cavtet, neightet;
15497   face checksh;
15498   int remcount, i;
15499 
15500   remcount = 0;
15501   for (i = 0; i < tetlist->len(); i++) {
15502     cavtet = * (triface *)(* tetlist)[i];
15503     if (!infected(cavtet)) {
15504       tetlist->del(i, 1);
15505       remcount++;
15506       i--;
15507     }
15508   }
15509 
15510   // Are there tets have been cut in BC_i(p)?
15511   if (remcount > 0) {
15512     // Re-form B_i(p).
15513     ceillist->clear();
15514     for (i = 0; i < tetlist->len(); i++) {
15515       cavtet = * (triface *)(* tetlist)[i];
15516       for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15517         tspivot(cavtet, checksh);
15518         if (checksh.sh == dummysh) {
15519           sym(cavtet, neightet);
15520           if (!infected(neightet)) {
15521             ceillist->append(&cavtet); // Found a face of B_i(p).
15522           }
15523         } else {
15524           // Do not cross a boundary face.
15525           if (!sinfected(checksh)) {
15526             ceillist->append(&cavtet); // Found a face of B_i(p).
15527           }
15528         }
15529       }
15530     }
15531     if (b->verbose > 2) {
15532       printf("    Update BC_i(p): %d tets, %d faces.\n", tetlist->len(),
15533              ceillist->len());
15534     }
15535   }
15536 }
15537 
15539 //                                                                           //
15540 // updatebowatcavitysub()    Check and update CBC(p) and C(p).               //
15541 //                                                                           //
15542 // A CBC(p) is valid if all its subfaces are inside or on the hull of BC(p). //
15543 // A subface s of CBC(p) is invalid if it is in one of the two cases:        //
15544 //   (1) s is completely outside BC(p);                                      //
15545 //   (2) s has two adjacent tets but only one of them is in BC(p);           //
15546 // s is removed from CBC(p) if it is invalid. If there is an adjacent tet of //
15547 // s which is in BC(p), it gets removed from BC(p) too. If CBC(p) is updated,//
15548 // C(p) is re-formed.                                                        //
15549 //                                                                           //
15550 // A C(p) is valid if all its edges are on the hull of BC(p).  An edge e of  //
15551 // C(p) may be inside BC(p) if e is a segment and belongs to only one facet. //
15552 // To correct C(p), a tet of BC(p) which shields e gets removed.             //
15553 //                                                                           //
15554 // If BC(p) is formed with locally non-Delaunay check (b->conformdel > 0).   //
15555 // A boundary-consistent check is needed for non-segment edges of C(p). Let  //
15556 // e be such an edge, the subface f contains e and outside C(p) may belong   //
15557 // to B(p) due to the non-coplanarity of the facet definition.  The tet of   //
15558 // BC(p) containing f gets removed to avoid creating a degenerate new tet.   //
15559 //                                                                           //
15560 // 'cutcount' accumulates the total number of cuttets(not only by this call).//
15561 //                                                                           //
15563 
15564 void tetgenmesh::updatebowatcavitysub(list* sublist, list* subceillist,
15565   int* cutcount)
15566 {
15567   triface adjtet, rotface;
15568   face checksh, neighsh;
15569   face checkseg;
15570   point pa, pb, pc;
15571   REAL ori1, ori2;
15572   int remcount;
15573   int i, j;
15574 
15575   remcount = 0;
15576   // Check the validity of CBC(p).
15577   for (i = 0; i < sublist->len(); i++) {
15578     checksh = * (face *)(* sublist)[i];
15579     // Check two adjacent tets of s.
15580     for (j = 0; j < 2; j++) {
15581       stpivot(checksh, adjtet);
15582       if (adjtet.tet != dummytet) {
15583         if (!infected(adjtet)) {
15584           // Could be either case (1) or (2).
15585           suninfect(checksh); // s survives.
15586           // If the sym. adjtet exists, it should remove from BC(p) too.
15587           sesymself(checksh);
15588           stpivot(checksh, adjtet);
15589           if (adjtet.tet != dummytet) {
15590             if (infected(adjtet)) {
15591               // Found an adj. tet in BC(p), remove it.
15592               uninfect(adjtet);
15593               (*cutcount)++;
15594             }
15595           }
15596           // Remove s from C(p).
15597           sublist->del(i, 1);
15598           i--;
15599           remcount++;
15600           break;
15601         }
15602       }
15603       sesymself(checksh);
15604     }
15605   }
15606   if (remcount > 0) {
15607     if (b->verbose > 2) {
15608       printf("    Removed %d subfaces from CBC(p).\n", remcount);
15609     }
15610     // Re-generate C(p).
15611     subceillist->clear();
15612     for (i = 0; i < sublist->len(); i++) {
15613       checksh = * (face *)(* sublist)[i];
15614       for (j = 0; j < 3; j++) {
15615         spivot(checksh, neighsh);
15616         if (!sinfected(neighsh)) {
15617           subceillist->append(&checksh);
15618         }
15619         senextself(checksh);
15620       }
15621     }
15622     if (b->verbose > 2) {
15623       printf("    Update CBC(p): %d subs, %d edges.\n", sublist->len(),
15624              subceillist->len());
15625     }
15626   }
15627 
15628   // Check the validity of C(p).
15629   for (i = 0; i < subceillist->len(); i++) {
15630     checksh = * (face *)(* subceillist)[i];
15631     sspivot(checksh, checkseg);
15632     if (checkseg.sh != dummysh) {
15633       // A segment. Check if it is inside BC(p).
15634       stpivot(checksh, adjtet);
15635       if (adjtet.tet == dummytet) {
15636         sesym(checksh, neighsh);
15637         stpivot(neighsh, adjtet);
15638       }
15639       findedge(&adjtet, sorg(checkseg), sdest(checkseg));
15640       adjustedgering(adjtet, CCW);
15641       fnext(adjtet, rotface); // It's the same tet.
15642       // Rotate rotface (f), stop on either of the following cases:
15643       //   (a) meet a subface, or
15644       //   (b) enter an uninfected tet, or
15645       //   (c) rewind back to adjtet.
15646       do {
15647         if (!infected(rotface)) break; // case (b)
15648         tspivot(rotface, neighsh);
15649         if (neighsh.sh != dummysh) break; // case (a)
15650         // Go to the next tet of the facing ring.
15651         fnextself(rotface);
15652       } while (apex(rotface) != apex(adjtet));
15653       // Is it case (c)?
15654       if (apex(rotface) == apex(adjtet)) {
15655         // The segment is enclosed by BC(p), invalid cavity.
15656         pa = org(adjtet);
15657         pb = dest(adjtet);
15658         pc = apex(adjtet);
15659         // Find the shield tet and cut it. Notice that the shield tet may
15660         //   not be unique when there are four coplanar points, ie.,
15661         //   ori1 * ori2 == 0.0. In such case, choose either of them.
15662         fnext(adjtet, rotface);
15663         do {
15664           fnextself(rotface);
15665           assert(infected(rotface));
15666           ori1 = orient3d(pa, pb, pc, apex(rotface));
15667           ori2 = orient3d(pa, pb, pc, oppo(rotface));
15668         } while (ori1 * ori2 > 0.0);
15669         // Cut this tet from BC(p).
15670         uninfect(rotface);
15671         (*cutcount)++;
15672       }
15673     } else {
15674       /*// An edge. Check if boundary-consistency should be enforced.
15675       if (b->conformdel > 0) {
15676         // Get the adj-sub n at e, it must be outside C(p).
15677         spivot(checksh, neighsh);
15678         assert(!sinfected(neighsh));
15679         // Check if n is on B(p).
15680         for (j = 0; j < 2; j++) {
15681           stpivot(neighsh, adjtet);
15682           if (adjtet.tet != dummytet) {
15683             if (infected(adjtet)) {
15684               uninfect(adjtet);
15685               (*cutcount)++;
15686             }
15687           }
15688           sesymself(neighsh);
15689         }
15690       } */
15691     }
15692   }
15693 }
15694 
15696 //                                                                           //
15697 // trimbowatcavity()    Validate B(p), CBC(p)s and C(p)s, update BC(p).      //
15698 //                                                                           //
15699 // A B(p) is valid if all its faces are visible by p. If a face f of B(p) is //
15700 // found invisible by p, the tet of BC(p) containing f gets removed and B(p) //
15701 // is refromed. The new B(p) may still contain invisible faces by p. Iterat- //
15702 // ively do the above procedure until B(p) is satisfied.                     //
15703 //                                                                           //
15704 // A CBC(p) is valid if each subface of CBC(p) is either on the hull of BC(p)//
15705 // or completely inside BC(p). If a subface s of CBC(p) is not valid, it is  //
15706 // removed from CBC(p) and C(p) is reformed. If there exists a tet t of BC(p)//
15707 // containg s, t is removed from BC(p). The process for validating BC(p) and //
15708 // B(p) is re-excuted.                                                       //
15709 //                                                                           //
15710 // A C(p) is valid if each edge of C(p) is on the hull of BC(p). If an edge  //
15711 // e of C(p) is invalid (e should be a subsegment which only belong to one   //
15712 // facet), a tet of BC(p) which contains e and has two other faces shielding //
15713 // e is removed. The process for validating BC(p) and B(p) is re-excuted.    //
15714 //                                                                           //
15715 // If either BC(p) or CBC(p) becomes empty. No valid BC(p) is found, return  //
15716 // FALSE. else, return TRUE.                                                 //
15717 //                                                                           //
15719 
15720 bool tetgenmesh::trimbowatcavity(point bp, face* bpseg, int n, list** sublists,
15721   list** subceillists, list** tetlists, list** ceillists, REAL maxcosd)
15722 {
15723   bool valflag;
15724   int oldnum, cutnum, cutcount;
15725   int i;
15726 
15727   cutnum = 0; // Count the total number of cut-off tets of BC(p).
15728   valflag = true;
15729 
15730   do {
15731     // Validate BC(p), B(p).
15732     for (i = 0; i < n && valflag; i++) {
15733       oldnum = tetlists[i]->len();
15734       // Iteratively validate BC_i(p) and B_i(p).
15735       while (!validatebowatcavityquad(bp, ceillists[i], maxcosd)) {
15736         // Update BC_i(p) and B_i(p).
15737         updatebowatcavityquad(tetlists[i], ceillists[i]);
15738         valflag = tetlists[i]->len() > 0;
15739       }
15740       cutnum += (oldnum - tetlists[i]->len());
15741     }
15742     if (valflag && (sublists != (list **) NULL)) {
15743       // Validate CBC(p), C(p).
15744       cutcount = 0;
15745       for (i = 0; i < n; i++) {
15746         updatebowatcavitysub(sublists[i], subceillists[i], &cutcount);
15747         // Only do once if p is on a facet.
15748         if (bpseg == (face *) NULL) break;
15749       }
15750       // Are there cut tets?
15751       if (cutcount > 0) {
15752         // Squeeze all cut tets in BC(p), keep valflag once it gets FLASE.
15753         for (i = 0; i < n; i++) {
15754           if (tetlists[i]->len() > 0) {
15755             updatebowatcavityquad(tetlists[i], ceillists[i]);
15756             if (valflag) {
15757               valflag = tetlists[i]->len() > 0;
15758             }
15759           }
15760         }
15761         cutnum += cutcount;
15762         // Go back to valid the updated BC(p).
15763         continue;
15764       }
15765     }
15766     break; // Leave the while-loop.
15767   } while (true);
15768 
15769   // Check if any CBC(p) becomes non-empty.
15770   if (valflag && (sublists != (list **) NULL)) {
15771     for (i = 0; i < n && valflag; i++) {
15772       valflag = (sublists[i]->len() > 0);
15773       if (bpseg == (face *) NULL) break;
15774     }
15775   }
15776 
15777   if (valflag && (cutnum > 0)) {
15778     // Accumulate counters.
15779     if (bpseg != (face *) NULL) {
15780       updsegcount++;
15781     } else if (sublists != (list **) NULL) {
15782       updsubcount++;
15783     } else {
15784       updvolcount++;
15785     }
15786   }
15787 
15788   if (!valflag) {
15789     // Accumulate counters.
15790     if (bpseg != (face *) NULL) {
15791       failsegcount++;
15792     } else if (sublists != (list **) NULL) {
15793       failsubcount++;
15794     } else {
15795       failvolcount++;
15796     }
15797   }
15798 
15799   return valflag;
15800 }
15801 
15803 //                                                                           //
15804 // bowatinsertsite()    Insert a point using the Bowyer-Watson method.       //
15805 //                                                                           //
15806 // Parameters: 'bp' = p, 'splitseg' = S, 'n' = the number of quadrants,      //
15807 // 'sublists', an array of CBC_i(p)s, 'subceillists', an array of C_i(p)s,   //
15808 // 'tetlists', an array of BC_i(p)s, 'ceillists', an array of B_i(p)s.       //
15809 //                                                                           //
15810 // If p is inside the mesh domain, then S = NULL, n = 1, CBC(p) and C(p) are //
15811 //   NULLs. 'tetlists[0]' = BC(p), 'ceillists[0]' = B(p).                    //
15812 // If p is on a facet F, then S = NULL, n = 2, and 'subceillists[0]' = C(p), //
15813 //  'subceillists[1]' is not needed (set it to NULL). B_1(p) and B_2(p) are  //
15814 //  in 'ceillists[0]' and 'ceillists[1]'.                                    //
15815 // If p is on a segment S, then F(S) is a list of subfaces around S, and n = //
15816 //   len(F(S)), there are n C_i(p)s and B_i(p)s supplied in 'subceillists[i]'//
15817 //   and 'ceillists[i]'.                                                     //
15818 //                                                                           //
15819 // If 'verlist' != NULL, it returns a list of vertices which connect to p.   //
15820 //   This vertices are used for interpolating size of p.                     //
15821 //                                                                           //
15822 // If 'flipque' != NULL, it returns a list of internal faces of new tets in  //
15823 //   BC(p), faces on C(p)s are excluded. These faces may be locally non-     //
15824 //   Delaunay and will be flipped if they are flippable. Such non-Delaunay   //
15825 //   faces may exist when p is inserted to split an encroaching segment.     //
15826 //                                                                           //
15827 // 'chkencseg', 'chkencsub', and 'chkbadtet' are flags that indicate whether //
15828 // or not there should be checks for the creation of encroached subsegments, //
15829 // subfaces, or bad quality tets. If 'chkencseg' = TRUE, the encroached sub- //
15830 // segments are added to the list of subsegments to be split.                //
15831 //                                                                           //
15832 // On return, 'ceillists' returns Star(p).                                   //
15833 //                                                                           //
15835 
15836 void tetgenmesh::bowatinsertsite(point bp,face* splitseg,int n,list** sublists,
15837   list** subceillists, list** tetlists, list** ceillists, list* verlist,
15838   queue* flipque, bool chkencseg, bool chkencsub, bool chkbadtet)
15839 {
15840   list *ceillist, *subceillist;
15841   triface oldtet, newtet, newface, rotface, neightet;
15842   face oldsh, newsh, newedge, checksh;
15843   face spinsh, casingin, casingout;
15844   face *apsegshs, *pbsegshs;
15845   face apseg, pbseg, checkseg;
15846   point pa, pb, pc;
15847   pa=NULL;
15848   pb=NULL;
15849   REAL attrib, volume;
15850   int idx, i, j, k;
15851 
15852   apsegshs = NULL;
15853   pbsegshs = NULL;
15854 
15855   if (b->verbose > 1) {
15856     printf("    Insert point %d (%.12g, %.12g, %.12g)", pointmark(bp), bp[0],
15857            bp[1], bp[2]);
15858   }
15859   if (splitseg != (face *) NULL) {
15860     if (b->verbose > 1) {
15861       printf(" on segment.\n");
15862     }
15863     bowatsegcount++;
15864   } else {
15865     if (subceillists != (list **) NULL) {
15866       if (b->verbose > 1) {
15867         printf(" on facet.\n");
15868       }
15869       bowatsubcount++;
15870     } else {
15871       if (b->verbose > 1) {
15872         printf(" in volume.\n");
15873       }
15874       bowatvolcount++;
15875     }
15876   }
15877 
15878   // Create new tets to fill B(p).
15879   for (k = 0; k < n; k++) {
15880     // Create new tets from each B_i(p).
15881     ceillist = ceillists[k];
15882     for (i = 0; i < ceillist->len(); i++) {
15883       oldtet = * (triface *)(* ceillist)[i];
15884       adjustedgering(oldtet, CCW);
15885       pa = org(oldtet);
15886       pb = dest(oldtet);
15887       pc = apex(oldtet);
15888       maketetrahedron(&newtet);
15889       setorg(newtet, pa);
15890       setdest(newtet, pb);
15891       setapex(newtet, pc);
15892       setoppo(newtet, bp);
15893       for (j = 0; j < in->numberoftetrahedronattributes; j++) {
15894         attrib = elemattribute(oldtet.tet, j);
15895         setelemattribute(newtet.tet, j, attrib);
15896       }
15897       if (b->varvolume) {
15898         volume = volumebound(oldtet.tet);
15899         if (volume > 0.0) {
15900           if (!b->fixedvolume && b->refine) {
15901             // '-r -a' switches and a .vol file case. Enlarge the maximum
15902             //   volume constraint for the new tets. Hence the new points
15903             //   only spread near the original constrained tet.
15904             volume *= 1.2;
15905           }
15906         }
15907         setvolumebound(newtet.tet, volume);
15908       }
15909       sym(oldtet, neightet);
15910       tspivot(oldtet, checksh);
15911       if (neightet.tet != dummytet) {
15912         bond(newtet, neightet);
15913       }
15914       if (checksh.sh != dummysh) {
15915         tsbond(newtet, checksh);
15916       }
15917       if (verlist != (list *) NULL) {
15918         // Collect vertices connecting to p.
15919         idx = pointmark(pa);
15920         if (idx >= 0) {
15921           setpointmark(pa, -idx - 1);
15922           verlist->append(&pa);
15923         }
15924         idx = pointmark(pb);
15925         if (idx >= 0) {
15926           setpointmark(pb, -idx - 1);
15927           verlist->append(&pb);
15928         }
15929         idx = pointmark(pc);
15930         if (idx >= 0) {
15931           setpointmark(pc, -idx - 1);
15932           verlist->append(&pc);
15933         }
15934       }
15935       // Replace the tet by the newtet for checking the quality.
15936       * (triface *)(* ceillist)[i] = newtet;
15937     }
15938   }
15939   if (verlist != (list *) NULL) {
15940     // Uninfect collected vertices.
15941     for (i = 0; i < verlist->len(); i++) {
15942       pa = * (point *)(* verlist)[i];
15943       idx = pointmark(pa);
15944       setpointmark(pa, -(idx + 1));
15945     }
15946   }
15947 
15948   // Connect new tets of B(p). Not all faces of new tets can be connected,
15949   //   e.g., if there are empty B_i(p)s.
15950   for (k = 0; k < n; k++) {
15951     ceillist = ceillists[k];
15952     for (i = 0; i < ceillist->len(); i++) {
15953       newtet = * (triface *)(* ceillist)[i];
15954       newtet.ver = 0;
15955       for (j = 0; j < 3; j++) {
15956         fnext(newtet, newface);
15957         sym(newface, neightet);
15958         if (neightet.tet == dummytet) {
15959           // Find the neighbor face by rotating the faces at edge ab.
15960           esym(newtet, rotface);
15961           pa = org(rotface);
15962           pb = dest(rotface);
15963           while (fnextself(rotface));
15964           // Do we meet a boundary face?
15965           tspivot(rotface, checksh);
15966           if (checksh.sh != dummysh) {
15967             // Walk through the boundary and continue to rotate faces.
15968             do {
15969               findedge(&checksh, pa, pb);
15970               sfnextself(checksh);
15971               assert((sorg(checksh) == pa) && (sdest(checksh) == pb));
15972               stpivot(checksh, rotface);
15973               if (infected(rotface)) {
15974                 // Meet an old tet of B_i(p). This side is on the hull and
15975                 //   will be connected to a new subface created in C(p).
15976                 break;
15977               }
15978               findedge(&rotface, pa, pb);
15979               while (fnextself(rotface));
15980               tspivot(rotface, checksh);
15981             } while (checksh.sh != dummysh);
15982           }
15983           // The rotface has edge ab, but it may not have newpt.
15984           if (apex(rotface) == apex(newface)) {
15985             // Bond the two tets together.
15986             bond(newface, rotface);
15987             // Queue (uniquely) this face if 'flipque' is given.
15988             if (flipque != (queue *) NULL) {
15989               enqueueflipface(newface, flipque);
15990             }
15991           }
15992         }
15993         enextself(newtet);
15994       }
15995     }
15996   }
15997 
15998   if (subceillists != (list **) NULL) {
15999     // There are C(p)s.
16000     if (splitseg != (face *) NULL) {
16001       // S (ab) is split by p.
16002       splitseg->shver = 0;
16003       pa = sorg(*splitseg);
16004       pb = sdest(*splitseg);
16005       // Allcate two arrays for saving the subface rings of the two new
16006       //   segments a->p and p->b.
16007       apsegshs = new face[n];
16008       pbsegshs = new face[n];
16009     }
16010 
16011     // For each C_k(p), do the following:
16012     //   (1) Create new subfaces to fill C_k(p), insert them into B(p);
16013     //   (2) Connect new subfaces to each other;
16014     for (k = 0; k < n; k++) {
16015       subceillist = subceillists[k];
16016 
16017       // Check if 'hullsize' should be updated.
16018       oldsh = * (face *)(* subceillist)[0];
16019       stpivot(oldsh, neightet);
16020       if (neightet.tet != dummytet) {
16021         sesymself(oldsh);
16022         stpivot(oldsh, neightet);
16023       }
16024       if (neightet.tet == dummytet) {
16025         // The hull size changes.
16026         hullsize += (subceillist->len() - sublists[k]->len());
16027       }
16028 
16029       // (1) Create new subfaces to fill C_k(p), insert them into B(p).
16030       for (i = 0; i < subceillist->len(); i++) {
16031         oldsh = * (face *)(* subceillist)[i];
16032         makeshellface(subfaces, &newsh);
16033         setsorg(newsh, sorg(oldsh));
16034         setsdest(newsh, sdest(oldsh));
16035         setsapex(newsh, bp);
16036         if (b->quality && varconstraint) {
16037           setareabound(newsh, areabound(oldsh));
16038         }
16039         setshellmark(newsh, shellmark(oldsh));
16040         setshelltype(newsh, shelltype(oldsh));
16041         if (checkpbcs) {
16042           setshellpbcgroup(newsh, shellpbcgroup(oldsh));
16043         }
16044         // Replace oldsh by newsh at the edge.
16045         spivot(oldsh, casingout);
16046         sspivot(oldsh, checkseg);
16047         if (checkseg.sh != dummysh) {
16048           // A segment. Insert s into the face ring, ie, s_in -> s -> s_out.
16049           if (oldsh.sh != casingout.sh) {
16050             // s is not bonded to itself.
16051             spinsh = casingout;
16052             do {
16053               casingin = spinsh;
16054               spivotself(spinsh);
16055             } while (sapex(spinsh) != sapex(oldsh));
16056             assert(casingin.sh != oldsh.sh);
16057             // Bond s_in -> s -> s_out (and dissolve s_in -> s_old -> s_out).
16058             sbond1(casingin, newsh);
16059             sbond1(newsh, casingout);
16060           } else {
16061             // Bond newsh -> newsh.
16062             sbond(newsh, newsh);
16063           }
16064           // Bond the segment.
16065           ssbond(newsh, checkseg);
16066         } else {
16067           // Bond s <-> s_out (and dissolve s_out -> s_old).
16068           sbond(newsh, casingout);
16069         }
16070 
16071         // Insert newsh into B(p). Use the coonections of oldsh.
16072         stpivot(oldsh, neightet);
16073         if (neightet.tet == dummytet) {
16074           sesymself(oldsh);
16075           sesymself(newsh); // Keep the same orientation as oldsh.
16076           stpivot(oldsh, neightet);
16077         }
16078         assert(infected(neightet));
16079         // Set on the rotating edge.
16080         findedge(&neightet, sorg(oldsh), sdest(oldsh));
16081         // Choose the rotating direction (to the inside of B(p)).
16082         adjustedgering(neightet, CCW);
16083         rotface = neightet;
16084         // Rotate face. Stop at a non-infected tet t (not in B(p)) or a
16085         //   hull face f (on B(p)). Get the neighbor n of t or f.  n is
16086         //   a new tet that has just been created to fill B(p).
16087         do {
16088           fnextself(rotface);
16089           sym(rotface, neightet);
16090           if (neightet.tet == dummytet) {
16091             tspivot(rotface, checksh);
16092             assert(checksh.sh != dummysh);
16093             stpivot(checksh, newtet);
16094             break;
16095           } else if (!infected(neightet)) {
16096             sym(neightet, newtet);
16097             break;
16098           }
16099         } while (true);
16100         assert(newtet.tet != rotface.tet);
16101         // Set the rotating edge of n.
16102         findedge(&newtet, sorg(oldsh), sdest(oldsh));
16103         // Choose the rotating direction (to the inside of B(p)).
16104         adjustedgering(newtet, CCW);
16105         fnext(newtet, newface);
16106         assert(apex(newface) == bp);
16107         // newsh has already been oriented toward n.
16108         tsbond(newface, newsh);
16109         sym(newface, neightet); // 'neightet' maybe outside.
16110         sesymself(newsh);
16111         tsbond(neightet, newsh); // Bond them anyway.
16112 
16113         // Replace oldsh by newsh in list.
16114         * (face *)(* subceillist)[i] = newsh;
16115       }
16116 
16117       // (2) Connect new subfaces to each other.
16118       for (i = 0; i < subceillist->len(); i++) {
16119         // Get a face cdp.
16120         newsh = * (face *)(* subceillist)[i];
16121         // Get a new tet containing cdp.
16122         stpivot(newsh, newtet);
16123         if (newtet.tet == dummytet) {
16124           sesymself(newsh);
16125           stpivot(newsh, newtet);
16126         }
16127         for (j = 0; j < 2; j++) {
16128           if (j == 0) {
16129             senext(newsh, newedge); // edge dp.
16130           } else {
16131             senext2(newsh, newedge); // edge pc.
16132             sesymself(newedge); // edge cp.
16133           }
16134           if (splitseg != (face *) NULL) {
16135             // Don not operate on newedge if it is ap or pb.
16136             if (sorg(newedge) == pa) {
16137               apsegshs[k] = newedge;
16138               continue;
16139             } else if (sorg(newedge) == pb) {
16140               pbsegshs[k] = newedge;
16141               continue;
16142             }
16143           }
16144           // There should no segment inside the cavity. Check it.
16145           sspivot(newedge, checkseg);
16146           assert(checkseg.sh == dummysh);
16147           spivot(newedge, casingout);
16148           if (casingout.sh == dummysh) {
16149             rotface = newtet;
16150             findedge(&rotface, sorg(newedge), sdest(newedge));
16151             // Rotate newtet until meeting a new subface which contains
16152             //   newedge. It must exist since newedge is not a seg.
16153             adjustedgering(rotface, CCW);
16154             do {
16155               fnextself(rotface);
16156               tspivot(rotface, checksh);
16157               if (checksh.sh != dummysh) break;
16158             } while (true);
16159             findedge(&checksh, sorg(newedge), sdest(newedge));
16160             sbond(newedge, checksh);
16161           }
16162         }
16163       }
16164       // Only do once if p is on a facet.
16165       if (splitseg == (face *) NULL) break;
16166     } // for (k = 0; k < n; k++)
16167 
16168     if (splitseg != (face *) NULL) {
16169       // Update a->b to be a->p.
16170       apseg = *splitseg;
16171       setsdest(apseg, bp);
16172       // Create a new subsegment p->b.
16173       makeshellface(subsegs, &pbseg);
16174       setsorg(pbseg, bp);
16175       setsdest(pbseg, pb);
16176       // p->b gets the same mark and segment type as a->p.
16177       setshellmark(pbseg, shellmark(apseg));
16178       setshelltype(pbseg, shelltype(apseg));
16179       if (b->quality && varconstraint) {
16180         // Copy the area bound into the new subsegment.
16181         setareabound(pbseg, areabound(apseg));
16182       }
16183       senext(apseg, checkseg);
16184       // Get the old connection at b of a->b.
16185       spivot(checkseg, casingout);
16186       // Bond a->p and p->b together.
16187       senext2(pbseg, casingin);
16188       sbond(casingin, checkseg);
16189       if (casingout.sh != dummysh) {
16190         // There is a subsegment connect at b of p->b.
16191         casingout.shver = 0;
16192 #ifdef SELF_CHECK
16193         assert(sorg(casingout) == pb);
16194 #endif
16195         senext2self(casingout);
16196         senext(pbseg, casingin);
16197         sbond(casingin, casingout);
16198       }
16199 
16200       // Bond all new subfaces to a->p and p->b.
16201       for (i = 0; i < n; i++) {
16202         spinsh = apsegshs[i];
16203         findedge(&spinsh, pa, bp);
16204         ssbond(spinsh, apseg);
16205         spinsh = pbsegshs[i];
16206         findedge(&spinsh, bp, pb);
16207         ssbond(spinsh, pbseg);
16208       }
16209       // Bond all subfaces share at a->p together.
16210       for (i = 0; i < n; i++) {
16211         spinsh = apsegshs[i];
16212         if (i < (n - 1)) {
16213           casingout = apsegshs[i + 1];
16214         } else {
16215           casingout = apsegshs[0];
16216         }
16217         sbond1(spinsh, casingout);
16218       }
16219       // Bond all subfaces share at p->b together.
16220       for (i = 0; i < n; i++) {
16221         spinsh = pbsegshs[i];
16222         if (i < (n - 1)) {
16223           casingout = pbsegshs[i + 1];
16224         } else {
16225           casingout = pbsegshs[0];
16226         }
16227         sbond1(spinsh, casingout);
16228       }
16229       delete [] apsegshs;
16230       delete [] pbsegshs;
16231 
16232       // Check for newly encroached subsegments if the flag is set.
16233       if (chkencseg) {
16234         // Check if a->p and p->b are encroached by other vertices.
16235         checkseg4encroach(&apseg, NULL, NULL, true);
16236         checkseg4encroach(&pbseg, NULL, NULL, true);
16237         // Check if the adjacent segments are encroached by p.
16238         tallencsegs(bp, n, ceillists);
16239       }
16240     } // if (splitseg != (face *) NULL)
16241 
16242     // Delete subfaces of old CBC_i(p)s.
16243     for (k = 0; k < n; k++) {
16244       for (i = 0; i < sublists[k]->len(); i++) {
16245         oldsh = * (face *)(* (sublists[k]))[i];
16246         shellfacedealloc(subfaces, oldsh.sh);
16247       }
16248       // Clear the list so that the subs will not get unmarked later in
16249       //   routine releasebowatcavity() which only frees the memory.
16250       sublists[k]->clear();
16251       // Only do once if p is on a facet.
16252       if (splitseg == (face *) NULL) break;
16253     }
16254 
16255     // Check for newly encroached subfaces if the flag is set.
16256     if (chkencsub) {
16257       // Check if new subfaces of C_i(p) are encroached by other vertices.
16258       for (k = 0; k < n; k++) {
16259         subceillist = subceillists[k];
16260         for (i = 0; i < subceillist->len(); i++) {
16261           newsh = * (face *)(* subceillist)[i];
16262           checksub4encroach(&newsh, NULL, true);
16263         }
16264         // Only do once if p is on a facet.
16265         if (splitseg == (face *) NULL) break;
16266       }
16267       // Check if the adjacent subfaces are encroached by p.
16268       tallencsubs(bp, n, ceillists);
16269     }
16270   } // if (subceillists != (list **) NULL)
16271 
16272   // Delete tets of old BC_i(p)s.
16273   for (k = 0; k < n; k++) {
16274     for (i = 0; i < tetlists[k]->len(); i++) {
16275       oldtet = * (triface *)(* (tetlists[k]))[i];
16276       tetrahedrondealloc(oldtet.tet);
16277     }
16278     // Clear the list so that the tets will not get unmarked later in
16279     //   routine releasebowatcavity() which only frees the memory.
16280     tetlists[k]->clear();
16281   }
16282 
16283   // check for bad quality tets if the flags is set.
16284   if (chkbadtet) {
16285     for (k = 0; k < n; k++) {
16286       ceillist = ceillists[k];
16287       for (i = 0; i < ceillist->len(); i++) {
16288         newtet = * (triface *)(* ceillist)[i];
16289         checktet4badqual(&newtet, true);
16290       }
16291     }
16292   }
16293 
16294   if (flipque != (queue *) NULL) {
16295     // Newly created internal faces of BC(p) (excluding faces on C(p)s) are
16296     //   in 'flipque'.  Some of these faces may be locally non-Delaunay due,
16297     //   to the existence of non-constrained tets. check and fix them.
16298     repairflipcount += flip(flipque, NULL);
16299   }
16300 }
16301 
16302 //
16303 // End of mesh transformation routines
16304 //
16305 
16306 //
16307 // Begin Delaunay tetrahedralization routines
16308 //
16309 
16311 //                                                                           //
16312 // formstarpolyhedron()    Get the star ployhedron of a point 'pt'.          //
16313 //                                                                           //
16314 // The polyhedron P is formed by faces of tets having 'pt' as a vertex.  If  //
16315 // 'complete' is TRUE, P is the complete star of 'pt'. Otherwise, P is boun- //
16316 // ded by subfaces, i.e. P is only part of the star of 'pt'.                 //
16317 //                                                                           //
16318 // 'tetlist' T returns the tets, it has one of such tets on input. Moreover, //
16319 // if t is in T, then oppo(t) = p.  Topologically, T is the star of p;  and  //
16320 // the faces of T is the link of p. 'verlist' V returns the vertices of T.   //
16321 //                                                                           //
16323 
16324 void tetgenmesh::formstarpolyhedron(point pt, list* tetlist, list* verlist,
16325   bool complete)
16326 {
16327   triface starttet, neightet;
16328   face checksh;
16329   point ver[3];
16330   int idx, i, j;
16331 
16332   // Get a tet t containing p.
16333   starttet = * (triface *)(* tetlist)[0];
16334   // Let oppo(t) = p.
16335   for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
16336     if (oppo(starttet) == pt) break;
16337   }
16338   assert(starttet.loc < 4);
16339   // Add t into T.
16340   * (triface *)(* tetlist)[0] = starttet;
16341   infect(starttet);
16342   if (verlist != (list *) NULL) {
16343     // Add three verts of t into V.
16344     ver[0] = org(starttet);
16345     ver[1] = dest(starttet);
16346     ver[2] = apex(starttet);
16347     for (i = 0; i < 3; i++) {
16348       // Mark the vert by inversing the index of the vert.
16349       idx = pointmark(ver[i]);
16350       setpointmark(ver[i], -idx - 1); // -1 to distinguish the zero.
16351       verlist->append(&(ver[i]));
16352     }
16353   }
16354 
16355   // Find other tets by a broadth-first search.
16356   for (i = 0; i < tetlist->len(); i++) {
16357     starttet = * (triface *)(* tetlist)[i];
16358     starttet.ver = 0;
16359     for (j = 0; j < 3; j++) {
16360       fnext(starttet, neightet);
16361       tspivot(neightet, checksh);
16362       // Should we cross a subface.
16363       if ((checksh.sh == dummysh) || complete) {
16364         // Get the neighbor n.
16365         symself(neightet);
16366         if ((neightet.tet != dummytet) && !infected(neightet)) {
16367           // Let oppo(n) = p.
16368           for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
16369             if (oppo(neightet) == pt) break;
16370           }
16371           assert(neightet.loc < 4);
16372           // Add n into T.
16373           infect(neightet);
16374           tetlist->append(&neightet);
16375           if (verlist != (list *) NULL) {
16376             // Add the apex vertex in n into V.
16377             ver[0] = org(starttet);
16378             ver[1] = dest(starttet);
16379             findedge(&neightet, ver[0], ver[1]);
16380             ver[2] = apex(neightet);
16381             idx = pointmark(ver[2]);
16382             if (idx >= 0) {
16383               setpointmark(ver[2], -idx - 1);
16384               verlist->append(&(ver[2]));
16385             }
16386           }
16387         }
16388       }
16389       enextself(starttet);
16390     }
16391   }
16392 
16393   // Uninfect tets.
16394   for (i = 0; i < tetlist->len(); i++) {
16395     starttet = * (triface *)(* tetlist)[i];
16396     uninfect(starttet);
16397   }
16398   if (verlist != (list *) NULL) {
16399     // Uninfect vertices.
16400     for (i = 0; i < verlist->len(); i++) {
16401       ver[0] = * (point *)(* verlist)[i];
16402       idx = pointmark(ver[0]);
16403       setpointmark(ver[0], -(idx + 1));
16404     }
16405   }
16406 }
16407 
16409 //                                                                           //
16410 // unifypoint()    Unify two distinct points if they're very close.          //
16411 //                                                                           //
16412 // This function is used for dealing with inputs from CAD tools.  Two points //
16413 // p and q are unified if: dist(p, q) / longest < eps.  Where dist() is the  //
16414 // Euclidean distance between p and q, longest is the maximum edge size of   //
16415 // the input point set, eps is the tolerrence specified by user, default is  //
16416 // 1e-6, it can be adjusted by '-T' switch.                                  //
16417 //                                                                           //
16419 
16420 bool tetgenmesh::unifypoint(point testpt, triface *starttet, enum locateresult
16421   loc, REAL eps)
16422 {
16423   triface symtet, spintet;
16424   point checkpt, tapex;
16425   REAL tol;
16426   bool merged;
16427   int hitbdry;
16428   int i;
16429 
16430   merged = false;
16431   tol = longest * eps;
16432   if ((loc == OUTSIDE) || (loc == INTETRAHEDRON) || (loc == ONFACE)) {
16433     // Check p is close to the four corners of the tet.
16434     for (i = 0; i < 4; i++) {
16435       checkpt = (point) starttet->tet[4 + i];
16436       if (distance(testpt, checkpt) < tol) {
16437         merged = true; // Found a merge point p'.
16438         break;
16439       }
16440     }
16441     if (!merged && (loc == ONFACE)) {
16442       // Check the opposite point of the neighbor tet if it exists.
16443       sym(*starttet, symtet);
16444       if (symtet.tet != dummytet) {
16445         checkpt = oppo(symtet);
16446         if (distance(testpt, checkpt) < tol) {
16447           merged = true; // Found a merge point p'.
16448         }
16449       }
16450     }
16451   } else if (loc == ONEDGE) {
16452     // Check two endpoints of the edge.
16453     checkpt = org(*starttet);
16454     if (distance(testpt, checkpt) < tol) {
16455       merged = true; // Found a merge point p'.
16456     }
16457     if (!merged) {
16458       checkpt = dest(*starttet);
16459       if (distance(testpt, checkpt) < tol) {
16460         merged = true; // Found a merge point p'.
16461       }
16462     }
16463     if (!merged) {
16464       // Check apexes of the faces having the edge.
16465       spintet = *starttet;
16466       tapex = apex(*starttet);
16467       hitbdry = 0;
16468       do {
16469         checkpt = apex(spintet);
16470         if (distance(testpt, checkpt) < tol) {
16471           merged = true; // Found a merge point p'.
16472           break;
16473         }
16474         if (!fnextself(spintet)) {
16475           hitbdry++;
16476           if (hitbdry < 2) {
16477             esym(*starttet, spintet);
16478             if (!fnextself(spintet)) {
16479               hitbdry++;
16480             }
16481           }
16482         }
16483       } while ((apex(spintet) != tapex) && (hitbdry < 2));
16484     }
16485   }
16486   if (merged) {
16487     if (b->object != tetgenbehavior::STL) {
16488       if (!b->quiet) {
16489         printf("Warning:  Point %d is unified to point %d.\n",
16490                pointmark(testpt), pointmark(checkpt));
16491       }
16492       // Count the number of duplicated points.
16493       dupverts++;
16494     }
16495     // Remember it is a duplicated point.
16496     setpointtype(testpt, DUPLICATEDVERTEX);
16497     // Set a pointer to the point it duplicates.
16498     setpoint2ppt(testpt, checkpt);
16499   }
16500   return merged;
16501 }
16502 
16504 //                                                                           //
16505 // incrflipdelaunay()   Construct a delaunay tetrahedrization from a set of  //
16506 //                      3D points by the incremental flip algorithm.         //
16507 //                                                                           //
16508 // The incremental flip algorithm (by Edelsbrunner and Shah) can be describ- //
16509 // ed as follows:                                                            //
16510 //                                                                           //
16511 //   S be a set of points in 3D, Let 4 <= i <= n and assume that the         //
16512 //   Delaunay tetrahedralization of the first i-1 points in S is already     //
16513 //   constructed; call it D(i-1). Add the i-th point p_i (belong to S) to    //
16514 //   D(i-1), and restore Delaunayhood by flipping; this result in D(i).      //
16515 //   Repeat this procedure until i = n.                                      //
16516 //                                                                           //
16517 // This strategy always leads to the Delaunay triangulation of a point set.  //
16518 // The return value is the number of convex hull faces of D.                 //
16519 //                                                                           //
16521 
16522 void tetgenmesh::incrflipdelaunay(triface* oldtet, point* insertarray,
16523   long arraysize, bool jump, bool merge, REAL eps, queue* flipque)
16524 {
16525   triface newtet, searchtet;
16526   point swappt, lastpt;
16527   enum locateresult loc;
16528   REAL det, n[3];
16529   REAL attrib, volume;
16530   int i, j;
16531 #ifdef SELF_CHECK
16532   clock_t loc_start, loc_end;
16533 #endif
16534 
16535   det = 0.0;
16536   if (b->verbose > 0) {
16537     printf("  Creating initial tetrahedralization.\n");
16538   }
16539 
16540   // The initial tetrahedralization T only has one tet formed by 4 affinely
16541   //   linear independent vertices of the point set V = 'insertarray'. The
16542   //   first point a = insertarray[0].
16543 
16544   // Get the second point b, that is not identical or very close to a.
16545   for (i = 1; i < arraysize; i++) {
16546     det = distance(insertarray[0], insertarray[i]);
16547     if (det > (longest * eps)) break;
16548   }
16549   if (i == arraysize) {
16550     printf("\nAll points seem to be identical.\n");
16551     return;
16552   } else {
16553     // Swap to move b from index i to index 1.
16554     swappt = insertarray[i];
16555     insertarray[i] = insertarray[1];
16556     insertarray[1] = swappt;
16557   }
16558   // Get the third point c, that is not collinear with a and b.
16559   for (i++; i < arraysize; i++) {
16560     if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
16561       break;
16562   }
16563   if (i == arraysize) {
16564     printf("\nAll points seem to be collinear.\n");
16565     return;
16566   } else {
16567     // Swap to move c from index i to index 2.
16568     swappt = insertarray[i];
16569     insertarray[i] = insertarray[2];
16570     insertarray[2] = swappt;
16571   }
16572   // Get the fourth point d, that is not coplanar with a, b, and c.
16573   for (i++; i < arraysize; i++) {
16574     det = orient3d(insertarray[0], insertarray[1], insertarray[2],
16575                    insertarray[i]);
16576     if (det == 0.0) continue;
16577     if (!iscoplanar(insertarray[0], insertarray[1], insertarray[2],
16578                     insertarray[i], det, eps)) break;
16579   }
16580   if (i == arraysize) {
16581     // It's a 2D problem.
16582     in->mesh_dim = 2;
16583     // All points are coplanar.
16584     if (b->plc) {
16585       // Create an abovepoint. Maybe a surface triangulation can be formed.
16586       facenormal(insertarray[0], insertarray[1], insertarray[2], n, &det);
16587       if (det != 0.0) for (j = 0; j < 3; j++) n[j] /= det;
16588       // Take the average edge length of the bounding box.
16589       det = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
16590       // Temporarily create a point. It will be removed by jettison();
16591       makepoint(&lastpt);
16592       for (j = 0; j < 3; j++) lastpt[j] = insertarray[0][j] + det * n[j];
16593       abovepoint = lastpt;
16594       det = orient3d(insertarray[0], insertarray[1], insertarray[2], lastpt);
16595       // The index of the next inserting point is 3.
16596       i = 3;
16597     } else {
16598       printf("\nAll points seem to be coplanar.\n");
16599       return;
16600     }
16601   } else {
16602     // Swap to move d from index i to index 3.
16603     swappt = insertarray[i];
16604     insertarray[i] = insertarray[3];
16605     insertarray[3] = swappt;
16606     lastpt = insertarray[3];
16607     // The index of the next inserting point is 4.
16608     i = 4;
16609   }
16610 
16611   // Create the initial tet.
16612   maketetrahedron(&newtet);
16613   if (det > 0.0) {
16614     // For keeping the positive orientation.
16615     swappt = insertarray[0];
16616     insertarray[0] = insertarray[1];
16617     insertarray[1] = swappt;
16618   }
16619   if (b->verbose > 2) {
16620     printf("  Create the first tet (%d, %d, %d, %d).\n",
16621            pointmark(insertarray[0]), pointmark(insertarray[1]),
16622            pointmark(insertarray[2]), pointmark(lastpt));
16623   }
16624   setorg(newtet, insertarray[0]);
16625   setdest(newtet, insertarray[1]);
16626   setapex(newtet, insertarray[2]);
16627   setoppo(newtet, lastpt);
16628   if (oldtet != (triface *) NULL) {
16629     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
16630       attrib = elemattribute(oldtet->tet, j);
16631       setelemattribute(newtet.tet, j, attrib);
16632     }
16633     if (b->varvolume) {
16634       volume = volumebound(oldtet->tet);
16635       setvolumebound(newtet.tet, volume);
16636     }
16637   }
16638   // Set vertex type be FREEVOLVERTEX if it has no type yet.
16639   if (pointtype(insertarray[0]) == UNUSEDVERTEX) {
16640     setpointtype(insertarray[0], FREEVOLVERTEX);
16641   }
16642   if (pointtype(insertarray[1]) == UNUSEDVERTEX) {
16643     setpointtype(insertarray[1], FREEVOLVERTEX);
16644   }
16645   if (pointtype(insertarray[2]) == UNUSEDVERTEX) {
16646     setpointtype(insertarray[2], FREEVOLVERTEX);
16647   }
16648   if (pointtype(lastpt) == UNUSEDVERTEX) {
16649     setpointtype(lastpt, FREEVOLVERTEX);
16650   }
16651   // Bond to 'dummytet' for point location.
16652   dummytet[0] = encode(newtet);
16653   if (b->verbose > 3) {
16654     printf("    Creating tetra ");
16655     printtet(&newtet);
16656   }
16657   // At init, all faces of this tet are hull faces.
16658   hullsize = 4;
16659 
16660   if (b->verbose > 0) {
16661     printf("  Incrementally inserting points.\n");
16662   }
16663 
16664   flip23s = flip32s = flip22s = flip44s = 0;
16665   searchtet.tet = (tetrahedron *) NULL;
16666 
16667   // Insert the rest of points, one by one.
16668   for (; i < arraysize; i++) {
16669     // Locate p_i in T.
16670 #ifdef SELF_CHECK
16671     loc_start = clock();
16672 #endif
16673     if (jump) {
16674       loc = locate(insertarray[i], &searchtet);
16675     } else {
16676       loc = preciselocate(insertarray[i], &searchtet, tetrahedrons->items);
16677     }
16678 #ifdef SELF_CHECK
16679     loc_end = clock();
16680     tloctime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16681 #endif
16682     // Keep current search state for next searching.
16683     recenttet = searchtet;
16684     if (loc == ONVERTEX) {
16685       if (b->object != tetgenbehavior::STL) {
16686         if (!b->quiet) {
16687           printf("Warning:  Point %d is identical with point %d.\n",
16688                  pointmark(insertarray[i]), pointmark(org(searchtet)));
16689         }
16690       }
16691       // Count the number of duplicated points.
16692       dupverts++;
16693       // Remember it is a duplicated point.
16694       setpointtype(insertarray[i], DUPLICATEDVERTEX);
16695       if (b->plc || b->refine) {
16696         // Set a pointer to the point it duplicates.
16697         setpoint2ppt(insertarray[i], org(searchtet));
16698       }
16699       continue; // p_i is not inserted.
16700     }
16701     if (merge) {
16702       // Unify p_i if it is too close to a point of T.
16703       if (unifypoint(insertarray[i], &searchtet, loc, eps)) {
16704         continue; // p_i is not inserted.
16705       }
16706     }
16707     // Insert p_i in T.
16708     if (loc != OUTSIDE) {
16709       if (b->verbose > 1) {
16710         printf("  Insert point %d in tetrahedralization.\n",
16711                pointmark(insertarray[i]));
16712       }
16713       if (loc == INTETRAHEDRON) {
16714         splittetrahedron(insertarray[i], &searchtet, flipque);
16715       } else if (loc == ONFACE) {
16716         splittetface(insertarray[i], &searchtet, flipque);
16717       } else if (loc == ONEDGE) {
16718         splittetedge(insertarray[i], &searchtet, flipque);
16719       }
16720     } else {
16721       if (b->verbose > 1) {
16722         printf("  Insert point %d on convex hull.\n",
16723                pointmark(insertarray[i]));
16724       }
16725       inserthullsite(insertarray[i], &searchtet, flipque);
16726     }
16727     if (pointtype(insertarray[i]) == UNUSEDVERTEX) {
16728       // p_i becomes a (volume) vertex of T.
16729       setpointtype(insertarray[i], FREEVOLVERTEX);
16730     }
16731 #ifdef SELF_CHECK
16732     loc_start = clock();
16733 #endif
16734     if (!b->noflip) {
16735       // Recover Delaunayness of T by flipping.
16736       flip(flipque, NULL);
16737     } else {
16738       lawson(NULL, flipque);
16739       // T remains regular.
16740       // flipque->clear();
16741     }
16742 #ifdef SELF_CHECK
16743     loc_end = clock();
16744     tfliptime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16745 #endif
16746   }
16747 
16748   if (b->verbose > 0) {
16749     printf("  %ld Flips (T23 %ld, T32 %ld, T22 %ld, T44 %ld)\n",
16750       flip23s+flip32s+flip22s+flip44s, flip23s, flip32s, flip22s, flip44s);
16751   }
16752 }
16753 
16755 //                                                                           //
16756 // delaunizevertices()    Form a Delaunay tetrahedralization.                //
16757 //                                                                           //
16758 // Given a point set V (saved in 'points').  The Delaunay tetrahedralization //
16759 // D of V is created by incrementally inserting vertices. Returns the number //
16760 // of triangular faces bounding the convex hull of D.                        //
16761 //                                                                           //
16763 
16764 long tetgenmesh::delaunizevertices()
16765 {
16766   queue *flipque;
16767   point *insertarray;
16768   long arraysize;
16769   int i, j;
16770 
16771   if (!b->quiet) {
16772     if (!b->noflip) {
16773       printf("Constructing Delaunay tetrahedralization.\n");
16774     } else {
16775       printf("Constructing regular tetrahedralization.\n");
16776     }
16777   }
16778 
16779   flipque = new queue(sizeof(badface));
16780   // Prepare the array of points for inserting.
16781   arraysize = points->items;
16782   insertarray = new point[arraysize];
16783   points->traversalinit();
16784 
16785   // Randomize the point order.
16786   // randomseed = b->srandseed;
16787   for (i = 0; i < arraysize; i++) {
16788     j = (int) randomnation(i + 1); // 0 <= j <= i;
16789     insertarray[i] = insertarray[j];
16790     insertarray[j] = pointtraverse();
16791   }
16792 
16793   // Use lawson flip.
16794   b->noflip = 1;
16795 
16796   // Form the DT by incremental flip Delaunay algorithm.
16797   incrflipdelaunay(NULL, insertarray, arraysize, true, b->plc, b->epsilon,
16798                    flipque);
16799 
16800   b->noflip = 0;
16801 
16802   delete [] insertarray;
16803   delete flipque;
16804   return hullsize;
16805 }
16806 
16807 //
16808 // End Delaunay tetrahedralization routines
16809 //
16810 
16811 //
16812 // Begin of surface triangulation routines
16813 //
16814 
16816 //                                                                           //
16817 // formstarpolygon()    Form the star polygon of a point in facet.           //
16818 //                                                                           //
16819 // The polygon P is formed by all coplanar subfaces having 'pt' as a vertex. //
16820 // P is bounded by segments, e.g, if no segments, P is the full star of pt.  //
16821 //                                                                           //
16822 // 'trilist' T returns the subfaces, it has one of such subfaces on input.   //
16823 // In addition, if f is in T, then sapex(f) = p. 'vertlist' V are verts of P.//
16824 // Topologically, T is the star of p; V and the edges of T are the link of p.//
16825 //                                                                           //
16827 
16828 void tetgenmesh::formstarpolygon(point pt, list* trilist, list* vertlist)
16829 {
16830   face steinsh, lnextsh, rnextsh;
16831   face checkseg;
16832   point pa, pb, pc, pd;
16833   int i;
16834 
16835   // Get a subface f containing p.
16836   steinsh = * (face *)(* trilist)[0];
16837   steinsh.shver = 0; // CCW
16838   // Let sapex(f) be p.
16839   for (i = 0; i < 3; i++) {
16840     if (sapex(steinsh) == pt) break;
16841     senextself(steinsh);
16842   }
16843   assert(i < 3);
16844   // Add the edge f into list.
16845   * (face *)(* trilist)[0] = steinsh;
16846   pa = sorg(steinsh);
16847   pb = sdest(steinsh);
16848   if (vertlist != (list *) NULL) {
16849     // Add two verts a, b into V,
16850     vertlist->append(&pa);
16851     vertlist->append(&pb);
16852   }
16853 
16854   // Rotate edge pa to the left (CW) until meet pb or a segment.
16855   lnextsh = steinsh;
16856   pc = pa;
16857   do {
16858     senext2self(lnextsh);
16859     assert(sorg(lnextsh) == pt);
16860     sspivot(lnextsh, checkseg);
16861     if (checkseg.sh != dummysh) break; // Do not cross a segment.
16862     // Get neighbor subface n (must exist).
16863     spivotself(lnextsh);
16864     if (lnextsh.sh == dummysh) break; // It's a hull edge.
16865     // Go to the edge ca opposite to p.
16866     if (sdest(lnextsh) != pt) sesymself(lnextsh);
16867     assert(sdest(lnextsh) == pt);
16868     senext2self(lnextsh);
16869     // Add n (at edge ca) to T.
16870     trilist->append(&lnextsh);
16871     // Add edge ca to E.
16872     pc = sorg(lnextsh);
16873     if (pc == pb) break; // Rotate back.
16874     if (vertlist != (list *) NULL) {
16875       // Add vert c into V.
16876       vertlist->append(&pc);
16877     }
16878   } while (true);
16879 
16880   if (pc != pb) {
16881     // Rotate edge bp to the right (CCW) until meet a segment.
16882     rnextsh = steinsh;
16883     do {
16884       senextself(rnextsh);
16885       assert(sdest(rnextsh) == pt);
16886       sspivot(rnextsh, checkseg);
16887       if (checkseg.sh != dummysh) break; // Do not cross a segment.
16888       // Get neighbor subface n (must exist).
16889       spivotself(rnextsh);
16890       if (rnextsh.sh == dummysh) break; // It's a hull edge.
16891       // Go to the edge bd opposite to p.
16892       if (sorg(rnextsh) != pt) sesymself(rnextsh);
16893       assert(sorg(rnextsh) == pt);
16894       senextself(rnextsh);
16895       // Add n (at edge bd) to T.
16896       trilist->append(&rnextsh);
16897       // Add edge bd to E.
16898       pd = sdest(rnextsh);
16899       if (pd == pa) break; // Rotate back.
16900       if (vertlist != (list *) NULL) {
16901         // Add vert d into V.
16902         vertlist->append(&pd);
16903       }
16904     } while (true);
16905   }
16906 }
16907 
16909 //                                                                           //
16910 // About the 'abovepoint'                                                    //
16911 //                                                                           //
16912 // The 'abovepoint' of a facet is a point which is exactly non-coplanar with //
16913 // the plane containing that facet.  With such an point, the 3D predicates:  //
16914 // orient3d(), and insphere() can be used to substitute the corresponding 2D //
16915 // siblings, e.g. orient2d(), and incircle().  Its location is not critical, //
16916 // but floating-point accuracy is improved if it is nicely placed over the   //
16917 // facet, not too close or too far away.                                     //
16918 //                                                                           //
16919 // We take the convention that the abovepoint of a facet always lies above   //
16920 // the facet. By this convention, given three points a, b, and c in a facet, //
16921 // we say c has the counterclockwise order with ab is corresponding to say   //
16922 // that c is below the plane abp, where p is the lift point.                 //
16923 //                                                                           //
16925 
16927 //                                                                           //
16928 // getfacetabovepoint()    Get a point above a plane pass through a facet.   //
16929 //                                                                           //
16930 // The calculcated point is saved in 'facetabovepointarray'. The 'abovepoint'//
16931 // is set on return.                                                         //
16932 //                                                                           //
16934 
16935 void tetgenmesh::getfacetabovepoint(face* facetsh)
16936 {
16937   list *verlist, *trilist, *tetlist;
16938   triface adjtet;
16939   face symsh;
16940   point p1, p2, p3, pa;
16941   enum locateresult loc;
16942   REAL smallcos, cosa;
16943   REAL largevol, volume;
16944   REAL v1[3], v2[3], len;
16945   int smallidx, largeidx;
16946   int shmark;
16947   int i, j;
16948 
16949   abovecount++;
16950   // Initialize working lists.
16951   verlist = new list(sizeof(point *), NULL);
16952   trilist = new list(sizeof(face), NULL);
16953   tetlist = new list(sizeof(triface), NULL);
16954 
16955   // Get three pivotal points p1, p2, and p3 in the facet as a base triangle
16956   //   which is non-trivil and has good base angle (close to 90 degree).
16957 
16958   // p1 is chosen as the one which has the smallest index in pa, pb, pc.
16959   p1 = sorg(*facetsh);
16960   pa = sdest(*facetsh);
16961   if (pointmark(pa) < pointmark(p1)) p1 = pa;
16962   pa = sapex(*facetsh);
16963   if (pointmark(pa) < pointmark(p1)) p1 = pa;
16964   // Form the star polygon of p1.
16965   trilist->append(facetsh);
16966   formstarpolygon(p1, trilist, verlist);
16967 
16968   // Get the second pivotal point p2.
16969   p2 = * (point *)(* verlist)[0];
16970   // Get vector v1 = p1->p2.
16971   for (i = 0; i < 3; i++) v1[i] = p2[i] - p1[i];
16972   len = sqrt(dot(v1, v1));
16973   assert(len > 0.0);  // p2 != p1.
16974   for (i = 0; i < 3; i++) v1[i] /= len;
16975 
16976   // Get the third pivotal point p3. p3 is chosen as the one in 'verlist'
16977   //   which forms an angle with v1 closer to 90 degree than others do.
16978   smallcos = 1.0; // The cosine value of 0 degree.
16979   smallidx = 1;   // Default value.
16980   for (i = 1; i < verlist->len(); i++) {
16981     p3 = * (point *)(* verlist)[i];
16982     for (j = 0; j < 3; j++) v2[j] = p3[j] - p1[j];
16983     len = sqrt(dot(v2, v2));
16984     if (len > 0.0) { // v2 is not too small.
16985       cosa = fabs(dot(v1, v2)) / len;
16986       if (cosa < smallcos) {
16987         smallidx = i;
16988         smallcos = cosa;
16989       }
16990     }
16991   }
16992   assert(smallcos < 1.0); // p1->p3 != p1->p2.
16993   p3 = * (point *)(* verlist)[smallidx];
16994   verlist->clear();
16995 
16996   if (tetrahedrons->items > 0l) {
16997     // Get a tet having p1 as a vertex.
16998     stpivot(*facetsh, adjtet);
16999     if (adjtet.tet == dummytet) {
17000       sesym(*facetsh, symsh);
17001       stpivot(symsh, adjtet);
17002     }
17003     if (adjtet.tet == dummytet) {
17004       decode(point2tet(p1), adjtet);
17005       if (isdead(&adjtet)) {
17006         adjtet.tet = dummytet;
17007       } else {
17008         if (!findorg(&adjtet, p1)) {
17009           adjtet.tet = dummytet;
17010         }
17011       }
17012     }
17013     if (adjtet.tet == dummytet) {
17014       loc = locate(p1, &adjtet);
17015       if (loc == ONVERTEX) {
17016         setpoint2tet(p1, encode(adjtet));
17017       } else {
17018         adjtet.tet = dummytet;
17019       }
17020     }
17021     if (adjtet.tet != dummytet) {
17022       // Get the star polyhedron of p1.
17023       tetlist->append(&adjtet);
17024       formstarpolyhedron(p1, tetlist, verlist, false);
17025     }
17026   }
17027 
17028   // Get the abovepoint in 'verlist'. It is the one form the largest valid
17029   //   volumw with the base triangle over other points in 'verlist.
17030   largevol = 0.0;
17031   largeidx = 0;
17032   for (i = 0; i < verlist->len(); i++) {
17033     pa = * (point *)(* verlist)[i];
17034     volume = orient3d(p1, p2, p3, pa);
17035     if (!iscoplanar(p1, p2, p3, pa, volume, b->epsilon * 1e+2)) {
17036       if (fabs(volume) > largevol) {
17037         largevol = fabs(volume);
17038         largeidx = i;
17039       }
17040     }
17041   }
17042 
17043   // Do we have the abovepoint?
17044   if (largevol > 0.0) {
17045     abovepoint = * (point *)(* verlist)[largeidx];
17046     if (b->verbose > 1) {
17047       printf("    Chosen abovepoint %d for facet %d.\n", pointmark(abovepoint),
17048              shellmark(*facetsh));
17049     }
17050   } else {
17051     // Calculate an abovepoint for this facet.
17052     facenormal(p1, p2, p3, v1, &len);
17053     if (len != 0.0) for (i = 0; i < 3; i++) v1[i] /= len;
17054     // Take the average edge length of the bounding box.
17055     len = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
17056     // Temporarily create a point. It will be removed by jettison();
17057     makepoint(&abovepoint);
17058     setpointtype(abovepoint, UNUSEDVERTEX);
17059     unuverts++;
17060     for (i = 0; i < 3; i++) abovepoint[i] = p1[i] + len * v1[i];
17061     if (b->verbose > 1) {
17062       printf("    Calculated abovepoint %d for facet %d.\n",
17063              pointmark(abovepoint), shellmark(*facetsh));
17064     }
17065   }
17066   // Save the abovepoint in 'facetabovepointarray'.
17067   shmark = shellmark(*facetsh);
17068   facetabovepointarray[shmark] = abovepoint;
17069 
17070   delete trilist;
17071   delete tetlist;
17072   delete verlist;
17073 }
17074 
17076 //                                                                           //
17077 // collectcavsubs()    Collect non-locally Delaunay subfaces wrt a point.    //
17078 //                                                                           //
17079 // 'cavsublist' returns the list of subfaces. On input, it conatins at least //
17080 // one subface.                                                              //
17081 //                                                                           //
17083 
17084 void tetgenmesh::collectcavsubs(point newpoint, list* cavsublist)
17085 {
17086   face startsub, neighsub;
17087   face checkseg;
17088   point pa, pb, pc;
17089   REAL sign, ori;
17090   int i, j;
17091 
17092   // First infect subfaces in 'cavsublist'.
17093   for (i = 0; i < cavsublist->len(); i++) {
17094     startsub = * (face *)(* cavsublist)[i];
17095     sinfect(startsub);
17096   }
17097   // Find the other subfaces by a broadth-first searching.
17098   for (i = 0; i < cavsublist->len(); i++) {
17099     startsub = * (face *)(* cavsublist)[i];
17100     for (j = 0; j < 3; j++) {
17101       sspivot(startsub, checkseg);
17102       // Is there a segment?
17103       if (checkseg.sh == dummysh) {
17104         // No segment. Get the neighbor.
17105         spivot(startsub, neighsub);
17106         if (!sinfected(neighsub)) {
17107           pa = sorg(neighsub);
17108           pb = sdest(neighsub);
17109           pc = sapex(neighsub);
17110           sign = insphere(pa, pb, pc, abovepoint, newpoint);
17111           ori = orient3d(pa, pb, pc, abovepoint);
17112           if (sign != 0.0) {
17113             // Correct the sign.
17114             sign = ori > 0.0 ? sign : -sign;
17115           }
17116           if (sign > 0.0) {
17117             // neighsub is encroached by newpoint.
17118             sinfect(neighsub);
17119             cavsublist->append(&neighsub);
17120           }
17121         }
17122       }
17123       senextself(startsub);
17124     }
17125   }
17126   // Having found all subfaces, uninfect them before return.
17127   for (i = 0; i < cavsublist->len(); i++) {
17128     startsub = * (face *)(* cavsublist)[i];
17129     suninfect(startsub);
17130   }
17131 }
17132 
17134 //                                                                           //
17135 // collectvisiblesubs()    Collect convex hull edges which are visible from  //
17136 //                         the inserting point. Construct new subfaces from  //
17137 //                         these edges and the point.                        //
17138 //                                                                           //
17139 // Let T be the current Delaunay triangulation (of vertices of a facet F).   //
17140 // 'shmark', the index of F in 'in->facetlist' (starts from 1);  'inspoint'  //
17141 // lies outside of T; 'horiz' is a hull edge of T which is visible by it.    //
17142 //                                                                           //
17144 
17145 void tetgenmesh::collectvisiblesubs(int shmark, point inspoint, face* horiz,
17146   queue* flipqueue)
17147 {
17148   face newsh, hullsh;
17149   face rightsh, leftsh, spinedge;
17150   point horg, hdest;
17151   bool aboveflag;
17152   REAL ori, sign;
17153 
17154   // Get the sign of abovepoint (so we can assume it is above the plane).
17155   adjustedgering(*horiz, CCW);
17156   horg = sorg(*horiz);
17157   hdest = sdest(*horiz);
17158   ori = orient3d(horg, hdest, sapex(*horiz), abovepoint);
17159   sign = ori > 0.0 ? -1 : 1;
17160 
17161   // Create a new subface above 'horiz'.
17162   makeshellface(subfaces, &newsh);
17163   setsorg(newsh, hdest);
17164   setsdest(newsh, horg);
17165   setsapex(newsh, inspoint);
17166   setshellmark(newsh, shmark);
17167   if (b->quality && varconstraint) {
17168     setareabound(newsh, areabound(*horiz));
17169   }
17170   if (checkpbcs) {
17171     setshellpbcgroup(newsh, shellpbcgroup(*horiz));
17172   }
17173   // Make the connection.
17174   sbond(newsh, *horiz);
17175   // 'horiz' becomes interior edge.
17176   enqueueflipedge(*horiz, flipqueue);
17177 
17178   // Finish the hull edges at the right side of the newsh.
17179   hullsh = *horiz;
17180   while (1) {
17181     senext(newsh, rightsh);
17182     // Get the right hull edge of 'horiz' by spinning inside edges around
17183     //   'horg' until reaching the 'dummysh'.
17184     spinedge = hullsh;
17185     do {
17186       hullsh = spinedge;
17187       senext2self(hullsh);
17188       spivot(hullsh, spinedge);
17189       if (spinedge.sh == dummysh) break;
17190       if (sorg(spinedge) != horg) sesymself(spinedge);
17191       assert(sorg(spinedge) == horg);
17192     } while (true);
17193     horg = sorg(hullsh);
17194     // Test whether 'inspoint' is visible by 'hullsh'.
17195     ori = orient3d(horg, sdest(hullsh), abovepoint, inspoint);
17196     ori *= sign;
17197     aboveflag = ori < 0.0;
17198     if (aboveflag) {
17199       // It's visible.
17200       makeshellface(subfaces, &newsh);
17201       setsorg(newsh, sdest(hullsh));
17202       setsdest(newsh, horg);
17203       setsapex(newsh, inspoint);
17204       setshellmark(newsh, shmark);
17205       if (b->quality && varconstraint) {
17206         setareabound(newsh, areabound(hullsh));
17207       }
17208       if (checkpbcs) {
17209         setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17210       }
17211       // Make the connection.
17212       sbond(newsh, hullsh);
17213       senext2(newsh, leftsh);
17214       sbond(leftsh, rightsh);
17215       // 'hullsh' becomes interior edge.
17216       enqueueflipedge(hullsh, flipqueue);
17217     } else {
17218       // 'rightsh' is a new hull edge.
17219       dummysh[0] = sencode(rightsh);
17220       break;
17221     }
17222   }
17223 
17224   // Finish the hull edges at the left side of the newsh.
17225   hullsh = *horiz;
17226   spivot(*horiz, newsh);
17227   while (1) {
17228     senext2(newsh, leftsh);
17229     // Get the left hull edge of 'horiz' by spinning edges around 'hdest'.
17230     spinedge = hullsh;
17231     do {
17232       hullsh = spinedge;
17233       senextself(hullsh);
17234       spivot(hullsh, spinedge);
17235       if (spinedge.sh == dummysh) break;
17236       if (sdest(spinedge) != hdest) sesymself(spinedge);
17237       assert(sdest(spinedge) == hdest);
17238     } while (true);
17239     // Update 'hdest'.
17240     hdest = sdest(hullsh);
17241     // Test whether 'inspoint' is visible from 'hullsh'.
17242     ori = orient3d(sorg(hullsh), hdest, abovepoint, inspoint);
17243     ori *= sign;
17244     aboveflag = ori < 0.0;
17245     if (aboveflag) {
17246       // It's a visible hull edge.
17247       makeshellface(subfaces, &newsh);
17248       setsorg(newsh, hdest);
17249       setsdest(newsh, sorg(hullsh));
17250       setsapex(newsh, inspoint);
17251       setshellmark(newsh, shmark);
17252       if (b->quality && varconstraint) {
17253         setareabound(newsh, areabound(hullsh));
17254       }
17255       if (checkpbcs) {
17256         setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17257       }
17258       // Make the connection.
17259       sbond(newsh, hullsh);
17260       senext(newsh, rightsh);
17261       sbond(rightsh, leftsh);
17262       // 'horiz' becomes interior edge.
17263       enqueueflipedge(hullsh, flipqueue);
17264     } else {
17265       // 'leftsh' is a new hull edge.
17266       dummysh[0] = sencode(leftsh);
17267       break;
17268     }
17269   }
17270 }
17271 
17273 //                                                                           //
17274 // incrflipdelaunaysub()    Create a DT from a 3D coplanar point set using   //
17275 //                          the incremental flip algorithm.                  //
17276 //                                                                           //
17277 // Let T be the current Delaunay triangulation (of vertices of a facet F).   //
17278 // 'shmark', the index of F in 'in->facetlist' (starts from 1).              //
17279 //                                                                           //
17281 
17282 void tetgenmesh::incrflipdelaunaysub(int shmark, REAL eps, list* ptlist,
17283   int holes, REAL* holelist, queue* flipque)
17284 {
17285   face newsh, startsh;
17286   point *insertarray;
17287   point swappt;
17288   pbcdata *pd;
17289   enum locateresult loc;
17290   REAL det, area;
17291   bool aboveflag;
17292   int arraysize;
17293   int epscount;
17294   int fmarker;
17295   int idx, i, j, k;
17296 
17297   // Get the point array (saved in 'ptlist').
17298   insertarray = (point *) ptlist->base;
17299   arraysize = ptlist->len();
17300   if (arraysize < 3) return;
17301 
17302   // Do calculation of 'abovepoint' if number of points > 3.
17303   aboveflag = (arraysize > 3);
17304 
17305   // The initial triangulation T only has one triangle formed by 3 not
17306   //   cillinear points of the set V = 'insertarray'. The first point:
17307   //   a = insertarray[0].
17308 
17309   epscount = 0;
17310   while (true) {
17311   for (i = 1; i < arraysize; i++) {
17312     det = distance(insertarray[0], insertarray[i]);
17313     if (det > (longest * eps)) break;
17314   }
17315   if (i < arraysize) {
17316     // Swap to move b from index i to index 1.
17317     swappt = insertarray[i];
17318     insertarray[i] = insertarray[1];
17319     insertarray[1] = swappt;
17320   }
17321   // Get the third point c, that is not collinear with a and b.
17322   for (i++; i < arraysize; i++) {
17323     if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
17324       break;
17325   }
17326   if (i < arraysize) {
17327     // Swap to move c from index i to index 2.
17328     swappt = insertarray[i];
17329     insertarray[i] = insertarray[2];
17330     insertarray[2] = swappt;
17331     i = 3; // The next inserting point.
17332   } else {
17333     // The set of vertices is not good (or nearly degenerate).  However,
17334     //   a trivial triangulation can be formed (using 3 vertices). It may
17335     //   be corrected (or deleted) by mergefacet().
17336     if ((eps == 0.0) || (epscount > 16)) {
17337       printf("Error:  Invalid PLC.\n");
17338       printf("  Facet (%d, %d, %d", pointmark(insertarray[0]),
17339              pointmark(insertarray[1]), pointmark(insertarray[2]));
17340       if (ptlist->len() > 3) {
17341         printf(", ...");
17342       }
17343       printf(") (%d) is not a valid polygon.\n", shmark);
17344       terminatetetgen(1);
17345     }
17346     // Decrease the eps, and continue to try.
17347     eps *= 1e-2;
17348     epscount++;
17349     continue;
17350   }
17351   break;
17352   } // while (true);
17353 
17354   // Create the initial triangle.
17355   makeshellface(subfaces, &newsh);
17356   setsorg(newsh, insertarray[0]);
17357   setsdest(newsh, insertarray[1]);
17358   setsapex(newsh, insertarray[2]);
17359   // Remeber the facet it belongs to.
17360   setshellmark(newsh, shmark);
17361   // Set vertex type be FREESUBVERTEX if it has no type yet.
17362   if (pointtype(insertarray[0]) == FREEVOLVERTEX) {
17363     setpointtype(insertarray[0], FREESUBVERTEX);
17364   }
17365   if (pointtype(insertarray[1]) == FREEVOLVERTEX) {
17366     setpointtype(insertarray[1], FREESUBVERTEX);
17367   }
17368   if (pointtype(insertarray[2]) == FREEVOLVERTEX) {
17369     setpointtype(insertarray[2], FREESUBVERTEX);
17370   }
17371   // Let 'dummysh' point to it (for point location).
17372   dummysh[0] = sencode(newsh);
17373 
17374   // Are there area constraints?
17375   if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
17376     idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker.
17377     for (k = 0; k < in->numberoffacetconstraints; k++) {
17378       fmarker = (int) in->facetconstraintlist[k * 2];
17379       if (fmarker == idx) {
17380         area = in->facetconstraintlist[k * 2 + 1];
17381         setareabound(newsh, area);
17382         break;
17383       }
17384     }
17385   }
17386 
17387   // Are there pbc conditions?
17388   if (checkpbcs) {
17389     idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker.
17390     for (k = 0; k < in->numberofpbcgroups; k++) {
17391       pd = &subpbcgrouptable[k];
17392       for (j = 0; j < 2; j++) {
17393         if (pd->fmark[j] == idx) {
17394           setshellpbcgroup(newsh, k);
17395           pd->ss[j] = newsh;
17396         }
17397       }
17398     }
17399   }
17400 
17401   if (aboveflag) {
17402     // Compute the 'abovepoint' for orient3d().
17403     abovepoint = facetabovepointarray[shmark];
17404     if (abovepoint == (point) NULL) {
17405       getfacetabovepoint(&newsh);
17406     }
17407   }
17408 
17409   if (holes > 0) {
17410     // Project hole points onto the plane containing the facet.
17411     REAL prj[3];
17412     for (k = 0; k < holes; k++) {
17413       projpt2face(&(holelist[k * 3]), insertarray[0], insertarray[1],
17414                   insertarray[2], prj);
17415       for (j = 0; j < 3; j++) holelist[k * 3 + j] = prj[j];
17416     }
17417   }
17418 
17419   // Incrementally insert the rest of points into T.
17420   for (; i < arraysize; i++) {
17421     // Insert p_i.
17422     startsh.sh = dummysh;
17423     loc = locatesub(insertarray[i], &startsh, 0, 0.0);
17424     if (loc == ONFACE) {
17425       splitsubface(insertarray[i], &startsh, flipque);
17426     } else if (loc == ONEDGE) {
17427       splitsubedge(insertarray[i], &startsh, flipque);
17428     } else if (loc == OUTSIDE) {
17429       collectvisiblesubs(shmark, insertarray[i], &startsh, flipque);
17430     } else if (loc == ONVERTEX) {
17431       // !should not happen!
17432     }
17433     // Set p_i's type FREESUBVERTEX if it has no type yet.
17434     if (pointtype(insertarray[i]) == FREEVOLVERTEX) {
17435       setpointtype(insertarray[i], FREESUBVERTEX);
17436     }
17437     flipsub(flipque);
17438   }
17439 }
17440 
17442 //                                                                           //
17443 // finddirectionsub()    Find the first subface in a facet on the path from  //
17444 //                       one point to another.                               //
17445 //                                                                           //
17446 // Finds the subface in the facet that intersects a line segment drawn from  //
17447 // the origin of `searchsh' to the point `tend', and returns the result in   //
17448 // `searchsh'.  The origin of `searchsh' does not change,  even though the   //
17449 // subface returned may differ from the one passed in.                       //
17450 //                                                                           //
17451 // The return value notes whether the destination or apex of the found face  //
17452 // is collinear with the two points in question.                             //
17453 //                                                                           //
17455 
17456 enum tetgenmesh::finddirectionresult tetgenmesh::finddirectionsub(
17457   face* searchsh, point tend)
17458 {
17459   face checksh;
17460   point startpoint, leftpoint, rightpoint;
17461   REAL leftccw, rightccw;
17462   REAL ori, sign;
17463   int leftflag, rightflag;
17464 
17465   startpoint = sorg(*searchsh);
17466   // Find the sign to simulate that abovepoint is 'above' the facet.
17467   adjustedgering(*searchsh, CCW);
17468   // Make sure 'startpoint' is the origin.
17469   if (sorg(*searchsh) != startpoint) senextself(*searchsh);
17470   rightpoint = sdest(*searchsh);
17471   leftpoint = sapex(*searchsh);
17472   ori = orient3d(startpoint, rightpoint, leftpoint, abovepoint);
17473   sign = ori > 0.0 ? -1 : 1;
17474 
17475   // Is `tend' to the left?
17476   ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17477   leftccw = ori * sign;
17478   leftflag = leftccw > 0.0;
17479   // Is `tend' to the right?
17480   ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17481   rightccw = ori * sign;
17482   rightflag = rightccw > 0.0;
17483   if (leftflag && rightflag) {
17484     // `searchsh' faces directly away from `tend'.  We could go left or
17485     //   right.  Ask whether it's a triangle or a boundary on the left.
17486     senext2(*searchsh, checksh);
17487     spivotself(checksh);
17488     if (checksh.sh == dummysh) {
17489       leftflag = 0;
17490     } else {
17491       rightflag = 0;
17492     }
17493   }
17494   while (leftflag) {
17495     // Turn left until satisfied.
17496     senext2self(*searchsh);
17497     spivotself(*searchsh);
17498     if (searchsh->sh == dummysh) {
17499       printf("Internal error in finddirectionsub():  Unable to find a\n");
17500       printf("  subface leading from %d to %d.\n", pointmark(startpoint),
17501              pointmark(tend));
17502       internalerror();
17503     }
17504     if (sorg(*searchsh) != startpoint) sesymself(*searchsh);
17505     assert(sorg(*searchsh) == startpoint);
17506     leftpoint = sapex(*searchsh);
17507     rightccw = leftccw;
17508     ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17509     leftccw = ori * sign;
17510     leftflag = leftccw > 0.0;
17511   }
17512   while (rightflag) {
17513     // Turn right until satisfied.
17514     spivotself(*searchsh);
17515     if (searchsh->sh == dummysh) {
17516       printf("Internal error in finddirectionsub():  Unable to find a\n");
17517       printf("  subface leading from %d to %d.\n", pointmark(startpoint),
17518              pointmark(tend));
17519       internalerror();
17520     }
17521     if (sdest(*searchsh) != startpoint) sesymself(*searchsh);
17522     assert(sdest(*searchsh) == startpoint);
17523     senextself(*searchsh);
17524     rightpoint = sdest(*searchsh);
17525     leftccw = rightccw;
17526     ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17527     rightccw = ori * sign;
17528     rightflag = rightccw > 0.0;
17529   }
17530   if (leftccw == 0.0) {
17531     return LEFTCOLLINEAR;
17532   } else if (rightccw == 0.0) {
17533     return RIGHTCOLLINEAR;
17534   } else {
17535     return ACROSSEDGE;
17536   }
17537 }
17538 
17540 //                                                                           //
17541 // insertsubseg()    Create a subsegment and insert it between two subfaces. //
17542 //                                                                           //
17543 // The new subsegment ab is inserted at the edge of subface 'tri'.  If ab is //
17544 // not a hull edge, it is inserted between two subfaces.  If 'tri' is a hull //
17545 // face, the initial face ring of ab will be set only one face which is self-//
17546 // bonded.  The final face ring will be constructed in 'unifysegments()'.    //
17547 //                                                                           //
17549 
17550 void tetgenmesh::insertsubseg(face* tri)
17551 {
17552   face oppotri;
17553   face newsubseg;
17554   point pa, pb;
17555   REAL len;
17556   int e1, e2;
17557   int i;
17558 
17559   // Check if there's already a subsegment here.
17560   sspivot(*tri, newsubseg);
17561   if (newsubseg.sh == dummysh) {
17562     // Make new subsegment and initialize its vertices.
17563     makeshellface(subsegs, &newsubseg);
17564     pa = sorg(*tri);
17565     pb = sdest(*tri);
17566     setsorg(newsubseg, pa);
17567     setsdest(newsubseg, pb);
17568     // Are there length constraints?
17569     if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
17570       for (i = 0; i < in->numberofsegmentconstraints; i++) {
17571         e1 = (int) in->segmentconstraintlist[i * 3];
17572         e2 = (int) in->segmentconstraintlist[i * 3 + 1];
17573         if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
17574             ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
17575           len = in->segmentconstraintlist[i * 3 + 2];
17576           setareabound(newsubseg, len);
17577           break;
17578         }
17579       }
17580     }
17581     // Bond new subsegment to the two subfaces it is sandwiched between.
17582     ssbond(*tri, newsubseg);
17583     spivot(*tri, oppotri);
17584     // 'oppotri' might be "out space".
17585     if (oppotri.sh != dummysh) {
17586       ssbond(oppotri, newsubseg);
17587     } /* else {
17588       // Outside! Bond '*tri' to itself.
17589       sbond(*tri, *tri);
17590     } */
17591   }
17592 }
17593 
17595 //                                                                           //
17596 // scoutsegmentsub()    Scout the first triangle on the path from one point  //
17597 //                      to another, and check for completion (reaching the   //
17598 //                      second point), a collinear point,or the intersection //
17599 //                      of two segments.                                     //
17600 //                                                                           //
17601 // Returns true if the entire segment is successfully inserted, and false if //
17602 // the job must be finished by constrainededge().                            //
17603 //                                                                           //
17605 
17606 bool tetgenmesh::scoutsegmentsub(face* searchsh, point tend)
17607 {
17608   face newsubseg;
17609   face crosssub, crosssubseg;
17610   point leftpoint, rightpoint;
17611   enum finddirectionresult collinear;
17612 
17613   collinear = finddirectionsub(searchsh, tend);
17614   rightpoint = sdest(*searchsh);
17615   leftpoint = sapex(*searchsh);
17616   if (rightpoint == tend || leftpoint == tend) {
17617     // The segment is already an edge.
17618     if (leftpoint == tend) {
17619       senext2self(*searchsh);
17620     }
17621     // Insert a subsegment.
17622     insertsubseg(searchsh);
17623     return true;
17624   } else if (collinear == LEFTCOLLINEAR) {
17625     // We've collided with a vertex between the segment's endpoints.
17626     // Make the collinear vertex be the triangle's origin.
17627     senextself(*searchsh); // lprevself(*searchtri);
17628     // Insert a subsegment.
17629     insertsubseg(searchsh);
17630     // Insert the remainder of the segment.
17631     return scoutsegmentsub(searchsh, tend);
17632   } else if (collinear == RIGHTCOLLINEAR) {
17633     // We've collided with a vertex between the segment's endpoints.
17634     // Insert a subsegment.
17635     insertsubseg(searchsh);
17636     // Make the collinear vertex be the triangle's origin.
17637     senextself(*searchsh); // lnextself(*searchtri);
17638     // Insert the remainder of the segment.
17639     return scoutsegmentsub(searchsh, tend);
17640   } else {
17641     senext(*searchsh, crosssub); // lnext(*searchtri, crosstri);
17642     // Check for a crossing segment.
17643     sspivot(crosssub, crosssubseg);
17644 #ifdef SELF_CHECK
17645     assert(crosssubseg.sh == dummysh);
17646 #endif
17647     return false;
17648   }
17649 }
17650 
17652 //                                                                           //
17653 // flipedgerecursive()    Flip an edge.                                      //
17654 //                                                                           //
17655 // This is a support routine for inserting segments into a CDT.              //
17656 //                                                                           //
17657 // Let 'flipedge' be ab, and two triangles abc, abd share at it.  ab may not //
17658 // flipable if the four vertices a, b, c, and d are non-convex. If it is the //
17659 // case, recursively flip ad or bd. Return when ab is flipped.               //
17660 //                                                                           //
17662 
17663 void tetgenmesh::flipedgerecursive(face* flipedge, queue* flipqueue)
17664 {
17665   face fixupsh;
17666   point pa, pb, pc, pd;
17667   REAL oria, orib;
17668   bool doflip;
17669 
17670   pa = sorg(*flipedge);
17671   pb = sdest(*flipedge);
17672   pc = sapex(*flipedge);
17673   do {
17674     spivot(*flipedge, fixupsh);
17675     pd = sapex(fixupsh);
17676     oria = orient3d(pc, pd, abovepoint, pa);
17677     orib = orient3d(pc, pd, abovepoint, pb);
17678     doflip = (oria * orib < 0.0);
17679     if (doflip) {
17680       // Flip the edge (a, b) away.
17681       flip22sub(flipedge, flipqueue);
17682       // Fix flipedge on edge e (c, d).
17683       findedge(flipedge, pc, pd);
17684     } else {
17685       // ab is unflipable. Get the next edge (bd, or da) to flip.
17686       if (sorg(fixupsh) != pb) sesymself(fixupsh);
17687       assert(sdest(fixupsh) == pa);
17688       if (fabs(oria) > fabs(orib)) {
17689         // acd has larger area. Choose da.
17690         senextself(fixupsh);
17691       } else {
17692         // bcd has larger area. Choose bd.
17693         senext2self(fixupsh);
17694       }
17695       // Flip the edge.
17696       flipedgerecursive(&fixupsh, flipqueue);
17697     }
17698   } while (!doflip);
17699 }
17700 
17702 //                                                                           //
17703 // constrainededge()    Force a segment into a CDT.                          //
17704 //                                                                           //
17705 // The segment s is recovered by flipping away the edges it intersects, and  //
17706 // triangulating the polygons that form on each side of it.                  //
17707 //                                                                           //
17708 // Generates a single subsegment connecting `tstart' to `tend'. The triangle //
17709 // `startsh' has `tstart' as its origin.                                     //
17710 //                                                                           //
17712 
17713 void tetgenmesh::constrainededge(face* startsh, point tend, queue* flipqueue)
17714 {
17715   point tstart, tright, tleft;
17716   REAL rori, lori;
17717   bool collision;
17718 
17719   tstart = sorg(*startsh);
17720   do {
17721     // Loop edges oppo to tstart until find one crosses the segment.
17722     do {
17723       tright = sdest(*startsh);
17724       tleft = sapex(*startsh);
17725       // Is edge (tright, tleft) corss the segment.
17726       rori = orient3d(tstart, tright, abovepoint, tend);
17727       collision = (rori == 0.0);
17728       if (collision) break; // tright is on the segment.
17729       lori = orient3d(tstart, tleft, abovepoint, tend);
17730       collision = (lori == 0.0);
17731       if (collision) { //  tleft is on the segment.
17732         senext2self(*startsh);
17733         break;
17734       }
17735       if (rori * lori < 0.0) break; // Find the crossing edge.
17736       // Both points are at one side of the segment.
17737       finddirectionsub(startsh, tend);
17738     } while (true);
17739     if (collision) break;
17740     // Get the neighbor face at edge e (tright, tleft).
17741     senextself(*startsh);
17742     // Flip the crossing edge.
17743     flipedgerecursive(startsh, flipqueue);
17744     // After flip, sorg(*startsh) == tstart.
17745     assert(sorg(*startsh) == tstart);
17746   } while (sdest(*startsh) != tend);
17747 
17748   // Insert a subsegment to make the segment permanent.
17749   insertsubseg(startsh);
17750   // If there was a collision with an interceding vertex, install another
17751   //   segment connecting that vertex with endpoint2.
17752   if (collision) {
17753     // Insert the remainder of the segment.
17754     if (!scoutsegmentsub(startsh, tend)) {
17755       constrainededge(startsh, tend, flipqueue);
17756     }
17757   }
17758 }
17759 
17761 //                                                                           //
17762 // recoversegment()    Recover a segment in the surface triangulation.       //
17763 //                                                                           //
17765 
17766 void tetgenmesh::recoversegment(point tstart, point tend, queue* flipqueue)
17767 {
17768   face searchsh;
17769 
17770   if (b->verbose > 2) {
17771     printf("    Insert seg (%d, %d).\n", pointmark(tstart), pointmark(tend));
17772   }
17773 
17774   // Find a triangle whose origin is the segment's first endpoint.
17775   searchsh.sh = dummysh;
17776   // Search for the segment's first endpoint by point location.
17777   if (locatesub(tstart, &searchsh, 0, 0.0) != ONVERTEX) {
17778     // Possibly caused by a degenerate subface. Do a brute-force search.
17779     list *newshlist;
17780     int i, j;
17781     newshlist = new list(sizeof(face), NULL, 256);
17782     // Get new subfaces, do not remove protected segments.
17783     retrievenewsubs(newshlist, false);
17784     // Search for a sub contain tstart.
17785     for (i = 0; i < newshlist->len(); i++) {
17786       searchsh = * (face *)(* newshlist)[i];
17787       for (j = 0; j < 3; j++) {
17788         if (sorg(searchsh) == tstart) break;
17789         senextself(searchsh);
17790       }
17791       if (j < 3) break;
17792     }
17793     delete newshlist;
17794     if (sorg(searchsh) != tstart) {
17795       printf("Internal error in recoversegment():  Vertex location failed.\n");
17796       internalerror();
17797     }
17798   }
17799   // Scout the segment and insert it if it is found.
17800   if (scoutsegmentsub(&searchsh, tend)) {
17801     // The segment was easily inserted.
17802     return;
17803   }
17804   // Insert the segment into the triangulation by flips.
17805   constrainededge(&searchsh, tend, flipqueue);
17806   // Some edges may need flipping.
17807   flipsub(flipqueue);
17808 }
17809 
17811 //                                                                           //
17812 // infecthullsub()    Virally infect all of the triangles of the convex hull //
17813 //                    that are not protected by subsegments.                 //
17814 //                                                                           //
17816 
17817 void tetgenmesh::infecthullsub(memorypool* viri)
17818 {
17819   face hulltri, nexttri, starttri;
17820   face hullsubseg;
17821   shellface **deadshellface;
17822 
17823   // Find a triangle handle on the hull.
17824   hulltri.sh = dummysh;
17825   hulltri.shver = 0;
17826   spivotself(hulltri);
17827   adjustedgering(hulltri, CCW);
17828   // Remember where we started so we know when to stop.
17829   starttri = hulltri;
17830   // Go once counterclockwise around the convex hull.
17831   do {
17832     // Ignore triangles that are already infected.
17833     if (!sinfected(hulltri)) {
17834       // Is the triangle protected by a subsegment?
17835       sspivot(hulltri, hullsubseg);
17836       if (hullsubseg.sh == dummysh) {
17837         // The triangle is not protected; infect it.
17838         if (!sinfected(hulltri)) {
17839           sinfect(hulltri);
17840           deadshellface = (shellface **) viri->alloc();
17841           *deadshellface = hulltri.sh;
17842         }
17843       }
17844     }
17845     // To find the next hull edge, go clockwise around the next vertex.
17846     senextself(hulltri); // lnextself(hulltri);
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     while (nexttri.sh != dummysh) {
17855       hulltri = nexttri;
17856       spivot(hulltri, nexttri); // oprev(hulltri, nexttri);
17857       if (nexttri.sh == hulltri.sh) {
17858         nexttri.sh = dummysh;  // 'hulltri' is self-bonded.
17859       } else {
17860         adjustedgering(nexttri, CCW);
17861         senextself(nexttri);
17862       }
17863     }
17864   } while (hulltri != starttri);
17865 }
17866 
17868 //                                                                           //
17869 // plaguesub()    Spread the virus from all infected triangles to any        //
17870 //                neighbors not protected by subsegments.  Delete all        //
17871 //                infected triangles.                                        //
17872 //                                                                           //
17873 // This is the procedure that actually creates holes and concavities.        //
17874 //                                                                           //
17876 
17877 void tetgenmesh::plaguesub(memorypool* viri)
17878 {
17879   face testtri, neighbor, ghostsh;
17880   face neighborsubseg;
17881   shellface **virusloop;
17882   shellface **deadshellface;
17883   int i;
17884 
17885   // Loop through all the infected triangles, spreading the virus to
17886   //   their neighbors, then to their neighbors' neighbors.
17887   viri->traversalinit();
17888   virusloop = (shellface **) viri->traverse();
17889   while (virusloop != (shellface **) NULL) {
17890     testtri.sh = *virusloop;
17891     // Check each of the triangle's three neighbors.
17892     for (i = 0; i < 3; i++) {
17893       // Find the neighbor.
17894       spivot(testtri, neighbor);
17895       // Check for a subsegment between the triangle and its neighbor.
17896       sspivot(testtri, neighborsubseg);
17897       // Check if the neighbor is nonexistent or already infected.
17898       if ((neighbor.sh == dummysh) || sinfected(neighbor)) {
17899         if (neighborsubseg.sh != dummysh) {
17900           // There is a subsegment separating the triangle from its
17901           //   neighbor, but both triangles are dying, so the subsegment
17902           //   dies too.
17903           shellfacedealloc(subsegs, neighborsubseg.sh);
17904           if (neighbor.sh != dummysh) {
17905             // Make sure the subsegment doesn't get deallocated again
17906             //   later when the infected neighbor is visited.
17907             ssdissolve(neighbor);
17908           }
17909         }
17910       } else {                   // The neighbor exists and is not infected.
17911         if (neighborsubseg.sh == dummysh) {
17912           // There is no subsegment protecting the neighbor, so the
17913           //   neighbor becomes infected.
17914           sinfect(neighbor);
17915           // Ensure that the neighbor's neighbors will be infected.
17916           deadshellface = (shellface **) viri->alloc();
17917           *deadshellface = neighbor.sh;
17918         } else {               // The neighbor is protected by a subsegment.
17919           // Remove this triangle from the subsegment.
17920           ssbond(neighbor, neighborsubseg);
17921         }
17922       }
17923       senextself(testtri);
17924     }
17925     virusloop = (shellface **) viri->traverse();
17926   }
17927 
17928   ghostsh.sh = dummysh; // A handle of outer space.
17929   viri->traversalinit();
17930   virusloop = (shellface **) viri->traverse();
17931   while (virusloop != (shellface **) NULL) {
17932     testtri.sh = *virusloop;
17933     // Record changes in the number of boundary edges, and disconnect
17934     //   dead triangles from their neighbors.
17935     for (i = 0; i < 3; i++) {
17936       spivot(testtri, neighbor);
17937       if (neighbor.sh != dummysh) {
17938         // Disconnect the triangle from its neighbor.
17939         // sdissolve(neighbor);
17940         sbond(neighbor, ghostsh);
17941       }
17942       senextself(testtri);
17943     }
17944     // Return the dead triangle to the pool of triangles.
17945     shellfacedealloc(subfaces, testtri.sh);
17946     virusloop = (shellface **) viri->traverse();
17947   }
17948   // Empty the virus pool.
17949   viri->restart();
17950 }
17951 
17953 //                                                                           //
17954 // carveholessub()    Find the holes and infect them.  Find the area         //
17955 //                    constraints and infect them.  Infect the convex hull.  //
17956 //                    Spread the infection and kill triangles.  Spread the   //
17957 //                    area constraints.                                      //
17958 //                                                                           //
17959 // This routine mainly calls other routines to carry out all these functions.//
17960 //                                                                           //
17962 
17963 void tetgenmesh::carveholessub(int holes, REAL* holelist, memorypool *viri)
17964 {
17965   face searchtri, triangleloop;
17966   shellface **holetri;
17967   enum locateresult intersect;
17968   int i;
17969 
17970   // Mark as infected any unprotected triangles on the boundary.
17971   //   This is one way by which concavities are created.
17972   infecthullsub(viri);
17973 
17974   if (holes > 0) {
17975     // Infect each triangle in which a hole lies.
17976     for (i = 0; i < 3 * holes; i += 3) {
17977       // Ignore holes that aren't within the bounds of the mesh.
17978       if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
17979           && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)
17980           && (holelist[i + 2] >= zmin) && (holelist[i + 2] <= zmax)) {
17981         // Start searching from some triangle on the outer boundary.
17982         searchtri.sh = dummysh;
17983         // Find a triangle that contains the hole.
17984         intersect = locatesub(&holelist[i], &searchtri, 0, 0.0);
17985         if ((intersect != OUTSIDE) && (!sinfected(searchtri))) {
17986           // Infect the triangle.  This is done by marking the triangle
17987           //   as infected and including the triangle in the virus pool.
17988           sinfect(searchtri);
17989           holetri = (shellface **) viri->alloc();
17990           *holetri = searchtri.sh;
17991         }
17992       }
17993     }
17994   }
17995 
17996   if (viri->items > 0) {
17997     // Carve the holes and concavities.
17998     plaguesub(viri);
17999   }
18000   // The virus pool should be empty now.
18001 }
18002 
18004 //                                                                           //
18005 // triangulate()    Triangulate a PSLG into a CDT.                           //
18006 //                                                                           //
18007 // A Planar Straight Line Graph (PSLG) P is actually a 2D polygonal region,  //
18008 // possibly contains holes, segments and vertices in its interior. P is tri- //
18009 // angulated into a set of _subfaces_ forming a CDT of P.                    //
18010 //                                                                           //
18011 // The vertices and segments of P are found in 'ptlist' and 'conlist', resp- //
18012 // ectively. 'holelist' contains a list of hole points. 'shmark' will be set //
18013 // to all subfaces of P.                                                     //
18014 //                                                                           //
18015 // The CDT is created directly in the pools 'subfaces' and 'subsegs'. It can //
18016 // be retrived by a broadth-first searching starting from 'dummysh[0]'(debug //
18017 // function 'outsurfmesh()' does it).                                        //
18018 //                                                                           //
18020 
18021 void tetgenmesh::triangulate(int shmark, REAL eps, list* ptlist, list* conlist,
18022   int holes, REAL* holelist, memorypool* viri, queue* flipqueue)
18023 {
18024   face newsh;
18025   point *cons;
18026   int i;
18027 
18028   if (b->verbose > 1) {
18029     printf("    %d vertices, %d segments", ptlist->len(), conlist->len());
18030     if (holes > 0) {
18031       printf(", %d holes", holes);
18032     }
18033     printf(", shmark: %d.\n", shmark);
18034   }
18035 
18036   // Create the DT of V by the 2D incremental flip algorithm.
18037   incrflipdelaunaysub(shmark, eps, ptlist, holes, holelist, flipqueue);
18038   // Recover boundary edges.
18039   if (ptlist->len() > 3) {
18040     // Insert segments into the DT.
18041     for (i = 0; i < conlist->len(); i++) {
18042       cons = (point *)(* conlist)[i];
18043       recoversegment(cons[0], cons[1], flipqueue);
18044     }
18045     // Carve holes and concavities.
18046     carveholessub(holes, holelist, viri);
18047   } else if (ptlist->len() == 3) {
18048     // Insert 3 segments directly.
18049     newsh.sh = dummysh;
18050     newsh.shver = 0;
18051     spivotself(newsh);
18052     for (i = 0; i < 3; i++) {
18053       insertsubseg(&newsh);
18054       senextself(newsh);
18055     }
18056   } else if (ptlist->len() == 2) {
18057     // This facet is actually a segment. It is not support by the mesh data
18058     //   strcuture. Hence the segment will not be maintained in the mesh.
18059     //   However, during segment recovery, the segment can be processed.
18060     cons = (point *)(* conlist)[0];
18061     makeshellface(subsegs, &newsh);
18062     setsorg(newsh, cons[0]);
18063     setsdest(newsh, cons[1]);
18064   }
18065 }
18066 
18068 //                                                                           //
18069 // retrievenewsubs()    Retrieve newly created subfaces.                     //
18070 //                                                                           //
18071 // The new subfaces created by triangulate() can be found by a broadth-first //
18072 // searching starting from 'dummysh[0]'.                                     //
18073 //                                                                           //
18074 // 'newshlist' (empty on input) returns the retrieved subfaces. Each edge on //
18075 // the hull is bound to 'dummysh' and protected by a segment. If 'removeseg' //
18076 // is TRUE, the segment is removed.                                          //
18077 //                                                                           //
18079 
18080 void tetgenmesh::retrievenewsubs(list* newshlist, bool removeseg)
18081 {
18082   face startsh, neighsh;
18083   face deadseg;
18084   int i, j;
18085 
18086   // The first new subface is found at dummysh[0].
18087   startsh.sh = dummysh;
18088   startsh.shver = 0;
18089   spivotself(startsh);
18090   assert(startsh.sh != dummysh);
18091   sinfect(startsh);
18092   newshlist->append(&startsh);
18093 
18094   // Find the rest of new subfaces by a broadth-first searching.
18095   for (i = 0; i < newshlist->len(); i++) {
18096     // Get a new subface s.
18097     startsh = * (face *)(* newshlist)[i];
18098     for (j = 0; j < 3; j++) {
18099       spivot(startsh, neighsh);
18100       if (neighsh.sh != dummysh) {
18101         if (!sinfected(neighsh)) {
18102           // Discovered a new subface.
18103           sinfect(neighsh);
18104           newshlist->append(&neighsh);
18105         }
18106       } else {
18107         // Found a boundary edge.
18108         if (removeseg) {
18109           // This side of s may be protected by a segment.
18110           sspivot(startsh, deadseg);
18111           if (deadseg.sh != dummysh) {
18112             // Detach it from s.
18113             ssdissolve(startsh);
18114             // Delete the segment.
18115             shellfacedealloc(subsegs, deadseg.sh);
18116           }
18117         }
18118       }
18119       senextself(startsh);
18120     }
18121   }
18122   for (i = 0; i < newshlist->len(); i++) {
18123     startsh = * (face *)(* newshlist)[i];
18124     suninfect(startsh);
18125   }
18126 }
18127 
18129 //                                                                           //
18130 // unifysegments()    Unify identical segments and build facet connections.  //
18131 //                                                                           //
18132 // After creating the surface mesh. Each facet has its own segments.  There  //
18133 // are duplicated segments between adjacent facets.  This routine has three  //
18134 // purposes:                                                                 //
18135 //   (1) identify the set of segments which have the same endpoints and      //
18136 //       unify them into one segment, remove redundant ones;                 //
18137 //   (2) create the face rings of the unified segments, hence setup the      //
18138 //       connections between facets; and                                     //
18139 //   (3) set a unique marker (1-based) for each segment.                     //
18140 // On finish, each segment is unique and the face ring around it (right-hand //
18141 // rule) is constructed. The connections between facets-facets are setup.    //
18142 //                                                                           //
18144 
18145 void tetgenmesh::unifysegments()
18146 {
18147   list *sfacelist;
18148   shellface **facesperverlist;
18149   face subsegloop, testseg;
18150   face sface, sface1, sface2;
18151   point torg, tdest;
18152   REAL da1, da2;
18153   int *idx2facelist;
18154   int segmarker;
18155   int idx, k, m;
18156 
18157   if (b->verbose > 0) {
18158     printf("  Unifying segments.\n");
18159   }
18160 
18161   // Compute a mapping from indices of vertices to subfaces.
18162   makesubfacemap(idx2facelist, facesperverlist);
18163   // Initialize 'sfacelist' for constructing the face link of each segment.
18164   sfacelist = new list(sizeof(face), NULL);
18165 
18166   segmarker = 1;
18167   subsegs->traversalinit();
18168   subsegloop.sh = shellfacetraverse(subsegs);
18169   while (subsegloop.sh != (shellface *) NULL) {
18170     subsegloop.shver = 0; // For sure.
18171     torg = sorg(subsegloop);
18172     tdest = sdest(subsegloop);
18173     idx = pointmark(torg) - in->firstnumber;
18174     // Loop through the set of subfaces containing 'torg'.  Get all the
18175     //   subfaces containing the edge (torg, tdest). Save and order them
18176     //   in 'sfacelist', the ordering is defined by the right-hand rule
18177     //   with thumb points from torg to tdest.
18178     for (k = idx2facelist[idx]; k < idx2facelist[idx + 1]; k++) {
18179       sface.sh = facesperverlist[k];
18180       sface.shver = 0;
18181       // sface may be died due to the removing of duplicated subfaces.
18182       if (!isdead(&sface) && isfacehasedge(&sface, torg, tdest)) {
18183         // 'sface' contains this segment.
18184         findedge(&sface, torg, tdest);
18185         // Save it in 'sfacelist'.
18186         if (sfacelist->len() < 2) {
18187           sfacelist->append(&sface);
18188         } else {
18189           for (m = 0; m < sfacelist->len() - 1; m++) {
18190             sface1 = * (face *)(* sfacelist)[m];
18191             sface2 = * (face *)(* sfacelist)[m + 1];
18192             da1 = facedihedral(torg, tdest, sapex(sface1), sapex(sface));
18193             da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
18194             if (da1 < da2) {
18195               break;  // Insert it after m.
18196             }
18197           }
18198           sfacelist->insert(m + 1, &sface);
18199         }
18200       }
18201     }
18202     if (b->verbose > 1) {
18203       printf("    Identifying %d segments of (%d  %d).\n", sfacelist->len(),
18204              pointmark(torg), pointmark(tdest));
18205     }
18206     // Set the connection between this segment and faces containing it,
18207     //   at the same time, remove redundant segments.
18208     for (k = 0; k < sfacelist->len(); k++) {
18209       sface = *(face *)(* sfacelist)[k];
18210       sspivot(sface, testseg);
18211       // If 'testseg' is not 'subsegloop', it is a redundant segment that
18212       //   needs be removed. BE CAREFUL it may already be removed. Do not
18213       //   remove it twice, i.e., do test 'isdead()' together.
18214       if ((testseg.sh != subsegloop.sh) && !isdead(&testseg)) {
18215         shellfacedealloc(subsegs, testseg.sh);
18216       }
18217       // 'ssbond' bonds the subface and the segment together, and dissloves
18218       //   the old bond as well.
18219       ssbond(sface, subsegloop);
18220     }
18221     // Set connection between these faces.
18222     sface = *(face *)(* sfacelist)[0];
18223     for (k = 1; k <= sfacelist->len(); k++) {
18224       if (k < sfacelist->len()) {
18225         sface1 = *(face *)(* sfacelist)[k];
18226       } else {
18227         sface1 = *(face *)(* sfacelist)[0];    // Form a face loop.
18228       }
18229       /*
18230       // Check if these two subfaces are the same. It is possible when user
18231       //   defines one facet (or polygon) two or more times. If they are,
18232       //   they should not be bonded together, instead of that, one of them
18233       //   should be delete from the surface mesh.
18234       if ((sfacelist->len() > 1) && sapex(sface) == sapex(sface1)) {
18235         // They are duplicated faces.
18236         if (b->verbose > 0) {
18237           printf("  A duplicated subface (%d, %d, %d) is removed.\n",
18238                  pointmark(torg), pointmark(tdest), pointmark(sapex(sface)));
18239         }
18240         if (k == sfacelist->len()) {
18241           // 'sface' is the last face, however, it is same as the first one.
18242           //   In order to form the ring, we have to let the second last
18243           //   face bond to the first one 'sface1'.
18244           shellfacedealloc(subfaces, sface.sh);
18245           assert(sfacelist->len() >= 2);
18246           assert(k == sfacelist->len());
18247           sface = *(face *)(* sfacelist)[k - 2];
18248         } else {
18249           // 'sface1' is in the middle and may be the last one.
18250           shellfacedealloc(subfaces, sface1.sh);
18251           // Skip this face and go to the next one.
18252           continue;
18253         }
18254       }
18255       */
18256       if (b->verbose > 2) {
18257         printf("    Bond subfaces (%d, %d, %d) and (%d, %d, %d).\n",
18258                pointmark(torg), pointmark(tdest), pointmark(sapex(sface)),
18259                pointmark(torg), pointmark(tdest), pointmark(sapex(sface1)));
18260       }
18261       sbond1(sface, sface1);
18262       sface = sface1;
18263     }
18264     // Set the unique segment marker into the unified segment.
18265     setshellmark(subsegloop, segmarker);
18266     // Increase the marker.
18267     segmarker++;
18268     // Clear the working list.
18269     sfacelist->clear();
18270     subsegloop.sh = shellfacetraverse(subsegs);
18271   }
18272 
18273   delete [] idx2facelist;
18274   delete [] facesperverlist;
18275   delete sfacelist;
18276 }
18277 
18279 //                                                                           //
18280 // mergefacets()    Merge adjacent facets to be one facet if they are        //
18281 //                  coplanar and have the same boundary marker.              //
18282 //                                                                           //
18283 // Segments between two merged facets will be removed from the mesh.  If all //
18284 // segments around a vertex have been removed, change its vertex type to be  //
18285 // FREESUBVERTEX. Edge flips will be performed to ensure the Delaunayness of //
18286 // the triangulation of merged facets.                                       //
18287 //                                                                           //
18289 
18290 void tetgenmesh::mergefacets(queue* flipqueue)
18291 {
18292   face parentsh, neighsh, neineighsh;
18293   face segloop;
18294   point eorg, edest;
18295   REAL ori;
18296   bool mergeflag, pbcflag;
18297   int* segspernodelist;
18298   int fidx1, fidx2;
18299   int i, j;
18300 
18301   if (b->verbose > 0) {
18302     printf("  Merging coplanar facets.\n");
18303   }
18304   // Create and initialize 'segspernodelist'.
18305   segspernodelist = new int[points->items + 1];
18306   for (i = 0; i < points->items + 1; i++) segspernodelist[i] = 0;
18307 
18308   // Loop the segments, counter the number of segments sharing each vertex.
18309   subsegs->traversalinit();
18310   segloop.sh = shellfacetraverse(subsegs);
18311   while (segloop.sh != (shellface *) NULL) {
18312     // Increment the number of sharing segments for each endpoint.
18313     for (i = 0; i < 2; i++) {
18314       j = pointmark((point) segloop.sh[3 + i]);
18315       segspernodelist[j]++;
18316     }
18317     segloop.sh = shellfacetraverse(subsegs);
18318   }
18319 
18320   // Loop the segments, find out dead segments.
18321   subsegs->traversalinit();
18322   segloop.sh = shellfacetraverse(subsegs);
18323   while (segloop.sh != (shellface *) NULL) {
18324     eorg = sorg(segloop);
18325     edest = sdest(segloop);
18326     spivot(segloop, parentsh);
18327     spivot(parentsh, neighsh);
18328     spivot(neighsh, neineighsh);
18329     if (parentsh.sh != neighsh.sh && parentsh.sh == neineighsh.sh) {
18330       // Exactly two subfaces at this segment.
18331       fidx1 = shellmark(parentsh) - 1;
18332       fidx2 = shellmark(neighsh) - 1;
18333       pbcflag = false;
18334       if (checkpbcs) {
18335         pbcflag = (shellpbcgroup(parentsh) >= 0)
18336           || (shellpbcgroup(neighsh) >= 0);
18337       }
18338       // Possibly merge them if they are not in the same facet.
18339       if ((fidx1 != fidx2) && !pbcflag) {
18340         // Test if they are coplanar.
18341         ori = orient3d(eorg, edest, sapex(parentsh), sapex(neighsh));
18342         if (ori != 0.0) {
18343           if (iscoplanar(eorg, edest, sapex(parentsh), sapex(neighsh), ori,
18344                          b->epsilon)) {
18345             ori = 0.0; // They are assumed as coplanar.
18346           }
18347         }
18348         if (ori == 0.0) {
18349           mergeflag = (in->facetmarkerlist == (int *) NULL ||
18350           in->facetmarkerlist[fidx1] == in->facetmarkerlist[fidx2]);
18351           if (mergeflag) {
18352             // This segment becomes dead.
18353             if (b->verbose > 1) {
18354               printf("  Removing segment (%d, %d).\n", pointmark(eorg),
18355                      pointmark(edest));
18356             }
18357             ssdissolve(parentsh);
18358             ssdissolve(neighsh);
18359             shellfacedealloc(subsegs, segloop.sh);
18360             j = pointmark(eorg);
18361             segspernodelist[j]--;
18362             if (segspernodelist[j] == 0) {
18363               setpointtype(eorg, FREESUBVERTEX);
18364             }
18365             j = pointmark(edest);
18366             segspernodelist[j]--;
18367             if (segspernodelist[j] == 0) {
18368               setpointtype(edest, FREESUBVERTEX);
18369             }
18370             // Add 'parentsh' to queue checking for flip.
18371             enqueueflipedge(parentsh, flipqueue);
18372           }
18373         }
18374       }
18375     }
18376     segloop.sh = shellfacetraverse(subsegs);
18377   }
18378 
18379   if (!flipqueue->empty()) {
18380     // Restore the Delaunay property in the facet triangulation.
18381     flipsub(flipqueue);
18382   }
18383 
18384   delete [] segspernodelist;
18385 }
18386 
18388 //                                                                           //
18389 // meshsurface()    Create the surface mesh of a PLC.                        //
18390 //                                                                           //
18391 // Let X be the PLC, the surface mesh S of X consists of triangulated facets.//
18392 // S is created mainly in the following steps:                               //
18393 //                                                                           //
18394 // (1) Form the CDT of each facet of X separately (by routine triangulate()).//
18395 // After it is done, the subfaces of each facet are connected to each other, //
18396 // however there is no connection between facets yet.  Notice each facet has //
18397 // its own segments, some of them are duplicated.                            //
18398 //                                                                           //
18399 // (2) Remove the redundant segments created in step (1) (by routine unify-  //
18400 // segment()). The subface ring of each segment is created,  the connection  //
18401 // between facets are established as well.                                   //
18402 //                                                                           //
18403 // The return value indicates the number of segments of X.                   //
18404 //                                                                           //
18406 
18407 long tetgenmesh::meshsurface()
18408 {
18409   list *ptlist, *conlist;
18410   queue *flipqueue;
18411   tetgenio::facet *f;
18412   tetgenio::polygon *p;
18413   memorypool *viri;
18414   point *idx2verlist;
18415   point tstart, tend, *cons;
18416   int *worklist;
18417   int end1, end2;
18418   int shmark, i, j;
18419 
18420   if (!b->quiet) {
18421     printf("Creating surface mesh.\n");
18422   }
18423 
18424   // Compute a mapping from indices to points.
18425   makeindex2pointmap(idx2verlist);
18426   // Compute a mapping from points to tets for computing abovepoints.
18427   makepoint2tetmap();
18428   // Initialize 'facetabovepointarray'.
18429   facetabovepointarray = new point[in->numberoffacets + 1];
18430   for (i = 0; i < in->numberoffacets + 1; i++) {
18431     facetabovepointarray[i] = (point) NULL;
18432   }
18433   if (checkpbcs) {
18434     // Initialize the global array 'subpbcgrouptable'.
18435     createsubpbcgrouptable();
18436   }
18437 
18438   // Initialize working lists.
18439   viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
18440   flipqueue = new queue(sizeof(badface));
18441   ptlist = new list(sizeof(point *), NULL, 256);
18442   conlist = new list(sizeof(point *) * 2, NULL, 256);
18443   worklist = new int[points->items + 1];
18444   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
18445 
18446   // Loop the facet list, triangulate each facet. On finish, all subfaces
18447   //   are in 'subfaces', all segments are in 'subsegs'. Notice: there're
18448   //   redundant segments.  Remember: All facet indices count from 1.
18449   for (shmark = 1; shmark <= in->numberoffacets; shmark++) {
18450     // Get a facet F.
18451     f = &in->facetlist[shmark - 1];
18452 
18453     // Process the duplicated points first, they are marked with type
18454     //   DUPLICATEDVERTEX by incrflipdelaunay().  Let p and q are dup.
18455     //   and the index of p is larger than q's, p is substituted by q.
18456     //   In a STL mesh, duplicated points are implicitly included.
18457     if ((b->object == tetgenbehavior::STL) || dupverts) {
18458       // Loop all polygons of this facet.
18459       for (i = 0; i < f->numberofpolygons; i++) {
18460         p = &(f->polygonlist[i]);
18461         // Loop other vertices of this polygon.
18462         for (j = 0; j < p->numberofvertices; j++) {
18463           end1 = p->vertexlist[j];
18464           tstart = idx2verlist[end1 - in->firstnumber];
18465           if (pointtype(tstart) == DUPLICATEDVERTEX) {
18466             // Reset the index of vertex-j.
18467             tend = point2ppt(tstart);
18468             end2 = pointmark(tend);
18469             p->vertexlist[j] = end2;
18470           }
18471         }
18472       }
18473     }
18474 
18475     // Loop polygons of F, get the set V of vertices and S of segments.
18476     for (i = 0; i < f->numberofpolygons; i++) {
18477       // Get a polygon.
18478       p = &(f->polygonlist[i]);
18479       // Get the first vertex.
18480       end1 = p->vertexlist[0];
18481       if ((end1 < in->firstnumber) ||
18482           (end1 >= in->firstnumber + in->numberofpoints)) {
18483         if (!b->quiet) {
18484           printf("Warning:  Invalid the 1st vertex %d of polygon", end1);
18485           printf(" %d in facet %d.\n", i + 1, shmark);
18486         }
18487         continue; // Skip this polygon.
18488       }
18489       tstart = idx2verlist[end1 - in->firstnumber];
18490       // Add tstart to V if it haven't been added yet.
18491       if (worklist[end1] == 0) {
18492         ptlist->append(&tstart);
18493         worklist[end1] = 1;
18494       }
18495       // Loop other vertices of this polygon.
18496       for (j = 1; j <= p->numberofvertices; j++) {
18497         // get a vertex.
18498         if (j < p->numberofvertices) {
18499           end2 = p->vertexlist[j];
18500         } else {
18501           end2 = p->vertexlist[0];  // Form a loop from last to first.
18502         }
18503         if ((end2 < in->firstnumber) ||
18504             (end2 >= in->firstnumber + in->numberofpoints)) {
18505           if (!b->quiet) {
18506             printf("Warning:  Invalid vertex %d in polygon %d", end2, i + 1);
18507             printf(" in facet %d.\n", shmark);
18508           }
18509         } else {
18510           if (end1 != end2) {
18511             // 'end1' and 'end2' form a segment.
18512             tend = idx2verlist[end2 - in->firstnumber];
18513             // Add tstart to V if it haven't been added yet.
18514             if (worklist[end2] == 0) {
18515               ptlist->append(&tend);
18516               worklist[end2] = 1;
18517             }
18518             // Save the segment in S (conlist).
18519             cons = (point *) conlist->append(NULL);
18520             cons[0] = tstart;
18521             cons[1] = tend;
18522             // Set the start for next continuous segment.
18523             end1 = end2;
18524             tstart = tend;
18525           } else {
18526             // Two identical vertices represent an isolated vertex of F.
18527             if (p->numberofvertices > 2) {
18528               // This may be an error in the input, anyway, we can continue
18529               //   by simply skipping this segment.
18530               if (!b->quiet) {
18531                 printf("Warning:  Polygon %d has two identical verts", i + 1);
18532                 printf(" in facet %d.\n", shmark);
18533               }
18534             }
18535             // Ignore this vertex.
18536           }
18537         }
18538         // Is the polygon degenerate (a segment or a vertex)?
18539         if (p->numberofvertices == 2) break;
18540       }
18541     }
18542     // Unmark vertices.
18543     for (i = 0; i < ptlist->len(); i++) {
18544       tstart = * (point *)(* ptlist)[i];
18545       end1 = pointmark(tstart);
18546       assert(worklist[end1] == 1);
18547       worklist[end1] = 0;
18548     }
18549 
18550     // Create a CDT of F.
18551     triangulate(shmark, b->epsilon * 1e+2, ptlist, conlist, f->numberofholes,
18552                 f->holelist, viri, flipqueue);
18553     // Clear working lists.
18554     ptlist->clear();
18555     conlist->clear();
18556     viri->restart();
18557   }
18558 
18559   // Unify segments in 'subsegs', remove redundant segments.  Face links
18560   //   of segments are also built.
18561   unifysegments();
18562   // Remember the number of input segments (for output).
18563   insegments = subsegs->items;
18564 
18565   if (checkpbcs) {
18566     // Create the global array 'segpbcgrouptable'.
18567     createsegpbcgrouptable();
18568   }
18569 
18570   if (b->object == tetgenbehavior::STL) {
18571     // Remove redundant vertices (for .stl input mesh).
18572     jettisonnodes();
18573   }
18574 
18575   if (!b->nomerge && !b->nobisect && !checkpbcs) {
18576     // No '-M' switch - merge adjacent facets if they are coplanar.
18577     mergefacets(flipqueue);
18578   }
18579 
18580   delete [] idx2verlist;
18581   delete [] worklist;
18582   delete ptlist;
18583   delete conlist;
18584   delete flipqueue;
18585   delete viri;
18586 
18587   return subsegs->items;
18588 }
18589 
18590 //
18591 // End of surface triangulation routines
18592 //
18593 
18595 //                                                                           //
18596 // interecursive()    Recursively do intersection test on a set of triangles.//
18597 //                                                                           //
18598 // Recursively split the set 'subfacearray' of subfaces into two sets using  //
18599 // a cut plane parallel to x-, or, y-, or z-axies.  The split criteria are   //
18600 // follows. Assume the cut plane is H, and H+ denotes the left halfspace of  //
18601 // H, and H- denotes the right halfspace of H; and s be a subface:           //
18602 //                                                                           //
18603 //    (1) If all points of s lie at H+, put it into left array;              //
18604 //    (2) If all points of s lie at H-, put it into right array;             //
18605 //    (3) If some points of s lie at H+ and some of lie at H-, or some       //
18606 //        points lie on H, put it into both arraies.                         //
18607 //                                                                           //
18608 // Partitions by x-axis if axis == '0'; by y-axis if axis == '1'; by z-axis  //
18609 // if axis == '2'. If current cut plane is parallel to the x-axis, the next  //
18610 // one will be parallel to y-axis, and the next one after the next is z-axis,//
18611 // and then alternately return back to x-axis.                               //
18612 //                                                                           //
18613 // Stop splitting when the number of triangles of the input array is not     //
18614 // decreased anymore. Do tests on the current set.                           //
18615 //                                                                           //
18617 
18618 void tetgenmesh::
18619 interecursive(shellface** subfacearray, int arraysize, int axis, REAL bxmin,
18620               REAL bxmax, REAL bymin, REAL bymax, REAL bzmin, REAL bzmax,
18621               int* internum)
18622 {
18623   shellface **leftarray, **rightarray;
18624   face sface1, sface2;
18625   point p1, p2, p3;
18626   point p4, p5, p6;
18627   enum interresult intersect;
18628   REAL split;
18629   bool toleft, toright;
18630   int leftsize, rightsize;
18631   int i, j;
18632 
18633   if (b->verbose > 1) {
18634     printf("  Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
18635            arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
18636            axis == 0 ? "x" : (axis == 1 ? "y" : "z"));
18637   }
18638 
18639   leftarray = new shellface*[arraysize];
18640   if (leftarray == NULL) {
18641     printf("Error in interecursive():  Insufficient memory.\n");
18642     terminatetetgen(1);
18643   }
18644   rightarray = new shellface*[arraysize];
18645   if (rightarray == NULL) {
18646     printf("Error in interecursive():  Insufficient memory.\n");
18647     terminatetetgen(1);
18648   }
18649   leftsize = rightsize = 0;
18650 
18651   if (axis == 0) {
18652     // Split along x-axis.
18653     split = 0.5 * (bxmin + bxmax);
18654   } else if (axis == 1) {
18655     // Split along y-axis.
18656     split = 0.5 * (bymin + bymax);
18657   } else {
18658     // Split along z-axis.
18659     split = 0.5 * (bzmin + bzmax);
18660   }
18661 
18662   for (i = 0; i < arraysize; i++) {
18663     sface1.sh = subfacearray[i];
18664     p1 = (point) sface1.sh[3];
18665     p2 = (point) sface1.sh[4];
18666     p3 = (point) sface1.sh[5];
18667     toleft = toright = false;
18668     if (p1[axis] < split) {
18669       toleft = true;
18670       if (p2[axis] >= split || p3[axis] >= split) {
18671         toright = true;
18672       }
18673     } else if (p1[axis] > split) {
18674       toright = true;
18675       if (p2[axis] <= split || p3[axis] <= split) {
18676         toleft = true;
18677       }
18678     } else {
18679       // p1[axis] == split;
18680       toleft = true;
18681       toright = true;
18682     }
18683     // At least one is true;
18684 #ifdef SELF_CHECK
18685     assert(!(toleft == false && toright == false));
18686 #endif
18687     if (toleft) {
18688       leftarray[leftsize] = sface1.sh;
18689       leftsize++;
18690     }
18691     if (toright) {
18692       rightarray[rightsize] = sface1.sh;
18693       rightsize++;
18694     }
18695   }
18696 
18697   if (leftsize < arraysize && rightsize < arraysize) {
18698     // Continue to partition the input set. Now 'subfacearray' has been
18699     //   split into two sets, it's memory can be freed. 'leftarray' and
18700     //   'rightarray' will be freed in the next recursive (after they're
18701     //   partitioned again or performing tests).
18702     delete [] subfacearray;
18703     // Continue to split these two sets.
18704     if (axis == 0) {
18705       interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax,
18706                     bzmin, bzmax, internum);
18707       interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax,
18708                     bzmin, bzmax, internum);
18709     } else if (axis == 1) {
18710       interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split,
18711                     bzmin, bzmax, internum);
18712       interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax,
18713                     bzmin, bzmax, internum);
18714     } else {
18715       interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax,
18716                     bzmin, split, internum);
18717       interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax,
18718                     split, bzmax, internum);
18719     }
18720   } else {
18721     if (b->verbose > 1) {
18722       printf("  Checking intersecting faces.\n");
18723     }
18724     // Perform a brute-force compare on the set.
18725     for (i = 0; i < arraysize; i++) {
18726       sface1.sh = subfacearray[i];
18727       p1 = (point) sface1.sh[3];
18728       p2 = (point) sface1.sh[4];
18729       p3 = (point) sface1.sh[5];
18730       for (j = i + 1; j < arraysize; j++) {
18731         sface2.sh = subfacearray[j];
18732         p4 = (point) sface2.sh[3];
18733         p5 = (point) sface2.sh[4];
18734         p6 = (point) sface2.sh[5];
18735         intersect = tri_tri_inter(p1, p2, p3, p4, p5, p6);
18736         if (intersect == INTERSECT || intersect == SHAREFACE) {
18737           if (!b->quiet) {
18738             if (intersect == INTERSECT) {
18739               printf("  Facet #%d intersects facet #%d at triangles:\n",
18740                      shellmark(sface1), shellmark(sface2));
18741               printf("    (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
18742                      pointmark(p1), pointmark(p2), pointmark(p3),
18743                      pointmark(p4), pointmark(p5), pointmark(p6));
18744             } else {
18745               printf("  Facet #%d duplicates facet #%d at triangle:\n",
18746                      shellmark(sface1), shellmark(sface2));
18747               printf("    (%4d, %4d, %4d)\n", pointmark(p1), pointmark(p2),
18748                      pointmark(p3));
18749             }
18750           }
18751           // Increase the number of intersecting pairs.
18752           (*internum)++;
18753           // Infect these two faces (although they may already be infected).
18754           sinfect(sface1);
18755           sinfect(sface2);
18756         }
18757       }
18758     }
18759     // Don't forget to free all three arrays. No further partition.
18760     delete [] leftarray;
18761     delete [] rightarray;
18762     delete [] subfacearray;
18763   }
18764 }
18765 
18767 //                                                                           //
18768 // detectinterfaces()    Detect intersecting triangles.                      //
18769 //                                                                           //
18770 // Given a set of triangles,  find the pairs of intersecting triangles from  //
18771 // them.  Here the set of triangles is in 'subfaces' which is a surface mesh //
18772 // of a PLC (.poly or .smesh).                                               //
18773 //                                                                           //
18774 // To detect whether two triangles are intersecting is done by the routine   //
18775 // 'tri_tri_inter()'.  The algorithm for the test is very simple and stable. //
18776 // It is based on geometric orientation test which uses exact arithmetics.   //
18777 //                                                                           //
18778 // Use divide-and-conquer algorithm for reducing the number of intersection  //
18779 // tests.  Start from the bounding box of the input point set, recursively   //
18780 // partition the box into smaller boxes, until the number of triangles in a  //
18781 // box is not decreased anymore. Then perform triangle-triangle tests on the //
18782 // remaining set of triangles.  The memory allocated in the input set is     //
18783 // freed immediately after it has been partitioned into two arrays.  So it   //
18784 // can be re-used for the consequent partitions.                             //
18785 //                                                                           //
18786 // On return, the pool 'subfaces' will be cleared, and only the intersecting //
18787 // triangles remain for output (to a .face file).                            //
18788 //                                                                           //
18790 
18791 void tetgenmesh::detectinterfaces()
18792 {
18793   shellface **subfacearray;
18794   face shloop;
18795   int internum;
18796   int i;
18797 
18798   if (!b->quiet) {
18799     printf("Detecting intersecting facets.\n");
18800   }
18801 
18802   // Construct a map from indices to subfaces;
18803   subfacearray = new shellface*[subfaces->items];
18804   subfaces->traversalinit();
18805   shloop.sh = shellfacetraverse(subfaces);
18806   i = 0;
18807   while (shloop.sh != (shellface *) NULL) {
18808     subfacearray[i] = shloop.sh;
18809     shloop.sh = shellfacetraverse(subfaces);
18810     i++;
18811   }
18812 
18813   internum = 0;
18814   // Recursively split the set of triangles into two sets using a cut plane
18815   //   parallel to x-, or, y-, or z-axies.  Stop splitting when the number
18816   //   of subfaces is not decreasing anymore. Do tests on the current set.
18817   interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax,
18818                 zmin, zmax, &internum);
18819 
18820   if (!b->quiet) {
18821     if (internum > 0) {
18822       printf("\n!! Found %d pairs of faces are intersecting.\n\n", internum);
18823     } else {
18824       printf("\nNo faces are intersecting.\n\n");
18825     }
18826   }
18827 
18828   if (internum > 0) {
18829     // Traverse all subfaces, deallocate those have not been infected (they
18830     //   are not intersecting faces). Uninfect those have been infected.
18831     //   After this loop, only intersecting faces remain.
18832     subfaces->traversalinit();
18833     shloop.sh = shellfacetraverse(subfaces);
18834     while (shloop.sh != (shellface *) NULL) {
18835       if (sinfected(shloop)) {
18836         suninfect(shloop);
18837       } else {
18838         shellfacedealloc(subfaces, shloop.sh);
18839       }
18840       shloop.sh = shellfacetraverse(subfaces);
18841     }
18842   } else {
18843     // Deallocate all subfaces.
18844     subfaces->restart();
18845   }
18846 }
18847 
18848 //
18849 // Begin of periodic boundary condition routines
18850 //
18851 
18853 //                                                                           //
18854 // createsubpbcgrouptable()    Create the 'subpbcgrouptable'.                //
18855 //                                                                           //
18856 // Allocate the memory for 'subpbcgrouptable'.  Each entry i (a pbcdata) of  //
18857 // the table represents a pbcgroup.  Most of the fields of a group-i are set //
18858 // in this routine. 'fmark[0]', 'fmark[1]', and 'transmat[0]' are directly   //
18859 // copied from the corresponding data of 'in->numberofpbcgroups'. 'transmat  //
18860 // [1]' is calculated as the inverse matrix of 'transmat[0]'.  'ss[0]' and   //
18861 // 'ss[1]' are initilized be 'dummysh'. They are set in 'trangulatefacet()'  //
18862 // (when -p is in use) or 'reconstructmesh()' (when -r is in use).           //
18863 //                                                                           //
18865 
18866 void tetgenmesh::createsubpbcgrouptable()
18867 {
18868   tetgenio::pbcgroup *pg;
18869   pbcdata *pd;
18870   REAL A[4][4], rhs[4], D;
18871   int indx[4];
18872   int i, j, k;
18873 
18874   subpbcgrouptable = new pbcdata[in->numberofpbcgroups];
18875   for (i = 0; i < in->numberofpbcgroups; i++) {
18876     pg = &(in->pbcgrouplist[i]);
18877     pd = &(subpbcgrouptable[i]);
18878     // Copy data from pg to pd.
18879     pd->fmark[0] = pg->fmark1;
18880     pd->fmark[1] = pg->fmark2;
18881     // Initialize array 'pd->ss'.
18882     pd->ss[0].sh = dummysh;
18883     pd->ss[1].sh = dummysh;
18884     // Copy the transform matrix from pg to pd->transmat[0].
18885     for (j = 0; j < 4; j++) {
18886       for (k = 0; k < 4; k++) {
18887         pd->transmat[0][j][k] = pg->transmat[j][k];
18888         // Prepare for inverting the matrix.
18889         A[j][k] = pg->transmat[j][k];
18890       }
18891     }
18892     // Calculate the inverse matrix (pd->transmat[1]) of pd->transmat[0].
18893     lu_decmp(A, 4, indx, &D, 0);
18894     for (j = 0; j < 4; j++) {
18895       for (k = 0; k < 4; k++) rhs[k] = 0.0;
18896       rhs[j] = 1.0;
18897       lu_solve(A, 4, indx, rhs, 0);
18898       for (k = 0; k < 4; k++) pd->transmat[1][k][j] = rhs[k];
18899     }
18900   }
18901 }
18902 
18904 //                                                                           //
18905 // getsubpbcgroup()    Get the pbcgroup of a subface.                        //
18906 //                                                                           //
18907 // 'pbcsub' has pbc defined. Its pbcgroup is returned in 'pd'. In addition,  //
18908 // 'f1' (0 or 1) indicates the position of 'pbcsub' in 'pd'; 'f2' (= 1 - f1) //
18909 // is the position where the symmetric subface of 'pbcsub' is found.         //
18910 //                                                                           //
18912 
18913 void tetgenmesh::getsubpbcgroup(face* pbcsub, pbcdata** pd, int *f1, int *f2)
18914 {
18915   int groupid, fmark, idx;
18916 
18917   groupid = shellpbcgroup(*pbcsub);
18918   *pd = &subpbcgrouptable[groupid];
18919 
18920   // Get the facet index (1 - based).
18921   idx = shellmark(*pbcsub);
18922   // Get the facet marker from array (0 - based).
18923   fmark = in->facetmarkerlist[idx - 1];
18924   if ((*pd)->fmark[0] == fmark) {
18925     *f1 = 0;
18926   } else {
18927 #ifdef SELF_CHECK
18928     assert((*pd)->fmark[1] == fmark);
18929 #endif
18930     *f1 = 1;
18931   }
18932   *f2 = 1 - (*f1);
18933 }
18934 
18936 //                                                                           //
18937 // getsubpbcsympoint()    Compute the symmetric point for a subface point.   //
18938 //                                                                           //
18939 // 'newpoint' lies on 'splitsub'. This routine calculates a 'sympoint' which //
18940 // locates on 'symsplitsub' and symmtric to 'newpoint'.  Return the location //
18941 // of sympoint wrt. symsplitsub.                                             //
18942 //                                                                           //
18944 
18945 enum tetgenmesh::locateresult tetgenmesh:: getsubpbcsympoint(point newpoint,
18946   face* splitsub, point sympoint, face* symsplitsub)
18947 {
18948   pbcdata *pd;
18949   face subloop;
18950   point pa, pb, pc;
18951   enum locateresult symloc;
18952   REAL ori;
18953   int f1, f2, i;
18954 
18955   // Get the pbcgroup of 'splitsub'.
18956   getsubpbcgroup(splitsub, &pd, &f1, &f2);
18957 
18958   // Transform newpoint from f1 -> f2.
18959   for (i = 0; i < 3; i++) {
18960     sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
18961                 + pd->transmat[f1][i][1] * newpoint[1]
18962                 + pd->transmat[f1][i][2] * newpoint[2]
18963                 + pd->transmat[f1][i][3] * 1.0;
18964   }
18965   // Locate sympoint in f2.
18966   symloc = OUTSIDE;
18967   *symsplitsub = pd->ss[f2];
18968   // Is the stored subface valid? Hole removal may delete the subface.
18969   if ((symsplitsub->sh != dummysh) && !isdead(symsplitsub)) {
18970     // 'symsplitsub' should lie on the symmetric facet. Check it.
18971     i = shellmark(*symsplitsub);
18972     if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18973       // 'symsplitsub' has the symmetric boundary marker.
18974       pa = sorg(*symsplitsub);
18975       pb = sdest(*symsplitsub);
18976       pc = sapex(*symsplitsub);
18977       // Test if they are (nearly) coplanar. Some facets may have the
18978       //   same boundary marker but not coplanar with this point.
18979       ori = orient3d(pa, pb, pc, sympoint);
18980       if (iscoplanar(pa, pb, pc, sympoint, ori, b->epsilon * 1e+2)) {
18981         // Locate sympoint in facet. Don't stop at subsegment.
18982         abovepoint = facetabovepointarray[shellmark(*symsplitsub)];
18983         if (abovepoint == (point) NULL) {
18984           getfacetabovepoint(symsplitsub);
18985         }
18986         symloc = locatesub(sympoint, symsplitsub, 0, b->epsilon * 1e+2);
18987       }
18988     }
18989   }
18990   if (symloc == OUTSIDE) {
18991     // Do a brute-force searching for the symmetric subface.
18992     REAL epspp = b->epsilon * 1e+2;
18993     int lcount = 0;
18994     do {
18995       // Locate sympoint in the pool of subfaces (with fmark pd->fmark[f2]).
18996       subfaces->traversalinit();
18997       subloop.sh = shellfacetraverse(subfaces);
18998       while (subloop.sh != (shellface *) NULL) {
18999         i = shellmark(subloop);
19000         if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
19001           // Found a facet have the symmetric boundary marker.
19002           pa = sorg(subloop);
19003           pb = sdest(subloop);
19004           pc = sapex(subloop);
19005           // Test if they are (nearly) coplanar. Some facets may have the
19006           //   same boundary marker but not coplanar with this point.
19007           ori = orient3d(pa, pb, pc, sympoint);
19008           if (iscoplanar(pa, pb, pc, sympoint, ori, epspp)) {
19009             // Test if sympoint is (nearly) inside this facet.
19010             // Get the abovepoint of the facet.
19011             abovepoint = facetabovepointarray[shellmark(subloop)];
19012             // Do we need to calculate the abovepoint?
19013             if (abovepoint == (point) NULL) {
19014               getfacetabovepoint(&subloop);
19015             }
19016             // subloop is on the facet, search sympoint.
19017             symloc = locatesub(sympoint, &subloop, 0, epspp);
19018             if (symloc != OUTSIDE) break;
19019           }
19020         }
19021         subloop.sh = shellfacetraverse(subfaces);
19022       }
19023       lcount++;
19024       epspp *= 10.0;
19025     } while ((symloc == OUTSIDE) && (lcount < 3));
19026 #ifdef SELF_CHECK
19027     // sympoint should be inside the facet.
19028     assert(symloc != OUTSIDE);
19029 #endif
19030     // Set the returning subface.
19031     *symsplitsub = subloop;
19032     // Update the stored subface for next searching.
19033     pd->ss[f2] = *symsplitsub;
19034   }
19035 
19036   return adjustlocatesub(sympoint, symsplitsub, symloc, b->epsilon);
19037 }
19038 
19040 //                                                                           //
19041 // createsegpbcgrouptable()    Create the 'segpbcgrouptable'.                //
19042 //                                                                           //
19043 // Each segment may belong to more than one pbcgroups.  For example, segment //
19044 // ab may need to be symmteric to both segments cd, and ef, then  ab and cd, //
19045 // cd and ef, ef and ab form three pbcgroups.                                //
19046 //                                                                           //
19047 // 'segpbcgrouptable' is  implemented as a list of pbcdatas. Each item i is  //
19048 // a pbcgroup.                                                               //
19049 //                                                                           //
19051 
19052 void tetgenmesh::createsegpbcgrouptable()
19053 {
19054   shellface** segsperverlist;
19055   pbcdata *pd, *ppd, pd1, pd2;
19056   face segloop, symseg;
19057   face startsh, spinsh, symsh;
19058   point pa, pb, syma, symb;
19059   enum locateresult symloc;
19060   REAL testpt[3], sympt[3];
19061   bool inflag;
19062   int *idx2seglist;
19063   int segid1, segid2;
19064   int f1, f2;
19065   int i, j, k, l;
19066 
19067   // Allocate memory for 'subpbcgrouptable'.
19068   segpbcgrouptable = new list(sizeof(pbcdata), NULL, 256);
19069 
19070   if (b->refine) {
19071     // Create a point-to-seg map for quickly finding PBC seg pairs.
19072     makesegmentmap(idx2seglist, segsperverlist);
19073   }
19074 
19075   // Loop through the segment list.
19076   subsegs->traversalinit();
19077   segloop.sh = shellfacetraverse(subsegs);
19078   while (segloop.sh != (shellface *) NULL) {
19079     // Loop the subface ring of segloop ab.
19080     pa = sorg(segloop);
19081     pb = sdest(segloop);
19082     segid1 = shellmark(segloop);
19083     spivot(segloop, startsh);
19084     spinsh = startsh;
19085     do {
19086       // Adjust spinsh be edge ab.
19087       if (sorg(spinsh) != pa) {
19088         sesymself(spinsh);
19089       }
19090       // Does spinsh belong to a pbcgroup?
19091       if (shellpbcgroup(spinsh) != -1) {
19092         // Yes! There exists a segment cd. ab and cd form a pbcgroup.
19093         if (b->refine) {
19094           getsubpbcgroup(&spinsh, &pd, &f1, &f2);
19095           // Transform pa from f1 -> f2.
19096           for (i = 0; i < 3; i++) {
19097             sympt[i] = pd->transmat[f1][i][0] * pa[0]
19098                      + pd->transmat[f1][i][1] * pa[1]
19099                      + pd->transmat[f1][i][2] * pa[2]
19100                      + pd->transmat[f1][i][3] * 1.0;
19101           }
19102           syma = point2pbcpt(pa);
19103           // Is 'sympt == syma'?
19104           if (distance(sympt, syma) > (longest * b->epsilon)) {
19105             // No. Search the symmetric vertex of pa.
19106             symloc = getsubpbcsympoint(pa, &spinsh, sympt, &symsh);
19107             syma = sorg(symsh);
19108             if (symloc != ONVERTEX) {
19109               // Do a brute force search. Not done yet.
19110               assert(0);
19111             }
19112           }
19113           // Transform pb from f1 -> f2.
19114           for (i = 0; i < 3; i++) {
19115             sympt[i] = pd->transmat[f1][i][0] * pb[0]
19116                      + pd->transmat[f1][i][1] * pb[1]
19117                      + pd->transmat[f1][i][2] * pb[2]
19118                      + pd->transmat[f1][i][3] * 1.0;
19119           }
19120           // Search sym subface from the point-to-subface map.
19121           symseg.shver = 0;
19122           j = pointmark(syma) - in->firstnumber;
19123           for (i = idx2seglist[j]; i < idx2seglist[j + 1]; i++) {
19124             symseg.sh = segsperverlist[i];
19125             if (sorg(symseg) == syma) symb = sdest(symseg);
19126             else symb = sorg(symseg);
19127             if (distance(sympt, symb) <= (longest * b->epsilon)) break;
19128           }
19129           assert(i < idx2seglist[j + 1]);
19130         } else {
19131           //   'testpt' is the midpoint of ab used to find cd.
19132           for (i = 0; i < 3; i++) testpt[i] = 0.5 * (pa[i] + pb[i]);
19133           symloc = getsubpbcsympoint(testpt, &spinsh, sympt, &symsh);
19134 #ifdef SELF_CHECK
19135           assert(symloc == ONEDGE);
19136 #endif
19137           sspivot(symsh, symseg);
19138         }
19139 #ifdef SELF_CHECK
19140         assert(symseg.sh != dummysh);
19141 #endif
19142         // Check whether this group has already been created in list.
19143         segid2 = shellmark(symseg);
19144         inflag = false;
19145         for (i = 0; i < segpbcgrouptable->len() && !inflag; i++) {
19146           pd = (pbcdata *)(* segpbcgrouptable)[i];
19147           if (pd->segid[0] == segid1) {
19148             if (pd->segid[1] == segid2) inflag = true;
19149           } else if (pd->segid[0] == segid2) {
19150             if (pd->segid[1] == segid1) inflag = true;
19151           }
19152         }
19153         if (!inflag) {
19154           // Create a segment pbcgroup in list for ab and cd.
19155           pd = (pbcdata *) segpbcgrouptable->append(NULL);
19156           // Save the markers of ab and cd.
19157           pd->segid[0] = segid1;
19158           pd->segid[1] = segid2;
19159           // Save the handles of ab and cd.
19160           pd->ss[0] = segloop;
19161           pd->ss[1] = symseg;
19162           // Find the map from ab to cd.
19163           getsubpbcgroup(&spinsh, &ppd, &f1, &f2);
19164           pd->fmark[0] = ppd->fmark[f1];
19165           pd->fmark[1] = ppd->fmark[f2];
19166           // Set the map from ab to cd.
19167           for (i = 0; i < 4; i++) {
19168             for (j = 0; j < 4; j++) {
19169               pd->transmat[0][i][j] = ppd->transmat[f1][i][j];
19170             }
19171           }
19172           // Set the map from cd to ab.
19173           for (i = 0; i < 4; i++) {
19174             for (j = 0; j < 4; j++) {
19175               pd->transmat[1][i][j] = ppd->transmat[f2][i][j];
19176             }
19177           }
19178         }
19179       }
19180       // Go to the next subface in the ring of ab.
19181       spivotself(spinsh);
19182     } while (spinsh.sh != startsh.sh);
19183     segloop.sh = shellfacetraverse(subsegs);
19184   }
19185 
19186   if (b->refine) {
19187     delete [] segsperverlist;
19188     delete [] idx2seglist;
19189   }
19190 
19191   // Create the indirect segment pbcgroups.
19192   // Bug-fixed (08 Sept. 2006). The total size of 'segpbcgrouptable' may get
19193   //   increased. Do not use pointers for 'pd1' and 'pd2'. The addresses may
19194   //   be invaild after realloc().
19195   for (i = 0; i < segpbcgrouptable->len(); i++) {
19196     pd1 = * (pbcdata *)(* segpbcgrouptable)[i];
19197     for (f1 = 0; f1 < 2; f1++) {
19198       // Search for a group (except i) contains pd1.segid[f1].
19199       for (j = 0; j < segpbcgrouptable->len(); j++) {
19200         if (j == i) continue;
19201         pd2 = * (pbcdata *)(* segpbcgrouptable)[j];
19202         f2 = -1;
19203         if (pd1.segid[f1] == pd2.segid[0]) {
19204           f2 = 0;
19205         } else if (pd1.segid[f1] == pd2.segid[1]) {
19206           f2 = 1;
19207         }
19208         if (f2 != -1) {
19209 #ifdef SELF_CHECK
19210           assert(pd1.segid[f1] == pd2.segid[f2]);
19211 #endif
19212           segid1 = pd1.segid[1 - f1];
19213           segid2 = pd2.segid[1 - f2];
19214           // Search for the existence of segment pbcgroup (segid1, segid2).
19215           inflag = false;
19216           for (k = 0; k < segpbcgrouptable->len() && !inflag; k++) {
19217             pd = (pbcdata *)(* segpbcgrouptable)[k];
19218             if (pd->segid[0] == segid1) {
19219               if (pd->segid[1] == segid2) inflag = true;
19220             } else if (pd->segid[0] == segid2) {
19221               if (pd->segid[1] == segid1) inflag = true;
19222             }
19223           }
19224           if (!inflag) {
19225             pd = (pbcdata *) segpbcgrouptable->append(NULL);
19226             pd->segid[0] = pd1.segid[1 - f1];
19227             pd->segid[1] = pd2.segid[1 - f2];
19228             pd->ss[0] = pd1.ss[1 - f1];
19229             pd->ss[1] = pd2.ss[1 - f2];
19230             // Invalid the fmark[0] == fmark[1].
19231             pd->fmark[0] = pd->fmark[1] = 0;
19232             // Translate matrix pd->transmat[0] = m2 * m1, where m1 =
19233             //   pd1.transmat[1 - f1], m2 = pd2.transmat[f2].
19234             for (k = 0; k < 4; k++) {
19235               for (l = 0; l < 4; l++) {
19236                 pd->transmat[0][k][l] = pd2.transmat[f2][k][l];
19237               }
19238             }
19239             m4xm4(pd->transmat[0], pd1.transmat[1 - f1]);
19240             // Translate matrix pd->transmat[1] = m4 * m3, where m3 =
19241             //   pd2.transmat[1 - f2], m4 = pd1.transmat[f1].
19242             for (k = 0; k < 4; k++) {
19243               for (l = 0; l < 4; l++) {
19244                 pd->transmat[1][k][l] = pd1.transmat[f1][k][l];
19245               }
19246             }
19247             m4xm4(pd->transmat[1], pd2.transmat[1 - f2]);
19248           }
19249         }
19250       }
19251     }
19252   }
19253 
19254   // Form a map from segment index to pbcgroup list of this segment.
19255   idx2segpglist = new int[subsegs->items + 1];
19256   for (i = 0; i < subsegs->items + 1; i++) idx2segpglist[i] = 0;
19257   // Loop through 'segpbcgrouptable', counter the number of pbcgroups of
19258   //   each segment.
19259   for (i = 0; i < segpbcgrouptable->len(); i++) {
19260     pd = (pbcdata *)(* segpbcgrouptable)[i];
19261     for (j = 0; j < 2; j++) {
19262       k = pd->segid[j] - 1;
19263       idx2segpglist[k]++;
19264     }
19265   }
19266   // Calculate the total length of array 'segpglist'.
19267   j = idx2segpglist[0];
19268   idx2segpglist[0] = 0;  // Array starts from 0 element.
19269   for (i = 0; i < subsegs->items; i++) {
19270     k = idx2segpglist[i + 1];
19271     idx2segpglist[i + 1] = idx2segpglist[i] + j;
19272     j = k;
19273   }
19274   // The total length is in the last unit of idx2segpglist.
19275   segpglist = new int[idx2segpglist[i]];
19276   // Loop the set of pbcgroups again, set the data into segpglist.
19277   for (i = 0; i < segpbcgrouptable->len(); i++) {
19278     pd = (pbcdata *)(* segpbcgrouptable)[i];
19279     for (j = 0; j < 2; j++) {
19280       k = pd->segid[j] - 1;
19281       segpglist[idx2segpglist[k]] = i;
19282       idx2segpglist[k]++;
19283     }
19284   }
19285   // Contents in 'idx2segpglist' are shifted, now shift them back.
19286   for (i = subsegs->items - 1; i >= 0; i--) {
19287     idx2segpglist[i + 1] = idx2segpglist[i];
19288   }
19289   idx2segpglist[0] = 0;
19290 }
19291 
19293 //                                                                           //
19294 // getsegpbcsympoint()    Compute the symmetric point for a segment point.   //
19295 //                                                                           //
19296 // 'newpoint' lies on 'splitseg'. This routine calculates a 'sympoint' which //
19297 // locates on 'symsplitseg' and symmtric to 'newpoint'.  Return the location //
19298 // of sympoint wrt. symsplitseg.                                             //
19299 //                                                                           //
19301 
19302 enum tetgenmesh::locateresult tetgenmesh::
19303 getsegpbcsympoint(point newpoint, face* splitseg, point sympoint,
19304                   face* symsplitseg, int groupid)
19305 {
19306   pbcdata *pd;
19307   enum locateresult symloc;
19308   int segid, f1, f2, i;
19309 
19310   pd = (pbcdata *)(* segpbcgrouptable)[groupid];
19311   segid = shellmark(*splitseg);
19312   if (pd->segid[0] == segid) {
19313     f1 = 0;
19314   } else {
19315 #ifdef SELF_CHECK
19316     assert(pd->segid[1] == segid);
19317 #endif
19318     f1 = 1;
19319   }
19320   f2 = 1 - f1;
19321 
19322   // Transform newpoint from f1 -> f2.
19323   for (i = 0; i < 3; i++) {
19324     sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
19325                 + pd->transmat[f1][i][1] * newpoint[1]
19326                 + pd->transmat[f1][i][2] * newpoint[2]
19327                 + pd->transmat[f1][i][3] * 1.0;
19328   }
19329   // Locate sympoint in f2.
19330   *symsplitseg = pd->ss[f2];
19331 #ifdef SELF_CHECK
19332   assert(symsplitseg->sh != dummysh);
19333 #endif
19334   // Locate sympoint in facet. Stop at subsegment.
19335   symloc = locateseg(sympoint, symsplitseg);
19336   symloc = adjustlocateseg(sympoint, symsplitseg, symloc, b->epsilon * 1e+2);
19337   return symloc;
19338 }
19339 
19340 //
19341 // End of periodic boundary condition routines
19342 //
19343 
19344 //
19345 // Begin of vertex perturbation routines
19346 //
19347 
19349 //                                                                           //
19350 // randgenerator()    Generate a random REAL number between (0, |range|).    //
19351 //                                                                           //
19353 
19354 REAL tetgenmesh::randgenerator(REAL range)
19355 {
19356   REAL worknumber, result;
19357   int expo;
19358 
19359   if (range == 0.0) return 0.0;
19360 
19361   expo = 0;
19362   worknumber = fabs(range);
19363   // Normalize worknumber (i.e., 1.xxxExx)
19364   if (worknumber > 10.0) {
19365     while (worknumber > 10.0) {
19366       worknumber /= 10.0;
19367       expo++;
19368     }
19369   } else if (worknumber < 1.0) {
19370     while (worknumber < 1.0) {
19371       worknumber *= 10.0;
19372       expo--;
19373     }
19374   }
19375 #ifdef SELF_CHECK
19376   assert(worknumber >= 1.0 && worknumber <= 10.0);
19377 #endif
19378 
19379   // Enlarge worknumber 1000 times.
19380   worknumber *= 1e+3;
19381   expo -= 3;
19382   // Generate a randome number between (0, worknumber).
19383   result = (double) randomnation((int) worknumber);
19384 
19385   // Scale result back into the original size.
19386   if (expo > 0) {
19387     while (expo != 0) {
19388       result *= 10.0;
19389       expo--;
19390     }
19391   } else if (expo < 0) {
19392     while (expo != 0) {
19393       result /= 10.0;
19394       expo++;
19395     }
19396   }
19397 #ifdef SELF_CHECK
19398   assert((result >= 0.0) && (result <= fabs(range)));
19399 #endif
19400 
19401   return result;
19402 }
19403 
19405 //                                                                           //
19406 // checksub4cocir()    Test a subface to find co-circular pair of subfaces.  //
19407 //                                                                           //
19408 // 'eps' is a relative tolerance for testing approximately cospherical case. //
19409 // Set it to zero if only exact test is desired.                             //
19410 //                                                                           //
19411 // An edge(not a segment) of 'testsub' is locally degenerate if the opposite //
19412 // vertex of the adjacent subface is cocircular with the vertices of testsub.//
19413 // If 'once' is TRUE, operate on the edge only if the pointer 'testsub->sh'  //
19414 // is smaller than its neighbor (for each edge is considered only once).     //
19415 //                                                                           //
19416 // Return TRUE if find an edge of testsub is locally degenerate.             //
19417 //                                                                           //
19419 
19420 bool tetgenmesh::checksub4cocir(face* testsub, REAL eps, bool once,
19421   bool enqflag)
19422 {
19423   badface *cocirsub;
19424   face subloop, neighsub;
19425   face checkseg;
19426   point pa, pb, pc, pd;
19427   REAL sign;
19428   int i;
19429 
19430   subloop = *testsub;
19431   subloop.shver = 0; // Keep the CCW orientation.
19432   // Get the abovepoint of the facet.
19433   abovepoint = facetabovepointarray[shellmark(subloop)];
19434   // Do we need to calculate the abovepoint?
19435   if (abovepoint == (point) NULL) {
19436     getfacetabovepoint(&subloop);
19437   }
19438   // Check the three edges of subloop.
19439   for (i = 0; i < 3; i++) {
19440     sspivot(subloop, checkseg);
19441     if (checkseg.sh == dummysh) {
19442       // It is not a segment, get the adjacent subface.
19443       spivot(subloop, neighsub);
19444       // assert(neighsub.sh != dummysh);
19445       if (!once || (once && (neighsub.sh > subloop.sh))) {
19446         pa = sorg(subloop);
19447         pb = sdest(subloop);
19448         pc = sapex(subloop);
19449         pd = sapex(neighsub);
19450         sign = insphere(pa, pb, pc, abovepoint, pd);
19451         if ((sign != 0.0) && (eps > 0.0)) {
19452           if (iscospheric(pa, pb, pc, abovepoint, pd, sign, eps)) sign = 0.0;
19453         }
19454         if (sign == 0.0) {
19455           // It's locally degenerate!
19456           if (enqflag && badsubfaces != (memorypool *) NULL) {
19457             // Save it.
19458             cocirsub = (badface *) badsubfaces->alloc();
19459             cocirsub->ss = subloop;
19460             cocirsub->forg = pa;
19461             cocirsub->fdest = pb;
19462             cocirsub->fapex = pc;
19463             cocirsub->foppo = pd;
19464             setshell2badface(cocirsub->ss, cocirsub);
19465           }
19466           if (b->verbose > 1) {
19467             printf("    Found set (%d, %d, %d, %d).\n", pointmark(pa),
19468                    pointmark(pb), pointmark(pc), pointmark(pd));
19469           }
19470           return true;
19471         }
19472       }
19473     }
19474     senextself(subloop);
19475   }
19476 
19477   return false;
19478 }
19479 
19481 //                                                                           //
19482 // tallcocirsubs()    Find all co-circular subfaces and save them in list.   //
19483 //                                                                           //
19485 
19486 void tetgenmesh::tallcocirsubs(REAL eps, bool enqflag)
19487 {
19488   face subloop;
19489 
19490   // Loop over all subfaces.
19491   subfaces->traversalinit();
19492   subloop.sh = shellfacetraverse(subfaces);
19493   while (subloop.sh != (shellface *) NULL) {
19494     checksub4cocir(&subloop, eps, true, enqflag);
19495     subloop.sh = shellfacetraverse(subfaces);
19496   }
19497 }
19498 
19500 //                                                                           //
19501 // tallencsegsfsubs()    Check for encroached segs from a list of subfaces.  //
19502 //                                                                           //
19504 
19505 bool tetgenmesh::tallencsegsfsubs(point testpt, list* cavsublist)
19506 {
19507   face startsub, checkseg;
19508   long oldencnum;
19509   int i, j;
19510 
19511   // Remember the current number of encroached segments.
19512   oldencnum = badsubsegs->items;
19513 
19514   // Check segments in the list of subfaces.
19515   for (i = 0; i < cavsublist->len(); i++) {
19516     startsub = * (face *)(* cavsublist)[i];
19517     // Test all three edges of startsub.
19518     for (j = 0; j < 3; j++) {
19519       sspivot(startsub, checkseg);
19520       if (checkseg.sh != dummysh) {
19521         if (!shell2badface(checkseg)) {
19522           checkseg4encroach(&checkseg, testpt, NULL, true);
19523         }
19524       }
19525       senextself(startsub);
19526     }
19527   }
19528 
19529   return (badsubsegs->items > oldencnum);
19530 }
19531 
19533 //                                                                           //
19534 // collectflipedges()    Collect edges of split subfaces for flip checking.  //
19535 //                                                                           //
19536 // 'inspoint' is a newly inserted segment point (inserted by insertsite()).  //
19537 // 'splitseg' is one of the two split subsegments. Some subfaces may be non- //
19538 // Delaunay since they're still not bonded to CDT. This routine collect all  //
19539 // such possible subfaces in 'flipqueue'.                                    //
19540 //                                                                           //
19542 
19543 void tetgenmesh::
19544 collectflipedges(point inspoint, face* splitseg, queue* flipqueue)
19545 {
19546   face startsh, spinsh, checksh;
19547   face nextseg;
19548   point pa, pb;
19549 
19550   // Let the dest of splitseg be inspoint.
19551   splitseg->shver = 0;
19552   if (sdest(*splitseg) != inspoint) {
19553     sesymself(*splitseg);
19554   }
19555 #ifdef SELF_CHECK
19556   assert(sdest(*splitseg) == inspoint);
19557 #endif
19558   pa = sorg(*splitseg);
19559   spivot(*splitseg, startsh);
19560   spinsh = startsh;
19561   do {
19562     findedge(&spinsh, pa, inspoint);
19563     senext2(spinsh, checksh);
19564     enqueueflipedge(checksh, flipqueue);
19565     spivotself(spinsh);
19566   } while (spinsh.sh != startsh.sh);
19567 
19568   // Get the next subsegment.
19569   senext(*splitseg, nextseg);
19570   spivotself(nextseg);
19571 #ifdef SELF_CHECK
19572   assert(nextseg.sh != (shellface *) NULL);
19573 #endif
19574 
19575   // Let the org of nextseg be inspoint.
19576   nextseg.shver = 0;
19577   if (sorg(nextseg) != inspoint) {
19578     sesymself(nextseg);
19579   }
19580 #ifdef SELF_CHECK
19581   assert(sorg(nextseg) == inspoint);
19582 #endif
19583   pb = sdest(nextseg);
19584   spivot(nextseg, startsh);
19585   spinsh = startsh;
19586   do {
19587     findedge(&spinsh, inspoint, pb);
19588     senext(spinsh, checksh);
19589     enqueueflipedge(checksh, flipqueue);
19590     spivotself(spinsh);
19591   } while (spinsh.sh != startsh.sh);
19592 }
19593 
19595 //                                                                           //
19596 // perturbrepairencsegs()    Repair all encroached segments.                 //
19597 //                                                                           //
19598 // All encroached segments are stored in 'badsubsegs'.  Each segment will be //
19599 // split by adding a perturbed point near its circumcenter.                  //
19600 //                                                                           //
19602 
19603 void tetgenmesh::perturbrepairencsegs(queue* flipqueue)
19604 {
19605   badface *encloop;
19606   tetrahedron encodedtet;
19607   triface splittet;
19608   face splitsub, symsplitsub;
19609   face splitseg, symsplitseg;
19610   point newpoint, sympoint;
19611   point pa, pb, pc;
19612   enum insertsiteresult success;
19613   enum locateresult loc, symloc;
19614   REAL cent[3], d1, ps, rs;
19615   int i, j;
19616 
19617   // Note that steinerleft == -1 if an unlimited number of Steiner points
19618   //   is allowed.  Loop until 'badsubsegs' is empty.
19619   badsubsegs->traversalinit();
19620   encloop = badfacetraverse(badsubsegs);
19621   while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19622     splitseg = encloop->ss;
19623 #ifdef SELF_CHECK
19624     assert(shell2badface(splitseg) == encloop);
19625 #endif
19626     setshell2badface(splitseg, NULL);
19627     pa = sorg(splitseg);
19628     pb = sdest(splitseg);
19629     if ((pa == encloop->forg) && (pb == encloop->fdest)) {
19630       if (b->verbose > 1) {
19631         printf("  Get seg (%d, %d).\n", pointmark(pa), pointmark(pb));
19632       }
19633       // Create the newpoint.
19634       makepoint(&newpoint);
19635       // Get the circumcenter and radius of ab.
19636       for (i = 0; i < 3; i++) cent[i] = 0.5 * (pa[i] + pb[i]);
19637       d1 = 0.5 * distance(pa, pb);
19638       // Add a random perturbation to newpoint along the vector ab.
19639       ps = randgenerator(d1 * 1.0e-3);
19640       rs = ps / d1;
19641       // Set newpoint (be at the perturbed circumcenter of ab).
19642       for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19643       setpointtype(newpoint, FREESEGVERTEX);
19644       // Set splitseg into the newpoint.
19645       setpoint2sh(newpoint, sencode(splitseg));
19646 
19647       // Is there periodic boundary condition?
19648       if (checkpbcs) {
19649         // Insert points on other segments of incident pbcgroups.
19650         i = shellmark(splitseg) - 1;
19651         for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
19652           makepoint(&sympoint);
19653           symloc = getsegpbcsympoint(newpoint, &splitseg, sympoint,
19654                                      &symsplitseg, segpglist[j]);
19655 #ifdef SELF_CHECK
19656           assert(symloc != OUTSIDE);
19657 #endif
19658           // Note: the symsplitseg and splitseg may be identical, in case
19659           //   when the the splitseg is the axis of the rotational sym.
19660           if ((symloc == ONEDGE) && (symsplitseg.sh != splitseg.sh)) {
19661             setpointtype(sympoint, FREESEGVERTEX);
19662             setpoint2sh(sympoint, sencode(symsplitseg));
19663             // Insert sympoint into DT.
19664             pc = sorg(symsplitseg);
19665             splittet.tet = dummytet;
19666             // Find a good start point to search.
19667             encodedtet = point2tet(pc);
19668             if (encodedtet != (tetrahedron) NULL) {
19669               decode(encodedtet, splittet);
19670               if (isdead(&splittet)) {
19671                 splittet.tet = dummytet;
19672               }
19673             }
19674             // Locate sympoint in DT.  Do exact location.
19675             success = insertsite(sympoint, &splittet, false, flipqueue);
19676 #ifdef SELF_CHECK
19677             assert(success != DUPLICATEPOINT);
19678 #endif
19679             if (success == OUTSIDEPOINT) {
19680               inserthullsite(sympoint, &splittet, flipqueue);
19681             }
19682             if (steinerleft > 0) steinerleft--;
19683             // Let sympoint remember splittet.
19684             setpoint2tet(sympoint, encode(splittet));
19685             // Do flip in DT.
19686             flip(flipqueue, NULL);
19687             // Insert sympoint into F.
19688             symloc = locateseg(sympoint, &symsplitseg);
19689             if (symloc == ONEDGE) {
19690               symsplitseg.shver = 0;
19691               spivot(symsplitseg, symsplitsub);
19692               // sympoint should on the edge of symsplitsub.
19693               splitsubedge(sympoint, &symsplitsub, flipqueue);
19694             } else {
19695               // insertsite() has done the whole job.
19696 #ifdef SELF_CHECK
19697               assert(symloc == ONVERTEX);
19698               assert(checksubfaces);
19699 #endif
19700               // Some edges may need to be flipped.
19701               collectflipedges(sympoint, &symsplitseg, flipqueue);
19702             }
19703             // Do flip in facet.
19704             flipsub(flipqueue);
19705           } else { // if (symloc == ONVERTEX) {
19706             // The symmtric point already exists. It is possible when two
19707             //   pbc group are idebtical. Omit sympoint.
19708             pointdealloc(sympoint);
19709           }
19710         }
19711       }
19712 
19713       // Insert newpoint into DT.
19714       splittet.tet = dummytet;
19715       // Find a good start point to search.
19716       encodedtet = point2tet(pa);
19717       if (encodedtet != (tetrahedron) NULL) {
19718         decode(encodedtet, splittet);
19719         if (isdead(&splittet)) {
19720           splittet.tet = dummytet;
19721         }
19722       }
19723       if (splittet.tet == dummytet) { // Try pb.
19724         encodedtet = point2tet(pb);
19725         if (encodedtet != (tetrahedron) NULL) {
19726           decode(encodedtet, splittet);
19727           if (isdead(&splittet)) {
19728             splittet.tet = dummytet;
19729           }
19730         }
19731       }
19732       // Locate the newpoint in DT.  Do exact location.
19733       success = insertsite(newpoint, &splittet, false, flipqueue);
19734 #ifdef SELF_CHECK
19735       assert(success != DUPLICATEPOINT);
19736 #endif
19737       if (success == OUTSIDEPOINT) {
19738         // A convex hull edge is mssing, and the inserting point lies
19739         //   (slightly) outside the convex hull due to the significant
19740         //   digits lost in the calculation. Enlarge the convex hull.
19741         inserthullsite(newpoint, &splittet, flipqueue);
19742       }
19743       if (steinerleft > 0) steinerleft--;
19744       // Let newpoint remember splittet.
19745       setpoint2tet(newpoint, encode(splittet));
19746       // Do flip in DT.
19747       flip(flipqueue, NULL);
19748       // Insert newpoint into F.
19749       loc = locateseg(newpoint, &splitseg);
19750       if (loc == ONEDGE) {
19751         splitseg.shver = 0;
19752         spivot(splitseg, splitsub);
19753         // newpoint should on the edge of splitsub.
19754         splitsubedge(newpoint, &splitsub, flipqueue);
19755       } else {
19756         // insertsite() has done the whole job.
19757 #ifdef SELF_CHECK
19758         assert(loc == ONVERTEX);
19759         assert(checksubfaces);
19760 #endif
19761         // Some edges may need to be flipped.
19762         collectflipedges(newpoint, &splitseg, flipqueue);
19763       }
19764       // Do flip in facet.
19765       flipsub(flipqueue);
19766     }
19767     // Remove this entry from list.
19768     badfacedealloc(badsubsegs, encloop);
19769     // Get the next encroached segments.
19770     encloop = badfacetraverse(badsubsegs);
19771   }
19772 }
19773 
19775 //                                                                           //
19776 // perturbrepairencsubs()    Repair all encroached subfaces.                 //
19777 //                                                                           //
19778 // All encroached subfaces are stored in 'badsubfaces'. Each subface will be //
19779 // split by adding a perturbed point near its circumcenter. However, if the  //
19780 // point encroaches some segments, it will not be inserted.  Instead, the    //
19781 // encroached segments are split.                                            //
19782 //                                                                           //
19784 
19785 void tetgenmesh::perturbrepairencsubs(list* cavsublist, queue* flipqueue)
19786 {
19787   badface *encloop, *encsubseg;
19788   tetrahedron encodedtet;
19789   triface splittet;
19790   face splitsub, symsplitsub;
19791   face checkseg, symsplitseg;
19792   point newpoint, sympoint;
19793   point pa, pb, pc, pd;
19794   enum insertsiteresult success;
19795   enum locateresult loc, symloc;
19796   REAL cent[3], d1, ps, rs;
19797   bool reject;
19798   int i;
19799 
19800   // Note that steinerleft == -1 if an unlimited number of Steiner points
19801   //   is allowed.  Loop until the list 'badsubfaces' is empty.
19802   while ((badsubfaces->items > 0) && (steinerleft != 0)) {
19803     badsubfaces->traversalinit();
19804     encloop = badfacetraverse(badsubfaces);
19805     while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19806       splitsub = encloop->ss;
19807 #ifdef SELF_CHECK
19808       assert(shell2badface(splitsub) == encloop);
19809 #endif
19810       setshell2badface(splitsub, NULL);
19811       pa = sorg(splitsub);
19812       pb = sdest(splitsub);
19813       pc = sapex(splitsub);
19814       // The subface may be not the same one when it was determined to be
19815       //   encroached.  If its adjacent encroached subface was split, the
19816       //   consequent flips may change it into another subface.
19817       if ((pa == encloop->forg) && (pb == encloop->fdest) &&
19818           (pc == encloop->fapex)) {
19819         if (b->verbose > 1) {
19820           printf("  Get subface (%d, %d, %d).\n", pointmark(pa),
19821                  pointmark(pb), pointmark(pc));
19822         }
19823         // Create the newpoint.
19824         makepoint(&newpoint);
19825         // Get the circumcenter of abc.
19826         circumsphere(pa, pb, pc, NULL, cent, &d1);
19827 #ifdef SELF_CHECK
19828         assert(d1 > 0.0);
19829 #endif
19830         // Add a random perturbation to newpoint along the vector a->cent.
19831         //   This way, the perturbed point still lies in the plane of abc.
19832         ps = randgenerator(d1 * 1.0e-3);
19833         rs = ps / d1;
19834         // Set newpoint (be at the perturbed circumcenter of abc).
19835         for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19836         // Get the abovepoint of the facet.
19837         abovepoint = facetabovepointarray[shellmark(splitsub)];
19838         // Do we need to calculate the abovepoint?
19839         if (abovepoint == (point) NULL) {
19840           getfacetabovepoint(&splitsub);
19841         }
19842         loc = locatesub(newpoint, &splitsub, 1, 0.0);
19843 #ifdef SELF_CHECK
19844         assert(loc != ONVERTEX);
19845 #endif
19846         if (loc != OUTSIDE) {
19847           // Add 'splitsub' into 'cavsublist'.
19848           cavsublist->append(&splitsub);
19849           // Collect all subfaces that encroached by newpoint.
19850           collectcavsubs(newpoint, cavsublist);
19851           // Find if there are encroached segments.
19852           reject = tallencsegsfsubs(newpoint, cavsublist);
19853           // Clear cavsublist for the next use.
19854           cavsublist->clear();
19855         } else {
19856           // newpoint lies outside. splitsub contains the boundary segment.
19857           sspivot(splitsub, checkseg);
19858 #ifdef SELF_CHECK
19859           assert(checkseg.sh != dummysh);
19860 #endif
19861           // Add this segment into list for splitting.
19862           if (b->verbose > 2) {
19863             printf("    Queuing boundary segment (%d, %d).\n",
19864                    pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
19865           }
19866           encsubseg = (badface *) badsubsegs->alloc();
19867           encsubseg->ss = checkseg;
19868           encsubseg->forg = sorg(checkseg);
19869           encsubseg->fdest = sdest(checkseg);
19870           encsubseg->foppo = (point) NULL;
19871           setshell2badface(encsubseg->ss, encsubseg);
19872           // Reject newpoint.
19873           reject = true;
19874         }
19875 
19876         if (!reject) {
19877           // newpoint is going to be inserted.
19878 
19879           // Is there periodic boundary condition?
19880           if (checkpbcs) {
19881             if (shellpbcgroup(splitsub) >= 0) {
19882               // Insert a point on another facet of the pbcgroup.
19883               makepoint(&sympoint);
19884               // Note: 'abovepoint' will be changed.
19885               symloc = getsubpbcsympoint(newpoint, &splitsub, sympoint,
19886                                          &symsplitsub);
19887 #ifdef SELF_CHECK
19888               assert(symloc != ONVERTEX);
19889 #endif
19890               setpoint2pbcpt(newpoint, sympoint);
19891               setpoint2pbcpt(sympoint, newpoint);
19892               setpointtype(sympoint, FREESUBVERTEX);
19893               // setpoint2sh(sympoint, sencode(symsplitsub));
19894               // Insert sympoint into DT.
19895               pd = sorg(symsplitsub);
19896               splittet.tet = dummytet;
19897               // Find a good start point to search.
19898               encodedtet = point2tet(pd);
19899               if (encodedtet != (tetrahedron) NULL) {
19900                 decode(encodedtet, splittet);
19901                 if (isdead(&splittet)) {
19902                   splittet.tet = dummytet;
19903                 }
19904               }
19905               // Locate sympoint in DT.  Do exact location.
19906               success = insertsite(sympoint, &splittet, false, flipqueue);
19907 #ifdef SELF_CHECK
19908               assert(success != DUPLICATEPOINT);
19909 #endif
19910               if (success == OUTSIDEPOINT) {
19911                 inserthullsite(sympoint, &splittet, flipqueue);
19912               }
19913               if (steinerleft > 0) steinerleft--;
19914               // Let sympoint remember splittet.
19915               setpoint2tet(sympoint, encode(splittet));
19916               // Do flip in DT.
19917               flip(flipqueue, NULL);
19918               // Insert sympoint into F.
19919               // getabovepoint(&symsplitsub);
19920               // symloc = locatesub(sympoint, &symsplitsub, 1, 0.0);
19921               if (symloc == ONFACE) {
19922                 splitsubface(sympoint, &symsplitsub, flipqueue);
19923               } else if (symloc == ONEDGE) {
19924                 splitsubedge(sympoint, &symsplitsub, flipqueue);
19925               } else {
19926                 // 'insertsite()' has done the whole job.
19927 #ifdef SELF_CHECK
19928                 assert(symloc == ONVERTEX);
19929                 assert(checksubfaces);
19930 #endif
19931                 // Split subfaces have been flipped.
19932                 flipqueue->clear();
19933               }
19934               // Do flip in facet.
19935               flipsub(flipqueue);
19936             }
19937           }
19938 
19939           // Insert newpoint into DT.
19940           splittet.tet = dummytet;
19941           // Find a good start point to search.
19942           encodedtet = point2tet(pa);
19943           if (encodedtet != (tetrahedron) NULL) {
19944             decode(encodedtet, splittet);
19945             if (isdead(&splittet)) {
19946               splittet.tet = dummytet;
19947             }
19948           }
19949           if (splittet.tet == dummytet) { // Try pb.
19950             encodedtet = point2tet(pb);
19951             if (encodedtet != (tetrahedron) NULL) {
19952               decode(encodedtet, splittet);
19953               if (isdead(&splittet)) {
19954                 splittet.tet = dummytet;
19955               }
19956             }
19957           }
19958           // Locate the newpoint in DT.  Do exact location.
19959           success = insertsite(newpoint, &splittet, false, flipqueue);
19960 #ifdef SELF_CHECK
19961           assert(success != DUPLICATEPOINT);
19962 #endif
19963           if (success == OUTSIDEPOINT) {
19964             inserthullsite(newpoint, &splittet, flipqueue);
19965           }
19966           if (steinerleft > 0) steinerleft--;
19967           // Let newpoint remember splittet.
19968           setpoint2tet(newpoint, encode(splittet));
19969           // Do flip in DT.
19970           flip(flipqueue, NULL);
19971           // Insert newpoint into F.
19972           // if (checkpbcs) {
19973             // 'abovepoint' has been changed.
19974             // getabovepoint(&splitsub);
19975             // loc = locatesub(newpoint, &splitsub, 1, 0.0);
19976           // }
19977           if (loc == ONFACE) {
19978             // Insert the newpoint in facet.
19979             splitsubface(newpoint, &splitsub, flipqueue);
19980           } else if (loc == ONEDGE) {
19981             // Insert the newpoint in facet.
19982             splitsubedge(newpoint, &splitsub, flipqueue);
19983           } else {
19984             // 'insertsite()' has done the whole job.
19985 #ifdef SELF_CHECK
19986             assert(loc == ONVERTEX);
19987             assert(checksubfaces);
19988 #endif
19989             // Split subfaces have been flipped.
19990             flipqueue->clear();
19991           }
19992           // Set the type of the newpoint.
19993           setpointtype(newpoint, FREESUBVERTEX);
19994           // Set splitsub into the newpoint.
19995           // setpoint2sh(newpoint, sencode(splitsub));
19996           // Do flip in the facet.
19997           flipsub(flipqueue);
19998 
19999           // Remove this entry from list.
20000           badfacedealloc(badsubfaces, encloop);
20001         } else {
20002           // newpoint is rejected. Remove it from points.
20003           pointdealloc(newpoint);
20004           // Repair all encroached segments.
20005           perturbrepairencsegs(flipqueue);
20006           // Do not remove 'encloop'. Later it will be tested again.
20007           setshell2badface(encloop->ss, encloop);
20008         }
20009       } else {
20010         // This subface has been changed. Remove this entry from list.
20011         badfacedealloc(badsubfaces, encloop);
20012         // It may be co-circular with its neighbors.
20013         // checksub4cocir(&splitsub, eps, false, true);
20014       }
20015       // Get the next encroached subfaces.
20016       encloop = badfacetraverse(badsubfaces);
20017     }
20018   }
20019 }
20020 
20022 //                                                                           //
20023 // incrperturbvertices()    Remove the local degeneracies in DT.             //
20024 //                                                                           //
20025 // A local degeneracy of a DT D is a set of 5 or more vertices which share a //
20026 // common sphere S and no other vertex of D in S.  D is not unique if it has //
20027 // local degeneracies. This routine removes the local degeneracies from D by //
20028 // inserting break points (as described in reference [2]).                   //
20029 //                                                                           //
20030 // 'eps' is a user-provided error tolerance. It is used to detect whether or //
20031 // not five points are approximate cospherical (evaluated in iscospheric()). //
20032 // Set it to 0.0 to disable it, i.e., only test pure degenerate point set.   //
20033 //                                                                           //
20035 
20036 void tetgenmesh::incrperturbvertices(REAL eps)
20037 {
20038   queue *flipqueue;
20039   list *cavsublist;
20040   long vertcount;
20041 
20042   if (!b->quiet) {
20043     printf("Perturbing vertices.\n");
20044   }
20045 
20046   vertcount = points->items;
20047   // Create a map from points to tets for fastening search.
20048   // makepoint2tetmap();  // This has been done in meshsurface().
20049 
20050   // Initialize working queues, lists.
20051   flipqueue = new queue(sizeof(badface));
20052   cavsublist = new list(sizeof(face), NULL, 256);
20053   // Initialize the pool of encroached subfaces and subsegments.
20054   badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20055   badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20056   // Find all pairs of co-circular subfaces.
20057   tallcocirsubs(eps, true);
20058   if (b->verbose && badsubfaces->items > 0) {
20059     printf("  Removing degenerate subfaces.\n");
20060   }
20061   perturbrepairencsubs(cavsublist, flipqueue);
20062 
20063   if (b->verbose > 0) {
20064     printf("  %ld break points.\n", points->items - vertcount);
20065   }
20066 
20067   delete cavsublist;
20068   delete flipqueue;
20069   delete badsubfaces;
20070   delete badsubsegs;
20071   badsubsegs = (memorypool *) NULL;
20072   badsubfaces = (memorypool *) NULL;
20073 }
20074 
20075 //
20076 // End of vertex perturbation routines
20077 //
20078 
20079 //
20080 // Begin of segment recovery routines
20081 //
20082 
20084 //                                                                           //
20085 // markacutevertices()    Mark acute vertices.                               //
20086 //                                                                           //
20087 // A vertex v is called acute if there are two segments sharing at v forming //
20088 // an acute angle (i.e. smaller than 90 degree).                             //
20089 //                                                                           //
20090 // This routine finds all acute vertices in the PLC and marks them as point- //
20091 // type ACUTEVERTEX. The other vertices of segments which are non-acute will //
20092 // be marked as NACUTEVERTEX.  Vertices which are not endpoints of segments  //
20093 // (such as DUPLICATEDVERTEX, UNUSEDVERTEX, etc) are not infected.           //
20094 //                                                                           //
20095 // NOTE: This routine should be called before Steiner points are introduced. //
20096 // That is, no point has type like FREESEGVERTEX, etc.                       //
20097 //                                                                           //
20099 
20100 void tetgenmesh::markacutevertices(REAL acuteangle)
20101 {
20102   shellface **segsperverlist;
20103   face segloop, nextseg;
20104   point pointloop, edest, eapex;
20105   REAL cosbound, anglearc;
20106   REAL v1[3], v2[3], L, D;
20107   bool isacute;
20108   int *idx2seglist;
20109   int acutecount;
20110   int idx, i, j, k;
20111 
20112   if (b->verbose > 0) {
20113     printf("  Marking acute vertices.\n");
20114   }
20115 
20116   anglearc = acuteangle * PI / 180.0;
20117   cosbound = cos(anglearc);
20118   acutecount = 0;
20119   // Constructing a map from vertex to segments.
20120   makesegmentmap(idx2seglist, segsperverlist);
20121 
20122   // Loop over the set of vertices.
20123   points->traversalinit();
20124   pointloop = pointtraverse();
20125   while (pointloop != (point) NULL) {
20126     idx = pointmark(pointloop) - in->firstnumber;
20127     // Only do test if p is an endpoint of some segments.
20128     if (idx2seglist[idx + 1] > idx2seglist[idx]) {
20129       // Init p to be non-acute.
20130       setpointtype(pointloop, NACUTEVERTEX);
20131       isacute = false;
20132       // Loop through all segments sharing at p.
20133       for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isacute; i++) {
20134         segloop.sh = segsperverlist[i];
20135         // segloop.shver = 0;
20136         if (sorg(segloop) != pointloop) sesymself(segloop);
20137         edest = sdest(segloop);
20138         for (j = i + 1; j < idx2seglist[idx + 1] && !isacute; j++) {
20139           nextseg.sh = segsperverlist[j];
20140           // nextseg.shver = 0;
20141           if (sorg(nextseg) != pointloop) sesymself(nextseg);
20142           eapex = sdest(nextseg);
20143           // Check the angle formed by segs (p, edest) and (p, eapex).
20144           for (k = 0; k < 3; k++) {
20145             v1[k] = edest[k] - pointloop[k];
20146             v2[k] = eapex[k] - pointloop[k];
20147           }
20148           L = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
20149           for (k = 0; k < 3; k++) v1[k] /= L;
20150           L = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
20151           for (k = 0; k < 3; k++) v2[k] /= L;
20152           D = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
20153           // Is D acute?
20154           isacute = (D >= cosbound);
20155         }
20156       }
20157       if (isacute) {
20158         // Mark p to be acute.
20159         setpointtype(pointloop, ACUTEVERTEX);
20160         acutecount++;
20161       }
20162     }
20163     pointloop = pointtraverse();
20164   }
20165 
20166   delete [] idx2seglist;
20167   delete [] segsperverlist;
20168 
20169   if ((b->verbose > 0) && (acutecount > 0)) {
20170     printf("  %d acute vertices.\n", acutecount);
20171   }
20172 }
20173 
20175 //                                                                           //
20176 // finddirection()    Find the first tetrahedron on the path from one point  //
20177 //                    to another.                                            //
20178 //                                                                           //
20179 // Find the tetrahedron that intersects a line segment L (from the origin of //
20180 // 'searchtet' to the point 'tend'), and returns the result in 'searchtet'.  //
20181 // The origin of 'searchtet' does not change, even though the tetrahedron    //
20182 // returned may differ from the one passed in.  This routine is used to find //
20183 // the direction to move in to get from one point to another.                //
20184 //                                                                           //
20185 // The return value notes the location of the line segment L with respect to //
20186 // 'searchtet':                                                              //
20187 //   - Returns RIGHTCOLLINEAR indicates L is collinear with the line segment //
20188 //     from the origin to the destination of 'searchtet'.                    //
20189 //   - Returns LEFTCOLLINEAR indicates L is collinear with the line segment  //
20190 //     from the origin to the apex of 'searchtet'.                           //
20191 //   - Returns TOPCOLLINEAR indicates L is collinear with the line segment   //
20192 //     from the origin to the opposite of 'searchtet'.                       //
20193 //   - Returns ACROSSEDGE indicates L intersects with the line segment from  //
20194 //     the destination to the apex of 'searchtet'.                           //
20195 //   - Returns ACROSSFACE indicates L intersects with the face opposite to   //
20196 //     the origin of 'searchtet'.                                            //
20197 //   - Returns BELOWHULL indicates L crosses outside the mesh domain. This   //
20198 //     can only happen when the domain is non-convex.                        //
20199 //                                                                           //
20200 // NOTE: This routine only works correctly when the mesh is exactly Delaunay.//
20201 //                                                                           //
20202 // If 'maxtetnumber' > 0, stop the searching process if the number of passed //
20203 // tets is larger than it. Return BELOWHULL.                                 //
20204 //                                                                           //
20206 
20207 enum tetgenmesh::finddirectionresult tetgenmesh::
20208 finddirection(triface *searchtet, point tend, long maxtetnumber)
20209 {
20210   triface neightet;
20211   point tstart, tdest, tapex, toppo;
20212   REAL ori1, ori2, ori3;
20213   long tetnumber;
20214 
20215   tstart = org(*searchtet);
20216 #ifdef SELF_CHECK
20217   assert(tstart != tend);
20218 #endif
20219   adjustedgering(*searchtet, CCW);
20220   if (tstart != org(*searchtet)) {
20221     enextself(*searchtet); // For keeping the same origin.
20222   }
20223   tdest = dest(*searchtet);
20224   if (tdest == tend) {
20225     return RIGHTCOLLINEAR;
20226   }
20227   tapex = apex(*searchtet);
20228   if (tapex == tend) {
20229     return LEFTCOLLINEAR;
20230   }
20231 
20232   ori1 = orient3d(tstart, tdest, tapex, tend);
20233   if (ori1 > 0.0) {
20234     // 'tend' is below the face, get the neighbor of this side.
20235     sym(*searchtet, neightet);
20236     if (neightet.tet != dummytet) {
20237       findorg(&neightet, tstart);
20238       adjustedgering(neightet, CCW);
20239       if (org(neightet) != tstart) {
20240         enextself(neightet); // keep the same origin.
20241       }
20242       // Set the changed configuratiuon.
20243       *searchtet = neightet;
20244       ori1 = -1.0;
20245       tdest = dest(*searchtet);
20246       tapex = apex(*searchtet);
20247     } else {
20248       // A hull face. Only possible for a nonconvex mesh.
20249 #ifdef SELF_CHECK
20250       assert(nonconvex);
20251 #endif
20252       return BELOWHULL;
20253     }
20254   }
20255 
20256   // Repeatedly change the 'searchtet', remain 'tstart' be its origin, until
20257   //   find a tetrahedron contains 'tend' or is crossed by the line segment
20258   //   from 'tstart' to 'tend'.
20259   tetnumber = 0l;
20260   while ((maxtetnumber > 0) && (tetnumber <= maxtetnumber)) {
20261     tetnumber++;
20262     toppo = oppo(*searchtet);
20263     if (toppo == tend) {
20264       return TOPCOLLINEAR;
20265     }
20266     ori2 = orient3d(tstart, toppo, tdest, tend);
20267     if (ori2 > 0.0) {
20268       // 'tend' is below the face, get the neighbor at this side.
20269       fnext(*searchtet, neightet);
20270       symself(neightet);
20271       if (neightet.tet != dummytet) {
20272         findorg(&neightet, tstart);
20273         adjustedgering(neightet, CCW);
20274         if (org(neightet) != tstart) {
20275           enextself(neightet); // keep the same origin.
20276         }
20277         // Set the changed configuration.
20278         *searchtet = neightet;
20279         ori1 = -1.0;
20280         tdest = dest(*searchtet);
20281         tapex = apex(*searchtet);
20282         // Continue the search from the changed 'searchtet'.
20283         continue;
20284       } else {
20285         // A hull face. Only possible for a nonconvex mesh.
20286 #ifdef SELF_CHECK
20287         assert(nonconvex);
20288 #endif
20289         return BELOWHULL;
20290       }
20291     }
20292     ori3 = orient3d(tapex, toppo, tstart, tend);
20293     if (ori3 > 0.0) {
20294       // 'tend' is below the face, get the neighbor at this side.
20295       enext2fnext(*searchtet, neightet);
20296       symself(neightet);
20297       if (neightet.tet != dummytet) {
20298         findorg(&neightet, tstart);
20299         adjustedgering(neightet, CCW);
20300         if (org(neightet) != tstart) {
20301           enextself(neightet); // keep the same origin.
20302         }
20303         // Set the changed configuration.
20304         *searchtet = neightet;
20305         ori1 = -1.0;
20306         tdest = dest(*searchtet);
20307         tapex = apex(*searchtet);
20308         // Continue the search from the changed 'searchtet'.
20309         continue;
20310       } else {
20311         // A hull face. Only possible for a nonconvex mesh.
20312 #ifdef SELF_CHECK
20313         assert(nonconvex);
20314 #endif
20315         return BELOWHULL;
20316       }
20317     }
20318     // Now 'ori1', 'ori2' and 'ori3' are possible be 0.0 or all < 0.0;
20319     if (ori1 < 0.0) {
20320       // Possible cases are: ACROSSFACE, ACROSSEDGE, TOPCOLLINEAR.
20321       if (ori2 < 0.0) {
20322         if (ori3 < 0.0) {
20323           return ACROSSFACE;
20324         } else { // ori3 == 0.0;
20325           // Cross edge (apex, oppo)
20326           enext2fnextself(*searchtet);
20327           esymself(*searchtet); // org(*searchtet) == tstart;
20328           return ACROSSEDGE;
20329         }
20330       } else { // ori2 == 0.0;
20331         if (ori3 < 0.0) {
20332           // Cross edge (dest, oppo)
20333           fnextself(*searchtet);
20334           esymself(*searchtet);
20335           enextself(*searchtet); // org(*searchtet) == tstart;
20336           return ACROSSEDGE;
20337         } else { // ori3 == 0.0;
20338           // Collinear with edge (org, oppo)
20339           return TOPCOLLINEAR;
20340         }
20341       }
20342     } else { // ori1 == 0.0;
20343       // Possible cases are: RIGHTCOLLINEAR, LEFTCOLLINEAR, ACROSSEDGE.
20344       if (ori2 < 0.0) {
20345         if (ori3 < 0.0) {
20346           // Cross edge (tdest, tapex)
20347           return ACROSSEDGE;
20348         } else { // ori3 == 0.0
20349           // Collinear with edge (torg, tapex)
20350           return LEFTCOLLINEAR;
20351         }
20352       } else { // ori2 == 0.0;
20353 #ifdef SELF_CHECK
20354         assert(ori3 != 0.0);
20355 #endif
20356         // Collinear with edge (torg, tdest)
20357         return RIGHTCOLLINEAR;
20358       }
20359     }
20360   }
20361   // Loop breakout. It may happen when the mesh is non-Delaunay.
20362   return BELOWHULL;
20363 }
20364 
20366 //                                                                           //
20367 // getsearchtet()    Find a tetrahedron whose origin is either 'p1' or 'p2'. //
20368 //                                                                           //
20369 // On return, the origin of 'searchtet' is either 'p1' or 'p2',  and 'tend'  //
20370 // returns the other point.  'searchtet' serves as the starting tetrahedron  //
20371 // for searching of the line segment from 'p1' to 'p2' or vice versa.        //
20372 //                                                                           //
20374 
20375 void tetgenmesh::getsearchtet(point p1, point p2, triface* searchtet,
20376   point* tend)
20377 {
20378   tetrahedron encodedtet1, encodedtet2;
20379 
20380   // Is there a valid handle provided by the user?
20381   if ((searchtet->tet != (tetrahedron *) NULL) && !isdead(searchtet)) {
20382     // Find which endpoint the handle holds.
20383     if (findorg(searchtet, p1)) {
20384       *tend = p2;
20385       return;
20386     } else {
20387       if (findorg(searchtet, p2)) {
20388         *tend = p1;
20389         return;
20390       }
20391     }
20392   }
20393   // If not, search the tet handle stored in 'p1' or 'p2'.
20394   *tend = (point) NULL;
20395   encodedtet1 = point2tet(p1);
20396   encodedtet2 = point2tet(p2);
20397   if (encodedtet1 != (tetrahedron) NULL) {
20398     decode(encodedtet1, *searchtet);
20399     // Be careful, here 'searchtet' may be dead.
20400     if (findorg(searchtet, p1)) {
20401       *tend = p2;
20402     }
20403   } else if (encodedtet2 != (tetrahedron) NULL) {
20404     decode(encodedtet2, *searchtet);
20405     // Be careful, here 'searchtet' may be dead.
20406     if (findorg(searchtet, p2)) {
20407       *tend = p1;
20408     }
20409   }
20410   // If still not, perform a full point location.  The starting tet is
20411   //   chosen as follows: Use the handle stored in 'p1' or 'p2' if it is
20412   //   alive; otherwise, start from a tet on the convex hull.
20413   if (*tend == (point) NULL) {
20414     if (encodedtet1 != (tetrahedron) NULL) {
20415       decode(encodedtet1, *searchtet);
20416       // Be careful, here 'searchtet' may be dead.
20417     }
20418     if (isdead(searchtet)) {
20419       if (encodedtet2 != (tetrahedron) NULL) {
20420         decode(encodedtet2, *searchtet);
20421         // Be careful, here 'searchtet' may be dead.
20422       }
20423       if (isdead(searchtet)) {
20424         searchtet->tet = dummytet;
20425         searchtet->loc = 0;
20426         symself(*searchtet);
20427       }
20428 #ifdef SELF_CHECK
20429       assert(!isdead(searchtet));
20430 #endif
20431     }
20432     if (locate(p1, searchtet) != ONVERTEX) {
20433       printf("Internal error in getsearchtet():  Failed to locate point\n");
20434       internalerror();
20435     }
20436     // Remember this handle in 'p1' to enhance the search speed.
20437     setpoint2tet(p1, encode(*searchtet));
20438     *tend = p2;
20439   }
20440 }
20441 
20443 //                                                                           //
20444 // isedgeencroached()    Check whether or not a subsegment is encroached.    //
20445 //                                                                           //
20446 // A segment with endpoints 'p1' and 'p2' is encroached by the point 'testpt'//
20447 // if it lies in the diametral sphere of this segment.  The degenerate case  //
20448 // that 'testpt' lies on the sphere is treated as encroached if 'degflag' is //
20449 // set to be TRUE.                                                           //
20450 //                                                                           //
20452 
20453 bool tetgenmesh::isedgeencroached(point p1, point p2, point testpt,
20454   bool degflag)
20455 {
20456   REAL dotproduct;
20457 
20458   // Check if the segment is facing an angle larger than 90 degree?
20459   dotproduct = (p1[0] - testpt[0]) * (p2[0] - testpt[0])
20460              + (p1[1] - testpt[1]) * (p2[1] - testpt[1])
20461              + (p1[2] - testpt[2]) * (p2[2] - testpt[2]);
20462   if (dotproduct < 0) {
20463     return true;
20464   } else if (dotproduct == 0 && degflag) {
20465     return true;
20466   } else {
20467     return false;
20468   }
20469 }
20470 
20472 //                                                                           //
20473 // scoutrefpoint()    Search the reference point of a missing segment.       //
20474 //                                                                           //
20475 // A segment S is missing in current Delaunay tetrahedralization DT and will //
20476 // be split by inserting a point V in it.  The two end points of S are the   //
20477 // origin of 'searchtet' and 'tend'. And we know that S is crossing the face //
20478 // of 'searchtet' opposite to its origin (may be intersecting with the edge  //
20479 // from the destination to the apex of the 'searchtet').  The search of P is //
20480 // completed by walking through all faces of DT across by S.                 //
20481 //                                                                           //
20482 // Warning:  This routine is correct when the tetrahedralization is Delaunay //
20483 // and convex. Otherwise, the search loop may not terminate.                 //
20484 //                                                                           //
20486 
20487 tetgenmesh::point tetgenmesh::scoutrefpoint(triface* searchtet, point tend)
20488 {
20489   triface checkface;
20490   point tstart, testpt, refpoint;
20491   REAL cent[3], radius, largest;
20492   REAL ahead;
20493   bool ncollinear;
20494   int sides;
20495 
20496   if (b->verbose > 2) {
20497     printf("  Scout the reference point of segment (%d, %d).\n",
20498            pointmark(org(*searchtet)), pointmark(tend));
20499   }
20500 
20501   tstart = org(*searchtet);
20502   refpoint = (point) NULL;
20503   largest = 0; // avoid compile warning.
20504 
20505   // Check the three vertices of the crossing face.
20506   testpt = apex(*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     refpoint = testpt;
20513     largest = radius;
20514   }
20515   testpt = dest(*searchtet);
20516   if (isedgeencroached(tstart, tend, testpt, true)) {
20517     ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20518 #ifdef SELF_CHECK
20519     assert(ncollinear);
20520 #endif
20521     if (refpoint == (point) NULL) {
20522       refpoint = testpt;
20523       largest = radius;
20524     } else {
20525       if (radius > largest) {
20526         refpoint = testpt;
20527         largest = radius;
20528       }
20529     }
20530   }
20531   testpt = oppo(*searchtet);
20532   if (isedgeencroached(tstart, tend, testpt, true)) {
20533     ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20534 #ifdef SELF_CHECK
20535     assert(ncollinear);
20536 #endif
20537     if (refpoint == (point) NULL) {
20538       refpoint = testpt;
20539       largest = radius;
20540     } else {
20541       if (radius > largest) {
20542         refpoint = testpt;
20543         largest = radius;
20544       }
20545     }
20546   }
20547   // Check the opposite vertex of the neighboring tet in case the segment
20548   //   crosses the edge (leftpoint, rightpoint) of the crossing face.
20549   sym(*searchtet, checkface);
20550   if (checkface.tet != dummytet) {
20551     testpt = oppo(checkface);
20552     if (isedgeencroached(tstart, tend, testpt, true)) {
20553       ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20554 #ifdef SELF_CHECK
20555       assert(ncollinear);
20556 #endif
20557       if (refpoint == (point) NULL) {
20558         refpoint = testpt;
20559         largest = radius;
20560       } else {
20561         if (radius > largest) {
20562           refpoint = testpt;
20563           largest = radius;
20564         }
20565       }
20566     }
20567   }
20568 
20569   // Walk through all crossing faces.
20570   enextfnext(*searchtet, checkface);
20571   sym(checkface, *searchtet);
20572   while (true) {
20573     // Check if we are reaching the boundary of the triangulation.
20574 #ifdef SELF_CHECK
20575     assert(searchtet->tet != dummytet);
20576 #endif
20577     // Search for an adjoining tetrahedron we can walk through.
20578     searchtet->ver = 0;
20579     // 'testpt' is the shared vertex for the following orientation tests.
20580     testpt = oppo(*searchtet);
20581     if (testpt == tend) {
20582       // The searching is finished.
20583       break;
20584     } else {
20585       // 'testpt' may encroach the segment.
20586       if ((testpt != tstart) && (testpt != refpoint)) {
20587         if (isedgeencroached(tstart, tend, testpt, true)) {
20588           ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20589           if (!ncollinear) {
20590             // 'testpt' is collinear with the segment. It may happen when a
20591             //   set of collinear and continuous segments is defined by two
20592             //   extreme endpoints.  In this case, we should choose 'testpt'
20593             //   as the splitting point immediately.  No new point should be
20594             //   created.
20595             refpoint = testpt;
20596             break;
20597           }
20598           if (refpoint == (point) NULL) {
20599             refpoint = testpt;
20600             largest = radius;
20601           } else {
20602             if (radius > largest) {
20603               refpoint = testpt;
20604               largest = radius;
20605             }
20606           }
20607         }
20608       }
20609     }
20610     // Check three side-faces of 'searchtet' to find the one through
20611     //   which we can walk next.
20612     for (sides = 0; sides < 3; sides++) {
20613       fnext(*searchtet, checkface);
20614       ahead = orient3d(org(checkface), dest(checkface), testpt, tend);
20615       if (ahead < 0.0) {
20616         // We can walk through this face and continue the searching.
20617         sym(checkface, *searchtet);
20618         break;
20619       }
20620       enextself(*searchtet);
20621     }
20622 #ifdef SELF_CHECK
20623     assert (sides < 3);
20624 #endif
20625   }
20626 
20627 #ifdef SELF_CHECK
20628   assert(refpoint != (point) NULL);
20629 #endif
20630   return refpoint;
20631 }
20632 
20634 //                                                                           //
20635 // getsegmentorigin()    Return the origin of the (unsplit) segment.         //
20636 //                                                                           //
20637 // After a segment (or a subsegment) is split. Two resulting subsegments are //
20638 // connecting each other through the pointers saved in their data fields.    //
20639 // With these pointers, the whole (unsplit) segment can be found. 'splitseg' //
20640 // may be a split subsegment.  Returns the origin of the unsplit segment.    //
20641 //                                                                           //
20643 
20644 tetgenmesh::point tetgenmesh::getsegmentorigin(face* splitseg)
20645 {
20646   face workseg;
20647   point farorg;
20648 
20649   farorg = sorg(*splitseg);
20650   if ((pointtype(farorg) != ACUTEVERTEX) &&
20651       (pointtype(farorg) != NACUTEVERTEX)) {
20652     workseg = *splitseg;
20653     do {
20654       senext2self(workseg);
20655       spivotself(workseg);
20656       if (workseg.sh != dummysh) {
20657         workseg.shver = 0;  // It's a subsegment.
20658         if (sdest(workseg) != farorg) {
20659           sesymself(workseg);
20660 #ifdef SELF_CHECK
20661           assert(sdest(workseg) == farorg);
20662 #endif
20663         }
20664         farorg = sorg(workseg);
20665         if ((pointtype(farorg) == ACUTEVERTEX) ||
20666             (pointtype(farorg) == NACUTEVERTEX)) break;
20667       }
20668     } while (workseg.sh != dummysh);
20669   }
20670 #ifdef SELF_CHECK
20671   assert((pointtype(farorg) == ACUTEVERTEX) ||
20672          (pointtype(farorg) == NACUTEVERTEX));
20673 #endif
20674   return farorg;
20675 }
20676 
20678 //                                                                           //
20679 // getsplitpoint()    Get a point for splitting a segment.                   //
20680 //                                                                           //
20681 // 'splitseg' is the segment will be split. 'refpoint' is a reference point  //
20682 // for splitting this segment. Moreover, it should not collinear with the    //
20683 // splitting segment. (The collinear case will be detected by iscollinear()  //
20684 // before entering this routine.)  The calculation of the splitting point is //
20685 // governed by three rules introduced in my paper.                           //
20686 //                                                                           //
20687 // After the position is calculated, a new point is created at this location.//
20688 // The new point has one of the two pointtypes: FREESEGVERTEX indicating it  //
20689 // is an inserting vertex on segment, and NACUTEVERTEX indicating it is an   //
20690 // endpoint of a segment which original has type-3 now becomes type-2.       //
20691 //                                                                           //
20693 
20694 tetgenmesh::point tetgenmesh::getsplitpoint(face* splitseg, point refpoint)
20695 {
20696   point splitpoint;
20697   point farorg, fardest;
20698   point ei, ej, ek, c;
20699   REAL v[3], r, split;
20700   REAL d1, d2, ps, rs;
20701   bool acuteorg, acutedest;
20702   int stype, rule;
20703   int i;
20704 
20705   // First determine the type of the segment (type-1, type-2, or type-3).
20706   farorg = getsegmentorigin(splitseg);
20707   acuteorg = (pointtype(farorg) == ACUTEVERTEX);
20708   sesymself(*splitseg);
20709   fardest = getsegmentorigin(splitseg);
20710   acutedest = (pointtype(fardest) == ACUTEVERTEX);
20711   sesymself(*splitseg);
20712 
20713   ek = (point) NULL; // avoid a compilation warning.
20714 
20715   if (acuteorg) {
20716     if (acutedest) {
20717       stype = 3;
20718     } else {
20719       stype = 2;
20720       ek = farorg;
20721     }
20722   } else {
20723     if (acutedest) {
20724       stype = 2;
20725       // Adjust splitseg, so that its origin is acute.
20726       sesymself(*splitseg);
20727       ek = fardest;
20728     } else {
20729       stype = 1;
20730     }
20731   }
20732   ei = sorg(*splitseg);
20733   ej = sdest(*splitseg);
20734 
20735   if (b->verbose > 1) {
20736     printf("  Splitting segment (%d, %d) type-%d with refpoint %d.\n",
20737            pointmark(ei), pointmark(ej), stype, pointmark(refpoint));
20738   }
20739 
20740   if (stype == 1 || stype == 3) {
20741     // Use rule-1.
20742     REAL eij, eip, ejp;
20743     eij = distance(ei, ej);
20744     eip = distance(ei, refpoint);
20745     ejp = distance(ej, refpoint);
20746     if ((eip < ejp) && (eip < 0.5 * eij)) {
20747       c = ei;
20748       r = eip;
20749     } else if ((eip > ejp) && (ejp < 0.5 * eij)) {
20750       c = ej;
20751       ej = ei;
20752       r = ejp;
20753     } else {
20754       c = ei;
20755       r = 0.5 * eij;
20756     }
20757     split = r / eij;
20758     for (i = 0; i < 3; i++) {
20759       v[i] = c[i] + split * (ej[i] - c[i]);
20760     }
20761     rule = 1;
20762   } else {
20763     // Use rule-2 or rule-3.
20764     REAL eki, ekj, ekp, evj, evp, eiv;
20765     c = ek;
20766     eki = distance(ek, ei);  // eki may equal zero.
20767     ekj = distance(ek, ej);
20768     ekp = distance(ek, refpoint);
20769     // Calculate v (the going to split position between ei, ej).
20770     r = ekp;
20771     // Check the validity of the position.
20772     if (!(eki < r && r < ekj)) {
20773       printf("Error:  Invalid PLC.\n");
20774       printf("  Hint:  Use -d switch to check it.\n");
20775       terminatetetgen(1);
20776     }
20777     split = r / ekj;
20778     for (i = 0; i < 3; i++) {
20779       v[i] = c[i] + split * (ej[i] - c[i]);
20780     }
20781     rule = 2;
20782     evj = ekj - r; // distance(v, ej);
20783     evp = distance(v, refpoint);
20784     if (evj < evp) {
20785       // v is rejected, use rule-3.
20786       eiv = distance(ei, v);
20787       if (evp <= 0.5 * eiv) {
20788         r = eki + eiv - evp;
20789       } else {
20790         r = eki + 0.5 * eiv;
20791       }
20792 #ifdef SELF_CHECK
20793       assert(eki < r && r < ekj);
20794 #endif
20795       split = r / ekj;
20796       for (i = 0; i < 3; i++) {
20797         v[i] = c[i] + split * (ej[i] - c[i]);
20798       }
20799       if (b->verbose > 1) {
20800         printf("    Using rule-3.\n");
20801       }
20802       rule = 3;
20803     }
20804   }
20805 
20806   // Accumulate the corresponding counters.
20807   if (rule == 1) r1count++;
20808   else if (rule == 2) r2count++;
20809   else if (rule == 3) r3count++;
20810 
20811   if (b->verbose > 1) {
20812     if (stype == 2) {
20813       printf("    Split = %.12g.\n", distance(ei, v) / distance(ei, ej));
20814     } else {
20815       printf("    Split = %.12g.\n", distance(c, v) / distance(c, ej));
20816     }
20817   }
20818 
20819   // Create the newpoint.
20820   makepoint(&splitpoint);
20821   // Add a random perturbation on splitpoint.
20822   d1 = distance(c, v);
20823   d2 = distance(refpoint, v);
20824   if (stype == 1 || stype == 3) {
20825     ps = randgenerator(d1 * 1.0e-3);
20826   } else {
20827     // For type-2 segment, add a smaller perturbation.
20828     // ps = randgenerator(d1 * 1.0e-5);
20829     // REAL d2 = distance(refpoint, v);
20830     ps = randgenerator(d2 * 1.0e-5);
20831   }
20832   rs = ps / d1;
20833   // Perturb splitpoint away from c.
20834   for (i = 0; i < 3; i++) {
20835     splitpoint[i] = c[i] + (1.0 + rs) * (v[i] - c[i]);
20836   }
20837   // for (i = 0; i < in->numberofpointattributes; i++) {
20838   //   splitpoint[i + 3] = c[i + 3] + (split + rs) * (ej[i + 3] - c[i + 3]);
20839   // }
20840   if (stype == 3) {
20841     // Change a type-3 segment into two type-2 segments.
20842     setpointtype(splitpoint, NACUTEVERTEX);
20843   } else {
20844     // Set it's type be FREESEGVERTEX.
20845     setpointtype(splitpoint, FREESEGVERTEX);
20846   }
20847   setpoint2sh(splitpoint, sencode(*splitseg));
20848 
20849   return splitpoint;
20850 }
20851 
20853 //                                                                           //
20854 // insertsegment()    Insert segment into DT. Queue it if it does not exist. //
20855 //                                                                           //
20857 
20858 bool tetgenmesh::insertsegment(face *insseg, list *misseglist)
20859 {
20860   badface *misseg;
20861   triface searchtet, spintet;
20862   point tend, checkpoint;
20863   point p1, p2;
20864   enum finddirectionresult collinear;
20865   int hitbdry;
20866 
20867   // Search segment ab in DT.
20868   p1 = (point) insseg->sh[3];
20869   p2 = (point) insseg->sh[4];
20870   getsearchtet(p1, p2, &searchtet, &tend);
20871   collinear = finddirection(&searchtet, tend, tetrahedrons->items);
20872   if (collinear == LEFTCOLLINEAR) {
20873     checkpoint = apex(searchtet);
20874     enext2self(searchtet);
20875     esymself(searchtet);
20876   } else if (collinear == RIGHTCOLLINEAR) {
20877     checkpoint = dest(searchtet);
20878   } else if (collinear == TOPCOLLINEAR) {
20879     checkpoint = oppo(searchtet);
20880     fnextself(searchtet);
20881     enext2self(searchtet);
20882     esymself(searchtet);
20883   } else {
20884     // assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
20885     checkpoint = (point) NULL;
20886   }
20887   if (checkpoint == tend) {
20888     // Segment exist. Bond it to all tets containing it.
20889     hitbdry = 0;
20890     adjustedgering(searchtet, CCW);
20891     fnextself(searchtet);
20892     spintet = searchtet;
20893     do {
20894       tssbond1(spintet, *insseg);
20895       if (!fnextself(spintet)) {
20896         hitbdry++;
20897         if (hitbdry < 2) {
20898           esym(searchtet, spintet);
20899           if (!fnextself(spintet)) {
20900             hitbdry++;
20901           }
20902         }
20903       }
20904     } while ((apex(spintet) != apex(searchtet)) && (hitbdry < 2));
20905     return true;
20906   } else {
20907     // Segment is missing.
20908     if (misseglist != (list *) NULL) {
20909       if (b->verbose > 2) {
20910         printf("    Queuing missing segment (%d, %d).\n", pointmark(p1),
20911                pointmark(p2));
20912       }
20913       misseg = (badface *) misseglist->append(NULL);
20914       misseg->ss = *insseg;
20915       misseg->forg = p1;
20916       misseg->fdest = p2;
20917       misseg->foppo = (point) NULL; // Not used.
20918       // setshell2badface(misseg->ss, misseg);
20919     }
20920     return false;
20921   }
20922 }
20923 
20925 //                                                                           //
20926 // tallmissegs()    Find and queue all missing segments in DT.               //
20927 //                                                                           //
20929 
20930 void tetgenmesh::tallmissegs(list *misseglist)
20931 {
20932   face segloop;
20933 
20934   if (b->verbose) {
20935     printf("  Queuing missing segments.\n");
20936   }
20937 
20938   subsegs->traversalinit();
20939   segloop.sh = shellfacetraverse(subsegs);
20940   while (segloop.sh != (shellface *) NULL) {
20941     insertsegment(&segloop, misseglist);
20942     segloop.sh = shellfacetraverse(subsegs);
20943   }
20944 }
20945 
20947 //                                                                           //
20948 // delaunizesegments()    Split segments repeatedly until they appear in a   //
20949 //                        Delaunay tetrahedralization.                       //
20950 //                                                                           //
20951 // Given a PLC X, which has a set V of vertices and a set of segments. Start //
20952 // from a Delaunay tetrahedralization D of V, this routine recovers segments //
20953 // of X in D by incrementally inserting points on missing segments, updating //
20954 // D with the newly inserted points into D', which remains to be a Delaunay  //
20955 // tetrahedralization and respects the segments of X. Hence, each segment of //
20956 // X appears as a union of edges in D'.                                      //
20957 //                                                                           //
20958 // This routine dynamically maintains two meshes, one is DT, another is the  //
20959 // surface mesh F of X.  DT and F have exactly the same vertices.  They are  //
20960 // updated simultaneously with the newly inserted points.                    //
20961 //                                                                           //
20962 // Missing segments are found by looping the set S of segments, checking the //
20963 // existence of each segment in DT.  Once a segment is found missing in DT,  //
20964 // it is split into two subsegments by inserting a point into both DT and F, //
20965 // and S is updated accordingly.  However, the inserted point may cause some //
20966 // other existing segments be non-Delaunay,  hence are missing from the DT.  //
20967 // In order to force all segments to appear in DT, we have to loop S again   //
20968 // after some segments are split. (A little ugly method)  Use a handle to    //
20969 // remember the last segment be split in one loop, hence all segments after  //
20970 // it are existing and need not be checked.                                  //
20971 //                                                                           //
20972 // In priciple, a segment on the convex hull should exist in DT. However, if //
20973 // there are four coplanar points on the convex hull, and the DT only can    //
20974 // contain one diagonal edge which is unfortunately not the segment, then it //
20975 // is missing. During the recovery of the segment, it is possible that the   //
20976 // calculated inserting point for recovering this convex hull segment is not //
20977 // exact enough and lies (slightly) outside the DT. In order to insert the   //
20978 // point, we enlarge the convex hull of the DT, so it can contain the point  //
20979 // and remains convex.  'inserthullsite()' is called for this case.          //
20980 //                                                                           //
20982 
20983 void tetgenmesh::delaunizesegments()
20984 {
20985   list *misseglist;
20986   queue *flipqueue;
20987   badface *misloop;
20988   tetrahedron encodedtet;
20989   triface searchtet, splittet;
20990   face splitsh, symsplitsub;
20991   face segloop, symsplitseg;
20992   point refpoint, splitpoint, sympoint;
20993   point tend, checkpoint;
20994   point p1, p2, pa;
20995   enum finddirectionresult collinear;
20996   enum insertsiteresult success;
20997   enum locateresult symloc;
20998   bool coll;
20999   long vertcount;
21000   int i, j;
21001 
21002   if (!b->quiet) {
21003     printf("Delaunizing segments.\n");
21004   }
21005 
21006   // Construct a map from points to tets for speeding point location.
21007   makepoint2tetmap();
21008   // Initialize a flipqueue.
21009   flipqueue = new queue(sizeof(badface));
21010   // Initialize the pool of missing segments.
21011   misseglist = new list(sizeof(badface), NULL, SUBPERBLOCK);
21012   // Looking for missing segments.
21013   tallmissegs(misseglist);
21014   // The DT contains segments now.
21015   checksubsegs = 1;
21016   // Remember the current number of points.
21017   vertcount = points->items;
21018   // Initialize the counters.
21019   r1count = r2count = r3count = 0l;
21020 
21021   // Loop until 'misseglist' is empty.
21022   while (misseglist->items > 0) {
21023     // Randomly pick a missing segment to recover.
21024     i = randomnation(misseglist->items);
21025     misloop = (badface *)(* misseglist)[i];
21026     segloop = misloop->ss;
21027     // Fill the "hole" in the list by filling the last one.
21028     *misloop = *(badface *)(* misseglist)[misseglist->items - 1];
21029     misseglist->items--;
21030     // Now recover the segment.
21031       p1 = (point) segloop.sh[3];
21032       p2 = (point) segloop.sh[4];
21033       if (b->verbose > 1) {
21034         printf("  Recover segment (%d, %d).\n", pointmark(p1), pointmark(p2));
21035       }
21036       getsearchtet(p1, p2, &searchtet, &tend);
21037       collinear = finddirection(&searchtet, tend, tetrahedrons->items);
21038       if (collinear == LEFTCOLLINEAR) {
21039         checkpoint = apex(searchtet);
21040       } else if (collinear == RIGHTCOLLINEAR) {
21041         checkpoint = dest(searchtet);
21042       } else if (collinear == TOPCOLLINEAR) {
21043         checkpoint = oppo(searchtet);
21044       } else {
21045 #ifdef SELF_CHECK
21046         assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
21047 #endif
21048         checkpoint = (point) NULL;
21049       }
21050       if (checkpoint != tend) {
21051         // ab is missing.
21052         splitpoint = (point) NULL;
21053         if (checkpoint != (point) NULL) {
21054           // An existing point c is found on the segment. It can happen when
21055           //   ab is defined by a long segment with c inside it. Use c to
21056           //   split ab. No new point is created.
21057           splitpoint = checkpoint;
21058           if (pointtype(checkpoint) == FREEVOLVERTEX) {
21059             // c is not a segment vertex yet. It becomes NACUTEVERTEX.
21060             setpointtype(splitpoint, NACUTEVERTEX);
21061           } else if (pointtype(checkpoint) == ACUTEVERTEX) {
21062             // c is an acute vertex. The definition of PLC is wrong.
21063           } else if (pointtype(checkpoint) == NACUTEVERTEX) {
21064             // c is an nonacute vertex. The definition of PLC is wrong.
21065           } else {
21066             // assert(0);
21067           }
21068         } else {
21069           // Find a reference point p of ab.
21070           refpoint = scoutrefpoint(&searchtet, tend);
21071           if (pointtype(refpoint) == FREEVOLVERTEX) {
21072             // p is an input point, check if it is nearly collinear with ab.
21073             coll = iscollinear(p1, p2, refpoint, b->epsilon);
21074             if (coll) {
21075               // a, b, and p are collinear. We insert p into ab. p becomes
21076               //   a segment vertex with type NACUTEVERTEX.
21077               splitpoint = refpoint;
21078               setpointtype(splitpoint, NACUTEVERTEX);
21079             }
21080           }
21081           if (splitpoint == (point) NULL) {
21082             // Calculate a split point v using rule 1, or 2, or 3.
21083             splitpoint = getsplitpoint(&segloop, refpoint);
21084 
21085             // Is there periodic boundary conditions?
21086             if (checkpbcs) {
21087               // Yes! Insert points on other segments of incident pbcgroups.
21088               i = shellmark(segloop) - 1;
21089               for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
21090                 makepoint(&sympoint);
21091                 symloc = getsegpbcsympoint(splitpoint, &segloop, sympoint,
21092                                            &symsplitseg, segpglist[j]);
21093 #ifdef SELF_CHECK
21094                 assert(symloc != OUTSIDE);
21095 #endif
21096                 if ((symloc == ONEDGE) && (symsplitseg.sh != segloop.sh)) {
21097 #ifdef SELF_CHECK
21098                   assert(symsplitseg.sh != dummysh);
21099 #endif
21100                   setpointtype(sympoint, FREESEGVERTEX);
21101                   setpoint2sh(sympoint, sencode(symsplitseg));
21102                   // Insert sympoint into DT.
21103                   pa = sorg(symsplitseg);
21104                   splittet.tet = dummytet;
21105                   // Find a good start point to search.
21106                   encodedtet = point2tet(pa);
21107                   if (encodedtet != (tetrahedron) NULL) {
21108                     decode(encodedtet, splittet);
21109                     if (isdead(&splittet)) {
21110                       splittet.tet = dummytet;
21111                     }
21112                   }
21113                   // Locate sympoint in DT.  Do exact location.
21114                   success = insertsite(sympoint, &splittet, false, flipqueue);
21115 #ifdef SELF_CHECK
21116                   assert(success != DUPLICATEPOINT);
21117 #endif
21118                   if (success == OUTSIDEPOINT) {
21119                     inserthullsite(sympoint, &splittet, flipqueue);
21120                   }
21121                   if (steinerleft > 0) steinerleft--;
21122                   // Let sympoint remember splittet.
21123                   setpoint2tet(sympoint, encode(splittet));
21124                   // Do flip in DT.
21125                   lawson(misseglist, flipqueue);
21126                   // Insert sympoint into F.
21127                   symsplitseg.shver = 0;
21128                   spivot(symsplitseg, symsplitsub);
21129                   // sympoint should on the edge of symsplitsub.
21130                   splitsubedge(sympoint, &symsplitsub, flipqueue);
21131                   // Do flip in facet.
21132                   flipsub(flipqueue);
21133                   // Insert the two subsegments.
21134                   symsplitseg.shver = 0;
21135                   insertsegment(&symsplitseg, misseglist);
21136                   senextself(symsplitseg);
21137                   spivotself(symsplitseg);
21138                   symsplitseg.shver = 0;
21139                   insertsegment(&symsplitseg, misseglist);
21140                 } else { // if (symloc == ONVERTEX) {
21141                   // The sympoint already exists. It is possible when two
21142                   //   pbc groups are exactly the same. Omit this point.
21143                   pointdealloc(sympoint);
21144                 }
21145               }
21146             }
21147 
21148             // Insert 'splitpoint' into DT.
21149             if (isdead(&searchtet)) searchtet.tet = dummytet;
21150             success = insertsite(splitpoint, &searchtet, false, flipqueue);
21151             if (success == OUTSIDEPOINT) {
21152               // A convex hull edge is missing, and the inserting point lies
21153               //   (slightly) outside the convex hull due to the significant
21154               //   digits lost in the calculation. Enlarge the convex hull.
21155               inserthullsite(splitpoint, &searchtet, flipqueue);
21156             }
21157             if (steinerleft > 0) steinerleft--;
21158             // Remember a handle in 'splitpoint' to enhance the speed of
21159             //   consequent point location.
21160             setpoint2tet(splitpoint, encode(searchtet));
21161             // Maintain Delaunayness in DT.
21162             lawson(misseglist, flipqueue);
21163           }
21164         }
21165         // Insert 'splitpoint' into F.
21166         spivot(segloop, splitsh);
21167         splitsubedge(splitpoint, &splitsh, flipqueue);
21168         flipsub(flipqueue);
21169         // Insert the two subsegments.
21170         segloop.shver = 0;
21171         insertsegment(&segloop, misseglist);
21172         senextself(segloop);
21173         spivotself(segloop);
21174         segloop.shver = 0;
21175         insertsegment(&segloop, misseglist);
21176       }
21177   }
21178 
21179   // Detach all segments from tets.
21180   tetrahedrons->traversalinit();
21181   searchtet.tet = tetrahedrontraverse();
21182   while (searchtet.tet != (tetrahedron *) NULL) {
21183     for (i = 0; i < 6; i++) {
21184       searchtet.tet[8 + i] = (tetrahedron) dummysh;
21185     }
21186     searchtet.tet = tetrahedrontraverse();
21187   }
21188   // No segments now.
21189   checksubsegs = 0;
21190 
21191   if (b->verbose > 0) {
21192     printf("  %ld protect points.\n", points->items - vertcount);
21193     printf("  R1: %ld,  R2: %ld,  R3: %ld.\n", r1count, r2count, r3count);
21194   }
21195 
21196   delete flipqueue;
21197   delete misseglist;
21198 }
21199 
21200 //
21201 // End of segments recovery routines
21202 //
21203 
21204 //
21205 // Begin of facet recovery routines
21206 //
21207 
21209 //                                                                           //
21210 // insertsubface()    Fix a subface in place.                                //
21211 //                                                                           //
21212 // Search a subface s in current tetrahedralization T.  If s is found a face //
21213 // face of T, it is inserted into T.  Return FALSE if s is not found in T.   //
21214 //                                                                           //
21216 
21217 bool tetgenmesh::insertsubface(face* insertsh, triface* searchtet)
21218 {
21219   triface spintet, symtet;
21220   face testsh, testseg;
21221   face spinsh, casin, casout;
21222   point tapex, checkpoint;
21223   enum finddirectionresult collinear;
21224   int hitbdry;
21225 
21226   // Search an edge of s.
21227   getsearchtet(sorg(*insertsh), sdest(*insertsh), searchtet, &checkpoint);
21228   collinear = finddirection(searchtet, checkpoint, tetrahedrons->items);
21229   if (collinear == LEFTCOLLINEAR) {
21230     enext2self(*searchtet);
21231     esymself(*searchtet);
21232   } else if (collinear == TOPCOLLINEAR) {
21233     fnextself(*searchtet);
21234     enext2self(*searchtet);
21235     esymself(*searchtet);
21236   }
21237   if (dest(*searchtet) != checkpoint) {
21238     // The edge doesn't exist => s is missing.
21239     return false;
21240   }
21241 
21242   // Search s by spinning faces around the edge.
21243   tapex = sapex(*insertsh);
21244   spintet = *searchtet;
21245   hitbdry = 0;
21246   do {
21247     if (apex(spintet) == tapex) {
21248       // Found s in T. Check if s has already been inserted.
21249       tspivot(spintet, testsh);
21250       if (testsh.sh == dummysh) {
21251         adjustedgering(spintet, CCW);
21252         findedge(insertsh, org(spintet), dest(spintet));
21253         tsbond(spintet, *insertsh);
21254         sym(spintet, symtet); // 'symtet' maybe outside, use it anyway.
21255         sesymself(*insertsh);
21256         tsbond(symtet, *insertsh);
21257       } else {
21258         // Found a duplicated subface (due to the redundant input).
21259         if (!b->quiet) {
21260           printf("Warning:  Two subfaces are found duplicated at ");
21261           printf("(%d, %d, %d)\n", pointmark(sorg(testsh)),
21262                  pointmark(sdest(testsh)), pointmark(sapex(testsh)));
21263           printf("  Subface of facet #%d is deleted.\n", shellmark(*insertsh));
21264           // printf("  Hint: -d switch can find all duplicated facets.\n");
21265         }
21266         shellfacedealloc(subfaces, insertsh->sh);
21267       }
21268       return true;
21269     }
21270     if (!fnextself(spintet)) {
21271       hitbdry ++;
21272       if (hitbdry < 2) {
21273         esym(*searchtet, spintet);
21274         if (!fnextself(spintet)) {
21275           hitbdry ++;
21276         }
21277       }
21278     }
21279   } while (hitbdry < 2 && apex(spintet) != apex(*searchtet));
21280 
21281   // s is missing.
21282   return false;
21283 }
21284 
21286 //                                                                           //
21287 // tritritest()    Test if two triangles are intersecting in their interior. //
21288 //                                                                           //
21289 // One triangle t1 is the face of 'checktet', the other t2 is given by three //
21290 // corners 'p1', 'p2' and 'p3'. This routine calls tri_tri_inter() to detect //
21291 // whether t1 and t2 exactly intersect in their interior. Cases like share a //
21292 // vertex, share an edge, or coincidence are considered not intersect.       //
21293 //                                                                           //
21295 
21296 bool tetgenmesh::tritritest(triface* checktet, point p1, point p2, point p3)
21297 {
21298   point forg, fdest, fapex;
21299   enum interresult intersect;
21300 
21301   forg = org(*checktet);
21302   fdest = dest(*checktet);
21303   fapex = apex(*checktet);
21304 
21305 #ifdef SELF_CHECK
21306   REAL ax, ay, az, bx, by, bz;
21307   REAL n[3];
21308   // face (torg, tdest, tapex) should not be degenerate. However p1, p2,
21309   //   and p3 may be collinear. Check it.
21310   ax = forg[0] - fdest[0];
21311   ay = forg[1] - fdest[1];
21312   az = forg[2] - fdest[2];
21313   bx = forg[0] - fapex[0];
21314   by = forg[1] - fapex[1];
21315   bz = forg[2] - fapex[2];
21316   n[0] = ay * bz - by * az;
21317   n[1] = az * bx - bz * ax;
21318   n[2] = ax * by - bx * ay;
21319   assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21320   // The components of n should not smaller than the machine epsilon.
21321 
21322   ax = p1[0] - p2[0];
21323   ay = p1[1] - p2[1];
21324   az = p1[2] - p2[2];
21325   bx = p1[0] - p3[0];
21326   by = p1[1] - p3[1];
21327   bz = p1[2] - p3[2];
21328   n[0] = ay * bz - by * az;
21329   n[1] = az * bx - bz * ax;
21330   n[2] = ax * by - bx * ay;
21331   assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21332   // The components of n should not smaller than the machine epsilon.
21333 #endif
21334 
21335   intersect = tri_tri_inter(forg, fdest, fapex, p1, p2, p3);
21336   return intersect == INTERSECT;
21337 }
21338 
21340 //                                                                           //
21341 // initializecavity()    Initialize the cavity.                              //
21342 //                                                                           //
21343 // A cavity C is bounded by a list of faces, called fronts.  Each front f is //
21344 // hold by a tet t adjacent to C, t is not in C (uninfected). If f is a hull //
21345 // face, t does't exist, a fake tet t' is created to hold f. t' has the same //
21346 // vertices as f but no opposite.  t' will be removed automatically after C  //
21347 // is filled with new tets (by carvecavity()).                               //
21348 //                                                                           //
21349 // The faces of C are given in two lists. 'floorlist' is a set of subfaces,  //
21350 // each subface has been oriented to face to the inside of C.  'ceillist' is //
21351 // a set of tetrahedral faces. 'frontlist' returns the initialized fronts.   //
21352 //                                                                           //
21354 
21355 void tetgenmesh::initializecavity(list* floorlist, list* ceillist,
21356   list* frontlist)
21357 {
21358   triface neightet, casingtet;
21359   triface faketet;
21360   face worksh;
21361   int i;
21362 
21363   // Initialize subfaces of C.
21364   for (i = 0; i < floorlist->len(); i++) {
21365     // Get a subface s.
21366     worksh = * (face *)(* floorlist)[i];
21367 #ifdef SELF_CHECK
21368     // Current side of s should be empty.
21369     stpivot(worksh, neightet);
21370     assert(neightet.tet == dummytet);
21371 #endif
21372     // Get the adjacent tet t.
21373     sesymself(worksh);
21374     stpivot(worksh, casingtet);
21375     // Does t exist?
21376     if (casingtet.tet == dummytet) {
21377       // Create a fake tet t' to hold f temporarily.
21378       maketetrahedron(&faketet);
21379       setorg(faketet, sorg(worksh));
21380       setdest(faketet, sdest(worksh));
21381       setapex(faketet, sapex(worksh));
21382       setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21383       tsbond(faketet, worksh);
21384       frontlist->append(&faketet);
21385     } else {
21386       frontlist->append(&casingtet);
21387     }
21388   }
21389   // Initialize tet faces of C.
21390   for (i = 0; i < ceillist->len(); i++) {
21391     // Get a tet face c.
21392     neightet = * (triface *) (* ceillist)[i];
21393 #ifdef SELF_CHECK
21394     // The tet of c must be inside C (going to be deleted).
21395     assert(infected(neightet));
21396 #endif
21397     // Get the adjacent tet t.
21398     sym(neightet, casingtet);
21399     // Does t exist?
21400     if (casingtet.tet == dummytet) {
21401       // No. Create a fake tet t' to hold f temporarily.
21402       maketetrahedron(&faketet);
21403       // Be sure that the vertices of t' are CCW oriented.
21404       adjustedgering(neightet, CW); // CW edge ring.
21405       setorg(faketet, org(neightet));
21406       setdest(faketet, dest(neightet));
21407       setapex(faketet, apex(neightet));
21408       setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21409       // Bond t' to a subface if it exists.
21410       tspivot(neightet, worksh);
21411       if (worksh.sh != dummysh) {
21412         sesymself(worksh);
21413         tsbond(faketet, worksh);
21414       }
21415       // Bond c <--> t'. So we're able to find t' and remove it.
21416       bond(faketet, neightet);
21417       // c may become uninfected due to the bond().
21418       infect(neightet);
21419       frontlist->append(&faketet);
21420     } else {
21421       frontlist->append(&casingtet);
21422     }
21423   }
21424 }
21425 
21427 //                                                                           //
21428 // retrievenewtets()    Retrieve the newly created tets.                     //
21429 //                                                                           //
21430 // On input, 'newtetlist' contains at least one alive new tet. From this tet,//
21431 // other new tets can be found by a broadth-first searching.                 //
21432 //                                                                           //
21434 
21435 void tetgenmesh::retrievenewtets(list* newtetlist)
21436 {
21437   triface searchtet, casingtet;
21438   int i;
21439 
21440   // There may be dead tets due to flip32(). Delete them first.
21441   for (i = 0; i < newtetlist->len(); i++) {
21442     searchtet = * (triface *)(* newtetlist)[i];
21443     if (isdead(&searchtet)) {
21444       newtetlist->del(i, 0); i--;
21445       continue;
21446     }
21447     infect(searchtet);
21448   }
21449   // Find all new tets.
21450   for (i = 0; i < newtetlist->len(); i++) {
21451     searchtet = * (triface *)(* newtetlist)[i];
21452     for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
21453       sym(searchtet, casingtet);
21454       if ((casingtet.tet != dummytet) && !infected(casingtet)) {
21455         infect(casingtet);
21456         newtetlist->append(&casingtet);
21457       }
21458     }
21459   }
21460   // Uninfect new tets.
21461   for (i = 0; i < newtetlist->len(); i++) {
21462     searchtet = * (triface *)(* newtetlist)[i];
21463     uninfect(searchtet);
21464   }
21465 }
21466 
21468 //                                                                           //
21469 // delaunizecavvertices()    Form a DT of the vertices of a cavity.          //
21470 //                                                                           //
21471 // 'floorptlist' and 'ceilptlist' are the vertices of the cavity.            //
21472 //                                                                           //
21473 // The tets of the DT are created directly in the pool 'tetrahedrons', i.e., //
21474 // no auxiliary data structure and memory are required.  The trick is at the //
21475 // time they're created, there are no connections between them to the other  //
21476 // tets in the pool. You can imagine they form an ioslated island.           //
21477 //                                                                           //
21479 
21480 void tetgenmesh::delaunizecavvertices(triface* oldtet, list* floorptlist,
21481   list* ceilptlist, list* newtetlist, queue* flipque)
21482 {
21483   point *insertarray;
21484   triface bakhulltet, newtet;
21485   long bakhullsize;
21486   long arraysize;
21487   int bakchksub;
21488   int i, j;
21489 
21490   // Prepare the array of points for inserting.
21491   arraysize = floorptlist->len();
21492   if (ceilptlist != (list *) NULL) {
21493     arraysize += ceilptlist->len();
21494   }
21495   insertarray = new point[arraysize];
21496   for (i = 0; i < floorptlist->len(); i++) {
21497     insertarray[i] = * (point *)(* floorptlist)[i];
21498   }
21499   if (ceilptlist != (list *) NULL) {
21500     for (j = 0; j < ceilptlist->len(); j++) {
21501       insertarray[i + j] = * (point *)(* ceilptlist)[j];
21502     }
21503   }
21504 
21505   // The incrflipdelaunay() is re-used. Backup global variables.
21506   decode(dummytet[0], bakhulltet);
21507   bakhullsize = hullsize;
21508   bakchksub = checksubfaces;
21509   checksubfaces = 0;
21510   b->verbose--;
21511 
21512   // Form the DT by incremental flip Delaunay algorithm. Do not jump for
21513   //   point location, do not merge points.
21514   incrflipdelaunay(oldtet, insertarray, arraysize, false, false, 0.0, flipque);
21515 
21516   // Get a tet in D.
21517   decode(dummytet[0], newtet);
21518   newtetlist->append(&newtet);
21519   // Get all tets of D.
21520   retrievenewtets(newtetlist);
21521 
21522   // Restore global variables.
21523   dummytet[0] = encode(bakhulltet);
21524   hullsize = bakhullsize;
21525   checksubfaces = bakchksub;
21526   b->verbose++;
21527 
21528   delete [] insertarray;
21529 }
21530 
21532 //                                                                           //
21533 // insertauxsubface()    Fix an auxilary subface in place.                   //
21534 //                                                                           //
21535 // An auxilary subface s is fixed in D as it is a real subface, but s has no //
21536 // vertices and neighbors. It has two uses: (1) it protects an identfied     //
21537 // front f in D; (2) it serves the link to bond a tet in C and f later. The  //
21538 // first neighbor of s (s->sh[0]) stores a pointer to f.                     //
21539 //                                                                           //
21540 // 'front' is a front f of C. idfront' t is a tet in D where f is identified //
21541 // be a face of it. s will be fixed between t and its neighbor.              //
21542 //                                                                           //
21544 
21545 void tetgenmesh::insertauxsubface(triface* front, triface* idfront)
21546 {
21547   triface neightet;
21548   face auxsh;
21549 
21550   // Create the aux subface s.
21551   makeshellface(subfaces, &auxsh);
21552   // Bond s <--> t.
21553   tsbond(*idfront, auxsh);
21554   // Does t's neighbor n exist?
21555   sym(*idfront, neightet);
21556   if (neightet.tet != dummytet) {
21557     // Bond s <--> n.
21558     sesymself(auxsh);
21559     tsbond(neightet, auxsh);
21560   }
21561   // Let s remember f.
21562   auxsh.sh[0] = (shellface) encode(*front);
21563 }
21564 
21566 //                                                                           //
21567 // scoutfront()    Scout a face in D.                                        //
21568 //                                                                           //
21569 // Search a 'front' f in D. If f is found, return TRUE and the face of D is  //
21570 // returned in 'idfront'. Otherwise, return FALSE.                           //
21571 //                                                                           //
21573 
21574 bool tetgenmesh::scoutfront(triface* front, triface* idfront, list* newtetlist)
21575 {
21576   triface spintet;
21577   point pa, pb, pc;
21578   enum locateresult loc;
21579   enum finddirectionresult col;
21580   int hitbdry;
21581   int i;
21582 
21583   // Let the front we're searching is abc.
21584   pa = org(*front);
21585   pb = dest(*front);
21586   // Get a tet in D for searching.
21587   *idfront = recenttet;
21588   // Make sure the tet is valid (it may be killed by flips).
21589   if (isdead(idfront)) {
21590     // The tet is dead. Search a live tet in D. !!!
21591     for (i = 0; i < newtetlist->len(); i++) {
21592       recenttet = * (triface *)(* newtetlist)[i];
21593       if (!isdead(&recenttet)) break;
21594     }
21595     assert(i < newtetlist->len());
21596   }
21597 
21598   // Search a tet having vertex a.
21599   loc = preciselocate(pa, idfront, (long) newtetlist->len());
21600   UNUSED_OPT(loc);
21601   assert(loc == ONVERTEX);
21602   recenttet = *idfront;
21603   // Search a tet having edge ab.
21604   col = finddirection(idfront, pb, (long) newtetlist->len());
21605   if (col == RIGHTCOLLINEAR) {
21606     // b is just the destination.
21607   } else if (col == LEFTCOLLINEAR) {
21608     enext2self(*idfront);
21609     esymself(*idfront);
21610   } else if (col == TOPCOLLINEAR) {
21611     fnextself(*idfront);
21612     enext2self(*idfront);
21613     esymself(*idfront);
21614   }
21615 
21616   if (dest(*idfront) == pb) {
21617     // Search a tet having face abc
21618     pc = apex(*front);
21619     spintet = *idfront;
21620     hitbdry = 0;
21621     do {
21622       if (apex(spintet) == pc) {
21623         // Found abc. Insert an auxilary subface s at idfront.
21624         // insertauxsubface(front, &spintet);
21625         *idfront = spintet;
21626         return true;
21627       }
21628       if (!fnextself(spintet)) {
21629         hitbdry ++;
21630         if (hitbdry < 2) {
21631           esym(*idfront, spintet);
21632           if (!fnextself(spintet)) {
21633             hitbdry ++;
21634           }
21635         }
21636       }
21637       if (apex(spintet) == apex(*idfront)) break;
21638     } while (hitbdry < 2);
21639   }
21640 
21641   // f is missing in D.
21642   if (b->verbose > 2) {
21643     printf("    Front (%d, %d, %d) is missing.\n", pointmark(pa),
21644            pointmark(pb), pointmark(apex(*front)));
21645   }
21646   return false;
21647 }
21648 
21650 //                                                                           //
21651 // gluefronts()    Glue two fronts together.                                 //
21652 //                                                                           //
21653 // This is a support routine for identifyfront().  Two fronts f and f1 are   //
21654 // found indentical. This is caused by the non-coplanarity of vertices of a  //
21655 // facet. Hence f and f1 are a subface and a tet. They are not fronts of the //
21656 // cavity anymore. This routine glues f and f1 together.                     //
21657 //                                                                           //
21659 
21660 void tetgenmesh::gluefronts(triface* front, triface* front1)
21661 {
21662   face consh;
21663 
21664   // Glue f and f1 together. There're four cases:
21665   //   (1) both f and f1 are not fake;
21666   //   (2) f is not fake, f1 is fake;
21667   //   (3) f is fake and f1 is not fake;
21668   //   (4) both f and f1 are fake.
21669   // Case (4) should be not possible.
21670 
21671   // Is there a concrete subface c at f.
21672   tspivot(*front, consh);
21673   if (consh.sh != dummysh) {
21674     sesymself(consh);
21675     tsbond(*front1, consh); // Bond: f1 <--> c.
21676     sesymself(consh);
21677   }
21678   // Does f hold by a fake tet.
21679   if (oppo(*front) == (point) NULL) {
21680     // f is fake. Case (3) or (4).
21681     assert(oppo(*front1) != (point) NULL); // Eliminate (4).
21682     // Case (3).
21683     if (consh.sh != dummysh) {
21684       stdissolve(consh);  // Dissolve: c -x-> f.
21685     }
21686     // Dealloc f.
21687     tetrahedrondealloc(front->tet);
21688     // f1 becomes a hull. let 'dummytet' bond to it.
21689     dummytet[0] = encode(*front1);
21690   } else {
21691     // Case (1) or (2).
21692     bond(*front, *front1); // Bond f1 <--> f.
21693   }
21694   // Is f a fake tet?
21695   if (!isdead(front)) {
21696     // No. Check for case (2).
21697     tspivot(*front1, consh);
21698     // Is f1 fake?
21699     if (oppo(*front1) == (point) NULL) {
21700       // Case (2) or (4)
21701       assert(oppo(*front) != (point) NULL); // Eliminate (4).
21702       // Case (2).
21703       if (consh.sh != dummysh) {
21704         stdissolve(consh);  // Dissolve: c -x-> f1.
21705         sesymself(consh); // Bond: f <--> c.
21706         tsbond(*front, consh);
21707       }
21708       // Dissolve: f -x->f1.
21709       dissolve(*front);
21710       // Dealloc f1.
21711       tetrahedrondealloc(front1->tet);
21712       // f becomes a hull. let 'dummytet' bond to it.
21713       dummytet[0] = encode(*front);
21714     } else {
21715       // Case (1).
21716       if (consh.sh != dummysh) {
21717         sesymself(consh);
21718         tsbond(*front, consh); // Bond: f <--> c.
21719       }
21720     }
21721   }
21722 }
21723 
21725 //                                                                           //
21726 // identifyfronts()    Identify cavity faces in D.                           //
21727 //                                                                           //
21728 // 'frontlist' are fronts of C need indentfying.  This routine searches each //
21729 // front f in D. Once f is found, an auxilary subface s is inserted in D at  //
21730 // the face. If f is not found in D, remove it from frontlist and save it in //
21731 // 'misfrontlist'.                                                           //
21732 //                                                                           //
21734 
21735 bool tetgenmesh::identifyfronts(list* frontlist, list* misfrontlist,
21736   list* newtetlist)
21737 {
21738   triface front, front1, tfront;
21739   triface idfront, neightet;
21740   face auxsh;
21741   int len, i, j;
21742 
21743   misfrontlist->clear();
21744   // Set a new tet in D for searching.
21745   recenttet = * (triface *)(* newtetlist)[0];
21746 
21747   // Identify all fronts in D.
21748   for (i = 0; i < frontlist->len(); i++) {
21749     // Get a front f.
21750     front = * (triface *)( *frontlist)[i];
21751     if (scoutfront(&front, &idfront, newtetlist)) {
21752       // Found f. Insert an aux subface s.
21753       assert((idfront.tet != dummytet) && !isdead(&idfront));
21754       // Does s already exist?
21755       tspivot(idfront, auxsh);
21756       if (auxsh.sh != dummysh) {
21757         // There're two identical fronts, f (front) and f1 (s.sh[0])!
21758         decode((tetrahedron) auxsh.sh[0], front1);
21759         assert((front1.tet != dummytet) && !infected(front1));
21760         // Detach s in D.
21761         tsdissolve(idfront);
21762         sym(idfront, neightet);
21763         if (neightet.tet != dummytet) {
21764           tsdissolve(neightet);
21765         }
21766         // s has fulfilled its duty. Can be deleted.
21767         shellfacedealloc(subfaces, auxsh.sh);
21768         // Remove f from frontlist.
21769         frontlist->del(i, 1); i--;
21770         // Remove f1 from frontlist.
21771         len = frontlist->len();
21772         for (j = 0; j < frontlist->len(); j++) {
21773           tfront = * (triface *)(* frontlist)[j];
21774           if ((tfront.tet == front1.tet) && (tfront.loc == front1.loc)) {
21775             // Found f1 in list.  Check f1 != f.
21776             assert((tfront.tet != front.tet) || (tfront.loc != front.loc));
21777             frontlist->del(j, 1); i--;
21778             break;
21779           }
21780         }
21781         assert((frontlist->len() + 1) == len);
21782         UNUSED_OPT(len);
21783         // Glue f and f1 together.
21784         gluefronts(&front, &front1);
21785       } else {
21786         // Insert an aux subface to protect f in D.
21787         insertauxsubface(&front, &idfront);
21788       }
21789     } else {
21790       // f is missing.
21791       frontlist->del(i, 1); i--;
21792       // Are there two identical fronts, f (front) and f1 (front1)?
21793       for (j = 0; j < misfrontlist->len(); j++) {
21794         front1 = * (triface *)(* misfrontlist)[j];
21795         if (isfacehaspoint(&front1, org(front)) &&
21796             isfacehaspoint(&front1, dest(front)) &&
21797             isfacehaspoint(&front1, apex(front))) break;
21798       }
21799       if (j < misfrontlist->len()) {
21800         // Found an identical front f1. Remove f1 from the list.
21801         misfrontlist->del(j, 1);
21802         // Glue f and f1 together.
21803         gluefronts(&front, &front1);
21804       } else {
21805         // Add f into misfrontlist.
21806         misfrontlist->append(&front);
21807       }
21808     }
21809   }
21810   return misfrontlist->len() == 0;
21811 }
21812 
21814 //                                                                           //
21815 // detachauxsubfaces()    Detach auxilary subfaces in D.                     //
21816 //                                                                           //
21817 // This is a reverse routine of identifyfronts(). Some fronts are missing in //
21818 // D. C can not be easily tetrahedralized. It needs remediation (expansion,  //
21819 // or constrained flips, or adding a Steiner point).  This routine detaches  //
21820 // the auxilary subfaces have been inserted in D and delete them.            //
21821 //                                                                           //
21823 
21824 void tetgenmesh::detachauxsubfaces(list* newtetlist)
21825 {
21826   triface newtet, neightet;
21827   face auxsh;
21828   int i;
21829 
21830   for (i = 0; i < newtetlist->len(); i++) {
21831     // Get a new tet t.
21832     newtet = * (triface *)(* newtetlist)[i];
21833     // t may e dead due to flips.
21834     if (isdead(&newtet)) continue;
21835     assert(!infected(newtet));
21836     // Check the four faces of t.
21837     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
21838       tspivot(newtet, auxsh);
21839       if (auxsh.sh != dummysh) {
21840         // An auxilary subface s.
21841         assert(sorg(auxsh) == (point) NULL);
21842         tsdissolve(newtet);  // t -x-> s.
21843         sym(newtet, neightet);
21844         if (neightet.tet != dummytet) {
21845           assert(!isdead(&neightet));
21846           tsdissolve(neightet); // n -x-> s.
21847         }
21848         // Delete s.
21849         shellfacedealloc(subfaces, auxsh.sh);
21850       }
21851     }
21852   }
21853 }
21854 
21856 //                                                                           //
21857 // expandcavity()    Expand the cavity by adding new fronts.                 //
21858 //                                                                           //
21859 // This is the support routine for delaunizecavity().  Some fronts of C are  //
21860 // missing in D since they're not strongly Delaunay. Such fronts are removed //
21861 // and the faces of the tets abutting to them are added. C is then expanded. //
21862 // Some removed faces may be subfaces, they're queued to recover later. D is //
21863 // expanded simultaneously with the new vertices of the new fronts.          //
21864 //                                                                           //
21866 
21867 void tetgenmesh::expandcavity(list* frontlist, list* misfrontlist,
21868   list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
21869 {
21870   triface misfront, newfront, casingtet, crosstet;
21871   triface searchtet, faketet, bakhulltet;
21872   face checksh;
21873   point pd;
21874   enum insertsiteresult success;
21875   long bakhullsize;
21876   int bakchksub;
21877   int i, j, k;
21878 
21879   if (b->verbose > 1) {
21880     printf("    Expand cavity (%d missing fronts).\n", misfrontlist->len());
21881   }
21882   // Increase the number of expanded times.
21883   expcavcount++;
21884   // The incrflipdelaunay() is re-used. Backup global variables.
21885   decode(dummytet[0], bakhulltet);
21886   bakhullsize = hullsize;
21887   bakchksub = checksubfaces;
21888   checksubfaces = 0;
21889   b->verbose--;
21890 
21891   // Choose a tet in D for searching.
21892   recenttet = * (triface *)(* newtetlist)[0];
21893   assert((recenttet.tet != dummytet) && !isdead(&recenttet));
21894 
21895   // Loop through 'misfrontlist'.
21896   for (i = 0; i < misfrontlist->len(); i++) {
21897     // Get a missing front f.
21898     misfront = * (triface *)(* misfrontlist)[i];
21899     // C will be expanded at f.
21900     if (b->verbose > 1) {
21901       printf("    Get misfront (%d, %d, %d).\n", pointmark(org(misfront)),
21902              pointmark(dest(misfront)), pointmark(apex(misfront)));
21903     }
21904     // Is f has a subface s?
21905     tspivot(misfront, checksh);
21906     if (checksh.sh != dummysh) {
21907       // A subface s is found. Check whether f is expandable at s.
21908       sym(misfront, crosstet);
21909       if (!infected(crosstet)) {
21910         // f is not expandable. In principle is should not happen. However,
21911         //   it can happen when PBC is in use.
21912         assert(checkpbcs);
21913         // Skip expanding f. It will be processed later.
21914         continue;
21915       }
21916       // Temporarily remove s. Queue and recover it later.
21917       if (b->verbose > 1) {
21918         printf("    Queuing subface (%d, %d, %d).\n",
21919                pointmark(sorg(checksh)), pointmark(sdest(checksh)),
21920                pointmark(sapex(checksh)));
21921       }
21922       // Detach s from tets at its both sides.
21923       tsdissolve(misfront);
21924       tsdissolve(crosstet);
21925       // Detach tets at from s.
21926       stdissolve(checksh);
21927       sesymself(checksh);
21928       stdissolve(checksh);
21929       // Mark and queue it.
21930       sinfect(checksh);
21931       missingshqueue->push(&checksh);
21932     }
21933     // f may already be processed (become a cross tet of C).
21934     if (infected(misfront)) continue;
21935     // Get the point p = oppo(t), t is the tet holds f.
21936     pd = oppo(misfront);
21937 #ifdef SELF_CHECK
21938     // t must not be fake.
21939     assert(pd != (point) NULL);
21940 #endif
21941     // Insert p in D. p may not be inserted if it is one of the two cases:
21942     //   (1) p is already a vertex of D;
21943     //   (2) p lies outside the CH of D;
21944     searchtet = recenttet;
21945     // Make sure the tet is valid (it may be killed by flips).
21946     if (isdead(&searchtet)) {
21947       // The tet is dead. Get a live tet in D. !!!
21948       for (j = 0; j < newtetlist->len(); j++) {
21949         recenttet = * (triface *)(* newtetlist)[j];
21950         if (!isdead(&recenttet)) break;
21951       }
21952       assert(j < newtetlist->len());
21953       searchtet = recenttet;
21954     }
21955     success = insertsite(pd, &searchtet, false, flipque);
21956     if (success == OUTSIDEPOINT) {
21957       // case (2). Insert p onto CH of D.
21958       inserthullsite(pd, &searchtet, flipque);
21959     }
21960     if (success != DUPLICATEPOINT) {
21961       // p is inserted. Recover Delaunness of D by flips.
21962       flip(flipque, NULL);
21963     }
21964     // Expand C by adding new fronts. The three faces of t which have p as a
21965     //   vertex become new fronts. However, if a new front is coincident with
21966     //   an old front of C, it is not added and the old front is removed.
21967     adjustedgering(misfront, CCW);
21968     for (j = 0; j < 3; j++) {
21969       // Notice: Below I mis-used the names. 'newfront' is not exactly a new
21970       //   front, instead the 'casingtet' should be called new front.
21971       // Get a new front f_n.
21972       fnext(misfront, newfront);
21973       // Get the neighbor tet n at f_n.
21974       sym(newfront, casingtet);
21975       // Is n a cross tet?
21976       if (!infected(casingtet)) {
21977         // f_n becomes a new front of C.
21978         // Does n exist?
21979         if (casingtet.tet == dummytet) {
21980           // Create a fake tet n' to hold f_n temporarily.
21981           maketetrahedron(&faketet);
21982           // Be sure that the vertices of fake tet are CCW oriented.
21983           adjustedgering(newfront, CW); // CW edge ring.
21984           setorg(faketet, org(newfront));
21985           setdest(faketet, dest(newfront));
21986           setapex(faketet, apex(newfront));
21987           setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21988           // Bond n' to a subface if it exists.
21989           tspivot(newfront, checksh);
21990           if (checksh.sh != dummysh) {
21991             sesymself(checksh);
21992             tsbond(faketet, checksh);
21993           }
21994           // Bond f_n <--> n'. So we're able to find n' and remove it.
21995           bond(faketet, newfront);
21996           frontlist->append(&faketet);
21997         } else {
21998           // Add n to frontlist.
21999           frontlist->append(&casingtet);
22000         }
22001       } else {
22002         // f_n is coincident with an existing front f' of C. f' is no longer
22003         //   a front, remove it from frontlist.  Use the inverse order to
22004         //   search f' (most likely, a newly added front may be f').
22005         for (k = frontlist->len() - 1; k >= 0; k--) {
22006           searchtet = * (triface *)(* frontlist)[k];
22007           if ((newfront.tet == searchtet.tet) &&
22008               (newfront.loc == searchtet.loc)) {
22009             frontlist->del(k, 0);
22010             break;
22011           }
22012         }
22013         // Is f_n a subface?
22014         tspivot(newfront, checksh);
22015         if (checksh.sh != dummysh) {
22016           // Temporarily remove checksh. Make it missing. recover it later.
22017           if (b->verbose > 2) {
22018             printf("    Queuing subface (%d, %d, %d).\n",
22019                    pointmark(sorg(checksh)), pointmark(sdest(checksh)),
22020                    pointmark(sapex(checksh)));
22021           }
22022           tsdissolve(newfront);
22023           tsdissolve(casingtet);
22024           // Detach tets at the both sides of checksh.
22025           stdissolve(checksh);
22026           sesymself(checksh);
22027           stdissolve(checksh);
22028           sinfect(checksh);
22029           missingshqueue->push(&checksh);
22030         }
22031       }
22032       enextself(misfront);
22033     }
22034     // C has been expanded at f. t becomes a cross tet.
22035     if (!infected(misfront)) {
22036       // t will be deleted, queue it.
22037       infect(misfront);
22038       crosstetlist->append(&misfront);
22039     }
22040   }
22041 
22042   // Loop through misfrontlist, remove infected misfronts.
22043   for (i = 0; i < misfrontlist->len(); i++) {
22044     misfront = * (triface *)(* misfrontlist)[i];
22045     if (infected(misfront)) {
22046       // Remove f, keep original list order.
22047       misfrontlist->del(i, 1);
22048       i--;
22049     }
22050   }
22051 
22052   // Are we done?
22053   if (misfrontlist->len() > 0) {
22054     // No. There are unexpandable fronts.
22055     // expandcavity_sos(misfrontlist);
22056     assert(0); // Not done yet.
22057   }
22058 
22059   // D has been updated (by added new tets or dead tets) (due to flips).
22060   retrievenewtets(newtetlist);
22061 
22062   // Restore global variables.
22063   dummytet[0] = encode(bakhulltet);
22064   hullsize = bakhullsize;
22065   checksubfaces = bakchksub;
22066   b->verbose++;
22067 }
22068 
22070 //                                                                           //
22071 // carvecavity()    Remove redundant (outside) tetrahedra from D.            //
22072 //                                                                           //
22073 // The fronts of C have been identified in D. Hence C can be tetrahedralized //
22074 // by removing the tets outside C. The CDT is then updated by filling C with //
22075 // the remaining tets (inside C) of D.                                       //
22076 //                                                                           //
22077 // Each front is protected by an auxilary subface s in D. s has a pointer to //
22078 // f (s.sh[0]). f can be used to classified the in- and out- tets of C (the  //
22079 // CW orientation of f faces to the inside of C). The classified out-tets of //
22080 // C are marked (infected) for removing.                                     //
22081 //                                                                           //
22082 // Notice that the out-tets may not only the tets on the CH of C,  but also  //
22083 // tets completely inside D, eg., there is a "hole" in D.  Such tets must be //
22084 // marked during classification. The hole tets are poped up and removed too. //
22085 //                                                                           //
22087 
22088 void tetgenmesh::carvecavity(list* newtetlist, list* outtetlist,
22089   queue* flipque)
22090 {
22091   triface newtet, neightet, front, outtet;
22092   face auxsh, consh;
22093   point pointptr;
22094   REAL ori;
22095   int i;
22096 
22097   // Clear work list.
22098   outtetlist->clear();
22099 
22100   // Classify in- and out- tets in D. Mark and queue classified out-tets.
22101   for (i = 0; i < newtetlist->len(); i++) {
22102     // Get a new tet t.
22103     newtet = * (triface *)(* newtetlist)[i];
22104     assert(!isdead(&newtet));
22105     // Look for aux subfaces attached at t.
22106     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22107       tspivot(newtet, auxsh);
22108       if (auxsh.sh != dummysh) {
22109         // Has this side a neighbor n?
22110         sym(newtet, neightet);
22111         if (neightet.tet != dummytet) {
22112           // Classify t and n (one is "in" and another is "out").
22113           // Get the front f.
22114           decode((tetrahedron) auxsh.sh[0], front);
22115           // Let f face to the inside of C.
22116           adjustedgering(front, CW);
22117           ori = orient3d(org(front), dest(front), apex(front), oppo(newtet));
22118           assert(ori != 0.0);
22119           if (ori < 0.0) {
22120             // t is in-tet. n is out-tet.
22121             outtet = neightet;
22122           } else {
22123             // n is in-tet. t is out-tet.
22124             outtet = newtet;
22125           }
22126           // Add the out-tet into list.
22127           if (!infected(outtet)) {
22128             infect(outtet);
22129             outtetlist->append(&outtet);
22130           }
22131         }
22132       }
22133     }
22134   }
22135 
22136   // Find and mark all out-tets.
22137   for (i = 0; i < outtetlist->len(); i++) {
22138     outtet = * (triface *)(* outtetlist)[i];
22139     for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22140       sym(outtet, neightet);
22141       // Does the neighbor exist and unmarked?
22142       if ((neightet.tet != dummytet) && !infected(neightet)) {
22143         // Is it protected by an aux subface?
22144         tspivot(outtet, auxsh);
22145         if (auxsh.sh == dummysh) {
22146           // It's an out-tet.
22147           infect(neightet);
22148           outtetlist->append(&neightet);
22149         }
22150       }
22151     }
22152   }
22153 
22154   // Remove the out- (and hole) tets.
22155   for (i = 0; i < outtetlist->len(); i++) {
22156     // Get an out-tet t.
22157     outtet = * (triface *)(* outtetlist)[i];
22158     // Detach t from the in-tets.
22159     for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22160       // Is there an aux subface s?
22161       tspivot(outtet, auxsh);
22162       if (auxsh.sh != dummysh) {
22163         // Get the neighbor n.
22164         sym(outtet, neightet);
22165         assert(!infected(neightet)); // t must be in-tet.
22166         // Detach n -x-> t.
22167         dissolve(neightet);
22168       }
22169     }
22170     // Dealloc the tet.
22171     tetrahedrondealloc(outtet.tet);
22172   }
22173 
22174   // Connect the in-tets of C to fronts. Remove aux subfaces and fake tets.
22175   for (i = 0; i < newtetlist->len(); i++) {
22176     // Get a new tet t.
22177     newtet = * (triface *)(* newtetlist)[i];
22178     // t may be an out-tet and has got deleted.
22179     if (isdead(&newtet)) continue;
22180     // t is an in-tet. Look for aux subfaces attached at t.
22181     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22182       // Is there an aux subface s?
22183       tspivot(newtet, auxsh);
22184       if (auxsh.sh != dummysh) {
22185         // Get the front f.
22186         decode((tetrahedron) auxsh.sh[0], front);
22187         assert((front.tet != dummytet) && !infected(front));
22188         // s has fulfilled its duty. Can be deleted.
22189         tsdissolve(newtet); // dissolve: t -x-> s.
22190         // Delete s.
22191         shellfacedealloc(subfaces, auxsh.sh);
22192         // Connect the newtet t and front f.
22193         // Is there a concrete subface c at f.
22194         tspivot(front, consh);
22195         if (consh.sh != dummysh) {
22196           sesymself(consh);
22197           // Bond: t <--> c.
22198           tsbond(newtet, consh);
22199         }
22200         // Does f hold by a fake tet.
22201         if (oppo(front) == (point) NULL) {
22202           // f is fake.
22203           if (consh.sh != dummysh) {
22204             sesymself(consh);
22205             // Dissolve: c -x-> f.
22206             stdissolve(consh);
22207           }
22208           // Dealloc f.
22209           tetrahedrondealloc(front.tet);
22210           // f becomes a hull. let 'dummytet' bond to it.
22211           dummytet[0] = encode(newtet);
22212         } else {
22213           // Bond t <--> f.
22214           bond(newtet, front);
22215         }
22216         // t may be non-locally Delaunay and flipable.
22217         if (flipque != (queue *) NULL) {
22218           enqueueflipface(newtet, flipque);
22219         }
22220       }
22221     }
22222     // Let the corners of t2 point to it for fast searching.
22223     pointptr = org(newtet);
22224     setpoint2tet(pointptr, encode(newtet));
22225     pointptr = dest(newtet);
22226     setpoint2tet(pointptr, encode(newtet));
22227     pointptr = apex(newtet);
22228     setpoint2tet(pointptr, encode(newtet));
22229     pointptr = oppo(newtet);
22230     setpoint2tet(pointptr, encode(newtet));
22231   }
22232   // The cavity has been re-tetrahedralized.
22233 }
22234 
22236 //                                                                           //
22237 // delaunizecavity()    Tetrahedralize a cavity by Delaunay tetrahedra.      //
22238 //                                                                           //
22239 // The cavity C is bounded by a set of triangles in 'floorlist' (a list of   //
22240 // coplanar subfaces) and 'ceillist' (a list of tetrahedral faces lie above  //
22241 // the subfaces). 'floorptlist' and 'ceilptlist' are the vertices of C.      //
22242 //                                                                           //
22244 
22245 void tetgenmesh::delaunizecavity(list* floorlist, list* ceillist,
22246   list* ceilptlist, list* floorptlist, list* frontlist, list* misfrontlist,
22247   list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
22248 {
22249   int vertnum;
22250 
22251   vertnum = floorptlist->len();
22252   vertnum += (ceilptlist != (list *) NULL ? ceilptlist->len() : 0);
22253   if (b->verbose > 1) {
22254     printf("    Delaunizing cavity (%d floors, %d ceilings, %d vertices).\n",
22255            floorlist->len(), ceillist->len(), vertnum);
22256   }
22257   // Save the size of the largest cavity.
22258   if ((floorlist->len() + ceillist->len()) > maxcavfaces) {
22259     maxcavfaces = floorlist->len() + ceillist->len();
22260   }
22261   if (vertnum > maxcavverts) {
22262     maxcavverts = vertnum;
22263   }
22264 
22265   // Clear these lists.
22266   frontlist->clear();
22267   misfrontlist->clear();
22268   newtetlist->clear();
22269 
22270   // Initialize the cavity C.
22271   initializecavity(floorlist, ceillist, frontlist);
22272   // Form the D of the vertices of C.
22273   delaunizecavvertices(NULL, floorptlist, ceilptlist, newtetlist, flipque);
22274   // Identify faces of C in D.
22275   while (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
22276     // Remove protecting subfaces, keep new tets.
22277     detachauxsubfaces(newtetlist);
22278     // Expand C and updateing D.
22279     expandcavity(frontlist, misfrontlist, newtetlist, crosstetlist,
22280                  missingshqueue, flipque);
22281   }
22282   // All fronts have identified in D. Get the shape of C by removing out
22283   //   tets of C. 'misfrontlist' is reused for removing out tets.
22284   carvecavity(newtetlist, misfrontlist, NULL);
22285 }
22286 
22288 //                                                                           //
22289 // formmissingregion()    Form the missing region.                           //
22290 //                                                                           //
22291 // 'missingsh' is a missing subface.  Start from it we can form the missing  //
22292 // region R (a set of connected missing subfaces).  Because all missing sub- //
22293 // faces have been marked (infected) before. R can be formed by checking the //
22294 // neighbors of 'missingsh', and the neighbors of the neighbors, and so on.  //
22295 // Stop checking further at either a segment or an unmarked subface.         //
22296 //                                                                           //
22297 // 'missingshlist' returns R. The edge ring of subfaces of R are oriented in //
22298 // the same direction. 'equatptlist' returns the vertices of R, each vertex  //
22299 // is marked with '1' (in 'worklist').                                       //
22300 //                                                                           //
22302 
22303 void tetgenmesh::formmissingregion(face* missingsh, list* missingshlist,
22304   list* equatptlist, int* worklist)
22305 {
22306   face neighsh, worksh, workseg;
22307   point workpt[3];
22308   int idx, i, j;
22309 
22310   // Add 'missingsh' into 'missingshlist'.
22311   missingshlist->append(missingsh);
22312   // Save and mark its three vertices.
22313   workpt[0] = sorg(*missingsh);
22314   workpt[1] = sdest(*missingsh);
22315   workpt[2] = sapex(*missingsh);
22316   for (i = 0; i < 3; i++) {
22317     idx = pointmark(workpt[i]) - in->firstnumber;
22318     worklist[idx] = 1;
22319     equatptlist->append(&workpt[i]);
22320   }
22321   // Temporarily uninfect it (avoid to save it again).
22322   suninfect(*missingsh);
22323 
22324   // Find the other missing subfaces.
22325   for (i = 0; i < missingshlist->len(); i++) {
22326     // Get a missing subface.
22327     worksh = * (face *)(* missingshlist)[i];
22328     // Check three neighbors of this face.
22329     for (j = 0; j < 3; j++) {
22330       sspivot(worksh, workseg);
22331       if (workseg.sh == dummysh) {
22332         spivot(worksh, neighsh);
22333         if (sinfected(neighsh)) {
22334           // Find a missing subface, adjust the face orientation.
22335           if (sorg(neighsh) != sdest(worksh)) {
22336             sesymself(neighsh);
22337           }
22338           if (b->verbose > 2) {
22339             printf("    Add missing subface (%d, %d, %d).\n",
22340                    pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
22341                    pointmark(sapex(neighsh)));
22342           }
22343           missingshlist->append(&neighsh);
22344           // Save and mark its apex.
22345           workpt[0] = sapex(neighsh);
22346           idx = pointmark(workpt[0]) - in->firstnumber;
22347           // Has workpt[0] been added?
22348           if (worklist[idx] == 0) {
22349             worklist[idx] = 1;
22350             equatptlist->append(&workpt[0]);
22351           }
22352           // Temporarily uninfect it (avoid to save it again).
22353           suninfect(neighsh);
22354         }
22355       }
22356       senextself(worksh);
22357     }
22358   }
22359 
22360   // R has been formed. Infect missing subfaces again.
22361   for (i = 0; i < missingshlist->len(); i++) {
22362     worksh = * (face *)(* missingshlist)[i];
22363     sinfect(worksh);
22364   }
22365 }
22366 
22368 //                                                                           //
22369 // rearrangesubfaces()    Rearrange the set of subfaces of a missing region  //
22370 //                        so that they conform to the faces of DT.           //
22371 //                                                                           //
22372 // The missing region formed by subfaces of 'missingshlist' contains a set   //
22373 // of degenerate vertices, hence the set of subfaces don't match the set of  //
22374 // faces in DT.  Instead of forcing them to present in DT, we re-arrange the //
22375 // connection of them so that the new subfaces conform to the faces of DT.   //
22376 // 'boundedgelist' is a set of boundary edges of the region, these edges(may //
22377 // be subsegments) must exist in DT.                                         //
22378 //                                                                           //
22379 // On completion, we have created and inserted a set of new subfaces which   //
22380 // conform to faces of DT. The set of old subfaces in 'missingshlist' are    //
22381 // deleted. The region vertices in 'equatptlist' are unmarked.               //
22382 //                                                                           //
22384 
22385 void tetgenmesh::rearrangesubfaces(list* missingshlist, list* boundedgelist,
22386   list* equatptlist, int* worklist)
22387 {
22388   link *boundedgelink;
22389   link *newshlink;
22390   triface starttet, spintet, neightet, worktet;
22391   face shloop, newsh, neighsh, spinsh, worksh;
22392   face workseg, casingin, casingout;
22393   point torg, tdest, workpt;
22394   point spt1, spt2, spt3;
22395   enum finddirectionresult collinear;
22396   enum shestype shtype;
22397   REAL area;
22398   bool matchflag, finishflag;
22399   int shmark, pbcgp, idx, hitbdry;
22400   int i, j;
22401 
22402   // Initialize the boundary edge link.
22403   boundedgelink = new link(sizeof(face), NULL, 256);
22404   // Initialize the new subface link.
22405   newshlink = new link(sizeof(face), NULL, 256);
22406   // Remember the type (skinny or not) of replaced subfaces.  They should
22407   //   all have the same type since there is no segment inside the region.
22408   worksh = * (face *)(* missingshlist)[0];
22409   shtype = shelltype(worksh);
22410   // The following loop is only for checking purpose.
22411   for (i = 1; i < missingshlist->len(); i++) {
22412     worksh = * (face *)(* missingshlist)[i];
22413     assert(shelltype(worksh) == shtype);
22414   }
22415   // To avoid compilation warnings.
22416   shmark = pbcgp = 0;
22417   area = 0.0;
22418 
22419   // Create an initial boundary link.
22420   for (i = 0; i < boundedgelist->len(); i++) {
22421     shloop = * (face *)(* boundedgelist)[i];
22422     if (i == 0) {
22423       // 'shmark' will be set to all new created subfaces.
22424       shmark = shellmark(shloop);
22425       if (b->quality && varconstraint) {
22426         // area will be copied to all new created subfaces.
22427         area = areabound(shloop);
22428       }
22429       if (checkpbcs) {
22430         // pbcgp will be copied to all new created subfaces.
22431         pbcgp = shellpbcgroup(shloop);
22432       }
22433       // Get the abovepoint of this facet.
22434       abovepoint = facetabovepointarray[shellmark(shloop)];
22435       if (abovepoint == (point) NULL) {
22436         getfacetabovepoint(&shloop);
22437       }
22438     }
22439     sspivot(shloop, workseg);
22440     if (workseg.sh == dummysh) {
22441       // This edge is an interior edge.
22442       spivot(shloop, neighsh);
22443       boundedgelink->add(&neighsh);
22444     } else {
22445       // This side has a segment, the edge exists.
22446       boundedgelink->add(&shloop);
22447     }
22448   }
22449 
22450   // Each edge ab of boundedgelink will be finished by finding a vertex c
22451   //   which is a vertex of the missing region, such that:
22452   //   (1) abc is inside the missing region, i.e., abc intersects at least
22453   //       one of missing subfaces (saved in missingshlist);
22454   //   (2) abc is not intersect with any previously created new subfaces
22455   //       in the missing region (saved in newshlink).
22456   //   After abc is created, it will be inserted into both the surface mesh
22457   //   and the DT. The boundedgelink will be updated, ab is removed, bc and
22458   //   ca will be added if they are open.
22459 
22460   while (boundedgelink->len() > 0) {
22461     // Remove an edge (ab) from the link.
22462     shloop = * (face *) boundedgelink->del(1);
22463     // 'workseg' indicates it is a segment or not.
22464     sspivot(shloop, workseg);
22465     torg = sorg(shloop);  // torg = a;
22466     tdest = sdest(shloop);  // tdest = b;
22467     // Find a tetrahedron containing ab.
22468     getsearchtet(torg, tdest, &starttet, &workpt);
22469     collinear = finddirection(&starttet, workpt, tetrahedrons->items);
22470     if (collinear == LEFTCOLLINEAR) {
22471       enext2self(starttet);
22472       esymself(starttet);
22473     } else if (collinear == TOPCOLLINEAR) {
22474       fnextself(starttet);
22475       enext2self(starttet);
22476       esymself(starttet);
22477     }
22478     assert(dest(starttet) == workpt);
22479     // Checking faces around ab until a valid face is found.
22480     matchflag = false;
22481     spintet = starttet;
22482     hitbdry = 0;
22483     do {
22484       workpt = apex(spintet);
22485       idx = pointmark(workpt) - in->firstnumber;
22486       if (worklist[idx] == 1) {
22487         // (trog, tdest, workpt) is on the facet. Check if it satisfies (1).
22488         finishflag = false;
22489         for (i = 0; i < missingshlist->len(); i++) {
22490           worksh = * (face *)(* missingshlist)[i];
22491           spt1 = sorg(worksh);
22492           spt2 = sdest(worksh);
22493           spt3 = sapex(worksh);
22494           // Does bc intersect the face?
22495           if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22496               == INTERSECT) {
22497             finishflag = true; break;
22498           }
22499           // Does ca intersect the face?
22500           if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22501               == INTERSECT) {
22502             finishflag = true; break;
22503           }
22504           // Does c inside the face?
22505           if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22506               == INTERSECT) {
22507             finishflag = true; break;
22508           }
22509         }
22510         if (finishflag) {
22511           // Satisfying (1). Check if it satisfies (2).
22512           matchflag = true;
22513           for (i = 0; i < newshlink->len() && matchflag; i++) {
22514             worksh = * (face *) newshlink->getnitem(i + 1);
22515             spt1 = sorg(worksh);
22516             spt2 = sdest(worksh);
22517             spt3 = sapex(worksh);
22518             // Does bc intersect the face?
22519             if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22520                 == INTERSECT) {
22521               matchflag = false; break;
22522             }
22523             // Does ca intersect the face?
22524             if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22525                 == INTERSECT) {
22526               matchflag = false; break;
22527             }
22528             // Does c inside the face?
22529             if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22530                 == INTERSECT) {
22531               matchflag = false; break;
22532             }
22533           }
22534         }
22535         if (matchflag == true) {
22536           // Satisfying both (1) and (2). Find abc.
22537           break;
22538         }
22539       }
22540       if (!fnextself(spintet)) {
22541         hitbdry ++;
22542         if (hitbdry < 2) {
22543           esym(starttet, spintet);
22544           if (!fnextself(spintet)) {
22545             hitbdry ++;
22546           }
22547         }
22548       }
22549     } while (hitbdry < 2 && apex(spintet) != apex(starttet));
22550     assert(matchflag == true);
22551     tspivot(spintet, neighsh);
22552     if (neighsh.sh != dummysh) {
22553       printf("Error:  Invalid PLC.\n");
22554       printf("  Facet #%d and facet #%d overlap each other.\n",
22555              shellmark(neighsh), shellmark(shloop));
22556       printf("  It might be caused by a facet is defined more than once.\n");
22557       printf("  Hint:  Use -d switch to find all overlapping facets.\n");
22558       exit(1);
22559     }
22560     // The side of 'spintet' is at which a new subface will be attached.
22561     adjustedgering(spintet, CCW);
22562     // Create the new subface.
22563     makeshellface(subfaces, &newsh);
22564     setsorg(newsh, org(spintet));
22565     setsdest(newsh, dest(spintet));
22566     setsapex(newsh, apex(spintet));
22567     if (b->quality && varconstraint) {
22568       setareabound(newsh, area);
22569     }
22570     if (checkpbcs) {
22571       setshellpbcgroup(newsh, pbcgp);
22572     }
22573     setshellmark(newsh, shmark);
22574     setshelltype(newsh, shtype);  // It may be a skinny subface.
22575     // Add newsh into newshlink for intersecting checking.
22576     newshlink->add(&newsh);
22577     // Insert it into the current mesh.
22578     tsbond(spintet, newsh);
22579     sym(spintet, neightet);
22580     if (neightet.tet != dummytet) {
22581       sesym(newsh, neighsh);
22582       tsbond(neightet, neighsh);
22583     }
22584     // Insert it into the surface mesh.
22585     sspivot(shloop, workseg);
22586     if (workseg.sh == dummysh) {
22587       sbond(shloop, newsh);
22588     } else {
22589       // There is a subsegment, 'shloop' is the subface which is going to
22590       //   die. Insert the 'newsh' at the place of 'shloop' into its face
22591       //   link, so as to dettach 'shloop'.   The original connection is:
22592       //   -> casingin -> shloop -> casingout ->, it will be changed with:
22593       //   -> casingin ->  newsh -> casingout ->.  Pay attention to the
22594       //   case when this subsegment is dangling in the mesh, i.e., 'shloop'
22595       //   is bonded to itself.
22596       spivot(shloop, casingout);
22597       if (shloop.sh != casingout.sh) {
22598         // 'shloop' is not bonded to itself.
22599         spinsh = casingout;
22600         do {
22601           casingin = spinsh;
22602           spivotself(spinsh);
22603         } while (sapex(spinsh) != sapex(shloop));
22604         assert(casingin.sh != shloop.sh);
22605         // Bond casingin -> newsh -> casingout.
22606         sbond1(casingin, newsh);
22607         sbond1(newsh, casingout);
22608       } else {
22609         // Bond newsh -> newsh.
22610         sbond(newsh, newsh);
22611       }
22612       // Bond the segment.
22613       ssbond(newsh, workseg);
22614     }
22615     // Check other two sides of this new subface.  If a side is not bonded
22616     //   to any edge in the link, it will be added to the link.
22617     for (i = 0; i < 2; i++) {
22618       if (i == 0) {
22619         senext(newsh, worksh);
22620       } else {
22621         senext2(newsh, worksh);
22622       }
22623       torg = sorg(worksh);
22624       tdest = sdest(worksh);
22625       finishflag = false;
22626       for (j = 0; j < boundedgelink->len() && !finishflag; j++) {
22627         neighsh = * (face *) boundedgelink->getnitem(j + 1);
22628         if ((sorg(neighsh) == torg && sdest(neighsh) == tdest) ||
22629             (sorg(neighsh) == tdest && sdest(neighsh) == torg)) {
22630           // Find a boundary edge.  Bond them and exit the loop.
22631           sspivot(neighsh, workseg);
22632           if (workseg.sh == dummysh) {
22633             sbond(neighsh, worksh);
22634           } else {
22635             // There is a subsegment, 'neighsh' is the subface which is
22636             //   going to die. Do the same as above for 'worksh'.
22637             spivot(neighsh, casingout);
22638             if (neighsh.sh != casingout.sh) {
22639               // 'neighsh' is not bonded to itself.
22640               spinsh = casingout;
22641               do {
22642                 casingin = spinsh;
22643                 spivotself(spinsh);
22644               } while (sapex(spinsh) != sapex(neighsh));
22645               assert(casingin.sh != neighsh.sh);
22646               // Bond casingin -> worksh -> casingout.
22647               sbond1(casingin, worksh);
22648               sbond1(worksh, casingout);
22649             } else {
22650               // Bond worksh -> worksh.
22651               sbond(worksh, worksh);
22652             }
22653             // Bond the segment.
22654             ssbond(worksh, workseg);
22655           }
22656           // Remove this boundary edge from the link.
22657           boundedgelink->del(j + 1);
22658           finishflag = true;
22659         }
22660       }
22661       if (!finishflag) {
22662         // It's a new boundary edge, add it to link.
22663         boundedgelink->add(&worksh);
22664       }
22665     }
22666   }
22667 
22668   // Deallocate the set of old missing subfaces.
22669   for (i = 0; i < missingshlist->len(); i++) {
22670     worksh = * (face *)(* missingshlist)[i];
22671     shellfacedealloc(subfaces, worksh.sh);
22672   }
22673   // Unmark region vertices in 'worklist'.
22674   for (i = 0; i < equatptlist->len(); i++) {
22675     workpt = * (point *)(* equatptlist)[i];
22676     idx = pointmark(workpt) - in->firstnumber;
22677     worklist[idx] = 0;
22678   }
22679 
22680   delete boundedgelink;
22681   delete newshlink;
22682 }
22683 
22685 //                                                                           //
22686 // scoutcrossingedge()    Search an edge crossing the missing region.        //
22687 //                                                                           //
22688 // 'missingshlist' forms the missing region R. This routine searches for an  //
22689 // edge crossing R.  It first forms a 'boundedgelist' consisting of the      //
22690 // boundary edges of R. Such edges are existing in CDT.  A crossing edge is  //
22691 // found by rotating faces around one of the boundary edges. It is possible  //
22692 // there is no edge crosses R (e.g. R has a degenerate point set).           //
22693 //                                                                           //
22694 // If find a croosing edge, return TRUE, 'crossedgelist' contains this edge. //
22695 // Otherwise, return FALSE.                                                  //
22696 //                                                                           //
22698 
22699 bool tetgenmesh::scoutcrossingedge(list* missingshlist, list* boundedgelist,
22700   list* crossedgelist, int* worklist)
22701 {
22702   triface starttet, spintet, worktet;
22703   face startsh, neighsh, worksh, workseg;
22704   point torg, tdest, tapex;
22705   point workpt[3], pa, pb, pc;
22706   enum finddirectionresult collinear;
22707   REAL ori1, ori2;
22708   bool crossflag;
22709   int hitbdry;
22710   int i, j, k;
22711 
22712   // Form the 'boundedgelist'. Loop through 'missingshlist', check each
22713   //   edge of these subfaces. If an edge is a segment or the neighbor
22714   //   subface is uninfected, add it to 'boundedgelist'.
22715   for (i = 0; i < missingshlist->len(); i++) {
22716     worksh = * (face *)(* missingshlist)[i];
22717     for (j = 0; j < 3; j++) {
22718       sspivot(worksh, workseg);
22719       if (workseg.sh == dummysh) {
22720         spivot(worksh, neighsh);
22721         if (!sinfected(neighsh)) {
22722           boundedgelist->append(&worksh);
22723         }
22724       } else {
22725         boundedgelist->append(&worksh);
22726       }
22727       senextself(worksh);
22728     }
22729   }
22730 
22731   crossflag = false;
22732   // Find a crossing edge. It is possible there is no such edge. We need to
22733   //   loop through all edges of 'boundedgelist' for sure we don't miss any.
22734   for (i = 0; i < boundedgelist->len() && !crossflag; i++) {
22735     startsh = * (face *)(* boundedgelist)[i];
22736     // 'startsh' (abc) holds an existing edge of the DT, find it.
22737     torg = sorg(startsh);
22738     tdest = sdest(startsh);
22739     tapex = sapex(startsh);
22740     getsearchtet(torg, tdest, &starttet, &workpt[0]);
22741     collinear = finddirection(&starttet, workpt[0], tetrahedrons->items);
22742     if (collinear == LEFTCOLLINEAR) {
22743       enext2self(starttet);
22744       esymself(starttet);
22745     } else if (collinear == TOPCOLLINEAR) {
22746       fnextself(starttet);
22747       enext2self(starttet);
22748       esymself(starttet);
22749     }
22750 #ifdef SELF_CHECK
22751     assert(dest(starttet) == workpt[0]);
22752 #endif
22753     // Now starttet holds edge ab. Find is edge de crossing R.
22754     spintet = starttet;
22755     hitbdry = 0;
22756     do {
22757       if (fnextself(spintet)) {
22758         // splittet = abde. Check if de crosses abc.
22759         workpt[1] = apex(spintet);  // workpt[1] = d.
22760         workpt[2] = oppo(spintet);  // workpt[2] = e.
22761         j = pointmark(workpt[1]) - in->firstnumber;
22762         k = pointmark(workpt[2]) - in->firstnumber;
22763         if (worklist[j] == 1) {
22764           ori1 = 0.0; // d is a vertex of the missing region.
22765         } else {
22766           // Get the orientation of d wrt. abc.
22767           ori1 = orient3d(torg, tdest, tapex, workpt[1]);
22768         }
22769         if (worklist[k] == 1) {
22770           ori2 = 0.0; // e is a vertex of the missing region.
22771         } else {
22772           // Get the orientation of e wrt. abc.
22773           ori2 = orient3d(torg, tdest, tapex, workpt[2]);
22774         }
22775         // Only do check if d and e locate on different sides of abc.
22776         if (ori1 * ori2 < 0.0) {
22777           // Check if de crosses any subface of R.
22778           for (j = 0; j < missingshlist->len(); j++) {
22779             worksh = * (face *)(* missingshlist)[j];
22780             pa = sorg(worksh);
22781             pb = sdest(worksh);
22782             pc = sapex(worksh);
22783             crossflag = (tri_tri_inter(pa, pb, pc, workpt[0], workpt[1],
22784                                        workpt[2]) == INTERSECT);
22785             if (crossflag) {
22786               // Find a crossing edge. We're done.
22787               worktet = spintet;
22788               adjustedgering(worktet, CCW);
22789               enextfnextself(worktet);
22790               enextself(worktet);
22791               // Add this edge (worktet) into 'crossedgelist'.
22792               crossedgelist->append(&worktet);
22793               break;
22794             }
22795           }
22796           if (crossflag) break;
22797         }
22798         if (apex(spintet) == apex(starttet)) break;
22799       } else {
22800         hitbdry++;
22801         // It is only possible to hit boundary once.
22802         if (hitbdry < 2) {
22803           esym(starttet, spintet);
22804         }
22805       }
22806     } while (hitbdry < 2);
22807   }
22808 
22809   return crossflag;
22810 }
22811 
22813 //                                                                           //
22814 // formcavity()    Form the cavity for recovering the missing region.        //
22815 //                                                                           //
22816 // The cavity C is bounded by faces of current CDT.  All tetrahedra inside C //
22817 // will be removed, intead a set of constrained Delaunay tetrahedra will be  //
22818 // filled in and the missing region are recovered.                           //
22819 //                                                                           //
22820 // 'missingshlist' contains a set of subfaces forming the missing region R.  //
22821 // C is formed by first finding all the tetrahedra in CDT that intersect the //
22822 // relative interior of R; then deleting them from the CDT, this will form C //
22823 // inside the CDT. At the beginning, 'crossedgelist' contains an edge which  //
22824 // is crossing R. All tets containing this edge must cross R. Start from it, //
22825 // other crossing edges can be found incrementally.  The discovered crossing //
22826 // tets are saved in 'crosstetlist'.                                         //
22827 //                                                                           //
22828 // Notice that not all tets in 'crosstetlist' are crossing R. The discovered //
22829 // tets are connected each other. However, there may be other tets crossing  //
22830 // R but disjoint with the found tets. Due to this fact we need to check the //
22831 // 'missingshlist' once more. Only recover those subfaces which are crossed  //
22832 // by the set of discovered tets, i.e., R may be shrinked to conform the set //
22833 // of discovered tets. The extra subfaces of R will be recovered later.      //
22834 //                                                                           //
22835 // Notice that some previous recovered subfaces may completely included in C.//
22836 // This can happen when R is very big and these subfaces lie above R and so  //
22837 // close to it. Such subfaces have to be queued (and sinfected()) to recover //
22838 // them later. Otherwise, we lost the connection to these subfaces forever.  //
22839 //                                                                           //
22841 
22842 void tetgenmesh::formcavity(list* missingshlist, list* crossedgelist,
22843   list* equatptlist, list* crossshlist, list* crosstetlist,
22844   list* belowfacelist, list* abovefacelist, list* horizptlist,
22845   list* belowptlist, list* aboveptlist, queue* missingshqueue, int* worklist)
22846 {
22847   triface starttet, spintet, neightet, worktet;
22848   face startsh, neighsh, worksh, workseg;
22849   point torg, tdest, tapex, workpt[3];
22850   REAL checksign, orgori, destori;
22851   bool crossflag, inlistflag;
22852   bool belowflag, aboveflag;
22853   int idx, share;
22854   int i, j, k;
22855 
22856   // Get a face at horizon.
22857   startsh = * (face *)(* missingshlist)[0];
22858   torg = sorg(startsh);
22859   tdest = sdest(startsh);
22860   tapex = sapex(startsh);
22861 
22862   // Collect the set of crossing tetrahedra by rotating crossing edges.
22863   for (i = 0; i < crossedgelist->len(); i++) {
22864     // Get a tet abcd, ab is a crossing edge.
22865     starttet = * (triface *)(* crossedgelist)[i];
22866     adjustedgering(starttet, CCW);
22867     if (b->verbose > 2) {
22868       printf("    Collect tets containing edge (%d, %d).\n",
22869              pointmark(org(starttet)), pointmark(dest(starttet)));
22870     }
22871     orgori = orient3d(torg, tdest, tapex, org(starttet));
22872     destori = orient3d(torg, tdest, tapex, dest(starttet));
22873     UNUSED_OPT(destori);
22874 #ifdef SELF_CHECK
22875     assert(orgori * destori < 0.0);
22876 #endif
22877     spintet = starttet;
22878     do {
22879       // The face rotation should not meet boundary.
22880       fnextself(spintet);
22881       // Check the validity of the PLC.
22882       tspivot(spintet, worksh);
22883       if (worksh.sh != dummysh) {
22884         printf("Error:  Invalid PLC.\n");
22885         printf("  Two subfaces (%d, %d, %d) and (%d, %d, %d)\n",
22886                pointmark(torg), pointmark(tdest), pointmark(tapex),
22887                pointmark(sorg(worksh)), pointmark(sdest(worksh)),
22888                pointmark(sapex(worksh)));
22889         printf("  are found intersecting each other.\n");
22890         printf("  Hint:  Use -d switch to find all intersecting facets.\n");
22891         terminatetetgen(1);
22892       }
22893       if (!infected(spintet)) {
22894         if (b->verbose > 2) {
22895           printf("      Add crossing tet (%d, %d, %d, %d).\n",
22896                  pointmark(org(spintet)), pointmark(dest(spintet)),
22897                  pointmark(apex(spintet)), pointmark(oppo(spintet)));
22898         }
22899         infect(spintet);
22900         crosstetlist->append(&spintet);
22901       }
22902       // Check whether other two edges of 'spintet' is a crossing edge.
22903       //   It can be quickly checked from the apex of 'spintet', if it is
22904       //   not on the facet, then there exists a crossing edge.
22905       workpt[0] = apex(spintet);
22906       idx = pointmark(workpt[0]) - in->firstnumber;
22907       if (worklist[idx] != 1) {
22908         // Either edge (dest, apex) or edge (apex, org) crosses.
22909         checksign = orient3d(torg, tdest, tapex, workpt[0]);
22910 #ifdef SELF_CHECK
22911         assert(checksign != 0.0);
22912 #endif
22913         if (checksign * orgori < 0.0) {
22914           enext2(spintet, worktet); // edge (apex, org).
22915           workpt[1] = org(spintet);
22916         } else {
22917 //#ifdef SELF_CHECK // commented out to get gcc 4.6 working
22918           assert(checksign * destori < 0.0);
22919 //#endif
22920           enext(spintet, worktet);  // edge (dest, apex).
22921           workpt[1] = dest(spintet);
22922         }
22923         // 'worktet' represents the crossing edge. Add it into list only
22924         //   it doesn't exist in 'crossedgelist'.
22925         inlistflag = false;
22926         for (j = 0; j < crossedgelist->len() && !inlistflag; j++) {
22927           neightet = * (triface *)(* crossedgelist)[j];
22928           if (org(neightet) == workpt[0]) {
22929             if (dest(neightet) == workpt[1]) inlistflag = true;
22930           } else if (org(neightet) == workpt[1]) {
22931             if (dest(neightet) == workpt[0]) inlistflag = true;
22932           }
22933         }
22934         if (!inlistflag) {
22935           crossedgelist->append(&worktet);
22936         }
22937       }
22938     } while (apex(spintet) != apex(starttet));
22939   }
22940 
22941   // Identifying the boundary faces and vertices of C. Sort them into
22942   //   'abovefacelist', 'aboveptlist, 'belowfacelist', and 'belowptlist',
22943   //    respectively. "above" and "below" are wrt.(torg, tdest, tapex).
22944   for (i = 0; i < crosstetlist->len(); i++) {
22945     // Get a tet abcd, ab is the crossing edge.
22946     starttet = * (triface *)(* crosstetlist)[i];
22947 #ifdef SELF_CHECK
22948     assert(infected(starttet));
22949 #endif
22950     adjustedgering(starttet, CCW);
22951     // abc and abd are sharing the crossing edge, the two neighbors must
22952     //   be crossing tetrahedra too. They can't be boundaries of C.
22953     for (j = 0; j < 2; j++) {
22954       if (j == 0) {
22955         enextfnext(starttet, worktet); // Check bcd.
22956       } else {
22957         enext2fnext(starttet, worktet); // Check acd.
22958       }
22959       sym(worktet, neightet);
22960       // If the neighbor doesn't exist or exists but doesn't be infected,
22961       //   it's a boundary face of C, save it.
22962       if ((neightet.tet == dummytet) || !infected(neightet)) {
22963         workpt[0] = org(worktet);
22964         workpt[1] = dest(worktet);
22965         workpt[2] = apex(worktet);
22966         belowflag = aboveflag = false;
22967         share = 0;
22968         for (k = 0; k < 3; k++) {
22969           idx = pointmark(workpt[k]) - in->firstnumber;
22970           if (worklist[idx] == 0) {
22971             // It's not a vertices of facet, find which side it lies.
22972             checksign = orient3d(torg, tdest, tapex, workpt[k]);
22973 #ifdef SELF_CHECK
22974             assert(checksign != 0.0);
22975 #endif
22976             if (checksign > 0.0) {
22977               // It lies "below" the facet wrt. 'startsh'.
22978               worklist[idx] = 2;
22979               belowptlist->append(&workpt[k]);
22980             } else if (checksign < 0.0) {
22981               // It lies "above" the facet wrt. 'startsh'.
22982               worklist[idx] = 3;
22983               aboveptlist->append(&workpt[k]);
22984             }
22985           }
22986           if (worklist[idx] == 2) {
22987             // This face lies "below" the facet wrt. 'startsh'.
22988             belowflag = true;
22989           } else if (worklist[idx] == 3) {
22990             // This face lies "above" the facet wrt. 'startsh'.
22991             aboveflag = true;
22992           } else {
22993 #ifdef SELF_CHECK
22994             // In degenerate case, this face may just be the equator.
22995             assert(worklist[idx] == 1);
22996 #endif
22997             share++;
22998           }
22999         }
23000 #ifdef SELF_CHECK
23001         // The degenerate case has been ruled out.
23002         assert(share < 3);
23003         // Only one flag is possible for a cavity face.
23004         assert(belowflag ^ aboveflag);
23005 #endif
23006         if (belowflag) {
23007           belowfacelist->append(&worktet);
23008         } else if (aboveflag) {
23009           abovefacelist->append(&worktet);
23010         }
23011       }
23012     }
23013   }
23014 
23015   // Shrink R if not all its subfaces are crossing by the discovered tets.
23016   //   'crossshlist' and 'horizptlist' represent the set of subfaces and
23017   //   vertices of the shrinked missing region, respectively.
23018   for (i = 0; i < missingshlist->len(); i++) {
23019     worksh = * (face *)(* missingshlist)[i];
23020 #ifdef SELF_CHECK
23021     assert(sinfected(worksh));
23022 #endif
23023     workpt[0] = sorg(worksh);
23024     workpt[1] = sdest(worksh);
23025     workpt[2] = sapex(worksh);
23026     crossflag = false;
23027     for (j = 0; j < crosstetlist->len() && !crossflag; j++) {
23028       // Get a tet abcd, ab is a crossing edge.
23029       starttet = * (triface *)(* crosstetlist)[j];
23030       adjustedgering(starttet, CCW);
23031       // Only need to check two sides of worktet.
23032       for (k = 0; k < 2 && !crossflag; k++) {
23033         if (k == 0) {
23034           worktet = starttet; // Check abc.
23035         } else {
23036           fnext(starttet, worktet); // Check abd.
23037         }
23038         crossflag = tritritest(&worktet, workpt[0], workpt[1], workpt[2]);
23039       }
23040     }
23041     if (crossflag) {
23042       // 'worksh' is crossed by 'worktet', uninfect it.
23043       suninfect(worksh);
23044       crossshlist->append(&worksh);
23045       // Add its corners into 'horizptlist'.
23046       for (k = 0; k < 3; k++) {
23047         idx = pointmark(workpt[k]) - in->firstnumber;
23048         if (worklist[idx] != 4) {
23049           worklist[idx] = 4;
23050           horizptlist->append(&workpt[k]);
23051         }
23052       }
23053     }
23054   }
23055 
23056   // Check 'crossingtetlist'. Queue subfaces inside them.
23057   for (i = 0; i < crosstetlist->len(); i++) {
23058     starttet = * (triface *)(* crosstetlist)[i];
23059     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
23060       sym(starttet, neightet);
23061       // If the neighbor exist and is infected, check it.
23062       if ((neightet.tet != dummytet) && infected(neightet)) {
23063         tspivot(starttet, worksh);
23064         if (worksh.sh != dummysh) {
23065           // Temporarily remove worksh. Make it missing. recover it later.
23066           if (b->verbose > 2) {
23067             printf("    Queuing subface (%d, %d, %d).\n",
23068                    pointmark(sorg(worksh)), pointmark(sdest(worksh)),
23069                    pointmark(sapex(worksh)));
23070           }
23071           tsdissolve(neightet);
23072           tsdissolve(starttet);
23073           // Detach tets at the both sides of this subface.
23074           stdissolve(worksh);
23075           sesymself(worksh);
23076           stdissolve(worksh);
23077           sinfect(worksh);
23078           missingshqueue->push(&worksh);
23079         }
23080       }
23081     }
23082   }
23083 
23084   // Clear flags set in 'worklist'.
23085   for (i = 0; i < equatptlist->len(); i++) {
23086     workpt[0] = * (point *)(* equatptlist)[i];
23087     idx = pointmark(workpt[0]) - in->firstnumber;
23088 #ifdef SELF_CHECK
23089     assert((worklist[idx] == 1) || (worklist[idx] == 4));
23090 #endif
23091     worklist[idx] = 0;
23092   }
23093   for (i = 0; i < belowptlist->len(); i++) {
23094     workpt[0] = * (point *)(* belowptlist)[i];
23095     idx = pointmark(workpt[0]) - in->firstnumber;
23096 #ifdef SELF_CHECK
23097     assert(worklist[idx] == 2);
23098 #endif
23099     worklist[idx] = 0;
23100   }
23101   for (i = 0; i < aboveptlist->len(); i++) {
23102     workpt[0] = * (point *)(* aboveptlist)[i];
23103     idx = pointmark(workpt[0]) - in->firstnumber;
23104 #ifdef SELF_CHECK
23105     assert(worklist[idx] == 3);
23106 #endif
23107     worklist[idx] = 0;
23108   }
23109 }
23110 
23112 //                                                                           //
23113 // insertallsubfaces()    Insert all subfaces, queue missing subfaces.       //
23114 //                                                                           //
23115 // Loop through all subfaces, insert each into the DT. If one already exists,//
23116 // bond it to the tetrahedra having it. Otherwise, it is missing, infect it  //
23117 // and save it in 'missingshqueue'.                                          //
23118 //                                                                           //
23120 
23121 void tetgenmesh::insertallsubfaces(queue* missingshqueue)
23122 {
23123   triface searchtet;
23124   face subloop;
23125 
23126   searchtet.tet = (tetrahedron *) NULL;
23127   subfaces->traversalinit();
23128   subloop.sh = shellfacetraverse(subfaces);
23129   while (subloop.sh != (shellface *) NULL) {
23130     if (!insertsubface(&subloop, &searchtet)) {
23131       if (b->verbose > 1) {
23132         printf("    Queuing subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23133                pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23134       }
23135       sinfect(subloop);
23136       missingshqueue->push(&subloop);
23137     }
23138     subloop.sh = shellfacetraverse(subfaces);
23139   }
23140 }
23141 
23143 //                                                                           //
23144 // constrainedfacets()    Recover subfaces in a Delaunay tetrahedralization. //
23145 //                                                                           //
23146 // This routine creates a CDT by incrementally updating a DT D into a CDT T. //
23147 // The process of recovering facets can be imagined by "merging" the surface //
23148 // mesh F into D. At the beginning, F and D are completely seperated.  Some  //
23149 // faces of them are matching some are not because they are crossed by some  //
23150 // tetrahedra of D. The non-matching subfaces will be forced to appear in T  //
23151 // by locally retetrahedralizing the regions where F and D are intersecting. //
23152 //                                                                           //
23153 // When a subface s of F is found missing in D, probably some other subfaces //
23154 // near to s are missing too.  The set of adjoining coplanar missing faces   //
23155 // forms a missing region R (R may not simply connected).                    //
23156 //                                                                           //
23157 // There are two possibilities can result a mssing region R: (1) Some edges  //
23158 // of D cross R; (2) No edge of D crosses R, but some faces of D spans R, ie,//
23159 // D is locally degenerate at R. In case (1), D is modified so that it resp- //
23160 // ects R (done by a cavity retetrahedralization algorithm).  In case (2), F //
23161 // is modified so that the set of subfaces of R matches faces in D (done by  //
23162 // a face rearrangment algorithm).                                           //
23163 //                                                                           //
23165 
23166 void tetgenmesh::constrainedfacets()
23167 {
23168   queue *missingshqueue, *flipque;
23169   list *missingshlist, *equatptlist;
23170   list *boundedgelist, *crossedgelist, *crosstetlist;
23171   list *crossshlist, *belowfacelist, *abovefacelist;
23172   list *horizptlist, *belowptlist, *aboveptlist;
23173   list *frontlist, *misfrontlist, *newtetlist;
23174   triface searchtet, worktet;
23175   face subloop, worksh;
23176   int *worklist;
23177   int i;
23178 
23179   if (!b->quiet) {
23180     printf("Constraining facets.\n");
23181   }
23182 
23183   // Initialize queues.
23184   missingshqueue = new queue(sizeof(face));
23185   flipque = new queue(sizeof(badface));
23186   // Initialize the working lists.
23187   missingshlist = new list(sizeof(face), NULL);
23188   boundedgelist = new list(sizeof(face), NULL);
23189   crossedgelist = new list(sizeof(triface), NULL);
23190   equatptlist = new list((char*) "point *");
23191   crossshlist = new list(sizeof(face), NULL);
23192   crosstetlist = new list(sizeof(triface), NULL);
23193   belowfacelist = new list(sizeof(triface), NULL);
23194   abovefacelist = new list(sizeof(triface), NULL);
23195   horizptlist = new list((char*)"point *");
23196   belowptlist = new list((char*)"point *");
23197   aboveptlist = new list((char*)"point *");
23198   frontlist = new list(sizeof(triface), NULL);
23199   misfrontlist = new list(sizeof(triface), NULL);
23200   newtetlist = new list(sizeof(triface), NULL);
23201   // Initialize the array for marking vertices.
23202   worklist = new int[points->items + 1];
23203   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
23204 
23205   // Compute a mapping from points to tetrahedra for fast searching.
23206   makepoint2tetmap();
23207 
23208   // Match subfaces in D, queue all missing subfaces.
23209   insertallsubfaces(missingshqueue);
23210 
23211   // Recover all missing subfaces.
23212   while (!missingshqueue->empty()) {
23213     // Get a queued face s.
23214     subloop = * (face *) missingshqueue->pop();
23215     // s may have been deleted in a face rearrangment operation.
23216     if (isdead(&subloop)) continue;
23217     // s may have been recovered in a previous missing region.
23218     if (!sinfected(subloop)) continue;
23219     // s may match a face in D now due to previous transformations.
23220     if (insertsubface(&subloop, &searchtet)) {
23221       suninfect(subloop);
23222       continue;
23223     }
23224     if (b->verbose > 1) {
23225       printf("    Recover subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23226              pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23227     }
23228     // Form the missing region R containing s.
23229     formmissingregion(&subloop, missingshlist, equatptlist, worklist);
23230     // Is R crossing by any tetrahedron?
23231     if (scoutcrossingedge(missingshlist, boundedgelist, crossedgelist,
23232                           worklist)) {
23233       // Form the cavity C containing R.
23234       formcavity(missingshlist, crossedgelist, equatptlist, crossshlist,
23235                  crosstetlist, belowfacelist, abovefacelist, horizptlist,
23236                  belowptlist, aboveptlist, missingshqueue, worklist);
23237       // Recover the above part of C.
23238       delaunizecavity(crossshlist, abovefacelist, aboveptlist, horizptlist,
23239                       frontlist, misfrontlist, newtetlist, crosstetlist,
23240                       missingshqueue, flipque);
23241       // Inverse the direction of subfaces in R.
23242       for (i = 0; i < crossshlist->len(); i++) {
23243         worksh = * (face *)(* crossshlist)[i];
23244         sesymself(worksh);
23245         * (face *)(* crossshlist)[i] = worksh;
23246       }
23247       // Recover the below part of C.
23248       delaunizecavity(crossshlist, belowfacelist, belowptlist, horizptlist,
23249                       frontlist, misfrontlist, newtetlist, crosstetlist,
23250                       missingshqueue, flipque);
23251       // Delete tetrahedra in C.
23252       for (i = 0; i < crosstetlist->len(); i++) {
23253         worktet = * (triface *)(* crosstetlist)[i];
23254         tetrahedrondealloc(worktet.tet);
23255       }
23256       // There may have some un-recovered subfaces of R. Put them back into
23257       //   queue. Otherwise, they will be missing on the boundary.
23258       for (i = 0; i < missingshlist->len(); i++) {
23259         worksh = * (face *)(* missingshlist)[i];
23260         if (sinfected(worksh)) {
23261           // An unrecovered subface, put it back into queue.
23262           missingshqueue->push(&worksh);
23263         }
23264       }
23265       crossshlist->clear();
23266       belowfacelist->clear();
23267       abovefacelist->clear();
23268       horizptlist->clear();
23269       belowptlist->clear();
23270       aboveptlist->clear();
23271       crosstetlist->clear();
23272     } else {
23273       // No. Rearrange subfaces of F conforming to that of D in R. It can
23274       //   happen when the facet has non-coplanar vertices.
23275       rearrangesubfaces(missingshlist, boundedgelist, equatptlist, worklist);
23276     }
23277     // Clear all working lists.
23278     missingshlist->clear();
23279     boundedgelist->clear();
23280     crossedgelist->clear();
23281     equatptlist->clear();
23282   }
23283 
23284   // Subfaces have been merged into D.
23285   checksubfaces = 1;
23286 
23287   if (b->verbose > 0) {
23288     printf("  The biggest cavity: %d faces, %d vertices\n", maxcavfaces,
23289            maxcavverts);
23290     printf("  Enlarged %d times\n", expcavcount);
23291   }
23292 
23293   delete missingshqueue;
23294   delete flipque;
23295   delete missingshlist;
23296   delete boundedgelist;
23297   delete crossedgelist;
23298   delete equatptlist;
23299   delete crossshlist;
23300   delete crosstetlist;
23301   delete belowfacelist;
23302   delete abovefacelist;
23303   delete horizptlist;
23304   delete belowptlist;
23305   delete aboveptlist;
23306   delete frontlist;
23307   delete misfrontlist;
23308   delete newtetlist;
23309   delete [] worklist;
23310 }
23311 
23312 //
23313 // End of facet recovery routines
23314 //
23315 
23316 //
23317 // Begin of carving out holes and concavities routines
23318 //
23319 
23321 //                                                                           //
23322 // infecthull()    Virally infect all of the tetrahedra of the convex hull   //
23323 //                 that are not protected by subfaces.  Where there are      //
23324 //                 subfaces, set boundary markers as appropriate.            //
23325 //                                                                           //
23326 // Memorypool 'viri' is used to return all the infected tetrahedra.          //
23327 //                                                                           //
23329 
23330 void tetgenmesh::infecthull(memorypool *viri)
23331 {
23332   triface tetloop, tsymtet;
23333   tetrahedron **deadtet;
23334   face hullface;
23335   // point horg, hdest, hapex;
23336 
23337   if (b->verbose > 0) {
23338     printf("  Marking concavities for elimination.\n");
23339   }
23340   tetrahedrons->traversalinit();
23341   tetloop.tet = tetrahedrontraverse();
23342   while (tetloop.tet != (tetrahedron *) NULL) {
23343     // Is this tetrahedron on the hull?
23344     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
23345       sym(tetloop, tsymtet);
23346       if (tsymtet.tet == dummytet) {
23347         // Is the tetrahedron protected by a subface?
23348         tspivot(tetloop, hullface);
23349         if (hullface.sh == dummysh) {
23350           // The tetrahedron is not protected; infect it.
23351           if (!infected(tetloop)) {
23352             infect(tetloop);
23353             deadtet = (tetrahedron **) viri->alloc();
23354             *deadtet = tetloop.tet;
23355             break;  // Go and get next tet.
23356           }
23357         } else {
23358           // The tetrahedron is protected; set boundary markers if appropriate.
23359           if (shellmark(hullface) == 0) {
23360             setshellmark(hullface, 1);
23361             /*
23362             horg = sorg(hullface);
23363             hdest = sdest(hullface);
23364             hapex = sapex(hullface);
23365             if (pointmark(horg) == 0) {
23366               setpointmark(horg, 1);
23367             }
23368             if (pointmark(hdest) == 0) {
23369               setpointmark(hdest, 1);
23370             }
23371             if (pointmark(hapex) == 0) {
23372               setpointmark(hapex, 1);
23373             }
23374             */
23375           }
23376         }
23377       }
23378     }
23379     tetloop.tet = tetrahedrontraverse();
23380   }
23381 }
23382 
23384 //                                                                           //
23385 // plague()    Spread the virus from all infected tets to any neighbors not  //
23386 //             protected by subfaces.                                        //
23387 //                                                                           //
23388 // This routine identifies all the tetrahedra that will die, and marks them  //
23389 // as infected.  They are marked to ensure that each tetrahedron is added to //
23390 // the virus pool only once, so the procedure will terminate. 'viri' returns //
23391 // all infected tetrahedra which are outside the domian.                     //
23392 //                                                                           //
23394 
23395 void tetgenmesh::plague(memorypool *viri)
23396 {
23397   tetrahedron **virusloop;
23398   tetrahedron **deadtet;
23399   triface testtet, neighbor;
23400   face neighsh, testseg;
23401   face spinsh, casingin, casingout;
23402   int firstdadsub;
23403   int i;
23404 
23405   if (b->verbose > 0) {
23406     printf("  Marking neighbors of marked tetrahedra.\n");
23407   }
23408   firstdadsub = 0;
23409   // Loop through all the infected tetrahedra, spreading the virus to
23410   //   their neighbors, then to their neighbors' neighbors.
23411   viri->traversalinit();
23412   virusloop = (tetrahedron **) viri->traverse();
23413   while (virusloop != (tetrahedron **) NULL) {
23414     testtet.tet = *virusloop;
23415     // Temporarily uninfect this tetrahedron, not necessary.
23416     uninfect(testtet);
23417     // Check each of the tetrahedron's four neighbors.
23418     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23419       // Find the neighbor.
23420       sym(testtet, neighbor);
23421       // Check for a shell between the tetrahedron and its neighbor.
23422       tspivot(testtet, neighsh);
23423       // Check if the neighbor is nonexistent or already infected.
23424       if ((neighbor.tet == dummytet) || infected(neighbor)) {
23425         if (neighsh.sh != dummysh) {
23426           // There is a subface separating the tetrahedron from its neighbor,
23427           //   but both tetrahedra are dying, so the subface dies too.
23428           // Before deallocte this subface, dissolve the connections between
23429           //   other subfaces, subsegments and tetrahedra.
23430           neighsh.shver = 0;
23431           if (!firstdadsub) {
23432             firstdadsub = 1; // Report the problem once.
23433             if (!b->quiet) {
23434               printf("Warning:  Detecting an open face (%d, %d, %d).\n",
23435                      pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
23436                      pointmark(sapex(neighsh)));
23437             }
23438           }
23439           // For keep the same enext() direction.
23440           findedge(&testtet, sorg(neighsh), sdest(neighsh));
23441           for (i = 0; i < 3; i++) {
23442             sspivot(neighsh, testseg);
23443             if (testseg.sh != dummysh) {
23444               // A subsegment is found at this side, dissolve this subface
23445               //   from the face link of this subsegment.
23446               testseg.shver = 0;
23447               spinsh = neighsh;
23448               if (sorg(spinsh) != sorg(testseg)) {
23449                 sesymself(spinsh);
23450               }
23451               spivot(spinsh, casingout);
23452               if (casingout.sh == spinsh.sh) {
23453                 // This is a trivial face link, only 'neighsh' itself,
23454                 //   the subsegment at this side is also died.
23455                 shellfacedealloc(subsegs, testseg.sh);
23456               } else {
23457                 spinsh = casingout;
23458                 do {
23459                   casingin = spinsh;
23460                   spivotself(spinsh);
23461                 } while (spinsh.sh != neighsh.sh);
23462                 // Set the link casingin->casingout.
23463                 sbond1(casingin, casingout);
23464                 // Bond the subsegment anyway.
23465                 ssbond(casingin, testseg);
23466               }
23467             }
23468             senextself(neighsh);
23469             enextself(testtet);
23470           }
23471           if (neighbor.tet != dummytet) {
23472             // Make sure the subface doesn't get deallocated again later
23473             //   when the infected neighbor is visited.
23474             tsdissolve(neighbor);
23475           }
23476           // This subface has been separated.
23477           if (in->mesh_dim > 2) {
23478             shellfacedealloc(subfaces, neighsh.sh);
23479           } else {
23480             // Dimension is 2. keep it for output.
23481             // Dissolve tets at both sides of this subface.
23482             stdissolve(neighsh);
23483             sesymself(neighsh);
23484             stdissolve(neighsh);
23485           }
23486         }
23487       } else {                   // The neighbor exists and is not infected.
23488         if (neighsh.sh == dummysh) {
23489           // There is no subface protecting the neighbor, infect it.
23490           infect(neighbor);
23491           // Ensure that the neighbor's neighbors will be infected.
23492           deadtet = (tetrahedron **) viri->alloc();
23493           *deadtet = neighbor.tet;
23494         } else {               // The neighbor is protected by a subface.
23495           // Remove this tetrahedron from the subface.
23496           stdissolve(neighsh);
23497           // The subface becomes a boundary.  Set markers accordingly.
23498           if (shellmark(neighsh) == 0) {
23499             setshellmark(neighsh, 1);
23500           }
23501           // This side becomes hull. Update the handle in dummytet.
23502           dummytet[0] = encode(neighbor);
23503         }
23504       }
23505     }
23506     // Remark the tetrahedron as infected, so it doesn't get added to the
23507     //   virus pool again.
23508     infect(testtet);
23509     virusloop = (tetrahedron **) viri->traverse();
23510   }
23511 }
23512 
23514 //                                                                           //
23515 // regionplague()    Spread regional attributes and/or volume constraints    //
23516 //                   (from a .poly file) throughout the mesh.                //
23517 //                                                                           //
23518 // This procedure operates in two phases.  The first phase spreads an attri- //
23519 // bute and/or a volume constraint through a (facet-bounded) region.  The    //
23520 // second phase uninfects all infected tetrahedra, returning them to normal. //
23521 //                                                                           //
23523 
23524 void tetgenmesh::
23525 regionplague(memorypool *regionviri, REAL attribute, REAL volume)
23526 {
23527   tetrahedron **virusloop;
23528   tetrahedron **regiontet;
23529   triface testtet, neighbor;
23530   face neighsh;
23531 
23532   if (b->verbose > 1) {
23533     printf("  Marking neighbors of marked tetrahedra.\n");
23534   }
23535   // Loop through all the infected tetrahedra, spreading the attribute
23536   //   and/or volume constraint to their neighbors, then to their neighbors'
23537   //   neighbors.
23538   regionviri->traversalinit();
23539   virusloop = (tetrahedron **) regionviri->traverse();
23540   while (virusloop != (tetrahedron **) NULL) {
23541     testtet.tet = *virusloop;
23542     // Temporarily uninfect this tetrahedron, not necessary.
23543     uninfect(testtet);
23544     if (b->regionattrib) {
23545       // Set an attribute.
23546       setelemattribute(testtet.tet, in->numberoftetrahedronattributes,
23547                        attribute);
23548     }
23549     if (b->varvolume) {
23550       // Set a volume constraint.
23551       setvolumebound(testtet.tet, volume);
23552     }
23553     // Check each of the tetrahedron's four neighbors.
23554     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23555       // Find the neighbor.
23556       sym(testtet, neighbor);
23557       // Check for a subface between the tetrahedron and its neighbor.
23558       tspivot(testtet, neighsh);
23559       // Make sure the neighbor exists, is not already infected, and
23560       //   isn't protected by a subface, or is protected by a nonsolid
23561       //   subface.
23562       if ((neighbor.tet != dummytet) && !infected(neighbor)
23563           && (neighsh.sh == dummysh)) {
23564         // Infect the neighbor.
23565         infect(neighbor);
23566         // Ensure that the neighbor's neighbors will be infected.
23567         regiontet = (tetrahedron **) regionviri->alloc();
23568         *regiontet = neighbor.tet;
23569       }
23570     }
23571     // Remark the tetrahedron as infected, so it doesn't get added to the
23572     //   virus pool again.
23573     infect(testtet);
23574     virusloop = (tetrahedron **) regionviri->traverse();
23575   }
23576 
23577   // Uninfect all tetrahedra.
23578   if (b->verbose > 1) {
23579     printf("  Unmarking marked tetrahedra.\n");
23580   }
23581   regionviri->traversalinit();
23582   virusloop = (tetrahedron **) regionviri->traverse();
23583   while (virusloop != (tetrahedron **) NULL) {
23584     testtet.tet = *virusloop;
23585     uninfect(testtet);
23586     virusloop = (tetrahedron **) regionviri->traverse();
23587   }
23588   // Empty the virus pool.
23589   regionviri->restart();
23590 }
23591 
23593 //                                                                           //
23594 // removeholetets()    Remove tetrahedra which are outside the domain.       //
23595 //                                                                           //
23597 
23598 void tetgenmesh::removeholetets(memorypool* viri)
23599 {
23600   tetrahedron **virusloop;
23601   triface testtet, neighbor;
23602   point checkpt;
23603   int *tetspernodelist;
23604   int i, j;
23605 
23606   if (b->verbose > 0) {
23607     printf("  Deleting marked tetrahedra.\n");
23608   }
23609 
23610   // Create and initialize 'tetspernodelist'.
23611   tetspernodelist = new int[points->items + 1];
23612   for (i = 0; i < points->items + 1; i++) tetspernodelist[i] = 0;
23613 
23614   // Loop the tetrahedra list, counter the number of tets sharing each node.
23615   tetrahedrons->traversalinit();
23616   testtet.tet = tetrahedrontraverse();
23617   while (testtet.tet != (tetrahedron *) NULL) {
23618     // Increment the number of sharing tets for each endpoint.
23619     for (i = 0; i < 4; i++) {
23620       j = pointmark((point) testtet.tet[4 + i]);
23621       tetspernodelist[j]++;
23622     }
23623     testtet.tet = tetrahedrontraverse();
23624   }
23625 
23626   viri->traversalinit();
23627   virusloop = (tetrahedron **) viri->traverse();
23628   while (virusloop != (tetrahedron **) NULL) {
23629     testtet.tet = *virusloop;
23630     // Record changes in the number of boundary faces, and disconnect
23631     //   dead tetrahedra from their neighbors.
23632     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23633       sym(testtet, neighbor);
23634       if (neighbor.tet == dummytet) {
23635         // There is no neighboring tetrahedron on this face, so this face
23636         //   is a boundary face.  This tetrahedron is being deleted, so this
23637         //   boundary face is deleted.
23638         hullsize--;
23639       } else {
23640         // Disconnect the tetrahedron from its neighbor.
23641         dissolve(neighbor);
23642         // There is a neighboring tetrahedron on this face, so this face
23643         //   becomes a boundary face when this tetrahedron is deleted.
23644         hullsize++;
23645       }
23646     }
23647     // Check the four corners of this tet if they're isolated.
23648     for (i = 0; i < 4; i++) {
23649       checkpt = (point) testtet.tet[4 + i];
23650       j = pointmark(checkpt);
23651       tetspernodelist[j]--;
23652       if (tetspernodelist[j] == 0) {
23653         // If it is added volume vertex or '-j' is not used, delete it.
23654         if ((pointtype(checkpt) == FREEVOLVERTEX) || !b->nojettison) {
23655           setpointtype(checkpt, UNUSEDVERTEX);
23656           unuverts++;
23657         }
23658       }
23659     }
23660     // Return the dead tetrahedron to the pool of tetrahedra.
23661     tetrahedrondealloc(testtet.tet);
23662     virusloop = (tetrahedron **) viri->traverse();
23663   }
23664 
23665   delete [] tetspernodelist;
23666 }
23667 
23669 //                                                                           //
23670 // assignregionattribs()    Assign each tetrahedron a region number.         //
23671 //                                                                           //
23672 // This routine is called when '-AA' switch is specified.  Every tetrahedron //
23673 // of a (bounded) region will get a integer number to that region.  Default, //
23674 // regions are numbered as 1, 2, 3, etc. However, if a number has already    //
23675 // been used (set by user in the region section in .poly or .smesh), it is   //
23676 // skipped and the next available number will be used.                       //
23677 //                                                                           //
23679 
23680 void tetgenmesh::assignregionattribs()
23681 {
23682   list *regionnumlist;
23683   list *regiontetlist;
23684   triface tetloop, regiontet, neightet;
23685   face checksh;
23686   bool flag;
23687   int regionnum, num;
23688   int attridx, count;
23689   int i;
23690 
23691   if (b->verbose > 0) {
23692     printf("  Assign region numbers.\n");
23693   }
23694 
23695   regionnumlist = new list(sizeof(int), NULL, 256);
23696   regiontetlist = new list(sizeof(triface), NULL, 1024);
23697   attridx = in->numberoftetrahedronattributes;
23698 
23699   // Loop through all tets. Infect tets which already have a region number,
23700   //   and save the used numbers in 'regionnumlist'.
23701   tetrahedrons->traversalinit();
23702   tetloop.tet = tetrahedrontraverse();
23703   while (tetloop.tet != (tetrahedron *) NULL) {
23704     if (!infected(tetloop)) {
23705       regionnum = (int) elemattribute(tetloop.tet, attridx);
23706       if (regionnum != 0.0) {
23707         // Found a numbered region tet.
23708         infect(tetloop);
23709         regiontetlist->append(&tetloop);
23710         // Found and infect all tets in this region.
23711         for (i = 0; i < regiontetlist->len(); i++) {
23712           regiontet = * (triface *)(* regiontetlist)[i];
23713           for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23714             // Is there a boundary face?
23715             tspivot(regiontet, checksh);
23716             if (checksh.sh == dummysh) {
23717               sym(regiontet, neightet);
23718               if ((neightet.tet != dummytet) && !infected(neightet)) {
23719 #ifdef SELF_CHECK
23720                 // neightet should have the same region number. Check it.
23721                 num = (int) elemattribute(neightet.tet, attridx);
23722                 assert(num == regionnum);
23723 #endif
23724                 infect(neightet);
23725                 regiontetlist->append(&neightet);
23726               }
23727             }
23728           }
23729         }
23730         // Add regionnum to list if it is not exist.
23731         flag = false;
23732         for (i = 0; i < regionnumlist->len() && !flag; i++) {
23733           num = * (int *)(* regionnumlist)[i];
23734           flag = (num == regionnum);
23735         }
23736         if (!flag) regionnumlist->append(&regionnum);
23737         // Clear list for the next region.
23738         regiontetlist->clear();
23739       }
23740     }
23741     tetloop.tet = tetrahedrontraverse();
23742   }
23743 
23744   if (b->verbose > 0) {
23745     printf("  %d user-specified regions.\n", regionnumlist->len());
23746   }
23747 
23748   // Now loop the tets again. Assign region numbers to uninfected tets.
23749   tetrahedrons->traversalinit();
23750   tetloop.tet = tetrahedrontraverse();
23751   regionnum = 1;  // Start region number.
23752   count = 0;
23753   while (tetloop.tet != (tetrahedron *) NULL) {
23754     if (!infected(tetloop)) {
23755       // An unassigned region tet.
23756       count++;
23757       do {
23758         flag = false;
23759         // Check if the region number has been used.
23760         for (i = 0; i < regionnumlist->len() && !flag; i++) {
23761           num = * (int *)(* regionnumlist)[i];
23762           flag = (num == regionnum);
23763         }
23764         if (flag) regionnum++;
23765       } while (flag);
23766       setelemattribute(tetloop.tet, attridx, (REAL) regionnum);
23767       infect(tetloop);
23768       regiontetlist->append(&tetloop);
23769       // Found and infect all tets in this region.
23770       for (i = 0; i < regiontetlist->len(); i++) {
23771         regiontet = * (triface *)(* regiontetlist)[i];
23772         for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23773           // Is there a boundary face?
23774           tspivot(regiontet, checksh);
23775           if (checksh.sh == dummysh) {
23776             sym(regiontet, neightet);
23777             if ((neightet.tet != dummytet) && !infected(neightet)) {
23778 #ifdef SELF_CHECK
23779               // neightet should have not been assigned yet. Check it.
23780               num = (int) elemattribute(neightet.tet, attridx);
23781               assert(num == 0);
23782 #endif
23783               setelemattribute(neightet.tet, attridx, (REAL) regionnum);
23784               infect(neightet);
23785               regiontetlist->append(&neightet);
23786             }
23787           }
23788         }
23789       }
23790       regiontetlist->clear();
23791       regionnum++; // The next region number.
23792     }
23793     tetloop.tet = tetrahedrontraverse();
23794   }
23795 
23796   // Uninfect all tets.
23797   tetrahedrons->traversalinit();
23798   tetloop.tet = tetrahedrontraverse();
23799   while (tetloop.tet != (tetrahedron *) NULL) {
23800 #ifdef SELF_CHECK
23801     assert(infected(tetloop));
23802 #endif
23803     uninfect(tetloop);
23804     tetloop.tet = tetrahedrontraverse();
23805   }
23806 
23807   if (b->verbose > 0) {
23808     printf("  %d regions are numbered.\n", count);
23809   }
23810 
23811   delete regionnumlist;
23812   delete regiontetlist;
23813 }
23814 
23816 //                                                                           //
23817 // carveholes()    Find the holes and infect them.  Find the volume          //
23818 //                 constraints and infect them.  Infect the convex hull.     //
23819 //                 Spread the infection and kill tetrahedra.  Spread the     //
23820 //                 volume constraints.                                       //
23821 //                                                                           //
23822 // This routine mainly calls other routines to carry out all these functions.//
23823 //                                                                           //
23825 
23826 void tetgenmesh::carveholes()
23827 {
23828   memorypool *holeviri, *regionviri;
23829   tetrahedron *tptr, **holetet, **regiontet;
23830   triface searchtet, *holetets, *regiontets;
23831   enum locateresult intersect;
23832   int i;
23833 
23834   if (!b->quiet) {
23835     printf("Removing unwanted tetrahedra.\n");
23836     if (b->verbose && (in->numberofholes > 0)) {
23837       printf("  Marking holes for elimination.\n");
23838     }
23839   }
23840 
23841   // Initialize a pool of viri to be used for holes, concavities.
23842   holeviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23843   // Mark as infected any unprotected tetrahedra on the boundary.
23844   infecthull(holeviri);
23845 
23846   if (in->numberofholes > 0) {
23847     // Allocate storage for the tetrahedra in which hole points fall.
23848     holetets = (triface *) new triface[in->numberofholes];
23849     // Infect each tetrahedron in which a hole lies.
23850     for (i = 0; i < 3 * in->numberofholes; i += 3) {
23851       // Ignore holes that aren't within the bounds of the mesh.
23852       if ((in->holelist[i] >= xmin) && (in->holelist[i] <= xmax)
23853           && (in->holelist[i + 1] >= ymin)
23854           && (in->holelist[i + 1] <= ymax)
23855           && (in->holelist[i + 2] >= zmin)
23856           && (in->holelist[i + 2] <= zmax)) {
23857         searchtet.tet = dummytet;
23858         // Find a tetrahedron that contains the hole.
23859         intersect = locate(&in->holelist[i], &searchtet);
23860         if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23861           // Record the tetrahedron for processing carve hole.
23862           holetets[i / 3] = searchtet;
23863         }
23864       }
23865     }
23866     // Infect the hole tetrahedron.  This is done by marking the tet as
23867     //   infected and including the tetrahedron in the virus pool.
23868     for (i = 0; i < in->numberofholes; i++) {
23869       infect(holetets[i]);
23870       holetet = (tetrahedron **) holeviri->alloc();
23871       *holetet = holetets[i].tet;
23872     }
23873     // Free up memory.
23874     delete [] holetets;
23875   }
23876 
23877   // Mark as infected all tets of the holes and concavities.
23878   plague(holeviri);
23879   // The virus pool contains all outside tets now.
23880 
23881   // Is -A switch in use.
23882   if (b->regionattrib) {
23883     // Assign every tetrahedron a regional attribute of zero.
23884     tetrahedrons->traversalinit();
23885     tptr = tetrahedrontraverse();
23886     while (tptr != (tetrahedron *) NULL) {
23887       setelemattribute(tptr, in->numberoftetrahedronattributes, 0.0);
23888       tptr = tetrahedrontraverse();
23889     }
23890   }
23891 
23892   if (in->numberofregions > 0) {
23893     if (!b->quiet) {
23894       if (b->regionattrib) {
23895         if (b->varvolume) {
23896           printf("Spreading regional attributes and volume constraints.\n");
23897         } else {
23898           printf("Spreading regional attributes.\n");
23899         }
23900       } else {
23901         printf("Spreading regional volume constraints.\n");
23902       }
23903     }
23904     // Allocate storage for the tetrahedra in which region points fall.
23905     regiontets = (triface *) new triface[in->numberofregions];
23906     // Find the starting tetrahedron for each region.
23907     for (i = 0; i < in->numberofregions; i++) {
23908       regiontets[i].tet = dummytet;
23909       // Ignore region points that aren't within the bounds of the mesh.
23910       if ((in->regionlist[5 * i] >= xmin)
23911            && (in->regionlist[5 * i] <= xmax)
23912            && (in->regionlist[5 * i + 1] >= ymin)
23913            && (in->regionlist[5 * i + 1] <= ymax)
23914            && (in->regionlist[5 * i + 2] >= zmin)
23915            && (in->regionlist[5 * i + 2] <= zmax)) {
23916         searchtet.tet = dummytet;
23917         // Find a tetrahedron that contains the region point.
23918         intersect = locate(&in->regionlist[5 * i], &searchtet);
23919         if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23920           // Record the tetrahedron for processing after the
23921           //   holes have been carved.
23922           regiontets[i] = searchtet;
23923         }
23924       }
23925     }
23926     // Initialize a pool to be used for regional attrs, and/or regional
23927     //   volume constraints.
23928     regionviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23929     // Find and set all regions.
23930     for (i = 0; i < in->numberofregions; i++) {
23931       if (regiontets[i].tet != dummytet) {
23932         // Make sure the tetrahedron under consideration still exists.
23933         //   It may have been eaten by the virus.
23934         if (!isdead(&(regiontets[i]))) {
23935           // Put one tetrahedron in the virus pool.
23936           infect(regiontets[i]);
23937           regiontet = (tetrahedron **) regionviri->alloc();
23938           *regiontet = regiontets[i].tet;
23939           // Apply one region's attribute and/or volume constraint.
23940           regionplague(regionviri, in->regionlist[5 * i + 3],
23941                        in->regionlist[5 * i + 4]);
23942           // The virus pool should be empty now.
23943         }
23944       }
23945     }
23946     // Free up memory.
23947     delete [] regiontets;
23948     delete regionviri;
23949   }
23950 
23951   // Now acutually remove the outside and hole tets.
23952   removeholetets(holeviri);
23953   // The mesh is nonconvex now.
23954   nonconvex = 1;
23955 
23956   if (b->regionattrib) {
23957     if (b->regionattrib > 1) {
23958       // -AA switch. Assign each tet a region number (> 0).
23959       assignregionattribs();
23960     }
23961     // Note the fact that each tetrahedron has an additional attribute.
23962     in->numberoftetrahedronattributes++;
23963   }
23964 
23965   // Free up memory.
23966   delete holeviri;
23967 }
23968 
23969 //
23970 // End of carving out holes and concavities routines
23971 //
23972 
23973 //
23974 // Begin of boundary Steiner points removing routines
23975 //
23976 
23978 //                                                                           //
23979 // replacepolygonsubs()    Substitute the subfaces of a polygon.             //
23980 //                                                                           //
23981 // 'oldshlist' (T_old) contains the old subfaces of P.  It will be replaced  //
23982 // by 'newshlist' (T_new) of new subfaces. Each boundary edge of P is bonded //
23983 // to 'dummysh' in T_new.                                                    //
23984 //                                                                           //
23985 // Notice that Not every boundary edge of T_new is able to bond to a subface,//
23986 // e.g., when it is a segment recovered by removing a Steiner point in it.   //
23987 //                                                                           //
23989 
23990 void tetgenmesh::replacepolygonsubs(list* oldshlist, list* newshlist)
23991 {
23992   face newsh, oldsh, spinsh;
23993   face casingout, casingin;
23994   face checkseg;
23995   point pa, pb;
23996   int i, j, k, l;
23997 
23998   for (i = 0; i < newshlist->len(); i++) {
23999     // Get a new subface s.
24000     newsh = * (face *)(* newshlist)[i];
24001     // Check the three edges of s.
24002     for (k = 0; k < 3; k++) {
24003       spivot(newsh, casingout);
24004       // Is it a boundary edge?
24005       if (casingout.sh == dummysh) {
24006         // Find the old subface s_o having the same edge as s.
24007         pa = sorg(newsh);
24008         pb = sdest(newsh);
24009         for (j = 0; j < oldshlist->len(); j++) {
24010           oldsh = * (face *)(* oldshlist)[j];
24011       for (l = 0; l < 3; l++) {
24012             if (((sorg(oldsh) == pa) && (sdest(oldsh) == pb)) ||
24013                 ((sorg(oldsh) == pb) && (sdest(oldsh) == pa))) break;
24014             senextself(oldsh);
24015           }
24016           if (l < 3) break;
24017         }
24018         // Is there a matched edge?
24019         if (j < oldshlist->len()) {
24020           // Get the neighbor subface s_out.
24021           spivot(oldsh, casingout);
24022           sspivot(oldsh, checkseg);
24023           if (checkseg.sh != dummysh) {
24024             // A segment. Insert s into the face ring, ie, s_in -> s -> s_out.
24025             if (oldsh.sh != casingout.sh) {
24026               // s is not bonded to itself.
24027               spinsh = casingout;
24028               do {
24029                 casingin = spinsh;
24030                 spivotself(spinsh);
24031               } while (sapex(spinsh) != sapex(oldsh));
24032               assert(casingin.sh != oldsh.sh);
24033               // Bond s_in -> s -> s_out (and dissolve s_in -> s_old -> s_out).
24034               sbond1(casingin, newsh);
24035               sbond1(newsh, casingout);
24036             } else {
24037               // Bond newsh -> newsh.
24038               sbond(newsh, newsh);
24039             }
24040             // Bond the segment.
24041             ssbond(newsh, checkseg);
24042           } else {
24043             // Bond s <-> s_out (and dissolve s_out -> s_old).
24044             sbond(newsh, casingout);
24045           }
24046           // Unbound oldsh to indicate it's neighbor has been replaced.
24047           //   It will be used to indentfy the edge in the inverse.
24048           sdissolve(oldsh);
24049           ssdissolve(oldsh);
24050         }
24051       }
24052       // Go to the next edge of s.
24053       senextself(newsh);
24054     }
24055   }
24056 }
24057 
24059 //                                                                           //
24060 // orientnewsubs()    Orient new subfaces facing to the inside of cavity.    //
24061 //                                                                           //
24062 // 'newshlist' contains new subfaces of the cavity C (created by re-triangu- //
24063 // lation the polygon P). They're not necessary facing to the inside of C.   //
24064 // 'orientsh', faces to the inside of C, is used to adjust new subfaces. The //
24065 // normal of the new subfaces is returned in 'norm'.                         //
24066 //                                                                           //
24068 
24069 void tetgenmesh::orientnewsubs(list* newshlist, face* orientsh, REAL* norm)
24070 {
24071   face *newsh;
24072   point pa, pb, pc;
24073   REAL ref[3], ori, len;
24074   int i;
24075 
24076   // Calculate the normal of 'orientsh'.
24077   pa = sorg(*orientsh);
24078   pb = sdest(*orientsh);
24079   pc = sapex(*orientsh);
24080   facenormal(pa, pb, pc, norm, &len);
24081   for (i = 0; i < 3; i++) ref[i] = pa[i] + norm[i];
24082   for (i = 0; i < 3; i++) norm[i] /= len;
24083 
24084   // Orient new subfaces. Let the normal above each one.
24085   for (i = 0; i < newshlist->len(); i++) {
24086     newsh = (face *)(* newshlist)[i];
24087     pa = sorg(*newsh);
24088     pb = sdest(*newsh);
24089     pc = sapex(*newsh);
24090     ori = orient3d(pa, pb, pc, ref);
24091     assert(ori != 0.0);
24092     if (ori > 0.0) {
24093       sesymself(*newsh);
24094     }
24095   }
24096 }
24097 
24099 //                                                                           //
24100 // constrainedflip()    Flip a non-constrained face.                         //
24101 //                                                                           //
24102 // 'flipface' f (abc) is a face we want to flip. In addition, if 'front' is  //
24103 // given (not a NULL), f is a crossface. f may not be flippable if it is one //
24104 // of the following cases:                                                   //
24105 //   (1) f has an aux subface attached;                                      //
24106 //   (2) f is on the convex hull;                                            //
24107 //   (3) f is not locally Delaunay (f must be recovered by a previous flip,  //
24108 //       we should keep it, otherwise, we may fall into a flip loop);        //
24109 //   (4) f is T32 at ab, but abd or abe has an aux subface attached;         //
24110 //   (5) f is T22 or T44 at ab, but abd, or abe, or abf has an aux subface   //
24111 //       attached;                                                           //
24112 //   (6) f is unflipable at ab, and abd, abe, ... are all unflippable due to //
24113 //       the cases (1) - (5).                                                //
24114 // If f is a crssface ('front' != NULL) and it is unflipable due to case (3),//
24115 // (4), (5) and (6). Try to flip the next crossing face of front first.      //
24116 //                                                                           //
24118 
24119 bool tetgenmesh::constrainedflip(triface* flipface, triface* front,
24120   queue* flipque)
24121 {
24122   triface symface, spintet;
24123   face checksh;
24124   point pa, pb, pc, pd, pe;
24125   enum fliptype fc;
24126   REAL sign;
24127   bool doflip;
24128   int ia, ib, ic, id, ie;
24129   int i;
24130 
24131   // (1) Is f protected by an (auxilary) subface?
24132   tspivot(*flipface, checksh);
24133   if (checksh.sh != dummysh) return false;
24134   // (2) Is f on the convex hull?
24135   sym(*flipface, symface);
24136   if (symface.tet == dummytet) return false;
24137   // (3) Is f not locally Delaunay?
24138   adjustedgering(*flipface, CCW);
24139   pa = dest(*flipface);
24140   pb = org(*flipface);
24141   pc = apex(*flipface);
24142   pd = oppo(*flipface);
24143   pe = oppo(symface);
24144   // if (symbolic) {
24145     ia = pointmark(pa);
24146     ib = pointmark(pb);
24147     ic = pointmark(pc);
24148     id = pointmark(pd);
24149     ie = pointmark(pe);
24150     sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24151     assert(sign != 0.0);
24152   // } else {
24153   //   sign = insphere(pa, pb, pc, pd, pe);
24154   // }
24155   if (sign <= 0.0) {
24156     // Get the fliptype of f.
24157     checksubfaces = 0; // switch off subface test.
24158     fc = categorizeface(*flipface);
24159     checksubfaces = 1; // switch on subface test.
24160     if (fc == T23) {
24161       doflip = true;
24162       // Avoid one tet created by the 2-3 flip is nearly degenerate.
24163       /* pc = oppo(*flipface);
24164       pd = oppo(symface);
24165       adjustedgering(*flipface, CCW);
24166       for (i = 0; i < 3; i++) {
24167         pa = org(*flipface);
24168         pb = dest(*flipface);
24169         ori = orient3d(pa, pb, pc, pd);
24170         if (iscoplanar(pa, pb, pc, pd, ori, b->epsilon)) {
24171           doflip = false; break;
24172         }
24173         enextself(*flipface);
24174       } */
24175       if (doflip) {
24176         flip23(flipface, flipque);
24177         return true;
24178       }
24179     } else if (fc == T32) {
24180       // (4) Is abd, or abe protected?
24181       doflip = true;
24182       spintet = *flipface;
24183       for (i = 0; i < 2; i++) {
24184         fnextself(spintet);
24185         tspivot(spintet, checksh);
24186         if (checksh.sh != dummysh) {
24187           doflip = false; break; // f is protected. Unflipable.
24188         }
24189       }
24190       if (doflip) {
24191         flip32(flipface, flipque);
24192         return true;
24193       }
24194     } else if (fc == T22 || fc == T44) {
24195       // (5) Is abd, abe, or abf protected?
24196       doflip = true;
24197       if (fc == T22) {
24198         for (i = 0; i < 2; i++) {
24199           spintet = *flipface;
24200           if (i == 1) {
24201             esymself(spintet);
24202           }
24203           fnextself(spintet);
24204           tspivot(spintet, checksh);
24205           if (checksh.sh != dummysh) {
24206             doflip = false; break; // f is protected. Unflipable.
24207           }
24208         }
24209       } else if (fc == T44) {
24210         spintet = *flipface;
24211         for (i = 0; i < 3; i++) {
24212           fnextself(spintet);
24213           tspivot(spintet, checksh);
24214           if (checksh.sh != dummysh) {
24215             doflip = false; break; // f is protected. Unflipable.
24216           }
24217         }
24218       }
24219       if (doflip) {
24220         flip22(flipface, flipque);
24221         return true;
24222       }
24223     } else if (fc == N32) {
24224       // Is f a crossface?
24225       if (front != (triface *) NULL) {
24226         // (6) Is any obstacle face (abd, or abe, ...) flipable?
24227         spintet = *flipface;
24228         while (fnextself(spintet)) {
24229           if (apex(spintet) == apex(*flipface)) break;
24230           // Check if spintet is flipable, no recursive.
24231           if (constrainedflip(&spintet, NULL, flipque)) {
24232             // One obstacle face has been flipped.
24233             return true;
24234           }
24235           // Unflipable. Go to the next obstacle face.
24236           findedge(&spintet, org(*flipface), dest(*flipface));
24237         }
24238       }
24239     }
24240   }
24241 
24242   // f is unflipable. Is f a crossface?
24243   if (front != (triface *) NULL) {
24244     // Look if there is another crossface.
24245     pa = org(*front);
24246     pb = dest(*front);
24247     pc = apex(*front);
24248     // sym(*flipface, symface);
24249     // Have we reach the end of abc (We've started from edge ab).
24250     if (oppo(symface) != pc) {
24251       adjustedgering(symface, CCW);
24252       for (i = 0; i < 3; i++) {
24253         fnext(symface, spintet);
24254         // Is c ahead of this face?
24255         sign = orient3d(org(spintet), dest(spintet), apex(spintet), pc);
24256         if (sign < 0.0) {
24257           if (tritritest(&spintet, pa, pb, pc)) {
24258             if (b->verbose > 2) {
24259               printf("    Next crossface (%d, %d, %d).\n",
24260                      pointmark(org(spintet)), pointmark(dest(spintet)),
24261                      pointmark(apex(spintet)));
24262             }
24263             return constrainedflip(&spintet, front, flipque);
24264             // return constrainedflip(&spintet, NULL, flipque);
24265           }
24266         }
24267         enextself(symface);
24268       }
24269     }
24270   }
24271   return false;
24272 }
24273 
24275 //                                                                           //
24276 // recoverfront()    Recover a missing front by flips.                       //
24277 //                                                                           //
24278 // 'front' f is missing in D - it was crossed by faces of D. The cross faces //
24279 // may be flippable, so f can be recovered by flipping them away.            //
24280 //                                                                           //
24282 
24283 bool tetgenmesh::recoverfront(triface* front, list* newtetlist, queue* flipque)
24284 {
24285   triface idfront, starttet, spintet;
24286   point pa, pb, pc, pd, ref;
24287   enum locateresult loc;
24288   enum finddirectionresult col;
24289   REAL ori, ori1, ori2, sign;
24290   int hitbdry;
24291   int i, j;
24292 
24293   // Find an existing edge of f in D to start with.
24294   for (i = 0; i < 3; i++) {
24295     pa = org(*front);
24296     pb = dest(*front);
24297     // Get a tet for searching.
24298     idfront = recenttet;
24299     // Make sure the tet is valid (flip32() may kill a tet).
24300     if (isdead(&idfront)) {
24301       // The tet is dead. Get a live tet in D. !!!
24302       for (j = 0; j < newtetlist->len(); j++) {
24303         recenttet = * (triface *)(* newtetlist)[j];
24304         if (!isdead(&recenttet)) break;
24305       }
24306       assert(j < newtetlist->len());
24307     }
24308     loc = preciselocate(pa, &idfront, (long) newtetlist->len());
24309     if (loc != ONVERTEX) {
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)) break;
24315       }
24316       assert(j < newtetlist->len()); // a must belong to one tet.
24317     }
24318     recenttet = idfront;
24319     // Search for a tet having edge ab.
24320     col = finddirection(&idfront, pb, (long) newtetlist->len());
24321     if (col == BELOWHULL) {
24322       // Do a brute-force search in D.
24323       for (j = 0; j < newtetlist->len(); j++) {
24324         idfront = * (triface *)(* newtetlist)[j];
24325         if (isdead(&idfront)) continue;
24326         if (findorg(&idfront, pa)) {
24327           assert(org(idfront) == pa);
24328           if (dest(idfront) == pb) {
24329             col = RIGHTCOLLINEAR; break;
24330           } else if (apex(idfront) == pb) {
24331             col = LEFTCOLLINEAR; break;
24332           } else if (oppo(idfront) == pb) {
24333             col = TOPCOLLINEAR; break;
24334           }
24335         }
24336       }
24337     }
24338     if (col == RIGHTCOLLINEAR) {
24339       // b is just the destination.
24340     } else if (col == LEFTCOLLINEAR) {
24341       enext2self(idfront);
24342       esymself(idfront);
24343     } else if (col == TOPCOLLINEAR) {
24344       fnextself(idfront);
24345       enext2self(idfront);
24346       esymself(idfront);
24347     }
24348     if (dest(idfront) == pb) break; // Found.
24349     // Missing. Go to the next edge of f.
24350     enextself(*front);
24351   }
24352   if (i == 3) {
24353     // All three edges of f are missing - unrecoverable.
24354     return false;
24355   }
24356 
24357   // Search for a tet having f (abc).
24358   pc = apex(*front);
24359   spintet = idfront;
24360   hitbdry = 0;
24361   do {
24362     if (apex(spintet) == pc) {
24363       // Found abc. Insert an auxilary subface s at idfront.
24364       insertauxsubface(front, &spintet);
24365       return true;
24366     }
24367     if (!fnextself(spintet)) {
24368       hitbdry ++;
24369       if (hitbdry < 2) {
24370         esym(idfront, spintet);
24371         if (!fnextself(spintet)) {
24372           hitbdry ++;
24373         }
24374       }
24375     }
24376     if (apex(spintet) == apex(idfront)) break;
24377   } while (hitbdry < 2);
24378 
24379   // Search for a crossing face to flip.
24380   pd = apex(idfront);
24381   assert(pd != pc);
24382   // Decide the orientation of d with abc.
24383   ori = orient3d(pa, pb, pc, pd);
24384   if (ori < 0.0) {
24385     // d is above abc. Rotate downwards.
24386     esym(idfront, starttet);
24387     sign = -1.0;
24388   } else if (ori > 0.0) {
24389     // d is below abc. Rotate upwards.
24390     starttet = idfront;
24391     sign = 1.0;
24392   } else {
24393     assert(ori == 0.0);
24394     // d is coplanar with abc. Do abc and abd intersect?
24395     ref = oppo(idfront);
24396     ori1 = orient3d(pa, pb, ref, pc);
24397     ori2 = orient3d(pa, pb, ref, pd);
24398     assert(ori1 * ori2 != 0.0);
24399     if (ori1 * ori2 > 0) {
24400       // abc and abd intersect.  There're two possible intersections:
24401       //   ad and bc, or ac and bd.  Find it out.
24402       ori1 = orient3d(pb, pc, ref, pd);
24403       ori2 = orient3d(pb, pc, ref, pa);
24404       assert(ori1 * ori2 != 0.0);
24405       if (ori1 * ori2 > 0) {
24406         // ac intersects bd.
24407         enextself(idfront); // go to edge bd.
24408       } else {
24409         // ad intersects bc.
24410         enext2self(idfront); // go to edge ad.
24411       }
24412       adjustedgering(idfront, CCW);
24413       fnextself(idfront); // face ade or bce need a 4-to-4 flip.
24414       if (b->verbose > 2) {
24415         printf("    Get crossface (%d, %d, %d).\n", pointmark(org(idfront)),
24416                pointmark(dest(idfront)), pointmark(apex(idfront)));
24417       }
24418       if (constrainedflip(&idfront, front, flipque)) {
24419         // A crossface has been flipped. Continue to recover f.
24420         return recoverfront(front, newtetlist, flipque);
24421       }
24422       // Unable to recover f.
24423       return false; // sign = 0.0;
24424     } else {
24425       // Not intersect. We can go either direction.
24426       starttet = idfront;
24427       if (fnextself(starttet)) {
24428         // Choose to rotate upwards.
24429         sign = 1.0;
24430       } else {
24431         // Hit convex hull. Choose to rotate downwrads.
24432         esym(idfront, starttet);
24433         sign = -1.0;
24434       }
24435     }
24436   }
24437 
24438   assert(sign != 0.0);
24439   if (sign == -1) {
24440     // The edge ab has be changed. Reverse it.
24441     pa = org(starttet);
24442     pb = dest(starttet);
24443     // The sign has been reversed as well.
24444     sign = -sign;
24445   }
24446   // Rotate face abd around edge ab. Moreover, we've chosen the rotate
24447   //   direction such that no convex hull face will be reach.
24448   spintet = starttet;
24449   while (fnextself(spintet)) {
24450     pd = apex(spintet);
24451     assert(pd != pc);
24452     // Check if the orientation of d (with abc) has changed.
24453     ori = orient3d(pa, pb, pc, pd);
24454     if (ori == 0.0) {
24455       // abc and abd must coplanar intersect (4-to-4 flip is needed).
24456       ref = oppo(spintet);
24457       ori1 = orient3d(pb, pc, ref, pd);
24458       ori2 = orient3d(pb, pc, ref, pa);
24459       assert(ori1 * ori2 != 0.0);
24460       if (ori1 * ori2 > 0) {
24461         // ac intersects bd.
24462         enextself(spintet); // go to edge bd.
24463       } else {
24464         // ad intersects bc.
24465         enext2self(spintet); // go to edge ad.
24466       }
24467       adjustedgering(spintet, CCW);
24468       fnextself(spintet); // face ade or bce need a 4-to-4 flip.
24469       if (b->verbose > 2) {
24470         printf("    Get crossface (%d, %d, %d).\n", pointmark(org(spintet)),
24471                pointmark(dest(spintet)), pointmark(apex(spintet)));
24472       }
24473       if (constrainedflip(&spintet, front, flipque)) {
24474         // A crossface has been flipped. Continue to recover f.
24475         return recoverfront(front, newtetlist, flipque);
24476       }
24477       // Unable to recover f.
24478       return false; // sign = 0.0;
24479     } else if (ori * sign < 0.0) {
24480       // Sign has changed. The face dea or deb must cross abc.
24481       adjustedgering(spintet, CCW);
24482       enextself(spintet);
24483       for (i = 0; i < 2; i++) {
24484         // Get the face dea or deb.
24485         fnext(spintet, starttet);
24486         if (tritritest(&starttet, pa, pb, pc)) {
24487           if (b->verbose > 2) {
24488             printf("    Get crossface (%d, %d, %d).\n",
24489                    pointmark(org(starttet)), pointmark(dest(starttet)),
24490                    pointmark(apex(starttet)));
24491           }
24492           if (constrainedflip(&starttet, front, flipque)) {
24493             // A crossface has been flipped. Continue to recover f.
24494             return recoverfront(front, newtetlist, flipque);
24495           }
24496         }
24497         enextself(spintet);
24498       }
24499       // Unable to recover f.
24500       return false;
24501     }
24502   }
24503   // Impossible to be here.
24504   assert(0);
24505   return false;
24506 }
24507 
24509 //                                                                           //
24510 // repairflips()    Flip non-Delaunay and non-constrained faces.             //
24511 //                                                                           //
24513 
24514 void tetgenmesh::repairflips(queue* flipque)
24515 {
24516   badface *qface;
24517   triface flipface, symface, spintet;
24518   face checksh;
24519   point pa, pb, pc, pd, pe;
24520   enum fliptype fc;
24521   REAL sign;
24522   long flipcount;
24523   bool doflip;
24524   int ia, ib, ic, id, ie;
24525   int i;
24526 
24527   if (b->verbose > 1) {
24528     printf("    Repair flip %ld faces.\n", flipque->len());
24529   }
24530   flipcount = flip23s + flip32s + flip22s + flip44s;
24531   // Loop until the queue is empty.
24532   while (!flipque->empty()) {
24533     qface = (badface *) flipque->pop();
24534     flipface = qface->tt;
24535     // Check the validity of this face.
24536     if (isdead(&flipface) || flipface.tet == dummytet ||
24537         (org(flipface) != qface->forg) ||
24538         (dest(flipface) != qface->fdest) ||
24539         (apex(flipface) != qface->fapex) ||
24540         (oppo(flipface) == (point) NULL)) continue;
24541     // (1) Is f protected by an (auxilary) subface?
24542     tspivot(flipface, checksh);
24543     if (checksh.sh != dummysh) continue;
24544     // (2) Is f on the convex hull?
24545     sym(flipface, symface);
24546     if (symface.tet == dummytet) continue;
24547     // For positive orientation that insphere() test requires.
24548     adjustedgering(flipface, CW);
24549     pa = org(flipface);
24550     pb = dest(flipface);
24551     pc = apex(flipface);
24552     pd = oppo(flipface);
24553     pe = oppo(symface);
24554     // if (symbolic) {
24555       ia = pointmark(pa);
24556       ib = pointmark(pb);
24557       ic = pointmark(pc);
24558       id = pointmark(pd);
24559       ie = pointmark(pe);
24560       sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24561       assert(sign != 0.0);
24562     // } else {
24563     //   sign = insphere(pa, pb, pc, pd, pe);
24564     // }
24565     if (sign > 0.0) {
24566       // f is non-lcally Delaunay. Get the fliptype of f.
24567       checksubfaces = 0; // switch off subface test.
24568       fc = categorizeface(flipface);
24569       checksubfaces = 1; // switch on subface test.
24570       if (fc == T23) {
24571         doflip = true;
24572         // Avoid to create a nearly degenerate tet.
24573         /* pc = oppo(flipface);
24574         pd = oppo(symface);
24575         adjustedgering(flipface, CCW);
24576         for (i = 0; i < 3; i++) {
24577           pa = org(flipface);
24578           pb = dest(flipface);
24579           ori = orient3d(pa, pb, pc, pd);
24580           if (iscoplanar(pa, pb, pc, pd, ori, b->epsilon)) {
24581             doflip = false; break;
24582           }
24583           enextself(flipface);
24584         } */
24585         if (doflip) {
24586           flip23(&flipface, flipque);
24587         }
24588       } else if (fc == T32) {
24589         // (4) Is abd, or abe protected?
24590         doflip = true;
24591         spintet = flipface;
24592         for (i = 0; i < 2; i++) {
24593           fnextself(spintet);
24594           tspivot(spintet, checksh);
24595           if (checksh.sh != dummysh) {
24596             doflip = false; break; // f is protected. Unflipable.
24597           }
24598         }
24599         if (doflip) {
24600           flip32(&flipface, flipque);
24601         }
24602       } else if (fc == T22 || fc == T44) {
24603         // (5) Is abd, abe, or abf protected?
24604         doflip = true;
24605         if (fc == T22) {
24606           for (i = 0; i < 2; i++) {
24607             spintet = flipface;
24608             if (i == 1) {
24609               esymself(spintet);
24610             }
24611             fnextself(spintet);
24612             tspivot(spintet, checksh);
24613             if (checksh.sh != dummysh) {
24614               doflip = false; break; // f is protected. Unflipable.
24615             }
24616           }
24617         } else if (fc == T44) {
24618           spintet = flipface;
24619           for (i = 0; i < 3; i++) {
24620             fnextself(spintet);
24621             tspivot(spintet, checksh);
24622             if (checksh.sh != dummysh) {
24623               doflip = false; break; // f is protected. Unflipable.
24624             }
24625           }
24626         }
24627         if (doflip) {
24628           flip22(&flipface, flipque);
24629         }
24630       }
24631     }
24632   }
24633   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
24634   if (b->verbose > 1) {
24635     printf("    %ld flips.\n", flipcount);
24636   }
24637 }
24638 
24640 //                                                                           //
24641 // constrainedcavity()    Tetrahedralize a cavity by constrained tetrahedra. //
24642 //                                                                           //
24643 // The cavity C is bounded by faces F in 'floorlist' and 'ceillist'. 'ptlist'//
24644 // V is the set of vertices of C.                                            //
24645 //                                                                           //
24647 
24648 bool tetgenmesh::constrainedcavity(triface* oldtet, list* floorlist,
24649   list* ceillist, list* ptlist, list* frontlist, list* misfrontlist,
24650   list* newtetlist, queue* flipque)
24651 {
24652   triface misfront, newtet;
24653   long facenum;
24654   int i;
24655 
24656   if (b->verbose > 1) {
24657     printf("    Constrained cavity (%d floors, %d ceilings, %d vertices).\n",
24658            floorlist->len(), ceillist->len(), ptlist->len());
24659   }
24660 
24661   // symbolic = 1;
24662 
24663   // Initialize the cavity C.
24664   initializecavity(floorlist, ceillist, frontlist);
24665   // Form the D of the vertices of C.
24666   delaunizecavvertices(oldtet, ptlist, NULL, newtetlist, flipque);
24667 
24668   // Identify faces of C in D.
24669   if (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
24670     // Some faces are missing.
24671     recenttet = * (triface *)(* newtetlist)[0];
24672     assert((recenttet.tet != dummytet) && !isdead(&recenttet));
24673     // Try to recover missing faces by flips.
24674     do {
24675       facenum = misfrontlist->len();
24676       for (i = 0; i < misfrontlist->len(); i++) {
24677         // Get a missing front f.
24678         misfront = * (triface *)(* misfrontlist)[i];
24679         // Let f face toward the inside of C.
24680         adjustedgering(misfront, CW);
24681         if (b->verbose > 1) {
24682           printf("    Recover face (%d, %d, %d).\n", pointmark(org(misfront)),
24683                  pointmark(dest(misfront)), pointmark(apex(misfront)));
24684         }
24685         if (recoverfront(&misfront, newtetlist, flipque)) {
24686           // f has been recovered.
24687           frontlist->append(&misfront);
24688           misfrontlist->del(i, 0); i--;
24689         }
24690         // Flip non-locally non-constrained Delaunay faces.
24691         repairflips(flipque);
24692       }
24693       // Have all faces been recovered?
24694       if (misfrontlist->len() == 0) break;
24695       // No! There are still un-recovered faces. Continue the loop if any
24696       //   face has been recovered.
24697     } while (misfrontlist->len() < facenum);
24698     // Retrieve new tets and purge dead tets in D.
24699     retrievenewtets(newtetlist);
24700   }
24701 
24702   // symbolic = 0;
24703 
24704   if (misfrontlist->len() == 0) {
24705     // All fronts have identified in D. Get the shape of C by removing out
24706     //   tets of C. 'misfrontlist' is reused for removing out tets.
24707     //   Don't do flip since the new tets may get deleted later.
24708     carvecavity(newtetlist, misfrontlist, NULL);
24709     // Recover locally Delaunay faces.
24710     // flip(flipque, NULL);
24711     return true;
24712   } else {
24713     // Fail to tetrahedralize C.
24714     // Remove aux subfaces.
24715     detachauxsubfaces(newtetlist);
24716     // Remove new tets.
24717     for (i = 0; i < newtetlist->len(); i++) {
24718       newtet = * (triface *)(* newtetlist)[i];
24719       assert(!isdead(&newtet));
24720       tetrahedrondealloc(newtet.tet);
24721     }
24722     newtetlist->clear();
24723     // Restore faces of C in frontlist.
24724     for (i = 0; i < misfrontlist->len(); i++) {
24725       misfront = * (triface *)(* misfrontlist)[i];
24726       frontlist->append(&misfront);
24727     }
24728     return false;
24729   }
24730 }
24731 
24733 //                                                                           //
24734 // expandsteinercavity()    Expand the cavity of a Steiner point.            //
24735 //                                                                           //
24736 // Expand the cavity C if there fronts (except fronts having subfaces) which //
24737 // are either (nearly) coplanar or invisible by the Steiner point.           //
24738 //                                                                           //
24740 
24741 void tetgenmesh::expandsteinercavity(point steinpt, REAL eps, list* frontlist,
24742   list* oldtetlist)
24743 {
24744   triface front, symfront, newfront, oldfront;
24745   face frontsh;
24746   point pa, pb, pc;
24747   REAL ori;
24748   bool expflag, newflag;
24749   int i, j;
24750 
24751   do {
24752     expflag = false;
24753     for (i = 0; i < frontlist->len(); i++) {
24754       // Get a front f.
24755       front =  * (triface *)(* frontlist)[i];
24756       // f can be expanded if it is not a subface.
24757       tspivot(front, frontsh);
24758       if (frontsh.sh == dummysh) {
24759         // Let f face to the inside of C.
24760         adjustedgering(front, CW);
24761         pa = org(front);
24762         pb = dest(front);
24763         pc = apex(front);
24764         ori = orient3d(pa, pb, pc, steinpt);
24765         if (ori != 0.0) {
24766           if (iscoplanar(pa, pb, pc, steinpt, ori, eps)) {
24767             ori = 0.0; // f is nearly coplanar with p.
24768           }
24769         }
24770         if (ori >= 0.0) {
24771           // f is either invisible or coplanar with p.
24772           if (b->verbose > 2) {
24773             printf("    Remove front (%d, %d, %d).\n", pointmark(pa),
24774                    pointmark(pb), pointmark(pc));
24775           }
24776           frontlist->del(i, 1);
24777           expflag = true;
24778           break;
24779         }
24780       }
24781     }
24782     if (expflag) {
24783       assert(!infected(front) && (oppo(front) != NULL));
24784       // Expand C at f by including new fronts.
24785       adjustedgering(front, CCW);
24786       for (i = 0; i < 3; i++) {
24787         newflag = true;
24788         // Get a new boundary n of the cavity.
24789         fnext(front, symfront);
24790         tspivot(symfront, frontsh);
24791         sym(symfront, newfront);
24792         if (frontsh.sh == dummysh) {
24793           assert(newfront.tet != dummytet);
24794           // Is n a front of the unexp. cavity?
24795           if (infected(newfront)) {
24796             for (j = 0; j < frontlist->len(); j++) {
24797               oldfront = * (triface *)(* frontlist)[j];
24798               if ((oldfront.tet == symfront.tet) &&
24799                   (oldfront.loc == symfront.loc)) {
24800                 // n is not a front anymore.
24801                 if (b->verbose > 2) {
24802                   printf("    Remove front (%d, %d, %d).\n",
24803                          pointmark(org(oldfront)), pointmark(dest(oldfront)),
24804                          pointmark(apex(oldfront)));
24805                 }
24806                 frontlist->del(j, 1);
24807                 newflag = false;
24808                 break;
24809               }
24810             }
24811           }
24812         } else {
24813           // n is a subface.
24814           if (newfront.tet == dummytet) {
24815             sesymself(frontsh);
24816             // Create a fake tet to hold n.
24817             maketetrahedron(&newfront);
24818             setorg(newfront, sorg(frontsh));
24819             setdest(newfront, sdest(frontsh));
24820             setapex(newfront, sapex(frontsh));
24821             setoppo(newfront, (point) NULL);
24822             tsbond(newfront, frontsh);
24823           } else {
24824             // n should not be a front of cavity yet.
24825             assert(!infected(newfront));
24826           }
24827         }
24828         if (newflag) {
24829           if (b->verbose > 2) {
24830             printf("    Add front (%d, %d, %d).\n", pointmark(org(newfront)),
24831                    pointmark(dest(newfront)), pointmark(apex(newfront)));
24832           }
24833           frontlist->append(&newfront);
24834         }
24835         enextself(front);
24836       }
24837       // Add f into oldtetlist (to be deleted).
24838       infect(front);
24839       oldtetlist->append(&front);
24840       expcavcount++;
24841     }
24842   } while (expflag);
24843 }
24844 
24846 //                                                                           //
24847 // findrelocatepoint()    Find new location for relocating a point.          //
24848 //                                                                           //
24849 // 'frontlist' contains the boundary faces of the cavity C.  Some fronts are //
24850 // visible by 'stpt' p, some are coplanar with p.                            //
24851 //                                                                           //
24853 
24854 bool tetgenmesh::findrelocatepoint(point sp, point np, REAL* n,
24855   list* frontlist, list* oldtetlist)
24856 {
24857   triface front;
24858   point pa, pb, pc;
24859   REAL tp[3], tvol, mvol;
24860   REAL ori, eps;
24861   bool visible;
24862   int i, j, k;
24863 
24864   if (b->verbose > 1) {
24865     printf("    Find new location for point %d.\n", pointmark(sp));
24866   }
24867 
24868   // Avoid compilation warnings.
24869   tvol = mvol = 0.0;
24870   visible = false;
24871 
24872   eps = b->epsilon;
24873   // Initialize np far enough from p (outside C).
24874   for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24875   // Let tp = np;
24876   for (i = 0; i < 3; i++) tp[i] = np[i];
24877   // Interation to adjust np until it is visible by all fronts.
24878   j = 0;
24879   do {
24880     for (i = 0; i < frontlist->len(); i++) {
24881       // Get a front face f.
24882       front = * (triface *)(* frontlist)[i];
24883       // Let f face to the interior of C.
24884       adjustedgering(front, CW);
24885       pa = org(front);
24886       pb = dest(front);
24887       pc = apex(front);
24888       ori = orient3d(pa, pb, pc, np);
24889       visible = (ori < 0.0);
24890       if (!visible) {
24891         // A front is invisible by np. Move it towards p along the normal.
24892         for (i = 0; i < 3; i++) np[i] = sp[i] + 0.5 * (sp[i] - np[i]);
24893         // Failed if tp = np.
24894         if ((tp[0] == np[0]) && (tp[1] == np[1]) && (tp[2] == np[2])) {
24895           // Try to expand the cavity.
24896           expandsteinercavity(sp, eps, frontlist, oldtetlist);
24897           eps *= 10.0;
24898           if (eps > b->epsilon * 1000.0) {
24899           // printf("Internal error: Fail to relocate pt %d.\n",pointmark(sp));
24900             // internalerror();
24901             return false;
24902           }
24903           // Restart the point relocation.
24904           for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24905         }
24906         if (j % 2) {
24907           // Set tp = np (at every 2 steps) to catch the stop state.
24908           for (i = 0; i < 3; i++) tp[i] = np[i];
24909         }
24910         break;
24911       } else {
24912         // Save the smallest volume.
24913         if (i == 0) {
24914           mvol = fabs(ori);
24915         } else {
24916           mvol = fabs(ori) < mvol ? fabs(ori) : mvol;
24917         }
24918       }
24919     }
24920     j++;
24921   } while (!visible);
24922 
24923   if (b->verbose > 1) {
24924     printf("    %d iterations. minvol = %.12g.\n", j, mvol);
24925   }
24926 
24927   // Continue to adjust np until the minimal volume of tets formed by
24928   //   fronts and np doesn't increase (all fronts are visible by np).
24929   k = 0;
24930   do {
24931     j = 0;
24932     do {
24933       if (k == 0) {
24934         // Initial tp := np + 0.9 * (p - np). Move toward p.
24935         for (i = 0; i < 3; i++) tp[i] = sp[i] + 0.9 * (np[i] - sp[i]);
24936       } else {
24937         // Initial tp := np + 1.1 * (p - np). Move away from p.
24938         for (i = 0; i < 3; i++) tp[i] = sp[i] + 1.1 * (np[i] - sp[i]);
24939       }
24940       // Get the minial volume formed by tp with one of the fronts.
24941       for (i = 0; i < frontlist->len(); i++) {
24942         // Get a front face f.
24943         front = * (triface *)(* frontlist)[i];
24944         // Let f face to the interior of C.
24945         adjustedgering(front, CW);
24946         pa = org(front);
24947         pb = dest(front);
24948         pc = apex(front);
24949         ori = orient3d(pa, pb, pc, tp);
24950         visible = (ori < 0.0);
24951         if (visible) {
24952           // Save the smallest volume.
24953           if (i == 0) {
24954             tvol = fabs(ori);
24955           } else {
24956             tvol = fabs(ori) < tvol ? fabs(ori) : tvol;
24957           }
24958         } else {
24959           // A front is invisible by tp. Stop.
24960           tvol = 0.0;
24961           break;
24962         }
24963       }
24964       if (tvol > mvol) {
24965         // Get a larger minimal volume.
24966         for (i = 0; i < 3; i++) np[i] = tp[i];
24967         mvol = tvol;
24968       } else {
24969         // Minimal volume decreases. Stop.
24970         break;
24971       }
24972       // Continue to adjust np.
24973       j++;
24974     } while (true);
24975     // Has np been adjusted?
24976     if (j > 0) break;
24977     // Try to move np to anoter direction.
24978     k++;
24979   } while (k < 2);
24980 
24981   if (b->verbose > 1) {
24982     printf("    %d adjust iterations. minvol = %.12g.\n", j, mvol);
24983   }
24984   return true;
24985 }
24986 
24988 //                                                                           //
24989 // relocatepoint()    Relocate a point into the cavity.                      //
24990 //                                                                           //
24991 // 'frontlist' contains the boundary faces of the cavity C. All fronts must  //
24992 // be visible by 'steinpt'.  Some fronts may hold by 'fake' tets (they are   //
24993 // hull faces).  Fake tets will be removed when they're finished.            //
24994 //                                                                           //
24996 
24997 void tetgenmesh::relocatepoint(point steinpt, triface* oldtet, list* frontlist,
24998   list* newtetlist, queue* flipque)
24999 {
25000   triface front, newtet, newface, neightet;
25001   face checksh;
25002   point pa, pb;
25003   REAL attrib, volume;
25004   bool bdflag;
25005   int i, j, k, l;
25006 
25007   if (b->verbose > 1) {
25008     printf("    Insert Steiner point (%.12g, %.12g, %.12g) %d.\n",
25009            steinpt[0], steinpt[1], steinpt[2], pointmark(steinpt));
25010   }
25011   // Clear the list first.
25012   newtetlist->clear();
25013 
25014   // Create the tets formed by fronts and 'steinpt'.
25015   for (i = 0; i < frontlist->len(); i++) {
25016     // Get a front f.
25017     front = * (triface *)(* frontlist)[i];
25018     // Let f face inside C. (f is a face of tet adjacent to C).
25019     adjustedgering(front, CW);
25020     if (b->verbose > 2) {
25021       printf("    Get front (%d, %d, %d).\n", pointmark(org(front)),
25022              pointmark(dest(front)), pointmark(apex(front)));
25023     }
25024     maketetrahedron(&newtet);
25025     newtetlist->append(&newtet);
25026     setorg(newtet, org(front));
25027     setdest(newtet, dest(front));
25028     setapex(newtet, apex(front));
25029     setoppo(newtet, steinpt);
25030     if (oldtet != (triface *) NULL) {
25031       for (j = 0; j < in->numberoftetrahedronattributes; j++) {
25032         attrib = elemattribute(oldtet->tet, j);
25033         setelemattribute(newtet.tet, j, attrib);
25034       }
25035       if (b->varvolume) {
25036         volume = volumebound(oldtet->tet);
25037         setvolumebound(newtet.tet, volume);
25038       }
25039     }
25040     // 'front' may be a 'fake' tet.
25041     tspivot(front, checksh);
25042     if (oppo(front) == (point) NULL) {
25043       if (checksh.sh != dummysh) {
25044         stdissolve(checksh);
25045       }
25046       // Dealloc the 'fake' tet.
25047       tetrahedrondealloc(front.tet);
25048       // This side (newtet) is a boundary face, let 'dummytet' bond to it.
25049       //   Otherwise, 'dummytet' may point to a dead tetrahedron after the
25050       //   old cavity tets are removed.
25051       dummytet[0] = encode(newtet);
25052     } else {
25053       // Bond two tetrahedra, also dissolve the old bond at 'front'.
25054       bond(newtet, front);
25055     }
25056     if (checksh.sh != dummysh) {
25057       sesymself(checksh);
25058       tsbond(newtet, checksh);
25059     }
25060     if (flipque != (queue *) NULL) {
25061       // f may be non-locally Delaunay and flipable.
25062       enqueueflipface(newtet, flipque);
25063     }
25064     // The three neighbors are open. Will be finished later.
25065   }
25066 
25067   // Connect new tets in C. All connecting faces must contain 'steinpt'.
25068   for (i = 0; i < newtetlist->len(); i++) {
25069     newtet = * (triface *)(* newtetlist)[i];
25070     newtet.ver = 0;
25071     for (j = 0; j < 3; j++) {
25072       fnext(newtet, newface);
25073       sym(newface, neightet);
25074       if (neightet.tet == dummytet) {
25075         // Find a neightet to connect it.
25076         bdflag = false;
25077         pa = org(newface);
25078         pb = dest(newface);
25079         assert(apex(newface) == steinpt);
25080         for (k = i + 1; k < newtetlist->len() && !bdflag; k++) {
25081           neightet = * (triface *)(* newtetlist)[k];
25082           neightet.ver = 0;
25083           for (l = 0; l < 3; l++) {
25084             if ((org(neightet) == pa && dest(neightet) == pb) ||
25085                 (org(neightet) == pb && dest(neightet) == pa)) {
25086               // Find the neighbor.
25087               fnextself(neightet);
25088               assert(apex(neightet) == steinpt);
25089               // Now neightet is a face same as newface, bond them.
25090               bond(newface, neightet);
25091               bdflag = true;
25092               break;
25093             }
25094             enextself(neightet);
25095           }
25096         }
25097         assert(bdflag);
25098       }
25099       enextself(newtet);
25100     }
25101     // Let the corners of newtet point to it for fast searching.
25102     pa = org(newtet);
25103     setpoint2tet(pa, encode(newtet));
25104     pa = dest(newtet);
25105     setpoint2tet(pa, encode(newtet));
25106     pa = apex(newtet);
25107     setpoint2tet(pa, encode(newtet));
25108     pa = oppo(newtet);
25109     setpoint2tet(pa, encode(newtet));
25110   }
25111 
25112   if (flipque != (queue *) NULL) {
25113     // Recover locally Delaunay faces.
25114     flip(flipque, NULL);
25115   }
25116 }
25117 
25119 //                                                                           //
25120 // findcollapseedge()    Find collapseable edge to suppress an endpoint.     //
25121 //                                                                           //
25123 
25124 bool tetgenmesh::findcollapseedge(point suppt, point *conpt, list* oldtetlist,
25125   list* ptlist)
25126 {
25127   triface front;
25128   point pt, pa, pb, pc;
25129   REAL *lenarray, ltmp, ori;
25130   bool visflag;
25131   int *idxarray, itmp;
25132   int n, i, j;
25133 
25134   if (b->verbose > 2) {
25135     printf("    Search an edge (in %d edges) for collapse %d.\n",
25136            ptlist->len(), pointmark(suppt));
25137   }
25138 
25139   // Candidate edges are p to the points of B(p) (in 'ptlist').
25140   n = ptlist->len();
25141   lenarray = new REAL[n];
25142   idxarray = new int[n];
25143   // Sort the points of B(p) by distance to p.
25144   for (i = 0; i < n; i++) {
25145     pt = * (point *)(* ptlist)[i];
25146     lenarray[i] = distance(suppt, pt);
25147     idxarray[i] = i;
25148   }
25149   // Bubble sort.
25150   for (i = 0; i < n - 1; i++) {
25151     for (j = 0; j < n - 1 - i; j++) {
25152       if (lenarray[j + 1] < lenarray[j]) {  // compare the two neighbors
25153         ltmp = lenarray[j];           // swap a[j] and a[j + 1]
25154         lenarray[j] = lenarray[j + 1];
25155         lenarray[j + 1] = ltmp;
25156         itmp = idxarray[j];           // swap a[j] and a[j + 1]
25157         idxarray[j] = idxarray[j + 1];
25158         idxarray[j + 1] = itmp;
25159       }
25160     }
25161   }
25162   // For each point q of B(p), test if the edge (p, q) can be collapseed.
25163   for (i = 0; i < n; i++) {
25164     pt = * (point *)(* ptlist)[idxarray[i]];
25165     // Is q visible by faces of B(p) not with q as a vertex.
25166     lenarray[i] = 0.0; // zero volume.
25167     visflag = true;
25168     for (j = 0; j < oldtetlist->len() && visflag; j++) {
25169       front = * (triface *)(* oldtetlist)[j];
25170       // Let f face to inside of B(p).
25171       adjustedgering(front, CCW);
25172       pa = org(front);
25173       pb = dest(front);
25174       pc = apex(front);
25175       // Is f contains q?
25176       if ((pa != pt) && (pb != pt) && (pc != pt)) {
25177         ori = orient3d(pa, pb, pc, pt);
25178         if (ori != 0.0) {
25179           if (iscoplanar(pa, pb, pc, pt, ori, b->epsilon * 1e+2)) ori = 0.0;
25180         }
25181         visflag = ori < 0.0;
25182         if (visflag) {
25183           // Visible, set the smallest volume.
25184           if (j == 0) {
25185             lenarray[i] = fabs(ori);
25186           } else {
25187             lenarray[i] = fabs(ori) < lenarray[i] ? fabs(ori) : lenarray[i];
25188           }
25189         } else {
25190           // Invisible. Do not collapse (p, q).
25191           lenarray[i] = 0.0;
25192         }
25193       }
25194     }
25195     if ((b->verbose > 2) && visflag) {
25196       printf("    Got candidate %d vol(%g).\n", pointmark(pt), lenarray[i]);
25197     }
25198   }
25199 
25200   // Select the largest non-zero volume (result in ltmp).
25201   ltmp = lenarray[0];
25202   itmp = idxarray[0];
25203   for (i = 1; i < n; i++) {
25204     if (lenarray[i] != 0.0) {
25205       if (lenarray[i] > ltmp) {
25206         ltmp = lenarray[i];
25207         itmp = idxarray[i]; // The index to find the point.
25208       }
25209     }
25210   }
25211 
25212   delete [] lenarray;
25213   delete [] idxarray;
25214 
25215   if (ltmp == 0.0) {
25216     // No edge can be collapseed.
25217     *conpt = (point) NULL;
25218     return false;
25219   } else {
25220     pt = * (point *)(* ptlist)[itmp];
25221     *conpt = pt;
25222     return true;
25223   }
25224 }
25225 
25227 //                                                                           //
25228 // collapseedge()    Remove a point by edge collapse.                        //
25229 //                                                                           //
25231 
25232 void tetgenmesh::collapseedge(point suppt, point conpt, list* oldtetlist,
25233   list* deadtetlist)
25234 {
25235   triface oldtet, deadtet;
25236   triface adjtet1, adjtet2;
25237   face adjsh;
25238   point pa, pb, pc;
25239   int i, j;
25240 
25241   if (b->verbose > 2) {
25242     printf("    Collapse edge (%d,%d).\n", pointmark(suppt), pointmark(conpt));
25243   }
25244 
25245   // Loop in B(p), replace p with np, queue dead tets, uninfect old tets.
25246   for (i = 0; i < oldtetlist->len(); i++) {
25247     oldtet = * (triface *)(* oldtetlist)[i]; // assert(infected(oldtet));
25248     uninfect(oldtet);
25249     pa = org(oldtet);
25250     pb = dest(oldtet);
25251     pc = apex(oldtet);
25252     assert(oppo(oldtet) == suppt);
25253     setoppo(oldtet, conpt);
25254     if ((pa == conpt) || (pb == conpt) || (pc == conpt)) {
25255       deadtetlist->append(&oldtet); // a collpased tet.
25256     }
25257   }
25258   // Loop in deadtetlist, glue adjacent tets of dead tets.
25259   for (i = 0; i < deadtetlist->len(); i++) {
25260     deadtet = * (triface *)(* deadtetlist)[i];
25261     // Get the adjacent tet n1 (outside B(p)).
25262     sym(deadtet, adjtet1);
25263     tspivot(deadtet, adjsh);
25264     // Find the edge in deadtet opposite to conpt.
25265     adjustedgering(deadtet, CCW);
25266     for (j = 0; j < 3; j++) {
25267       if (apex(deadtet) == conpt) break;
25268       enextself(deadtet);
25269     }
25270     assert(j < 3);
25271     // Get another adjacent tet n2.
25272     fnext(deadtet, adjtet2);
25273     symself(adjtet2);
25274     assert(adjtet2.tet != dummytet); // n2 is inside B(p).
25275     if (adjtet1.tet != dummytet) {
25276       bond(adjtet1, adjtet2); // Bond n1 <--> n2.
25277     } else {
25278       dissolve(adjtet2); // Dissolve at n2.
25279       dummytet[0] = encode(adjtet2); // Let dummytet holds n2.
25280     }
25281     if (adjsh.sh != dummysh) {
25282       tsbond(adjtet2, adjsh); // Bond s <--> n2.
25283     }
25284     // Collapse deadtet.
25285     tetrahedrondealloc(deadtet.tet);
25286   }
25287   deadtetlist->clear();
25288 }
25289 
25291 //                                                                           //
25292 // deallocfaketets()    Deleted fake tets at fronts.                         //
25293 //                                                                           //
25294 // This routine is only called when the findrelocatepoint() routine fails.   //
25295 // In other cases, the fake tets are removed automatically in carvecavity()  //
25296 // or relocatepoint().                                                       //
25297 //                                                                           //
25299 
25300 void tetgenmesh::deallocfaketets(list* frontlist)
25301 {
25302   triface front, neightet;
25303   face checksh;
25304   bool infectflag;
25305   int i;
25306 
25307   for (i = 0; i < frontlist->len(); i++) {
25308     // Get a front f.
25309     front = * (triface *)(* frontlist)[i];
25310     // Let f face inside C. (f is a face of tet adjacent to C).
25311     adjustedgering(front, CW);
25312     sym(front, neightet);
25313     tspivot(front, checksh);
25314     if (oppo(front) == (point) NULL) {
25315       if (b->verbose > 2) {
25316         printf("    Get fake tet (%d, %d, %d).\n", pointmark(org(front)),
25317                pointmark(dest(front)), pointmark(apex(front)));
25318       }
25319       if (neightet.tet != dummytet) {
25320         // The neightet may be infected. After dissolve it, the infect flag
25321         //   will be lost. Save the flag and restore it later.
25322         infectflag = infected(neightet);
25323         dissolve(neightet);
25324         if (infectflag) {
25325           infect(neightet);
25326         }
25327       }
25328       if (checksh.sh != dummysh) {
25329         infectflag = sinfected(checksh);
25330         stdissolve(checksh);
25331         if (infectflag) {
25332           sinfect(checksh);
25333         }
25334       }
25335       // Dealloc the 'fake' tet.
25336       tetrahedrondealloc(front.tet);
25337       // If 'neightet' is a hull face, let 'dummytet' bond to it. It is
25338       //   a 'dummytet' when this front was created from a new subface.
25339       //   In such case, it should not be bounded.
25340       if (neightet.tet != dummytet) {
25341         dummytet[0] = encode(neightet);
25342       }
25343     }
25344   }
25345 }
25346 
25348 //                                                                           //
25349 // restorepolyhedron()    Restore the tetrahedralization in a polyhedron.    //
25350 //                                                                           //
25351 // This routine is only called when the operation of suppressing a point is  //
25352 // aborted (eg., findrelocatepoint() routine fails). The polyhedron has been //
25353 // remeshed by new tets. This routine restore the old tets in it.            //
25354 //                                                                           //
25355 // 'oldtetlist' contains the list of old tets. Each old tet t_o assumes that //
25356 // it still connects to a tet t_b of the mesh, however, t_b does not connect //
25357 // to t_o, this routine resets the connection such that t_b <--> t_o.        //
25358 //                                                                           //
25360 
25361 void tetgenmesh::restorepolyhedron(list* oldtetlist)
25362 {
25363   triface oldtet, neightet, neineitet;
25364   face checksh;
25365   int i;
25366 
25367   for (i = 0; i < oldtetlist->len(); i++) {
25368     // Get an old tet t_o.
25369     oldtet = * (triface *)(* oldtetlist)[i];
25370     // Check the four sides of t_o.
25371     for (oldtet.loc = 0; oldtet.loc < 4; oldtet.loc++) {
25372       sym(oldtet, neightet);
25373       tspivot(oldtet, checksh);
25374       if (neightet.tet != dummytet) {
25375         sym(neightet, neineitet);
25376         if (neineitet.tet != oldtet.tet) {
25377           // This face of t_o is a boundary of P.
25378           bond(neightet, oldtet);
25379           if (checksh.sh != dummysh) {
25380             tsbond(oldtet, checksh);
25381           }
25382         }
25383       } else {
25384         // t_o has a hull face. It should be the boundary of P.
25385 #ifdef SELF_CHECK
25386         assert(checksh.sh != dummysh);
25387         stpivot(checksh, neineitet);
25388         assert(neineitet.tet != oldtet.tet);
25389 #endif
25390         tsbond(oldtet, checksh);
25391         // Let dummytet[0] points to it.
25392         dummytet[0] = encode(oldtet);
25393       }
25394     }
25395   }
25396 }
25397 
25399 //                                                                           //
25400 // suppressfacetpoint()    Suppress a point inside a facet.                  //
25401 //                                                                           //
25402 // The point p inside a facet F will be suppressed from F by either being    //
25403 // deleted from the mesh or being relocated into the volume.                 //
25404 //                                                                           //
25405 // 'supsh' is a subface f of F, and p = sapex(f); the other parameters are   //
25406 // working lists which are empty at the beginning and the end.               //
25407 //                                                                           //
25408 // 'optflag' is used for mesh optimization. If it is set, after removing p,  //
25409 // test the object function on each new tet, queue bad tets.                 //
25410 //                                                                           //
25412 
25413 bool tetgenmesh::suppressfacetpoint(face* supsh, list* frontlist,
25414   list* misfrontlist, list* ptlist, list* conlist, memorypool* viri,
25415   queue* flipque, bool noreloc, bool optflag)
25416 {
25417   list *oldtetlist[2], *newtetlist[2];
25418   list *oldshlist, *newshlist;
25419   triface oldtet, newtet;
25420   face oldsh, newsh;
25421   point suppt, newpt[2];
25422   point *cons;
25423   REAL norm[3];
25424   bool success;
25425   int shmark;
25426   int i, j;
25427 
25428   suppt = sapex(*supsh);
25429   if (b->verbose > 1) {
25430     printf("    Suppress point %d in facet.\n", pointmark(suppt));
25431   }
25432 
25433   // Initialize working lists, variables.
25434   for (i = 0; i < 2; i++) {
25435     oldtetlist[i] = (list *) NULL;
25436     newtetlist[i] = (list *) NULL;
25437     newpt[i] = (point) NULL;
25438   }
25439   oldshlist = new list(sizeof(face), NULL, 256);
25440   newshlist = new list(sizeof(face), NULL, 256);
25441   success = true; // Assume p can be suppressed.
25442 
25443   // Find subs of C(p).
25444   oldshlist->append(supsh);
25445   formstarpolygon(suppt, oldshlist, ptlist);
25446   // Get the edges of C(p). They form a closed polygon.
25447   for (i = 0; i < oldshlist->len(); i++) {
25448     oldsh = * (face *)(* oldshlist)[i];
25449     cons = (point *) conlist->append(NULL);
25450     cons[0] = sorg(oldsh);
25451     cons[1] = sdest(oldsh);
25452   }
25453   // Re-triangulate the old C(p).
25454   shmark = shellmark(*supsh);
25455   triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25456   // Get new subs of C(p), remove protected segments.
25457   retrievenewsubs(newshlist, true);
25458   // Substitute the old C(p) with the new C(p)
25459   replacepolygonsubs(oldshlist, newshlist);
25460   // Clear work lists.
25461   ptlist->clear();
25462   conlist->clear();
25463   flipque->clear();
25464   viri->restart();
25465 
25466   // B(p) (tets with p as a vertex) has been separated into two parts
25467   //   (B_0(p) and B_1(p)) by F. Process them individually.
25468   for (i = 0; i < 2 && success; i++) {
25469     if (i == 1) sesymself(*supsh);
25470     // Get a tet containing p.
25471     stpivot(*supsh, oldtet);
25472     // Is this part empty?
25473     if (oldtet.tet == dummytet) continue;
25474     // Allocate spaces for storing (old and new) B_i(p).
25475     oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25476     newtetlist[i] = new list(sizeof(triface), NULL, 256);
25477     // Form old B_i(p) in oldtetlist[i].
25478     assert(!isdead(&oldtet));
25479     oldtetlist[i]->append(&oldtet);
25480     formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25481     // Infect the tets in old B_i(p) (they're going to be delete).
25482     for (j = 0; j < oldtetlist[i]->len(); j++) {
25483       oldtet = * (triface *)(* (oldtetlist[i]))[j];
25484       infect(oldtet);
25485     }
25486     // Preparation for re-tetrahedralzing old B_i(p).
25487     orientnewsubs(newshlist, supsh, norm);
25488     // Tetrahedralize old B_i(p).
25489     success = constrainedcavity(&oldtet, newshlist, oldtetlist[i], ptlist,
25490                 frontlist, misfrontlist, newtetlist[i], flipque);
25491     // If p is not suppressed, do relocation if 'noreloc' is not set.
25492     if (!success && !noreloc) {
25493       // Try to relocate p into the old B_i(p).
25494       makepoint(&(newpt[i]));
25495       success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25496                                   oldtetlist[i]);
25497       // Initialize newpt = suppt.
25498       // for (j = 0; j < 3; j++) newpt[i][j] = suppt[j];
25499       // success = smoothvolpoint(newpt[i], frontlist, true);
25500       if (success) {
25501         // p is relocated by newpt[i]. Now insert it. Don't do flip since
25502         //   the new tets may get deleted again.
25503         relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25504         setpointtype(newpt[i], FREEVOLVERTEX);
25505         relverts++;
25506       } else {
25507         // Fail to relocate p. Clean fake tets and quit this option.
25508         deallocfaketets(frontlist);
25509         pointdealloc(newpt[i]);
25510         newpt[i] = (point) NULL;
25511         assert(newtetlist[i]->len() == 0);
25512       }
25513     }
25514     if (!success && noreloc) {
25515       // Failed and no point relocation. Clean fake tets.
25516       deallocfaketets(frontlist);
25517     }
25518     // Clear work lists.
25519     ptlist->clear();
25520     frontlist->clear();
25521     misfrontlist->clear();
25522     flipque->clear();
25523   }
25524 
25525   if (success) {
25526     // p has been removed! (Still in the pool).
25527     setpointtype(suppt, UNUSEDVERTEX);
25528     unuverts++;
25529     // Delete old C(p).
25530     for (i = 0; i < oldshlist->len(); i++) {
25531       oldsh = * (face *)(* oldshlist)[i];
25532       if (i == 0) {
25533         // Update the 'hullsize' if C(p) is on the hull.
25534         stpivot(oldsh, oldtet);
25535         if (oldtet.tet != dummytet) {
25536           sesymself(oldsh);
25537           stpivot(oldsh, oldtet);
25538         }
25539         if (oldtet.tet == dummytet) {
25540           // A boundary face. Update the 'hullsize'.
25541           j = oldshlist->len() - newshlist->len();
25542           assert(j > 0);
25543           hullsize -= j;
25544         }
25545       }
25546       shellfacedealloc(subfaces, oldsh.sh);
25547     }
25548     // Delete old B_i(p).
25549     for (i = 0; i < 2; i++) {
25550       if (oldtetlist[i] != (list *) NULL) {
25551         // Delete tets of the old B_i(p).
25552         for (j = 0; j < oldtetlist[i]->len(); j++) {
25553           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25554           assert(!isdead(&oldtet));
25555           tetrahedrondealloc(oldtet.tet);
25556         }
25557       }
25558     }
25559     if (optflag) {
25560       // Check for new bad-quality tets.
25561       for (i = 0; i < 2; i++) {
25562         if (newtetlist[i] != (list *) NULL) {
25563           for (j = 0; j < newtetlist[i]->len(); j++) {
25564             newtet = * (triface *)(* (newtetlist[i]))[j];
25565             if (!isdead(&newtet)) checktet4opt(&newtet, true);
25566           }
25567         }
25568       }
25569     }
25570   } else {
25571     // p is not suppressed. Recover the original state.
25572     unsupverts++;
25573     // Restore the old C(p).
25574     replacepolygonsubs(newshlist, oldshlist);
25575     // Delete subs of the new C(p)
25576     for (i = 0; i < newshlist->len(); i++) {
25577       newsh = * (face *)(* newshlist)[i];
25578       shellfacedealloc(subfaces, newsh.sh);
25579     }
25580     // Restore old B_i(p).
25581     for (i = 0; i < 2; i++) {
25582       if (oldtetlist[i] != (list *) NULL) {
25583         // Uninfect tets of old B_i(p).
25584         for (j = 0; j < oldtetlist[i]->len(); j++) {
25585           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25586           assert(infected(oldtet));
25587           uninfect(oldtet);
25588         }
25589         // Has it been re-meshed?
25590         if (newtetlist[i]->len() > 0) {
25591           // Restore the old B_i(p).
25592           restorepolyhedron(oldtetlist[i]);
25593           // Delete tets of the new B_i(p);
25594           for (j = 0; j < newtetlist[i]->len(); j++) {
25595             newtet = * (triface *)(* (newtetlist[i]))[j];
25596             // Some new tets may already be deleted (by carvecavity()).
25597             if (!isdead(&newtet)) {
25598               tetrahedrondealloc(newtet.tet);
25599             }
25600           }
25601         }
25602         // Dealloc newpt[i] if it exists.
25603         if (newpt[i] != (point) NULL) {
25604           pointdealloc(newpt[i]);
25605           relverts--;
25606         }
25607       }
25608     }
25609   }
25610 
25611   // Delete work lists.
25612   delete oldshlist;
25613   delete newshlist;
25614   for (i = 0; i < 2; i++) {
25615     if (oldtetlist[i] != (list *) NULL) {
25616       delete oldtetlist[i];
25617       delete newtetlist[i];
25618     }
25619   }
25620 
25621   return success;
25622 }
25623 
25625 //                                                                           //
25626 // suppresssegpoint()    Suppress a point on a segment.                      //
25627 //                                                                           //
25628 // The point p on a segment S will be suppressed from S by either being      //
25629 // deleted from the mesh or being relocated into the volume.                 //
25630 //                                                                           //
25631 // 'supseg' is the segment S, and p = sdest(S); the other parameters are     //
25632 // working lists which are empty at the beginning and the end.               //
25633 //                                                                           //
25635 
25636 bool tetgenmesh::suppresssegpoint(face* supseg, list* spinshlist,
25637   list* newsegshlist, list* frontlist, list* misfrontlist, list* ptlist,
25638   list* conlist, memorypool* viri, queue* flipque, bool noreloc, bool optflag)
25639 {
25640   list **oldtetlist, **newtetlist;
25641   list **oldshlist, **newshlist;
25642   list *pnewshlist, *dnewshlist;
25643   triface oldtet, newtet;
25644   face oldsh, newsh;
25645   face startsh, spinsh, segsh1, segsh2;
25646   face nsupseg, newseg, prevseg, nextseg;
25647   point suppt, *newpt;
25648   point pa, pb, *cons;
25649   REAL pnorm[2][3], norm[3];
25650   bool success;
25651   int shmark;
25652   int n, i, j, k;
25653 
25654   // Get the Steiner point p.
25655   assert(supseg->shver < 2);
25656   suppt = sdest(*supseg);
25657   // Find the segment ab split by p.
25658   senext(*supseg, nsupseg);
25659   spivotself(nsupseg);
25660   assert(nsupseg.sh != dummysh);
25661   nsupseg.shver = 0;
25662   if (sorg(nsupseg) != suppt) sesymself(nsupseg);
25663   assert(sorg(nsupseg) == suppt);
25664   pa = sorg(*supseg);
25665   pb = sdest(nsupseg);
25666   if (b->verbose > 1) {
25667     printf("    Remove point %d on segment (%d, %d).\n",
25668            pointmark(suppt), pointmark(pa), pointmark(pb));
25669   }
25670 
25671   // Let startsh s containing p.
25672   spivot(*supseg, startsh);
25673   spinsh = startsh;
25674   do {
25675     // Save it in list.
25676     spinshlist->append(&spinsh);
25677     // Go to the next facet.
25678     spivotself(spinsh);
25679   } while (spinsh.sh != startsh.sh);
25680   if (spinshlist->len() == 1) {
25681     // This case has not handled yet.
25682     // printf("Unhandled case: segment only belongs to one facet.\n");
25683     spinshlist->clear();
25684     unsupverts++;
25685     return false;
25686   }
25687 
25688   // Suppose ab is shared by n facets (n > 1), then there are n B(p) (tets
25689   //   with p as a vertex). Some B(p) may be empty, eg, outside.
25690   n = spinshlist->len();
25691   oldtetlist = new list*[n];
25692   newtetlist = new list*[n];
25693   oldshlist = new list*[n];
25694   newshlist = new list*[n];
25695   newpt = new point[n];
25696   for (i = 0; i < n; i++) {
25697     oldtetlist[i] = (list *) NULL;
25698     newtetlist[i] = (list *) NULL;
25699     oldshlist[i] = (list *) NULL;
25700     newshlist[i] = (list *) NULL;
25701     newpt[i] = (point) NULL;
25702   }
25703 
25704   // Create a new segment ab (result in newseg).
25705   makeshellface(subsegs, &newseg);
25706   setsorg(newseg, pa);
25707   setsdest(newseg, pb);
25708   // ab gets the same mark and segment type as ap.
25709   setshellmark(newseg, shellmark(*supseg));
25710   setshelltype(newseg, shelltype(*supseg));
25711   if (b->quality && varconstraint) {
25712     // Copy the areabound into the new subsegment.
25713     setareabound(newseg, areabound(*supseg));
25714   }
25715   // Save the old connection at a.
25716   senext2(*supseg, prevseg);
25717   spivotself(prevseg);
25718   if (prevseg.sh != dummysh) {
25719     prevseg.shver = 0;
25720     if (sdest(prevseg) != pa) sesymself(prevseg);
25721     assert(sdest(prevseg) == pa);
25722     senextself(prevseg);
25723     senext2self(newseg);
25724     sbond(newseg, prevseg);
25725     newseg.shver = 0;
25726   }
25727   // Save the old connection at b.
25728   senext(nsupseg, nextseg);
25729   spivotself(nextseg);
25730   if (nextseg.sh != dummysh) {
25731     nextseg.shver = 0;
25732     if (sorg(nextseg) != pb) sesymself(nextseg);
25733     assert(sorg(nextseg) == pb);
25734     senext2self(nextseg);
25735     senextself(newseg);
25736     sbond(newseg, nextseg);
25737     newseg.shver = 0;
25738   }
25739 
25740   // Re-triangulate C(p) (subs with p as a vertex) to remove p.
25741   for (i = 0; i < spinshlist->len(); i++) {
25742     spinsh = * (face *)(* spinshlist)[i];
25743     // Allocate spaces for C_i(p).
25744     oldshlist[i] = new list(sizeof(face), NULL, 256);
25745     newshlist[i] = new list(sizeof(face), NULL, 256);
25746     // Get the subs of C_i(p).
25747     oldshlist[i]->append(&spinsh);
25748     formstarpolygon(suppt, oldshlist[i], ptlist);
25749     // Find the edges of C_i(p). It DOES NOT form a closed polygon.
25750     for (j = 0; j < oldshlist[i]->len(); j++) {
25751       oldsh = * (face *)(* (oldshlist[i]))[j];
25752       cons = (point *) conlist->append(NULL);
25753       cons[0] = sorg(oldsh);
25754       cons[1] = sdest(oldsh);
25755     }
25756     // The C_i(p) isn't closed without ab. Add it to it.
25757     cons = (point *) conlist->append(NULL);
25758     cons[0] = pa;
25759     cons[1] = pb;
25760     // Re-triangulate C_i(p).
25761     shmark = shellmark(spinsh);
25762     triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25763     // Get new subs of C_i(p), remove protected segments.
25764     retrievenewsubs(newshlist[i], true);
25765     // Substitute old C_i(p) with the new C_i(p). !IT IS NOT COMPLETE!
25766     replacepolygonsubs(oldshlist[i], newshlist[i]);
25767     // Find the new subface s having edge ab.
25768     for (j = 0; j < newshlist[i]->len(); j++) {
25769       segsh1 = * (face *)(* (newshlist[i]))[j];
25770       for (k = 0; k < 3; k++) {
25771         if (((sorg(segsh1) == pa) && (sdest(segsh1) == pb)) ||
25772             ((sorg(segsh1) == pb) && (sdest(segsh1) == pa))) break;
25773         senextself(segsh1);
25774       }
25775       if (k < 3) break; // Found.
25776     }
25777     assert(j < newshlist[i]->len()); // ab must exist.
25778     // Bond s and ab together. The C_i(p) is completedly substituted.
25779     ssbond(segsh1, newseg);
25780     // Save s for forming the face ring of ab.
25781     newsegshlist->append(&segsh1);
25782     // Clear work lists.
25783     ptlist->clear();
25784     conlist->clear();
25785     flipque->clear();
25786     viri->restart();
25787   }
25788   // Form the face ring of ab.
25789   for (i = 0; i < newsegshlist->len(); i++) {
25790     segsh1 = * (face *)(* newsegshlist)[i];
25791     if ((i + 1) == newsegshlist->len()) {
25792       segsh2 = * (face *)(* newsegshlist)[0];
25793     } else {
25794       segsh2 = * (face *)(* newsegshlist)[i + 1];
25795     }
25796     sbond1(segsh1, segsh2);
25797   }
25798 
25799   // A work list for keeping subfaces from two facets.
25800   dnewshlist = new list(sizeof(face), NULL, 256);
25801   success = true; // Assume p is suppressable.
25802 
25803   // Suppress p in all B(p). B_i(p) is looped wrt the right-hand rule of ab.
25804   for (i = 0; i < spinshlist->len() && success; i++) {
25805     // Get an old  subface s (ap) of a facet.
25806     spinsh = * (face *)(* spinshlist)[i];
25807     // Let the edge direction of s be a->b. Hence all subfaces follow
25808     //   the right-hand rule of ab.
25809     if (sorg(spinsh) != pa) sesymself(spinsh);
25810     // Get a tet t of B_i(p).
25811     stpivot(spinsh, oldtet);
25812     // Is B_i(p) empty?
25813     if (oldtet.tet == dummytet) continue;
25814     // Allocate spaces for B_i(p).
25815     oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25816     newtetlist[i] = new list(sizeof(triface), NULL, 256);
25817     // Find all tets of old B_i(p).
25818     oldtetlist[i]->append(&oldtet);
25819     formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25820     // Infect tets of old B_i(p) (they're going to be deleted).
25821     for (j = 0; j < oldtetlist[i]->len(); j++) {
25822       oldtet = * (triface *)(* (oldtetlist[i]))[j];
25823       infect(oldtet);
25824     }
25825     // Collect new subfaces (of two facets) bounded B_i(p).
25826     for (k = 0; k < 2; k++) {
25827       if ((i + k) < spinshlist->len()) {
25828         pnewshlist = newshlist[i + k];
25829         segsh1 = * (face *)(* spinshlist)[i + k];
25830       } else {
25831         pnewshlist = newshlist[0];
25832         segsh1 = * (face *)(* spinshlist)[0];
25833       }
25834       // Adjust the orientation of segsh1 to face to the inside of C.
25835       if (k == 0) {
25836         if (sorg(segsh1) != pa) sesymself(segsh1);
25837         assert(sorg(segsh1) == pa);
25838       } else {
25839         if (sdest(segsh1) != pa) sesymself(segsh1);
25840         assert(sdest(segsh1) == pa);
25841       }
25842       // Preparation for re-tetrahedralzing old B_i(p).
25843       orientnewsubs(pnewshlist, &segsh1, pnorm[k]);
25844       for (j = 0; j < pnewshlist->len(); j++) {
25845         dnewshlist->append((face *)(* pnewshlist)[j]);
25846       }
25847     }
25848     // Tetrahedralize B_i(p).
25849     success = constrainedcavity(&oldtet, dnewshlist, oldtetlist[i], ptlist,
25850                 frontlist, misfrontlist, newtetlist[i], flipque);
25851     if (!success && !noreloc) {
25852       // C must be finished by re-locating the steiner point.
25853       makepoint(&(newpt[i]));
25854       for (j = 0; j < 3; j++) norm[j] = 0.5 * (pnorm[0][j] + pnorm[1][j]);
25855       success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25856                                   oldtetlist[i]);
25857       // for (j = 0; j < 3; j++) newpt[i][j] = suppt[j];
25858       // success = smoothvolpoint(newpt[i], frontlist, true);
25859       if (success) {
25860         // p is relocated by newpt[i]. Now insert it. Don't do flip since
25861         //   the new tets may get deleted again.
25862         relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25863         setpointtype(newpt[i], FREEVOLVERTEX);
25864         relverts++;
25865       } else {
25866         // Fail to relocate p. Clean fake tets and quit this option.
25867         deallocfaketets(frontlist);
25868         pointdealloc(newpt[i]);
25869         newpt[i] = (point) NULL;
25870         assert(newtetlist[i]->len() == 0);
25871       }
25872     }
25873     if (!success && noreloc) {
25874       // Failed and no point relocation. Clean fake tets.
25875       deallocfaketets(frontlist);
25876     }
25877     // Clear work lists.
25878     dnewshlist->clear();
25879     ptlist->clear();
25880     frontlist->clear();
25881     misfrontlist->clear();
25882     flipque->clear();
25883   }
25884 
25885   if (success) {
25886     // p has been suppressed. (Still in the pool).
25887     setpointtype(suppt, UNUSEDVERTEX);
25888     unuverts++;
25889     // Update the segmnet pointers saved in a and b.
25890     setpoint2sh(pa, sencode(newseg));
25891     setpoint2sh(pb, sencode(newseg));
25892     // Delete old segments ap, pb.
25893     shellfacedealloc(subsegs, supseg->sh);
25894     shellfacedealloc(subsegs, nsupseg.sh);
25895     // Delete subs of old C_i(p).
25896     for (i = 0; i < spinshlist->len(); i++) {
25897       for (j = 0; j < oldshlist[i]->len(); j++) {
25898         oldsh = * (face *)(* (oldshlist[i]))[j];
25899         if (j == 0) {
25900           // Update 'hullsize' if C_i(p) is on the hull.
25901           stpivot(oldsh, oldtet);
25902           if (oldtet.tet != dummytet) {
25903             sesymself(oldsh);
25904             stpivot(oldsh, oldtet);
25905           }
25906           if (oldtet.tet == dummytet) {
25907             // Update 'hullsize'.
25908             k = oldshlist[i]->len() - newshlist[i]->len();
25909             assert(k > 0);
25910             hullsize -= k;
25911           }
25912         }
25913         shellfacedealloc(subfaces, oldsh.sh);
25914       }
25915     }
25916     // Delete tets old B_i(p).
25917     for (i = 0; i < spinshlist->len(); i++) {
25918       // Delete them if it is not empty.
25919       if (oldtetlist[i] != (list *) NULL) {
25920         for (j = 0; j < oldtetlist[i]->len(); j++) {
25921           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25922           assert(!isdead(&oldtet));
25923           tetrahedrondealloc(oldtet.tet);
25924         }
25925       }
25926     }
25927     if (optflag) {
25928       for (i = 0; i < spinshlist->len(); i++) {
25929         // Check for new bad-quality tets.
25930         if (newtetlist[i] != (list *) NULL) {
25931           for (j = 0; j < newtetlist[i]->len(); j++) {
25932             newtet = * (triface *)(* (newtetlist[i]))[j];
25933             if (!isdead(&newtet)) checktet4opt(&newtet, true);
25934           }
25935         }
25936       }
25937     }
25938   } else {
25939     // p is not suppressed. Recover the original state.
25940     unsupverts++;
25941     // Restore old connection at a.
25942     senext2(*supseg, prevseg);
25943     spivotself(prevseg);
25944     if (prevseg.sh != dummysh) {
25945       prevseg.shver = 0;
25946       if (sdest(prevseg) != pa) sesymself(prevseg);
25947       assert(sdest(prevseg) == pa);
25948       senextself(prevseg);
25949       senext2self(*supseg);
25950       sbond(*supseg, prevseg);
25951       senextself(*supseg); // Restore original state.
25952       assert(supseg->shver < 2);
25953     }
25954     // Restore old connection at b.
25955     senext(nsupseg, nextseg);
25956     spivotself(nextseg);
25957     if (nextseg.sh != dummysh) {
25958       nextseg.shver = 0;
25959       if (sorg(nextseg) != pb) sesymself(nextseg);
25960       assert(sorg(nextseg) == pb);
25961       senext2self(nextseg);
25962       senextself(nsupseg);
25963       sbond(nsupseg, nextseg);
25964       // nsupseg.shver = 0;
25965       senext2self(nsupseg); // Restore original state
25966       assert(nsupseg.shver < 2);
25967     }
25968     // Delete the new segment ab.
25969     shellfacedealloc(subsegs, newseg.sh);
25970     // Restore old C_i(p).
25971     for (i = 0; i < spinshlist->len(); i++) {
25972       replacepolygonsubs(newshlist[i], oldshlist[i]);
25973       // Delete subs of the new C_i(p)
25974       for (j = 0; j < newshlist[i]->len(); j++) {
25975         newsh = * (face *)(* (newshlist[i]))[j];
25976         shellfacedealloc(subfaces, newsh.sh);
25977       }
25978     }
25979     // Restore old B_i(p).
25980     for (i = 0; i < spinshlist->len(); i++) {
25981       if (oldtetlist[i] != (list *) NULL) {
25982         // Uninfect tets of old B_i(p).
25983         for (j = 0; j < oldtetlist[i]->len(); j++) {
25984           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25985           assert(infected(oldtet));
25986           uninfect(oldtet);
25987         }
25988         // Has it been re-meshed?
25989         if (newtetlist[i]->len() > 0) {
25990           // Restore the old B_i(p).
25991           restorepolyhedron(oldtetlist[i]);
25992           // Delete tets of the new B_i(p);
25993           for (j = 0; j < newtetlist[i]->len(); j++) {
25994             newtet = * (triface *)(* (newtetlist[i]))[j];
25995             // Some new tets may already be deleted (by carvecavity()).
25996             if (!isdead(&newtet)) {
25997               tetrahedrondealloc(newtet.tet);
25998             }
25999           }
26000         }
26001         // Dealloc newpt[i] if it exists.
26002         if (newpt[i] != (point) NULL) {
26003           pointdealloc(newpt[i]);
26004           relverts--;
26005         }
26006       }
26007     }
26008   }
26009 
26010   // Delete work lists.
26011   delete dnewshlist;
26012   for (i = 0; i < spinshlist->len(); i++) {
26013     delete oldshlist[i];
26014     delete newshlist[i];
26015   }
26016   delete [] oldshlist;
26017   delete [] newshlist;
26018   for (i = 0; i < spinshlist->len(); i++) {
26019     if (oldtetlist[i] != (list *) NULL) {
26020       delete oldtetlist[i];
26021       delete newtetlist[i];
26022     }
26023   }
26024   delete [] oldtetlist;
26025   delete [] newtetlist;
26026   // Clear work lists.
26027   newsegshlist->clear();
26028   spinshlist->clear();
26029 
26030   return success;
26031 }
26032 
26034 //                                                                           //
26035 // suppressvolpoint()    Suppress a point inside mesh.                       //
26036 //                                                                           //
26037 // The point p = org(suptet) is inside the mesh and will be suppressed from  //
26038 // the mesh. Note that p may not be suppressed.                              //
26039 //                                                                           //
26040 // 'optflag' is used for mesh optimization. If it is set, after removing p,  //
26041 // test the object function on each new tet, queue bad tets.                 //
26042 //                                                                           //
26044 
26045 bool tetgenmesh::suppressvolpoint(triface* suptet, list* frontlist,
26046   list* misfrontlist, list* ptlist, queue* flipque, bool optflag)
26047 {
26048   list *myfrontlist, *mymisfrontlist, *myptlist;
26049   list *oldtetlist, *newtetlist;
26050   list *newshlist; // a dummy list.
26051   queue *myflipque;
26052   triface oldtet, newtet;
26053   point suppt, conpt;
26054   bool success;
26055   int j;
26056 
26057   // Allocate spaces for storing (old and new) B(p).
26058   oldtetlist = new list(sizeof(triface), NULL, 256);
26059   newtetlist = new list(sizeof(triface), NULL, 256);
26060   newshlist = new list(sizeof(face), NULL, 256);
26061   // Allocate work lists if user doesn't supply them.
26062   myfrontlist = mymisfrontlist = myptlist = (list *) NULL;
26063   myflipque = (queue *) NULL;
26064   if (frontlist == (list *) NULL) {
26065     myfrontlist = new list(sizeof(triface), NULL, 256);
26066     frontlist = myfrontlist;
26067     mymisfrontlist = new list(sizeof(triface), NULL, 256);
26068     misfrontlist = mymisfrontlist;
26069     myptlist = new list(sizeof(point *), NULL, 256);
26070     ptlist = myptlist;
26071     myflipque = new queue(sizeof(badface));
26072     flipque = myflipque;
26073   }
26074 
26075   suppt = org(*suptet);
26076   oldtet = *suptet;
26077   success = true; // Assume p can be suppressed.
26078 
26079   if (b->verbose > 1) {
26080     printf("    Remove point %d in mesh.\n", pointmark(suppt));
26081   }
26082 
26083   // Form old B(p) in oldtetlist.
26084   oldtetlist->append(&oldtet);
26085   formstarpolyhedron(suppt, oldtetlist, ptlist, false);
26086   // Infect the tets in old B(p) (they're going to be delete).
26087   for (j = 0; j < oldtetlist->len(); j++) {
26088     oldtet = * (triface *)(* oldtetlist)[j];
26089     infect(oldtet);
26090   }
26091   // Tetrahedralize old B(p).
26092   success = constrainedcavity(&oldtet, newshlist, oldtetlist, ptlist,
26093               frontlist, misfrontlist, newtetlist, flipque);
26094   if (!success) {
26095     // Unable to suppress p.
26096     deallocfaketets(frontlist);
26097     // Try to collapse an edge at p.
26098     conpt = (point) NULL;
26099     assert(newtetlist->len() == 0);
26100     if (findcollapseedge(suppt, &conpt, oldtetlist, ptlist)) {
26101       // Collapse the edge suppt->conpt. Re-use newtetlist.
26102       collapseedge(suppt, conpt, oldtetlist, newtetlist);
26103       // The oldtetlist contains newtetlist.
26104       if (optflag) {
26105         assert(newtetlist->len() == 0);
26106         for (j = 0; j < oldtetlist->len(); j++) {
26107           newtet = * (triface *)(* oldtetlist)[j];
26108           newtetlist->append(&newtet);
26109         }
26110       }
26111       oldtetlist->clear(); // Do not delete them.
26112       collapverts++;
26113       success = true;
26114     }
26115   }
26116   if (success) {
26117     // p has been removed! (Still in the pool).
26118     setpointtype(suppt, UNUSEDVERTEX);
26119     unuverts++;
26120     suprelverts++;
26121     // Delete old B(p).
26122     for (j = 0; j < oldtetlist->len(); j++) {
26123       oldtet = * (triface *)(* oldtetlist)[j];
26124       assert(!isdead(&oldtet));
26125       tetrahedrondealloc(oldtet.tet);
26126     }
26127     if (optflag) {
26128       // Check for new bad tets.
26129       for (j = 0; j < newtetlist->len(); j++) {
26130         newtet = * (triface *)(* newtetlist)[j];
26131         if (!isdead(&newtet)) checktet4opt(&newtet, true);
26132       }
26133     }
26134   } else {
26135     // p is not suppressed. Recover the original state.
26136     // Uninfect tets of old B(p).
26137     for (j = 0; j < oldtetlist->len(); j++) {
26138       oldtet = * (triface *)(* oldtetlist)[j];
26139       assert(infected(oldtet));
26140       uninfect(oldtet);
26141     }
26142   }
26143 
26144   // Clear work lists.
26145   ptlist->clear();
26146   frontlist->clear();
26147   misfrontlist->clear();
26148   flipque->clear();
26149   // Deallocate work lists.
26150   if (myfrontlist != (list *) NULL) {
26151     delete myfrontlist;
26152     delete mymisfrontlist;
26153     delete myptlist;
26154     delete myflipque;
26155   }
26156   delete oldtetlist;
26157   delete newtetlist;
26158   delete newshlist;
26159 
26160   return success;
26161 }
26162 
26164 //                                                                           //
26165 // smoothpoint()    Smooth a volume/segment point.                           //
26166 //                                                                           //
26167 // 'smthpt' (p) is inside the polyhedron (C) bounded by faces in 'starlist'. //
26168 // This routine moves p inside C until an object function is maximized.      //
26169 //                                                                           //
26170 // Default, the CCW edge ring of the faces on C points to p. If 'invtori' is //
26171 // TRUE, the orientation is inversed.                                        //
26172 //                                                                           //
26173 // If 'key' != NULL, it contains an object value to be improved. Current it  //
26174 // means the cosine of the largest dihedral angle. In such case, the point   //
26175 // is smoothed only if the final configuration improves the object value, it //
26176 // is returned by the 'key'.                                                 //
26177 //                                                                           //
26179 
26180 bool tetgenmesh::smoothpoint(point smthpt, point e1, point e2, list *starlist,
26181   bool invtori, REAL *key)
26182 {
26183   triface starttet;
26184   point pa, pb, pc;
26185   REAL fcent[3], startpt[3], nextpt[3], bestpt[3];
26186   REAL iniTmax, oldTmax, newTmax;
26187   REAL ori, aspT, aspTmax, imprate;
26188   REAL cosd, maxcosd;
26189   bool segflag, randflag; //, subflag;
26190   int numdirs;
26191   int iter, i, j;
26192 
26193   // Is p a segment vertex?
26194   segflag = (e1 != (point) NULL);
26195   // Decide the number of moving directions.
26196   numdirs = segflag ? 2 : starlist->len();
26197   randflag = numdirs > 10;
26198   if (randflag) {
26199     numdirs = 10; // Maximum 10 directions.
26200   }
26201 
26202   aspTmax = 0.0;
26203   // Calculate the initial object value (the largest aspect ratio).
26204   for (i = 0; i < starlist->len(); i++) {
26205     starttet = * (triface *)(* starlist)[i];
26206     adjustedgering(starttet, !invtori ? CCW : CW);
26207     pa = org(starttet);
26208     pb = dest(starttet);
26209     pc = apex(starttet);
26210     aspT = tetaspectratio(pa, pb, pc, smthpt);
26211     if (i == 0) {
26212       aspTmax = aspT;
26213     } else {
26214       aspTmax = aspT > aspTmax ? aspT : aspTmax;
26215     }
26216   }
26217   iniTmax = aspTmax;
26218 
26219   if (b->verbose > 1) {
26220     printf("    Smooth %s point %d (%g, %g, %g).\n", segflag ? "seg" : "vol",
26221            pointmark(smthpt), smthpt[0], smthpt[1], smthpt[2]);
26222     printf("    Initial max L/h = %g.\n", iniTmax);
26223   }
26224   for (i = 0; i < 3; i++) {
26225     bestpt[i] = startpt[i] = smthpt[i];
26226   }
26227 
26228   // Do iteration until the new aspTmax does not decrease.
26229   newTmax = iniTmax;
26230   iter = 0;
26231   while (true) {
26232     // Find the best next location.
26233     oldTmax = newTmax;
26234     for (i = 0; i < numdirs; i++) {
26235       // Calculate the moved point (saved in 'nextpt').
26236       if (!segflag) {
26237         if (randflag) {
26238           // Randomly pick a direction.
26239           j = (int) randomnation(starlist->len());
26240         } else {
26241           j = i;
26242         }
26243         starttet = * (triface *)(* starlist)[j];
26244         adjustedgering(starttet, !invtori ? CCW : CW);
26245         pa = org(starttet);
26246         pb = dest(starttet);
26247         pc = apex(starttet);
26248         for (j = 0; j < 3; j++) {
26249           fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0;
26250         }
26251       } else {
26252         for (j = 0; j < 3; j++) {
26253           fcent[j] = (i == 0 ? e1[j] : e2[j]);
26254         }
26255       }
26256       for (j = 0; j < 3; j++) {
26257         nextpt[j] = startpt[j] + 0.01 * (fcent[j] - startpt[j]);
26258       }
26259       // Get the largest object value for the new location.
26260       for (j = 0; j < starlist->len(); j++) {
26261         starttet = * (triface *)(* starlist)[j];
26262         adjustedgering(starttet, !invtori ? CCW : CW);
26263         pa = org(starttet);
26264         pb = dest(starttet);
26265         pc = apex(starttet);
26266         ori = orient3d(pa, pb, pc, nextpt);
26267         if (ori < 0.0) {
26268           aspT = tetaspectratio(pa, pb, pc, nextpt);
26269           if (j == 0) {
26270             aspTmax = aspT;
26271           } else {
26272             aspTmax = aspT > aspTmax ? aspT : aspTmax;
26273           }
26274         } else {
26275           // An invalid new tet. Discard this point.
26276           aspTmax = newTmax;
26277         } // if (ori < 0.0)
26278         // Stop looping when the object value is bigger than before.
26279         if (aspTmax >= newTmax) break;
26280       } // for (j = 0; j < starlist->len(); j++)
26281       if (aspTmax < newTmax) {
26282         // Save the improved object value and the location.
26283         newTmax = aspTmax;
26284         for (j = 0; j < 3; j++) bestpt[j] = nextpt[j];
26285       }
26286     } // for (i = 0; i < starlist->len(); i++)
26287     // Does the object value improved much?
26288     imprate = fabs(oldTmax - newTmax) / oldTmax;
26289     if (imprate < 1e-3) break;
26290     // Yes, move p to the new location and continue.
26291     for (j = 0; j < 3; j++) startpt[j] = bestpt[j];
26292     iter++;
26293   } // while (true)
26294 
26295   if (iter > 0) {
26296     // The point is moved.
26297     if (key) {
26298       // Check if the quality is improved by the smoothed point.
26299       maxcosd = 0.0; // = cos(90.0).
26300       for (j = 0; j < starlist->len(); j++) {
26301         starttet = * (triface *)(* starlist)[j];
26302         adjustedgering(starttet, !invtori ? CCW : CW);
26303         pa = org(starttet);
26304         pb = dest(starttet);
26305         pc = apex(starttet);
26306         tetalldihedral(pa, pb, pc, startpt, NULL, &cosd, NULL);
26307         if (cosd < *key) {
26308           // This quality will not be improved. Stop.
26309           iter = 0; break;
26310         } else {
26311           // Remeber the worst quality value (of the new configuration).
26312           maxcosd = maxcosd < cosd ? maxcosd : cosd;
26313         }
26314       }
26315       if (iter > 0) *key = maxcosd;
26316     }
26317   }
26318 
26319   if (iter > 0) {
26320     segflag ? smoothsegverts++ : smoothvolverts++;
26321     for (i = 0; i < 3; i++) smthpt[i] = startpt[i];
26322     if (b->verbose > 1) {
26323       printf("    Move to new location (%g, %g, %g).\n", smthpt[0], smthpt[1],
26324              smthpt[2]);
26325       printf("    Final max L/h = %g. (%d iterations)\n", newTmax, iter);
26326       if (key) {
26327         printf("    Max. dihed = %g (degree).\n", acos(*key) / PI * 180.0);
26328       }
26329     }
26330     return true;
26331   } else {
26332     if (b->verbose > 1) {
26333       printf("    Not smoothed.\n");
26334     }
26335     return false;
26336   }
26337 }
26338 
26340 //                                                                           //
26341 // removesteiners()    Delete or relocate Steiner points on facets.          //
26342 //                                                                           //
26344 
26345 void tetgenmesh::removesteiners(bool coarseflag)
26346 {
26347   list *frontlist, *misfrontlist;
26348   list *spinshlist, *newsegshlist;
26349   list *ptlist, *conlist;
26350   memorypool *viri;
26351   queue *flipque;
26352   triface checktet;
26353   face shloop;
26354   face segloop, nextseg;
26355   point pa, neipt;
26356   REAL len;
26357   bool remflag;
26358   int *worklist;
26359   int oldnum, rmstein;
26360   int i, j;
26361 
26362   if (!b->quiet) {
26363     if (!coarseflag) {
26364       printf("Removing Steiner points.\n");
26365     } else {
26366       printf("Coarsening mesh.\n");
26367     }
26368   }
26369 
26370   // Initialize work lists.
26371   frontlist = new list(sizeof(triface), NULL);
26372   misfrontlist = new list(sizeof(triface), NULL);
26373   spinshlist = new list(sizeof(face), NULL);
26374   newsegshlist = new list(sizeof(face), NULL);
26375   ptlist = new list(sizeof(point *), NULL);
26376   conlist = new list(sizeof(point *) * 2, NULL);
26377   flipque = new queue(sizeof(badface));
26378   viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
26379   oldnum = unuverts;
26380   relverts = suprelverts = collapverts = unsupverts;
26381   smoothvolverts = 0;
26382   expcavcount = 0;
26383 
26384   // Suppress Steiner points inside facets.
26385   do {
26386     rmstein = unuverts;
26387     subfaces->traversalinit();
26388     shloop.sh = shellfacetraverse(subfaces);
26389     while (shloop.sh != (shellface *) NULL) {
26390       remflag = false;
26391       // Is s contains a Steiner point?
26392       shloop.shver = 0;
26393       for (i = 0; i < 3; i++) {
26394         pa = sapex(shloop);
26395         if (pointtype(pa) == FREESUBVERTEX) {
26396           if (!coarseflag) {
26397             // Remove it if it is not an input point.
26398             j = pointmark(pa) - in->firstnumber;
26399             if (j >= in->numberofpoints) {
26400               if (b->nobisect == 1) {
26401                 // '-Y'. Remove p if s is a hull face.
26402                 stpivot(shloop, checktet);
26403                 if (checktet.tet != dummytet) {
26404                   sesymself(shloop);
26405                   stpivot(shloop, checktet);
26406                 }
26407                 remflag = (checktet.tet == dummytet);
26408               } else {
26409                 // '-YY'. Remove p whatever s is a hull face or not.
26410                 remflag = true;
26411               }
26412             }
26413           } else {
26414             // Check if this vertex can be coarsed.
26415             if (b->nobisect == 0) {
26416               // Is a background mesh available?
26417               if (b->metric) {
26418                 // assert(pa[pointmtrindex] > 0.0);
26419                 // Form the star of pa.
26420                 spinshlist->append(&shloop);
26421                 formstarpolygon(pa, spinshlist, ptlist);
26422                 len = 0.0;
26423                 for (j = 0; j < ptlist->len(); j++) {
26424                   neipt = * (point *)(* ptlist)[j];
26425                   len += distance(pa, neipt);
26426                 }
26427                 len /= ptlist->len();
26428                 // Carse it if the average edge length is small.
26429                 remflag = len < pa[pointmtrindex];
26430                 spinshlist->clear();
26431                 ptlist->clear();
26432               } else {
26433                 // Coarse it if (1) it is an input point and its pointmarker
26434                 //   is zero, or (2) it is a Steiner point.
26435                 remflag = true;
26436                 j = pointmark(pa) - in->firstnumber;
26437                 if (j < in->numberofpoints) {
26438                   remflag = (in->pointmarkerlist[j] == 0);
26439                 }
26440               } // if (b->metric)
26441             } // if (b->nobisect == 0)
26442           } // if (!coarseflag)
26443           if (remflag) break;
26444         } // if (pointtype(pa) == FREESUBVERTEX)
26445         senextself(shloop);
26446       } // for (i = 0; i < 3; i++)
26447       if (remflag) {
26448         suppressfacetpoint(&shloop, frontlist, misfrontlist, ptlist, conlist,
26449                            viri, flipque, coarseflag, false);
26450       }
26451       shloop.sh = shellfacetraverse(subfaces);
26452     }
26453     // Continue if any Steiner point has been removed.
26454   } while (unuverts > rmstein);
26455 
26456   if (coarseflag) {
26457     shellface **segsperverlist;
26458     int *idx2seglist;
26459     face seg1, seg2;
26460     point e1, e2;
26461     // Connecting collinear segments. Hence the segment vertices may be
26462     //   removed. In fact, this should be done by reconstructmesh().
26463     makesegmentmap(idx2seglist, segsperverlist);
26464     subsegs->traversalinit();
26465     segloop.sh = shellfacetraverse(subsegs);
26466     while (segloop.sh != (shellface *) NULL) {
26467       for (i = 0; i < 2; i++) {
26468         segloop.shver = i;
26469         senext(segloop, nextseg);
26470         spivotself(nextseg);
26471         if ((nextseg.sh == dummysh) || (nextseg.sh > segloop.sh)) {
26472           // No neighbor segment connection or haven't been processed yet.
26473           pa = sdest(segloop);
26474           j = pointmark(pa) - in->firstnumber;
26475           if (idx2seglist[j + 1] - idx2seglist[j] == 2) {
26476             // pa is shared by only two segments. Get the other one.
26477             nextseg.sh = segsperverlist[idx2seglist[j]];
26478             if (nextseg.sh == segloop.sh) {
26479               nextseg.sh = segsperverlist[idx2seglist[j] + 1];
26480             }
26481             nextseg.shver = 0;
26482             if (sorg(nextseg) != pa) sesymself(nextseg);
26483             // Check if the two segments are collinear.
26484             e1 = sorg(segloop);
26485             e2 = sdest(nextseg);
26486             if (iscollinear(e1, pa, e2, b->epsilon)) {
26487               // Connect the two segments together.
26488               if (b->verbose > 1) {
26489                 printf("  Glue two insegs (%d, %d) at %d.\n", pointmark(e1),
26490                        pointmark(e2), pointmark(pa));
26491               }
26492               senext(segloop, seg1);
26493               senext2(nextseg, seg2);
26494               sbond(seg1, seg2);
26495             }
26496           }
26497         } // if (nextseg.sh == dummysh)
26498       } // for (i = 0;
26499       segloop.sh = shellfacetraverse(subsegs);
26500     }
26501     delete [] segsperverlist;
26502     delete [] idx2seglist;
26503   }
26504 
26505   // Suppress Steiner points on segments.
26506   do {
26507     rmstein = unuverts;
26508     subsegs->traversalinit();
26509     segloop.sh = shellfacetraverse(subsegs);
26510     while (segloop.sh != (shellface *) NULL) {
26511       remflag = false;
26512       // for (i = 0; i < 2; i++) {
26513         // Don't check the poinytype of pa, it may be a Steiner point but
26514         //   has type NACUTEVERTEX due to splitting a type-3 segment.
26515         segloop.shver = 0; // segloop.shver = i;
26516         senext(segloop, nextseg);
26517         spivotself(nextseg);
26518         if (nextseg.sh != dummysh) {
26519           pa = sdest(segloop); // p is going to be checked for removal.
26520           nextseg.shver = 0;
26521           if (sorg(nextseg) != pa) sesymself(nextseg);
26522           assert(sorg(nextseg) == pa);
26523           if (!coarseflag) {
26524             // try to remove it if it is not an input point.
26525             j = pointmark(pa) - in->firstnumber;
26526             if (j >= in->numberofpoints) {
26527               if (b->nobisect == 1) {
26528                 // '-Y'. Remove p if it is on the hull.
26529                 sstpivot(&segloop, &checktet);
26530                 assert(checktet.tet != dummytet);
26531                 pa = apex(checktet);
26532                 do {
26533                   if (!fnextself(checktet)) {
26534                     // Meet a boundary face - p is on the hull.
26535                     remflag = true; break;
26536                   }
26537                 } while (pa != apex(checktet));
26538               } else {
26539                 // '-YY'. Remove p whatever it is on the hull or not.
26540                 remflag = true;
26541               }
26542             }
26543           } else {
26544             // Check if this vertex can be coarsed.
26545             if (b->nobisect == 0) {
26546               if (b->metric) {
26547                 // assert(pa[pointmtrindex] > 0.0);
26548                 len = 0.0;
26549                 neipt = sorg(segloop);
26550                 for (j = 0; j < 2; j++) {
26551                   len += distance(pa, neipt);
26552                   /*// Is neipt inside the sparse ball of pa?
26553                   if (len < pa[pointmtrindex]) {
26554                     // Yes, the local of pa is too dense, corse it.
26555                     remflag = true; break;
26556                   } */
26557                   neipt = sdest(nextseg);
26558                 }
26559                 len /= 2.0;
26560                 // Carse it if the average edge lengh is small.
26561                 remflag = len < pa[pointmtrindex];
26562               } else {
26563                 // Coarse it if (1) it is an input point and its pointmarker
26564                 //   is zero, or (2) it is a Steiner point.
26565                 remflag = true;
26566                 j = pointmark(pa) - in->firstnumber;
26567                 if (j < in->numberofpoints) {
26568                   remflag = (in->pointmarkerlist[j] == 0);
26569                 }
26570               } // if (b->metric)
26571             } // if (b->nobisect == 0)
26572           } // if (!coarseflag)
26573         } // if (nextseg.sh != dummysh)
26574         // if (remflag) break;
26575       // } // for (i = 0; i < 2; i++)
26576       if (remflag) {
26577         suppresssegpoint(&segloop, spinshlist, newsegshlist, frontlist,
26578           misfrontlist, ptlist, conlist, viri, flipque, coarseflag, false);
26579       }
26580       segloop.sh = shellfacetraverse(subsegs);
26581     }
26582     // Continue if any Steiner point has been removed.
26583   } while (unuverts > rmstein);
26584 
26585   if ((relverts > 0) || coarseflag) {
26586     worklist = new int[points->items + 1];
26587     // Suppress relocated points & coarse free mesh points.
26588     do {
26589       // Initialize the work list. Each entry of the list counts how many
26590       //   times the point has been processed.
26591       for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26592       rmstein = unuverts;
26593       tetrahedrons->traversalinit();
26594       checktet.tet = tetrahedrontraverse();
26595       while (checktet.tet != (tetrahedron *) NULL) {
26596         remflag = false;
26597         for (i = 0; i < 4; i++) {
26598           pa = (point) checktet.tet[4 + i];
26599           if (pointtype(pa) == FREEVOLVERTEX) {
26600             // NOTE. Chenge the number 3 will change the number n of removed
26601             //   Steiner points. In my test, n is larger when it is 1. 3
26602             //   reduces n in a reasonable way (see example, mech_part,
26603             //   thepart), 5 results a larger n than 3 does. While the best
26604             //   result is no limit of this number, but it makes the code
26605             //   extremely slow.
26606             if (worklist[pointmark(pa)] < 3) {
26607               worklist[pointmark(pa)]++;
26608               if (!coarseflag) {
26609                 // Remove p if it is a Steiner point.
26610                 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26611                   remflag = true;
26612                 }
26613               } else {
26614                 if (b->metric) {
26615                   // assert(pa[pointmtrindex] > 0.0);
26616                   // Form the star of pa.
26617                   frontlist->append(&checktet);
26618                   formstarpolyhedron(pa, frontlist, ptlist, true);
26619                   len = 0.0;
26620                   for (j = 0; j < ptlist->len(); j++) {
26621                     neipt = * (point *)(* ptlist)[j];
26622                     len += distance(pa, neipt);
26623                   }
26624                   len /= ptlist->len();
26625                   // Carse it if the average edge length is small.
26626                   remflag = len < pa[pointmtrindex];
26627                   frontlist->clear();
26628                   ptlist->clear();
26629                 } else {
26630                   // Coarse it if (1) it is an input point and its pointmarker
26631                   //   is zero, or (2) it is a Steiner point.
26632                   remflag = true;
26633                   j = pointmark(pa) - in->firstnumber;
26634                   if (j < in->numberofpoints) {
26635                     remflag = (in->pointmarkerlist[j] == 0);
26636                   }
26637                 } // if (b->metric)
26638               } // if (!coarseflag)
26639               if (remflag) break;
26640             } // if (worklist[pointmark(pa)] == 0)
26641           } // if (pointtype(pa) == FREEVOLVERTEX)
26642         } // for (i = 0; i < 4; i++)
26643         if (remflag) {
26644           findorg(&checktet, pa);
26645           assert(org(checktet) == pa);
26646           suppressvolpoint(&checktet, frontlist, misfrontlist, ptlist, flipque,
26647                            false);
26648         }
26649         checktet.tet = tetrahedrontraverse();
26650       }
26651       // Continue if any relocated point has been suppressed.
26652     } while (unuverts > rmstein);
26653 
26654 
26655     // Smooth the unsuppressed points if it is not coarse mesh.
26656     if (!coarseflag && (relverts > suprelverts)) {
26657       if (b->verbose) {
26658         printf("  Smoothing relocated points.\n");
26659       }
26660       for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26661       tetrahedrons->traversalinit();
26662       checktet.tet = tetrahedrontraverse();
26663       while (checktet.tet != (tetrahedron *) NULL) {
26664         for (i = 0; i < 4; i++) {
26665           pa = (point) checktet.tet[4 + i];
26666           if (pointtype(pa) == FREEVOLVERTEX) {
26667             if (worklist[pointmark(pa)] == 0) {
26668               worklist[pointmark(pa)] = 1;
26669               if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26670                 // Smooth pa.
26671                 findorg(&checktet, pa);
26672                 frontlist->append(&checktet);
26673                 formstarpolyhedron(pa, frontlist, NULL, false);
26674                 smoothpoint(pa, NULL, NULL, frontlist, false, NULL);
26675                 frontlist->clear();
26676               }
26677             } // if (worklist[pointmark(pa)] == 0)
26678           } // if (pointtype(pa) == FREEVOLVERTEX)
26679         } // for (i = 0; i < 4; i++)
26680         checktet.tet = tetrahedrontraverse();
26681       }
26682     }
26683     delete [] worklist;
26684   }
26685 
26686   if (b->verbose > 0) {
26687     if (!coarseflag) {
26688       printf("  %d points removed from boundary", unuverts - oldnum);
26689       if (expcavcount > 0) {
26690         printf(" (%d cavity corrections)", expcavcount);
26691       }
26692       printf("\n");
26693       if (relverts > 0) {
26694         printf("  %d points relocated (%d suppressed, %d collapsed).\n",
26695                relverts, suprelverts - collapverts, collapverts);
26696         if (smoothvolverts > 0) {
26697           printf("  %d points are smoothed.\n", smoothvolverts);
26698         }
26699       }
26700       if (unsupverts > 0) {
26701         printf("  !! %d points are unsuppressed.\n", unsupverts);
26702       }
26703     } else {
26704       printf("  %d points are removed.\n", unuverts - oldnum);
26705     }
26706   }
26707 
26708   // Delete work lists.
26709   delete frontlist;
26710   delete misfrontlist;
26711   delete spinshlist;
26712   delete newsegshlist;
26713   delete ptlist;
26714   delete conlist;
26715   delete flipque;
26716   delete viri;
26717 }
26718 
26719 //
26720 // End of boundary Steiner points removing routines
26721 //
26722 
26724 //                                                                           //
26725 // reconstructmesh()    Reconstruct a tetrahedral mesh from a list of        //
26726 //                      tetrahedra and possibly a list of boundary faces.    //
26727 //                                                                           //
26728 // The list of tetrahedra is stored in 'in->tetrahedronlist',  the list of   //
26729 // boundary faces is stored in 'in->trifacelist'.  The tetrahedral mesh is   //
26730 // reconstructed in memorypool 'tetrahedrons', its boundary faces (subfaces) //
26731 // are reconstructed in 'subfaces', its boundary edges (subsegments) are     //
26732 // reconstructed in 'subsegs'. If the -a switch is used, this procedure will //
26733 // also read a list of REALs from 'in->tetrahedronvolumelist' and set a      //
26734 // maximum volume constraint on each tetrahedron.                            //
26735 //                                                                           //
26736 // If the user has provided the boundary faces in 'in->trifacelist', they    //
26737 // will be inserted the mesh. Otherwise subfaces will be identified from the //
26738 // mesh.  All hull faces (including faces of the internal holes) will be     //
26739 // recognized as subfaces, internal faces between two tetrahedra which have  //
26740 // different attributes will also be recognized as subfaces.                 //
26741 //                                                                           //
26742 // Subsegments will be identified after subfaces are reconstructed. Edges at //
26743 // the intersections of non-coplanar subfaces are recognized as subsegments. //
26744 // Edges between two coplanar subfaces with different boundary markers are   //
26745 // also recognized as subsegments.                                           //
26746 //                                                                           //
26747 // The facet index of each subface will be set automatically after we have   //
26748 // recovered subfaces and subsegments.  That is, the set of subfaces, which  //
26749 // are coplanar and have the same boundary marker will be recognized as a    //
26750 // facet and has a unique index, stored as the facet marker in each subface  //
26751 // of the set, the real boundary marker of each subface will be found in     //
26752 // 'in->facetmarkerlist' by the index.  Facet index will be used in Delaunay //
26753 // refinement for detecting two incident facets.                             //
26754 //                                                                           //
26755 // Points which are not corners of tetrahedra will be inserted into the mesh.//
26756 // Return the number of faces on the hull after the reconstruction.          //
26757 //                                                                           //
26759 
26760 long tetgenmesh::reconstructmesh()
26761 {
26762   tetrahedron **tetsperverlist;
26763   shellface **facesperverlist;
26764   triface tetloop, neightet, neineightet, spintet;
26765   face subloop, neighsh, neineighsh, subseg;
26766   face sface1, sface2;
26767   point *idx2verlist;
26768   point torg, tdest, tapex, toppo;
26769   point norg, ndest, napex;
26770   list *neighshlist, *markerlist;
26771   REAL sign, attrib, volume;
26772   REAL da1, da2;
26773   bool bondflag, insertsegflag;
26774   int *idx2tetlist;
26775   int *idx2facelist;
26776   int *worklist;
26777   int facetidx, marker;
26778   int iorg, idest, iapex, ioppo;
26779   int inorg, indest, inapex;
26780   int index, i, j;
26781 
26782   if (!b->quiet) {
26783     printf("Reconstructing mesh.\n");
26784   }
26785 
26786   // Create a map from index to points.
26787   makeindex2pointmap(idx2verlist);
26788 
26789   // Create the tetrahedra.
26790   for (i = 0; i < in->numberoftetrahedra; i++) {
26791     // Create a new tetrahedron and set its four corners, make sure that
26792     //   four corners form a positive orientation.
26793     maketetrahedron(&tetloop);
26794     index = i * in->numberofcorners;
26795     // Although there may be 10 nodes, we only read the first 4.
26796     iorg = in->tetrahedronlist[index] - in->firstnumber;
26797     idest = in->tetrahedronlist[index + 1] - in->firstnumber;
26798     iapex = in->tetrahedronlist[index + 2] - in->firstnumber;
26799     ioppo = in->tetrahedronlist[index + 3] - in->firstnumber;
26800     torg = idx2verlist[iorg];
26801     tdest = idx2verlist[idest];
26802     tapex = idx2verlist[iapex];
26803     toppo = idx2verlist[ioppo];
26804     sign = orient3d(torg, tdest, tapex, toppo);
26805     if (sign > 0.0) {
26806       norg = torg; torg = tdest; tdest = norg;
26807     } else if (sign == 0.0) {
26808       if (!b->quiet) {
26809         printf("Warning:  Tet %d is degenerate.\n", i + in->firstnumber);
26810       }
26811     }
26812     setorg(tetloop, torg);
26813     setdest(tetloop, tdest);
26814     setapex(tetloop, tapex);
26815     setoppo(tetloop, toppo);
26816     // Temporarily set the vertices be type FREEVOLVERTEX, to indicate that
26817     //   they belong to the mesh.  These types may be changed later.
26818     setpointtype(torg, FREEVOLVERTEX);
26819     setpointtype(tdest, FREEVOLVERTEX);
26820     setpointtype(tapex, FREEVOLVERTEX);
26821     setpointtype(toppo, FREEVOLVERTEX);
26822     // Set element attributes if they exist.
26823     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
26824       index = i * in->numberoftetrahedronattributes;
26825       attrib = in->tetrahedronattributelist[index + j];
26826       setelemattribute(tetloop.tet, j, attrib);
26827     }
26828     // If -a switch is used (with no number follows) Set a volume
26829     //   constraint if it exists.
26830     if (b->varvolume) {
26831       if (in->tetrahedronvolumelist != (REAL *) NULL) {
26832         volume = in->tetrahedronvolumelist[i];
26833       } else {
26834         volume = -1.0;
26835       }
26836       setvolumebound(tetloop.tet, volume);
26837     }
26838   }
26839 
26840   // Set the connection between tetrahedra.
26841   hullsize = 0l;
26842   // Create a map from nodes to tetrahedra.
26843   maketetrahedronmap(idx2tetlist, tetsperverlist);
26844   // Initialize the worklist.
26845   worklist = new int[points->items];
26846   for (i = 0; i < points->items; i++) worklist[i] = 0;
26847 
26848   // Loop all tetrahedra, bond two tetrahedra if they share a common face.
26849   tetrahedrons->traversalinit();
26850   tetloop.tet = tetrahedrontraverse();
26851   while (tetloop.tet != (tetrahedron *) NULL) {
26852     // Loop the four sides of the tetrahedron.
26853     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26854       sym(tetloop, neightet);
26855       if (neightet.tet != dummytet) continue; // This side has finished.
26856       torg = org(tetloop);
26857       tdest = dest(tetloop);
26858       tapex = apex(tetloop);
26859       iorg = pointmark(torg) - in->firstnumber;
26860       idest = pointmark(tdest) - in->firstnumber;
26861       iapex = pointmark(tapex) - in->firstnumber;
26862       worklist[iorg] = 1;
26863       worklist[idest] = 1;
26864       worklist[iapex] = 1;
26865       bondflag = false;
26866       // Search its neighbor in the adjacent tets of torg.
26867       for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26868            j++) {
26869         if (tetsperverlist[j] == tetloop.tet) continue; // Skip myself.
26870         neightet.tet = tetsperverlist[j];
26871         for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26872           sym(neightet, neineightet);
26873           if (neineightet.tet == dummytet) {
26874             norg = org(neightet);
26875             ndest = dest(neightet);
26876             napex = apex(neightet);
26877             inorg = pointmark(norg) - in->firstnumber;
26878             indest = pointmark(ndest) - in->firstnumber;
26879             inapex = pointmark(napex) - in->firstnumber;
26880             if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26881               // Find! Bond them together and break the loop.
26882               bond(tetloop, neightet);
26883               bondflag = true;
26884               break;
26885             }
26886           }
26887         }
26888       }
26889       if (!bondflag) {
26890         hullsize++;  // It's a hull face.
26891         // Bond this side to outer space.
26892         dummytet[0] = encode(tetloop);
26893         if ((in->pointmarkerlist != (int *) NULL) && !b->coarse) {
26894           // Set its three corners's markers be boundary (hull) vertices.
26895           if (in->pointmarkerlist[iorg] == 0) {
26896             in->pointmarkerlist[iorg] = 1;
26897           }
26898           if (in->pointmarkerlist[idest] == 0) {
26899             in->pointmarkerlist[idest] = 1;
26900           }
26901           if (in->pointmarkerlist[iapex] == 0) {
26902             in->pointmarkerlist[iapex] = 1;
26903           }
26904         }
26905       }
26906       worklist[iorg] = 0;
26907       worklist[idest] = 0;
26908       worklist[iapex] = 0;
26909     }
26910     tetloop.tet = tetrahedrontraverse();
26911   }
26912 
26913   // Subfaces will be inserted into the mesh. It has two phases:
26914   //   (1) Insert subfaces provided by user (in->trifacelist);
26915   //   (2) Create subfaces for hull faces (if they're not subface yet) and
26916   //       interior faces which separate two different materials.
26917 
26918   // Phase (1). Is there a list of user-provided subfaces?
26919   if (in->trifacelist != (int *) NULL) {
26920     // Recover subfaces from 'in->trifacelist'.
26921     for (i = 0; i < in->numberoftrifaces; i++) {
26922       index = i * 3;
26923       iorg = in->trifacelist[index] - in->firstnumber;
26924       idest = in->trifacelist[index + 1] - in->firstnumber;
26925       iapex = in->trifacelist[index + 2] - in->firstnumber;
26926       // Look for the location of this subface.
26927       worklist[iorg] = 1;
26928       worklist[idest] = 1;
26929       worklist[iapex] = 1;
26930       bondflag = false;
26931       // Search its neighbor in the adjacent tets of torg.
26932       for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26933            j++) {
26934         neightet.tet = tetsperverlist[j];
26935         for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26936           norg = org(neightet);
26937           ndest = dest(neightet);
26938           napex = apex(neightet);
26939           inorg = pointmark(norg) - in->firstnumber;
26940           indest = pointmark(ndest) - in->firstnumber;
26941           inapex = pointmark(napex) - in->firstnumber;
26942           if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26943             bondflag = true;  // Find!
26944             break;
26945           }
26946         }
26947       }
26948       if (bondflag) {
26949         // Create a new subface and insert it into the mesh.
26950         makeshellface(subfaces, &subloop);
26951         torg = idx2verlist[iorg];
26952         tdest = idx2verlist[idest];
26953         tapex = idx2verlist[iapex];
26954         setsorg(subloop, torg);
26955         setsdest(subloop, tdest);
26956         setsapex(subloop, tapex);
26957         // Set the vertices be FREESUBVERTEX to indicate they belong to a
26958         //   facet of the domain.  They may be changed later.
26959         setpointtype(torg, FREESUBVERTEX);
26960         setpointtype(tdest, FREESUBVERTEX);
26961         setpointtype(tapex, FREESUBVERTEX);
26962         if (in->trifacemarkerlist != (int *) NULL) {
26963           setshellmark(subloop, in->trifacemarkerlist[i]);
26964         }
26965         adjustedgering(neightet, CCW);
26966         findedge(&subloop, org(neightet), dest(neightet));
26967         tsbond(neightet, subloop);
26968         sym(neightet, neineightet);
26969         if (neineightet.tet != dummytet) {
26970           sesymself(subloop);
26971           tsbond(neineightet, subloop);
26972         }
26973       } else {
26974         if (!b->quiet) {
26975           printf("Warning:  Subface %d is discarded.\n", i + in->firstnumber);
26976         }
26977       }
26978       worklist[iorg] = 0;
26979       worklist[idest] = 0;
26980       worklist[iapex] = 0;
26981     }
26982   }
26983 
26984   // Phase (2). Indentify subfaces from the mesh.
26985   tetrahedrons->traversalinit();
26986   tetloop.tet = tetrahedrontraverse();
26987   while (tetloop.tet != (tetrahedron *) NULL) {
26988     // Loop the four sides of the tetrahedron.
26989     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26990       tspivot(tetloop, subloop);
26991       if (subloop.sh != dummysh) continue;
26992       bondflag = false;
26993       sym(tetloop, neightet);
26994       if (neightet.tet == dummytet) {
26995         // It's a hull face. Insert a subface at here.
26996         bondflag = true;
26997       } else {
26998         // It's an interior face. Insert a subface if two tetrahedra have
26999         //   different attributes (i.e., they belong to two regions).
27000         if (in->numberoftetrahedronattributes > 0) {
27001           if (elemattribute(neightet.tet,
27002               in->numberoftetrahedronattributes - 1) !=
27003               elemattribute(tetloop.tet,
27004               in->numberoftetrahedronattributes - 1)) {
27005             bondflag = true;
27006           }
27007         }
27008       }
27009       if (bondflag) {
27010         adjustedgering(tetloop, CCW);
27011         makeshellface(subfaces, &subloop);
27012         torg = org(tetloop);
27013         tdest = dest(tetloop);
27014         tapex = apex(tetloop);
27015         setsorg(subloop, torg);
27016         setsdest(subloop, tdest);
27017         setsapex(subloop, tapex);
27018         // Set the vertices be FREESUBVERTEX to indicate they belong to a
27019         //   facet of the domain.  They may be changed later.
27020         setpointtype(torg, FREESUBVERTEX);
27021         setpointtype(tdest, FREESUBVERTEX);
27022         setpointtype(tapex, FREESUBVERTEX);
27023         tsbond(tetloop, subloop);
27024         if (neightet.tet != dummytet) {
27025           sesymself(subloop);
27026           tsbond(neightet, subloop);
27027         }
27028       }
27029     }
27030     tetloop.tet = tetrahedrontraverse();
27031   }
27032 
27033   // Set the connection between subfaces. A subsegment may have more than
27034   //   two subfaces sharing it, 'neighshlist' stores all subfaces sharing
27035   //   one edge.
27036   neighshlist = new list(sizeof(face), NULL);
27037   // Create a map from nodes to subfaces.
27038   makesubfacemap(idx2facelist, facesperverlist);
27039 
27040   // Loop over the set of subfaces, setup the connection between subfaces.
27041   subfaces->traversalinit();
27042   subloop.sh = shellfacetraverse(subfaces);
27043   while (subloop.sh != (shellface *) NULL) {
27044     for (i = 0; i < 3; i++) {
27045       spivot(subloop, neighsh);
27046       if (neighsh.sh == dummysh) {
27047         // This side is 'empty', operate on it.
27048         torg = sorg(subloop);
27049         tdest = sdest(subloop);
27050         tapex = sapex(subloop);
27051         neighshlist->append(&subloop);
27052         iorg = pointmark(torg) - in->firstnumber;
27053         // Search its neighbor in the adjacent list of torg.
27054         for (j = idx2facelist[iorg]; j < idx2facelist[iorg + 1]; j++) {
27055           neighsh.sh = facesperverlist[j];
27056           if (neighsh.sh == subloop.sh) continue;
27057           neighsh.shver = 0;
27058           if (isfacehasedge(&neighsh, torg, tdest)) {
27059             findedge(&neighsh, torg, tdest);
27060             // Insert 'neighsh' into 'neighshlist'.
27061             if (neighshlist->len() < 2) {
27062               neighshlist->append(&neighsh);
27063             } else {
27064               for (index = 0; index < neighshlist->len() - 1; index++) {
27065                 sface1 = * (face *)(* neighshlist)[index];
27066                 sface2 = * (face *)(* neighshlist)[index + 1];
27067                 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(neighsh));
27068                 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
27069                 if (da1 < da2) {
27070                   break;  // Insert it after index.
27071                 }
27072               }
27073               neighshlist->insert(index + 1, &neighsh);
27074             }
27075           }
27076         }
27077         // Bond the subfaces in 'neighshlist'.
27078         if (neighshlist->len() > 1) {
27079           neighsh = * (face *)(* neighshlist)[0];
27080           for (j = 1; j <= neighshlist->len(); j++) {
27081             if (j < neighshlist->len()) {
27082               neineighsh = * (face *)(* neighshlist)[j];
27083             } else {
27084               neineighsh = * (face *)(* neighshlist)[0];
27085             }
27086             sbond1(neighsh, neineighsh);
27087             neighsh = neineighsh;
27088           }
27089         } else {
27090           // No neighbor subface be found, bond 'subloop' to itself.
27091           sbond(subloop, subloop);
27092         }
27093         neighshlist->clear();
27094       }
27095       senextself(subloop);
27096     }
27097     subloop.sh = shellfacetraverse(subfaces);
27098   }
27099 
27100   // Segments will be introudced. Each segment has a unique marker (1-based).
27101   marker = 1;
27102   subfaces->traversalinit();
27103   subloop.sh = shellfacetraverse(subfaces);
27104   while (subloop.sh != (shellface *) NULL) {
27105     for (i = 0; i < 3; i++) {
27106       sspivot(subloop, subseg);
27107       if (subseg.sh == dummysh) {
27108         // This side has no subsegment bonded, check it.
27109         torg = sorg(subloop);
27110         tdest = sdest(subloop);
27111         tapex = sapex(subloop);
27112         spivot(subloop, neighsh);
27113         spivot(neighsh, neineighsh);
27114         insertsegflag = false;
27115         if (subloop.sh == neighsh.sh || subloop.sh != neineighsh.sh) {
27116           // This side is either self-bonded or more than two subfaces,
27117           //   insert a subsegment at this side.
27118           insertsegflag = true;
27119         } else {
27120           // Only two subfaces case.
27121 #ifdef SELF_CHECK
27122           assert(subloop.sh != neighsh.sh);
27123 #endif
27124           napex = sapex(neighsh);
27125           sign = orient3d(torg, tdest, tapex, napex);
27126           if (iscoplanar(torg, tdest, tapex, napex, sign, b->epsilon)) {
27127             // Although they are coplanar, we still need to check if they
27128             //   have the same boundary marker.
27129             insertsegflag = (shellmark(subloop) != shellmark(neighsh));
27130           } else {
27131             // Non-coplanar.
27132             insertsegflag = true;
27133           }
27134         }
27135         if (insertsegflag) {
27136           // Create a subsegment at this side.
27137           makeshellface(subsegs, &subseg);
27138           setsorg(subseg, torg);
27139           setsdest(subseg, tdest);
27140           // The two vertices have been marked as FREESUBVERTEX. Now mark
27141           //   them as NACUTEVERTEX.
27142           setpointtype(torg, NACUTEVERTEX);
27143           setpointtype(tdest, NACUTEVERTEX);
27144           setshellmark(subseg, marker);
27145           marker++;
27146           // Bond all subfaces to this subsegment.
27147           neighsh = subloop;
27148           do {
27149             ssbond(neighsh, subseg);
27150             spivotself(neighsh);
27151           } while (neighsh.sh != subloop.sh);
27152         }
27153       }
27154       senextself(subloop);
27155     }
27156     subloop.sh = shellfacetraverse(subfaces);
27157   }
27158   // Remember the number of input segments.
27159   insegments = subsegs->items;
27160   // Find the acute vertices and set them be type ACUTEVERTEX.
27161 
27162   // Indentify facets and set the facet marker (1-based) for subfaces.
27163   markerlist = new list((char*)"int");
27164 
27165   subfaces->traversalinit();
27166   subloop.sh = shellfacetraverse(subfaces);
27167   while (subloop.sh != (shellface *) NULL) {
27168     // Only operate on uninfected subface, after operating, infect it.
27169     if (!sinfected(subloop)) {
27170       // A new facet is found.
27171       marker = shellmark(subloop);
27172       markerlist->append(&marker);
27173       facetidx = markerlist->len(); // 'facetidx' starts from 1.
27174       setshellmark(subloop, facetidx);
27175       sinfect(subloop);
27176       neighshlist->append(&subloop);
27177       // Find out all subfaces of this facet (bounded by subsegments).
27178       for (i = 0; i < neighshlist->len(); i++) {
27179         neighsh = * (face *) (* neighshlist)[i];
27180         for (j = 0; j < 3; j++) {
27181           sspivot(neighsh, subseg);
27182           if (subseg.sh == dummysh) {
27183             spivot(neighsh, neineighsh);
27184             if (!sinfected(neineighsh)) {
27185               // 'neineighsh' is in the same facet as 'subloop'.
27186 #ifdef SELF_CHECK
27187               assert(shellmark(neineighsh) == marker);
27188 #endif
27189               setshellmark(neineighsh, facetidx);
27190               sinfect(neineighsh);
27191               neighshlist->append(&neineighsh);
27192             }
27193           }
27194           senextself(neighsh);
27195         }
27196       }
27197       neighshlist->clear();
27198     }
27199     subloop.sh = shellfacetraverse(subfaces);
27200   }
27201   // Uninfect all subfaces.
27202   subfaces->traversalinit();
27203   subloop.sh = shellfacetraverse(subfaces);
27204   while (subloop.sh != (shellface *) NULL) {
27205 #ifdef SELF_CHECK
27206     assert(sinfected(subloop));
27207 #endif
27208     suninfect(subloop);
27209     subloop.sh = shellfacetraverse(subfaces);
27210   }
27211   // Save the facet markers in 'in->facetmarkerlist'.
27212   in->numberoffacets = markerlist->len();
27213   in->facetmarkerlist = new int[in->numberoffacets];
27214   for (i = 0; i < in->numberoffacets; i++) {
27215     marker = * (int *) (* markerlist)[i];
27216     in->facetmarkerlist[i] = marker;
27217   }
27218   // Initialize the 'facetabovepointlist'.
27219   facetabovepointarray = new point[in->numberoffacets + 1];
27220   for (i = 0; i < in->numberoffacets + 1; i++) {
27221     facetabovepointarray[i] = (point) NULL;
27222   }
27223 
27224   // The mesh contains boundary now.
27225   checksubfaces = 1;
27226   // The mesh is nonconvex now.
27227   nonconvex = 1;
27228 
27229   // Is there periodic boundary confitions?
27230   if (checkpbcs) {
27231     tetgenio::pbcgroup *pg;
27232     pbcdata *pd;
27233     // Initialize the global array 'subpbcgrouptable'.
27234     createsubpbcgrouptable();
27235     // Loop for each pbcgroup i.
27236     for (i = 0; i < in->numberofpbcgroups; i++) {
27237       pg = &(in->pbcgrouplist[i]);
27238       pd = &(subpbcgrouptable[i]);
27239       // Find all subfaces of pd, set each subface's group id be i.
27240       for (j = 0; j < 2; j++) {
27241         subfaces->traversalinit();
27242         subloop.sh = shellfacetraverse(subfaces);
27243         while (subloop.sh != (shellface *) NULL) {
27244           facetidx = shellmark(subloop);
27245           marker = in->facetmarkerlist[facetidx - 1];
27246           if (marker == pd->fmark[j]) {
27247             setshellpbcgroup(subloop, i);
27248             pd->ss[j] = subloop;
27249           }
27250           subloop.sh = shellfacetraverse(subfaces);
27251         }
27252       }
27253       if (pg->pointpairlist != (int *) NULL) {
27254         // Set the connections between pbc point pairs.
27255         for (j = 0; j < pg->numberofpointpairs; j++) {
27256           iorg = pg->pointpairlist[j * 2] - in->firstnumber;
27257           idest = pg->pointpairlist[j * 2 + 1] - in->firstnumber;
27258           torg = idx2verlist[iorg];
27259           tdest = idx2verlist[idest];
27260           setpoint2pbcpt(torg, tdest);
27261           setpoint2pbcpt(tdest, torg);
27262         }
27263       }
27264     }
27265     // Create the global array 'segpbcgrouptable'.
27266     createsegpbcgrouptable();
27267   }
27268 
27269   delete markerlist;
27270   delete neighshlist;
27271   delete [] worklist;
27272   delete [] idx2tetlist;
27273   delete [] tetsperverlist;
27274   delete [] idx2facelist;
27275   delete [] facesperverlist;
27276   delete [] idx2verlist;
27277 
27278   return hullsize;
27279 }
27280 
27282 //                                                                           //
27283 // insertconstrainedpoints()    Insert a list of constrained points.         //
27284 //                                                                           //
27286 
27287 void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
27288 {
27289   queue *flipqueue;
27290   triface searchtet;
27291   face checksh, checkseg;
27292   point newpoint;
27293   enum locateresult loc;
27294   REAL *attr;
27295   bool insertflag;
27296   int covertices, outvertices;
27297   int index;
27298   int i, j;
27299 
27300   if (!b->quiet) {
27301     printf("Insert additional points into mesh.\n");
27302   }
27303   // Initialize 'flipqueue'.
27304   flipqueue = new queue(sizeof(badface));
27305   recenttet.tet = dummytet;
27306   covertices = outvertices = 0;
27307 
27308   index = 0;
27309   for (i = 0; i < addio->numberofpoints; i++) {
27310     // Create a newpoint.
27311     makepoint(&newpoint);
27312     newpoint[0] = addio->pointlist[index++];
27313     newpoint[1] = addio->pointlist[index++];
27314     newpoint[2] = addio->pointlist[index++];
27315     // Read the add point attributes if current points have attributes.
27316     if ((addio->numberofpointattributes > 0) &&
27317         (in->numberofpointattributes > 0)) {
27318       attr = addio->pointattributelist + addio->numberofpointattributes * i;
27319       for (j = 0; j < in->numberofpointattributes; j++) {
27320         if (j < addio->numberofpointattributes) {
27321           newpoint[3 + j] = attr[j];
27322         }
27323       }
27324     }
27325     // Find the location of the inserted point.
27326     searchtet = recenttet;
27327     loc = locate(newpoint, &searchtet);
27328     if (loc != ONVERTEX) {
27329       loc = adjustlocate(newpoint, &searchtet, loc, b->epsilon2);
27330     }
27331     if (loc == OUTSIDE) {
27332       loc = hullwalk(newpoint, &searchtet);
27333       if (loc == OUTSIDE) {
27334         // Perform a brute-force search.
27335         tetrahedrons->traversalinit();
27336         searchtet.tet = tetrahedrontraverse();
27337         while (searchtet.tet != (tetrahedron *) NULL) {
27338           loc = adjustlocate(newpoint, &searchtet, OUTSIDE, b->epsilon2);
27339           if (loc != OUTSIDE) break;
27340           searchtet.tet = tetrahedrontraverse();
27341         }
27342       }
27343     }
27344     // Insert the point if it not lies outside or on a vertex.
27345     insertflag = true;
27346     switch (loc) {
27347     case INTETRAHEDRON:
27348       setpointtype(newpoint, FREEVOLVERTEX);
27349       splittetrahedron(newpoint, &searchtet, flipqueue);
27350       break;
27351     case ONFACE:
27352       tspivot(searchtet, checksh);
27353       if (checksh.sh != dummysh) {
27354         // It is a boundary face. Don't insert it if -Y option is used.
27355         if (b->nobisect) {
27356           insertflag = false;
27357         } else {
27358           setpointtype(newpoint, FREESUBVERTEX);
27359         }
27360       } else {
27361         setpointtype(newpoint, FREEVOLVERTEX);
27362       }
27363       if (insertflag) {
27364         splittetface(newpoint, &searchtet, flipqueue);
27365       }
27366       break;
27367     case ONEDGE:
27368       tsspivot(&searchtet, &checkseg);
27369       if (checkseg.sh != dummysh) {
27370         if (b->nobisect) {
27371           insertflag = false;
27372         } else {
27373           setpointtype(newpoint, FREESEGVERTEX);
27374           setpoint2sh(newpoint, sencode(checkseg));
27375         }
27376       } else {
27377         tspivot(searchtet, checksh);
27378         if (checksh.sh != dummysh) {
27379           if (b->nobisect) {
27380             insertflag = false;
27381           } else {
27382             setpointtype(newpoint, FREESUBVERTEX);
27383           }
27384         } else {
27385           setpointtype(newpoint, FREEVOLVERTEX);
27386         }
27387       }
27388       if (insertflag) {
27389         splittetedge(newpoint, &searchtet, flipqueue);
27390       }
27391       break;
27392     case ONVERTEX:
27393       insertflag = false;
27394       covertices++;
27395       break;
27396     case OUTSIDE:
27397       insertflag = false;
27398       outvertices++;
27399       break;
27400     }
27401     // Remember the tetrahedron for next point searching.
27402     recenttet = searchtet;
27403     if (!insertflag) {
27404       pointdealloc(newpoint);
27405     } else {
27406       flip(flipqueue, NULL);
27407     }
27408   }
27409 
27410   if (b->verbose) {
27411     if (covertices > 0) {
27412       printf("  %d constrained points already exist.\n", covertices);
27413     }
27414     if (outvertices > 0) {
27415       printf("  %d constrained points lie outside the mesh.\n", outvertices);
27416     }
27417     printf("  %d constrained points have been inserted.\n",
27418            addio->numberofpoints - covertices - outvertices);
27419   }
27420 
27421   delete flipqueue;
27422 }
27423 
27425 //                                                                           //
27426 // p1interpolatebgm()    Set pt size by p^1 interpolation in background mesh.//
27427 //                                                                           //
27428 // On input, 'bgmtet' is a suggesting tet in background mesh for searching   //
27429 // 'pt'. It returns the tet containing 'pt'.                                 //
27430 //                                                                           //
27432 
27433 bool tetgenmesh::p1interpolatebgm(point pt, triface* bgmtet, long *scount)
27434 {
27435   point bgmpt[4];
27436   enum locateresult loc;
27437   REAL vol, volpt[4], weights[4];
27438   int i;
27439 
27440   loc = bgm->preciselocate(pt, bgmtet, bgm->tetrahedrons->items);
27441   if (loc == OUTSIDE) {
27442     loc = bgm->hullwalk(pt, bgmtet);
27443     if (loc == OUTSIDE) {
27444       // Perform a brute-force search.
27445       if (b->verbose) {
27446         printf("Warning:  Global point location.\n");
27447       }
27448       if (scount) (*scount)++;
27449       bgm->tetrahedrons->traversalinit(); // in bgm
27450       bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
27451       while (bgmtet->tet != (tetrahedron *) NULL) {
27452         loc = bgm->adjustlocate(pt, bgmtet, OUTSIDE, b->epsilon);
27453         if (loc != OUTSIDE) break;
27454         bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
27455       }
27456     }
27457   }
27458   if (loc != OUTSIDE) {
27459     // Let p remember t.
27460     setpoint2bgmtet(pt, encode(*bgmtet)); // in m
27461     // get the corners of t.
27462     for (i = 0; i < 4; i++) bgmpt[i] = (point) bgmtet->tet[4 + i];
27463     // Calculate the weighted coordinates of p in t.
27464     vol = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], bgmpt[3]);
27465     volpt[0] = orient3d(pt, bgmpt[1], bgmpt[2], bgmpt[3]);
27466     volpt[1] = orient3d(bgmpt[0], pt, bgmpt[2], bgmpt[3]);
27467     volpt[2] = orient3d(bgmpt[0], bgmpt[1], pt, bgmpt[3]);
27468     volpt[3] = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], pt);
27469     for (i = 0; i < 4; i++) weights[i] = fabs(volpt[i] / vol);
27470     // Interpolate the solution for p.
27471     for (i = 0; i < bgm->in->numberofpointmtrs; i++) {
27472       pt[pointmtrindex + i] = weights[0] * bgmpt[0][bgm->pointmtrindex + i]
27473                             + weights[1] * bgmpt[1][bgm->pointmtrindex + i]
27474                             + weights[2] * bgmpt[2][bgm->pointmtrindex + i]
27475                             + weights[3] * bgmpt[3][bgm->pointmtrindex + i];
27476     }
27477   } else {
27478     setpoint2bgmtet(pt, (tetrahedron) NULL);  // in m
27479   }
27480   return loc != OUTSIDE;
27481 }
27482 
27484 //                                                                           //
27485 // interpolatesizemap()    Interpolate the point sizes in the given size map.//
27486 //                                                                           //
27487 // The size map is specified on each node of the background mesh. The points //
27488 // of current mesh get their sizes by interpolating.                         //
27489 //                                                                           //
27490 // This function operation on two meshes simultaneously, the current mesh m, //
27491 // and the background mesh bgm. After this function, each point p in m will  //
27492 // have a pointer to a tet of bgm.                                           //
27493 //                                                                           //
27495 
27496 void tetgenmesh::interpolatesizemap()
27497 {
27498   list *adjtetlist;
27499   triface tetloop, neightet, bgmtet;
27500   point searchpt;
27501   long scount;
27502   int *worklist;
27503   int sepcount;
27504   int i;
27505 
27506   if (b->verbose) {
27507     printf("  Interpolating size map.\n");
27508   }
27509 
27510   worklist = new int[points->items + 1];
27511   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
27512   sepcount = 0;
27513   scount = 0l;
27514 
27515   tetrahedrons->traversalinit();
27516   tetloop.tet = tetrahedrontraverse();
27517   while (tetloop.tet != (tetrahedron *) NULL) {
27518     if (!infected(tetloop)) {
27519       // Find a new subdomain.
27520       adjtetlist = new list(sizeof(triface), NULL, 1024);
27521       infect(tetloop);
27522       // Search the four corners in background mesh.
27523       for (i = 0; i < 4; i++) {
27524         searchpt = (point) tetloop.tet[4 + i];
27525         // Mark the point for avoiding multiple searchings.
27526         // assert(worklist[pointmark(searchpt)] == 0);
27527         worklist[pointmark(searchpt)] = 1;
27528         // Does it contain a pointer to bgm tet?
27529         bgm->decode(point2bgmtet(searchpt), bgmtet);
27530         if (bgm->isdead(&bgmtet)) {
27531           bgmtet = bgm->recenttet;
27532         }
27533         if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27534           bgm->recenttet = bgmtet;
27535         }
27536       } // for (i = 0; i < 4; i++)
27537       // Collect all tets in this region.
27538       adjtetlist->append(&tetloop);
27539       // Collect the tets in the subdomain.
27540       for (i = 0; i < adjtetlist->len(); i++) {
27541         tetloop = * (triface *)(* adjtetlist)[i];
27542         for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27543           sym(tetloop, neightet);
27544           if ((neightet.tet != dummytet) && !infected(neightet)) {
27545             // Only need to search for the opposite point.
27546             searchpt = oppo(neightet);
27547             if (worklist[pointmark(searchpt)] == 0) {
27548               worklist[pointmark(searchpt)] = 1;
27549               decode(point2bgmtet(searchpt), bgmtet);
27550               if (bgm->isdead(&bgmtet)) {
27551                 bgmtet = bgm->recenttet;
27552               }
27553               if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27554                 bgm->recenttet = bgmtet;
27555               }
27556             }
27557             infect(neightet);
27558             adjtetlist->append(&neightet);
27559           }
27560         }
27561       }
27562       // Increase the number of separated domains.
27563       sepcount++;
27564       delete adjtetlist;
27565     } // if (!infect())
27566     tetloop.tet = tetrahedrontraverse();
27567   }
27568 
27569   // Unmark all tets.
27570   tetrahedrons->traversalinit();
27571   tetloop.tet = tetrahedrontraverse();
27572   while (tetloop.tet != (tetrahedron *) NULL) {
27573     assert(infected(tetloop));
27574     uninfect(tetloop);
27575     tetloop.tet = tetrahedrontraverse();
27576   }
27577   delete [] worklist;
27578 
27579 #ifdef SELF_CHECK
27580   if (b->verbose && scount > 0l) {
27581     printf("  %ld brute-force searches.\n", scount);
27582   }
27583   if (b->verbose && sepcount > 0) {
27584     printf("  %d separate domains.\n", sepcount);
27585   }
27586 #endif
27587 }
27588 
27590 //                                                                           //
27591 // duplicatebgmesh()    Duplicate current mesh to background mesh.           //
27592 //                                                                           //
27593 // Current mesh 'this' is copied into 'this->bgm'.Both meshes share the same //
27594 // input tetgenio object, 'this->in', same tetgenbehavior object 'this->b'.  //
27595 //                                                                           //
27597 
27598 void tetgenmesh::duplicatebgmesh()
27599 {
27600   triface tetloop, btetloop;
27601   triface symtet, bsymtet;
27602   face bhullsh, bneighsh;
27603   point *idx2bplist, *tetptbaklist;
27604   point ploop, bploop;
27605   int idx, i;
27606 
27607   if (!b->quiet) {
27608     printf("Duplicating background mesh.\n");
27609   }
27610 
27611   // The background mesh itself has no background mesh.
27612   // assert(bgm->bgm == (tetgenmesh *) NULL);
27613   // The space for metric tensor should be allocated.
27614   // assert(bgm->sizeoftensor > 0);
27615 
27616   // Copy point list.
27617   idx2bplist = new point[points->items + 1];
27618   idx = in->firstnumber;
27619   points->traversalinit();
27620   ploop = pointtraverse();
27621   while (ploop != (point) NULL) {
27622     bgm->makepoint(&bploop);
27623     // Copy coordinates, attributes.
27624     for (i = 0; i < 3 + in->numberofpointattributes; i++) {
27625       bploop[i] = ploop[i];
27626     }
27627     // Transfer the metric tensor.
27628     for (i = 0; i < bgm->sizeoftensor; i++) {
27629       bploop[bgm->pointmtrindex + i] = ploop[pointmtrindex + i];
27630       // Metric tensor should have a positive value.
27631       if (bploop[bgm->pointmtrindex + i] <= 0.0) {
27632         printf("Error:  Point %d has non-positive size %g (-m option).\n",
27633                bgm->pointmark(bploop), bploop[bgm->pointmtrindex + i]);
27634         terminatetetgen(1);
27635       }
27636     }
27637     // Remember the point for searching.
27638     idx2bplist[idx++] = bploop;
27639     ploop = pointtraverse();
27640   }
27641 
27642   // Copy tetrahedra list.
27643   tetptbaklist = new point[tetrahedrons->items + 1];
27644   idx = in->firstnumber;
27645   tetrahedrons->traversalinit();
27646   tetloop.tet = tetrahedrontraverse();
27647   while (tetloop.tet != (tetrahedron *) NULL) {
27648     bgm->maketetrahedron(&btetloop);
27649     // Set the four corners.
27650     for (i = 0; i < 4; i++) {
27651       ploop = (point) tetloop.tet[4 + i];
27652       bploop = idx2bplist[pointmark(ploop)];
27653       btetloop.tet[4 + i] = (tetrahedron) bploop;
27654     }
27655     // Remember the tet for setting neighbor connections.
27656     tetptbaklist[idx++] = (point) tetloop.tet[4];
27657     tetloop.tet[4] = (tetrahedron) btetloop.tet;
27658     tetloop.tet = tetrahedrontraverse();
27659   }
27660 
27661   // Set the connections between background tetrahedra. Create background
27662   //   hull subfaces. Create the map of point-to-bgmtet.
27663   idx = in->firstnumber;
27664   tetrahedrons->traversalinit();
27665   tetloop.tet = tetrahedrontraverse();
27666   while (tetloop.tet != (tetrahedron *) NULL) {
27667     // Get the corresponding background tet.
27668     btetloop.tet = (tetrahedron *) tetloop.tet[4];
27669     // Set the four neighbors.
27670     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27671       btetloop.loc = tetloop.loc;
27672       sym(tetloop, symtet);
27673       if ((symtet.tet != dummytet) && (symtet.tet > tetloop.tet)) {
27674         // Operate on the un-connected interior face.
27675         bsymtet.tet = (tetrahedron *) symtet.tet[4]; // The saved bgm tet.
27676         bsymtet.loc = symtet.loc;
27677         bgm->bond(btetloop, bsymtet);
27678       } else if (symtet.tet == dummytet) {
27679         // Create a subface in background mesh.
27680         bgm->makeshellface(bgm->subfaces, &bhullsh);
27681         bgm->adjustedgering(btetloop, CCW); // face to inside.
27682         bgm->setsorg(bhullsh, bgm->org(btetloop));
27683         bgm->setsdest(bhullsh, bgm->dest(btetloop));
27684         bgm->setsapex(bhullsh, bgm->apex(btetloop));
27685         bgm->tsbond(btetloop, bhullsh);
27686         // Remember a hull face for point location.
27687         bgm->dummytet[0] = bgm->encode(btetloop);
27688       }
27689     }
27690     // Restore the backup tet point.
27691     tetloop.tet[4] = (tetrahedron) tetptbaklist[idx++];
27692     // Make the point-to-bgmtet map for size interpolation.
27693     btetloop.loc = 0;
27694     for (i = 0; i < 4; i++) {
27695       ploop = (point) tetloop.tet[4 + i];
27696       setpoint2bgmtet(ploop, bgm->encode(btetloop));
27697     }
27698     // Go to the next tet, btet.
27699     tetloop.tet = tetrahedrontraverse();
27700   }
27701 
27702   // Connect bgm hull subfaces. Note: all hull subfaces form a 2-manifold.
27703   bgm->subfaces->traversalinit();
27704   bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27705   while (bhullsh.sh != (shellface *) NULL) {
27706     bhullsh.shver = 0;
27707     bgm->stpivot(bhullsh, btetloop);
27708     assert(btetloop.tet != bgm->dummytet);
27709     bgm->adjustedgering(btetloop, CCW);
27710     for (i = 0; i < 3; i++) {
27711       bgm->spivot(bhullsh, bneighsh);
27712       if (bneighsh.sh == bgm->dummysh) {
27713         // This side is open, operate on it.
27714         bsymtet = btetloop;
27715         while (bgm->fnextself(bsymtet));
27716         bgm->tspivot(bsymtet, bneighsh);
27717         bgm->findedge(&bneighsh, bgm->sdest(bhullsh), bgm->sorg(bhullsh));
27718         bgm->sbond(bhullsh, bneighsh);
27719       }
27720       bgm->enextself(btetloop);
27721       bgm->senextself(bhullsh);
27722     }
27723     bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27724   }
27725 
27726   delete [] tetptbaklist;
27727   delete [] idx2bplist;
27728 }
27729 
27730 //
27731 // Begin of Delaunay refinement routines
27732 //
27733 
27735 //                                                                           //
27736 // marksharpsegments()    Mark sharp segments.                               //
27737 //                                                                           //
27738 // A segment s is called sharp if it is in one of the two cases:             //
27739 //  (1) There is a segment s' intersecting with s.  The internal angle (*)   //
27740 //      between s and s' is acute.                                           //
27741 //  (2) There are two facets f1 and f2 intersecting at s.  The internal      //
27742 //      dihedral angle (*) between f1 and f2 is acute.                       //
27743 // This routine finds the sharp segments and marked them as type SHARP.      //
27744 // The minimum angle between segments (minfaceang) and the minimum dihedral  //
27745 // angle between facets (minfacetdihed) are calulcated.                      //
27746 //                                                                           //
27747 // (*) The internal angle (or dihedral) bewteen two features means the angle //
27748 // inside the mesh domain.                                                   //
27749 //                                                                           //
27751 
27752 void tetgenmesh::marksharpsegments(REAL sharpangle)
27753 {
27754   triface adjtet;
27755   face startsh, spinsh, neighsh;
27756   face segloop, prevseg, nextseg;
27757   point eorg, edest;
27758   REAL ang, smallang;
27759   bool issharp;
27760   int sharpsegcount;
27761 
27762   if (b->verbose > 0) {
27763     printf("  Marking sharp segments.\n");
27764   }
27765 
27766   smallang = sharpangle * PI / 180.;
27767   sharpsegcount = 0;
27768   eorg = edest = (point) NULL; // To avoid compiler warnings.
27769 
27770   // A segment s may have been split into many subsegments. Operate the one
27771   //   which contains the origin of s. Then mark the rest of subsegments.
27772   subsegs->traversalinit();
27773   segloop.sh = shellfacetraverse(subsegs);
27774   while (segloop.sh != (shellface *) NULL) {
27775     segloop.shver = 0;
27776     senext2(segloop, prevseg);
27777     spivotself(prevseg);
27778     if (prevseg.sh == dummysh) {
27779       // Operate on this seg s.
27780       assert(shelltype(segloop) != SHARP); // It should be unmarked.
27781       issharp = false;
27782       spivot(segloop, startsh);
27783       if (startsh.sh != dummysh) {
27784         // First check if two facets form an acute dihedral angle at s.
27785         eorg = sorg(segloop);
27786         edest = sdest(segloop);
27787         spinsh = startsh;
27788         do {
27789           if (sorg(spinsh) != eorg) {
27790             sesymself(spinsh);
27791           }
27792           // Only do test when the spinsh is faceing inward.
27793           stpivot(spinsh, adjtet);
27794           if (adjtet.tet != dummytet) {
27795             // Get the subface on the adjacent facet.
27796             spivot(spinsh, neighsh);
27797             // Do not calculate if it is self-bonded.
27798             if (neighsh.sh != spinsh.sh) {
27799               // Calculate the dihedral angle between the two subfaces.
27800               ang = facedihedral(eorg, edest, sapex(spinsh), sapex(neighsh));
27801               // Only do check if a sharp angle has not been found.
27802               if (!issharp) issharp = (ang < smallang);
27803               // Remember the smallest facet dihedral angle.
27804               minfacetdihed = minfacetdihed < ang ? minfacetdihed : ang;
27805             }
27806           }
27807           // Go to the next facet.
27808           spivotself(spinsh);
27809         } while (spinsh.sh != startsh.sh);
27810         // if (!issharp) {
27811           // Second check if s forms an acute angle with another seg.
27812           spinsh = startsh;
27813           do {
27814             if (sorg(spinsh) != eorg) {
27815               sesymself(spinsh);
27816             }
27817             // Calculate the angle between s and s' of this facet.
27818             neighsh = spinsh;
27819             // Rotate edges around 'eorg' until meeting another seg s'. Such
27820             //   seg (s') must exist since the facet is segment-bounded.
27821             //   The sum of the angles of faces at 'eorg' gives the internal
27822             //   angle between the two segments.
27823             ang = 0.0;
27824             do {
27825               ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27826               senext2self(neighsh);
27827               sspivot(neighsh, nextseg);
27828               if (nextseg.sh != dummysh) break;
27829               // Go to the next coplanar subface.
27830               spivotself(neighsh);
27831               assert(neighsh.sh != dummysh);
27832               if (sorg(neighsh) != eorg) {
27833                 sesymself(neighsh);
27834               }
27835             } while (true);
27836             // Only do check if a sharp angle has not been found.
27837             if (!issharp) issharp = (ang < smallang);
27838             // Remember the smallest input face angle.
27839             minfaceang = minfaceang < ang ? minfaceang : ang;
27840             // Go to the next facet.
27841             spivotself(spinsh);
27842           } while (spinsh.sh != startsh.sh);
27843         // }
27844       }
27845       if (issharp) {
27846         setshelltype(segloop, SHARP);
27847         // Set the type for all subsegments at forwards.
27848         senext(segloop, nextseg);
27849         spivotself(nextseg);
27850         while (nextseg.sh != dummysh) {
27851           nextseg.shver = 0;
27852           setshelltype(nextseg, SHARP);
27853           senextself(nextseg);
27854           spivotself(nextseg);
27855         }
27856         sharpsegcount++;
27857       }
27858     }
27859     segloop.sh = shellfacetraverse(subsegs);
27860   }
27861 
27862   // So far we have marked all segments which have an acute dihedral angle
27863   //   or whose ORIGINs have an acute angle. In the un-marked subsegments,
27864   //   there are possible ones whose DESTINATIONs have an acute angle.
27865   subsegs->traversalinit();
27866   segloop.sh = shellfacetraverse(subsegs);
27867   while (segloop.sh != (shellface *) NULL) {
27868     // Only operate if s is non-sharp and contains the dest.
27869     segloop.shver = 0;
27870     senext(segloop, nextseg);
27871     spivotself(nextseg);
27872     // if ((nextseg.sh == dummysh) && (shelltype(segloop) != SHARP)) {
27873     if (nextseg.sh == dummysh) {
27874       // issharp = false;
27875       issharp = (shelltype(segloop) == SHARP);
27876       spivot(segloop, startsh);
27877       if (startsh.sh != dummysh) {
27878         // Check if s forms an acute angle with another seg.
27879         eorg = sdest(segloop);
27880         spinsh = startsh;
27881         do {
27882           if (sorg(spinsh) != eorg) {
27883             sesymself(spinsh);
27884           }
27885           // Calculate the angle between s and s' of this facet.
27886           neighsh = spinsh;
27887           ang = 0.0;
27888           do {
27889             ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27890             senext2self(neighsh);
27891             sspivot(neighsh, nextseg);
27892             if (nextseg.sh != dummysh) break;
27893             // Go to the next coplanar subface.
27894             spivotself(neighsh);
27895             assert(neighsh.sh != dummysh);
27896             if (sorg(neighsh) != eorg) {
27897               sesymself(neighsh);
27898             }
27899           } while (true);
27900           // Only do check if a sharp angle has not been found.
27901           if (!issharp) issharp = (ang < smallang);
27902           // Remember the smallest input face angle.
27903           minfaceang = minfaceang < ang ? minfaceang : ang;
27904           // Go to the next facet.
27905           spivotself(spinsh);
27906         } while (spinsh.sh != startsh.sh);
27907       }
27908       if (issharp) {
27909         setshelltype(segloop, SHARP);
27910         // Set the type for all subsegments at backwards.
27911         senext2(segloop, prevseg);
27912         spivotself(prevseg);
27913         while (prevseg.sh != dummysh) {
27914           prevseg.shver = 0;
27915           setshelltype(prevseg, SHARP);
27916           senext2self(prevseg);
27917           spivotself(prevseg);
27918         }
27919         sharpsegcount++;
27920       }
27921     }
27922     segloop.sh = shellfacetraverse(subsegs);
27923   }
27924 
27925   if ((b->verbose > 0) && (sharpsegcount > 0)) {
27926     printf("  %d sharp segments.\n", sharpsegcount);
27927   }
27928 }
27929 
27931 //                                                                           //
27932 // decidefeaturepointsizes()    Decide the sizes for all feature points.     //
27933 //                                                                           //
27934 // A feature point is a point on a sharp segment. Every feature point p will //
27935 // be assigned a positive size which is the radius of the protecting ball.   //
27936 //                                                                           //
27937 // The size of a feature point may be specified by one of the following ways://
27938 //   (1) directly specifying on an input vertex (by using .mtr file);        //
27939 //   (2) imposing a fixed maximal volume constraint ('-a__' option);         //
27940 //   (3) imposing a maximal volume constraint in a region ('-a' option);     //
27941 //   (4) imposing a maximal area constraint on a facet (in .var file);       //
27942 //   (5) imposing a maximal length constraint on a segment (in .var file);   //
27943 //   (6) combining (1) - (5).                                                //
27944 //   (7) automatically deriving a size if none of (1) - (6) is available.    //
27945 // In case (7),the size of p is set to be the smallest edge length among all //
27946 // edges connecting at p.  The final size of p is the minimum of (1) - (7).  //
27947 //                                                                           //
27949 
27950 void tetgenmesh::decidefeaturepointsizes()
27951 {
27952   list *tetlist, *verlist;
27953   shellface **segsperverlist;
27954   triface starttet;
27955   face shloop;
27956   face checkseg, prevseg, nextseg, testseg;
27957   point ploop, adjpt, e1, e2;
27958   REAL lfs_0, len, vol, maxlen, varlen;
27959   bool isfeature;
27960   int *idx2seglist;
27961   int featurecount;
27962   int idx, i, j;
27963 
27964   maxlen = 0.0;
27965 
27966   if (b->verbose > 0) {
27967     printf("  Deciding feature-point sizes.\n");
27968   }
27969 
27970   // Constructing a map from vertices to segments.
27971   makesegmentmap(idx2seglist, segsperverlist);
27972   // Initialize working lists.
27973   tetlist = new list(sizeof(triface), NULL, 256);
27974   verlist = new list(sizeof(point *), NULL, 256);
27975 
27976   if (b->fixedvolume) {
27977     // A fixed volume constraint is imposed. This gives an upper bound of
27978     //   the maximal radius of the protect ball of a vertex.
27979     maxlen = pow(6.0 * b->maxvolume, 1.0/3.0);
27980   }
27981 
27982   if (!b->refine) {
27983     // Initially correct types for Steiner points.
27984     featurecount = 0;
27985     points->traversalinit();
27986     ploop = pointtraverse();
27987     while (ploop != (point) NULL) {
27988       if (pointtype(ploop) == NACUTEVERTEX) {
27989         if (point2sh(ploop) != (shellface) NULL) {
27990           setpointtype(ploop, FREESEGVERTEX);
27991           featurecount++;
27992         }
27993       }
27994       ploop = pointtraverse();
27995     }
27996 #ifdef SELF_CHECK
27997     if ((b->verbose > 0) && (featurecount > 0)) {
27998       printf("  %d Steiner points correction.\n", featurecount);
27999     }
28000 #endif
28001   }
28002 
28003   // First only assign a size of p if p is not a Steiner point. The size of
28004   //   a Steiner point will be interpolated later from the endpoints of the
28005   //   segment on which it lies.
28006   featurecount = 0;
28007   points->traversalinit();
28008   ploop = pointtraverse();
28009   while (ploop != (point) NULL) {
28010     if (pointtype(ploop) != FREESEGVERTEX) {
28011       // Is p a feature point?
28012       isfeature = false;
28013       idx = pointmark(ploop) - in->firstnumber;
28014       for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; i++) {
28015         checkseg.sh = segsperverlist[i];
28016         isfeature = (shelltype(checkseg) == SHARP);
28017       }
28018       // Decide the size of p if it is on a sharp segment.
28019       if (isfeature) {
28020         // Find a tet containing p (checkseg is a sharp seg which contains p).
28021         sstpivot(&checkseg, &starttet);
28022         // Form star(p).
28023         tetlist->append(&starttet);
28024         formstarpolyhedron(ploop, tetlist, verlist, true);
28025         // Decide the size for p if no input size is given on input.
28026         if (ploop[pointmtrindex] == 0.0) {
28027           // Calculate lfs_0(p).
28028           lfs_0 = longest;
28029           for (i = 0; i < verlist->len(); i++) {
28030             adjpt = * (point *)(* verlist)[i];
28031             if (pointtype(adjpt) == FREESEGVERTEX) {
28032               // A Steiner point q. Find the seg it lies on.
28033               sdecode(point2sh(adjpt), checkseg);
28034               assert(checkseg.sh != dummysh);
28035               checkseg.shver = 0;
28036               // Find the origin of this seg.
28037               prevseg = checkseg;
28038               do {
28039                 senext2(prevseg, testseg);
28040                 spivotself(testseg);
28041                 if (testseg.sh == dummysh) break;
28042                 prevseg = testseg; // Go to the previous subseg.
28043                 prevseg.shver = 0;
28044               } while (true);
28045               // Find the dest of this seg.
28046               nextseg = checkseg;
28047               do {
28048                 senext(nextseg, testseg);
28049                 spivotself(testseg);
28050                 if (testseg.sh == dummysh) break;
28051                 nextseg = testseg; // Go to the next subseg.
28052                 nextseg.shver = 0;
28053               } while (true);
28054               e1 = sorg(prevseg);
28055               e2 = sdest(nextseg);
28056               // Check if p is the origin or the dest of this seg.
28057               if (ploop == e1) {
28058                 // Set q to be the dest of this seg.
28059                 adjpt = e2;
28060               } else if (ploop == e2) {
28061                 // Set q to be the org of this seg.
28062                 adjpt = e1;
28063               }
28064             }
28065             len = distance(ploop, adjpt);
28066             if (lfs_0 > len) lfs_0 = len;
28067           }
28068           ploop[pointmtrindex] = lfs_0;
28069         }
28070         if (b->fixedvolume) {
28071           // A fixed volume constraint is imposed. Adjust H(p) <= maxlen.
28072           if (ploop[pointmtrindex] > maxlen) {
28073             ploop[pointmtrindex] = maxlen;
28074           }
28075         }
28076         if (b->varvolume) {
28077           // Variant volume constraints are imposed. Adjust H(p) <= varlen.
28078           for (i = 0; i < tetlist->len(); i++) {
28079             starttet = * (triface *)(* tetlist)[i];
28080             vol = volumebound(starttet.tet);
28081             if (vol > 0.0) {
28082               varlen = pow(6 * vol, 1.0/3.0);
28083               if (ploop[pointmtrindex] > varlen) {
28084                 ploop[pointmtrindex] = varlen;
28085               }
28086             }
28087           }
28088         }
28089         // Clear working lists.
28090         tetlist->clear();
28091         verlist->clear();
28092         featurecount++;
28093       } else {
28094         // NO feature point, set the size of p be zero.
28095         ploop[pointmtrindex] = 0.0;
28096       }
28097     } // if (pointtype(ploop) != FREESEGVERTEX) {
28098     ploop = pointtraverse();
28099   }
28100 
28101   if (b->verbose > 0) {
28102     printf("  %d feature points.\n", featurecount);
28103   }
28104 
28105   if (!b->refine) {
28106     // Second only assign sizes for all Steiner points. A Steiner point p
28107     //   inserted on a sharp segment s is assigned a size by interpolating
28108     //   the sizes of the original endpoints of s.
28109     featurecount = 0;
28110     points->traversalinit();
28111     ploop = pointtraverse();
28112     while (ploop != (point) NULL) {
28113       if (pointtype(ploop) == FREESEGVERTEX) {
28114         if (ploop[pointmtrindex] == 0.0) {
28115           sdecode(point2sh(ploop), checkseg);
28116           assert(checkseg.sh != dummysh);
28117           if (shelltype(checkseg) == SHARP) {
28118             checkseg.shver = 0;
28119             // Find the origin of this seg.
28120             prevseg = checkseg;
28121             do {
28122               senext2(prevseg, testseg);
28123               spivotself(testseg);
28124               if (testseg.sh == dummysh) break;
28125               prevseg = testseg; // Go the previous subseg.
28126               prevseg.shver = 0;
28127             } while (true);
28128             // Find the dest of this seg.
28129             nextseg = checkseg;
28130             do {
28131               senext(nextseg, testseg);
28132               spivotself(testseg);
28133               if (testseg.sh == dummysh) break;
28134               nextseg = testseg; // Go the next subseg.
28135               nextseg.shver = 0;
28136             } while (true);
28137             e1 = sorg(prevseg);
28138             e2 = sdest(nextseg);
28139             len = distance(e1, e2);
28140             lfs_0 = distance(e1, ploop);
28141             // The following assert() happens when -Y option is used.
28142             if (b->nobisect == 0) {
28143               assert(lfs_0 < len);
28144             }
28145             ploop[pointmtrindex] = e1[pointmtrindex]
28146               + (lfs_0 / len) * (e2[pointmtrindex] - e1[pointmtrindex]);
28147             featurecount++;
28148           } else {
28149             // NO feature point, set the size of p be zero.
28150             ploop[pointmtrindex] = 0.0;
28151           } // if (shelltype(checkseg) == SHARP)
28152         } // if (ploop[pointmtrindex] == 0.0)
28153       } // if (pointtype(ploop) != FREESEGVERTEX)
28154       ploop = pointtraverse();
28155     }
28156     if ((b->verbose > 0) && (featurecount > 0)) {
28157       printf("  %d Steiner feature points.\n", featurecount);
28158     }
28159   }
28160 
28161   if (varconstraint) {
28162     // A .var file exists. Adjust feature sizes.
28163     if (in->facetconstraintlist) {
28164       // Have facet area constrains.
28165       subfaces->traversalinit();
28166       shloop.sh = shellfacetraverse(subfaces);
28167       while (shloop.sh != (shellface *) NULL) {
28168         varlen = areabound(shloop);
28169         if (varlen > 0.0) {
28170           // Check if the three corners are feature points.
28171           varlen = sqrt(varlen);
28172           for (j = 0; j < 3; j++) {
28173             ploop = (point) shloop.sh[3 + j];
28174             isfeature = false;
28175             idx = pointmark(ploop) - in->firstnumber;
28176             for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28177                  i++) {
28178               checkseg.sh = segsperverlist[i];
28179               isfeature = (shelltype(checkseg) == SHARP);
28180             }
28181             if (isfeature) {
28182               assert(ploop[pointmtrindex] > 0.0);
28183               if (ploop[pointmtrindex] > varlen) {
28184                 ploop[pointmtrindex] = varlen;
28185               }
28186             }
28187           } // for (j = 0; j < 3; j++)
28188         }
28189         shloop.sh = shellfacetraverse(subfaces);
28190       }
28191     }
28192     if (in->segmentconstraintlist) {
28193       // Have facet area constrains.
28194       subsegs->traversalinit();
28195       shloop.sh = shellfacetraverse(subsegs);
28196       while (shloop.sh != (shellface *) NULL) {
28197         varlen = areabound(shloop);
28198         if (varlen > 0.0) {
28199           // Check if the two endpoints are feature points.
28200           for (j = 0; j < 2; j++) {
28201             ploop = (point) shloop.sh[3 + j];
28202             isfeature = false;
28203             idx = pointmark(ploop) - in->firstnumber;
28204             for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28205                  i++) {
28206               checkseg.sh = segsperverlist[i];
28207               isfeature = (shelltype(checkseg) == SHARP);
28208             }
28209             if (isfeature) {
28210               assert(ploop[pointmtrindex] > 0.0);
28211               if (ploop[pointmtrindex] > varlen) {
28212                 ploop[pointmtrindex] = varlen;
28213               }
28214             }
28215           } // for (j = 0; j < 2; j++)
28216         }
28217         shloop.sh = shellfacetraverse(subsegs);
28218       }
28219     }
28220   } // if (varconstraint)
28221 
28222   delete [] segsperverlist;
28223   delete [] idx2seglist;
28224   delete tetlist;
28225   delete verlist;
28226 }
28227 
28229 //                                                                           //
28230 // enqueueencsub()    Add an encroached subface into the queue.              //
28231 //                                                                           //
28233 
28234 void tetgenmesh::enqueueencsub(face* testsub, point encpt, int quenumber,
28235   REAL* cent)
28236 {
28237   badface *encsub;
28238   int i;
28239 
28240   encsub = (badface *) badsubfaces->alloc();
28241   encsub->ss = *testsub;
28242   encsub->forg = sorg(*testsub);
28243   encsub->fdest = sdest(*testsub);
28244   encsub->fapex = sapex(*testsub);
28245   encsub->foppo = (point) encpt;
28246   for (i = 0; i < 3; i++) encsub->cent[i] = cent[i];
28247   encsub->nextitem = (badface *) NULL;
28248   // Set the pointer of 'encsubseg' into 'testsub'.  It has two purposes:
28249   //   (1) We can regonize it is encroached; (2) It is uniquely queued.
28250   setshell2badface(encsub->ss, encsub);
28251   // Add the subface to the end of a queue (quenumber = 2, high priority).
28252   *subquetail[quenumber] = encsub;
28253   // Maintain a pointer to the NULL pointer at the end of the queue.
28254   subquetail[quenumber] = &encsub->nextitem;
28255   if (b->verbose > 2) {
28256     printf("    Queuing subface (%d, %d, %d) [%d].\n", pointmark(encsub->forg),
28257            pointmark(encsub->fdest), pointmark(encsub->fapex), quenumber);
28258   }
28259 }
28260 
28262 //                                                                           //
28263 // dequeueencsub()    Remove an enc-subface from the front of the queue.     //
28264 //                                                                           //
28266 
28267 tetgenmesh::badface* tetgenmesh::dequeueencsub(int* pquenumber)
28268 {
28269   badface *result;
28270   int quenumber;
28271 
28272   // Look for a nonempty queue.
28273   for (quenumber = 2; quenumber >= 0; quenumber--) {
28274     result = subquefront[quenumber];
28275     if (result != (badface *) NULL) {
28276       // Remove the badface from the queue.
28277       subquefront[quenumber] = result->nextitem;
28278       // Maintain a pointer to the NULL pointer at the end of the queue.
28279       if (subquefront[quenumber] == (badface *) NULL) {
28280         subquetail[quenumber] = &subquefront[quenumber];
28281       }
28282       *pquenumber = quenumber;
28283       return result;
28284     }
28285   }
28286   return (badface *) NULL;
28287 }
28288 
28290 //                                                                           //
28291 // enqueuebadtet()    Add a tetrahedron into the queue.                      //
28292 //                                                                           //
28294 
28295 void tetgenmesh::enqueuebadtet(triface* testtet, REAL ratio2, REAL* cent)
28296 {
28297   badface *newbadtet;
28298   int queuenumber;
28299   int i;
28300 
28301   // Allocate space for the bad tetrahedron.
28302   newbadtet = (badface *) badtetrahedrons->alloc();
28303   newbadtet->tt = *testtet;
28304   newbadtet->key = ratio2;
28305   if (cent != NULL) {
28306     for (i = 0; i < 3; i++) newbadtet->cent[i] = cent[i];
28307   } else {
28308     for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
28309   }
28310   newbadtet->forg = org(*testtet);
28311   newbadtet->fdest = dest(*testtet);
28312   newbadtet->fapex = apex(*testtet);
28313   newbadtet->foppo = oppo(*testtet);
28314   newbadtet->nextitem = (badface *) NULL;
28315   // Determine the appropriate queue to put the bad tetrahedron into.
28316   if (ratio2 > b->goodratio) {
28317     // queuenumber = (int) ((ratio2 - b->goodratio) / 0.5);
28318     queuenumber = (int) (64.0 - 64.0 / ratio2);
28319     // 'queuenumber' may overflow (negative) caused by a very large ratio.
28320     if ((queuenumber > 63) || (queuenumber < 0)) {
28321       queuenumber = 63;
28322     }
28323   } else {
28324     // It's not a bad ratio; put the tet in the lowest-priority queue.
28325     queuenumber = 0;
28326   }
28327 
28328   // Are we inserting into an empty queue?
28329   if (tetquefront[queuenumber] == (badface *) NULL) {
28330     // Yes. Will this become the highest-priority queue?
28331     if (queuenumber > firstnonemptyq) {
28332       // Yes, this is the highest-priority queue.
28333       nextnonemptyq[queuenumber] = firstnonemptyq;
28334       firstnonemptyq = queuenumber;
28335     } else {
28336       // No. Find the queue with next higher priority.
28337       i = queuenumber + 1;
28338       while (tetquefront[i] == (badface *) NULL) {
28339         i++;
28340       }
28341       // Mark the newly nonempty queue as following a higher-priority queue.
28342       nextnonemptyq[queuenumber] = nextnonemptyq[i];
28343       nextnonemptyq[i] = queuenumber;
28344     }
28345     // Put the bad tetrahedron at the beginning of the (empty) queue.
28346     tetquefront[queuenumber] = newbadtet;
28347   } else {
28348     // Add the bad tetrahedron to the end of an already nonempty queue.
28349     tetquetail[queuenumber]->nextitem = newbadtet;
28350   }
28351   // Maintain a pointer to the last tetrahedron of the queue.
28352   tetquetail[queuenumber] = newbadtet;
28353 
28354   if (b->verbose > 2) {
28355     printf("    Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
28356            pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
28357            pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
28358            sqrt(ratio2), queuenumber);
28359   }
28360 }
28361 
28363 //                                                                           //
28364 // dequeuebadtet()    Remove a tetrahedron from the front of the queue.      //
28365 //                                                                           //
28367 
28368 tetgenmesh::badface* tetgenmesh::topbadtetra()
28369 {
28370   // Keep a record of which queue was accessed in case dequeuebadtetra()
28371   //   is called later.
28372   recentq = firstnonemptyq;
28373   // If no queues are nonempty, return NULL.
28374   if (firstnonemptyq < 0) {
28375     return (badface *) NULL;
28376   } else {
28377     // Return the first tetrahedron of the highest-priority queue.
28378     return tetquefront[firstnonemptyq];
28379   }
28380 }
28381 
28382 void tetgenmesh::dequeuebadtet()
28383 {
28384   badface *deadbadtet;
28385   int i;
28386 
28387   // If queues were empty last time topbadtetra() was called, do nothing.
28388   if (recentq >= 0) {
28389     // Find the tetrahedron last returned by topbadtetra().
28390     deadbadtet = tetquefront[recentq];
28391     // Remove the tetrahedron from the queue.
28392     tetquefront[recentq] = deadbadtet->nextitem;
28393     // If this queue is now empty, update the list of nonempty queues.
28394     if (deadbadtet == tetquetail[recentq]) {
28395       // Was this the highest-priority queue?
28396       if (firstnonemptyq == recentq) {
28397         // Yes; find the queue with next lower priority.
28398         firstnonemptyq = nextnonemptyq[firstnonemptyq];
28399       } else {
28400         // No; find the queue with next higher priority.
28401         i = recentq + 1;
28402         while (tetquefront[i] == (badface *) NULL) {
28403           i++;
28404         }
28405         nextnonemptyq[i] = nextnonemptyq[recentq];
28406       }
28407     }
28408     // Return the bad tetrahedron to the pool.
28409     badfacedealloc(badtetrahedrons, deadbadtet);
28410   }
28411 }
28412 
28414 //                                                                           //
28415 // checkseg4encroach()    Check a subsegment to see if it is encroached.     //
28416 //                                                                           //
28417 // A segment s is encroached if there is a vertex lies inside or on its dia- //
28418 // metral circumsphere, i.e., s faces an angle theta >= 90 degrees.          //
28419 //                                                                           //
28420 // If 'testpt' (p) != NULL, only test if 'testseg' (s) is encroached by it,  //
28421 // else, check all apexes of faces around s. Return TRUE if s is encroached. //
28422 // If and 'enqflag' is TRUE, add it into 'badsubsegs' if s is encroached.    //
28423 //                                                                           //
28424 // If 'prefpt' != NULL, it returns the reference point (defined in my paper) //
28425 // if it exists.  This point is will be used to split s.                     //
28426 //                                                                           //
28428 
28429 bool tetgenmesh::checkseg4encroach(face* testseg, point testpt, point* prefpt,
28430   bool enqflag)
28431 {
28432   badface *encsubseg;
28433   triface starttet, spintet;
28434   point eorg, edest, eapex, encpt;
28435   REAL cent[3], radius, dist, diff;
28436   REAL maxradius;
28437   bool enq;
28438   int hitbdry;
28439 
28440   enq = false;
28441   eorg = sorg(*testseg);
28442   edest = sdest(*testseg);
28443   cent[0] = 0.5 * (eorg[0] + edest[0]);
28444   cent[1] = 0.5 * (eorg[1] + edest[1]);
28445   cent[2] = 0.5 * (eorg[2] + edest[2]);
28446   radius = distance(cent, eorg);
28447 
28448   if (varconstraint && (areabound(*testseg) > 0.0)) {
28449     enq = (2.0 * radius) > areabound(*testseg);
28450   }
28451 
28452   if (!enq) {
28453     maxradius = 0.0;
28454     if (testpt == (point) NULL) {
28455       // Check if it is encroached by traversing all faces containing it.
28456       sstpivot(testseg, &starttet);
28457       eapex = apex(starttet);
28458       spintet = starttet;
28459       hitbdry = 0;
28460       do {
28461         dist = distance(cent, apex(spintet));
28462         diff = dist - radius;
28463         if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28464         if (diff <= 0.0) {
28465           // s is encroached.
28466           enq = true;
28467           if (prefpt != (point *) NULL) {
28468             // Find the reference point.
28469             encpt = apex(spintet);
28470             circumsphere(eorg, edest, encpt, NULL, NULL, &dist);
28471             if (dist > maxradius) {
28472               // Rememebr this point.
28473               *prefpt = encpt;
28474               maxradius = dist;
28475             }
28476           } else {
28477             break;
28478           }
28479         }
28480         if (!fnextself(spintet)) {
28481           hitbdry++;
28482           if (hitbdry < 2) {
28483             esym(starttet, spintet);
28484             if (!fnextself(spintet)) {
28485               hitbdry++;
28486             }
28487           }
28488         }
28489       } while (apex(spintet) != eapex && (hitbdry < 2));
28490     } else {
28491       // Only check if 'testseg' is encroached by 'testpt'.
28492       dist = distance(cent, testpt);
28493       diff = dist - radius;
28494       if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28495       enq = (diff <= 0.0);
28496     }
28497   }
28498 
28499   if (enq && enqflag) {
28500     if (b->verbose > 2) {
28501       printf("    Queuing encroaching subsegment (%d, %d).\n",
28502              pointmark(eorg), pointmark(edest));
28503     }
28504     encsubseg = (badface *) badsubsegs->alloc();
28505     encsubseg->ss = *testseg;
28506     encsubseg->forg = eorg;
28507     encsubseg->fdest = edest;
28508     encsubseg->foppo = (point) NULL; // Not used.
28509     // Set the pointer of 'encsubseg' into 'testseg'.  It has two purposes:
28510     //   (1) We can regonize it is encroached; (2) It is uniquely queued.
28511     setshell2badface(encsubseg->ss, encsubseg);
28512   }
28513 
28514   return enq;
28515 }
28516 
28518 //                                                                           //
28519 // checksub4encroach()    Check a subface to see if it is encroached.        //
28520 //                                                                           //
28521 // A subface f is encroached if there is a vertex inside or on its diametral //
28522 // circumsphere.                                                             //
28523 //                                                                           //
28524 // If 'testpt (p) != NULL', test if 'testsub' (f) is encroached by it, else, //
28525 // test if f is encroached by one of the two opposites of the adjacent tets. //
28526 // Return TRUE if f is encroached and queue it if 'enqflag' is set.          //
28527 //                                                                           //
28529 
28530 bool tetgenmesh::checksub4encroach(face* testsub, point testpt, bool enqflag)
28531 {
28532   triface abuttet;
28533   point pa, pb, pc, encpt;
28534   REAL A[4][4], rhs[4], D;
28535   REAL cent[3], area;
28536   REAL radius, dist, diff;
28537   bool enq;
28538   int indx[4];
28539   int quenumber;
28540 
28541   enq = false;
28542   radius = 0.0;
28543   encpt = (point) NULL;
28544 
28545   pa = sorg(*testsub);
28546   pb = sdest(*testsub);
28547   pc = sapex(*testsub);
28548 
28549   // Compute the coefficient matrix A (3x3).
28550   A[0][0] = pb[0] - pa[0];
28551   A[0][1] = pb[1] - pa[1];
28552   A[0][2] = pb[2] - pa[2]; // vector V1 (pa->pb)
28553   A[1][0] = pc[0] - pa[0];
28554   A[1][1] = pc[1] - pa[1];
28555   A[1][2] = pc[2] - pa[2]; // vector V2 (pa->pc)
28556   cross(A[0], A[1], A[2]); // vector V3 (V1 X V2)
28557 
28558   if (varconstraint && (areabound(*testsub) > 0.0)) {
28559     // Check if the subface has too big area.
28560     area = 0.5 * sqrt(dot(A[2], A[2]));
28561     enq = area > areabound(*testsub);
28562     if (enq) {
28563       quenumber = 2; // A queue of subfaces having too big area.
28564     }
28565   }
28566 
28567   // Compute the right hand side vector b (3x1).
28568   rhs[0] = 0.5 * dot(A[0], A[0]);
28569   rhs[1] = 0.5 * dot(A[1], A[1]);
28570   rhs[2] = 0.0;
28571   // Solve the 3 by 3 equations use LU decomposition with partial pivoting
28572   //   and backward and forward substitute..
28573   if (lu_decmp(A, 3, indx, &D, 0)) {
28574     lu_solve(A, 3, indx, rhs, 0);
28575     cent[0] = pa[0] + rhs[0];
28576     cent[1] = pa[1] + rhs[1];
28577     cent[2] = pa[2] + rhs[2];
28578     radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
28579   }
28580 
28581   if (!enq) {
28582     // Check if the subface is encroached.
28583     if (testpt == (point) NULL) {
28584       stpivot(*testsub, abuttet);
28585       if (abuttet.tet != dummytet) {
28586         dist = distance(cent, oppo(abuttet));
28587         diff = dist - radius;
28588         if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28589         enq = (diff <= 0.0);
28590         if (enq) encpt = oppo(abuttet);
28591       }
28592       if (!enq) {
28593         sesymself(*testsub);
28594         stpivot(*testsub, abuttet);
28595         if (abuttet.tet != dummytet) {
28596           dist = distance(cent, oppo(abuttet));
28597           diff = dist - radius;
28598           if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28599           enq = (diff <= 0.0);
28600           if (enq) encpt = oppo(abuttet);
28601         }
28602       }
28603     } else {
28604       dist = distance(cent, testpt);
28605       diff = dist - radius;
28606       if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28607       enq = (diff <= 0.0);
28608     }
28609     if (enq) {
28610       quenumber = 0; // A queue of encroached subfaces.
28611     }
28612   }
28613 
28614   if (enq && enqflag) {
28615     enqueueencsub(testsub, encpt, quenumber, cent);
28616   }
28617 
28618   return enq;
28619 }
28620 
28622 //                                                                           //
28623 // checktet4badqual()    Test a tetrahedron for quality measures.            //
28624 //                                                                           //
28625 // Tests a tetrahedron to see if it satisfies the minimum ratio condition    //
28626 // and the maximum volume condition. Tetrahedra that aren't upto spec are    //
28627 // added to the bad tetrahedron queue.                                       //
28628 //                                                                           //
28630 
28631 bool tetgenmesh::checktet4badqual(triface* testtet, bool enqflag)
28632 {
28633   point pa, pb, pc, pd, pe1, pe2;
28634   REAL vda[3], vdb[3], vdc[3];
28635   REAL vab[3], vbc[3], vca[3];
28636   REAL N[4][3], A[4][4], rhs[4], D;
28637   REAL elen[6], circumcent[3];
28638   REAL bicent[3], offcent[3];
28639   offcent[0] = 0.0; // Just to avoid uninitialised value warnings.
28640   offcent[1] = 0.0; // Just to avoid uninitialised value warnings.
28641   offcent[2] = 0.0; // Just to avoid uninitialised value warnings.
28642   REAL volume, L, cosd;
28643   REAL radius2, smlen2, ratio2;
28644   REAL dist, sdist, split;
28645   bool enq;
28646   int indx[4];
28647   int sidx, i, j;
28648 
28649   pa = (point) testtet->tet[4];
28650   pb = (point) testtet->tet[5];
28651   pc = (point) testtet->tet[6];
28652   pd = (point) testtet->tet[7];
28653 
28654   // Get the edge vectors vda: d->a, vdb: d->b, vdc: d->c.
28655   // Set the matrix A = [vda, vdb, vdc]^T.
28656   for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
28657   for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
28658   for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
28659   // Get the rest edge vectors
28660   for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
28661   for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i];
28662   for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i];
28663 
28664   // Lu-decompose the matrix A.
28665   lu_decmp(A, 3, indx, &D, 0);
28666   // Get the volume of abcd.
28667   volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
28668   if (volume < 0.0) volume = -volume;
28669   // Check the radiu-edge ratio of the tet.
28670   rhs[0] = 0.5 * dot(vda, vda);
28671   rhs[1] = 0.5 * dot(vdb, vdb);
28672   rhs[2] = 0.5 * dot(vdc, vdc);
28673   lu_solve(A, 3, indx, rhs, 0);
28674   // Get the circumcenter.
28675   for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
28676   // Get the square of the circumradius.
28677   radius2 = dot(rhs, rhs);
28678   // Find the square of the shortest edge length.
28679   elen[0] = dot(vda, vda);
28680   elen[1] = dot(vdb, vdb);
28681   elen[2] = dot(vdc, vdc);
28682   elen[3] = dot(vab, vab);
28683   elen[4] = dot(vbc, vbc);
28684   elen[5] = dot(vca, vca);
28685   smlen2 = elen[0]; sidx = 0;
28686   for (i = 1; i < 6; i++) {
28687     if (smlen2 > elen[i]) { smlen2 = elen[i]; sidx = i; }
28688   }
28689   // Calculate the square of radius-edge ratio.
28690   ratio2 = radius2 / smlen2;
28691   // Check whether the ratio is smaller than permitted.
28692   enq = ratio2 > b->goodratio;
28693   if (!enq) {
28694     // abcd has good ratio.
28695     // ratio2 = 0.0;
28696     // if (b->offcenter) {
28697       // Test if it is a sliver.
28698       // Compute the 4 face normals (N[0], ..., N[3]).
28699       for (j = 0; j < 3; j++) {
28700         for (i = 0; i < 3; i++) rhs[i] = 0.0;
28701         rhs[j] = 1.0;  // Positive means the inside direction
28702         lu_solve(A, 3, indx, rhs, 0);
28703         for (i = 0; i < 3; i++) N[j][i] = rhs[i];
28704       }
28705       // Get the fourth normal by summing up the first three.
28706       for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
28707       // Normalized the normals.
28708       for (i = 0; i < 4; i++) {
28709         L = sqrt(dot(N[i], N[i]));
28710         if (L > 0.0) {
28711           for (j = 0; j < 3; j++) N[i][j] /= L;
28712         }
28713       }
28714       // N[0] is the normal of face bcd. Test the dihedral angles at edge
28715       //   cd, bd, and bc to see if they are too small or too big.
28716       for (i = 1; i < 4 && !enq; i++) {
28717         cosd = -dot(N[0], N[i]); // Edge cd, bd, bc.
28718         enq = cosd > cosmindihed;
28719       }
28720       if (!enq) {
28721         for (i = 2; i < 4 && !enq; i++) {
28722           cosd = -dot(N[1], N[i]); // Edge ad, ac
28723           enq = cosd > cosmindihed;
28724         }
28725         if (!enq) {
28726           cosd = -dot(N[2], N[3]); // Edge ab
28727           enq = cosd > cosmindihed;
28728         }
28729       }
28730     // }
28731   } else if (b->offcenter) {
28732     // abcd has bad-quality. Use off-center instead of circumcenter.
28733     switch (sidx) {
28734     case 0: // edge da.
28735       pe1 = pd; pe2 = pa; break;
28736     case 1: // edge db.
28737       pe1 = pd; pe2 = pb; break;
28738     case 2: // edge dc.
28739       pe1 = pd; pe2 = pc; break;
28740     case 3: // edge ab.
28741       pe1 = pa; pe2 = pb; break;
28742     case 4: // edge bc.
28743       pe1 = pb; pe2 = pc; break;
28744     case 5: // edge ca.
28745       pe1 = pc; pe2 = pa; break;
28746     default:
28747       pe1 = pe2 = (point) NULL; // Avoid a compile warning.
28748     }
28749     // The shortest edge is e1->e2.
28750     for (i = 0; i < 3; i++) bicent[i] = 0.5 * (pe1[i] + pe2[i]);
28751     dist = distance(bicent, circumcent);
28752     // sdist = sqrt(smlen2) * sin(PI / 3.0); // A icoso-triangle.
28753     // The following formulae is from
28754     sdist = b->alpha3 * (b->minratio+sqrt(b->goodratio-0.25))* sqrt(smlen2);
28755     split = sdist / dist;
28756     if (split > 1.0) split = 1.0;
28757     // Get the off-center.
28758     for (i = 0; i < 3; i++) {
28759       offcent[i] = bicent[i] + split * (circumcent[i] - bicent[i]);
28760     }
28761   }
28762 
28763   if (!enq && (b->varvolume || b->fixedvolume)) {
28764     // Check if the tet has too big volume.
28765     enq = b->fixedvolume && (volume > b->maxvolume);
28766     if (!enq && b->varvolume) {
28767       enq = (volume > volumebound(testtet->tet)) &&
28768             (volumebound(testtet->tet) > 0.0);
28769     }
28770   }
28771 
28772   if (!enq) {
28773     // Check if the user-defined sizing function is satisfied.
28774     if (b->metric) {
28775       // assert(b->alpha1 > 0.0);
28776       sdist = sqrt(radius2) / b->alpha1;
28777       for (i = 0; i < 4; i++) {
28778         pa = (point) testtet->tet[4 + i];
28779         // Get the indicated size of p.
28780         dist = pa[pointmtrindex]; // dist = b->alpha1 * pa[pointmtrindex];
28781         enq = ((dist < sdist) && (dist > 0.0));
28782         if (enq) break; // It is bad wrt. a node constraint.
28783         // *** Experiment ! Stop test if c is inside H(a).
28784         // if ((dist > 0.0) && (dist > sdist)) break;
28785       }
28786       // *** Experiment !
28787       // enq = (i == 4); // Does c lies outside all sparse-ball?
28788     } // if (b->metric)
28789   }
28790 
28791   if (enq && enqflag) {
28792     if (b->offcenter && (ratio2 > b->goodratio)) {
28793       for (i = 0; i < 3; i++) circumcent[i] = offcent[i];
28794     }
28795     enqueuebadtet(testtet, ratio2, circumcent);
28796   }
28797 
28798   return enq;
28799 }
28800 
28802 //                                                                           //
28803 // acceptsegpt()    Check if a segment point can be inserted or not.         //
28804 //                                                                           //
28805 // Segment(ab) is indicated to be split by a point p (\in ab). This routine  //
28806 // decides whether p can be inserted or not.                                 //
28807 //                                                                           //
28808 // p can not be inserted either the '-Y' option is used and ab is a hull     //
28809 // segment or '-YY' option is used.                                          //
28810 //                                                                           //
28811 // p can be inserted if it is in one of the following cases:                 //
28812 //   (1) if L = |a - b| is too long wrt the edge constraint; or              //
28813 //   (2) if |x - p| > \alpha_2 H(x) for x = a, b; or                         //
28814 //   (3) if 'refpt' != NULL.                                                 //
28815 //                                                                           //
28817 
28818 bool tetgenmesh::acceptsegpt(point segpt, point refpt, face* splitseg)
28819 {
28820   point p[2];
28821   REAL L, lfs;
28822   int i, j;
28823 
28824   if (b->nobisect == 1) {
28825     // '-Y'. It can not be split if it is on the hull.
28826     triface spintet;
28827     point pc;
28828     sstpivot(splitseg, &spintet);
28829     assert(spintet.tet != dummytet);
28830     pc = apex(spintet);
28831     do {
28832       if (!fnextself(spintet)) {
28833         // Meet a boundary face - s is on the hull.
28834         return false;
28835       }
28836     } while (pc != apex(spintet));
28837   } else if (b->nobisect > 1) {
28838     // '-YY'. Do not split it.
28839     return false;
28840   }
28841 
28842   p[0] = sorg(*splitseg);
28843   p[1] = sdest(*splitseg);
28844   if (varconstraint && (areabound(*splitseg) > 0)) {
28845     lfs = areabound(*splitseg);
28846     L = distance(p[0], p[1]);
28847     if (L > lfs) {
28848       return true; // case (1)
28849     }
28850   }
28851 
28852   j = 0; // Use j to count the number of inside balls.
28853   for (i = 0; i < 2; i++) {
28854     // Check if p is inside the protect ball of q.
28855     if (p[i][pointmtrindex] > 0.0) {
28856       lfs = b->alpha2 * p[i][pointmtrindex];
28857       L = distance(p[i], segpt);
28858       if (L < lfs) j++; // p is inside ball.
28859     }
28860   }
28861   if (j == 0) return true; // case (3).
28862 
28863   // If 'refpt' != NULL, force p to be inserted.
28864   if (refpt != (point) NULL) {
28865     cdtenforcesegpts++;
28866     return true;
28867   }
28868 
28869   // Do not split it.
28870   rejsegpts++;
28871   return false;
28872 }
28873 
28875 //                                                                           //
28876 // acceptfacpt()    Check if a facet point can be inserted or not.           //
28877 //                                                                           //
28878 // 'subceillist' is CBC(p). 'verlist' (V) is empty on input, it returns the  //
28879 // set of vertices of CBC(p).                                                //
28880 //                                                                           //
28881 // p can not be inserted either the '-Y' option is used and the facet is on  //
28882 // the hull or '-YY' option is used.                                         //
28883 //                                                                           //
28884 // p can be inserted if |p - v| > \alpha_2 H(v), for all v \in V.            //
28885 //                                                                           //
28887 
28888 bool tetgenmesh::acceptfacpt(point facpt, list* subceillist, list* verlist)
28889 {
28890   face *testsh;
28891   point p[2], ploop;
28892   REAL L, lfs;
28893   int idx, i, j;
28894 
28895   if (b->nobisect == 1) {
28896     // '-Y'. p can not be inserted if CBC(p) is on the hull.
28897     triface testtet;
28898     testsh = (face *)(* subceillist)[0];
28899     stpivot(*testsh, testtet);
28900     if (testtet.tet != dummytet) {
28901       sesymself(*testsh);
28902       stpivot(*testsh, testtet);
28903     }
28904     if (testtet.tet == dummytet) return false;
28905   } else if (b->nobisect > 1) {
28906     // '-YY'. Do not split s.
28907     return false;
28908   }
28909 
28910   // Collect the vertices of CBC(p), save them in V.
28911   for (i = 0; i < subceillist->len(); i++) {
28912     testsh = (face *)(* subceillist)[i];
28913     p[0] = sorg(*testsh);
28914     p[1] = sdest(*testsh);
28915     for (j = 0; j < 2; j++) {
28916       idx = pointmark(p[j]);
28917       if (idx >= 0) {
28918         setpointmark(p[j], -idx - 1);
28919         verlist->append(&(p[j]));
28920       }
28921     }
28922   }
28923 
28924   j = 0; // Use j to count the number of inside balls.
28925   for (i = 0; i < verlist->len(); i++) {
28926     ploop = * (point *)(* verlist)[i];
28927     // Uninfect q.
28928     idx = pointmark(ploop);
28929     setpointmark(ploop, -(idx + 1));
28930     // Check if p is inside the protect ball of q.
28931     if (ploop[pointmtrindex] > 0.0) {
28932       lfs = b->alpha2 * ploop[pointmtrindex];
28933       L = distance(ploop, facpt);
28934       if (L < lfs) j++; // p is inside ball.
28935     }
28936   }
28937   verlist->clear();
28938 
28939   if (j == 0) return true; // case (3).
28940 
28941   rejsubpts++;
28942   return false;
28943 }
28944 
28946 //                                                                           //
28947 // acceptvolpt()    Check if a volume point can be inserted or not.          //
28948 //                                                                           //
28949 // 'ceillist' is B(p).  'verlist' (V) is empty on input, it returns the set  //
28950 // of vertices of B(p).                                                      //
28951 //                                                                           //
28952 // p can be split if |p - v| > \alpha_2 H(v), for all v \in V.               //
28953 //                                                                           //
28955 
28956 bool tetgenmesh::acceptvolpt(point volpt, list* ceillist, list* verlist)
28957 {
28958   triface* testtet;
28959   point p[3], ploop;
28960   REAL L, lfs;
28961   int idx, i, j;
28962 
28963   // Collect the vertices of CBC(p), save them in V.
28964   for (i = 0; i < ceillist->len(); i++) {
28965     testtet = (triface *)(* ceillist)[i];
28966     p[0] = org(*testtet);
28967     p[1] = dest(*testtet);
28968     p[2] = apex(*testtet);
28969     for (j = 0; j < 3; j++) {
28970       idx = pointmark(p[j]);
28971       if (idx >= 0) {
28972         setpointmark(p[j], -idx - 1);
28973         verlist->append(&(p[j]));
28974       }
28975     }
28976   }
28977 
28978   j = 0; // Use j to counte the number of inside balls.
28979   for (i = 0; i < verlist->len(); i++) {
28980     ploop = * (point *)(* verlist)[i];
28981     // Uninfect q.
28982     idx = pointmark(ploop);
28983     setpointmark(ploop, -(idx + 1));
28984     // Check if p is inside the protect ball of q.
28985     if (ploop[pointmtrindex] > 0.0) {
28986       lfs = b->alpha2 * ploop[pointmtrindex];
28987       L = distance(ploop, volpt);
28988       if (L < lfs) j++; // p is inside the protect ball.
28989     }
28990   }
28991   verlist->clear();
28992 
28993   if (j == 0) return true; // case (2).
28994 
28995   rejtetpts++;
28996   return false;
28997 }
28998 
29000 //                                                                           //
29001 // getsplitpoint()    Get the inserting point in a segment.                  //
29002 //                                                                           //
29004 
29005 void tetgenmesh::getsplitpoint(point e1, point e2, point refpt, point newpt)
29006 {
29007   point ei, ej;
29008   REAL split, L, d1, d2, ps, rs;
29009   bool acutea, acuteb;
29010   int i;
29011 
29012   if (refpt != (point) NULL) {
29013     // Use the CDT rules to split the segment.
29014     acutea = (pointtype(e1) == ACUTEVERTEX);
29015     acuteb = (pointtype(e2) == ACUTEVERTEX);
29016     if (acutea ^ acuteb) {
29017       // Only one endpoint is acute. Use rule-2 or rule-3.
29018       ei = acutea ? e1 : e2;
29019       ej = acutea ? e2 : e1;
29020       L = distance(ei, ej);
29021       // Apply rule-2.
29022       d1 = distance(ei, refpt);
29023       split = d1 / L;
29024       for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29025       // Check if rule-3 is needed.
29026       d2 = distance(refpt, newpt);
29027       if (d2 > (L - d1)) {
29028         // Apply rule-3.
29029         if ((d1 - d2) > (0.5 * d1)) {
29030           split = (d1 - d2) / L;
29031         } else {
29032           split = 0.5 * d1 / L;
29033         }
29034         for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29035         if (b->verbose > 1) {
29036           printf("    Found by rule-3:");
29037         }
29038         r3count++;
29039       } else {
29040         if (b->verbose > 1) {
29041           printf("    Found by rule-2:");
29042         }
29043         r2count++;
29044       }
29045       if (b->verbose > 1) {
29046         printf(" center %d, split = %.12g.\n", pointmark(ei), split);
29047       }
29048       // Add a random perturbation on newpt.
29049       d1 = distance(ei, newpt);
29050       d2 = distance(newpt, refpt);
29051       ps = randgenerator(d2 * b->epsilon2 * 1e+2);
29052       rs = ps / d1;
29053       // Perturb newpt away from ei.
29054       for (i = 0; i < 3; i++) newpt[i] = ei[i] + (1.0+rs) * (newpt[i] - ei[i]);
29055     } else {
29056       // Both endpoints are acute or not. Split it at the middle.
29057       for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29058       // Add a random perturbation on newpt.
29059       d1 = 0.5 * distance(e1, e2);
29060       ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29061       rs = ps / d1;
29062       for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29063     }
29064   } else {
29065     // Split the segment at its midpoint.
29066     for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29067     // Add a random perturbation on newpt.
29068     d1 = 0.5 * distance(e1, e2);
29069     ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29070     rs = ps / d1;
29071     for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29072   }
29073 }
29074 
29076 //                                                                           //
29077 // shepardinterpolation()    Interpolate the local size of a newpoint.       //
29078 //                                                                           //
29079 // The classical Shepard interoplation (inversed weighted distance) is used. //
29080 // (With the choice p = 2).                                                  //
29081 //                                                                           //
29082 // 'verlist' contains a list vertices neighboring to 'newpt'.                //
29083 //                                                                           //
29085 
29086 void tetgenmesh::shepardinterpolate(point newpt, list *verlist)
29087 {
29088   point neipt;
29089   REAL *weights, sumweight;
29090   REAL vec[3];
29091   int i, j;
29092 
29093   weights = new REAL[verlist->len()];
29094   sumweight = 0.0;
29095 
29096   // Calculate the weight of each point.
29097   for (i = 0; i < verlist->len(); i++) {
29098     neipt = * (point *)(* verlist)[i];
29099     for (j = 0; j < 3; j++) vec[j] = neipt[j] - newpt[j];
29100     weights[i] = 1.0 / dot(vec, vec);
29101     sumweight += weights[i];
29102   }
29103   // Interpolate.
29104   newpt[pointmtrindex] = 0.0;
29105   for (i = 0; i < verlist->len(); i++) {
29106     neipt = * (point *)(* verlist)[i];
29107     newpt[pointmtrindex] += (weights[i] * neipt[pointmtrindex]) / sumweight;
29108   }
29109 
29110   delete [] weights;
29111 }
29112 
29114 //                                                                           //
29115 // setnewpointsize()    Set the size for a new point.                        //
29116 //                                                                           //
29117 // The size of the new point p is interpolated either from a background mesh //
29118 // (b->bgmesh) or from the two input endpoints.                              //
29119 //                                                                           //
29121 
29122 void tetgenmesh::setnewpointsize(point newpt, point e1, point e2)
29123 {
29124   if (b->metric) {
29125     // Interpolate the point size in a background mesh.
29126     triface bgmtet;
29127     // Get a tet in background mesh for locating p.
29128     decode(point2bgmtet(e1), bgmtet);
29129     p1interpolatebgm(newpt, &bgmtet, NULL);
29130   } else {
29131     if (e2 != (point) NULL) {
29132       // Interpolate the size between the two endpoints.
29133       REAL split, l, d;
29134       l = distance(e1, e2);
29135       d = distance(e1, newpt);
29136       split = d / l;
29137 #ifdef SELF_CHECK
29138       // Check if e1 and e2 are endpoints of a sharp segment.
29139       assert(e1[pointmtrindex] > 0.0);
29140       assert(e2[pointmtrindex] > 0.0);
29141 #endif
29142       newpt[pointmtrindex] = (1.0 - split) * e1[pointmtrindex]
29143                            + split * e2[pointmtrindex];
29144     }
29145   }
29146 }
29147 
29149 //                                                                           //
29150 // splitencseg()    Split an enc-seg and recover the Delaunayness by flips.  //
29151 //                                                                           //
29153 
29154 void tetgenmesh::splitencseg(point newpt, face* splitseg, list* tetlist,
29155   list* sublist, list* verlist, queue* flipque, bool chkencsub, bool chkbadtet,
29156   bool optflag)
29157 {
29158   list *mytetlist;
29159   queue *myflipque;
29160   triface starttet;
29161   face startsh, spinsh, checksh;
29162   int i;
29163 
29164   mytetlist = NULL;
29165   myflipque = NULL;
29166 
29167   if (optflag) {
29168     mytetlist = new list(sizeof(triface), NULL, 1024);
29169     myflipque = new queue(sizeof(badface));
29170     tetlist = mytetlist;
29171     flipque = myflipque;
29172   }
29173 
29174   // Use the base orientation (important in this routine).
29175   splitseg->shver = 0;
29176   // Insert p, this should always success.
29177   sstpivot(splitseg, &starttet);
29178   splittetedge(newpt, &starttet, flipque);
29179   // Remove locally non-Delaunay faces by flipping.
29180   flip(flipque, NULL); // lawson(NULL, flipque);
29181 
29182   if (!optflag) {
29183     // Check the two new subsegs to see if they're encroached (not by p).
29184     for (i = 0; i < 2; i++) {
29185       if (!shell2badface(*splitseg)) {
29186         checkseg4encroach(splitseg, NULL, NULL, true);
29187       }
29188       if (i == 1) break; // Two new segs have been checked.
29189       senextself(*splitseg);
29190       spivotself(*splitseg);
29191 #ifdef SELF_CHECK
29192       assert(splitseg->sh != (shellface *) NULL);
29193 #endif
29194       splitseg->shver = 0;
29195     }
29196     // Check the new subfaces to see if they're encroached (not by p).
29197     if (chkencsub) {
29198       spivot(*splitseg, startsh);
29199       spinsh = startsh;
29200       do {
29201         sublist->append(&spinsh);
29202         formstarpolygon(newpt, sublist, verlist);
29203         for (i = 0; i < sublist->len(); i++) {
29204           checksh = * (face *)(* sublist)[i];
29205           if (!shell2badface(checksh)) {
29206             checksub4encroach(&checksh, NULL, true);
29207           }
29208         }
29209         sublist->clear();
29210         if (verlist) verlist->clear();
29211         spivotself(spinsh);
29212       } while (spinsh.sh != startsh.sh);
29213     }
29214   } // if (!optflag)
29215 
29216   // Collect the new tets connecting at p.
29217   sstpivot(splitseg, &starttet);
29218   tetlist->append(&starttet);
29219   formstarpolyhedron(newpt, tetlist, verlist, true);
29220 
29221   if (!optflag) {
29222     // Check if p encroaches adjacent segments.
29223     tallencsegs(newpt, 1, &tetlist);
29224     if (chkencsub) {
29225       // Check if p encroaches adjacent subfaces.
29226       tallencsubs(newpt, 1, &tetlist);
29227     }
29228     if (chkbadtet) {
29229       // Check if there are new bad quality tets at p.
29230       for (i = 0; i < tetlist->len(); i++) {
29231         starttet = * (triface *)(* tetlist)[i];
29232         checktet4badqual(&starttet, true);
29233       }
29234     }
29235     tetlist->clear();
29236   } else {
29237     // Check if new tets are non-optimal.
29238     for (i = 0; i < tetlist->len(); i++) {
29239       starttet = * (triface *)(* tetlist)[i];
29240       checktet4opt(&starttet, true);
29241     }
29242     delete mytetlist;
29243     delete myflipque;
29244   }
29245 }
29246 
29248 //                                                                           //
29249 // tallencsegs()    Check for encroached segments and save them in list.     //
29250 //                                                                           //
29251 // If 'testpt' (p) != NULL, only check if segments are encroached by p, else,//
29252 // check all the nearby mesh vertices.                                       //
29253 //                                                                           //
29254 // If 'ceillists' (B_i(p)) != NULL, there are 'n' B_i(p)s, only check the    //
29255 // segments which are on B_i(p)s, else, check the entire list of segments    //
29256 // (in the pool 'this->subsegs').                                            //
29257 //                                                                           //
29259 
29260 bool tetgenmesh::tallencsegs(point testpt, int n, list **ceillists)
29261 {
29262   list *ceillist;
29263   triface ceiltet;
29264   face checkseg;
29265   long oldencnum;
29266   int i, j, k;
29267 
29268   // Remember the current number of encroached segments.
29269   oldencnum = badsubsegs->items;
29270 
29271   if (ceillists != (list **) NULL) {
29272     for (k = 0; k < n; k++) {
29273       ceillist = ceillists[k];
29274       // Check the segments on B_i(p).
29275       for (i = 0; i < ceillist->len(); i++) {
29276         ceiltet = * (triface *)(* ceillist)[i];
29277         ceiltet.ver = 0;
29278         for (j = 0; j < 3; j++) {
29279           tsspivot(&ceiltet, &checkseg);
29280           if (checkseg.sh != dummysh) {
29281             // Found a segment. Test it if it isn't in enc-list.
29282             if (!shell2badface(checkseg)) {
29283               checkseg4encroach(&checkseg, testpt, NULL, true);
29284             }
29285           }
29286           enextself(ceiltet);
29287         }
29288       }
29289     }
29290   } else {
29291     // Check the entire list of segments.
29292     subsegs->traversalinit();
29293     checkseg.sh = shellfacetraverse(subsegs);
29294     while (checkseg.sh != (shellface *) NULL) {
29295       // Test it if it isn't in enc-list.
29296       if (!shell2badface(checkseg)) {
29297         checkseg4encroach(&checkseg, testpt, NULL, true);
29298       }
29299       checkseg.sh = shellfacetraverse(subsegs);
29300     }
29301   }
29302 
29303   return (badsubsegs->items > oldencnum);
29304 }
29305 
29307 //                                                                           //
29308 // tallencsubs()    Find all encroached subfaces and save them in list.      //
29309 //                                                                           //
29310 // If 'testpt' (p) != NULL, only check if subfaces are encroached by p, else,//
29311 // check the adjacent vertices of subfaces.                                  //
29312 //                                                                           //
29313 // If 'ceillists' (B_i(p)) != NULL, there are 'n' B_i(p)s, only check the    //
29314 // subfaces which are on B_i(p)s, else, check the entire list of subfaces    //
29315 // (in the pool 'this->subfaces').                                           //
29316 //                                                                           //
29318 
29319 bool tetgenmesh::tallencsubs(point testpt, int n, list** ceillists)
29320 {
29321   list *ceillist;
29322   triface ceiltet;
29323   face checksh;
29324   long oldencnum;
29325   int i, k;
29326 
29327   // Remember the current number of encroached segments.
29328   oldencnum = badsubfaces->items;
29329 
29330   if (ceillists != (list **) NULL) {
29331     for (k = 0; k < n; k++) {
29332       ceillist = ceillists[k];
29333       // Check the subfaces on B_i(p).
29334       for (i = 0; i < ceillist->len(); i++) {
29335         ceiltet = * (triface *)(* ceillist)[i];
29336         tspivot(ceiltet, checksh);
29337         if (checksh.sh != dummysh) {
29338           // Found a subface. Test it if it isn't in enc-list.
29339           if (!shell2badface(checksh)) {
29340             checksub4encroach(&checksh, testpt, true);
29341           }
29342         }
29343       }
29344     }
29345   } else {
29346     // Check the entire list of subfaces.
29347     subfaces->traversalinit();
29348     checksh.sh = shellfacetraverse(subfaces);
29349     while (checksh.sh != (shellface *) NULL) {
29350       // Test it if it isn't in enc-list.
29351       if (!shell2badface(checksh)) {
29352         checksub4encroach(&checksh, testpt, true);
29353       }
29354       checksh.sh = shellfacetraverse(subfaces);
29355     }
29356   }
29357 
29358   return (badsubfaces->items > oldencnum);
29359 }
29360 
29362 //                                                                           //
29363 // tallbadtetrahedrons()    Queue all the bad-quality tetrahedra in the mesh.//
29364 //                                                                           //
29366 
29367 void tetgenmesh::tallbadtetrahedrons()
29368 {
29369   triface tetloop;
29370 
29371   tetrahedrons->traversalinit();
29372   tetloop.tet = tetrahedrontraverse();
29373   while (tetloop.tet != (tetrahedron *) NULL) {
29374     checktet4badqual(&tetloop, true);
29375     tetloop.tet = tetrahedrontraverse();
29376   }
29377 }
29378 
29380 //                                                                           //
29381 // repairencsegs()    Repair (split) all the encroached segments.            //
29382 //                                                                           //
29383 // Each encroached segment is repaired by splitting it - inserting a vertex  //
29384 // at or near its midpoint.  Newly inserted vertices may encroach upon other //
29385 // subsegments, these are also repaired.                                     //
29386 //                                                                           //
29387 // 'chkencsub' and 'chkbadtet' are two flags that specify whether one should //
29388 // take note of new encroaced subfaces and bad quality tets that result from //
29389 // inserting vertices to repair encroached subsegments.                      //
29390 //                                                                           //
29392 
29393 void tetgenmesh::repairencsegs(bool chkencsub, bool chkbadtet)
29394 {
29395   list **tetlists, **ceillists;
29396   list **sublists, **subceillists;
29397   list *tetlist, *sublist;
29398   queue *flipque;
29399   badface *encloop;
29400   face splitseg, symsplitseg;
29401   point newpt, sympt, refpt;
29402   point e1, e2;
29403   enum locateresult symloc;
29404   int nmax, n, i, j;
29405 
29406   ceillists = NULL;
29407   flipque = NULL;
29408   subceillists = NULL;
29409   sublist = NULL;
29410   sublists = NULL;
29411   tetlist = NULL;
29412   tetlists = NULL;
29413 
29414   n = 0;
29415   nmax = 128;
29416   if (!b->fliprepair) {
29417     tetlists = new list*[nmax];
29418     ceillists = new list*[nmax];
29419     sublists = new list*[nmax];
29420     subceillists = new list*[nmax];
29421   } else {
29422     tetlist = new list(sizeof(triface), NULL, 1024);
29423     sublist = new list(sizeof(face), NULL, 256);
29424     flipque = new queue(sizeof(badface));
29425   }
29426 
29427   // Loop until the pool 'badsubsegs' is empty. Note that steinerleft == -1
29428   //   if an unlimited number of Steiner points is allowed.
29429   while ((badsubsegs->items > 0) && (steinerleft != 0)) {
29430     badsubsegs->traversalinit();
29431     encloop = badfacetraverse(badsubsegs);
29432     while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
29433       // Get an encroached subsegment s.
29434       splitseg = encloop->ss;
29435       // Clear the in-queue flag in s.
29436       setshell2badface(splitseg, NULL);
29437       if ((sorg(splitseg) == encloop->forg) &&
29438           (sdest(splitseg) == encloop->fdest)) {
29439         if (b->verbose > 1) {
29440           printf("  Get an enc-seg (%d, %d)\n", pointmark(encloop->forg),
29441                  pointmark(encloop->fdest));
29442         }
29443         refpt = (point) NULL;
29444         if (b->conformdel) {
29445           // Look for a reference point.
29446           checkseg4encroach(&splitseg, NULL, &refpt, false);
29447         }
29448         // Create the new point p (at the middle of s).
29449         makepoint(&newpt);
29450         getsplitpoint(encloop->forg, encloop->fdest, refpt, newpt);
29451         setpointtype(newpt, FREESEGVERTEX);
29452         setpoint2sh(newpt, sencode(splitseg));
29453         // Decide whether p can be inserted or not.
29454         if (acceptsegpt(newpt, refpt, &splitseg)) {
29455           // Is there periodic boundary condition?
29456           if (checkpbcs) {
29457             // Insert points on other segments of incident pbcgroups.
29458             i = shellmark(splitseg) - 1;
29459             for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
29460               makepoint(&sympt);
29461               symloc = getsegpbcsympoint(newpt, &splitseg, sympt, &symsplitseg,
29462                                          segpglist[j]);
29463               if (symloc == ONEDGE) {
29464                 if (symsplitseg.sh != splitseg.sh) {
29465                   // Insert sympt.
29466                   setpointtype(sympt, FREESEGVERTEX);
29467                   setpoint2sh(sympt, sencode(symsplitseg));
29468                   // Save the endpoints of the seg for size interpolation.
29469                   e1 = sorg(symsplitseg);
29470                   if (shelltype(symsplitseg) == SHARP) {
29471                     e2 = sdest(symsplitseg);
29472                   } else {
29473                     e2 = (point) NULL; // No need to do size interpolation.
29474                   }
29475                   if (!b->fliprepair) {
29476                     // Form BC(symp), B(symp), CBC(symp)s, C(symp)s.
29477                     formbowatcavity(sympt, &symsplitseg, NULL, &n, &nmax,
29478                       sublists, subceillists, tetlists, ceillists);
29479                     // Validate BC(symp), B(symp), CBC(symp)s, C(symp)s.
29480                     if (trimbowatcavity(sympt, &symsplitseg, n, sublists,
29481                           subceillists, tetlists, ceillists, -1.0)) {
29482                       bowatinsertsite(sympt, &symsplitseg, n, sublists,
29483                         subceillists, tetlists, ceillists, NULL, flipque,
29484                         true, chkencsub, chkbadtet);
29485                       setnewpointsize(sympt, e1, e2);
29486                       if (steinerleft > 0) steinerleft--;
29487                     } else {
29488                       // p did not insert for invalid BC(symp).
29489                       pointdealloc(sympt);
29490                     }
29491                     // Free the memory allocated in formbowatcavity().
29492                     releasebowatcavity(&symsplitseg, n, sublists, subceillists,
29493                                        tetlists, ceillists);
29494                   } else {
29495                     splitencseg(sympt, &symsplitseg, tetlist, sublist, NULL,
29496                                 flipque, chkencsub, chkbadtet, false);
29497                     setnewpointsize(sympt, e1, e2);
29498                     if (steinerleft > 0) steinerleft--;
29499                   }
29500                 } else {
29501                   // The sympt are on the same segment. It is possible when
29502                   //   splitseg is the symmetric rotating axes.
29503                   pointdealloc(sympt);
29504                 }
29505               } else if (symloc == ONVERTEX) {
29506                 // The sympt already exists. It is possible when two pbc
29507                 //   groups are exactly the same. Omit this point.
29508                 pointdealloc(sympt);
29509               } else {
29510                 // Do not isnert symp for unknown cases: ONFACE, OUTSIDE.
29511                 // assert(0);
29512                 pointdealloc(sympt);
29513               }
29514             } // for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++)
29515           } // if (checkpbcs)
29516           // Save the endpoints of the seg for size interpolation.
29517           e1 = sorg(splitseg);
29518           if (shelltype(splitseg) == SHARP) {
29519             e2 = sdest(splitseg);
29520           } else {
29521             e2 = (point) NULL; // No need to do size interoplation.
29522           }
29523           if (!b->fliprepair) {
29524             // Form BC(p), B(p), CBC(p)s, and C(p)s.
29525             formbowatcavity(newpt, &splitseg, NULL, &n, &nmax, sublists,
29526                             subceillists, tetlists, ceillists);
29527             // Validate/update BC(p), B(p), CBC(p)s, and C(p)s.
29528             if (trimbowatcavity(newpt, &splitseg, n, sublists, subceillists,
29529                                 tetlists, ceillists, -1.0)) {
29530               bowatinsertsite(newpt, &splitseg, n, sublists, subceillists,
29531                               tetlists, ceillists, NULL, flipque, true,
29532                               chkencsub, chkbadtet);
29533               setnewpointsize(newpt, e1, e2);
29534               if (steinerleft > 0) steinerleft--;
29535             } else {
29536               // p did not insert for invalid B(p).
29537               pointdealloc(newpt);
29538             }
29539             // Free the memory allocated in formbowatcavity().
29540             releasebowatcavity(&splitseg, n, sublists, subceillists, tetlists,
29541                                ceillists);
29542           } else {
29543             splitencseg(newpt, &splitseg, tetlist, sublist, NULL, flipque,
29544                         chkencsub, chkbadtet, false);
29545             setnewpointsize(newpt, e1, e2);
29546             if (steinerleft > 0) steinerleft--;
29547           }
29548         } else {
29549           // p did not accept for insertion.
29550           pointdealloc(newpt);
29551         } // if (checkseg4splitting(newpt, &splitseg))
29552       } // if ((encloop->forg == pa) && (encloop->fdest == pb))
29553       badfacedealloc(badsubsegs, encloop); // Remove this entry from list.
29554       encloop = badfacetraverse(badsubsegs); // Get the next enc-segment.
29555     } // while ((encloop != (badface *) NULL) && (steinerleft != 0))
29556   } // while ((badsubsegs->items > 0) && (steinerleft != 0))
29557 
29558   if (!b->fliprepair) {
29559     delete [] tetlists;
29560     delete [] ceillists;
29561     delete [] sublists;
29562     delete [] subceillists;
29563   } else {
29564     delete tetlist;
29565     delete sublist;
29566     delete flipque;
29567   }
29568 }
29569 
29571 //                                                                           //
29572 // repairencsubs()    Repair (split) all the encroached subfaces.            //
29573 //                                                                           //
29574 // Each encroached subface is repaired by splitting it - inserting a vertex  //
29575 // at or near its circumcenter.  Newly inserted vertices may encroach upon   //
29576 // other subfaces, these are also repaired.                                  //
29577 //                                                                           //
29578 // 'chkbadtet' is a flag that specifies whether one should take note of new  //
29579 // bad quality tets that result from inserted vertices.                      //
29580 //                                                                           //
29582 
29583 void tetgenmesh::repairencsubs(bool chkbadtet)
29584 {
29585   list *tetlists[2], *ceillists[2];
29586   list *sublist, *subceillist;
29587   list *verlist;
29588   badface *encloop;
29589   face splitsub, symsplitsub;
29590   point newpt, sympt, e1;
29591   enum locateresult loc, symloc;
29592   bool reject;
29593   long oldptnum;
29594   int quenumber, n, i;
29595 
29596   quenumber = 0;
29597   n = 0;
29598   sublist = (list *) NULL;
29599   subceillist = (list *) NULL;
29600   verlist = new list(sizeof(point *), NULL, 256);
29601 
29602   // Loop until the pool 'badsubfaces' is empty. Note that steinerleft == -1
29603   //   if an unlimited number of Steiner points is allowed.
29604   while ((badsubfaces->items > 0) && (steinerleft != 0)) {
29605     // Get an encroached subface f.
29606     encloop = dequeueencsub(&quenumber);
29607     splitsub = encloop->ss;
29608     // Clear the in-queue flag of f.
29609     setshell2badface(splitsub, NULL);
29610     // f may not be the same one when it was determined to be encroached.
29611     if (!isdead(&splitsub)
29612         && (sorg(splitsub) == encloop->forg)
29613         && (sdest(splitsub) == encloop->fdest)
29614         && (sapex(splitsub) == encloop->fapex)) {
29615       if (b->verbose > 1) {
29616         printf("    Dequeuing ensub (%d, %d, %d) [%d].\n",
29617                pointmark(encloop->forg), pointmark(encloop->fdest),
29618                pointmark(encloop->fapex), quenumber);
29619       }
29620       // Create a new point p at the circumcenter of f.
29621       makepoint(&newpt);
29622       for (i = 0; i < 3; i++) newpt[i] = encloop->cent[i];
29623       setpointtype(newpt, FREESUBVERTEX);
29624       setpoint2sh(newpt, sencode(splitsub));
29625       // Set the abovepoint of f for point location.
29626       abovepoint = facetabovepointarray[shellmark(splitsub)];
29627       if (abovepoint == (point) NULL) {
29628         getfacetabovepoint(&splitsub);
29629       }
29630       // Locate p, start from f, stop at segment (1), use a tolerance to
29631       //   detect ONVERTEX or OUTSIDE case. Update f on return.
29632       loc = locatesub(newpt, &splitsub, 1, b->epsilon * 1e+2);
29633       if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29634         // Form BC(p), B(p), CBC(p) and C(p).
29635         formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29636                         &subceillist, tetlists, ceillists);
29637         // Check for encroached subsegments (on B(p)).
29638         reject = tallencsegs(newpt, 2, ceillists);
29639         // Execute point accept rule if p does not encroach upon any segment.
29640         if (!reject) {
29641           reject = !acceptfacpt(newpt, subceillist, verlist);
29642         }
29643         if (!reject) {
29644           // Validate/update cavity.
29645           reject = !trimbowatcavity(newpt, NULL, n, &sublist, &subceillist,
29646                                     tetlists, ceillists, -1.0);
29647         }
29648         if (!reject) {
29649           // CBC(p) should include s, so that s can be removed after CBC(p)
29650           //   is remeshed. However, if there are locally non-Delaunay faces
29651           //   and encroached subsegments, s may not be collected in CBC(p).
29652           //   p should not be inserted in such case.
29653           reject = !sinfected(encloop->ss);
29654         }
29655         if (!reject) {
29656           if (checkpbcs) {
29657             if (shellpbcgroup(splitsub) >= 0) {
29658               // Check for splitting of the symmetric subface of f.
29659               makepoint(&sympt);
29660               symloc = getsubpbcsympoint(newpt,&splitsub,sympt,&symsplitsub);
29661               if (symloc != ONVERTEX) {
29662                 // Release CBC(p) and BC(p) and free the memory..
29663                 releasebowatcavity(NULL, 2, &sublist, &subceillist, tetlists,
29664                                    ceillists);
29665                 // Form CBC(symp), C(symp), BC(sympt) and B(sympt).
29666                 formbowatcavity(sympt, NULL, &symsplitsub, &n, NULL, &sublist,
29667                                 &subceillist, tetlists, ceillists);
29668                 reject = tallencsegs(sympt, 2, ceillists);
29669                 if (!reject) {
29670                   reject = !acceptfacpt(sympt, subceillist, verlist);
29671                 }
29672                 if (!reject) {
29673                   reject = !trimbowatcavity(sympt,NULL,n,&sublist,&subceillist,
29674                                             tetlists, ceillists, -1.0);
29675                 }
29676                 if (!reject) {
29677                   // Insert sympt.
29678                   setpoint2pbcpt(newpt, sympt);
29679                   setpoint2pbcpt(sympt, newpt);
29680                   setpointtype(sympt, FREESUBVERTEX);
29681                   setpoint2sh(sympt, sencode(symsplitsub));
29682                   // Save a point for size interpolation.
29683                   e1 = sorg(symsplitsub);
29684                   bowatinsertsite(sympt, NULL, n, &sublist, &subceillist,
29685                      tetlists,ceillists,NULL,NULL,false,true,chkbadtet);
29686                   setnewpointsize(sympt, e1, NULL);
29687                   if (steinerleft > 0) steinerleft--;
29688                   // Release CBC(symp) and BC(symp) and free the memory..
29689                   releasebowatcavity(NULL, n, &sublist, &subceillist, tetlists,
29690                                      ceillists);
29691                 } else {
29692                   // symp is rejected for one of the following reasons:
29693                   //   (1) BC(symp) is not valid; or
29694                   //   (2) symp encroaches upon some subsegments (queued); or
29695                   //   (3) symp is rejected by point accepting rule.
29696                   pointdealloc(sympt);
29697                   // Cavity will be released by the following code.
29698                 }
29699               } else {
29700                 // Do not insert sympt for invalid PBC data.
29701                 pointdealloc(sympt);
29702                 // p is rejected due to symp.
29703                 reject = true;
29704               }
29705             }
29706           } // if (checkpbcs)
29707         }
29708         if (!reject) {
29709           // Insert p.
29710           if (checkpbcs) {
29711             if (shellpbcgroup(splitsub) >= 0) {
29712               // Form CBC(p), C(p), BC(p) and B(p).
29713               formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29714                               &subceillist, tetlists, ceillists);
29715               trimbowatcavity(newpt, NULL, n, &sublist, &subceillist, tetlists,
29716                               ceillists, -1.0);
29717             }
29718           }
29719           // Save a point for size interpolation.
29720           e1 = sorg(splitsub);
29721           bowatinsertsite(newpt, NULL, n, &sublist, &subceillist, tetlists,
29722                           ceillists, NULL, NULL, true, true, chkbadtet);
29723           setnewpointsize(newpt, e1, NULL);
29724           if (steinerleft > 0) steinerleft--;
29725         } else {
29726           // p is rejected for the one of the following reasons:
29727           //   (1) BC(p) is not valid.
29728           //   (2) s does not in CBC(p).
29729           //   (3) p encroaches upon some segments (queued); or
29730           //   (4) p is rejected by point accepting rule, or
29731           //   (5) due to the rejection of symp (the PBC).
29732           pointdealloc(newpt);
29733         } // if (!reject)
29734         // Release the cavity and free the memory.
29735         releasebowatcavity(NULL,n,&sublist,&subceillist,tetlists,ceillists);
29736         if (reject) {
29737           // Are there queued encroached subsegments.
29738           if (badsubsegs->items > 0) {
29739             // Repair enc-subsegments.
29740             oldptnum = points->items;
29741             repairencsegs(true, chkbadtet);
29742             if (points->items > oldptnum) {
29743               // Some enc-subsegments got split. Try to repair f later.
29744               splitsub = encloop->ss;
29745               if (!isdead(&splitsub)) {
29746                 if (!shell2badface(splitsub)) {
29747                   checksub4encroach(&splitsub, NULL, true);
29748                 }
29749               }
29750             }
29751           }
29752         }
29753       } else {
29754         // Don't insert p for one of the following reasons:
29755         //   (1) Locate on an existing vertex; or
29756         //   (2) locate outside the domain.
29757         // Case (1) should not be possible. If such vertex v exists, it is
29758         //   the circumcenter of f, ie., f is non-Delaunay. Either f was got
29759         //   split before by v, but survived after v was inserted, or the
29760         //   same for a f' which is nearly co-circular with f.  Whatsoever,
29761         //   there are encroached segs by v, but the routine tallencsegs()
29762         //   did not find them out.
29763         if (loc == ONVERTEX) {
29764           printf("Internal error in repairencsubs():\n");
29765           printf("  During repairing encroached subface (%d, %d, %d)\n",
29766                  pointmark(encloop->forg), pointmark(encloop->fdest),
29767                  pointmark(encloop->fapex));
29768           printf("  New point %d is coincident with an existing vertex %d\n",
29769                  pointmark(newpt), pointmark(sorg(splitsub)));
29770           internalerror();
29771         }
29772         // Case (2) can happen when thers is a segment s which is close to f
29773         //   and is non-conforming Delaunay. The circumcenter of f encroaches
29774         //   upon s, but the circumcenter of s is rejected for insertion.
29775         pointdealloc(newpt);
29776       } // if ((loc != ONVERTEX) && (loc != OUTSIDE))
29777     } else {
29778       if (!isdead(&splitsub)) {
29779         // The subface has been changed, re-check it.
29780         checksub4encroach(&splitsub, NULL, true);
29781       }
29782     } // if (!isdead(&splitsub) && (sorg(splitsub) == encloop->forg) &&
29783     // Remove this entry from list.
29784     badfacedealloc(badsubfaces, encloop);
29785   } // while ((badsubfaces->items > 0) && (steinerleft != 0))
29786 
29787   delete verlist;
29788 }
29789 
29791 //                                                                           //
29792 // repairbadtets()    Repair all bad-quality tetrahedra.                     //
29793 //                                                                           //
29794 // All bad-quality tets are stored in pool 'badtetrahedrons'.  Each bad tet  //
29795 // is repaired by inserting a point at or near its circumcenter. However, if //
29796 // this point encroaches any subsegment or subface, it is not inserted. Ins- //
29797 // tead the encroached segment and subface are split.  Newly inserted points //
29798 // may create other bad-quality tets, these are also repaired.               //
29799 //                                                                           //
29801 
29802 void tetgenmesh::repairbadtets()
29803 {
29804   list *tetlist, *ceillist;
29805   list *verlist;
29806   badface *badtet;
29807   triface starttet;
29808   point newpt, e1;
29809   enum locateresult loc;
29810   bool reject;
29811   long oldptnum;
29812   int i;
29813 
29814   tetlist = new list(sizeof(triface), NULL, 1024);
29815   ceillist = new list(sizeof(triface), NULL, 1024);
29816   verlist = new list(sizeof(point *), NULL, 256);
29817 
29818   // Loop until pool 'badtetrahedrons' is empty. Note that steinerleft == -1
29819   //   if an unlimited number of Steiner points is allowed.
29820   while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
29821     // Get a bad-quality tet t.
29822     badtet = topbadtetra();
29823     // Make sure that the tet is still the same one when it was tested.
29824     //   Subsequent transformations may have made it a different tet.
29825     if ((badtet != (badface *) NULL) && !isdead(&badtet->tt)
29826          && org(badtet->tt) == badtet->forg
29827          && dest(badtet->tt) == badtet->fdest
29828          && apex(badtet->tt) == badtet->fapex
29829          && oppo(badtet->tt) == badtet->foppo) {
29830       if (b->verbose > 1) {
29831         printf("    Dequeuing btet (%d, %d, %d, %d).\n",
29832                pointmark(badtet->forg), pointmark(badtet->fdest),
29833                pointmark(badtet->fapex), pointmark(badtet->foppo));
29834       }
29835       // Create the new point p (at the circumcenter of t).
29836       makepoint(&newpt);
29837       for (i = 0; i < 3; i++) newpt[i] = badtet->cent[i];
29838       setpointtype(newpt, FREEVOLVERTEX);
29839       // Locate p.
29840       starttet = badtet->tt;
29841       loc = preciselocate(newpt, &starttet, tetrahedrons->items);
29842       if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29843         // For BC(p) and B(p).
29844         infect(starttet);
29845         tetlist->append(&starttet);
29846         formbowatcavityquad(newpt, tetlist, ceillist);
29847         // Check for encroached subsegments.
29848         reject = tallencsegs(newpt, 1, &ceillist);
29849         if (!reject) {
29850           // Check for encroached subfaces.
29851           reject = tallencsubs(newpt, 1, &ceillist);
29852         }
29853         // Execute point accepting rule if p does not encroach upon any
29854         //   subsegment and subface.
29855         if (!reject) {
29856           reject = !acceptvolpt(newpt, ceillist, verlist);
29857         }
29858         if (!reject) {
29859           reject = !trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist,
29860                                     &ceillist, -1.0);
29861         }
29862         if (!reject) {
29863           // BC(p) should include t, so that t can be removed after BC(p) is
29864           //   remeshed. However, if there are locally non-Delaunay faces
29865           //   and encroached subsegments/subfaces, t may not be collected
29866           //   in BC(p). p should not be inserted in such case.
29867           reject = !infected(badtet->tt);
29868           if (reject) outbowatcircumcount++;
29869         }
29870         if (!reject) {
29871           // Save a point for size interpolation.
29872           e1 = org(starttet);
29873           // Insert p.
29874           bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist,
29875                           NULL, NULL, false, false, true);
29876           setnewpointsize(newpt, e1, NULL);
29877           if (steinerleft > 0) steinerleft--;
29878         } else {
29879           // p is rejected for one of the following reasons:
29880           //   (1) BC(p) is not valid.
29881           //   (2) t does not in BC(p).
29882           //   (3) p encroaches upon some segments;
29883           //   (4) p encroaches upon some subfaces;
29884           //   (5) p is rejected by the point accepting rule.
29885           pointdealloc(newpt);
29886           // Uninfect tets of BC(p).
29887           for (i = 0; i < tetlist->len(); i++) {
29888             starttet = * (triface *)(* tetlist)[i];
29889             uninfect(starttet);
29890           }
29891         }
29892         tetlist->clear();
29893         ceillist->clear();
29894         // Split encroached subsegments/subfaces if there are.
29895         if (reject) {
29896           oldptnum = points->items;
29897           if (badsubsegs->items > 0) {
29898             repairencsegs(true, true);
29899           }
29900           if (badsubfaces->items > 0) {
29901             repairencsubs(true);
29902           }
29903           if (points->items > oldptnum) {
29904             // Some encroaching subsegments/subfaces got split. Re-queue the
29905             //   tet if it is still alive.
29906             starttet = badtet->tt;
29907             if (!isdead(&starttet)) {
29908               checktet4badqual(&starttet, true);
29909             }
29910           }
29911         }
29912       } else {
29913         // Do not insert p. The reason may be one of:
29914         //   (1) p is coincident (ONVERTEX) with an existing vertex; or
29915         //   (2) p is outside (OUTSIDE) the mesh.
29916         // Case (1) should not be possible. If such vertex v exists, it is
29917         //   the circumcenter of t, ie., t is non-Delaunay. Either t was got
29918         //   split before by v, but survived after v was inserted, or the
29919         //   same for a t' which is nearly co-spherical with t.  Whatsoever,
29920         //   there are encroached segments or subfaces by v but the routines
29921         //   tallencsegs() or tallencsubs() did not find them out.
29922         if (loc == ONVERTEX) {
29923           printf("Internal error in repairbadtets():\n");
29924           printf("  During repairing bad tet (%d, %d, %d, %d)\n",
29925                  pointmark(badtet->forg), pointmark(badtet->fdest),
29926                  pointmark(badtet->fapex), pointmark(badtet->foppo));
29927           printf("  New point %d is coincident with an existing vertex %d\n",
29928                  pointmark(newpt), pointmark(org(starttet)));
29929           internalerror();
29930         }
29931         // Case (2) can happen when there is a segment s (or subface f) which
29932         //   is close to f and is non-conforming Delaunay.  The circumcenter
29933         //   of t encroaches upon s (or f), but the circumcenter of s (or f)
29934         //   is rejected for insertion.
29935         pointdealloc(newpt);
29936       } // if ((loc != ONVERTEX) && (loc != OUTSIDE))
29937     } // if (!isdead(&badtet->tt) && org(badtet->tt) == badtet->forg &&
29938     // Remove the tet from the queue.
29939     dequeuebadtet();
29940   } // while ((badtetrahedrons->items > 0) && (steinerleft != 0))
29941 
29942   delete tetlist;
29943   delete ceillist;
29944   delete verlist;
29945 }
29946 
29948 //                                                                           //
29949 // enforcequality()    Refine the mesh.                                      //
29950 //                                                                           //
29952 
29953 void tetgenmesh::enforcequality()
29954 {
29955   long total, vertcount;
29956   int i;
29957 
29958   if (!b->quiet) {
29959     printf("Adding Steiner points to enforce quality.\n");
29960   }
29961 
29962   total = vertcount = 0l;
29963   if (b->conformdel) {
29964     r2count = r3count = 0l;
29965   }
29966 
29967   // If both '-D' and '-r' options are used.
29968   if (b->conformdel && b->refine) {
29969     markacutevertices(65.0);
29970   }
29971   // If '-m' is not used.
29972   if (!b->metric) {
29973     // Find and mark all sharp segments.
29974     marksharpsegments(65.0);
29975     // Decide the sizes for feature points.
29976     decidefeaturepointsizes();
29977   }
29978 
29979   // Initialize the pool of encroached subsegments.
29980   badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29981   // Looking for encroached subsegments.
29982   tallencsegs(NULL, 0, NULL);
29983   if (b->verbose && badsubsegs->items > 0) {
29984     printf("  Splitting encroached subsegments.\n");
29985   }
29986   vertcount = points->items;
29987   // Fix encroached segments without noting any enc subfaces.
29988   repairencsegs(false, false);
29989   if (b->verbose > 0) {
29990     printf("  %ld split points.\n", points->items - vertcount);
29991   }
29992   total += points->items - vertcount;
29993 
29994   // Initialize the pool of encroached subfaces.
29995   badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29996   // Initialize the priority queues of badfaces.
29997   for (i = 0; i < 3; i++) subquefront[i] = (badface *) NULL;
29998   for (i = 0; i < 3; i++) subquetail[i] = &subquefront[i];
29999   // Looking for encroached subfaces.
30000   tallencsubs(NULL, 0, NULL);
30001   if (b->verbose && badsubfaces->items > 0) {
30002     printf("  Splitting encroached subfaces.\n");
30003   }
30004   vertcount = points->items;
30005   // Fix encroached subfaces without noting bad tetrahedra.
30006   repairencsubs(false);
30007   if (b->verbose > 0) {
30008     printf("  %ld split points.\n", points->items - vertcount);
30009   }
30010   total += points->items - vertcount;
30011   // At this point, the mesh should be conforming Delaunay if no input
30012   //   angle is smaller than 90 degree.
30013 
30014   // Next, fix bad quality tetrahedra.
30015   if ((b->minratio > 0.0) || b->varvolume || b->fixedvolume) {
30016     // Initialize the pool of bad tets
30017     badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30018     // Initialize the priority queues of bad tets.
30019     for (i = 0; i < 64; i++) tetquefront[i] = (badface *) NULL;
30020     firstnonemptyq = -1;
30021     recentq = -1;
30022     // Looking for bad quality tets.
30023     cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30024     cosmindihed = cos(b->mindihedral * PI / 180.0);
30025     tallbadtetrahedrons();
30026     if (b->verbose && badtetrahedrons->items > 0) {
30027       printf("  Splitting bad tetrahedra.\n");
30028     }
30029     vertcount = points->items;
30030     repairbadtets();
30031     if (b->verbose > 0) {
30032       printf("  %ld refinement points.\n", points->items - vertcount);
30033     }
30034     total += points->items - vertcount;
30035     delete badtetrahedrons;
30036   }
30037 
30038   if (b->verbose > 0) {
30039     printf("  Totally added %ld points.\n", total);
30040   }
30041 
30042   delete badsubfaces;
30043   delete badsubsegs;
30044 }
30045 
30046 //
30047 // End of Delaunay refinement routines
30048 //
30049 
30050 //
30051 // Begin of mesh optimization routines
30052 //
30053 
30054 void tetgenmesh::dumpbadtets()
30055 {
30056   FILE *fout;
30057   badface *remtet;
30058 
30059   // Write out a file of remaining bad tets.
30060   printf("  Writing bad tets to file bad-dump.lua.\n");
30061   fout = fopen("bad-dump.lua", "w");
30062   fprintf(fout, "-- %ld remaining bad tets (> %g degree).\n",
30063           badtetrahedrons->items, b->maxdihedral);
30064   badtetrahedrons->traversalinit();
30065   remtet = badfacetraverse(badtetrahedrons);
30066   while (remtet != (badface *) NULL) {
30067     if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30068         dest(remtet->tt) == remtet->fdest &&
30069         apex(remtet->tt) == remtet->fapex &&
30070         oppo(remtet->tt) == remtet->foppo) {
30071       fprintf(fout, "p:draw_tet(%d, %d, %d, %d) -- %g\n",
30072               pointmark(remtet->forg), pointmark(remtet->fdest),
30073               pointmark(remtet->fapex), pointmark(remtet->foppo),
30074               acos(remtet->key) * 180.0 / PI);
30075     }
30076     remtet = badfacetraverse(badtetrahedrons);
30077   }
30078   fclose(fout);
30079 }
30080 
30082 //                                                                           //
30083 // checktet4ill()    Check a tet to see if it is illegal.                    //
30084 //                                                                           //
30085 // A tet is "illegal" if it spans on one input facet.  Save the tet in queue //
30086 // if it is illegal and the flag 'enqflag' is set.                           //
30087 //                                                                           //
30088 // Note: Such case can happen when the input facet has non-coplanar vertices //
30089 // and the Delaunay tetrahedralization of the vertices may creat such tets.  //
30090 //                                                                           //
30092 
30093 bool tetgenmesh::checktet4ill(triface* testtet, bool enqflag)
30094 {
30095   badface *newbadtet;
30096   triface checktet;
30097   face checksh1, checksh2;
30098   face checkseg;
30099   bool illflag;
30100   int i;
30101 
30102   illflag = false;
30103   for (testtet->loc = 0; testtet->loc < 4; testtet->loc++) {
30104     tspivot(*testtet, checksh1);
30105     if (checksh1.sh != dummysh) {
30106       testtet->ver = 0;
30107       findedge(&checksh1, org(*testtet), dest(*testtet));
30108       for (i = 0; i < 3; i++) {
30109         fnext(*testtet, checktet);
30110         tspivot(checktet, checksh2);
30111         if (checksh2.sh != dummysh) {
30112           // Two subfaces share this edge.
30113           sspivot(checksh1, checkseg);
30114           if (checkseg.sh == dummysh) {
30115             // The four corners of the tet are on one facet. Illegal! Try to
30116             //   flip the opposite edge of the current one.
30117             enextfnextself(*testtet);
30118             enextself(*testtet);
30119             illflag = true;
30120             break;
30121           }
30122         }
30123         enextself(*testtet);
30124         senextself(checksh1);
30125       }
30126     }
30127     if (illflag) break;
30128   }
30129 
30130   if (illflag && enqflag) {
30131     // Allocate space for the bad tetrahedron.
30132     newbadtet = (badface *) badtetrahedrons->alloc();
30133     newbadtet->tt = *testtet;
30134     newbadtet->key = -1.0; // = 180 degree.
30135     for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
30136     newbadtet->forg = org(*testtet);
30137     newbadtet->fdest = dest(*testtet);
30138     newbadtet->fapex = apex(*testtet);
30139     newbadtet->foppo = oppo(*testtet);
30140     newbadtet->nextitem = (badface *) NULL;
30141     if (b->verbose > 2) {
30142       printf("    Queueing illtet: (%d, %d, %d, %d).\n",
30143              pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30144              pointmark(newbadtet->fapex), pointmark(newbadtet->foppo));
30145     }
30146   }
30147 
30148   return illflag;
30149 }
30150 
30152 //                                                                           //
30153 // checktet4opt()    Check a tet to see if it needs to be optimized.         //
30154 //                                                                           //
30155 // A tet t needs to be optimized if it fails to certain quality measures.    //
30156 // The only quality measure currently used is the maximal dihedral angle at  //
30157 // edges. The desired maximal dihedral angle is b->maxdihed (set by the '-s' //
30158 // option.                                                                   //
30159 //                                                                           //
30160 // A tet may have one, two, or three big dihedral angles. Examples: Let the  //
30161 // tet t = abcd, and its four corners are nearly co-planar. Then t has one   //
30162 // big dihedral angle if d is very close to the edge ab; t has three big     //
30163 // dihedral angles if d's projection on the face abc is also inside abc, i.e.//
30164 // the shape of t likes a hat; finally, t has two big dihedral angles if d's //
30165 // projection onto abc is outside abc.                                       //
30166 //                                                                           //
30168 
30169 bool tetgenmesh::checktet4opt(triface* testtet, bool enqflag)
30170 {
30171   badface *newbadtet;
30172   point pa, pb, pc, pd;
30173   REAL N[4][3], len;
30174   REAL cosd;
30175   bool enq;
30176   int i, j;
30177 
30178   cosd = 0.0;
30179   enq = false;
30180   pa = (point) testtet->tet[4];
30181   pb = (point) testtet->tet[5];
30182   pc = (point) testtet->tet[6];
30183   pd = (point) testtet->tet[7];
30184   // Compute the 4 face normals: N[0] cbd, N[1] acd, N[2] bad, N[3] abc.
30185   tetallnormal(pa, pb, pc, pd, N, NULL);
30186   // Normalize the normals.
30187   for (i = 0; i < 4; i++) {
30188     len = sqrt(dot(N[i], N[i]));
30189     if (len != 0.0) {
30190       for (j = 0; j < 3; j++) N[i][j] /= len;
30191     }
30192   }
30193   // Find all large dihedral angles.
30194   for (i = 0; i < 6; i++) {
30195     // Locate the edge i and calculate the dihedral angle at the edge.
30196     testtet->loc = 0;
30197     testtet->ver = 0;
30198     switch (i) {
30199     case 0: // edge ab
30200       cosd = -dot(N[2], N[3]);
30201       break;
30202     case 1: // edge cd
30203       enextfnextself(*testtet);
30204       enextself(*testtet);
30205       cosd = -dot(N[0], N[1]);
30206       break;
30207     case 2: // edge bd
30208       enextfnextself(*testtet);
30209       enext2self(*testtet);
30210       cosd = -dot(N[0], N[2]);
30211       break;
30212     case 3: // edge bc
30213       enextself(*testtet);
30214       cosd = -dot(N[0], N[3]);
30215       break;
30216     case 4: // edge ad
30217       enext2fnextself(*testtet);
30218       enextself(*testtet);
30219       cosd = -dot(N[1], N[2]);
30220       break;
30221     case 5: // edge ac
30222       enext2self(*testtet);
30223       cosd = -dot(N[1], N[3]);
30224       break;
30225     }
30226     if (cosd < cosmaxdihed) {
30227       // A bigger dihedral angle.
30228       if (enqflag) {
30229         // Allocate space for the bad tetrahedron.
30230         newbadtet = (badface *) badtetrahedrons->alloc();
30231         newbadtet->tt = *testtet;
30232         newbadtet->key = cosd;
30233         for (j = 0; j < 3; j++) newbadtet->cent[j] = 0.0;
30234         newbadtet->forg = org(*testtet);
30235         newbadtet->fdest = dest(*testtet);
30236         newbadtet->fapex = apex(*testtet);
30237         newbadtet->foppo = oppo(*testtet);
30238         newbadtet->nextitem = (badface *) NULL;
30239         if (b->verbose > 2) {
30240           printf("    Queueing tet: (%d, %d, %d, %d), dihed %g (degree).\n",
30241                  pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30242                  pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
30243                  acos(cosd) * 180.0 / PI);
30244         }
30245       }
30246       enq = true;
30247     }
30248   }
30249 
30250   return enq;
30251 }
30252 
30254 //                                                                           //
30255 // removeedge()    Remove an edge                                            //
30256 //                                                                           //
30257 // 'remedge' is a tet (abcd) having the edge ab wanted to be removed.  Local //
30258 // reconnecting operations are used to remove edge ab.  The following opera- //
30259 // tion will be tryed.                                                       //
30260 //                                                                           //
30261 // If ab is on the hull, and abc and abd are both hull faces. Then ab can be //
30262 // removed by stripping abcd from the mesh. However, if ab is a segemnt, do  //
30263 // the operation only if 'b->optlevel' > 1 and 'b->nobisect == 0'.           //
30264 //                                                                           //
30265 // If ab is an internal edge, there are n tets contains it.  Then ab can be  //
30266 // removed if there exists another m tets which can replace the n tets with- //
30267 // out changing the boundary of the n tets.                                  //
30268 //                                                                           //
30269 // If 'optflag' is set.  The value 'remedge->key' means cos(theta), where    //
30270 // 'theta' is the maximal dishedral angle at ab. In this case, even if the   //
30271 // n-to-m flip exists, it will not be performed if the maximum dihedral of   //
30272 // the new tets is larger than 'theta'.                                      //
30273 //                                                                           //
30275 
30276 bool tetgenmesh::removeedge(badface* remedge, bool optflag)
30277 {
30278   triface abcd, badc;  // Tet configuration at edge ab.
30279   triface baccasing, abdcasing;
30280   triface abtetlist[11];  // Old configuration at ab, save maximum 10 tets.
30281   triface bftetlist[11];  // Old configuration at bf, save maximum 10 tets.
30282   triface newtetlist[33]; // New configuration after removing ab.
30283   face checksh;
30284   enum fliptype fty;
30285   REAL key;
30286   bool remflag, subflag;
30287   int n, n1, m, i, j;
30288 
30289   // First try to strip abcd from the mesh. This needs to check either ab
30290   //   or cd is on the hull. Try to strip it whichever is true.
30291   abcd = remedge->tt;
30292   adjustedgering(abcd, CCW);
30293   i = 0;
30294   do {
30295     sym(abcd, baccasing);
30296     // Is the tet on the hull?
30297     if (baccasing.tet == dummytet) {
30298       fnext(abcd, badc);
30299       sym(badc, abdcasing);
30300       if (abdcasing.tet == dummytet) {
30301         // Strip the tet from the mesh -> ab is removed as well.
30302         if (removetetbypeeloff(&abcd)) {
30303           if (b->verbose > 1) {
30304             printf("    Stripped tet from the mesh.\n");
30305           }
30306           optcount[0]++;
30307           return true;
30308         }
30309       }
30310     }
30311     // Check if the oppsite edge cd is on the hull.
30312     enext2fnextself(abcd);
30313     enext2self(abcd);
30314     esymself(abcd); // --> cdab
30315     i++;
30316   } while (i < 2);
30317 
30318   // Get the tets configuration at ab. Collect maximum 10 tets.
30319   subflag = false;
30320   abcd = remedge->tt;
30321   adjustedgering(abcd, CW);
30322   n = 0;
30323   abtetlist[n] = abcd;
30324   do {
30325     // Is the list full?
30326     if (n == 10) break;
30327     // Stop if a subface appears.
30328     tspivot(abtetlist[n], checksh);
30329     if (checksh.sh != dummysh) {
30330       // ab is either a segment or a facet edge. The latter case is not
30331       //   handled yet! An edge flip is needed.
30332       subflag = true; break; // return false;
30333     }
30334     // Get the next tet at ab.
30335     fnext(abtetlist[n], abtetlist[n + 1]);
30336     n++;
30337   } while (apex(abtetlist[n]) != apex(abcd));
30338 
30339   remflag = false;
30340   key = remedge->key;
30341 
30342   if (subflag && optflag) {
30343     abcd = remedge->tt;
30344     adjustedgering(abcd, CCW);
30345     // Try to flip face cda or cdb to improve quality.
30346     for (j = 0; j < 2; j++) {
30347       if (j == 0) {
30348         enext2fnext(abcd, abtetlist[0]); // Goto cda.
30349       } else {
30350         enextfnext(abcd, abtetlist[0]); // Goto cdb.
30351       }
30352       fty = categorizeface(abtetlist[0]);
30353       if (fty == T23) {
30354         // A 2-to-3 flip is possible.
30355         sym(abtetlist[0], abtetlist[1]);
30356         assert(abtetlist[1].tet != dummytet);
30357         n = 2;
30358         m = 3;
30359         remflag = removefacebyflip23(&key, abtetlist, newtetlist, NULL);
30360       } else if (fty == T22) {
30361         // A 2-to-2 or 4-to-4 flip is possible.
30362         n = 2;
30363         newtetlist[0] = abtetlist[0];
30364         adjustedgering(newtetlist[0], CW);
30365         fnext(newtetlist[0], newtetlist[1]);
30366         assert(newtetlist[1].tet != dummytet);
30367         // May it is 4-to-4 flip.
30368         if (fnext(newtetlist[1], newtetlist[2])) {
30369           fnext(newtetlist[2], newtetlist[3]);
30370           assert(newtetlist[3].tet != dummytet);
30371           n = 4;
30372         }
30373         m = n;
30374         remflag = removeedgebyflip22(&key, n, newtetlist, NULL);
30375       }
30376       // Has quality been improved?
30377       if (remflag) {
30378         if (b->verbose > 1) {
30379           printf("  Done flip %d-to-%d. Qual: %g -> %g.\n", n, m,
30380                  acos(remedge->key) / PI * 180.0, acos(key) / PI * 180.0);
30381         }
30382         // Delete the old tets. Note, flip22() does not create new tets.
30383         if (m == 3) {
30384           for (i = 0; i < n; i++) {
30385             tetrahedrondealloc(abtetlist[i].tet);
30386           }
30387         }
30388         for (i = 0; i < m; i++) {
30389           checktet4opt(&(newtetlist[i]), true);
30390         }
30391         optcount[1]++;
30392         return true;
30393       }
30394     } // if (j = 0; j < 2; j++)
30395     // Faces are not flipable. Return.
30396     return false;
30397   }
30398 
30399   // 2 <= n <= 10.
30400   if (n == 3) {
30401     // There are three tets at ab. Try to do a flip32 at ab.
30402     remflag = removeedgebyflip32(&key, abtetlist, newtetlist, NULL);
30403   } else if ((n == 4) || (n == 5) || (n == 6)) {
30404     // Four tets case. Try to do edge transformation.
30405     remflag = removeedgebytranNM(&key,n,abtetlist,newtetlist,NULL,NULL,NULL);
30406   } else {
30407     if (b->verbose > 1) {
30408       printf("  !! Unhandled case: n = %d.\n", n);
30409     }
30410   }
30411   if (remflag) {
30412     optcount[n]++;
30413     // Delete the old tets.
30414     for (i = 0; i < n; i++) {
30415       tetrahedrondealloc(abtetlist[i].tet);
30416     }
30417     m = (n - 2) * 2; // The numebr of new tets.
30418     if (b->verbose > 1) {
30419       printf("  Done flip %d-to-%d. ", n, m);
30420       if (optflag) {
30421         printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30422                acos(key) / PI * 180.0);
30423       }
30424       printf("\n");
30425     }
30426   }
30427 
30428   if (!remflag && (key == remedge->key) && (n < 7)) {
30429     // Try to do a combination of flips.
30430     n1 = 0;
30431     remflag = removeedgebycombNM(&key, n, abtetlist, &n1, bftetlist,
30432       newtetlist, NULL);
30433     if (remflag) {
30434       optcount[9]++;
30435       // Delete the old tets.
30436       for (i = 0; i < n; i++) {
30437         tetrahedrondealloc(abtetlist[i].tet);
30438       }
30439       for (i = 0; i < n1; i++) {
30440         if (!isdead(&(bftetlist[i]))) {
30441           tetrahedrondealloc(bftetlist[i].tet);
30442         }
30443       }
30444       m = ((n1 - 2) * 2 - 1) + (n - 3) * 2; // The number of new tets.
30445       if (b->verbose > 1) {
30446         printf("  Done flip %d-to-%d (n-1=%d, n1=%d). ", n+n1-2, m, n-1,n1);
30447         if (optflag) {
30448           printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30449                acos(key) / PI * 180.0);
30450         }
30451         printf("\n");
30452       }
30453     }
30454   }
30455 
30456   if (remflag) {
30457     // edge is removed. Test new tets for further optimization.
30458     for (i = 0; i < m; i++) {
30459       if (optflag) {
30460         checktet4opt(&(newtetlist[i]), true);
30461       } else {
30462         checktet4ill(&(newtetlist[i]), true);
30463       }
30464     }
30465   }
30466 
30467   return remflag;
30468 }
30469 
30471 //                                                                           //
30472 // smoothsliver()    Remove a sliver by smoothing a vertex of it.            //
30473 //                                                                           //
30474 // The 'slivtet' represents a sliver abcd, and ab is the current edge which  //
30475 // has a large dihedral angle (close to 180 degree).                         //
30476 //                                                                           //
30478 
30479 bool tetgenmesh::smoothsliver(badface* remedge, list *starlist)
30480 {
30481   triface checktet;
30482   point smthpt;
30483   bool smthed;
30484   int idx, i, j;
30485 
30486   // Find a Steiner volume point and smooth it.
30487   smthed = false;
30488   for (i = 0; i < 4 && !smthed; i++) {
30489     smthpt = (point) remedge->tt.tet[4 + i];
30490     // Is it a volume point?
30491     if (pointtype(smthpt) == FREEVOLVERTEX) {
30492       // Is it a Steiner point?
30493       idx = pointmark(smthpt) - in->firstnumber;
30494       if (!(idx < in->numberofpoints)) {
30495         // Smooth a Steiner volume point.
30496         starlist->append(&(remedge->tt.tet));
30497         formstarpolyhedron(smthpt, starlist, NULL, false);
30498         smthed = smoothpoint(smthpt,NULL,NULL,starlist,false,&remedge->key);
30499         // If it is smoothed. Queue new bad tets.
30500         if (smthed) {
30501           for (j = 0; j < starlist->len(); j++) {
30502             checktet = * (triface *)(* starlist)[j];
30503             checktet4opt(&checktet, true);
30504           }
30505         }
30506         starlist->clear();
30507       }
30508     }
30509   }
30510 
30511   /* Omit to smooth segment points. This may cause infinite loop.
30512   if (smthed) {
30513     return true;
30514   }
30515   face abseg, nextseg, prevseg;
30516   point pt[2];
30517   // Check if ab is a segment.
30518   tsspivot(slivtet, &abseg);
30519   if (abseg.sh == dummysh) {
30520     // ab is not a segment. Check if a or b is a Steiner segment point.
30521     for (i = 0; i < 2 && !smthed; i++) {
30522       smthpt = (i == 0 ? org(*slivtet) : dest(*slivtet));
30523       if (pointtype(smthpt) == FREESEGVERTEX) {
30524         // Is it a Steiner point?
30525         idx = pointmark(smthpt) - in->firstnumber;
30526         if (!(idx < in->numberofpoints)) {
30527           // Smooth a Steiner segment point. Get the segment.
30528           sdecode(point2sh(smthpt), nextseg);
30529           locateseg(smthpt, &nextseg);
30530           assert(sorg(nextseg) == smthpt);
30531           pt[0] = sdest(nextseg);
30532           senext2(nextseg, prevseg);
30533           spivotself(prevseg);
30534           prevseg.shver = 0;
30535           if (sorg(prevseg) == smthpt) sesymself(prevseg);
30536           assert(sdest(prevseg) == smthpt);
30537           pt[1] = sorg(prevseg);
30538           starlist->append(slivtet);
30539           formstarpolyhedron(smthpt, starlist, NULL, true);
30540           smthed = smoothpoint(smthpt, pt[0], pt[1], starlist, false);
30541           // If it is smoothed. Check if the tet is still a sliver.
30542           if (smthed) checktet4opt(slivtet, true);
30543           starlist->clear();
30544         }
30545       }
30546     }
30547   }
30548   */
30549 
30550   return smthed;
30551 }
30552 
30554 //                                                                           //
30555 // splitsliver()    Remove a sliver by inserting a point.                    //
30556 //                                                                           //
30557 // The 'remedge->tt' represents a sliver abcd, ab is the current edge which  //
30558 // has a large dihedral angle (close to 180 degree).                         //
30559 //                                                                           //
30561 
30562 bool tetgenmesh::splitsliver(badface *remedge, list *tetlist, list *ceillist)
30563 {
30564   triface starttet;
30565   face checkseg;
30566   point newpt, pt[4];
30567   bool remflag;
30568   int i;
30569 
30570   starttet = remedge->tt;
30571 
30572   // Check if cd is a segment.
30573   adjustedgering(starttet, CCW);
30574   enextfnextself(starttet);
30575   enextself(starttet);
30576   tsspivot(&starttet, &checkseg);
30577   if (b->nobisect == 0) {
30578     if (checkseg.sh != dummysh) {
30579       // cd is a segment. The seg will be split. BUT do not flip! Due to the
30580       //   exact predicates, lot of slivers ay be rsulted and hard to remove.
30581       checkseg.shver = 0;
30582       pt[0] = sorg(checkseg);
30583       pt[1] = sdest(checkseg);
30584       makepoint(&newpt);
30585       getsplitpoint(pt[0], pt[1], NULL, newpt);
30586       setpointtype(newpt, FREESEGVERTEX);
30587       setpoint2sh(newpt, sencode(checkseg));
30588       // Insert p, this should always success.
30589       sstpivot(&checkseg, &starttet);
30590       splittetedge(newpt, &starttet, NULL);
30591       // Collect the new tets connecting at p.
30592       sstpivot(&checkseg, &starttet);
30593       ceillist->append(&starttet);
30594       formstarpolyhedron(newpt, ceillist, NULL, true);
30595       setnewpointsize(newpt, pt[0], NULL);
30596       if (steinerleft > 0) steinerleft--;
30597       // Smooth p.
30598       smoothpoint(newpt, pt[0], pt[1], ceillist, false, NULL);
30599       // Queue new slivers.
30600       for (i = 0; i < ceillist->len(); i++) {
30601         starttet = * (triface *)(* ceillist)[i];
30602         checktet4opt(&starttet, true);
30603       }
30604       ceillist->clear();
30605       return true;
30606     }
30607   }
30608 
30609   // Get the four corners.
30610   for (i = 0; i < 4; i++) {
30611     pt[i] = (point) starttet.tet[4 + i];
30612   }
30613   // Create the new point p (at the circumcenter of t).
30614   makepoint(&newpt);
30615   for (i = 0; i < 3; i++) {
30616     newpt[i] = 0.25 * (pt[0][i] + pt[1][i] + pt[2][i] + pt[3][i]);
30617   }
30618   setpointtype(newpt, FREEVOLVERTEX);
30619 
30620   // Form the Bowyer-Watson cavity of p.
30621   remflag = false;
30622   infect(starttet);
30623   tetlist->append(&starttet);
30624   formbowatcavityquad(newpt, tetlist, ceillist);
30625   if (trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, -1.0)) {
30626     // Smooth p.
30627     if (smoothpoint( newpt, NULL, NULL, ceillist, false, &remedge->key)) {
30628       // Insert p.
30629       bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, NULL,
30630                       NULL, false, false, false);
30631       setnewpointsize(newpt, pt[0], NULL);
30632       if (steinerleft > 0) steinerleft--;
30633       // Queue new slivers.
30634       for (i = 0; i < ceillist->len(); i++) {
30635         starttet = * (triface *)(* ceillist)[i];
30636         checktet4opt(&starttet, true);
30637       }
30638       remflag = true;
30639     } // if (smoothpoint)
30640   } // if (trimbowatcavity)
30641 
30642   if (!remflag) {
30643     // p is rejected for BC(p) is not valid.
30644     pointdealloc(newpt);
30645     // Uninfect tets of BC(p).
30646     for (i = 0; i < tetlist->len(); i++) {
30647       starttet = * (triface *)(* tetlist)[i];
30648       uninfect(starttet);
30649     }
30650   }
30651   tetlist->clear();
30652   ceillist->clear();
30653 
30654   return remflag;
30655 }
30656 
30658 //                                                                           //
30659 // tallslivers()    Queue all the slivers in the mesh.                       //
30660 //                                                                           //
30662 
30663 void tetgenmesh::tallslivers(bool optflag)
30664 {
30665   triface tetloop;
30666 
30667   tetrahedrons->traversalinit();
30668   tetloop.tet = tetrahedrontraverse();
30669   while (tetloop.tet != (tetrahedron *) NULL) {
30670     if (optflag) {
30671       checktet4opt(&tetloop, true);
30672     } else {
30673       checktet4ill(&tetloop, true);
30674     }
30675     tetloop.tet = tetrahedrontraverse();
30676   }
30677 }
30678 
30680 //                                                                           //
30681 // optimizemesh()    Improve mesh quality by mesh optimizations.             //
30682 //                                                                           //
30683 // Available mesh optimizing operations are: (1) multiple edge flips (3-to-2,//
30684 // 4-to-4, 5-to-6, etc), (2) free vertex deletion, (3) new vertex insertion. //
30685 // (1) is mandatory, while (2) and (3) are optionally.                       //
30686 //                                                                           //
30687 // The variable 'b->optlevel' (set after '-s') determines the use of these   //
30688 // operations. If it is: 0, do no optimization; 1, only do (1) operation; 2, //
30689 // do (1) and (2) operations; 3, do all operations. Deault, b->optlvel = 2.  //
30690 //                                                                           //
30692 
30693 void tetgenmesh::optimizemesh(bool optflag)
30694 {
30695   list *splittetlist, *tetlist, *ceillist;
30696   badface *remtet, *lastentry;
30697   //REAL maxdihed, objdihed, curdihed; // maxdihead commented out to get gcc 4.6 working
30698   REAL objdihed, curdihed;
30699   long oldnum;
30700   int iter, i;
30701 
30702   objdihed = 0.0;
30703 
30704   if (!b->quiet) {
30705     if (optflag) {
30706       printf("Optimizing mesh.\n");
30707     } else {
30708       printf("Repairing mesh.\n");
30709     }
30710   }
30711 
30712 #ifdef SELF_CHECK
30713   if (optflag && (b->verbose)) {
30714     printf("  level = %d.\n", b->optlevel);
30715   }
30716 #endif
30717 
30718   // Initialize the pool of bad tets.
30719   badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30720   if (optflag) {
30721     cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30722     cosmindihed = cos(b->mindihedral * PI / 180.0);
30723     // The radian of the maximum dihedral angle.
30724     //maxdihed = b->maxdihedral / 180.0 * PI; // maxdihead commented out to get gcc 4.6 working
30725     // A sliver has an angle large than 'objdihed' will be split.
30726     objdihed = b->maxdihedral + 5.0;
30727     if (objdihed < 170.0) objdihed = 170.0;
30728     objdihed = objdihed / 180.0 * PI;
30729   }
30730   // Looking for non-optimal tets.
30731   tallslivers(optflag);
30732 
30733   optcount[0] = 0l;  // tet strip count.
30734   optcount[1] = 0l;  // face (2-3) and edge (2-2) flip count.
30735   optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l; // edge flips.
30736   optcount[9] = 0l;  // combined flip count.
30737 
30738   // Perform edge flip to improve quality.
30739   lastentry = (badface *) NULL;
30740   // Loop until pool 'badtetrahedrons' is empty.
30741   while (badtetrahedrons->items > 0) {
30742     badtetrahedrons->traversalinit();
30743     remtet = badfacetraverse(badtetrahedrons);
30744     while (remtet != (badface *) NULL) {
30745       // Make sure that the tet is still the same one when it was tested.
30746       //   Subsequent transformations may have made it a different tet.
30747       if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30748           dest(remtet->tt) == remtet->fdest &&
30749           apex(remtet->tt) == remtet->fapex &&
30750           oppo(remtet->tt) == remtet->foppo) {
30751         if (b->verbose > 1) {
30752           printf("    Repair tet (%d, %d, %d, %d) %g (degree).\n",
30753                  pointmark(remtet->forg), pointmark(remtet->fdest),
30754                  pointmark(remtet->fapex), pointmark(remtet->foppo),
30755                  acos(remtet->key) / PI * 180.0);
30756         }
30757         if (!removeedge(remtet, optflag)) {
30758           // An unremoveable tet. Check if it forms a loop.
30759           if (lastentry != (badface *) NULL) {
30760             if (remtet == lastentry) break;
30761           } else {
30762             // Remember this tet as a breakpoint.
30763             lastentry = remtet;
30764           }
30765         } else {
30766           // Clear the breakpoint.
30767           lastentry = (badface *) NULL;
30768           // Remove the entry from the queue.
30769           badfacedealloc(badtetrahedrons, remtet);
30770         }
30771       } else {
30772         // Remove the entry from the queue.
30773         badfacedealloc(badtetrahedrons, remtet);
30774       }
30775       remtet = badfacetraverse(badtetrahedrons);
30776     }
30777     // Stop if the above loop was out by force.
30778     if (remtet != (badface *) NULL) break;
30779   }
30780 
30781   if (b->verbose) {
30782     if (optcount[0] > 0l) {
30783       printf("  %ld tets are peeled off.\n", optcount[0]);
30784     }
30785     if (optcount[1] > 0l) {
30786       printf("  %ld faces are flipped.\n", optcount[1]);
30787     }
30788     if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30789         optcount[9] > 0l) {
30790       printf("  %ld edges are flipped.\n", optcount[3] + optcount[4] +
30791              optcount[5] + optcount[6] + optcount[9]);
30792     }
30793     // if (badtetrahedrons->items > 0l) {
30794     //   printf("  %ld edges remain.\n", badtetrahedrons->items);
30795     // }
30796   }
30797 
30798   if ((badtetrahedrons->items > 0l) && optflag  && (b->optlevel > 2)) {
30799     splittetlist = new list(sizeof(badface), NULL, 256);
30800     tetlist = new list(sizeof(triface), NULL, 256);
30801     ceillist = new list(sizeof(triface), NULL, 256);
30802     oldnum = points->items;
30803     smoothsegverts = smoothvolverts = 0;
30804     optcount[1] = 0l;
30805     optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l; // edge flips.
30806     optcount[9] = 0l;  // combined flip count.
30807     iter = 0;
30808 
30809     do {
30810       // Form a list of slivers to be split and clean the pool.
30811       badtetrahedrons->traversalinit();
30812       remtet = badfacetraverse(badtetrahedrons);
30813       while (remtet != (badface *) NULL) {
30814         splittetlist->append(remtet);
30815         // Remove the entry from the queue.
30816         badfacedealloc(badtetrahedrons, remtet);
30817         remtet = badfacetraverse(badtetrahedrons);
30818       }
30819       for (i = 0; i < splittetlist->len(); i++) {
30820         remtet = (badface *)(* splittetlist)[i];
30821         // Make sure that the tet is still the same one when it was tested.
30822         //   Subsequent transformations may have made it a different tet.
30823         if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30824             dest(remtet->tt) == remtet->fdest &&
30825             apex(remtet->tt) == remtet->fapex &&
30826             oppo(remtet->tt) == remtet->foppo) {
30827           // The sliver may get smoothed due to a neighboring tet.
30828           curdihed = facedihedral(remtet->forg, remtet->fdest, remtet->fapex,
30829                                   remtet->foppo);
30830           // The dihedral angle of a tet must less than PI, correct it.
30831           if (curdihed > PI) curdihed = 2 * PI - curdihed;
30832           // Is it a large angle?
30833           if (curdihed > objdihed) {
30834             remtet->key = cos(curdihed);
30835             if (b->verbose > 1) {
30836               printf("    Get sliver (%d, %d, %d, %d) %g (degree).\n",
30837                      pointmark(remtet->forg), pointmark(remtet->fdest),
30838                      pointmark(remtet->fapex), pointmark(remtet->foppo),
30839                      acos(remtet->key) / PI * 180.0);
30840             }
30841             if (!removeedge(remtet, optflag)) {
30842               if (!smoothsliver(remtet, tetlist)) {
30843                 splitsliver(remtet, tetlist, ceillist);
30844               }
30845             }
30846           }
30847         }
30848       }
30849       iter++;
30850     } while ((badtetrahedrons->items > 0l) && (iter < b->optpasses));
30851 
30852     if (b->verbose) {
30853       printf("  %d passes.\n", iter);
30854       if ((points->items - oldnum) > 0l) {
30855         printf("  %ld points are inserted (%d on segment).\n",
30856                points->items - oldnum, smoothsegverts);
30857       }
30858       if (optcount[1] > 0l) {
30859         printf("  %ld faces are flipped.\n", optcount[1]);
30860       }
30861       if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30862           optcount[9] > 0l) {
30863         printf("  %ld edges are flipped.\n", optcount[3] + optcount[4] +
30864                optcount[5] + optcount[6] + optcount[9]);
30865       }
30866       // if (badtetrahedrons->items > 0l) {
30867       //   printf("  %ld edges remain.\n", badtetrahedrons->items);
30868       // }
30869     }
30870     delete tetlist;
30871     delete ceillist;
30872     delete splittetlist;
30873   }
30874 
30875   delete badtetrahedrons;
30876   badtetrahedrons = (memorypool *) NULL;
30877 }
30878 
30879 //
30880 // End of mesh optimization routines
30881 //
30882 
30883 //
30884 // Begin of I/O rouitnes
30885 //
30886 
30888 //                                                                           //
30889 // transfernodes()    Transfer nodes from 'io->pointlist' to 'this->points'. //
30890 //                                                                           //
30891 // Initializing 'this->points'.  Transferring all points from 'in->pointlist'//
30892 // into it. All points are indexed (start from in->firstnumber).  Each point //
30893 // is initialized be UNUSEDVERTEX.  The bounding box (xmin, xmax, ymin, ymax,//
30894 // zmin, zmax) and the diameter (longest) of the point set are calculated.   //
30895 //                                                                           //
30897 
30898 void tetgenmesh::transfernodes()
30899 {
30900   point pointloop;
30901   REAL x, y, z;
30902   int coordindex;
30903   int attribindex;
30904   int mtrindex;
30905   int i, j;
30906 
30907   // Read the points.
30908   coordindex = 0;
30909   attribindex = 0;
30910   mtrindex = 0;
30911   for (i = 0; i < in->numberofpoints; i++) {
30912     makepoint(&pointloop);
30913     // Read the point coordinates.
30914     x = pointloop[0] = in->pointlist[coordindex++];
30915     y = pointloop[1] = in->pointlist[coordindex++];
30916     z = pointloop[2] = in->pointlist[coordindex++];
30917     // Read the point attributes.
30918     for (j = 0; j < in->numberofpointattributes; j++) {
30919       pointloop[3 + j] = in->pointattributelist[attribindex++];
30920     }
30921     // Read the point metric tensor.
30922     for (j = 0; j < in->numberofpointmtrs; j++) {
30923       pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
30924     }
30925     // Determine the smallest and largests x, y and z coordinates.
30926     if (i == 0) {
30927       xmin = xmax = x;
30928       ymin = ymax = y;
30929       zmin = zmax = z;
30930     } else {
30931       xmin = (x < xmin) ? x : xmin;
30932       xmax = (x > xmax) ? x : xmax;
30933       ymin = (y < ymin) ? y : ymin;
30934       ymax = (y > ymax) ? y : ymax;
30935       zmin = (z < zmin) ? z : zmin;
30936       zmax = (z > zmax) ? z : zmax;
30937     }
30938   }
30939   // 'longest' is the largest possible edge length formed by input vertices.
30940   x = xmax - xmin;
30941   y = ymax - ymin;
30942   z = zmax - zmin;
30943   longest = sqrt(x * x + y * y + z * z);
30944   if (longest == 0.0) {
30945     printf("Error:  The point set is trivial.\n");
30946     terminatetetgen(1);
30947   }
30948   // Two identical points are distinguished by 'lengthlimit'.
30949   lengthlimit = longest * b->epsilon * 1e+2;
30950 }
30951 
30953 //                                                                           //
30954 // jettisonnodes()    Jettison unused or duplicated vertices.                //
30955 //                                                                           //
30956 // Unused points are those input points which are outside the mesh domain or //
30957 // have no connection (isolated) to the mesh.  Duplicated points exist for   //
30958 // example if the input PLC is read from a .stl mesh file (marked during the //
30959 // Delaunay tetrahedralization step. This routine remove these points from   //
30960 // points list. All existing points are reindexed.                           //
30961 //                                                                           //
30963 
30964 void tetgenmesh::jettisonnodes()
30965 {
30966   point pointloop;
30967   bool jetflag;
30968   int oldidx, newidx;
30969   int remcount;
30970 
30971   if (!b->quiet) {
30972     printf("Jettisoning redundants points.\n");
30973   }
30974 
30975   points->traversalinit();
30976   pointloop = pointtraverse();
30977   oldidx = newidx = 0; // in->firstnumber;
30978   remcount = 0;
30979   while (pointloop != (point) NULL) {
30980     jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) ||
30981       (pointtype(pointloop) == UNUSEDVERTEX);
30982     if (jetflag) {
30983       // It is a duplicated point, delete it.
30984       pointdealloc(pointloop);
30985       remcount++;
30986     } else {
30987       // Re-index it.
30988       setpointmark(pointloop, newidx + in->firstnumber);
30989       if (in->pointmarkerlist != (int *) NULL) {
30990         if (oldidx < in->numberofpoints) {
30991           // Re-index the point marker as well.
30992           in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
30993         }
30994       }
30995       newidx++;
30996     }
30997     oldidx++;
30998     if (oldidx == in->numberofpoints) {
30999       // Update the numbe of input points (Because some were removed).
31000       in->numberofpoints -= remcount;
31001       // Remember this number for output original input nodes.
31002       jettisoninverts = remcount;
31003     }
31004     pointloop = pointtraverse();
31005   }
31006   if (b->verbose) {
31007     printf("  %d duplicated vertices have been removed.\n", dupverts);
31008     printf("  %d unused vertices have been removed.\n", unuverts);
31009   }
31010   dupverts = 0;
31011   unuverts = 0;
31012 
31013   // The following line ensures that dead items in the pool of nodes cannot
31014   //   be allocated for the new created nodes. This ensures that the input
31015   //   nodes will occur earlier in the output files, and have lower indices.
31016   points->deaditemstack = (void *) NULL;
31017 }
31018 
31020 //                                                                           //
31021 // highorder()   Create extra nodes for quadratic subparametric elements.    //
31022 //                                                                           //
31023 // 'highordertable' is an array (size = numberoftetrahedra * 6) for storing  //
31024 // high-order nodes of each tetrahedron.  This routine is used only when -o2 //
31025 // switch is used.                                                           //
31026 //                                                                           //
31028 
31029 void tetgenmesh::highorder()
31030 {
31031   triface tetloop, worktet;
31032   triface spintet, adjtet;
31033   point torg, tdest, tapex;
31034   point *extralist, *adjextralist;
31035   point newpoint;
31036   int hitbdry, ptmark;
31037   int i, j;
31038 
31039   if (!b->quiet) {
31040     printf("Adding vertices for second-order tetrahedra.\n");
31041   }
31042 
31043   // Initialize the 'highordertable'.
31044   highordertable = new point[tetrahedrons->items * 6];
31045   if (highordertable == (point *) NULL) {
31046     printf("Error:  Out of memory.\n");
31047     terminatetetgen(1);
31048   }
31049 
31050   // The following line ensures that dead items in the pool of nodes cannot
31051   //   be allocated for the extra nodes associated with high order elements.
31052   //   This ensures that the primary nodes (at the corners of elements) will
31053   //   occur earlier in the output files, and have lower indices, than the
31054   //   extra nodes.
31055   points->deaditemstack = (void *) NULL;
31056 
31057   // Assign an entry for each tetrahedron to find its extra nodes. At the
31058   //   mean while, initialize all extra nodes be NULL.
31059   i = 0;
31060   tetrahedrons->traversalinit();
31061   tetloop.tet = tetrahedrontraverse();
31062   while (tetloop.tet != (tetrahedron *) NULL) {
31063     tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
31064     for (j = 0; j < 6; j++) {
31065       highordertable[i + j] = (point) NULL;
31066     }
31067     i += 6;
31068     tetloop.tet = tetrahedrontraverse();
31069   }
31070 
31071   // To create a unique node on each edge. Loop over all tetrahedra, and
31072   //   look at the six edges of each tetrahedron.  If the extra node in
31073   //   the tetrahedron corresponding to this edge is NULL, create a node
31074   //   for this edge, at the same time, set the new node into the extra
31075   //   node lists of all other tetrahedra sharing this edge.
31076   tetrahedrons->traversalinit();
31077   tetloop.tet = tetrahedrontraverse();
31078   while (tetloop.tet != (tetrahedron *) NULL) {
31079     // Get the list of extra nodes.
31080     extralist = (point *) tetloop.tet[highorderindex];
31081     worktet.tet = tetloop.tet;
31082     for (i = 0; i < 6; i++) {
31083       if (extralist[i] == (point) NULL) {
31084         // Operate on this edge.
31085         worktet.loc = edge2locver[i][0];
31086         worktet.ver = edge2locver[i][1];
31087         // Create a new node on this edge.
31088         torg = org(worktet);
31089         tdest = dest(worktet);
31090         // Create a new node in the middle of the edge.
31091         newpoint = (point) points->alloc();
31092         // Interpolate its attributes.
31093         for (j = 0; j < 3 + in->numberofpointattributes; j++) {
31094           newpoint[j] = 0.5 * (torg[j] + tdest[j]);
31095         }
31096         ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
31097         setpointmark(newpoint, ptmark);
31098         // Add this node to its extra node list.
31099         extralist[i] = newpoint;
31100         // Set 'newpoint' into extra node lists of other tetrahedra
31101         //   sharing this edge.
31102         tapex = apex(worktet);
31103         spintet = worktet;
31104         hitbdry = 0;
31105         while (hitbdry < 2) {
31106           if (fnextself(spintet)) {
31107             // Get the extra node list of 'spintet'.
31108             adjextralist = (point *) spintet.tet[highorderindex];
31109             // Find the index of its extra node list.
31110             j = locver2edge[spintet.loc][spintet.ver];
31111             // Only set 'newpoint' into 'adjextralist' if it is a NULL.
31112             //   Because two faces can belong to the same tetrahedron.
31113             if (adjextralist[j] == (point) NULL) {
31114               adjextralist[j] = newpoint;
31115             }
31116             if (apex(spintet) == tapex) {
31117               break;
31118             }
31119           } else {
31120             hitbdry++;
31121             if (hitbdry < 2) {
31122               esym(worktet, spintet);
31123         }
31124           }
31125         }
31126       }
31127     }
31128     tetloop.tet = tetrahedrontraverse();
31129   }
31130 }
31131 
31133 //                                                                           //
31134 // outnodes()    Output the points to a .node file or a tetgenio structure.  //
31135 //                                                                           //
31136 // Note: each point has already been numbered on input (the first index is   //
31137 // 'in->firstnumber').                                                       //
31138 //                                                                           //
31140 
31141 void tetgenmesh::outnodes(tetgenio* out)
31142 {
31143   FILE *outfile;
31144   char outnodefilename[FILENAMESIZE];
31145   shellface subptr;
31146   triface adjtet;
31147   face subloop;
31148   point pointloop;
31149   point *extralist, ep[3];
31150   int nextras, bmark, shmark, marker;
31151   int coordindex, attribindex;
31152   int pointnumber, firstindex;
31153   int index, i;
31154 
31155   if (out == (tetgenio *) NULL) {
31156     strcpy(outnodefilename, b->outfilename);
31157     strcat(outnodefilename, ".node");
31158   }
31159 
31160   if (!b->quiet) {
31161     if (out == (tetgenio *) NULL) {
31162       printf("Writing %s.\n", outnodefilename);
31163     } else {
31164       printf("Writing nodes.\n");
31165     }
31166   }
31167 
31168   nextras = in->numberofpointattributes;
31169   bmark = !b->nobound && in->pointmarkerlist;
31170 
31171   // Avoid compile warnings.
31172   outfile = (FILE *) NULL;
31173   marker = coordindex = 0;
31174 
31175   if (out == (tetgenio *) NULL) {
31176     outfile = fopen(outnodefilename, "w");
31177     if (outfile == (FILE *) NULL) {
31178       printf("File I/O Error:  Cannot create file %s.\n", outnodefilename);
31179       terminatetetgen(1);
31180     }
31181     // Number of points, number of dimensions, number of point attributes,
31182     //   and number of boundary markers (zero or one).
31183     fprintf(outfile, "%ld  %d  %d  %d\n", points->items, 3, nextras, bmark);
31184   } else {
31185     // Allocate space for 'pointlist';
31186     out->pointlist = new REAL[points->items * 3];
31187     if (out->pointlist == (REAL *) NULL) {
31188       printf("Error:  Out of memory.\n");
31189       terminatetetgen(1);
31190     }
31191     // Allocate space for 'pointattributelist' if necessary;
31192     if (nextras > 0) {
31193       out->pointattributelist = new REAL[points->items * nextras];
31194       if (out->pointattributelist == (REAL *) NULL) {
31195         printf("Error:  Out of memory.\n");
31196         terminatetetgen(1);
31197       }
31198     }
31199     // Allocate space for 'pointmarkerlist' if necessary;
31200     if (bmark) {
31201       out->pointmarkerlist = new int[points->items];
31202       if (out->pointmarkerlist == (int *) NULL) {
31203         printf("Error:  Out of memory.\n");
31204         terminatetetgen(1);
31205       }
31206     }
31207     out->numberofpoints = points->items;
31208     out->numberofpointattributes = nextras;
31209     coordindex = 0;
31210     attribindex = 0;
31211   }
31212 
31213   if (bmark && (b->plc || b->refine)) {
31214     // Initialize the point2tet field of each point.
31215     points->traversalinit();
31216     pointloop = pointtraverse();
31217     while (pointloop != (point) NULL) {
31218       setpoint2tet(pointloop, (tetrahedron) NULL);
31219       pointloop = pointtraverse();
31220     }
31221     // Make a map point-to-subface. Hence a boundary point will get the
31222     //   facet marker from that facet where it lies on.
31223     subfaces->traversalinit();
31224     subloop.sh = shellfacetraverse(subfaces);
31225     while (subloop.sh != (shellface *) NULL) {
31226       subloop.shver = 0;
31227       // Check all three points of the subface.
31228       for (i = 0; i < 3; i++) {
31229         pointloop = (point) subloop.sh[3 + i];
31230         setpoint2tet(pointloop, (tetrahedron) sencode(subloop));
31231       }
31232       if (b->order == 2) {
31233         // '-o2' switch. Set markers for quadratic nodes of this subface.
31234         stpivot(subloop, adjtet);
31235         if (adjtet.tet == dummytet) {
31236           sesymself(subloop);
31237           stpivot(subloop, adjtet);
31238         }
31239         assert(adjtet.tet != dummytet);
31240         extralist = (point *) adjtet.tet[highorderindex];
31241         switch (adjtet.loc) {
31242         case 0:
31243           ep[0] = extralist[0];
31244           ep[1] = extralist[1];
31245           ep[2] = extralist[2];
31246           break;
31247         case 1:
31248           ep[0] = extralist[0];
31249           ep[1] = extralist[4];
31250           ep[2] = extralist[3];
31251           break;
31252         case 2:
31253           ep[0] = extralist[1];
31254           ep[1] = extralist[5];
31255           ep[2] = extralist[4];
31256           break;
31257         case 3:
31258           ep[0] = extralist[2];
31259           ep[1] = extralist[3];
31260           ep[2] = extralist[5];
31261           break;
31262         default: break;
31263         }
31264         for (i = 0; i < 3; i++) {
31265           setpoint2tet(ep[i], (tetrahedron) sencode(subloop));
31266         }
31267       }
31268       subloop.sh = shellfacetraverse(subfaces);
31269     }
31270   }
31271 
31272   // Determine the first index (0 or 1).
31273   firstindex = b->zeroindex ? 0 : in->firstnumber;
31274 
31275   points->traversalinit();
31276   pointloop = pointtraverse();
31277   pointnumber = firstindex; // in->firstnumber;
31278   index = 0;
31279   while (pointloop != (point) NULL) {
31280     if (bmark) {
31281       // Default the vertex has a zero marker.
31282       marker = 0;
31283       // Is it an input vertex?
31284       if (index < in->numberofpoints) {
31285         // Input point's marker is directly copied to output.
31286         marker = in->pointmarkerlist[index];
31287       }
31288       // Is it a boundary vertex has marker zero?
31289       if ((marker == 0) && (b->plc || b->refine)) {
31290         subptr = (shellface) point2tet(pointloop);
31291         if (subptr != (shellface) NULL) {
31292           // Default a boundary vertex has marker 1.
31293           marker = 1;
31294           if (in->facetmarkerlist != (int *) NULL) {
31295             // The vertex gets the marker from the facet it lies on.
31296             sdecode(subptr, subloop);
31297             shmark = shellmark(subloop);
31298             marker = in->facetmarkerlist[shmark - 1];
31299           }
31300         }
31301       }
31302     }
31303     if (out == (tetgenio *) NULL) {
31304       // Point number, x, y and z coordinates.
31305       fprintf(outfile, "%4d    %.17g  %.17g  %.17g", pointnumber,
31306               pointloop[0], pointloop[1], pointloop[2]);
31307       for (i = 0; i < nextras; i++) {
31308         // Write an attribute.
31309         fprintf(outfile, "  %.17g", pointloop[3 + i]);
31310       }
31311       if (bmark) {
31312         // Write the boundary marker.
31313         fprintf(outfile, "    %d", marker);
31314       }
31315       fprintf(outfile, "\n");
31316     } else {
31317       // X, y, and z coordinates.
31318       out->pointlist[coordindex++] = pointloop[0];
31319       out->pointlist[coordindex++] = pointloop[1];
31320       out->pointlist[coordindex++] = pointloop[2];
31321       // Point attributes.
31322       for (i = 0; i < nextras; i++) {
31323         // Output an attribute.
31324         out->pointattributelist[attribindex++] = pointloop[3 + i];
31325       }
31326       if (bmark) {
31327         // Output the boundary marker.
31328         out->pointmarkerlist[index] = marker;
31329       }
31330     }
31331     pointloop = pointtraverse();
31332     pointnumber++;
31333     index++;
31334   }
31335 
31336   if (out == (tetgenio *) NULL) {
31337     fprintf(outfile, "# Generated by %s\n", b->commandline);
31338     fclose(outfile);
31339   }
31340 }
31341 
31343 //                                                                           //
31344 // outmetrics()    Output the metric to a file (*.mtr) or a tetgenio obj.    //
31345 //                                                                           //
31347 
31348 void tetgenmesh::outmetrics(tetgenio* out)
31349 {
31350   FILE *outfile;
31351   char outmtrfilename[FILENAMESIZE];
31352   list *tetlist, *ptlist;
31353   triface tetloop;
31354   point ptloop, neipt;
31355   REAL lave, len; // lmin, lmax,
31356   int mtrindex;
31357   int i;
31358 
31359   lave = 0.0;
31360 
31361   if (out == (tetgenio *) NULL) {
31362     strcpy(outmtrfilename, b->outfilename);
31363     strcat(outmtrfilename, ".mtr");
31364   }
31365 
31366   if (!b->quiet) {
31367     if (out == (tetgenio *) NULL) {
31368       printf("Writing %s.\n", outmtrfilename);
31369     } else {
31370       printf("Writing metrics.\n");
31371     }
31372   }
31373 
31374   // Avoid compile warnings.
31375   outfile = (FILE *) NULL;
31376   mtrindex = 0;
31377 
31378   if (out == (tetgenio *) NULL) {
31379     outfile = fopen(outmtrfilename, "w");
31380     if (outfile == (FILE *) NULL) {
31381       printf("File I/O Error:  Cannot create file %s.\n", outmtrfilename);
31382       terminatetetgen(1);
31383     }
31384     // Number of points, number of point metrices,
31385     // fprintf(outfile, "%ld  %d\n", points->items, sizeoftensor + 3);
31386     fprintf(outfile, "%ld  %d\n", points->items, 1);
31387   } else {
31388     // Allocate space for 'pointmtrlist' if necessary;
31389     // out->pointmtrlist = new REAL[points->items * (sizeoftensor + 3)];
31390     out->pointmtrlist = new REAL[points->items];
31391     if (out->pointmtrlist == (REAL *) NULL) {
31392       printf("Error:  Out of memory.\n");
31393       terminatetetgen(1);
31394     }
31395     out->numberofpointmtrs = 1; // (sizeoftensor + 3);
31396     mtrindex = 0;
31397   }
31398 
31399   // Initialize the point2tet field of each point.
31400   points->traversalinit();
31401   ptloop = pointtraverse();
31402   while (ptloop != (point) NULL) {
31403     setpoint2tet(ptloop, (tetrahedron) NULL);
31404     ptloop = pointtraverse();
31405   }
31406   // Create the point-to-tet map.
31407   tetrahedrons->traversalinit();
31408   tetloop.tet = tetrahedrontraverse();
31409   while (tetloop.tet != (tetrahedron *) NULL) {
31410     for (i = 0; i < 4; i++) {
31411       ptloop = (point) tetloop.tet[4 + i];
31412       setpoint2tet(ptloop, encode(tetloop));
31413     }
31414     tetloop.tet = tetrahedrontraverse();
31415   }
31416 
31417   tetlist = new list(sizeof(triface), NULL, 256);
31418   ptlist = new list(sizeof(point *), NULL, 256);
31419 
31420   points->traversalinit();
31421   ptloop = pointtraverse();
31422   while (ptloop != (point) NULL) {
31423     decode(point2tet(ptloop), tetloop);
31424     if (!isdead(&tetloop)) {
31425       // Form the star of p.
31426       tetlist->append(&tetloop);
31427       formstarpolyhedron(ptloop, tetlist, ptlist, true);
31428       // lmin = longest;
31429       // lmax = 0.0;
31430       lave = 0.0;
31431       for (i = 0; i < ptlist->len(); i++) {
31432         neipt = * (point *)(* ptlist)[i];
31433         len = distance(ptloop, neipt);
31434         // lmin = lmin < len ? lmin : len;
31435         // lmax = lmax > len ? lmax : len;
31436         lave += len;
31437       }
31438       lave /= ptlist->len();
31439     }
31440     if (out == (tetgenio *) NULL) {
31441       // for (i = 0; i < sizeoftensor; i++) {
31442       //   fprintf(outfile, "%-16.8e ", ptloop[pointmtrindex + i]);
31443       // }
31444       if (ptlist->len() > 0) {
31445         // fprintf(outfile, "%-16.8e %-16.8e %-16.8e", lmin, lmax, lave);
31446         fprintf(outfile, "%-16.8e ", lave);
31447       } else {
31448         fprintf(outfile, "0.0 "); // fprintf(outfile, "0.0  0.0  0.0");
31449       }
31450       fprintf(outfile, "\n");
31451     } else {
31452       // for (i = 0; i < sizeoftensor; i++) {
31453       //   out->pointmtrlist[mtrindex++] = ptloop[pointmtrindex + i];
31454       // }
31455       if (ptlist->len() > 0) {
31456         // out->pointmtrlist[mtrindex++] = lmin;
31457         // out->pointmtrlist[mtrindex++] = lmax;
31458         out->pointmtrlist[mtrindex++] = lave;
31459       } else {
31460         // out->pointmtrlist[mtrindex++] = 0.0;
31461         // out->pointmtrlist[mtrindex++] = 0.0;
31462         out->pointmtrlist[mtrindex++] = 0.0;
31463       }
31464     }
31465     tetlist->clear();
31466     ptlist->clear();
31467     ptloop = pointtraverse();
31468   }
31469 
31470   delete tetlist;
31471   delete ptlist;
31472 
31473   if (out == (tetgenio *) NULL) {
31474     fprintf(outfile, "# Generated by %s\n", b->commandline);
31475     fclose(outfile);
31476   }
31477 }
31478 
31480 //                                                                           //
31481 // outelements()    Output the tetrahedra to an .ele file or a tetgenio      //
31482 //                  structure.                                               //
31483 //                                                                           //
31485 
31486 void tetgenmesh::outelements(tetgenio* out)
31487 {
31488   FILE *outfile;
31489   char outelefilename[FILENAMESIZE];
31490   tetrahedron* tptr;
31491   int *tlist;
31492   REAL *talist;
31493   int firstindex, shift;
31494   int pointindex;
31495   int attribindex;
31496   point p1, p2, p3, p4;
31497   point *extralist;
31498   int elementnumber;
31499   int eextras;
31500   int i;
31501 
31502   if (out == (tetgenio *) NULL) {
31503     strcpy(outelefilename, b->outfilename);
31504     strcat(outelefilename, ".ele");
31505   }
31506 
31507   if (!b->quiet) {
31508     if (out == (tetgenio *) NULL) {
31509       printf("Writing %s.\n", outelefilename);
31510     } else {
31511       printf("Writing elements.\n");
31512     }
31513   }
31514 
31515   // Avoid compile warnings.
31516   outfile = (FILE *) NULL;
31517   tlist = (int *) NULL;
31518   talist = (double *) NULL;
31519   pointindex = attribindex = 0;
31520 
31521   eextras = in->numberoftetrahedronattributes;
31522   if (out == (tetgenio *) NULL) {
31523     outfile = fopen(outelefilename, "w");
31524     if (outfile == (FILE *) NULL) {
31525       printf("File I/O Error:  Cannot create file %s.\n", outelefilename);
31526       terminatetetgen(1);
31527     }
31528     // Number of tetras, points per tetra, attributes per tetra.
31529     fprintf(outfile, "%ld  %d  %d\n", tetrahedrons->items,
31530             b->order == 1 ? 4 : 10, eextras);
31531   } else {
31532     // Allocate memory for output tetrahedra.
31533     out->tetrahedronlist = new int[tetrahedrons->items *
31534                                    (b->order == 1 ? 4 : 10)];
31535     if (out->tetrahedronlist == (int *) NULL) {
31536       printf("Error:  Out of memory.\n");
31537       terminatetetgen(1);
31538     }
31539     // Allocate memory for output tetrahedron attributes if necessary.
31540     if (eextras > 0) {
31541       out->tetrahedronattributelist = new REAL[tetrahedrons->items * eextras];
31542       if (out->tetrahedronattributelist == (REAL *) NULL) {
31543         printf("Error:  Out of memory.\n");
31544         terminatetetgen(1);
31545       }
31546     }
31547     out->numberoftetrahedra = tetrahedrons->items;
31548     out->numberofcorners = b->order == 1 ? 4 : 10;
31549     out->numberoftetrahedronattributes = eextras;
31550     tlist = out->tetrahedronlist;
31551     talist = out->tetrahedronattributelist;
31552     pointindex = 0;
31553     attribindex = 0;
31554   }
31555 
31556   // Determine the first index (0 or 1).
31557   firstindex = b->zeroindex ? 0 : in->firstnumber;
31558   shift = 0; // Default no shiftment.
31559   if ((in->firstnumber == 1) && (firstindex == 0)) {
31560     shift = 1; // Shift the output indices by 1.
31561   }
31562 
31563   tetrahedrons->traversalinit();
31564   tptr = tetrahedrontraverse();
31565   elementnumber = firstindex; // in->firstnumber;
31566   while (tptr != (tetrahedron *) NULL) {
31567     p1 = (point) tptr[4];
31568     p2 = (point) tptr[5];
31569     p3 = (point) tptr[6];
31570     p4 = (point) tptr[7];
31571     if (out == (tetgenio *) NULL) {
31572       // Tetrahedron number, indices for four points.
31573       fprintf(outfile, "%5d   %5d %5d %5d %5d", elementnumber,
31574               pointmark(p1) - shift, pointmark(p2) - shift,
31575               pointmark(p3) - shift, pointmark(p4) - shift);
31576       if (b->order == 2) {
31577         extralist = (point *) tptr[highorderindex];
31578         // Tetrahedron number, indices for four points plus six extra points.
31579         fprintf(outfile, "  %5d %5d %5d %5d %5d %5d",
31580           pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
31581           pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
31582           pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
31583       }
31584       for (i = 0; i < eextras; i++) {
31585         fprintf(outfile, "    %.17g", elemattribute(tptr, i));
31586       }
31587       fprintf(outfile, "\n");
31588     } else {
31589       tlist[pointindex++] = pointmark(p1) - shift;
31590       tlist[pointindex++] = pointmark(p2) - shift;
31591       tlist[pointindex++] = pointmark(p3) - shift;
31592       tlist[pointindex++] = pointmark(p4) - shift;
31593       if (b->order == 2) {
31594         extralist = (point *) tptr[highorderindex];
31595         tlist[pointindex++] = pointmark(extralist[0]) - shift;
31596         tlist[pointindex++] = pointmark(extralist[1]) - shift;
31597         tlist[pointindex++] = pointmark(extralist[2]) - shift;
31598         tlist[pointindex++] = pointmark(extralist[3]) - shift;
31599         tlist[pointindex++] = pointmark(extralist[4]) - shift;
31600         tlist[pointindex++] = pointmark(extralist[5]) - shift;
31601       }
31602       for (i = 0; i < eextras; i++) {
31603         talist[attribindex++] = elemattribute(tptr, i);
31604       }
31605     }
31606     if (b->neighout) {
31607       // Remember the index of this element.
31608       * (int *) (tptr + elemmarkerindex) = elementnumber;
31609     }
31610     tptr = tetrahedrontraverse();
31611     elementnumber++;
31612   }
31613   if (b->neighout) {
31614     // Set the outside element marker.
31615     * (int *) (dummytet + elemmarkerindex) = -1;
31616   }
31617 
31618   if (out == (tetgenio *) NULL) {
31619     fprintf(outfile, "# Generated by %s\n", b->commandline);
31620     fclose(outfile);
31621   }
31622 }
31623 
31625 //                                                                           //
31626 // outfaces()    Output all faces to a .face file or a tetgenio structure.   //
31627 //                                                                           //
31628 // This routines outputs all triangular faces (including outer boundary      //
31629 // faces and inner faces) of this mesh.                                      //
31630 //                                                                           //
31632 
31633 void tetgenmesh::outfaces(tetgenio* out)
31634 {
31635   FILE *outfile;
31636   char facefilename[FILENAMESIZE];
31637   int *elist;
31638   int *emlist;
31639   int neigh1, neigh2;
31640   int index;
31641   triface tface, tsymface;
31642   face checkmark;
31643   point torg, tdest, tapex;
31644   long faces;
31645   int bmark, faceid, marker;
31646   int firstindex, shift;
31647   int facenumber;
31648 
31649   neigh1 = 0;
31650   neigh2 = 0;
31651 
31652   if (out == (tetgenio *) NULL) {
31653     strcpy(facefilename, b->outfilename);
31654     strcat(facefilename, ".face");
31655   }
31656 
31657   if (!b->quiet) {
31658     if (out == (tetgenio *) NULL) {
31659       printf("Writing %s.\n", facefilename);
31660     } else {
31661       printf("Writing faces.\n");
31662     }
31663   }
31664 
31665   // Avoid compile warnings.
31666   outfile = (FILE *) NULL;
31667   elist = (int *) NULL;
31668   emlist = (int *) NULL;
31669   index =  marker = 0;
31670 
31671   faces = (4l * tetrahedrons->items + hullsize) / 2l;
31672   bmark = !b->nobound && in->facetmarkerlist;
31673 
31674   if (out == (tetgenio *) NULL) {
31675     outfile = fopen(facefilename, "w");
31676     if (outfile == (FILE *) NULL) {
31677       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31678       terminatetetgen(1);
31679     }
31680     fprintf(outfile, "%ld  %d\n", faces, bmark);
31681   } else {
31682     // Allocate memory for 'trifacelist'.
31683     out->trifacelist = new int[faces * 3];
31684     if (out->trifacelist == (int *) NULL) {
31685       printf("Error:  Out of memory.\n");
31686       terminatetetgen(1);
31687     }
31688     // Allocate memory for 'trifacemarkerlist' if necessary.
31689     if (bmark) {
31690       out->trifacemarkerlist = new int[faces];
31691       if (out->trifacemarkerlist == (int *) NULL) {
31692         printf("Error:  Out of memory.\n");
31693         terminatetetgen(1);
31694       }
31695     }
31696     if (b->neighout > 1) {
31697       // '-nn' switch.
31698       out->adjtetlist = new int[subfaces->items * 2];
31699       if (out->adjtetlist == (int *) NULL) {
31700         printf("Error:  Out of memory.\n");
31701         terminatetetgen(1);
31702       }
31703     }
31704     out->numberoftrifaces = faces;
31705     elist = out->trifacelist;
31706     emlist = out->trifacemarkerlist;
31707     index = 0;
31708   }
31709 
31710   // Determine the first index (0 or 1).
31711   firstindex = b->zeroindex ? 0 : in->firstnumber;
31712   shift = 0; // Default no shiftment.
31713   if ((in->firstnumber == 1) && (firstindex == 0)) {
31714     shift = 1; // Shift the output indices by 1.
31715   }
31716 
31717   tetrahedrons->traversalinit();
31718   tface.tet = tetrahedrontraverse();
31719   facenumber = firstindex; // in->firstnumber;
31720   // To loop over the set of faces, loop over all tetrahedra, and look at
31721   //   the four faces of each one. If there isn't another tetrahedron
31722   //   adjacent to this face, operate on the face.  If there is another
31723   //   adjacent tetrahedron, operate on the face only if the current
31724   //   tetrahedron has a smaller pointer than its neighbor.  This way, each
31725   //   face is considered only once.
31726   while (tface.tet != (tetrahedron *) NULL) {
31727     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31728       sym(tface, tsymface);
31729       if ((tsymface.tet == dummytet) || (tface.tet < tsymface.tet)) {
31730         torg = org(tface);
31731         tdest = dest(tface);
31732         tapex = apex(tface);
31733         if (bmark) {
31734           // Get the boundary marker of this face. If it is an inner face,
31735           //   it has no boundary marker, set it be zero.
31736           if (b->useshelles) {
31737             // Shell face is used.
31738             tspivot(tface, checkmark);
31739             if (checkmark.sh == dummysh) {
31740               marker = 0;  // It is an inner face.
31741             } else {
31742               faceid = shellmark(checkmark) - 1;
31743               marker = in->facetmarkerlist[faceid];
31744             }
31745           } else {
31746             // Shell face is not used, only distinguish outer and inner face.
31747             marker = tsymface.tet != dummytet ? 1 : 0;
31748           }
31749         }
31750         if (b->neighout > 1) {
31751           // '-nn' switch. Output adjacent tets indices.
31752           neigh1 = * (int *)(tface.tet + elemmarkerindex);
31753           if (tsymface.tet != dummytet) {
31754             neigh2 = * (int *)(tsymface.tet + elemmarkerindex);
31755           } else {
31756             neigh2 = -1;
31757           }
31758         }
31759         if (out == (tetgenio *) NULL) {
31760           // Face number, indices of three vertices.
31761           fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
31762                   pointmark(torg) - shift, pointmark(tdest) - shift,
31763                   pointmark(tapex) - shift);
31764           if (bmark) {
31765             // Output a boundary marker.
31766             fprintf(outfile, "  %d", marker);
31767           }
31768           if (b->neighout > 1) {
31769             fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
31770           }
31771           fprintf(outfile, "\n");
31772         } else {
31773           // Output indices of three vertices.
31774           elist[index++] = pointmark(torg) - shift;
31775           elist[index++] = pointmark(tdest) - shift;
31776           elist[index++] = pointmark(tapex) - shift;
31777           if (bmark) {
31778             emlist[facenumber - in->firstnumber] = marker;
31779           }
31780           if (b->neighout > 1) {
31781             out->adjtetlist[(facenumber - in->firstnumber) * 2]     = neigh1;
31782             out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
31783           }
31784         }
31785         facenumber++;
31786       }
31787     }
31788     tface.tet = tetrahedrontraverse();
31789   }
31790 
31791   if (out == (tetgenio *) NULL) {
31792     fprintf(outfile, "# Generated by %s\n", b->commandline);
31793     fclose(outfile);
31794   }
31795 }
31796 
31798 //                                                                           //
31799 // outhullfaces()    Output outer boundary faces to a .face file or a        //
31800 //                   tetgenio structure.                                     //
31801 //                                                                           //
31802 // The normal of each face is arranged to point inside of the domain (use    //
31803 // right-hand rule).  This routines will outputs convex hull faces if the    //
31804 // mesh is a Delaunay tetrahedralization.                                    //
31805 //                                                                           //
31807 
31808 void tetgenmesh::outhullfaces(tetgenio* out)
31809 {
31810   FILE *outfile;
31811   char facefilename[FILENAMESIZE];
31812   int *elist;
31813   int index;
31814   triface tface, tsymface;
31815   face checkmark;
31816   point torg, tdest, tapex;
31817   int firstindex, shift;
31818   int facenumber;
31819 
31820   if (out == (tetgenio *) NULL) {
31821     strcpy(facefilename, b->outfilename);
31822     strcat(facefilename, ".face");
31823   }
31824 
31825   if (!b->quiet) {
31826     if (out == (tetgenio *) NULL) {
31827       printf("Writing %s.\n", facefilename);
31828     } else {
31829       printf("Writing faces.\n");
31830     }
31831   }
31832 
31833   // Avoid compile warnings.
31834   outfile = (FILE *) NULL;
31835   elist = (int *) NULL;
31836   index = 0;
31837 
31838   if (out == (tetgenio *) NULL) {
31839     outfile = fopen(facefilename, "w");
31840     if (outfile == (FILE *) NULL) {
31841       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31842       terminatetetgen(1);
31843     }
31844     fprintf(outfile, "%ld  0\n", hullsize);
31845   } else {
31846     // Allocate memory for 'trifacelist'.
31847     out->trifacelist = new int[hullsize * 3];
31848     if (out->trifacelist == (int *) NULL) {
31849       printf("Error:  Out of memory.\n");
31850       terminatetetgen(1);
31851     }
31852     out->numberoftrifaces = hullsize;
31853     elist = out->trifacelist;
31854     index = 0;
31855   }
31856 
31857   // Determine the first index (0 or 1).
31858   firstindex = b->zeroindex ? 0 : in->firstnumber;
31859   shift = 0; // Default no shiftment.
31860   if ((in->firstnumber == 1) && (firstindex == 0)) {
31861     shift = 1; // Shift the output indices by 1.
31862   }
31863 
31864   tetrahedrons->traversalinit();
31865   tface.tet = tetrahedrontraverse();
31866   facenumber = firstindex; // in->firstnumber;
31867   // To loop over the set of hull faces, loop over all tetrahedra, and look
31868   //   at the four faces of each one. If there isn't another tetrahedron
31869   //   adjacent to this face, operate on the face.
31870   while (tface.tet != (tetrahedron *) NULL) {
31871     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31872       sym(tface, tsymface);
31873       if (tsymface.tet == dummytet) {
31874         torg = org(tface);
31875         tdest = dest(tface);
31876         tapex = apex(tface);
31877         if (out == (tetgenio *) NULL) {
31878           // Face number, indices of three vertices.
31879           fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
31880                   pointmark(torg) - shift, pointmark(tdest) - shift,
31881                   pointmark(tapex) - shift);
31882           fprintf(outfile, "\n");
31883         } else {
31884           // Output indices of three vertices.
31885           elist[index++] = pointmark(torg) - shift;
31886           elist[index++] = pointmark(tdest) - shift;
31887           elist[index++] = pointmark(tapex) - shift;
31888         }
31889         facenumber++;
31890       }
31891     }
31892     tface.tet = tetrahedrontraverse();
31893   }
31894 
31895   if (out == (tetgenio *) NULL) {
31896     fprintf(outfile, "# Generated by %s\n", b->commandline);
31897     fclose(outfile);
31898   }
31899 }
31900 
31902 //                                                                           //
31903 // outsubfaces()    Output subfaces (i.e. boundary faces) to a .face file or //
31904 //                  a tetgenio structure.                                    //
31905 //                                                                           //
31906 // The boundary faces are exist in 'subfaces'. For listing triangle vertices //
31907 // in the same sense for all triangles in the mesh, the direction determined //
31908 // by right-hand rule is pointer to the inside of the volume.                //
31909 //                                                                           //
31911 
31912 void tetgenmesh::outsubfaces(tetgenio* out)
31913 {
31914   FILE *outfile;
31915   char facefilename[FILENAMESIZE];
31916   int *elist;
31917   int *emlist;
31918   int index, index1, index2;
31919   triface abuttingtet;
31920   face faceloop;
31921   point torg, tdest, tapex;
31922   int bmark, faceid, marker;
31923   int firstindex, shift;
31924   int neigh1, neigh2;
31925   int facenumber;
31926 
31927   if (out == (tetgenio *) NULL) {
31928     strcpy(facefilename, b->outfilename);
31929     strcat(facefilename, ".face");
31930   }
31931 
31932   if (!b->quiet) {
31933     if (out == (tetgenio *) NULL) {
31934       printf("Writing %s.\n", facefilename);
31935     } else {
31936       printf("Writing faces.\n");
31937     }
31938   }
31939 
31940   // Avoid compile warnings.
31941   outfile = (FILE *) NULL;
31942   elist = (int *) NULL;
31943   emlist = (int *) NULL;
31944   index = index1 = index2 = 0;
31945   faceid = marker = 0;
31946   neigh1 = neigh2 = 0;
31947 
31948   bmark = !b->nobound && in->facetmarkerlist;
31949 
31950   if (out == (tetgenio *) NULL) {
31951     outfile = fopen(facefilename, "w");
31952     if (outfile == (FILE *) NULL) {
31953       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31954       terminatetetgen(1);
31955     }
31956     // Number of subfaces.
31957     fprintf(outfile, "%ld  %d\n", subfaces->items, bmark);
31958   } else {
31959     // Allocate memory for 'trifacelist'.
31960     out->trifacelist = new int[subfaces->items * 3];
31961     if (out->trifacelist == (int *) NULL) {
31962       printf("Error:  Out of memory.\n");
31963       terminatetetgen(1);
31964     }
31965     if (bmark) {
31966       // Allocate memory for 'trifacemarkerlist'.
31967       out->trifacemarkerlist = new int[subfaces->items];
31968       if (out->trifacemarkerlist == (int *) NULL) {
31969         printf("Error:  Out of memory.\n");
31970         terminatetetgen(1);
31971       }
31972     }
31973     if (b->neighout > 1) {
31974       // '-nn' switch.
31975       out->adjtetlist = new int[subfaces->items * 2];
31976       if (out->adjtetlist == (int *) NULL) {
31977         printf("Error:  Out of memory.\n");
31978         terminatetetgen(1);
31979       }
31980     }
31981     out->numberoftrifaces = subfaces->items;
31982     elist = out->trifacelist;
31983     emlist = out->trifacemarkerlist;
31984   }
31985 
31986   // Determine the first index (0 or 1).
31987   firstindex = b->zeroindex ? 0 : in->firstnumber;
31988   shift = 0; // Default no shiftment.
31989   if ((in->firstnumber == 1) && (firstindex == 0)) {
31990     shift = 1; // Shift the output indices by 1.
31991   }
31992 
31993   subfaces->traversalinit();
31994   faceloop.sh = shellfacetraverse(subfaces);
31995   facenumber = firstindex; // in->firstnumber;
31996   while (faceloop.sh != (shellface *) NULL) {
31997     stpivot(faceloop, abuttingtet);
31998     if (abuttingtet.tet == dummytet) {
31999       sesymself(faceloop);
32000       stpivot(faceloop, abuttingtet);
32001     }
32002     if (abuttingtet.tet != dummytet) {
32003       // If there is a tetrahedron containing this subface, orient it so
32004       //   that the normal of this face points to inside of the volume by
32005       //   right-hand rule.
32006       adjustedgering(abuttingtet, CCW);
32007       torg = org(abuttingtet);
32008       tdest = dest(abuttingtet);
32009       tapex = apex(abuttingtet);
32010     } else {
32011       // This may happen when only a surface mesh be generated.
32012       torg = sorg(faceloop);
32013       tdest = sdest(faceloop);
32014       tapex = sapex(faceloop);
32015     }
32016     if (bmark) {
32017       faceid = shellmark(faceloop) - 1;
32018       marker = in->facetmarkerlist[faceid];
32019     }
32020     if (b->neighout > 1) {
32021       // '-nn' switch. Output adjacent tets indices.
32022       neigh1 = -1;
32023       stpivot(faceloop, abuttingtet);
32024       if (abuttingtet.tet != dummytet) {
32025         neigh1 = * (int *)(abuttingtet.tet + elemmarkerindex);
32026       }
32027       neigh2 = -1;
32028       sesymself(faceloop);
32029       stpivot(faceloop, abuttingtet);
32030       if (abuttingtet.tet != dummytet) {
32031         neigh2 = * (int *)(abuttingtet.tet + elemmarkerindex);
32032       }
32033     }
32034     if (out == (tetgenio *) NULL) {
32035       fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
32036               pointmark(torg) - shift, pointmark(tdest) - shift,
32037               pointmark(tapex) - shift);
32038       if (bmark) {
32039         fprintf(outfile, "    %d", marker);
32040       }
32041       if (b->neighout > 1) {
32042         fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
32043       }
32044       fprintf(outfile, "\n");
32045     } else {
32046       // Output three vertices of this face;
32047       elist[index++] = pointmark(torg) - shift;
32048       elist[index++] = pointmark(tdest) - shift;
32049       elist[index++] = pointmark(tapex) - shift;
32050       if (bmark) {
32051         emlist[index1++] = marker;
32052       }
32053       if (b->neighout > 1) {
32054         out->adjtetlist[index2++] = neigh1;
32055         out->adjtetlist[index2++] = neigh2;
32056       }
32057     }
32058     facenumber++;
32059     faceloop.sh = shellfacetraverse(subfaces);
32060   }
32061 
32062   if (out == (tetgenio *) NULL) {
32063     fprintf(outfile, "# Generated by %s\n", b->commandline);
32064     fclose(outfile);
32065   }
32066 }
32067 
32069 //                                                                           //
32070 // outedges()    Output all edges to a .edge file or a structure.            //
32071 //                                                                           //
32073 
32074 void tetgenmesh::outedges(tetgenio* out)
32075 {
32076   FILE *outfile;
32077   char edgefilename[FILENAMESIZE];
32078   int *elist, *emlist;
32079   int index, index1;
32080   triface tetloop, worktet, spintet;
32081   face checksh;
32082   point torg, tdest;
32083   long faces, edges;
32084   int firstindex, shift;
32085   int edgenumber, faceid, marker;
32086   int hitbdry, i;
32087 
32088   if (out == (tetgenio *) NULL) {
32089     strcpy(edgefilename, b->outfilename);
32090     strcat(edgefilename, ".edge");
32091   }
32092 
32093   if (!b->quiet) {
32094     if (out == (tetgenio *) NULL) {
32095       printf("Writing %s.\n", edgefilename);
32096     } else {
32097       printf("Writing edges.\n");
32098     }
32099   }
32100 
32101   // Avoid compile warnings.
32102   outfile = (FILE *) NULL;
32103   elist = (int *) NULL;
32104   emlist = (int *) NULL;
32105   index = index1 = 0;
32106   faceid = marker = 0;
32107 
32108   // Using the Euler formula (V-E+F-T=1) to get the total number of edges.
32109   faces = (4l * tetrahedrons->items + hullsize) / 2l;
32110   edges = points->items + faces - tetrahedrons->items - 1l;
32111 
32112   if (out == (tetgenio *) NULL) {
32113     outfile = fopen(edgefilename, "w");
32114     if (outfile == (FILE *) NULL) {
32115       printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
32116       terminatetetgen(1);
32117     }
32118     // Write the number of edges, boundary markers (0 or 1).
32119     fprintf(outfile, "%ld  %d\n", edges, !b->nobound);
32120   } else {
32121     // Allocate memory for 'edgelist'.
32122     out->edgelist = new int[edges * 2];
32123     if (out->edgelist == (int *) NULL) {
32124       printf("Error:  Out of memory.\n");
32125       terminatetetgen(1);
32126     }
32127     if (!b->nobound) {
32128       out->edgemarkerlist = new int[edges];
32129     }
32130     out->numberofedges = edges;
32131     elist = out->edgelist;
32132     emlist = out->edgemarkerlist;
32133   }
32134 
32135   // Determine the first index (0 or 1).
32136   firstindex = b->zeroindex ? 0 : in->firstnumber;
32137   shift = 0; // Default no shiftment.
32138   if ((in->firstnumber == 1) && (firstindex == 0)) {
32139     shift = 1; // Shift (reduce) the output indices by 1.
32140   }
32141 
32142   tetrahedrons->traversalinit();
32143   tetloop.tet = tetrahedrontraverse();
32144   edgenumber = firstindex; // in->firstnumber;
32145   while (tetloop.tet != (tetrahedron *) NULL) {
32146     // Count the number of Voronoi faces. Look at the six edges of each
32147     //   tetrahedron. Count the edge only if the tetrahedron's pointer is
32148     //   smaller than those of all other tetrahedra that share the edge.
32149     worktet.tet = tetloop.tet;
32150     for (i = 0; i < 6; i++) {
32151       worktet.loc = edge2locver[i][0];
32152       worktet.ver = edge2locver[i][1];
32153       adjustedgering(worktet, CW);
32154       spintet = worktet;
32155       hitbdry = 0;
32156       while (hitbdry < 2) {
32157         if (fnextself(spintet)) {
32158           if (apex(spintet) == apex(worktet)) break;
32159           if (spintet.tet < worktet.tet) break;
32160         } else {
32161           hitbdry++;
32162           if (hitbdry < 2) {
32163             esym(worktet, spintet);
32164             fnextself(spintet); // In the same tet.
32165       }
32166         }
32167       }
32168       // Count this edge if no adjacent tets are smaller than this tet.
32169       if (spintet.tet >= worktet.tet) {
32170         torg = org(worktet);
32171         tdest = dest(worktet);
32172         if (out == (tetgenio *) NULL) {
32173           fprintf(outfile, "%5d   %4d  %4d", edgenumber,
32174                   pointmark(torg) - shift, pointmark(tdest) - shift);
32175         } else {
32176           // Output three vertices of this face;
32177           elist[index++] = pointmark(torg) - shift;
32178           elist[index++] = pointmark(tdest) - shift;
32179         }
32180         if (!b->nobound) {
32181           if (hitbdry > 0) {
32182             // It is a boundary edge. Get the boundary marker of the facet
32183             //   containing this edge. Note there may have more than one
32184             //   facet, choose one arbitrarily.
32185             if ((b->plc || b->refine) && in->facetmarkerlist) {
32186               tspivot(spintet, checksh);
32187               faceid = shellmark(checksh) - 1;
32188               marker = in->facetmarkerlist[faceid];
32189             } else {
32190               marker = 1;  // Indicate it's a boundary edge.
32191             }
32192           } else {
32193             marker = 0;
32194           }
32195           if (out == (tetgenio *) NULL) {
32196             fprintf(outfile, "  %d", marker);
32197           } else {
32198             emlist[index1++] = marker;
32199           }
32200         }
32201         if (out == (tetgenio *) NULL) {
32202           fprintf(outfile, "\n");
32203         }
32204         edgenumber++;
32205       }
32206     }
32207     tetloop.tet = tetrahedrontraverse();
32208   }
32209 
32210   if (out == (tetgenio *) NULL) {
32211     fprintf(outfile, "# Generated by %s\n", b->commandline);
32212     fclose(outfile);
32213   }
32214 }
32215 
32217 //                                                                           //
32218 // outsubsegments()    Output segments to a .edge file or a structure.       //
32219 //                                                                           //
32221 
32222 void tetgenmesh::outsubsegments(tetgenio* out)
32223 {
32224   FILE *outfile;
32225   char edgefilename[FILENAMESIZE];
32226   int *elist;
32227   int index;
32228   face edgeloop;
32229   point torg, tdest;
32230   int firstindex, shift;
32231   int edgenumber;
32232 
32233   if (out == (tetgenio *) NULL) {
32234     strcpy(edgefilename, b->outfilename);
32235     strcat(edgefilename, ".edge");
32236   }
32237 
32238   if (!b->quiet) {
32239     if (out == (tetgenio *) NULL) {
32240       printf("Writing %s.\n", edgefilename);
32241     } else {
32242       printf("Writing edges.\n");
32243     }
32244   }
32245 
32246   // Avoid compile warnings.
32247   outfile = (FILE *) NULL;
32248   elist = (int *) NULL;
32249   index = 0;
32250 
32251   if (out == (tetgenio *) NULL) {
32252     outfile = fopen(edgefilename, "w");
32253     if (outfile == (FILE *) NULL) {
32254       printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
32255       terminatetetgen(1);
32256     }
32257     // Number of subsegments.
32258     fprintf(outfile, "%ld\n", subsegs->items);
32259   } else {
32260     // Allocate memory for 'edgelist'.
32261     out->edgelist = new int[subsegs->items * 2];
32262     if (out->edgelist == (int *) NULL) {
32263       printf("Error:  Out of memory.\n");
32264       terminatetetgen(1);
32265     }
32266     out->numberofedges = subsegs->items;
32267     elist = out->edgelist;
32268   }
32269 
32270   // Determine the first index (0 or 1).
32271   firstindex = b->zeroindex ? 0 : in->firstnumber;
32272   shift = 0; // Default no shiftment.
32273   if ((in->firstnumber == 1) && (firstindex == 0)) {
32274     shift = 1; // Shift the output indices by 1.
32275   }
32276 
32277   subsegs->traversalinit();
32278   edgeloop.sh = shellfacetraverse(subsegs);
32279   edgenumber = firstindex; // in->firstnumber;
32280   while (edgeloop.sh != (shellface *) NULL) {
32281     torg = sorg(edgeloop);
32282     tdest = sdest(edgeloop);
32283     if (out == (tetgenio *) NULL) {
32284       fprintf(outfile, "%5d   %4d  %4d\n", edgenumber,
32285               pointmark(torg) - shift, pointmark(tdest) - shift);
32286     } else {
32287       // Output three vertices of this face;
32288       elist[index++] = pointmark(torg) - shift;
32289       elist[index++] = pointmark(tdest) - shift;
32290     }
32291     edgenumber++;
32292     edgeloop.sh = shellfacetraverse(subsegs);
32293   }
32294 
32295   if (out == (tetgenio *) NULL) {
32296     fprintf(outfile, "# Generated by %s\n", b->commandline);
32297     fclose(outfile);
32298   }
32299 }
32300 
32302 //                                                                           //
32303 // outneighbors()    Output tet neighbors to a .neigh file or a structure.   //
32304 //                                                                           //
32306 
32307 void tetgenmesh::outneighbors(tetgenio* out)
32308 {
32309   FILE *outfile;
32310   char neighborfilename[FILENAMESIZE];
32311   int *nlist;
32312   int index;
32313   triface tetloop, tetsym;
32314   int neighbor1, neighbor2, neighbor3, neighbor4;
32315   int firstindex;
32316   int elementnumber;
32317 
32318   if (out == (tetgenio *) NULL) {
32319     strcpy(neighborfilename, b->outfilename);
32320     strcat(neighborfilename, ".neigh");
32321   }
32322 
32323   if (!b->quiet) {
32324     if (out == (tetgenio *) NULL) {
32325       printf("Writing %s.\n", neighborfilename);
32326     } else {
32327       printf("Writing neighbors.\n");
32328     }
32329   }
32330 
32331   // Avoid compile warnings.
32332   outfile = (FILE *) NULL;
32333   nlist = (int *) NULL;
32334   index = 0;
32335 
32336   if (out == (tetgenio *) NULL) {
32337     outfile = fopen(neighborfilename, "w");
32338     if (outfile == (FILE *) NULL) {
32339       printf("File I/O Error:  Cannot create file %s.\n", neighborfilename);
32340       terminatetetgen(1);
32341     }
32342     // Number of tetrahedra, four faces per tetrahedron.
32343     fprintf(outfile, "%ld  %d\n", tetrahedrons->items, 4);
32344   } else {
32345     // Allocate memory for 'neighborlist'.
32346     out->neighborlist = new int[tetrahedrons->items * 4];
32347     if (out->neighborlist == (int *) NULL) {
32348       printf("Error:  Out of memory.\n");
32349       terminatetetgen(1);
32350     }
32351     nlist = out->neighborlist;
32352   }
32353 
32354   // Determine the first index (0 or 1).
32355   firstindex = b->zeroindex ? 0 : in->firstnumber;
32356 
32357   tetrahedrons->traversalinit();
32358   tetloop.tet = tetrahedrontraverse();
32359   elementnumber = firstindex; // in->firstnumber;
32360   while (tetloop.tet != (tetrahedron *) NULL) {
32361     tetloop.loc = 2;
32362     sym(tetloop, tetsym);
32363     neighbor1 = * (int *) (tetsym.tet + elemmarkerindex);
32364     tetloop.loc = 3;
32365     sym(tetloop, tetsym);
32366     neighbor2 = * (int *) (tetsym.tet + elemmarkerindex);
32367     tetloop.loc = 1;
32368     sym(tetloop, tetsym);
32369     neighbor3 = * (int *) (tetsym.tet + elemmarkerindex);
32370     tetloop.loc = 0;
32371     sym(tetloop, tetsym);
32372     neighbor4 = * (int *) (tetsym.tet + elemmarkerindex);
32373     if (out == (tetgenio *) NULL) {
32374       // Tetrahedra number, neighboring tetrahedron numbers.
32375       fprintf(outfile, "%4d    %4d  %4d  %4d  %4d\n", elementnumber,
32376               neighbor1, neighbor2, neighbor3, neighbor4);
32377     } else {
32378       nlist[index++] = neighbor1;
32379       nlist[index++] = neighbor2;
32380       nlist[index++] = neighbor3;
32381       nlist[index++] = neighbor4;
32382     }
32383     tetloop.tet = tetrahedrontraverse();
32384     elementnumber++;
32385   }
32386 
32387   if (out == (tetgenio *) NULL) {
32388     fprintf(outfile, "# Generated by %s\n", b->commandline);
32389     fclose(outfile);
32390   }
32391 }
32392 
32394 //                                                                           //
32395 // outvoronoi()    Output the Voronoi diagram to .v.node, .v.edge, v.face,   //
32396 //                 and .v.cell.                                              //
32397 //                                                                           //
32398 // The Voronoi diagram is the geometric dual of the Delaunay triangulation.  //
32399 // The Voronoi vertices are the circumcenters of Delaunay tetrahedra.  Each  //
32400 // Voronoi edge connects two Voronoi vertices at two sides of a common Dela- //
32401 // unay face. At a face of convex hull, it becomes a ray (goto the infinity).//
32402 // A Voronoi face is the convex hull of all Voronoi vertices around a common //
32403 // Delaunay edge. It is a closed polygon for any interal Delaunay edge. At a //
32404 // ridge, it is unbounded.  Each Voronoi cell is the convex hull of all Vor- //
32405 // onoi vertices around a common Delaunay vertex. It is a polytope for any   //
32406 // internal Delaunay vertex. It is an unbounded polyhedron for a Delaunay    //
32407 // vertex belonging to the convex hull.                                      //
32408 //                                                                           //
32410 
32411 void tetgenmesh::outvoronoi(tetgenio* out)
32412 {
32413   FILE *outfile;
32414   char outfilename[FILENAMESIZE];
32415   tetgenio::voroedge *vedge;
32416   tetgenio::vorofacet *vfacet;
32417   list *tetlist, *ptlist;
32418   triface tetloop, worktet, spintet;
32419   point pt[4], ptloop, neipt;
32420   REAL ccent[3], infvec[3], vec1[3], vec2[3], L;
32421   long faces, edges;
32422   int *tetfaceindexarray, *tetedgeindexarray;
32423   int arraysize, *vertarray;
32424   int vpointcount, vedgecount, vfacecount, tcount;
32425   int index, shift;
32426   int end1, end2;
32427   int hitbdry, i, j, k;
32428 
32429   vedge = NULL;
32430   vertarray = NULL;
32431   vfacet = NULL;
32432   k = 0;
32433 
32434   // Output Voronoi vertices to .v.node file.
32435   if (out == (tetgenio *) NULL) {
32436     strcpy(outfilename, b->outfilename);
32437     strcat(outfilename, ".v.node");
32438   }
32439 
32440   if (!b->quiet) {
32441     if (out == (tetgenio *) NULL) {
32442       printf("Writing %s.\n", outfilename);
32443     } else {
32444       printf("Writing Voronoi vertices.\n");
32445     }
32446   }
32447 
32448   // Determine the first index (0 or 1).
32449   shift = (b->zeroindex ? 0 : in->firstnumber);
32450   // The number of Delaunay faces (= the number of Voronoi edges).
32451   faces = (4l * tetrahedrons->items + hullsize) / 2l;
32452   // The number of Delaunay edges (= the number of Voronoi faces).
32453   edges = points->items + faces - tetrahedrons->items - 1;
32454   outfile = (FILE *) NULL; // Avoid compile warnings.
32455 
32456   if (out == (tetgenio *) NULL) {
32457     outfile = fopen(outfilename, "w");
32458     if (outfile == (FILE *) NULL) {
32459       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32460       terminatetetgen(1);
32461     }
32462     // Number of voronoi points, 3 dim, no attributes, no marker.
32463     fprintf(outfile, "%ld  3  0  0\n", tetrahedrons->items);
32464   } else {
32465     // Allocate space for 'vpointlist'.
32466     out->numberofvpoints = (int) tetrahedrons->items;
32467     out->vpointlist = new REAL[out->numberofvpoints * 3];
32468     if (out->vpointlist == (REAL *) NULL) {
32469       printf("Error:  Out of memory.\n");
32470       terminatetetgen(1);
32471     }
32472   }
32473 
32474   // Loop the tetrahedronlist once, do the following:
32475   //   (1) Output Voronoi vertices (the circumcenter of the tetrahedron).
32476   //   (2) Make a map from points-to-tetrahedra (for Voronoi cells).
32477   tetrahedrons->traversalinit();
32478   tetloop.tet = tetrahedrontraverse();
32479   vpointcount = 0;
32480   index = 0;
32481   while (tetloop.tet != (tetrahedron *) NULL) {
32482     // Calculate the circumcenter.
32483     for (i = 0; i < 4; i++) {
32484       pt[i] = (point) tetloop.tet[4 + i];
32485       setpoint2tet(pt[i], encode(tetloop));
32486     }
32487     circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
32488     if (out == (tetgenio *) NULL) {
32489       fprintf(outfile, "%4d  %16.8e %16.8e %16.8e\n", vpointcount + shift,
32490               ccent[0], ccent[1], ccent[2]);
32491     } else {
32492       out->vpointlist[index++] = ccent[0];
32493       out->vpointlist[index++] = ccent[1];
32494       out->vpointlist[index++] = ccent[2];
32495     }
32496     // Remember the index of this element.
32497     * (int *) (tetloop.tet + elemmarkerindex) = vpointcount;
32498     vpointcount++;
32499     tetloop.tet = tetrahedrontraverse();
32500   }
32501   // Set the outside element marker.
32502   * (int *) (dummytet + elemmarkerindex) = -1;
32503 
32504   if (out == (tetgenio *) NULL) {
32505     fprintf(outfile, "# Generated by %s\n", b->commandline);
32506     fclose(outfile);
32507   }
32508 
32509   // Output Voronoi edges to .v.edge file.
32510   if (out == (tetgenio *) NULL) {
32511     strcpy(outfilename, b->outfilename);
32512     strcat(outfilename, ".v.edge");
32513   }
32514 
32515   if (!b->quiet) {
32516     if (out == (tetgenio *) NULL) {
32517       printf("Writing %s.\n", outfilename);
32518     } else {
32519       printf("Writing Voronoi edges.\n");
32520     }
32521   }
32522 
32523   if (out == (tetgenio *) NULL) {
32524     outfile = fopen(outfilename, "w");
32525     if (outfile == (FILE *) NULL) {
32526       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32527       terminatetetgen(1);
32528     }
32529     // Number of Voronoi edges, no marker.
32530     fprintf(outfile, "%ld  0\n", faces);
32531   } else {
32532     // Allocate space for 'vpointlist'.
32533     out->numberofedges = (int) faces;
32534     out->vedgelist = new tetgenio::voroedge[out->numberofvedges];
32535   }
32536 
32537   // Loop the tetrahedronlist once, output the Voronoi edges. The index of
32538   //   each Voronoi edge corresponding to the index of the Delaunay face.
32539   //   The four faces' indices of each tetrahedron are saved in the list
32540   //   'tetfaceindexarray', in the entry of i,  where i (0-based) is the
32541   //   index of this tetrahedron (= vpointcount).
32542   tetfaceindexarray = new int[tetrahedrons->items * 4];
32543   tetrahedrons->traversalinit();
32544   tetloop.tet = tetrahedrontraverse();
32545   vedgecount = 0;
32546   index = 0;
32547   while (tetloop.tet != (tetrahedron *) NULL) {
32548     // Count the number of Voronoi edges. Look at the four faces of each
32549     //   tetrahedron. Count the face if the tetrahedron's pointer is
32550     //   smaller than its neighbor's or the neighbor is outside.
32551     end1 = * (int *) (tetloop.tet + elemmarkerindex);
32552     for (i = 0; i < 4; i++) {
32553       decode(tetloop.tet[i], worktet);
32554       if ((worktet.tet == dummytet) || (tetloop.tet < worktet.tet)) {
32555         if (out == (tetgenio *) NULL) {
32556           fprintf(outfile, "%4d  %4d", vedgecount + shift, end1 + shift);
32557         } else {
32558           vedge = &(out->vedgelist[index++]);
32559           vedge->v1 = end1 + shift;
32560         }
32561         end2 = * (int *) (worktet.tet + elemmarkerindex);
32562         // Note that end2 may be -1 (worktet.tet is outside).
32563         if (end2 == -1) {
32564           // Calculate the out normal of this hull face.
32565           worktet.tet = tetloop.tet;
32566           worktet.loc = i;
32567           worktet.ver = 1; // The CW edge ring.
32568           pt[0] = org(worktet);
32569           pt[1] = dest(worktet);
32570           pt[2] = apex(worktet);
32571           for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j];
32572           for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j];
32573           cross(vec1, vec2, infvec);
32574           // Normalize it.
32575           L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1]
32576                    + infvec[2] * infvec[2]);
32577           if (L > 0) for (j = 0; j < 3; j++) infvec[j] /= L;
32578           if (out == (tetgenio *) NULL) {
32579             fprintf(outfile, " -1");
32580             fprintf(outfile, " %g %g %g\n", infvec[0], infvec[1], infvec[2]);
32581           } else {
32582             vedge->v2 = -1;
32583             vedge->vnormal[0] = infvec[0];
32584             vedge->vnormal[1] = infvec[1];
32585             vedge->vnormal[2] = infvec[2];
32586           }
32587         } else {
32588           if (out == (tetgenio *) NULL) {
32589             fprintf(outfile, " %4d\n", end2 + shift);
32590           } else {
32591             vedge->v2 = end2 + shift;
32592             vedge->vnormal[0] = 0.0;
32593             vedge->vnormal[1] = 0.0;
32594             vedge->vnormal[2] = 0.0;
32595           }
32596         }
32597         // Save the face index in this tet and its neighbor if exists.
32598         tetfaceindexarray[end1 * 4 + i] = vedgecount;
32599         if (end2 != -1) {
32600           tetfaceindexarray[end2 * 4 + worktet.loc] = vedgecount;
32601         }
32602         vedgecount++;
32603       }
32604     }
32605     tetloop.tet = tetrahedrontraverse();
32606   }
32607 
32608   if (out == (tetgenio *) NULL) {
32609     fprintf(outfile, "# Generated by %s\n", b->commandline);
32610     fclose(outfile);
32611   }
32612 
32613   // Output Voronoi faces to .v.face file.
32614   if (out == (tetgenio *) NULL) {
32615     strcpy(outfilename, b->outfilename);
32616     strcat(outfilename, ".v.face");
32617   }
32618 
32619   if (!b->quiet) {
32620     if (out == (tetgenio *) NULL) {
32621       printf("Writing %s.\n", outfilename);
32622     } else {
32623       printf("Writing Voronoi faces.\n");
32624     }
32625   }
32626 
32627   if (out == (tetgenio *) NULL) {
32628     outfile = fopen(outfilename, "w");
32629     if (outfile == (FILE *) NULL) {
32630       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32631       terminatetetgen(1);
32632     }
32633     // Number of Voronoi faces.
32634     fprintf(outfile, "%ld  0\n", edges);
32635   } else {
32636     out->numberofvfacets = edges;
32637     out->vfacetlist = new tetgenio::vorofacet[out->numberofvfacets];
32638     if (out->vfacetlist == (tetgenio::vorofacet *) NULL) {
32639       printf("Error:  Out of memory.\n");
32640       terminatetetgen(1);
32641     }
32642   }
32643 
32644   // Loop the tetrahedronlist once, Output Voronoi facets. The index of each
32645   //   Voronoi facet corresponding to the index of the Delaunay edge.  The
32646   //   six edges' indices of each tetrahedron are saved in the list 'tetedge-
32647   //   indexarray', in the entry of i,  where i (0-based) is the index of
32648   //   this tetrahedron (= vpointcount).
32649   tetedgeindexarray = new int[tetrahedrons->items * 6];
32650   tetrahedrons->traversalinit();
32651   tetloop.tet = tetrahedrontraverse();
32652   vfacecount = 0;
32653   while (tetloop.tet != (tetrahedron *) NULL) {
32654     // Count the number of Voronoi faces. Look at the six edges of each
32655     //   tetrahedron. Count the edge only if the tetrahedron's pointer is
32656     //   smaller than those of all other tetrahedra that share the edge.
32657     worktet = tetloop;
32658     for (i = 0; i < 6; i++) {
32659       worktet.loc = edge2locver[i][0];
32660       worktet.ver = edge2locver[i][1];
32661       // Now count the number of tets surrounding this edge.
32662       tcount = 1;
32663       adjustedgering(worktet, CW);
32664       spintet = worktet;
32665       hitbdry = 0;
32666       while (hitbdry < 2) {
32667         if (fnextself(spintet)) {
32668           if (apex(spintet) == apex(worktet)) break;
32669           if (spintet.tet < worktet.tet) break;
32670           tcount++;
32671         } else {
32672           hitbdry++;
32673           if (hitbdry < 2) {
32674             esym(worktet, spintet);
32675             fnextself(spintet); // In the same tet.
32676       }
32677         }
32678       }
32679       // Count this edge if no adjacent tets are smaller than this tet.
32680       if (spintet.tet >= worktet.tet) {
32681         // Get the two endpoints of this edge.
32682         pt[0] = org(worktet);
32683         pt[1] = dest(worktet);
32684         end1 = pointmark(pt[0]) - in->firstnumber;
32685         end2 = pointmark(pt[1]) - in->firstnumber;
32686         if (out == (tetgenio *) NULL) {
32687           fprintf(outfile, "%4d  %4d %4d  %-2d ", vfacecount + shift,
32688                   end1 + shift, end2 + shift, tcount + (hitbdry > 0));
32689         } else {
32690           vfacet = &(out->vfacetlist[vfacecount]);
32691           vfacet->c1 = end1 + shift;
32692           vfacet->c2 = end2 + shift;
32693           vfacet->elist = new int[tcount + (hitbdry > 0) + 1];
32694           vfacet->elist[0] = tcount + (hitbdry > 0);
32695           index = 1;
32696         }
32697         // If hitbdry > 0, then spintet is a hull face.
32698         if (hitbdry > 0) {
32699           // The edge list starts with a ray.
32700           vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32701           vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32702           if (out == (tetgenio *) NULL) {
32703             fprintf(outfile, " %d", vedgecount + shift);
32704           } else {
32705             vfacet->elist[index++] = vedgecount + shift;
32706           }
32707           // Save this facet number in tet.
32708           tetedgeindexarray[vpointcount * 6 +
32709             locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32710           esymself(spintet);
32711           fnextself(spintet); // In the same tet.
32712         }
32713         // Output internal Voronoi edges.
32714         for (j = 0; j < tcount; j++) {
32715           vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32716           vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32717           if (out == (tetgenio *) NULL) {
32718             fprintf(outfile, " %d", vedgecount + shift);
32719           } else {
32720             vfacet->elist[index++] = vedgecount + shift;
32721           }
32722           // Save this facet number in tet.
32723           tetedgeindexarray[vpointcount * 6 +
32724             locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32725           fnextself(spintet);
32726         }
32727         if (out == (tetgenio *) NULL) {
32728           fprintf(outfile, "\n");
32729         }
32730         vfacecount++;
32731       }
32732     } // if (i = 0; i < 6; i++)
32733     tetloop.tet = tetrahedrontraverse();
32734   }
32735 
32736   if (out == (tetgenio *) NULL) {
32737     fprintf(outfile, "# Generated by %s\n", b->commandline);
32738     fclose(outfile);
32739   }
32740 
32741   // Output Voronoi cells to .v.cell file.
32742   if (out == (tetgenio *) NULL) {
32743     strcpy(outfilename, b->outfilename);
32744     strcat(outfilename, ".v.cell");
32745   }
32746 
32747   if (!b->quiet) {
32748     if (out == (tetgenio *) NULL) {
32749       printf("Writing %s.\n", outfilename);
32750     } else {
32751       printf("Writing Voronoi cells.\n");
32752     }
32753   }
32754 
32755   if (out == (tetgenio *) NULL) {
32756     outfile = fopen(outfilename, "w");
32757     if (outfile == (FILE *) NULL) {
32758       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32759       terminatetetgen(1);
32760     }
32761     // Number of Voronoi cells.
32762     fprintf(outfile, "%ld\n", points->items);
32763   } else {
32764     out->numberofvcells = points->items;
32765     out->vcelllist = new int*[out->numberofvcells];
32766     if (out->vcelllist == (int **) NULL) {
32767       printf("Error:  Out of memory.\n");
32768       terminatetetgen(1);
32769     }
32770   }
32771 
32772   // Loop through point list, for each point, output a Voronoi cell.
32773   tetlist = new list(sizeof(triface), NULL, 256);
32774   ptlist = new list(sizeof(point *), NULL, 256);
32775   points->traversalinit();
32776   ptloop = pointtraverse();
32777   vpointcount = 0;
32778   while (ptloop != (point) NULL) {
32779     decode(point2tet(ptloop), tetloop);
32780     // assert(!isdead(&tetloop));
32781     if (!isdead(&tetloop)) {
32782       // Form the star of p.
32783       tetlist->append(&tetloop);
32784       formstarpolyhedron(ptloop, tetlist, ptlist, true);
32785       tcount = ptlist->len();
32786       if (out == (tetgenio *) NULL) {
32787         fprintf(outfile, "%4d  %-2d ", vpointcount + shift, tcount);
32788       } else {
32789         arraysize = tcount;
32790         vertarray = out->vcelllist[vpointcount];
32791         vertarray = new int[arraysize + 1];
32792         vertarray[0] = arraysize;
32793         index = 1;
32794       }
32795       // List Voronoi facets bounding this cell.
32796       for (i = 0; i < ptlist->len(); i++) {
32797         neipt =  * (point *)(* ptlist)[i];
32798         // Find a tet in tetlist having edge (ptloop, neipt) -- Very Slow.
32799         for (j = 0; j < tetlist->len(); j++) {
32800           tetloop = * (triface *)(* tetlist)[j];
32801           for (k = 0; k < 6; k++) {
32802             tetloop.loc = edge2locver[k][0];
32803             tetloop.ver = edge2locver[k][1];
32804             if (org(tetloop) == ptloop) {
32805               if (dest(tetloop) == neipt) break;
32806             } else if (org(tetloop) == neipt) {
32807               if (dest(tetloop) == ptloop) break;
32808             }
32809           }
32810           if (k < 6) break; // Found this edge.
32811         }
32812         assert(j < tetlist->len());
32813         // k is the right edge number.
32814         end1 = * (int *) (tetloop.tet + elemmarkerindex);
32815         vfacecount = tetedgeindexarray[end1 * 6 + k];
32816         if (out == (tetgenio *) NULL) {
32817           fprintf(outfile, " %d", vfacecount + shift);
32818         } else {
32819           vertarray[index++] = vfacecount + shift;
32820         }
32821       } // for (i = 0; i < ptlist->len(); i++) {
32822       if (out == (tetgenio *) NULL) {
32823         fprintf(outfile, "\n");
32824       }
32825       vpointcount++;
32826     }
32827     tetlist->clear();
32828     ptlist->clear();
32829     ptloop = pointtraverse();
32830   }
32831   delete tetlist;
32832   delete ptlist;
32833   delete [] tetfaceindexarray;
32834   delete [] tetedgeindexarray;
32835 
32836   if (out == (tetgenio *) NULL) {
32837     fprintf(outfile, "# Generated by %s\n", b->commandline);
32838     fclose(outfile);
32839   }
32840 }
32841 
32843 //                                                                           //
32844 // outpbcnodes()    Output pbc node pairs to a .pbc file or a structure.     //
32845 //                                                                           //
32847 
32848 void tetgenmesh::outpbcnodes(tetgenio* out)
32849 {
32850   FILE *outfile;
32851   char pbcfilename[FILENAMESIZE];
32852   list *ptpairlist;
32853   tetgenio::pbcgroup *pgi, *pgo;
32854   pbcdata *pd;
32855   face faceloop;
32856   face checkseg, symseg;
32857   point *ptpair, pa, pb;
32858   enum locateresult loc;
32859   REAL sympt[3], d1, d2;
32860   int *worklist;
32861   int firstindex, shift;
32862   int index, idx;
32863   int i, j, k, l;
32864 
32865   if (out == (tetgenio *) NULL) {
32866     strcpy(pbcfilename, b->outfilename);
32867     strcat(pbcfilename, ".pbc");
32868   }
32869 
32870   if (!b->quiet) {
32871     if (out == (tetgenio *) NULL) {
32872       printf("Writing %s.\n", pbcfilename);
32873     } else {
32874       printf("Writing pbc nodes.\n");
32875     }
32876   }
32877 
32878   // Avoid compilation warnings.
32879   outfile = (FILE *) NULL;
32880   pgo = (tetgenio::pbcgroup *) NULL;
32881   index = 0;
32882 
32883   if (out == (tetgenio *) NULL) {
32884     outfile = fopen(pbcfilename, "w");
32885     if (outfile == (FILE *) NULL) {
32886       printf("File I/O Error:  Cannot create file %s.\n", pbcfilename);
32887       terminatetetgen(1);
32888     }
32889     // Number of pbc groups.
32890     fprintf(outfile, "# number of PBCs.\n");
32891     fprintf(outfile, "%d\n\n", in->numberofpbcgroups);
32892   } else {
32893     out->numberofpbcgroups = in->numberofpbcgroups;
32894     // Allocate memory for 'out->pbcgrouplist'.
32895     out->pbcgrouplist = new tetgenio::pbcgroup[in->numberofpbcgroups];
32896     // (Next line was a bug, reported by Murry Nigel).
32897     if (out->pbcgrouplist == (tetgenio::pbcgroup *) NULL) {
32898       printf("Error:  Out of memory.\n");
32899       terminatetetgen(1);
32900     }
32901   }
32902 
32903   ptpairlist = new list(2 * sizeof(point *), NULL, 256);
32904   worklist = new int[points->items + 1];
32905   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
32906 
32907   // Determine the first index (0 or 1).
32908   firstindex = b->zeroindex ? 0 : in->firstnumber;
32909   shift = 0; // Default no shiftment.
32910   if ((in->firstnumber == 1) && (firstindex == 0)) {
32911     shift = 1; // Shift the output indices by 1.
32912   }
32913 
32914   for (i = 0; i < in->numberofpbcgroups; i++) {
32915     // Group i.
32916     pgi = &(in->pbcgrouplist[i]);
32917     if (out == (tetgenio *) NULL) {
32918       fprintf(outfile, "# PBC %d\n", in->firstnumber + i);
32919       // Output facet markers.
32920       fprintf(outfile, "%d  %d\n", pgi->fmark1, pgi->fmark2);
32921       // Output transformation matrix.
32922       fprintf(outfile, "[\n");
32923       for (j = 0; j < 4; j++) {
32924         fprintf(outfile, "  %.12g %.12g %.12g %.12g\n", pgi->transmat[j][0],
32925                 pgi->transmat[j][1], pgi->transmat[j][2], pgi->transmat[j][3]);
32926       }
32927       fprintf(outfile, "]\n");
32928     } else {
32929       pgo = &(out->pbcgrouplist[i]);
32930       // Copy data from pgi to pgo.
32931       pgo->fmark1 = pgi->fmark1;
32932       pgo->fmark2 = pgi->fmark2;
32933       for (j = 0; j < 4; j++) {
32934         for (k = 0; k < 4; k++) pgo->transmat[j][k] = pgi->transmat[j][k];
32935       }
32936     }
32937 
32938     // Find the point pairs of group i.
32939     subfaces->traversalinit();
32940     faceloop.sh = shellfacetraverse(subfaces);
32941     while (faceloop.sh != (shellface *) NULL) {
32942       if (shellpbcgroup(faceloop) == i) {
32943         // It is in group i. Operate on it if it has pgi->fmark1.
32944         idx = shellmark(faceloop) - 1;
32945         if (in->facetmarkerlist[idx] == pgi->fmark1) {
32946           // Loop three edges of the subface.
32947           for (j = 0; j < 3; j++) {
32948             sspivot(faceloop, checkseg);
32949             // Loop two vertices of the edge.
32950             for (k = 0; k < 2; k++) {
32951               if (k == 0) pa = sorg(faceloop);
32952               else pa = sdest(faceloop);
32953               if (worklist[pointmark(pa)] == 0) {
32954                 pb = (point) NULL;
32955                 if (checkseg.sh != dummysh) {
32956                   // pa is on a segment. Find pb.
32957                   // Find the incident pbcgroup of checkseg.
32958                   idx = shellmark(checkseg) - 1;
32959                   for (l = idx2segpglist[idx]; l < idx2segpglist[idx + 1];
32960                        l++) {
32961                     pd = (pbcdata *)(* segpbcgrouptable)[segpglist[l]];
32962                     if (((pd->fmark[0] == pgi->fmark1) &&
32963                          (pd->fmark[1] == pgi->fmark2)) ||
32964                         ((pd->fmark[0] == pgi->fmark2) &&
32965                          (pd->fmark[1] == pgi->fmark1))) break;
32966                   }
32967 #ifdef SELF_CHECK
32968                   assert(l < idx2segpglist[idx + 1]);
32969 #endif
32970                   loc = getsegpbcsympoint(pa, &checkseg, sympt, &symseg,
32971                                           segpglist[l]);
32972                   if (loc != ONVERTEX) {
32973                     // Not found a match point! It may be caused by the
32974                     //   pair of input vertices don't have enough digits.
32975                     //   Choose a near vertex.
32976                     d1 = distance(sympt, sorg(symseg));
32977                     d2 = distance(sympt, sdest(symseg));
32978                     if (d1 > d2) sesymself(symseg);
32979                   }
32980                   pb = sorg(symseg);
32981                 } else {
32982                   // Operate on pa if it is inside the facet.
32983                   if (pointtype(pa) == FREESUBVERTEX) {
32984                     pb = point2pbcpt(pa);
32985                   }
32986                 }
32987                 if (pb != (point) NULL) {
32988                   // Add the pair (pa, pb) into list.
32989                   ptpair = (point *) ptpairlist->append(NULL);
32990                   ptpair[0] = pa;
32991                   ptpair[1] = pb;
32992                   // Mark pa (avoid to operate on it later).
32993                   worklist[pointmark(pa)] = 1;
32994                 }
32995               }
32996             }
32997             // Get the next edge.
32998             senextself(faceloop);
32999           }
33000         }
33001       }
33002       faceloop.sh = shellfacetraverse(subfaces);
33003     }
33004 
33005     // Output the list of pbc points.
33006     if (out == (tetgenio *) NULL) {
33007       fprintf(outfile, "%d\n", ptpairlist->len());
33008     } else {
33009       pgo->numberofpointpairs = ptpairlist->len();
33010       pgo->pointpairlist = new int[pgo->numberofpointpairs * 2];
33011       index = 0;
33012     }
33013     for (j = 0; j < ptpairlist->len(); j++) {
33014       ptpair = (point *)(* ptpairlist)[j];
33015       pa = ptpair[0];
33016       pb = ptpair[1];
33017       if (out == (tetgenio *) NULL) {
33018         fprintf(outfile, "  %4d %4d\n", pointmark(pa) - shift,
33019                 pointmark(pb) - shift);
33020       } else {
33021         pgo->pointpairlist[index++] = pointmark(pa) - shift;
33022         pgo->pointpairlist[index++] = pointmark(pb) - shift;
33023       }
33024       // Unmark pa.
33025       worklist[pointmark(pa)] = 0;
33026     }
33027     if (out == (tetgenio *) NULL) {
33028       fprintf(outfile, "\n");
33029     }
33030     ptpairlist->clear();
33031   }
33032 
33033   delete [] worklist;
33034   delete ptpairlist;
33035 
33036   if (out == (tetgenio *) NULL) {
33037     fprintf(outfile, "# Generated by %s\n", b->commandline);
33038     fclose(outfile);
33039   }
33040 }
33041 
33043 //                                                                           //
33044 // outsmesh()    Write surface mesh to a .smesh file, which can be read and  //
33045 //               tetrahedralized by TetGen.                                  //
33046 //                                                                           //
33047 // You can specify a filename (without suffix) in 'smfilename'. If you don't //
33048 // supply a filename (let smfilename be NULL), the default name stored in    //
33049 // 'tetgenbehavior' will be used.                                            //
33050 //                                                                           //
33052 
33053 void tetgenmesh::outsmesh(char* smfilename)
33054 {
33055   FILE *outfile;
33056   char nodfilename[FILENAMESIZE];
33057   char smefilename[FILENAMESIZE];
33058   face faceloop;
33059   point p1, p2, p3;
33060   int firstindex, shift;
33061   int bmark;
33062   int faceid, marker;
33063   int i;
33064 
33065   if (smfilename != (char *) NULL && smfilename[0] != '\0') {
33066     strcpy(smefilename, smfilename);
33067   } else if (b->outfilename[0] != '\0') {
33068     strcpy(smefilename, b->outfilename);
33069   } else {
33070     strcpy(smefilename, "unnamed");
33071   }
33072   strcpy(nodfilename, smefilename);
33073   strcat(smefilename, ".smesh");
33074   strcat(nodfilename, ".node");
33075 
33076   if (!b->quiet) {
33077     printf("Writing %s.\n", smefilename);
33078   }
33079   outfile = fopen(smefilename, "w");
33080   if (outfile == (FILE *) NULL) {
33081     printf("File I/O Error:  Cannot create file %s.\n", smefilename);
33082     return;
33083   }
33084 
33085   // Determine the first index (0 or 1).
33086   firstindex = b->zeroindex ? 0 : in->firstnumber;
33087   shift = 0; // Default no shiftment.
33088   if ((in->firstnumber == 1) && (firstindex == 0)) {
33089     shift = 1; // Shift the output indices by 1.
33090   }
33091 
33092   fprintf(outfile, "# %s.  TetGen's input file.\n", smefilename);
33093   fprintf(outfile, "\n# part 1: node list.\n");
33094   fprintf(outfile, "0  3  0  0  # nodes are found in %s.\n", nodfilename);
33095 
33096   marker = 0; // avoid compile warning.
33097   bmark = !b->nobound && in->facetmarkerlist;
33098 
33099   fprintf(outfile, "\n# part 2: facet list.\n");
33100   // Number of facets, boundary marker.
33101   fprintf(outfile, "%ld  %d\n", subfaces->items, bmark);
33102 
33103   subfaces->traversalinit();
33104   faceloop.sh = shellfacetraverse(subfaces);
33105   while (faceloop.sh != (shellface *) NULL) {
33106     p1 = sorg(faceloop);
33107     p2 = sdest(faceloop);
33108     p3 = sapex(faceloop);
33109     if (bmark) {
33110       faceid = shellmark(faceloop) - 1;
33111       if (faceid >= 0) {
33112         marker = in->facetmarkerlist[faceid];
33113       } else {
33114         marker = 0; // This subface must be added manually later.
33115       }
33116     }
33117     fprintf(outfile, "3    %4d  %4d  %4d", pointmark(p1) - shift,
33118             pointmark(p2) - shift, pointmark(p3) - shift);
33119     if (bmark) {
33120       fprintf(outfile, "    %d", marker);
33121     }
33122     fprintf(outfile, "\n");
33123     faceloop.sh = shellfacetraverse(subfaces);
33124   }
33125 
33126   // Copy input holelist.
33127   fprintf(outfile, "\n# part 3: hole list.\n");
33128   fprintf(outfile, "%d\n", in->numberofholes);
33129   for (i = 0; i < in->numberofholes; i++) {
33130     fprintf(outfile, "%d  %g  %g  %g\n", i + in->firstnumber,
33131             in->holelist[i * 3], in->holelist[i * 3 + 1],
33132             in->holelist[i * 3 + 2]);
33133   }
33134 
33135   // Copy input regionlist.
33136   fprintf(outfile, "\n# part 4: region list.\n");
33137   fprintf(outfile, "%d\n", in->numberofregions);
33138   for (i = 0; i < in->numberofregions; i++) {
33139     fprintf(outfile, "%d  %g  %g  %g  %d  %g\n", i + in->firstnumber,
33140             in->regionlist[i * 5], in->regionlist[i * 5 + 1],
33141             in->regionlist[i * 5 + 2], (int) in->regionlist[i * 5 + 3],
33142             in->regionlist[i * 5 + 4]);
33143   }
33144 
33145   fprintf(outfile, "# Generated by %s\n", b->commandline);
33146   fclose(outfile);
33147 }
33148 
33150 //                                                                           //
33151 // outmesh2medit()    Write mesh to a .mesh file, which can be read and      //
33152 //                    rendered by Medit (a free mesh viewer from INRIA).     //
33153 //                                                                           //
33154 // You can specify a filename (without suffix) in 'mfilename'.  If you don't //
33155 // supply a filename (let mfilename be NULL), the default name stored in     //
33156 // 'tetgenbehavior' will be used. The output file will have the suffix .mesh.//
33157 //                                                                           //
33159 
33160 void tetgenmesh::outmesh2medit(char* mfilename)
33161 {
33162   FILE *outfile;
33163   char mefilename[FILENAMESIZE];
33164   tetrahedron* tetptr;
33165   triface tface, tsymface;
33166   face segloop, checkmark;
33167   point ptloop, p1, p2, p3, p4;
33168   long faces;
33169   int pointnumber;
33170   int i;
33171 
33172   if (mfilename != (char *) NULL && mfilename[0] != '\0') {
33173     strcpy(mefilename, mfilename);
33174   } else if (b->outfilename[0] != '\0') {
33175     strcpy(mefilename, b->outfilename);
33176   } else {
33177     strcpy(mefilename, "unnamed");
33178   }
33179   strcat(mefilename, ".mesh");
33180 
33181   if (!b->quiet) {
33182     printf("Writing %s.\n", mefilename);
33183   }
33184   outfile = fopen(mefilename, "w");
33185   if (outfile == (FILE *) NULL) {
33186     printf("File I/O Error:  Cannot create file %s.\n", mefilename);
33187     return;
33188   }
33189 
33190   fprintf(outfile, "MeshVersionFormatted 1\n");
33191   fprintf(outfile, "\n");
33192   fprintf(outfile, "Dimension\n");
33193   fprintf(outfile, "3\n");
33194   fprintf(outfile, "\n");
33195 
33196   fprintf(outfile, "\n# Set of mesh vertices\n");
33197   fprintf(outfile, "Vertices\n");
33198   fprintf(outfile, "%ld\n", points->items);
33199 
33200   points->traversalinit();
33201   ptloop = pointtraverse();
33202   pointnumber = 1;                        // Medit need start number form 1.
33203   while (ptloop != (point) NULL) {
33204     // Point coordinates.
33205     fprintf(outfile, "%.17g  %.17g  %.17g", ptloop[0], ptloop[1], ptloop[2]);
33206     if (in->numberofpointattributes > 0) {
33207       // Write an attribute, ignore others if more than one.
33208       fprintf(outfile, "  %.17g\n", ptloop[3]);
33209     } else {
33210       fprintf(outfile, "    0\n");
33211     }
33212     setpointmark(ptloop, pointnumber);
33213     ptloop = pointtraverse();
33214     pointnumber++;
33215   }
33216 
33217   // Compute the number of edges.
33218   faces = (4l * tetrahedrons->items + hullsize) / 2l;
33219 
33220   fprintf(outfile, "\n# Set of Triangles\n");
33221   fprintf(outfile, "Triangles\n");
33222   fprintf(outfile, "%ld\n", faces);
33223 
33224   tetrahedrons->traversalinit();
33225   tface.tet = tetrahedrontraverse();
33226   // To loop over the set of faces, loop over all tetrahedra, and look at
33227   //   the four faces of each tetrahedron. If there isn't another tetrahedron
33228   //   adjacent to the face, operate on the face.  If there is another adj-
33229   //   acent tetrahedron, operate on the face only if the current tetrahedron
33230   //   has a smaller pointer than its neighbor.  This way, each face is
33231   //   considered only once.
33232   while (tface.tet != (tetrahedron *) NULL) {
33233     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33234       sym(tface, tsymface);
33235       if (tface.tet < tsymface.tet || tsymface.tet == dummytet) {
33236         p1 = org (tface);
33237         p2 = dest(tface);
33238         p3 = apex(tface);
33239         fprintf(outfile, "%5d  %5d  %5d",
33240                 pointmark(p1), pointmark(p2), pointmark(p3));
33241         fprintf(outfile, "    0\n");
33242       }
33243     }
33244     tface.tet = tetrahedrontraverse();
33245   }
33246 
33247   fprintf(outfile, "\n# Set of Tetrahedra\n");
33248   fprintf(outfile, "Tetrahedra\n");
33249   fprintf(outfile, "%ld\n", tetrahedrons->items);
33250 
33251   tetrahedrons->traversalinit();
33252   tetptr = tetrahedrontraverse();
33253   while (tetptr != (tetrahedron *) NULL) {
33254     p1 = (point) tetptr[4];
33255     p2 = (point) tetptr[5];
33256     p3 = (point) tetptr[6];
33257     p4 = (point) tetptr[7];
33258     fprintf(outfile, "%5d  %5d  %5d  %5d",
33259             pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33260     if (in->numberoftetrahedronattributes > 0) {
33261       fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
33262     } else {
33263       fprintf(outfile, "  0");
33264     }
33265     fprintf(outfile, "\n");
33266     tetptr = tetrahedrontraverse();
33267   }
33268 
33269   fprintf(outfile, "\nCorners\n");
33270   fprintf(outfile, "%d\n", in->numberofpoints);
33271 
33272   for (i = 0; i < in->numberofpoints; i++) {
33273     fprintf(outfile, "%4d\n", i + 1);
33274   }
33275 
33276   if (b->useshelles) {
33277     fprintf(outfile, "\nEdges\n");
33278     fprintf(outfile, "%ld\n", subsegs->items);
33279 
33280     subsegs->traversalinit();
33281     segloop.sh = shellfacetraverse(subsegs);
33282     while (segloop.sh != (shellface *) NULL) {
33283       p1 = sorg(segloop);
33284       p2 = sdest(segloop);
33285       fprintf(outfile, "%5d  %5d", pointmark(p1), pointmark(p2));
33286       fprintf(outfile, "    0\n");
33287       segloop.sh = shellfacetraverse(subsegs);
33288     }
33289   }
33290 
33291   fprintf(outfile, "\nEnd\n");
33292   fclose(outfile);
33293 }
33294 
33296 //                                                                           //
33297 // outmesh2gid()    Write mesh to a .ele.msh file and a .face.msh file,      //
33298 //                  which can be imported and rendered by Gid.               //
33299 //                                                                           //
33300 // You can specify a filename (without suffix) in 'gfilename'.  If you don't //
33301 // supply a filename (let gfilename be NULL), the default name stored in     //
33302 // 'tetgenbehavior' will be used. The suffixes (.ele.msh and .face.msh) will //
33303 // be automatically added.                                                   //
33304 //                                                                           //
33306 
33307 void tetgenmesh::outmesh2gid(char* gfilename)
33308 {
33309   FILE *outfile;
33310   char gidfilename[FILENAMESIZE];
33311   tetrahedron* tetptr;
33312   triface tface, tsymface;
33313   face sface;
33314   point ptloop, p1, p2, p3, p4;
33315   int pointnumber;
33316   int elementnumber;
33317 
33318   if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33319     strcpy(gidfilename, gfilename);
33320   } else if (b->outfilename[0] != '\0') {
33321     strcpy(gidfilename, b->outfilename);
33322   } else {
33323     strcpy(gidfilename, "unnamed");
33324   }
33325   strcat(gidfilename, ".ele.msh");
33326 
33327   if (!b->quiet) {
33328     printf("Writing %s.\n", gidfilename);
33329   }
33330   outfile = fopen(gidfilename, "w");
33331   if (outfile == (FILE *) NULL) {
33332     printf("File I/O Error:  Cannot create file %s.\n", gidfilename);
33333     return;
33334   }
33335 
33336   fprintf(outfile, "mesh dimension = 3 elemtype tetrahedron nnode = 4\n");
33337   fprintf(outfile, "coordinates\n");
33338 
33339   points->traversalinit();
33340   ptloop = pointtraverse();
33341   pointnumber = 1;                        // Gid need start number form 1.
33342   while (ptloop != (point) NULL) {
33343     // Point coordinates.
33344     fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
33345             ptloop[0], ptloop[1], ptloop[2]);
33346     if (in->numberofpointattributes > 0) {
33347       // Write an attribute, ignore others if more than one.
33348       fprintf(outfile, "  %.17g", ptloop[3]);
33349     }
33350     fprintf(outfile, "\n");
33351     setpointmark(ptloop, pointnumber);
33352     ptloop = pointtraverse();
33353     pointnumber++;
33354   }
33355 
33356   fprintf(outfile, "end coordinates\n");
33357   fprintf(outfile, "elements\n");
33358 
33359   tetrahedrons->traversalinit();
33360   tetptr = tetrahedrontraverse();
33361   elementnumber = 1;
33362   while (tetptr != (tetrahedron *) NULL) {
33363     p1 = (point) tetptr[4];
33364     p2 = (point) tetptr[5];
33365     p3 = (point) tetptr[6];
33366     p4 = (point) tetptr[7];
33367     fprintf(outfile, "%5d  %5d %5d %5d %5d", elementnumber,
33368             pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33369     if (in->numberoftetrahedronattributes > 0) {
33370       fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
33371     }
33372     fprintf(outfile, "\n");
33373     tetptr = tetrahedrontraverse();
33374     elementnumber++;
33375   }
33376 
33377   fprintf(outfile, "end elements\n");
33378   fclose(outfile);
33379 
33380   if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33381     strcpy(gidfilename, gfilename);
33382   } else if (b->outfilename[0] != '\0') {
33383     strcpy(gidfilename, b->outfilename);
33384   } else {
33385     strcpy(gidfilename, "unnamed");
33386   }
33387   strcat(gidfilename, ".face.msh");
33388 
33389   if (!b->quiet) {
33390     printf("Writing %s.\n", gidfilename);
33391   }
33392   outfile = fopen(gidfilename, "w");
33393   if (outfile == (FILE *) NULL) {
33394     printf("File I/O Error:  Cannot create file %s.\n", gidfilename);
33395     return;
33396   }
33397 
33398   fprintf(outfile, "mesh dimension = 3 elemtype triangle nnode = 3\n");
33399   fprintf(outfile, "coordinates\n");
33400 
33401   points->traversalinit();
33402   ptloop = pointtraverse();
33403   pointnumber = 1;                        // Gid need start number form 1.
33404   while (ptloop != (point) NULL) {
33405     // Point coordinates.
33406     fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
33407             ptloop[0], ptloop[1], ptloop[2]);
33408     if (in->numberofpointattributes > 0) {
33409       // Write an attribute, ignore others if more than one.
33410       fprintf(outfile, "  %.17g", ptloop[3]);
33411     }
33412     fprintf(outfile, "\n");
33413     setpointmark(ptloop, pointnumber);
33414     ptloop = pointtraverse();
33415     pointnumber++;
33416   }
33417 
33418   fprintf(outfile, "end coordinates\n");
33419   fprintf(outfile, "elements\n");
33420 
33421   tetrahedrons->traversalinit();
33422   tface.tet = tetrahedrontraverse();
33423   elementnumber = 1;
33424   while (tface.tet != (tetrahedron *) NULL) {
33425     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33426       sym(tface, tsymface);
33427       if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33428         p1 = org(tface);
33429         p2 = dest(tface);
33430         p3 = apex(tface);
33431         if (tsymface.tet == dummytet) {
33432           // It's a hull face, output it.
33433           fprintf(outfile, "%5d   %d  %d  %d\n", elementnumber,
33434                   pointmark(p1), pointmark(p2), pointmark(p3));
33435           elementnumber++;
33436         } else if (b->useshelles) {
33437           // Only output it if it's a subface.
33438           tspivot(tface, sface);
33439           if (sface.sh != dummysh) {
33440             fprintf(outfile, "%5d   %d  %d  %d\n", elementnumber,
33441                     pointmark(p1), pointmark(p2), pointmark(p3));
33442             elementnumber++;
33443           }
33444         }
33445       }
33446     }
33447     tface.tet = tetrahedrontraverse();
33448   }
33449 
33450   fprintf(outfile, "end elements\n");
33451   fclose(outfile);
33452 }
33453 
33455 //                                                                           //
33456 // outmesh2off()    Write the mesh to an .off file.                          //
33457 //                                                                           //
33458 // .off, the Object File Format, is one of the popular file formats from the //
33459 // Geometry Center's Geomview package (http://www.geomview.org).             //
33460 //                                                                           //
33462 
33463 void tetgenmesh::outmesh2off(char* ofilename)
33464 {
33465   FILE *outfile;
33466   char offfilename[FILENAMESIZE];
33467   triface tface, tsymface;
33468   point ptloop, p1, p2, p3;
33469   long faces;
33470   int shift;
33471 
33472   if (ofilename != (char *) NULL && ofilename[0] != '\0') {
33473     strcpy(offfilename, ofilename);
33474   } else if (b->outfilename[0] != '\0') {
33475     strcpy(offfilename, b->outfilename);
33476   } else {
33477     strcpy(offfilename, "unnamed");
33478   }
33479   strcat(offfilename, ".off");
33480 
33481   if (!b->quiet) {
33482     printf("Writing %s.\n", offfilename);
33483   }
33484   outfile = fopen(offfilename, "w");
33485   if (outfile == (FILE *) NULL) {
33486     printf("File I/O Error:  Cannot create file %s.\n", offfilename);
33487     return;
33488   }
33489 
33490   // Calculate the number of triangular faces in the tetrahedral mesh.
33491   faces = (4l * tetrahedrons->items + hullsize) / 2l;
33492 
33493   // Number of points, faces, and edges(not used, here show hullsize).
33494   fprintf(outfile, "OFF\n%ld  %ld  %ld\n", points->items, faces, hullsize);
33495 
33496   // Write the points.
33497   points->traversalinit();
33498   ptloop = pointtraverse();
33499   while (ptloop != (point) NULL) {
33500     fprintf(outfile, " %.17g  %.17g  %.17g\n",ptloop[0], ptloop[1], ptloop[2]);
33501     ptloop = pointtraverse();
33502   }
33503 
33504   // OFF always use zero as the first index.
33505   shift = in->firstnumber == 1 ? 1 : 0;
33506 
33507   tetrahedrons->traversalinit();
33508   tface.tet = tetrahedrontraverse();
33509   // To loop over the set of faces, loop over all tetrahedra, and look at
33510   //   the four faces of each tetrahedron. If there isn't another tetrahedron
33511   //   adjacent to the face, operate on the face.  If there is another adj-
33512   //   acent tetrahedron, operate on the face only if the current tetrahedron
33513   //   has a smaller pointer than its neighbor.  This way, each face is
33514   //   considered only once.
33515   while (tface.tet != (tetrahedron *) NULL) {
33516     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33517       sym(tface, tsymface);
33518       if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33519         p1 = org(tface);
33520         p2 = dest(tface);
33521         p3 = apex(tface);
33522         // Face number, indices of three vertexs.
33523         fprintf(outfile, "3   %4d  %4d  %4d\n", pointmark(p1) - shift,
33524                 pointmark(p2) - shift, pointmark(p3) - shift);
33525       }
33526     }
33527     tface.tet = tetrahedrontraverse();
33528   }
33529 
33530   fprintf(outfile, "# Generated by %s\n", b->commandline);
33531   fclose(outfile);
33532 }
33533 
33534 //
33535 // End of I/O rouitnes
33536 //
33537 
33538 //
33539 // Begin of user interaction routines
33540 //
33541 
33543 //                                                                           //
33544 // internalerror()    Ask the user to send me the defective product.  Exit.  //
33545 //                                                                           //
33547 
33548 void tetgenmesh::internalerror()
33549 {
33550   printf("  Please report this bug to sihang@mail.berlios.de. Include the\n");
33551   printf("    message above, your input data set, and the exact command\n");
33552   printf("    line you used to run this program, thank you.\n");
33553   terminatetetgen(2);
33554 }
33555 
33557 //                                                                           //
33558 // checkmesh()    Test the mesh for topological consistency.                 //
33559 //                                                                           //
33561 
33562 void tetgenmesh::checkmesh()
33563 {
33564   triface tetraloop;
33565   triface oppotet, oppooppotet;
33566   point tetorg, tetdest, tetapex, tetoppo;
33567   REAL oritest;
33568   int horrors;
33569 
33570   if (!b->quiet) {
33571     printf("  Checking consistency of mesh...\n");
33572   }
33573 
33574   horrors = 0;
33575   // Run through the list of tetrahedra, checking each one.
33576   tetrahedrons->traversalinit();
33577   tetraloop.tet = tetrahedrontraverse();
33578   while (tetraloop.tet != (tetrahedron *) NULL) {
33579     // Check all four faces of the tetrahedron.
33580     for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33581       tetorg = org(tetraloop);
33582       tetdest = dest(tetraloop);
33583       tetapex = apex(tetraloop);
33584       tetoppo = oppo(tetraloop);
33585       if (tetraloop.loc == 0) {             // Only test for inversion once.
33586         oritest = orient3d(tetorg, tetdest, tetapex, tetoppo);
33587         if (oritest >= 0.0) {
33588           printf("  !! !! %s ", oritest > 0.0 ? "Inverted" : "Degenerated");
33589           printtet(&tetraloop);
33590           printf("  orient3d = %.17g.\n", oritest);
33591           horrors++;
33592         }
33593       }
33594       // Find the neighboring tetrahedron on this face.
33595       sym(tetraloop, oppotet);
33596       if (oppotet.tet != dummytet) {
33597         // Check that the tetrahedron's neighbor knows it's a neighbor.
33598         sym(oppotet, oppooppotet);
33599         if ((tetraloop.tet != oppooppotet.tet)
33600             || (tetraloop.loc != oppooppotet.loc)) {
33601           printf("  !! !! Asymmetric tetra-tetra bond:\n");
33602           if (tetraloop.tet == oppooppotet.tet) {
33603             printf("   (Right tetrahedron, wrong orientation)\n");
33604           }
33605           printf("    First ");
33606           printtet(&tetraloop);
33607           printf("    Second (nonreciprocating) ");
33608           printtet(&oppotet);
33609           horrors++;
33610         }
33611       }
33612     }
33613     tetraloop.tet = tetrahedrontraverse();
33614   }
33615   if (horrors == 0) {
33616     if (!b->quiet) {
33617       printf("  In my studied opinion, the mesh appears to be consistent.\n");
33618     }
33619   } else if (horrors == 1) {
33620     printf("  !! !! !! !! Precisely one festering wound discovered.\n");
33621   } else {
33622     printf("  !! !! !! !! %d abominations witnessed.\n", horrors);
33623   }
33624 }
33625 
33627 //                                                                           //
33628 // checkshells()       Test the boundary mesh for topological consistency.   //
33629 //                                                                           //
33631 
33632 void tetgenmesh::checkshells()
33633 {
33634   triface oppotet, oppooppotet, testtet;
33635   face shloop, segloop, spin;
33636   face testsh, testseg, testshsh;
33637   point shorg, shdest, segorg, segdest;
33638   REAL checksign;
33639   bool same;
33640   int horrors;
33641   int i;
33642 
33643   if (!b->quiet) {
33644     printf("  Checking consistency of the mesh boundary...\n");
33645   }
33646   horrors = 0;
33647 
33648   // Run through the list of subfaces, checking each one.
33649   subfaces->traversalinit();
33650   shloop.sh = shellfacetraverse(subfaces);
33651   while (shloop.sh != (shellface *) NULL) {
33652     // Check two connected tetrahedra if they exist.
33653     shloop.shver = 0;
33654     stpivot(shloop, oppotet);
33655     if (oppotet.tet != dummytet) {
33656       tspivot(oppotet, testsh);
33657       if (testsh.sh != shloop.sh) {
33658         printf("  !! !! Wrong tetra-subface connection.\n");
33659         printf("    Tetra: ");
33660         printtet(&oppotet);
33661         printf("    Subface: ");
33662         printsh(&shloop);
33663         horrors++;
33664       }
33665       if (oppo(oppotet) != (point) NULL) {
33666         adjustedgering(oppotet, CCW);
33667         checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33668                              oppo(oppotet));
33669         if (checksign >= 0.0) {
33670           printf("  !! !! Wrong subface orientation.\n");
33671           printf("    Subface: ");
33672           printsh(&shloop);
33673           horrors++;
33674         }
33675       }
33676     }
33677     sesymself(shloop);
33678     stpivot(shloop, oppooppotet);
33679     if (oppooppotet.tet != dummytet) {
33680       tspivot(oppooppotet, testsh);
33681       if (testsh.sh != shloop.sh) {
33682         printf("  !! !! Wrong tetra-subface connection.\n");
33683         printf("    Tetra: ");
33684         printtet(&oppooppotet);
33685         printf("    Subface: ");
33686         printsh(&shloop);
33687         horrors++;
33688       }
33689       if (oppotet.tet != dummytet) {
33690         sym(oppotet, testtet);
33691         if (testtet.tet != oppooppotet.tet) {
33692           printf("  !! !! Wrong tetra-subface-tetra connection.\n");
33693           printf("    Tetra 1: ");
33694           printtet(&oppotet);
33695           printf("    Subface: ");
33696           printsh(&shloop);
33697           printf("    Tetra 2: ");
33698           printtet(&oppooppotet);
33699           horrors++;
33700         }
33701       }
33702       if (oppo(oppooppotet) != (point) NULL) {
33703         adjustedgering(oppooppotet, CCW);
33704         checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33705                              oppo(oppooppotet));
33706         if (checksign >= 0.0) {
33707           printf("  !! !! Wrong subface orientation.\n");
33708           printf("    Subface: ");
33709           printsh(&shloop);
33710           horrors++;
33711         }
33712       }
33713     }
33714     // Check connection between subfaces.
33715     shloop.shver = 0;
33716     for (i = 0; i < 3; i++) {
33717       shorg = sorg(shloop);
33718       shdest = sdest(shloop);
33719       sspivot(shloop, testseg);
33720       if (testseg.sh != dummysh) {
33721         segorg = sorg(testseg);
33722         segdest = sdest(testseg);
33723         same = ((shorg == segorg) && (shdest == segdest))
33724         || ((shorg == segdest) && (shdest == segorg));
33725         if (!same) {
33726           printf("  !! !! Wrong subface-subsegment connection.\n");
33727           printf("    Subface: ");
33728           printsh(&shloop);
33729           printf("    Subsegment: ");
33730           printsh(&testseg);
33731           horrors++;
33732         }
33733       }
33734       spivot(shloop, testsh);
33735       if (testsh.sh != dummysh) {
33736         segorg = sorg(testsh);
33737         segdest = sdest(testsh);
33738         same = ((shorg == segorg) && (shdest == segdest))
33739         || ((shorg == segdest) && (shdest == segorg));
33740         if (!same) {
33741           printf("  !! !! Wrong subface-subface connection.\n");
33742           printf("    Subface 1: ");
33743           printsh(&shloop);
33744           printf("    Subface 2: ");
33745           printsh(&testsh);
33746           horrors++;
33747         }
33748         spivot(testsh, testshsh);
33749         shorg = sorg(testshsh);
33750         shdest = sdest(testshsh);
33751         same = ((shorg == segorg) && (shdest == segdest))
33752         || ((shorg == segdest) && (shdest == segorg));
33753         if (!same) {
33754           printf("  !! !! Wrong subface-subface connection.\n");
33755           printf("    Subface 1: ");
33756           printsh(&testsh);
33757           printf("    Subface 2: ");
33758           printsh(&testshsh);
33759           horrors++;
33760         }
33761         if (testseg.sh == dummysh) {
33762           if (testshsh.sh != shloop.sh) {
33763             printf("  !! !! Wrong subface-subface connection.\n");
33764             printf("    Subface 1: ");
33765             printsh(&shloop);
33766             printf("    Subface 2: ");
33767             printsh(&testsh);
33768             horrors++;
33769           }
33770         }
33771       }
33772       senextself(shloop);
33773     }
33774     shloop.sh = shellfacetraverse(subfaces);
33775   }
33776 
33777   // Run through the list of subsegs, checking each one.
33778   subsegs->traversalinit();
33779   segloop.sh = shellfacetraverse(subsegs);
33780   while (segloop.sh != (shellface *) NULL) {
33781     segorg = sorg(segloop);
33782     segdest = sdest(segloop);
33783     spivot(segloop, testsh);
33784     if (testsh.sh == dummysh) {
33785       printf("  !! !! Wrong subsegment-subface connection.\n");
33786       printf("    Subsegment: ");
33787       printsh(&segloop);
33788       horrors++;
33789       segloop.sh = shellfacetraverse(subsegs);
33790       continue;
33791     }
33792     shorg = sorg(testsh);
33793     shdest = sdest(testsh);
33794     same = ((shorg == segorg) && (shdest == segdest))
33795         || ((shorg == segdest) && (shdest == segorg));
33796     if (!same) {
33797       printf("  !! !! Wrong subsegment-subface connection.\n");
33798       printf("    Subsegment : ");
33799       printsh(&segloop);
33800       printf("    Subface : ");
33801       printsh(&testsh);
33802       horrors++;
33803       segloop.sh = shellfacetraverse(subsegs);
33804       continue;
33805     }
33806     // Check the connection of face loop around this subsegment.
33807     spin = testsh;
33808     i = 0;
33809     do {
33810       spivotself(spin);
33811       shorg = sorg(spin);
33812       shdest = sdest(spin);
33813       same = ((shorg == segorg) && (shdest == segdest))
33814           || ((shorg == segdest) && (shdest == segorg));
33815       if (!same) {
33816         printf("  !! !! Wrong subsegment-subface connection.\n");
33817         printf("    Subsegment : ");
33818         printsh(&segloop);
33819         printf("    Subface : ");
33820         printsh(&testsh);
33821         horrors++;
33822         break;
33823       }
33824       i++;
33825     } while (spin.sh != testsh.sh && i < 1000);
33826     if (i >= 1000) {
33827       printf("  !! !! Wrong subsegment-subface connection.\n");
33828       printf("    Subsegment : ");
33829       printsh(&segloop);
33830       horrors++;
33831     }
33832     segloop.sh = shellfacetraverse(subsegs);
33833   }
33834   if (horrors == 0) {
33835     if (!b->quiet) {
33836       printf("  Mesh boundaries connected correctly.\n");
33837     }
33838   } else {
33839     printf("  !! !! !! !! %d boundary connection viewed with horror.\n",
33840            horrors);
33841     return;
33842   }
33843 }
33844 
33846 //                                                                           //
33847 // checkdelaunay()    Ensure that the mesh is constrained Delaunay.          //
33848 //                                                                           //
33849 // If 'flipqueue' is not NULL, non-locally Delaunay faces are saved in it.   //
33850 //                                                                           //
33852 
33853 void tetgenmesh::checkdelaunay(REAL eps, queue* flipqueue)
33854 {
33855   triface tetraloop;
33856   triface oppotet;
33857   face opposhelle;
33858   point tetorg, tetdest, tetapex, tetoppo;
33859   point oppooppo;
33860   enum fliptype fc;
33861   REAL sign;
33862   int shouldbedelaunay;
33863   int horrors;
33864 
33865   if (!b->quiet) {
33866     printf("  Checking Delaunay property of the mesh...\n");
33867   }
33868   horrors = 0;
33869   // Run through the list of triangles, checking each one.
33870   tetrahedrons->traversalinit();
33871   tetraloop.tet = tetrahedrontraverse();
33872   while (tetraloop.tet != (tetrahedron *) NULL) {
33873     // Check all four faces of the tetrahedron.
33874     for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33875       tetorg = org(tetraloop);
33876       tetdest = dest(tetraloop);
33877       tetapex = apex(tetraloop);
33878       tetoppo = oppo(tetraloop);
33879       sym(tetraloop, oppotet);
33880       oppooppo = oppo(oppotet);
33881       // Only do testif there is an adjoining tetrahedron whose pointer is
33882       //   larger (to ensure that each pair isn't tested twice).
33883       shouldbedelaunay = (oppotet.tet != dummytet)
33884                           && (tetoppo != (point) NULL)
33885                           && (oppooppo != (point) NULL)
33886                           && (tetraloop.tet < oppotet.tet);
33887       if (checksubfaces && shouldbedelaunay) {
33888         // If a shell face separates the tetrahedra, then the face is
33889         //   constrained, so no local Delaunay test should be done.
33890         tspivot(tetraloop, opposhelle);
33891         if (opposhelle.sh != dummysh){
33892           shouldbedelaunay = 0;
33893         }
33894       }
33895       if (shouldbedelaunay) {
33896         sign = insphere(tetdest, tetorg, tetapex, tetoppo, oppooppo);
33897         if ((sign > 0.0) && (eps > 0.0)) {
33898           if (iscospheric(tetdest, tetorg, tetapex, tetoppo, oppooppo, sign,
33899                           eps)) sign = 0.0;
33900         }
33901         if (sign > 0.0) {
33902           if (flipqueue) {
33903             enqueueflipface(tetraloop, flipqueue);
33904           } else {
33905             printf("  !! Non-locally Delaunay face (%d, %d, %d) ",
33906                    pointmark(tetorg), pointmark(tetdest), pointmark(tetapex));
33907             fc = categorizeface(tetraloop);
33908             switch (fc) {
33909             case T23: printf("\"T23\""); break;
33910             case T32: printf("\"T32\""); break;
33911             case T22: printf("\"T22\""); break;
33912             case T44: printf("\"T44\""); break;
33913             case N32: printf("\"N32\""); break;
33914             case N40: printf("\"N40\""); break;
33915             case FORBIDDENFACE:printf("\"FORBIDDENFACE\""); break;
33916             case FORBIDDENEDGE:printf("\"FORBIDDENEDGE\""); break;
33917             }
33918             printf("\n");
33919           }
33920           horrors++;
33921         }
33922       }
33923     }
33924     tetraloop.tet = tetrahedrontraverse();
33925   }
33926   if (flipqueue == (queue *) NULL) {
33927     if (horrors == 0) {
33928       if (!b->quiet) {
33929         printf("  The mesh is %s.\n",
33930                checksubfaces ? "constrained Delaunay" : "Delaunay");
33931       }
33932     } else {
33933       printf("  !! !! !! !! %d obscenities viewed with horror.\n", horrors);
33934     }
33935   }
33936 }
33937 
33939 //                                                                           //
33940 // checkconforming()    Ensure that the mesh is conforming Delaunay.         //
33941 //                                                                           //
33943 
33944 void tetgenmesh::checkconforming()
33945 {
33946   face segloop, shloop;
33947   int encsubsegs, encsubfaces;
33948 
33949   if (!b->quiet) {
33950     printf("  Checking conforming Delaunay property of mesh...\n");
33951   }
33952   encsubsegs = encsubfaces = 0;
33953   // Run through the list of subsegments, check each one.
33954   subsegs->traversalinit();
33955   segloop.sh = shellfacetraverse(subsegs);
33956   while (segloop.sh != (shellface *) NULL) {
33957     if (checkseg4encroach(&segloop, NULL, NULL, false)) {
33958       printf("  !! !! Non-conforming subsegment: (%d, %d)\n",
33959              pointmark(sorg(segloop)), pointmark(sdest(segloop)));
33960       encsubsegs++;
33961     }
33962     segloop.sh = shellfacetraverse(subsegs);
33963   }
33964   // Run through the list of subfaces, check each one.
33965   subfaces->traversalinit();
33966   shloop.sh = shellfacetraverse(subfaces);
33967   while (shloop.sh != (shellface *) NULL) {
33968     if (checksub4encroach(&shloop, NULL, false)) {
33969       printf("  !! !! Non-conforming subface: (%d, %d, %d)\n",
33970              pointmark(sorg(shloop)), pointmark(sdest(shloop)),
33971              pointmark(sapex(shloop)));
33972       encsubfaces++;
33973     }
33974     shloop.sh = shellfacetraverse(subfaces);
33975   }
33976   if (encsubsegs == 0 && encsubfaces == 0) {
33977     if (!b->quiet) {
33978       printf("  The mesh is conforming Delaunay.\n");
33979     }
33980   } else {
33981     if (encsubsegs > 0) {
33982       printf("  !! !! %d subsegments are non-conforming.\n", encsubsegs);
33983     }
33984     if (encsubfaces > 0) {
33985       printf("  !! !! %d subfaces are non-conforming.\n", encsubfaces);
33986     }
33987   }
33988 }
33989 
33991 //                                                                           //
33992 // algorithmicstatistics()    Print statistics about the mesh algorithms.    //
33993 //                                                                           //
33995 
33996 #ifdef SELF_CHECK
33997 
33998 void tetgenmesh::algorithmicstatistics()
33999 {
34000   /*
34001   printf("Algorithmic statistics:\n\n");
34002   printf("  Point location millisecond:  %g\n", (REAL) tloctime * 1e+3);
34003   printf("  Flip millisecond:  %g\n", (REAL) tfliptime * 1e+3);
34004   if (b->plc || b->refine) {
34005     printf("  Number of facet above points calculations: %ld\n", abovecount);
34006   }
34007   if (b->plc) {
34008     printf("  Segment split rules: R1 %ld, R2 %ld, R3 %ld\n", r1count, r2count,
34009            r3count);
34010   }
34011   if (b->quality) {
34012     printf("  Bowyer-Watson insertions: seg %ld, sub %ld, vol %ld.\n",
34013            bowatsegcount, bowatsubcount, bowatvolcount);
34014     printf("  Bowyer-Watson corrections: seg %ld, sub %ld, vol %ld\n",
34015            updsegcount, updsubcount, updvolcount);
34016     printf("  Bowyer-Watson failures: seg %ld, sub %ld, vol %ld\n",
34017            failsegcount, failsubcount, failvolcount);
34018     printf("  Number of repair flips: %ld.\n", repairflipcount);
34019     printf("  Number of circumcenters outside Bowat-cav.: %ld.\n",
34020            outbowatcircumcount);
34021     if (b->conformdel) {
34022       printf("  Segment split rules: R2 %ld, R3 %ld\n", r2count, r3count);
34023       printf("  Number of CDT enforcement points: %ld.\n", cdtenforcesegpts);
34024     }
34025     printf("  Number of Rejections: seg %ld, sub %ld, tet %ld.\n", rejsegpts,
34026            rejsubpts, rejtetpts);
34027     if (b->optlevel) {
34028       printf(
34029       "  Optimization flips: f32 %ld, f44 %ld, f56 %ld, f68 %ld, fnm %ld.\n",
34030              optcount[3], optcount[4], optcount[5], optcount[6], optcount[9]);
34031       printf("  Optimization segment deletions: %ld.\n", optcount[1]);
34032     }
34033   }
34034   printf("\n");
34035   */
34036 }
34037 
34038 #endif // #ifdef SELF_CHECK
34039 
34041 //                                                                           //
34042 // qualitystatistics()    Print statistics about the quality of the mesh.    //
34043 //                                                                           //
34045 
34046 void tetgenmesh::qualitystatistics()
34047 {
34048   triface tetloop, neightet;
34049   point p[4];
34050   char sbuf[128];
34051   REAL radiusratiotable[12];
34052   REAL aspectratiotable[12];
34053   REAL A[4][4], rhs[4], D;
34054   REAL V[6][3], N[4][3], H[4]; // edge-vectors, face-normals, face-heights.
34055   REAL edgelength[6], alldihed[6], faceangle[3];
34056   REAL shortest, longest;
34057   REAL smallestvolume, biggestvolume;
34058   REAL smallestdiangle, biggestdiangle;
34059   REAL smallestfaangle, biggestfaangle;
34060   REAL tetvol, minaltitude;
34061   REAL cirradius, minheightinv; // insradius;
34062   REAL shortlen, longlen;
34063   REAL tetaspect, tetradius;
34064   REAL smalldiangle, bigdiangle;
34065   REAL smallfaangle, bigfaangle;
34066   int radiustable[12];
34067   int aspecttable[16];
34068   int dihedangletable[18];
34069   int faceangletable[18];
34070   int indx[4];
34071   int radiusindex;
34072   int aspectindex;
34073   int tendegree;
34074   int i, j;
34075 
34076   smallfaangle = 0.0;
34077   bigfaangle = 0.0;
34078 
34079   printf("Mesh quality statistics:\n\n");
34080 
34081   // Avoid compile warnings.
34082   shortlen = longlen = 0.0;
34083   smalldiangle = bigdiangle = 0.0;
34084 
34085   radiusratiotable[0]  =    0.707;    radiusratiotable[1]  =     1.0;
34086   radiusratiotable[2]  =      1.1;    radiusratiotable[3]  =     1.2;
34087   radiusratiotable[4]  =      1.4;    radiusratiotable[5]  =     1.6;
34088   radiusratiotable[6]  =      1.8;    radiusratiotable[7]  =     2.0;
34089   radiusratiotable[8]  =      2.5;    radiusratiotable[9]  =     3.0;
34090   radiusratiotable[10] =     10.0;    radiusratiotable[11] =     0.0;
34091 
34092   aspectratiotable[0]  =      1.5;    aspectratiotable[1]  =     2.0;
34093   aspectratiotable[2]  =      2.5;    aspectratiotable[3]  =     3.0;
34094   aspectratiotable[4]  =      4.0;    aspectratiotable[5]  =     6.0;
34095   aspectratiotable[6]  =     10.0;    aspectratiotable[7]  =    15.0;
34096   aspectratiotable[8]  =     25.0;    aspectratiotable[9]  =    50.0;
34097   aspectratiotable[10] =    100.0;    aspectratiotable[11] =     0.0;
34098 
34099   for (i = 0; i < 12; i++) radiustable[i] = 0;
34100   for (i = 0; i < 12; i++) aspecttable[i] = 0;
34101   for (i = 0; i < 18; i++) dihedangletable[i] = 0;
34102   for (i = 0; i < 18; i++) faceangletable[i] = 0;
34103 
34104   minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
34105   minaltitude = minaltitude * minaltitude;
34106   shortest = minaltitude;
34107   longest = 0.0;
34108   smallestvolume = minaltitude;
34109   biggestvolume = 0.0;
34110   smallestdiangle = smallestfaangle = 180.0;
34111   biggestdiangle = biggestfaangle = 0.0;
34112 
34113   // Loop all elements, calculate quality parameters for each element.
34114   tetrahedrons->traversalinit();
34115   tetloop.tet = tetrahedrontraverse();
34116   while (tetloop.tet != (tetrahedron *) NULL) {
34117 
34118     // Get four vertices: p0, p1, p2, p3.
34119     for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i];
34120     // Set the edge vectors: V[0], ..., V[5]
34121     for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i]; // V[0]: p3->p0.
34122     for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i]; // V[1]: p3->p1.
34123     for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i]; // V[2]: p3->p2.
34124     for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i]; // V[3]: p0->p1.
34125     for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i]; // V[4]: p1->p2.
34126     for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i]; // V[5]: p2->p0.
34127     // Set the matrix A = [V[0], V[1], V[2]]^T.
34128     for (j = 0; j < 3; j++) {
34129       for (i = 0; i < 3; i++) A[j][i] = V[j][i];
34130     }
34131     // Decompose A just once.
34132     lu_decmp(A, 3, indx, &D, 0);
34133     // Get the tet volume.
34134     tetvol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
34135     // Get the three faces normals.
34136     for (j = 0; j < 3; j++) {
34137       for (i = 0; i < 3; i++) rhs[i] = 0.0;
34138       rhs[j] = 1.0;  // Positive means the inside direction
34139       lu_solve(A, 3, indx, rhs, 0);
34140       for (i = 0; i < 3; i++) N[j][i] = rhs[i];
34141     }
34142     // Get the fourth face normal by summing up the first three.
34143     for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
34144     // Get the radius of the circumsphere.
34145     for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]);
34146     lu_solve(A, 3, indx, rhs, 0);
34147     cirradius = sqrt(dot(rhs, rhs));
34148     // Normalize the face normals.
34149     for (i = 0; i < 4; i++) {
34150       // H[i] is the inverse of height of its corresponding face.
34151       H[i] = sqrt(dot(N[i], N[i]));
34152       for (j = 0; j < 3; j++) N[i][j] /= H[i];
34153     }
34154     // Get the radius of the inscribed sphere.
34155     // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]);
34156     // Get the biggest H[i] (corresponding to the smallest height).
34157     minheightinv = H[0];
34158     for (i = 1; i < 3; i++) {
34159       if (H[i] > minheightinv) minheightinv = H[i];
34160     }
34161     // Get the squares of the edge lengthes.
34162     for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
34163     // Get the dihedrals (in degree) at each edges.
34164     j = 0;
34165     for (i = 1; i < 4; i++) {
34166       alldihed[j] = -dot(N[0], N[i]); // Edge cd, bd, bc.
34167       if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34168       else if (alldihed[j] > 1.0) alldihed[j] = 1;
34169       alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34170       j++;
34171     }
34172     for (i = 2; i < 4; i++) {
34173       alldihed[j] = -dot(N[1], N[i]); // Edge ad, ac.
34174       if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34175       else if (alldihed[j] > 1.0) alldihed[j] = 1;
34176       alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34177       j++;
34178     }
34179     alldihed[j] = -dot(N[2], N[3]); // Edge ab.
34180     if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34181     else if (alldihed[j] > 1.0) alldihed[j] = 1;
34182     alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34183 
34184     // Calculate the longest and shortest edge length.
34185     for (i = 0; i < 6; i++) {
34186       if (i == 0) {
34187         shortlen = longlen = edgelength[i];
34188       } else {
34189         shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen;
34190         longlen  = edgelength[i] > longlen  ? edgelength[i] : longlen;
34191       }
34192       if (edgelength[i] > longest) {
34193         longest = edgelength[i];
34194       }
34195       if (edgelength[i] < shortest) {
34196         shortest = edgelength[i];
34197       }
34198     }
34199 
34200     // Calculate the largest and smallest volume.
34201     if (tetvol < smallestvolume) {
34202       smallestvolume = tetvol;
34203     }
34204     if (tetvol > biggestvolume) {
34205       biggestvolume = tetvol;
34206     }
34207 
34208     // Calculate the largest and smallest dihedral angles.
34209     for (i = 0; i < 6; i++) {
34210       if (i == 0) {
34211         smalldiangle = bigdiangle = alldihed[i];
34212       } else {
34213         smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle;
34214         bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle;
34215       }
34216       if (alldihed[i] < smallestdiangle) {
34217         smallestdiangle = alldihed[i];
34218       }
34219       if (alldihed[i] > biggestdiangle) {
34220         biggestdiangle = alldihed[i];
34221       }
34222     }
34223     // Accumulate the corresponding number in the dihedral angle histogram.
34224     if (smalldiangle < 5.0) {
34225       tendegree = 0;
34226     } else if (smalldiangle >= 5.0 && smalldiangle < 10.0) {
34227       tendegree = 1;
34228     } else if (smalldiangle >= 80.0 && smalldiangle < 110.0) {
34229       tendegree = 9; // Angles between 80 to 110 degree are in one entry.
34230     } else {
34231       tendegree = (int) (smalldiangle / 10.);
34232       if (smalldiangle < 80.0) {
34233         tendegree++;  // In the left column.
34234       } else {
34235         tendegree--;  // In the right column.
34236       }
34237     }
34238     dihedangletable[tendegree]++;
34239     if (bigdiangle >= 80.0 && bigdiangle < 110.0) {
34240       tendegree = 9; // Angles between 80 to 110 degree are in one entry.
34241     } else if (bigdiangle >= 170.0 && bigdiangle < 175.0) {
34242       tendegree = 16;
34243     } else if (bigdiangle >= 175.0) {
34244       tendegree = 17;
34245     } else {
34246       tendegree = (int) (bigdiangle / 10.);
34247       if (bigdiangle < 80.0) {
34248         tendegree++;  // In the left column.
34249       } else {
34250         tendegree--;  // In the right column.
34251       }
34252     }
34253     dihedangletable[tendegree]++;
34254 
34255     // Calulate the largest and smallest face angles.
34256     tetloop.ver = 0;
34257     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
34258       sym(tetloop, neightet);
34259       // Only do the calulation once for a face.
34260       if ((neightet.tet == dummytet) || (tetloop.tet < neightet.tet)) {
34261         p[0] = org(tetloop);
34262         p[1] = dest(tetloop);
34263         p[2] = apex(tetloop);
34264         faceangle[0] = interiorangle(p[0], p[1], p[2], NULL);
34265         faceangle[1] = interiorangle(p[1], p[2], p[0], NULL);
34266         faceangle[2] = PI - (faceangle[0] + faceangle[1]);
34267         // Translate angles into degrees.
34268         for (i = 0; i < 3; i++) {
34269           faceangle[i] = (faceangle[i] * 180.0) / PI;
34270         }
34271         // Calculate the largest and smallest face angles.
34272         for (i = 0; i < 3; i++) {
34273           if (i == 0) {
34274             smallfaangle = bigfaangle = faceangle[i];
34275           } else {
34276             smallfaangle = faceangle[i] < smallfaangle ?
34277               faceangle[i] : smallfaangle;
34278             bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle;
34279           }
34280           if (faceangle[i] < smallestfaangle) {
34281             smallestfaangle = faceangle[i];
34282           }
34283           if (faceangle[i] > biggestfaangle) {
34284             biggestfaangle = faceangle[i];
34285           }
34286         }
34287         tendegree = (int) (smallfaangle / 10.);
34288         faceangletable[tendegree]++;
34289         tendegree = (int) (bigfaangle / 10.);
34290         faceangletable[tendegree]++;
34291       }
34292     }
34293 
34294     // Calculate aspect ratio and radius-edge ratio for this element.
34295     tetradius = cirradius / sqrt(shortlen);
34296     // tetaspect = sqrt(longlen) / (2.0 * insradius);
34297     tetaspect = sqrt(longlen) * minheightinv;
34298     aspectindex = 0;
34299     while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) {
34300       aspectindex++;
34301     }
34302     aspecttable[aspectindex]++;
34303     radiusindex = 0;
34304     while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) {
34305       radiusindex++;
34306     }
34307     radiustable[radiusindex]++;
34308 
34309     tetloop.tet = tetrahedrontraverse();
34310   }
34311 
34312   shortest = sqrt(shortest);
34313   longest = sqrt(longest);
34314   minaltitude = sqrt(minaltitude);
34315 
34316   printf("  Smallest volume: %16.5g   |  Largest volume: %16.5g\n",
34317          smallestvolume, biggestvolume);
34318   printf("  Shortest edge:   %16.5g   |  Longest edge:   %16.5g\n",
34319          shortest, longest);
34320   sprintf(sbuf, "%.17g", biggestfaangle);
34321   if (strlen(sbuf) > 8) {
34322     sbuf[8] = '\0';
34323   }
34324   printf("  Smallest facangle: %14.5g   |  Largest facangle:       %s\n",
34325          smallestfaangle, sbuf);
34326   sprintf(sbuf, "%.17g", biggestdiangle);
34327   if (strlen(sbuf) > 8) {
34328     sbuf[8] = '\0';
34329   }
34330   printf("  Smallest dihedral: %14.5g   |  Largest dihedral:       %s\n\n",
34331          smallestdiangle, sbuf);
34332 
34333   /*
34334   printf("  Radius-edge ratio histogram:\n");
34335   printf("         < %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34336          radiusratiotable[0], radiustable[0], radiusratiotable[5],
34337          radiusratiotable[6], radiustable[6]);
34338   for (i = 1; i < 5; i++) {
34339     printf("  %6.6g - %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34340            radiusratiotable[i - 1], radiusratiotable[i], radiustable[i],
34341            radiusratiotable[i + 5], radiusratiotable[i + 6],
34342            radiustable[i + 6]);
34343   }
34344   printf("  %6.6g - %-6.6g    :  %8d      | %6.6g -            :  %8d\n",
34345          radiusratiotable[4], radiusratiotable[5], radiustable[5],
34346          radiusratiotable[10], radiustable[11]);
34347   printf("  (A tetrahedron's radius-edge ratio is its radius of ");
34348   printf("circumsphere divided\n");
34349   printf("    by its shortest edge length)\n\n");
34350   */
34351 
34352   printf("  Aspect ratio histogram:\n");
34353   printf("         < %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34354          aspectratiotable[0], aspecttable[0], aspectratiotable[5],
34355          aspectratiotable[6], aspecttable[6]);
34356   for (i = 1; i < 5; i++) {
34357     printf("  %6.6g - %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34358            aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i],
34359            aspectratiotable[i + 5], aspectratiotable[i + 6],
34360            aspecttable[i + 6]);
34361   }
34362   printf("  %6.6g - %-6.6g    :  %8d      | %6.6g -            :  %8d\n",
34363          aspectratiotable[4], aspectratiotable[5], aspecttable[5],
34364          aspectratiotable[10], aspecttable[11]);
34365   printf("  (A tetrahedron's aspect ratio is its longest edge length");
34366   printf(" divided by its\n");
34367   printf("    smallest side height)\n\n");
34368 
34369   printf("  Face angle histogram:\n");
34370   for (i = 0; i < 9; i++) {
34371     printf("    %3d - %3d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34372            i * 10, i * 10 + 10, faceangletable[i],
34373            i * 10 + 90, i * 10 + 100, faceangletable[i + 9]);
34374   }
34375   if (minfaceang != PI) {
34376     printf("  Minimum input face angle is %g (degree).\n",
34377            minfaceang / PI * 180.0);
34378   }
34379   printf("\n");
34380 
34381   printf("  Dihedral angle histogram:\n");
34382   // Print the three two rows:
34383   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34384          0, 5, dihedangletable[0], 80, 110, dihedangletable[9]);
34385   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34386          5, 10, dihedangletable[1], 110, 120, dihedangletable[10]);
34387   // Print the third to seventh rows.
34388   for (i = 2; i < 7; i++) {
34389     printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34390            (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i],
34391            (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]);
34392   }
34393   // Print the last two rows.
34394   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34395          60, 70, dihedangletable[7], 170, 175, dihedangletable[16]);
34396   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34397          70, 80, dihedangletable[8], 175, 180, dihedangletable[17]);
34398   if (minfacetdihed != PI) {
34399     printf("  Minimum input facet dihedral angle is %g (degree).\n",
34400            minfacetdihed / PI * 180.0);
34401   }
34402   printf("\n");
34403 }
34404 
34406 //                                                                           //
34407 // statistics()    Print all sorts of cool facts.                            //
34408 //                                                                           //
34410 
34411 void tetgenmesh::statistics()
34412 {
34413   printf("\nStatistics:\n\n");
34414   printf("  Input points: %d\n", in->numberofpoints + jettisoninverts);
34415   if (b->refine) {
34416     printf("  Input tetrahedra: %d\n", in->numberoftetrahedra);
34417   }
34418   if (b->plc) {
34419     printf("  Input facets: %d\n", in->numberoffacets);
34420     printf("  Input segments: %ld\n", insegments);
34421     printf("  Input holes: %d\n", in->numberofholes);
34422     printf("  Input regions: %d\n", in->numberofregions);
34423   }
34424 
34425   printf("\n  Mesh points: %ld\n", points->items);
34426   printf("  Mesh tetrahedra: %ld\n", tetrahedrons->items);
34427   if (b->plc || b->refine) {
34428     printf("  Mesh triangles: %ld\n", (4l*tetrahedrons->items+hullsize)/2l);
34429   }
34430   if (b->plc || b->refine) {
34431     printf("  Mesh subfaces: %ld\n", subfaces->items);
34432     printf("  Mesh subsegments: %ld\n\n", subsegs->items);
34433   } else {
34434     printf("  Convex hull triangles: %ld\n\n", hullsize);
34435   }
34436   if (b->verbose > 0) {
34437     qualitystatistics();
34438     unsigned long totalmeshbytes;
34439     printf("Memory allocation statistics:\n\n");
34440     printf("  Maximum number of vertices: %ld\n", points->maxitems);
34441     totalmeshbytes = points->maxitems * points->itembytes;
34442     printf("  Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems);
34443     totalmeshbytes += tetrahedrons->maxitems * tetrahedrons->itembytes;
34444     if (subfaces != (memorypool *) NULL) {
34445       printf("  Maximum number of subfaces: %ld\n", subfaces->maxitems);
34446       totalmeshbytes += subfaces->maxitems * subfaces->itembytes;
34447     }
34448     if (subsegs != (memorypool *) NULL) {
34449       printf("  Maximum number of segments: %ld\n", subsegs->maxitems);
34450       totalmeshbytes += subsegs->maxitems * subsegs->itembytes;
34451     }
34452     printf("  Approximate heap memory used by the mesh (K bytes): %g\n\n",
34453            (double) totalmeshbytes / 1024.0);
34454 #ifdef SELF_CHECK
34455     algorithmicstatistics();
34456 #endif
34457   }
34458 }
34459 
34460 //
34461 // End of user interaction routines
34462 //
34463 
34464 //
34465 // Begin of constructor and destructor of tetgenmesh
34466 //
34467 
34469 //                                                                           //
34470 // ~tetgenmesh()    Deallocte memory occupied by a tetgenmesh object.        //
34471 //                                                                           //
34473 
34474 tetgenmesh::~tetgenmesh()
34475 {
34476   bgm = (tetgenmesh *) NULL;
34477   in = (tetgenio *) NULL;
34478   b = (tetgenbehavior *) NULL;
34479 
34480   if (tetrahedrons != (memorypool *) NULL) {
34481     delete tetrahedrons;
34482   }
34483   if (subfaces != (memorypool *) NULL) {
34484     delete subfaces;
34485   }
34486   if (subsegs != (memorypool *) NULL) {
34487     delete subsegs;
34488   }
34489   if (points != (memorypool *) NULL) {
34490     delete points;
34491   }
34492   if (dummytetbase != (tetrahedron *) NULL) {
34493     delete [] dummytetbase;
34494   }
34495   if (dummyshbase != (shellface *) NULL) {
34496     delete [] dummyshbase;
34497   }
34498   if (facetabovepointarray != (point *) NULL) {
34499     delete [] facetabovepointarray;
34500   }
34501   if (highordertable != (point *) NULL) {
34502     delete [] highordertable;
34503   }
34504   if (subpbcgrouptable != (pbcdata *) NULL) {
34505     delete [] subpbcgrouptable;
34506   }
34507   if (segpbcgrouptable != (list *) NULL) {
34508     delete segpbcgrouptable;
34509     delete [] idx2segpglist;
34510     delete [] segpglist;
34511   }
34512 }
34513 
34515 //                                                                           //
34516 // tetgenmesh()    Initialize a tetgenmesh object.                           //
34517 //                                                                           //
34519 
34520 tetgenmesh::tetgenmesh()
34521 {
34522   bgm = (tetgenmesh *) NULL;
34523   in = (tetgenio *) NULL;
34524   b = (tetgenbehavior *) NULL;
34525 
34526   tetrahedrons = (memorypool *) NULL;
34527   subfaces = (memorypool *) NULL;
34528   subsegs = (memorypool *) NULL;
34529   points = (memorypool *) NULL;
34530   badsubsegs = (memorypool *) NULL;
34531   badsubfaces = (memorypool *) NULL;
34532   badtetrahedrons = (memorypool *) NULL;
34533   flipstackers = (memorypool *) NULL;
34534 
34535   dummytet = (tetrahedron *) NULL;
34536   dummytetbase = (tetrahedron *) NULL;
34537   dummysh = (shellface *) NULL;
34538   dummyshbase = (shellface *) NULL;
34539 
34540   facetabovepointarray = (point *) NULL;
34541   abovepoint = (point) NULL;
34542   highordertable = (point *) NULL;
34543   subpbcgrouptable = (pbcdata *) NULL;
34544   segpbcgrouptable = (list *) NULL;
34545   idx2segpglist = (int *) NULL;
34546   segpglist = (int *) NULL;
34547 
34548   xmax = xmin = ymax = ymin = zmax = zmin = 0.0;
34549   longest = 0.0;
34550   hullsize = 0l;
34551   insegments = 0l;
34552   pointmtrindex = 0;
34553   pointmarkindex = 0;
34554   point2simindex = 0;
34555   point2pbcptindex = 0;
34556   highorderindex = 0;
34557   elemattribindex = 0;
34558   volumeboundindex = 0;
34559   shmarkindex = 0;
34560   areaboundindex = 0;
34561   checksubfaces = 0;
34562   checksubsegs = 0;
34563   checkpbcs = 0;
34564   varconstraint = 0;
34565   nonconvex = 0;
34566   dupverts = 0;
34567   unuverts = 0;
34568   relverts = 0;
34569   suprelverts = 0;
34570   collapverts = 0;
34571   unsupverts = 0;
34572   jettisoninverts = 0;
34573   symbolic = 1;
34574   samples = 0l;
34575   randomseed = 1l;
34576   macheps = 0.0;
34577   minfaceang = minfacetdihed = PI;
34578   maxcavfaces = maxcavverts = 0;
34579   expcavcount = 0;
34580   abovecount = 0l;
34581   bowatvolcount = bowatsubcount = bowatsegcount = 0l;
34582   updvolcount = updsubcount = updsegcount = 0l;
34583   repairflipcount = 0l;
34584   outbowatcircumcount = 0l;
34585   failvolcount = failsubcount = failsegcount = 0l;
34586   r1count = r2count = r3count = 0l;
34587   cdtenforcesegpts = 0l;
34588   rejsegpts = rejsubpts = rejtetpts = 0l;
34589   flip23s = flip32s = flip22s = flip44s = 0l;
34590   tloctime = tfliptime = 0.0;
34591 }
34592 
34593 //
34594 // End of constructor and destructor of tetgenmesh
34595 //
34596 
34597 //
34598 // End of class 'tetgenmesh' implementation.
34599 //
34600 
34602 //                                                                           //
34603 // tetrahedralize()    The interface for users using TetGen library to       //
34604 //                     generate tetrahedral meshes with all features.        //
34605 //                                                                           //
34606 // The sequence is roughly as follows.  Many of these steps can be skipped,  //
34607 // depending on the command line switches.                                   //
34608 //                                                                           //
34609 // - Initialize constants and parse the command line.                        //
34610 // - Read the vertices from a file and either                                //
34611 //   - tetrahedralize them (no -r), or                                       //
34612 //   - read an old mesh from files and reconstruct it (-r).                  //
34613 // - Insert the PLC segments and facets (-p).                                //
34614 // - Read the holes (-p), regional attributes (-pA), and regional volume     //
34615 //   constraints (-pa).  Carve the holes and concavities, and spread the     //
34616 //   regional attributes and volume constraints.                             //
34617 // - Enforce the constraints on minimum quality bound (-q) and maximum       //
34618 //   volume (-a). Also enforce the conforming Delaunay property (-q and -a). //
34619 // - Promote the mesh's linear tetrahedra to higher order elements (-o).     //
34620 // - Write the output files and print the statistics.                        //
34621 // - Check the consistency and Delaunay property of the mesh (-C).           //
34622 //                                                                           //
34624 
34625 void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
34626   tetgenio *addin, tetgenio *bgmin)
34627 {
34628   tetgenmesh m;
34629   // Variables for timing the performance of TetGen (defined in time.h).
34630   clock_t tv[14];
34631 
34632   tv[0] = clock();
34633 
34634   m.b = b;
34635   m.in = in;
34636   m.macheps = exactinit();
34637   m.steinerleft = b->steiner;
34638   if (b->metric) {
34639     m.bgm = new tetgenmesh();
34640     m.bgm->b = b;
34641     m.bgm->in = bgmin;
34642     m.bgm->macheps = exactinit();
34643   }
34644   m.initializepools();
34645   m.transfernodes();
34646 
34647   tv[1] = clock();
34648 
34649   if (b->refine) {
34650     m.reconstructmesh();
34651   } else {
34652     m.delaunizevertices();
34653   }
34654 
34655   tv[2] = clock();
34656 
34657   if (!b->quiet) {
34658     if (b->refine) {
34659       printf("Mesh reconstruction seconds:");
34660     } else {
34661       printf("Delaunay seconds:");
34662     }
34663     printf("  %g\n", (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
34664   }
34665 
34666   if (b->metric) {
34667     if (bgmin != (tetgenio *) NULL) {
34668       m.bgm->initializepools();
34669       m.bgm->transfernodes();
34670       m.bgm->reconstructmesh();
34671     } else {
34672       m.bgm->in = in;
34673       m.bgm->initializepools();
34674       m.duplicatebgmesh();
34675     }
34676   }
34677 
34678   tv[3] = clock();
34679 
34680   if (!b->quiet) {
34681     if (b->metric) {
34682       printf("Background mesh reconstruct seconds:  %g\n",
34683              (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
34684     }
34685   }
34686 
34687   if (b->useshelles && !b->refine) {
34688     m.meshsurface();
34689     if (b->diagnose != 1) {
34690       m.markacutevertices(89.0);
34691       m.incrperturbvertices(b->epsilon);
34692       m.delaunizesegments();
34693       if (m.checkpbcs) {
34694         long oldnum;
34695         do {
34696           oldnum = m.points->items;
34697           m.incrperturbvertices(b->epsilon);
34698           if (m.points->items > oldnum) {
34699             oldnum = m.points->items;
34700             m.delaunizesegments();
34701           }
34702         } while (oldnum < m.points->items);
34703       }
34704       m.constrainedfacets();
34705     } else {
34706       m.detectinterfaces();
34707     }
34708   }
34709 
34710   tv[4] = clock();
34711 
34712   if (!b->quiet) {
34713     if (b->useshelles && !b->refine) {
34714       if (b->diagnose != 1) {
34715         printf("Segment and facet ");
34716       } else {
34717         printf("Intersection ");
34718       }
34719       printf("seconds:  %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
34720     }
34721   }
34722 
34723   if (b->plc && !(b->diagnose == 1)) {
34724     m.carveholes();
34725   }
34726 
34727   tv[5] = clock();
34728 
34729   if (!b->quiet) {
34730     if (b->plc && !(b->diagnose == 1)) {
34731       printf("Hole seconds:  %g\n", (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
34732     }
34733   }
34734 
34735   if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34736     m.optimizemesh(false);
34737   }
34738 
34739   tv[6] = clock();
34740 
34741   if (!b->quiet) {
34742     if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34743       printf("Repair seconds:  %g\n", (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
34744     }
34745   }
34746 
34747   if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34748     m.removesteiners(false);
34749   }
34750 
34751   tv[7] = clock();
34752 
34753   if (!b->quiet) {
34754     if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34755       printf("Steiner removal seconds:  %g\n",
34756              (tv[7] - tv[6]) / (REAL) CLOCKS_PER_SEC);
34757     }
34758   }
34759 
34760   if (b->insertaddpoints && (addin != (tetgenio *) NULL)) {
34761     if (addin->numberofpoints > 0) {
34762       m.insertconstrainedpoints(addin);
34763     }
34764   }
34765 
34766   tv[8] = clock();
34767 
34768   if (!b->quiet) {
34769     if ((b->plc || b->refine) && (b->insertaddpoints)) {
34770       printf("Constrained points seconds:  %g\n",
34771              (tv[8] - tv[7]) / (REAL) CLOCKS_PER_SEC);
34772     }
34773   }
34774 
34775   if (b->metric) {
34776     m.interpolatesizemap();
34777   }
34778 
34779   tv[9] = clock();
34780 
34781   if (!b->quiet) {
34782     if (b->metric) {
34783       printf("Size interpolating seconds:  %g\n",
34784              (tv[9] - tv[8]) / (REAL) CLOCKS_PER_SEC);
34785     }
34786   }
34787 
34788   if (b->coarse) {
34789     m.removesteiners(true);
34790   }
34791 
34792   tv[10] = clock();
34793 
34794   if (!b->quiet) {
34795     if (b->coarse) {
34796       printf("Mesh coarsening seconds:  %g\n",
34797              (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
34798     }
34799   }
34800 
34801   if (b->quality) {
34802     m.enforcequality();
34803   }
34804 
34805   tv[11] = clock();
34806 
34807   if (!b->quiet) {
34808     if (b->quality) {
34809       printf("Quality seconds:  %g\n",
34810              (tv[11] - tv[10]) / (REAL) CLOCKS_PER_SEC);
34811     }
34812   }
34813 
34814   if (b->quality && (b->optlevel > 0)) {
34815     m.optimizemesh(true);
34816   }
34817 
34818   tv[12] = clock();
34819 
34820   if (!b->quiet) {
34821     if (b->quality && (b->optlevel > 0)) {
34822       printf("Optimize seconds:  %g\n",
34823              (tv[12] - tv[11]) / (REAL) CLOCKS_PER_SEC);
34824     }
34825   }
34826 
34827   if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0)
34828       || (b->refine && (in->numberofcorners == 10)))) {
34829     m.jettisonnodes();
34830   }
34831 
34832   if (b->order > 1) {
34833     m.highorder();
34834   }
34835 
34836   if (!b->quiet) {
34837     printf("\n");
34838   }
34839 
34840   if (out != (tetgenio *) NULL) {
34841     out->firstnumber = in->firstnumber;
34842     out->mesh_dim = in->mesh_dim;
34843   }
34844 
34845   if (b->nonodewritten || b->noiterationnum) {
34846     if (!b->quiet) {
34847       printf("NOT writing a .node file.\n");
34848     }
34849   } else {
34850     if (b->diagnose == 1) {
34851       if (m.subfaces->items > 0l) {
34852         m.outnodes(out);  // Only output when self-intersecting faces exist.
34853       }
34854     } else {
34855       m.outnodes(out);
34856       if (b->quality || b->metric) {
34857         // m.outmetrics(out);
34858       }
34859     }
34860   }
34861 
34862   if (b->noelewritten) {
34863     if (!b->quiet) {
34864       printf("NOT writing an .ele file.\n");
34865     }
34866   } else {
34867     if (!(b->diagnose == 1)) {
34868       if (m.tetrahedrons->items > 0l) {
34869         m.outelements(out);
34870       }
34871     }
34872   }
34873 
34874   if (b->nofacewritten) {
34875     if (!b->quiet) {
34876       printf("NOT writing an .face file.\n");
34877     }
34878   } else {
34879     if (b->facesout) {
34880       if (m.tetrahedrons->items > 0l) {
34881         m.outfaces(out);  // Output all faces.
34882       }
34883     } else {
34884       if (b->diagnose == 1) {
34885         if (m.subfaces->items > 0l) {
34886           m.outsubfaces(out); // Only output self-intersecting faces.
34887         }
34888       } else if (b->plc || b->refine) {
34889         if (m.subfaces->items > 0l) {
34890           m.outsubfaces(out); // Output boundary faces.
34891         }
34892       } else {
34893         if (m.tetrahedrons->items > 0l) {
34894           m.outhullfaces(out); // Output convex hull faces.
34895         }
34896       }
34897     }
34898   }
34899 
34900   if (m.checkpbcs) {
34901     m.outpbcnodes(out);
34902   }
34903 
34904   if (b->edgesout) {
34905     if (b->edgesout > 1) {
34906       m.outedges(out); // -ee, output all mesh edges.
34907     } else {
34908       m.outsubsegments(out); // -e, only output subsegments.
34909     }
34910   }
34911 
34912   if (!out && b->plc &&
34913       ((b->object == tetgenbehavior::OFF) ||
34914        (b->object == tetgenbehavior::PLY) ||
34915        (b->object == tetgenbehavior::STL))) {
34916     m.outsmesh(b->outfilename);
34917   }
34918 
34919   if (!out && b->meditview) {
34920     m.outmesh2medit(b->outfilename);
34921   }
34922 
34923   if (!out && b->gidview) {
34924     m.outmesh2gid(b->outfilename);
34925   }
34926 
34927   if (!out && b->geomview) {
34928     m.outmesh2off(b->outfilename);
34929   }
34930 
34931   if (b->neighout) {
34932     m.outneighbors(out);
34933   }
34934 
34935   if (b->voroout) {
34936     m.outvoronoi(out);
34937   }
34938 
34939   tv[13] = clock();
34940 
34941   if (!b->quiet) {
34942     printf("\nOutput seconds:  %g\n",
34943            (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
34944     printf("Total running seconds:  %g\n",
34945            (tv[13] - tv[0]) / (REAL) CLOCKS_PER_SEC);
34946   }
34947 
34948   if (b->docheck) {
34949     m.checkmesh();
34950     if (m.checksubfaces) {
34951       m.checkshells();
34952     }
34953     if (b->docheck > 1) {
34954       m.checkdelaunay(0.0, NULL);
34955       if (b->docheck > 2) {
34956         if (b->quality || b->refine) {
34957           m.checkconforming();
34958         }
34959       }
34960     }
34961   }
34962 
34963   if (!b->quiet) {
34964     m.statistics();
34965   }
34966 
34967   if (b->metric) {
34968     delete m.bgm;
34969   }
34970 }
34971 
34972 #ifndef TETLIBRARY
34973 
34975 //                                                                           //
34976 // main()    The entrance for running TetGen from command line.              //
34977 //                                                                           //
34979 
34980 int main(int argc, char *argv[])
34981 
34982 #else // with TETLIBRARY
34983 
34985 //                                                                           //
34986 // tetrahedralize()    The entrance for calling TetGen from another program. //
34987 //                                                                           //
34989 
34990 void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
34991   tetgenio *addin, tetgenio *bgmin)
34992 
34993 #endif // not TETLIBRARY
34994 
34995 {
34996   tetgenbehavior b;
34997 
34998 #ifndef TETLIBRARY
34999 
35000   tetgenio in, addin, bgmin;
35001 
35002   if (!b.parse_commandline(argc, argv)) {
35003     terminatetetgen(1);
35004   }
35005   if (b.refine) {
35006     if (!in.load_tetmesh(b.infilename)) {
35007       terminatetetgen(1);
35008     }
35009   } else {
35010     if (!in.load_plc(b.infilename, (int) b.object)) {
35011       terminatetetgen(1);
35012     }
35013   }
35014   if (b.insertaddpoints) {
35015     if (!addin.load_node(b.addinfilename)) {
35016       addin.numberofpoints = 0l;
35017     }
35018   }
35019   if (b.metric) {
35020     if (!bgmin.load_tetmesh(b.bgmeshfilename)) {
35021       bgmin.numberoftetrahedra = 0l;
35022     }
35023   }
35024 
35025   if (bgmin.numberoftetrahedra > 0l) {
35026     tetrahedralize(&b, &in, NULL, &addin, &bgmin);
35027   } else {
35028     tetrahedralize(&b, &in, NULL, &addin, NULL);
35029   }
35030 
35031   return 0;
35032 
35033 #else // with TETLIBRARY
35034 
35035   if (!b.parse_commandline(switches)) {
35036     terminatetetgen(1);
35037   }
35038   tetrahedralize(&b, in, out, addin, bgmin);
35039 
35040 #endif // not TETLIBRARY
35041 }
35042 
35043 } //Added namespace to avoid clash with triangle
35044 
35045 #ifndef TETLIBRARY
35046 // Shim for entry point to main inside the namespace.  This is just in case we want to compile up a binary from this
35047 // source code.
35048 int main(int argc, char *argv[])
35049 {
35050     tetgen::main(argc, argv);
35051 }
35052 #endif // not TETLIBRARY

Generated by  doxygen 1.6.2